]> git.proxmox.com Git - qemu.git/blame - target-mips/translate.c
Use glib memory allocation and free functions
[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)
3c824109 7 * Copyright (c) 2009 CodeSourcery (MIPS16 and microMIPS 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"
6af0bf9c 30#include "disas.h"
57fec1fe 31#include "tcg-op.h"
ca10f867 32#include "qemu-common.h"
6af0bf9c 33
a7812ae4
PB
34#include "helper.h"
35#define GEN_HELPER 1
36#include "helper.h"
37
eeef26cd 38//#define MIPS_DEBUG_DISAS
c570fd16 39//#define MIPS_DEBUG_SIGN_EXTENSIONS
6af0bf9c 40
7a387fff
TS
41/* MIPS major opcodes */
42#define MASK_OP_MAJOR(op) (op & (0x3F << 26))
e37e863f
FB
43
44enum {
45 /* indirect opcode tables */
7a387fff
TS
46 OPC_SPECIAL = (0x00 << 26),
47 OPC_REGIMM = (0x01 << 26),
48 OPC_CP0 = (0x10 << 26),
49 OPC_CP1 = (0x11 << 26),
50 OPC_CP2 = (0x12 << 26),
51 OPC_CP3 = (0x13 << 26),
52 OPC_SPECIAL2 = (0x1C << 26),
53 OPC_SPECIAL3 = (0x1F << 26),
e37e863f 54 /* arithmetic with immediate */
7a387fff
TS
55 OPC_ADDI = (0x08 << 26),
56 OPC_ADDIU = (0x09 << 26),
57 OPC_SLTI = (0x0A << 26),
58 OPC_SLTIU = (0x0B << 26),
324d9e32 59 /* logic with immediate */
7a387fff
TS
60 OPC_ANDI = (0x0C << 26),
61 OPC_ORI = (0x0D << 26),
62 OPC_XORI = (0x0E << 26),
63 OPC_LUI = (0x0F << 26),
324d9e32 64 /* arithmetic with immediate */
7a387fff
TS
65 OPC_DADDI = (0x18 << 26),
66 OPC_DADDIU = (0x19 << 26),
e37e863f 67 /* Jump and branches */
7a387fff
TS
68 OPC_J = (0x02 << 26),
69 OPC_JAL = (0x03 << 26),
620e48f6 70 OPC_JALS = OPC_JAL | 0x5,
7a387fff
TS
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 */
620e48f6 80 OPC_JALXS = OPC_JALX | 0x5,
e37e863f 81 /* Load and stores */
7a387fff
TS
82 OPC_LDL = (0x1A << 26),
83 OPC_LDR = (0x1B << 26),
84 OPC_LB = (0x20 << 26),
85 OPC_LH = (0x21 << 26),
86 OPC_LWL = (0x22 << 26),
87 OPC_LW = (0x23 << 26),
364d4831 88 OPC_LWPC = OPC_LW | 0x5,
7a387fff
TS
89 OPC_LBU = (0x24 << 26),
90 OPC_LHU = (0x25 << 26),
91 OPC_LWR = (0x26 << 26),
92 OPC_LWU = (0x27 << 26),
93 OPC_SB = (0x28 << 26),
94 OPC_SH = (0x29 << 26),
95 OPC_SWL = (0x2A << 26),
96 OPC_SW = (0x2B << 26),
97 OPC_SDL = (0x2C << 26),
98 OPC_SDR = (0x2D << 26),
99 OPC_SWR = (0x2E << 26),
100 OPC_LL = (0x30 << 26),
101 OPC_LLD = (0x34 << 26),
102 OPC_LD = (0x37 << 26),
364d4831 103 OPC_LDPC = OPC_LD | 0x5,
7a387fff
TS
104 OPC_SC = (0x38 << 26),
105 OPC_SCD = (0x3C << 26),
106 OPC_SD = (0x3F << 26),
e37e863f 107 /* Floating point load/store */
7a387fff
TS
108 OPC_LWC1 = (0x31 << 26),
109 OPC_LWC2 = (0x32 << 26),
110 OPC_LDC1 = (0x35 << 26),
111 OPC_LDC2 = (0x36 << 26),
112 OPC_SWC1 = (0x39 << 26),
113 OPC_SWC2 = (0x3A << 26),
114 OPC_SDC1 = (0x3D << 26),
115 OPC_SDC2 = (0x3E << 26),
116 /* MDMX ASE specific */
117 OPC_MDMX = (0x1E << 26),
e37e863f 118 /* Cache and prefetch */
7a387fff
TS
119 OPC_CACHE = (0x2F << 26),
120 OPC_PREF = (0x33 << 26),
121 /* Reserved major opcode */
122 OPC_MAJOR3B_RESERVED = (0x3B << 26),
e37e863f
FB
123};
124
125/* MIPS special opcodes */
7a387fff
TS
126#define MASK_SPECIAL(op) MASK_OP_MAJOR(op) | (op & 0x3F)
127
e37e863f
FB
128enum {
129 /* Shifts */
7a387fff 130 OPC_SLL = 0x00 | OPC_SPECIAL,
e37e863f
FB
131 /* NOP is SLL r0, r0, 0 */
132 /* SSNOP is SLL r0, r0, 1 */
7a387fff
TS
133 /* EHB is SLL r0, r0, 3 */
134 OPC_SRL = 0x02 | OPC_SPECIAL, /* also ROTR */
ea63e2c3 135 OPC_ROTR = OPC_SRL | (1 << 21),
7a387fff
TS
136 OPC_SRA = 0x03 | OPC_SPECIAL,
137 OPC_SLLV = 0x04 | OPC_SPECIAL,
e189e748 138 OPC_SRLV = 0x06 | OPC_SPECIAL, /* also ROTRV */
ea63e2c3 139 OPC_ROTRV = OPC_SRLV | (1 << 6),
7a387fff
TS
140 OPC_SRAV = 0x07 | OPC_SPECIAL,
141 OPC_DSLLV = 0x14 | OPC_SPECIAL,
142 OPC_DSRLV = 0x16 | OPC_SPECIAL, /* also DROTRV */
ea63e2c3 143 OPC_DROTRV = OPC_DSRLV | (1 << 6),
7a387fff
TS
144 OPC_DSRAV = 0x17 | OPC_SPECIAL,
145 OPC_DSLL = 0x38 | OPC_SPECIAL,
146 OPC_DSRL = 0x3A | OPC_SPECIAL, /* also DROTR */
ea63e2c3 147 OPC_DROTR = OPC_DSRL | (1 << 21),
7a387fff
TS
148 OPC_DSRA = 0x3B | OPC_SPECIAL,
149 OPC_DSLL32 = 0x3C | OPC_SPECIAL,
150 OPC_DSRL32 = 0x3E | OPC_SPECIAL, /* also DROTR32 */
ea63e2c3 151 OPC_DROTR32 = OPC_DSRL32 | (1 << 21),
7a387fff 152 OPC_DSRA32 = 0x3F | OPC_SPECIAL,
e37e863f 153 /* Multiplication / division */
7a387fff
TS
154 OPC_MULT = 0x18 | OPC_SPECIAL,
155 OPC_MULTU = 0x19 | OPC_SPECIAL,
156 OPC_DIV = 0x1A | OPC_SPECIAL,
157 OPC_DIVU = 0x1B | OPC_SPECIAL,
158 OPC_DMULT = 0x1C | OPC_SPECIAL,
159 OPC_DMULTU = 0x1D | OPC_SPECIAL,
160 OPC_DDIV = 0x1E | OPC_SPECIAL,
161 OPC_DDIVU = 0x1F | OPC_SPECIAL,
e37e863f 162 /* 2 registers arithmetic / logic */
7a387fff
TS
163 OPC_ADD = 0x20 | OPC_SPECIAL,
164 OPC_ADDU = 0x21 | OPC_SPECIAL,
165 OPC_SUB = 0x22 | OPC_SPECIAL,
166 OPC_SUBU = 0x23 | OPC_SPECIAL,
167 OPC_AND = 0x24 | OPC_SPECIAL,
168 OPC_OR = 0x25 | OPC_SPECIAL,
169 OPC_XOR = 0x26 | OPC_SPECIAL,
170 OPC_NOR = 0x27 | OPC_SPECIAL,
171 OPC_SLT = 0x2A | OPC_SPECIAL,
172 OPC_SLTU = 0x2B | OPC_SPECIAL,
173 OPC_DADD = 0x2C | OPC_SPECIAL,
174 OPC_DADDU = 0x2D | OPC_SPECIAL,
175 OPC_DSUB = 0x2E | OPC_SPECIAL,
176 OPC_DSUBU = 0x2F | OPC_SPECIAL,
e37e863f 177 /* Jumps */
7a387fff
TS
178 OPC_JR = 0x08 | OPC_SPECIAL, /* Also JR.HB */
179 OPC_JALR = 0x09 | OPC_SPECIAL, /* Also JALR.HB */
364d4831 180 OPC_JALRC = OPC_JALR | (0x5 << 6),
620e48f6 181 OPC_JALRS = 0x10 | OPC_SPECIAL | (0x5 << 6),
e37e863f 182 /* Traps */
7a387fff
TS
183 OPC_TGE = 0x30 | OPC_SPECIAL,
184 OPC_TGEU = 0x31 | OPC_SPECIAL,
185 OPC_TLT = 0x32 | OPC_SPECIAL,
186 OPC_TLTU = 0x33 | OPC_SPECIAL,
187 OPC_TEQ = 0x34 | OPC_SPECIAL,
188 OPC_TNE = 0x36 | OPC_SPECIAL,
e37e863f 189 /* HI / LO registers load & stores */
7a387fff
TS
190 OPC_MFHI = 0x10 | OPC_SPECIAL,
191 OPC_MTHI = 0x11 | OPC_SPECIAL,
192 OPC_MFLO = 0x12 | OPC_SPECIAL,
193 OPC_MTLO = 0x13 | OPC_SPECIAL,
e37e863f 194 /* Conditional moves */
7a387fff
TS
195 OPC_MOVZ = 0x0A | OPC_SPECIAL,
196 OPC_MOVN = 0x0B | OPC_SPECIAL,
e37e863f 197
7a387fff 198 OPC_MOVCI = 0x01 | OPC_SPECIAL,
e37e863f
FB
199
200 /* Special */
a0d700e4 201 OPC_PMON = 0x05 | OPC_SPECIAL, /* unofficial */
7a387fff
TS
202 OPC_SYSCALL = 0x0C | OPC_SPECIAL,
203 OPC_BREAK = 0x0D | OPC_SPECIAL,
a0d700e4 204 OPC_SPIM = 0x0E | OPC_SPECIAL, /* unofficial */
7a387fff
TS
205 OPC_SYNC = 0x0F | OPC_SPECIAL,
206
207 OPC_SPECIAL15_RESERVED = 0x15 | OPC_SPECIAL,
208 OPC_SPECIAL28_RESERVED = 0x28 | OPC_SPECIAL,
209 OPC_SPECIAL29_RESERVED = 0x29 | OPC_SPECIAL,
210 OPC_SPECIAL35_RESERVED = 0x35 | OPC_SPECIAL,
211 OPC_SPECIAL37_RESERVED = 0x37 | OPC_SPECIAL,
212 OPC_SPECIAL39_RESERVED = 0x39 | OPC_SPECIAL,
213 OPC_SPECIAL3D_RESERVED = 0x3D | OPC_SPECIAL,
214};
215
e9c71dd1
TS
216/* Multiplication variants of the vr54xx. */
217#define MASK_MUL_VR54XX(op) MASK_SPECIAL(op) | (op & (0x1F << 6))
218
219enum {
220 OPC_VR54XX_MULS = (0x03 << 6) | OPC_MULT,
221 OPC_VR54XX_MULSU = (0x03 << 6) | OPC_MULTU,
222 OPC_VR54XX_MACC = (0x05 << 6) | OPC_MULT,
223 OPC_VR54XX_MACCU = (0x05 << 6) | OPC_MULTU,
224 OPC_VR54XX_MSAC = (0x07 << 6) | OPC_MULT,
225 OPC_VR54XX_MSACU = (0x07 << 6) | OPC_MULTU,
226 OPC_VR54XX_MULHI = (0x09 << 6) | OPC_MULT,
227 OPC_VR54XX_MULHIU = (0x09 << 6) | OPC_MULTU,
228 OPC_VR54XX_MULSHI = (0x0B << 6) | OPC_MULT,
229 OPC_VR54XX_MULSHIU = (0x0B << 6) | OPC_MULTU,
230 OPC_VR54XX_MACCHI = (0x0D << 6) | OPC_MULT,
231 OPC_VR54XX_MACCHIU = (0x0D << 6) | OPC_MULTU,
232 OPC_VR54XX_MSACHI = (0x0F << 6) | OPC_MULT,
233 OPC_VR54XX_MSACHIU = (0x0F << 6) | OPC_MULTU,
234};
235
7a387fff
TS
236/* REGIMM (rt field) opcodes */
237#define MASK_REGIMM(op) MASK_OP_MAJOR(op) | (op & (0x1F << 16))
238
239enum {
240 OPC_BLTZ = (0x00 << 16) | OPC_REGIMM,
241 OPC_BLTZL = (0x02 << 16) | OPC_REGIMM,
242 OPC_BGEZ = (0x01 << 16) | OPC_REGIMM,
243 OPC_BGEZL = (0x03 << 16) | OPC_REGIMM,
244 OPC_BLTZAL = (0x10 << 16) | OPC_REGIMM,
3c824109 245 OPC_BLTZALS = OPC_BLTZAL | 0x5, /* microMIPS */
7a387fff
TS
246 OPC_BLTZALL = (0x12 << 16) | OPC_REGIMM,
247 OPC_BGEZAL = (0x11 << 16) | OPC_REGIMM,
3c824109 248 OPC_BGEZALS = OPC_BGEZAL | 0x5, /* microMIPS */
7a387fff
TS
249 OPC_BGEZALL = (0x13 << 16) | OPC_REGIMM,
250 OPC_TGEI = (0x08 << 16) | OPC_REGIMM,
251 OPC_TGEIU = (0x09 << 16) | OPC_REGIMM,
252 OPC_TLTI = (0x0A << 16) | OPC_REGIMM,
253 OPC_TLTIU = (0x0B << 16) | OPC_REGIMM,
254 OPC_TEQI = (0x0C << 16) | OPC_REGIMM,
255 OPC_TNEI = (0x0E << 16) | OPC_REGIMM,
256 OPC_SYNCI = (0x1F << 16) | OPC_REGIMM,
e37e863f
FB
257};
258
7a387fff
TS
259/* Special2 opcodes */
260#define MASK_SPECIAL2(op) MASK_OP_MAJOR(op) | (op & 0x3F)
261
e37e863f 262enum {
7a387fff
TS
263 /* Multiply & xxx operations */
264 OPC_MADD = 0x00 | OPC_SPECIAL2,
265 OPC_MADDU = 0x01 | OPC_SPECIAL2,
266 OPC_MUL = 0x02 | OPC_SPECIAL2,
267 OPC_MSUB = 0x04 | OPC_SPECIAL2,
268 OPC_MSUBU = 0x05 | OPC_SPECIAL2,
161f85e6
AJ
269 /* Loongson 2F */
270 OPC_MULT_G_2F = 0x10 | OPC_SPECIAL2,
271 OPC_DMULT_G_2F = 0x11 | OPC_SPECIAL2,
272 OPC_MULTU_G_2F = 0x12 | OPC_SPECIAL2,
273 OPC_DMULTU_G_2F = 0x13 | OPC_SPECIAL2,
274 OPC_DIV_G_2F = 0x14 | OPC_SPECIAL2,
275 OPC_DDIV_G_2F = 0x15 | OPC_SPECIAL2,
276 OPC_DIVU_G_2F = 0x16 | OPC_SPECIAL2,
277 OPC_DDIVU_G_2F = 0x17 | OPC_SPECIAL2,
278 OPC_MOD_G_2F = 0x1c | OPC_SPECIAL2,
279 OPC_DMOD_G_2F = 0x1d | OPC_SPECIAL2,
280 OPC_MODU_G_2F = 0x1e | OPC_SPECIAL2,
281 OPC_DMODU_G_2F = 0x1f | OPC_SPECIAL2,
e37e863f 282 /* Misc */
7a387fff
TS
283 OPC_CLZ = 0x20 | OPC_SPECIAL2,
284 OPC_CLO = 0x21 | OPC_SPECIAL2,
285 OPC_DCLZ = 0x24 | OPC_SPECIAL2,
286 OPC_DCLO = 0x25 | OPC_SPECIAL2,
e37e863f 287 /* Special */
7a387fff
TS
288 OPC_SDBBP = 0x3F | OPC_SPECIAL2,
289};
290
291/* Special3 opcodes */
292#define MASK_SPECIAL3(op) MASK_OP_MAJOR(op) | (op & 0x3F)
293
294enum {
295 OPC_EXT = 0x00 | OPC_SPECIAL3,
296 OPC_DEXTM = 0x01 | OPC_SPECIAL3,
297 OPC_DEXTU = 0x02 | OPC_SPECIAL3,
298 OPC_DEXT = 0x03 | OPC_SPECIAL3,
299 OPC_INS = 0x04 | OPC_SPECIAL3,
300 OPC_DINSM = 0x05 | OPC_SPECIAL3,
301 OPC_DINSU = 0x06 | OPC_SPECIAL3,
302 OPC_DINS = 0x07 | OPC_SPECIAL3,
ead9360e
TS
303 OPC_FORK = 0x08 | OPC_SPECIAL3,
304 OPC_YIELD = 0x09 | OPC_SPECIAL3,
7a387fff
TS
305 OPC_BSHFL = 0x20 | OPC_SPECIAL3,
306 OPC_DBSHFL = 0x24 | OPC_SPECIAL3,
307 OPC_RDHWR = 0x3B | OPC_SPECIAL3,
161f85e6
AJ
308
309 /* Loongson 2E */
310 OPC_MULT_G_2E = 0x18 | OPC_SPECIAL3,
311 OPC_MULTU_G_2E = 0x19 | OPC_SPECIAL3,
312 OPC_DIV_G_2E = 0x1A | OPC_SPECIAL3,
313 OPC_DIVU_G_2E = 0x1B | OPC_SPECIAL3,
314 OPC_DMULT_G_2E = 0x1C | OPC_SPECIAL3,
315 OPC_DMULTU_G_2E = 0x1D | OPC_SPECIAL3,
316 OPC_DDIV_G_2E = 0x1E | OPC_SPECIAL3,
317 OPC_DDIVU_G_2E = 0x1F | OPC_SPECIAL3,
318 OPC_MOD_G_2E = 0x22 | OPC_SPECIAL3,
319 OPC_MODU_G_2E = 0x23 | OPC_SPECIAL3,
320 OPC_DMOD_G_2E = 0x26 | OPC_SPECIAL3,
321 OPC_DMODU_G_2E = 0x27 | OPC_SPECIAL3,
e37e863f
FB
322};
323
7a387fff
TS
324/* BSHFL opcodes */
325#define MASK_BSHFL(op) MASK_SPECIAL3(op) | (op & (0x1F << 6))
326
e37e863f 327enum {
7a387fff
TS
328 OPC_WSBH = (0x02 << 6) | OPC_BSHFL,
329 OPC_SEB = (0x10 << 6) | OPC_BSHFL,
330 OPC_SEH = (0x18 << 6) | OPC_BSHFL,
e37e863f
FB
331};
332
7a387fff
TS
333/* DBSHFL opcodes */
334#define MASK_DBSHFL(op) MASK_SPECIAL3(op) | (op & (0x1F << 6))
335
e37e863f 336enum {
7a387fff
TS
337 OPC_DSBH = (0x02 << 6) | OPC_DBSHFL,
338 OPC_DSHD = (0x05 << 6) | OPC_DBSHFL,
e37e863f
FB
339};
340
7a387fff
TS
341/* Coprocessor 0 (rs field) */
342#define MASK_CP0(op) MASK_OP_MAJOR(op) | (op & (0x1F << 21))
343
6ea83fed 344enum {
7a387fff
TS
345 OPC_MFC0 = (0x00 << 21) | OPC_CP0,
346 OPC_DMFC0 = (0x01 << 21) | OPC_CP0,
347 OPC_MTC0 = (0x04 << 21) | OPC_CP0,
348 OPC_DMTC0 = (0x05 << 21) | OPC_CP0,
ead9360e 349 OPC_MFTR = (0x08 << 21) | OPC_CP0,
7a387fff
TS
350 OPC_RDPGPR = (0x0A << 21) | OPC_CP0,
351 OPC_MFMC0 = (0x0B << 21) | OPC_CP0,
ead9360e 352 OPC_MTTR = (0x0C << 21) | OPC_CP0,
7a387fff
TS
353 OPC_WRPGPR = (0x0E << 21) | OPC_CP0,
354 OPC_C0 = (0x10 << 21) | OPC_CP0,
355 OPC_C0_FIRST = (0x10 << 21) | OPC_CP0,
356 OPC_C0_LAST = (0x1F << 21) | OPC_CP0,
6ea83fed 357};
7a387fff
TS
358
359/* MFMC0 opcodes */
b48cfdff 360#define MASK_MFMC0(op) MASK_CP0(op) | (op & 0xFFFF)
7a387fff
TS
361
362enum {
ead9360e
TS
363 OPC_DMT = 0x01 | (0 << 5) | (0x0F << 6) | (0x01 << 11) | OPC_MFMC0,
364 OPC_EMT = 0x01 | (1 << 5) | (0x0F << 6) | (0x01 << 11) | OPC_MFMC0,
365 OPC_DVPE = 0x01 | (0 << 5) | OPC_MFMC0,
366 OPC_EVPE = 0x01 | (1 << 5) | OPC_MFMC0,
7a387fff
TS
367 OPC_DI = (0 << 5) | (0x0C << 11) | OPC_MFMC0,
368 OPC_EI = (1 << 5) | (0x0C << 11) | OPC_MFMC0,
369};
370
371/* Coprocessor 0 (with rs == C0) */
372#define MASK_C0(op) MASK_CP0(op) | (op & 0x3F)
373
374enum {
375 OPC_TLBR = 0x01 | OPC_C0,
376 OPC_TLBWI = 0x02 | OPC_C0,
377 OPC_TLBWR = 0x06 | OPC_C0,
378 OPC_TLBP = 0x08 | OPC_C0,
379 OPC_RFE = 0x10 | OPC_C0,
380 OPC_ERET = 0x18 | OPC_C0,
381 OPC_DERET = 0x1F | OPC_C0,
382 OPC_WAIT = 0x20 | OPC_C0,
383};
384
385/* Coprocessor 1 (rs field) */
386#define MASK_CP1(op) MASK_OP_MAJOR(op) | (op & (0x1F << 21))
387
bf4120ad
NF
388/* Values for the fmt field in FP instructions */
389enum {
390 /* 0 - 15 are reserved */
e459440a
AJ
391 FMT_S = 16, /* single fp */
392 FMT_D = 17, /* double fp */
393 FMT_E = 18, /* extended fp */
394 FMT_Q = 19, /* quad fp */
395 FMT_W = 20, /* 32-bit fixed */
396 FMT_L = 21, /* 64-bit fixed */
397 FMT_PS = 22, /* paired single fp */
bf4120ad
NF
398 /* 23 - 31 are reserved */
399};
400
7a387fff
TS
401enum {
402 OPC_MFC1 = (0x00 << 21) | OPC_CP1,
403 OPC_DMFC1 = (0x01 << 21) | OPC_CP1,
404 OPC_CFC1 = (0x02 << 21) | OPC_CP1,
5a5012ec 405 OPC_MFHC1 = (0x03 << 21) | OPC_CP1,
7a387fff
TS
406 OPC_MTC1 = (0x04 << 21) | OPC_CP1,
407 OPC_DMTC1 = (0x05 << 21) | OPC_CP1,
408 OPC_CTC1 = (0x06 << 21) | OPC_CP1,
5a5012ec 409 OPC_MTHC1 = (0x07 << 21) | OPC_CP1,
7a387fff 410 OPC_BC1 = (0x08 << 21) | OPC_CP1, /* bc */
5a5012ec
TS
411 OPC_BC1ANY2 = (0x09 << 21) | OPC_CP1,
412 OPC_BC1ANY4 = (0x0A << 21) | OPC_CP1,
e459440a
AJ
413 OPC_S_FMT = (FMT_S << 21) | OPC_CP1,
414 OPC_D_FMT = (FMT_D << 21) | OPC_CP1,
415 OPC_E_FMT = (FMT_E << 21) | OPC_CP1,
416 OPC_Q_FMT = (FMT_Q << 21) | OPC_CP1,
417 OPC_W_FMT = (FMT_W << 21) | OPC_CP1,
418 OPC_L_FMT = (FMT_L << 21) | OPC_CP1,
419 OPC_PS_FMT = (FMT_PS << 21) | OPC_CP1,
7a387fff
TS
420};
421
5a5012ec
TS
422#define MASK_CP1_FUNC(op) MASK_CP1(op) | (op & 0x3F)
423#define MASK_BC1(op) MASK_CP1(op) | (op & (0x3 << 16))
424
7a387fff
TS
425enum {
426 OPC_BC1F = (0x00 << 16) | OPC_BC1,
427 OPC_BC1T = (0x01 << 16) | OPC_BC1,
428 OPC_BC1FL = (0x02 << 16) | OPC_BC1,
429 OPC_BC1TL = (0x03 << 16) | OPC_BC1,
430};
431
5a5012ec
TS
432enum {
433 OPC_BC1FANY2 = (0x00 << 16) | OPC_BC1ANY2,
434 OPC_BC1TANY2 = (0x01 << 16) | OPC_BC1ANY2,
435};
436
437enum {
438 OPC_BC1FANY4 = (0x00 << 16) | OPC_BC1ANY4,
439 OPC_BC1TANY4 = (0x01 << 16) | OPC_BC1ANY4,
440};
7a387fff
TS
441
442#define MASK_CP2(op) MASK_OP_MAJOR(op) | (op & (0x1F << 21))
e0c84da7
TS
443
444enum {
445 OPC_MFC2 = (0x00 << 21) | OPC_CP2,
446 OPC_DMFC2 = (0x01 << 21) | OPC_CP2,
447 OPC_CFC2 = (0x02 << 21) | OPC_CP2,
448 OPC_MFHC2 = (0x03 << 21) | OPC_CP2,
449 OPC_MTC2 = (0x04 << 21) | OPC_CP2,
450 OPC_DMTC2 = (0x05 << 21) | OPC_CP2,
451 OPC_CTC2 = (0x06 << 21) | OPC_CP2,
452 OPC_MTHC2 = (0x07 << 21) | OPC_CP2,
453 OPC_BC2 = (0x08 << 21) | OPC_CP2,
454};
455
456#define MASK_CP3(op) MASK_OP_MAJOR(op) | (op & 0x3F)
457
458enum {
459 OPC_LWXC1 = 0x00 | OPC_CP3,
460 OPC_LDXC1 = 0x01 | OPC_CP3,
461 OPC_LUXC1 = 0x05 | OPC_CP3,
462 OPC_SWXC1 = 0x08 | OPC_CP3,
463 OPC_SDXC1 = 0x09 | OPC_CP3,
464 OPC_SUXC1 = 0x0D | OPC_CP3,
465 OPC_PREFX = 0x0F | OPC_CP3,
466 OPC_ALNV_PS = 0x1E | OPC_CP3,
467 OPC_MADD_S = 0x20 | OPC_CP3,
468 OPC_MADD_D = 0x21 | OPC_CP3,
469 OPC_MADD_PS = 0x26 | OPC_CP3,
470 OPC_MSUB_S = 0x28 | OPC_CP3,
471 OPC_MSUB_D = 0x29 | OPC_CP3,
472 OPC_MSUB_PS = 0x2E | OPC_CP3,
473 OPC_NMADD_S = 0x30 | OPC_CP3,
fbcc6828 474 OPC_NMADD_D = 0x31 | OPC_CP3,
e0c84da7
TS
475 OPC_NMADD_PS= 0x36 | OPC_CP3,
476 OPC_NMSUB_S = 0x38 | OPC_CP3,
477 OPC_NMSUB_D = 0x39 | OPC_CP3,
478 OPC_NMSUB_PS= 0x3E | OPC_CP3,
479};
480
39454628 481/* global register indices */
a7812ae4
PB
482static TCGv_ptr cpu_env;
483static TCGv cpu_gpr[32], cpu_PC;
4b2eb8d2 484static TCGv cpu_HI[MIPS_DSP_ACC], cpu_LO[MIPS_DSP_ACC], cpu_ACX[MIPS_DSP_ACC];
41db4607
AJ
485static TCGv cpu_dspctrl, btarget, bcond;
486static TCGv_i32 hflags;
a7812ae4 487static TCGv_i32 fpu_fcr0, fpu_fcr31;
aa0bf00b 488
1a7ff922
PB
489static uint32_t gen_opc_hflags[OPC_BUF_SIZE];
490
2e70f6ef
PB
491#include "gen-icount.h"
492
a7812ae4
PB
493#define gen_helper_0i(name, arg) do { \
494 TCGv_i32 helper_tmp = tcg_const_i32(arg); \
495 gen_helper_##name(helper_tmp); \
496 tcg_temp_free_i32(helper_tmp); \
497 } while(0)
be24bb4f 498
a7812ae4
PB
499#define gen_helper_1i(name, arg1, arg2) do { \
500 TCGv_i32 helper_tmp = tcg_const_i32(arg2); \
501 gen_helper_##name(arg1, helper_tmp); \
502 tcg_temp_free_i32(helper_tmp); \
503 } while(0)
be24bb4f 504
a7812ae4
PB
505#define gen_helper_2i(name, arg1, arg2, arg3) do { \
506 TCGv_i32 helper_tmp = tcg_const_i32(arg3); \
507 gen_helper_##name(arg1, arg2, helper_tmp); \
508 tcg_temp_free_i32(helper_tmp); \
509 } while(0)
be24bb4f 510
a7812ae4
PB
511#define gen_helper_3i(name, arg1, arg2, arg3, arg4) do { \
512 TCGv_i32 helper_tmp = tcg_const_i32(arg4); \
513 gen_helper_##name(arg1, arg2, arg3, helper_tmp); \
514 tcg_temp_free_i32(helper_tmp); \
515 } while(0)
c239529e 516
8e9ade68
TS
517typedef struct DisasContext {
518 struct TranslationBlock *tb;
519 target_ulong pc, saved_pc;
520 uint32_t opcode;
7b270ef2 521 int singlestep_enabled;
8e9ade68
TS
522 /* Routine used to access memory */
523 int mem_idx;
524 uint32_t hflags, saved_hflags;
525 int bstate;
526 target_ulong btarget;
527} DisasContext;
528
529enum {
530 BS_NONE = 0, /* We go out of the TB without reaching a branch or an
d077b6f7 531 * exception condition */
8e9ade68
TS
532 BS_STOP = 1, /* We want to stop translation for any reason */
533 BS_BRANCH = 2, /* We reached a branch condition */
534 BS_EXCP = 3, /* We reached an exception condition */
535};
536
537static const char *regnames[] =
6af0bf9c
FB
538 { "r0", "at", "v0", "v1", "a0", "a1", "a2", "a3",
539 "t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7",
540 "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7",
541 "t8", "t9", "k0", "k1", "gp", "sp", "s8", "ra", };
542
4b2eb8d2
TS
543static const char *regnames_HI[] =
544 { "HI0", "HI1", "HI2", "HI3", };
545
546static const char *regnames_LO[] =
547 { "LO0", "LO1", "LO2", "LO3", };
548
549static const char *regnames_ACX[] =
550 { "ACX0", "ACX1", "ACX2", "ACX3", };
551
8e9ade68
TS
552static const char *fregnames[] =
553 { "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7",
554 "f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15",
555 "f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23",
556 "f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31", };
958fb4a9 557
8e9ade68 558#ifdef MIPS_DEBUG_DISAS
001faf32 559#define MIPS_DEBUG(fmt, ...) \
93fcfe39
AL
560 qemu_log_mask(CPU_LOG_TB_IN_ASM, \
561 TARGET_FMT_lx ": %08x " fmt "\n", \
001faf32 562 ctx->pc, ctx->opcode , ## __VA_ARGS__)
93fcfe39 563#define LOG_DISAS(...) qemu_log_mask(CPU_LOG_TB_IN_ASM, ## __VA_ARGS__)
8e9ade68 564#else
001faf32 565#define MIPS_DEBUG(fmt, ...) do { } while(0)
d12d51d5 566#define LOG_DISAS(...) do { } while (0)
8e9ade68 567#endif
958fb4a9 568
8e9ade68
TS
569#define MIPS_INVAL(op) \
570do { \
571 MIPS_DEBUG("Invalid %s %03x %03x %03x", op, ctx->opcode >> 26, \
572 ctx->opcode & 0x3F, ((ctx->opcode >> 16) & 0x1F)); \
573} while (0)
ead9360e 574
8e9ade68
TS
575/* General purpose registers moves. */
576static inline void gen_load_gpr (TCGv t, int reg)
aaa9128a 577{
8e9ade68
TS
578 if (reg == 0)
579 tcg_gen_movi_tl(t, 0);
580 else
4b2eb8d2 581 tcg_gen_mov_tl(t, cpu_gpr[reg]);
aaa9128a
TS
582}
583
8e9ade68 584static inline void gen_store_gpr (TCGv t, int reg)
aaa9128a 585{
8e9ade68 586 if (reg != 0)
4b2eb8d2 587 tcg_gen_mov_tl(cpu_gpr[reg], t);
aaa9128a
TS
588}
589
b10fa3c9 590/* Moves to/from ACX register. */
4b2eb8d2 591static inline void gen_load_ACX (TCGv t, int reg)
893f9865 592{
4b2eb8d2 593 tcg_gen_mov_tl(t, cpu_ACX[reg]);
893f9865
TS
594}
595
4b2eb8d2 596static inline void gen_store_ACX (TCGv t, int reg)
893f9865 597{
4b2eb8d2 598 tcg_gen_mov_tl(cpu_ACX[reg], t);
893f9865
TS
599}
600
8e9ade68 601/* Moves to/from shadow registers. */
be24bb4f 602static inline void gen_load_srsgpr (int from, int to)
aaa9128a 603{
d9bea114 604 TCGv t0 = tcg_temp_new();
be24bb4f
TS
605
606 if (from == 0)
d9bea114 607 tcg_gen_movi_tl(t0, 0);
8e9ade68 608 else {
d9bea114 609 TCGv_i32 t2 = tcg_temp_new_i32();
a7812ae4 610 TCGv_ptr addr = tcg_temp_new_ptr();
aaa9128a 611
d9bea114
AJ
612 tcg_gen_ld_i32(t2, cpu_env, offsetof(CPUState, CP0_SRSCtl));
613 tcg_gen_shri_i32(t2, t2, CP0SRSCtl_PSS);
614 tcg_gen_andi_i32(t2, t2, 0xf);
615 tcg_gen_muli_i32(t2, t2, sizeof(target_ulong) * 32);
616 tcg_gen_ext_i32_ptr(addr, t2);
a7812ae4 617 tcg_gen_add_ptr(addr, cpu_env, addr);
aaa9128a 618
d9bea114 619 tcg_gen_ld_tl(t0, addr, sizeof(target_ulong) * from);
a7812ae4 620 tcg_temp_free_ptr(addr);
d9bea114 621 tcg_temp_free_i32(t2);
8e9ade68 622 }
d9bea114
AJ
623 gen_store_gpr(t0, to);
624 tcg_temp_free(t0);
aaa9128a
TS
625}
626
be24bb4f 627static inline void gen_store_srsgpr (int from, int to)
aaa9128a 628{
be24bb4f 629 if (to != 0) {
d9bea114
AJ
630 TCGv t0 = tcg_temp_new();
631 TCGv_i32 t2 = tcg_temp_new_i32();
a7812ae4 632 TCGv_ptr addr = tcg_temp_new_ptr();
be24bb4f 633
d9bea114
AJ
634 gen_load_gpr(t0, from);
635 tcg_gen_ld_i32(t2, cpu_env, offsetof(CPUState, CP0_SRSCtl));
636 tcg_gen_shri_i32(t2, t2, CP0SRSCtl_PSS);
637 tcg_gen_andi_i32(t2, t2, 0xf);
638 tcg_gen_muli_i32(t2, t2, sizeof(target_ulong) * 32);
639 tcg_gen_ext_i32_ptr(addr, t2);
a7812ae4 640 tcg_gen_add_ptr(addr, cpu_env, addr);
be24bb4f 641
d9bea114 642 tcg_gen_st_tl(t0, addr, sizeof(target_ulong) * to);
a7812ae4 643 tcg_temp_free_ptr(addr);
d9bea114
AJ
644 tcg_temp_free_i32(t2);
645 tcg_temp_free(t0);
8e9ade68 646 }
aaa9128a
TS
647}
648
aaa9128a 649/* Floating point register moves. */
a7812ae4 650static inline void gen_load_fpr32 (TCGv_i32 t, int reg)
aa0bf00b 651{
6d066274 652 tcg_gen_ld_i32(t, cpu_env, offsetof(CPUState, active_fpu.fpr[reg].w[FP_ENDIAN_IDX]));
6ea83fed
FB
653}
654
a7812ae4 655static inline void gen_store_fpr32 (TCGv_i32 t, int reg)
aa0bf00b 656{
6d066274
AJ
657 tcg_gen_st_i32(t, cpu_env, offsetof(CPUState, active_fpu.fpr[reg].w[FP_ENDIAN_IDX]));
658}
659
660static inline void gen_load_fpr32h (TCGv_i32 t, int reg)
661{
662 tcg_gen_ld_i32(t, cpu_env, offsetof(CPUState, active_fpu.fpr[reg].w[!FP_ENDIAN_IDX]));
663}
664
665static inline void gen_store_fpr32h (TCGv_i32 t, int reg)
666{
667 tcg_gen_st_i32(t, cpu_env, offsetof(CPUState, active_fpu.fpr[reg].w[!FP_ENDIAN_IDX]));
aa0bf00b 668}
6ea83fed 669
a7812ae4 670static inline void gen_load_fpr64 (DisasContext *ctx, TCGv_i64 t, int reg)
aa0bf00b 671{
f364515c 672 if (ctx->hflags & MIPS_HFLAG_F64) {
6d066274 673 tcg_gen_ld_i64(t, cpu_env, offsetof(CPUState, active_fpu.fpr[reg].d));
f364515c 674 } else {
6d066274
AJ
675 TCGv_i32 t0 = tcg_temp_new_i32();
676 TCGv_i32 t1 = tcg_temp_new_i32();
677 gen_load_fpr32(t0, reg & ~1);
678 gen_load_fpr32(t1, reg | 1);
679 tcg_gen_concat_i32_i64(t, t0, t1);
680 tcg_temp_free_i32(t0);
681 tcg_temp_free_i32(t1);
aa0bf00b
TS
682 }
683}
6ea83fed 684
a7812ae4 685static inline void gen_store_fpr64 (DisasContext *ctx, TCGv_i64 t, int reg)
aa0bf00b 686{
f364515c 687 if (ctx->hflags & MIPS_HFLAG_F64) {
6d066274 688 tcg_gen_st_i64(t, cpu_env, offsetof(CPUState, active_fpu.fpr[reg].d));
f364515c 689 } else {
6d066274
AJ
690 TCGv_i64 t0 = tcg_temp_new_i64();
691 TCGv_i32 t1 = tcg_temp_new_i32();
692 tcg_gen_trunc_i64_i32(t1, t);
693 gen_store_fpr32(t1, reg & ~1);
694 tcg_gen_shri_i64(t0, t, 32);
695 tcg_gen_trunc_i64_i32(t1, t0);
696 gen_store_fpr32(t1, reg | 1);
697 tcg_temp_free_i32(t1);
698 tcg_temp_free_i64(t0);
aa0bf00b
TS
699 }
700}
6ea83fed 701
d94536f4 702static inline int get_fp_bit (int cc)
a16336e4 703{
d94536f4
AJ
704 if (cc)
705 return 24 + cc;
706 else
707 return 23;
a16336e4
TS
708}
709
30898801 710/* Tests */
8e9ade68
TS
711static inline void gen_save_pc(target_ulong pc)
712{
1eb75d4a 713 tcg_gen_movi_tl(cpu_PC, pc);
8e9ade68 714}
30898801 715
356265ae 716static inline void save_cpu_state (DisasContext *ctx, int do_save_pc)
6af0bf9c 717{
d12d51d5 718 LOG_DISAS("hflags %08x saved %08x\n", ctx->hflags, ctx->saved_hflags);
6af0bf9c 719 if (do_save_pc && ctx->pc != ctx->saved_pc) {
9b9e4393 720 gen_save_pc(ctx->pc);
6af0bf9c
FB
721 ctx->saved_pc = ctx->pc;
722 }
723 if (ctx->hflags != ctx->saved_hflags) {
41db4607 724 tcg_gen_movi_i32(hflags, ctx->hflags);
6af0bf9c 725 ctx->saved_hflags = ctx->hflags;
364d4831 726 switch (ctx->hflags & MIPS_HFLAG_BMASK_BASE) {
5a5012ec 727 case MIPS_HFLAG_BR:
5a5012ec
TS
728 break;
729 case MIPS_HFLAG_BC:
5a5012ec 730 case MIPS_HFLAG_BL:
5a5012ec 731 case MIPS_HFLAG_B:
d077b6f7 732 tcg_gen_movi_tl(btarget, ctx->btarget);
5a5012ec 733 break;
6af0bf9c
FB
734 }
735 }
736}
737
356265ae 738static inline void restore_cpu_state (CPUState *env, DisasContext *ctx)
5a5012ec 739{
fd4a04eb 740 ctx->saved_hflags = ctx->hflags;
364d4831 741 switch (ctx->hflags & MIPS_HFLAG_BMASK_BASE) {
fd4a04eb 742 case MIPS_HFLAG_BR:
fd4a04eb
TS
743 break;
744 case MIPS_HFLAG_BC:
745 case MIPS_HFLAG_BL:
39454628 746 case MIPS_HFLAG_B:
fd4a04eb 747 ctx->btarget = env->btarget;
fd4a04eb 748 break;
5a5012ec
TS
749 }
750}
751
356265ae 752static inline void
48d38ca5 753generate_exception_err (DisasContext *ctx, int excp, int err)
aaa9128a 754{
a7812ae4
PB
755 TCGv_i32 texcp = tcg_const_i32(excp);
756 TCGv_i32 terr = tcg_const_i32(err);
aaa9128a 757 save_cpu_state(ctx, 1);
a7812ae4
PB
758 gen_helper_raise_exception_err(texcp, terr);
759 tcg_temp_free_i32(terr);
760 tcg_temp_free_i32(texcp);
aaa9128a
TS
761}
762
356265ae 763static inline void
48d38ca5 764generate_exception (DisasContext *ctx, int excp)
aaa9128a 765{
6af0bf9c 766 save_cpu_state(ctx, 1);
a7812ae4 767 gen_helper_0i(raise_exception, excp);
6af0bf9c
FB
768}
769
48d38ca5 770/* Addresses computation */
941694d0 771static inline void gen_op_addr_add (DisasContext *ctx, TCGv ret, TCGv arg0, TCGv arg1)
4ad40f36 772{
941694d0 773 tcg_gen_add_tl(ret, arg0, arg1);
48d38ca5
TS
774
775#if defined(TARGET_MIPS64)
776 /* For compatibility with 32-bit code, data reference in user mode
777 with Status_UX = 0 should be casted to 32-bit and sign extended.
778 See the MIPS64 PRA manual, section 4.10. */
2623c1ec
AJ
779 if (((ctx->hflags & MIPS_HFLAG_KSU) == MIPS_HFLAG_UM) &&
780 !(ctx->hflags & MIPS_HFLAG_UX)) {
941694d0 781 tcg_gen_ext32s_i64(ret, ret);
48d38ca5
TS
782 }
783#endif
4ad40f36
FB
784}
785
356265ae 786static inline void check_cp0_enabled(DisasContext *ctx)
387a8fe5 787{
fe253235 788 if (unlikely(!(ctx->hflags & MIPS_HFLAG_CP0)))
c2c65dab 789 generate_exception_err(ctx, EXCP_CpU, 0);
387a8fe5
TS
790}
791
356265ae 792static inline void check_cp1_enabled(DisasContext *ctx)
5e755519 793{
fe253235 794 if (unlikely(!(ctx->hflags & MIPS_HFLAG_FPU)))
5e755519
TS
795 generate_exception_err(ctx, EXCP_CpU, 1);
796}
797
b8aa4598
TS
798/* Verify that the processor is running with COP1X instructions enabled.
799 This is associated with the nabla symbol in the MIPS32 and MIPS64
800 opcode tables. */
801
356265ae 802static inline void check_cop1x(DisasContext *ctx)
b8aa4598
TS
803{
804 if (unlikely(!(ctx->hflags & MIPS_HFLAG_COP1X)))
805 generate_exception(ctx, EXCP_RI);
806}
807
808/* Verify that the processor is running with 64-bit floating-point
809 operations enabled. */
810
356265ae 811static inline void check_cp1_64bitmode(DisasContext *ctx)
5e755519 812{
b8aa4598 813 if (unlikely(~ctx->hflags & (MIPS_HFLAG_F64 | MIPS_HFLAG_COP1X)))
5e755519
TS
814 generate_exception(ctx, EXCP_RI);
815}
816
817/*
818 * Verify if floating point register is valid; an operation is not defined
819 * if bit 0 of any register specification is set and the FR bit in the
820 * Status register equals zero, since the register numbers specify an
821 * even-odd pair of adjacent coprocessor general registers. When the FR bit
822 * in the Status register equals one, both even and odd register numbers
823 * are valid. This limitation exists only for 64 bit wide (d,l,ps) registers.
824 *
825 * Multiple 64 bit wide registers can be checked by calling
826 * gen_op_cp1_registers(freg1 | freg2 | ... | fregN);
827 */
356265ae 828static inline void check_cp1_registers(DisasContext *ctx, int regs)
5e755519 829{
fe253235 830 if (unlikely(!(ctx->hflags & MIPS_HFLAG_F64) && (regs & 1)))
5e755519
TS
831 generate_exception(ctx, EXCP_RI);
832}
833
3a95e3a7 834/* This code generates a "reserved instruction" exception if the
e189e748 835 CPU does not support the instruction set corresponding to flags. */
356265ae 836static inline void check_insn(CPUState *env, DisasContext *ctx, int flags)
3a95e3a7 837{
e189e748 838 if (unlikely(!(env->insn_flags & flags)))
3a95e3a7
TS
839 generate_exception(ctx, EXCP_RI);
840}
841
e189e748
TS
842/* This code generates a "reserved instruction" exception if 64-bit
843 instructions are not enabled. */
356265ae 844static inline void check_mips_64(DisasContext *ctx)
e189e748 845{
fe253235 846 if (unlikely(!(ctx->hflags & MIPS_HFLAG_64)))
e189e748
TS
847 generate_exception(ctx, EXCP_RI);
848}
849
8153667c
NF
850/* Define small wrappers for gen_load_fpr* so that we have a uniform
851 calling interface for 32 and 64-bit FPRs. No sense in changing
852 all callers for gen_load_fpr32 when we need the CTX parameter for
853 this one use. */
854#define gen_ldcmp_fpr32(ctx, x, y) gen_load_fpr32(x, y)
855#define gen_ldcmp_fpr64(ctx, x, y) gen_load_fpr64(ctx, x, y)
856#define FOP_CONDS(type, abs, fmt, ifmt, bits) \
857static inline void gen_cmp ## type ## _ ## fmt(DisasContext *ctx, int n, \
858 int ft, int fs, int cc) \
859{ \
860 TCGv_i##bits fp0 = tcg_temp_new_i##bits (); \
861 TCGv_i##bits fp1 = tcg_temp_new_i##bits (); \
862 switch (ifmt) { \
863 case FMT_PS: \
864 check_cp1_64bitmode(ctx); \
865 break; \
866 case FMT_D: \
867 if (abs) { \
868 check_cop1x(ctx); \
869 } \
870 check_cp1_registers(ctx, fs | ft); \
871 break; \
872 case FMT_S: \
873 if (abs) { \
874 check_cop1x(ctx); \
875 } \
876 break; \
877 } \
878 gen_ldcmp_fpr##bits (ctx, fp0, fs); \
879 gen_ldcmp_fpr##bits (ctx, fp1, ft); \
880 switch (n) { \
881 case 0: gen_helper_2i(cmp ## type ## _ ## fmt ## _f, fp0, fp1, cc); break;\
882 case 1: gen_helper_2i(cmp ## type ## _ ## fmt ## _un, fp0, fp1, cc); break;\
883 case 2: gen_helper_2i(cmp ## type ## _ ## fmt ## _eq, fp0, fp1, cc); break;\
884 case 3: gen_helper_2i(cmp ## type ## _ ## fmt ## _ueq, fp0, fp1, cc); break;\
885 case 4: gen_helper_2i(cmp ## type ## _ ## fmt ## _olt, fp0, fp1, cc); break;\
886 case 5: gen_helper_2i(cmp ## type ## _ ## fmt ## _ult, fp0, fp1, cc); break;\
887 case 6: gen_helper_2i(cmp ## type ## _ ## fmt ## _ole, fp0, fp1, cc); break;\
888 case 7: gen_helper_2i(cmp ## type ## _ ## fmt ## _ule, fp0, fp1, cc); break;\
889 case 8: gen_helper_2i(cmp ## type ## _ ## fmt ## _sf, fp0, fp1, cc); break;\
890 case 9: gen_helper_2i(cmp ## type ## _ ## fmt ## _ngle, fp0, fp1, cc); break;\
891 case 10: gen_helper_2i(cmp ## type ## _ ## fmt ## _seq, fp0, fp1, cc); break;\
892 case 11: gen_helper_2i(cmp ## type ## _ ## fmt ## _ngl, fp0, fp1, cc); break;\
893 case 12: gen_helper_2i(cmp ## type ## _ ## fmt ## _lt, fp0, fp1, cc); break;\
894 case 13: gen_helper_2i(cmp ## type ## _ ## fmt ## _nge, fp0, fp1, cc); break;\
895 case 14: gen_helper_2i(cmp ## type ## _ ## fmt ## _le, fp0, fp1, cc); break;\
896 case 15: gen_helper_2i(cmp ## type ## _ ## fmt ## _ngt, fp0, fp1, cc); break;\
897 default: abort(); \
898 } \
899 tcg_temp_free_i##bits (fp0); \
900 tcg_temp_free_i##bits (fp1); \
901}
902
903FOP_CONDS(, 0, d, FMT_D, 64)
904FOP_CONDS(abs, 1, d, FMT_D, 64)
905FOP_CONDS(, 0, s, FMT_S, 32)
906FOP_CONDS(abs, 1, s, FMT_S, 32)
907FOP_CONDS(, 0, ps, FMT_PS, 64)
908FOP_CONDS(abs, 1, ps, FMT_PS, 64)
909#undef FOP_CONDS
910#undef gen_ldcmp_fpr32
911#undef gen_ldcmp_fpr64
912
958fb4a9 913/* load/store instructions. */
d9bea114 914#define OP_LD(insn,fname) \
5c13fdfd 915static inline void op_ld_##insn(TCGv ret, TCGv arg1, DisasContext *ctx) \
d9bea114
AJ
916{ \
917 tcg_gen_qemu_##fname(ret, arg1, ctx->mem_idx); \
aaa9128a
TS
918}
919OP_LD(lb,ld8s);
920OP_LD(lbu,ld8u);
921OP_LD(lh,ld16s);
922OP_LD(lhu,ld16u);
923OP_LD(lw,ld32s);
924#if defined(TARGET_MIPS64)
925OP_LD(lwu,ld32u);
926OP_LD(ld,ld64);
927#endif
928#undef OP_LD
929
d9bea114 930#define OP_ST(insn,fname) \
5c13fdfd 931static inline void op_st_##insn(TCGv arg1, TCGv arg2, DisasContext *ctx) \
d9bea114
AJ
932{ \
933 tcg_gen_qemu_##fname(arg1, arg2, ctx->mem_idx); \
aaa9128a
TS
934}
935OP_ST(sb,st8);
936OP_ST(sh,st16);
937OP_ST(sw,st32);
938#if defined(TARGET_MIPS64)
939OP_ST(sd,st64);
940#endif
941#undef OP_ST
942
e7139c44 943#ifdef CONFIG_USER_ONLY
d9bea114 944#define OP_LD_ATOMIC(insn,fname) \
5c13fdfd 945static inline void op_ld_##insn(TCGv ret, TCGv arg1, DisasContext *ctx) \
d9bea114
AJ
946{ \
947 TCGv t0 = tcg_temp_new(); \
948 tcg_gen_mov_tl(t0, arg1); \
949 tcg_gen_qemu_##fname(ret, arg1, ctx->mem_idx); \
e7139c44 950 tcg_gen_st_tl(t0, cpu_env, offsetof(CPUState, lladdr)); \
590bc601 951 tcg_gen_st_tl(ret, cpu_env, offsetof(CPUState, llval)); \
d9bea114 952 tcg_temp_free(t0); \
aaa9128a 953}
e7139c44
AJ
954#else
955#define OP_LD_ATOMIC(insn,fname) \
5c13fdfd 956static inline void op_ld_##insn(TCGv ret, TCGv arg1, DisasContext *ctx) \
e7139c44
AJ
957{ \
958 gen_helper_2i(insn, ret, arg1, ctx->mem_idx); \
959}
960#endif
aaa9128a
TS
961OP_LD_ATOMIC(ll,ld32s);
962#if defined(TARGET_MIPS64)
963OP_LD_ATOMIC(lld,ld64);
964#endif
965#undef OP_LD_ATOMIC
966
590bc601
PB
967#ifdef CONFIG_USER_ONLY
968#define OP_ST_ATOMIC(insn,fname,ldname,almask) \
5c13fdfd 969static inline void op_st_##insn(TCGv arg1, TCGv arg2, int rt, DisasContext *ctx) \
590bc601
PB
970{ \
971 TCGv t0 = tcg_temp_new(); \
972 int l1 = gen_new_label(); \
973 int l2 = gen_new_label(); \
974 \
975 tcg_gen_andi_tl(t0, arg2, almask); \
976 tcg_gen_brcondi_tl(TCG_COND_EQ, t0, 0, l1); \
977 tcg_gen_st_tl(arg2, cpu_env, offsetof(CPUState, CP0_BadVAddr)); \
978 generate_exception(ctx, EXCP_AdES); \
979 gen_set_label(l1); \
e7139c44 980 tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUState, lladdr)); \
590bc601
PB
981 tcg_gen_brcond_tl(TCG_COND_NE, arg2, t0, l2); \
982 tcg_gen_movi_tl(t0, rt | ((almask << 3) & 0x20)); \
983 tcg_gen_st_tl(t0, cpu_env, offsetof(CPUState, llreg)); \
984 tcg_gen_st_tl(arg1, cpu_env, offsetof(CPUState, llnewval)); \
985 gen_helper_0i(raise_exception, EXCP_SC); \
986 gen_set_label(l2); \
987 tcg_gen_movi_tl(t0, 0); \
988 gen_store_gpr(t0, rt); \
989 tcg_temp_free(t0); \
990}
991#else
992#define OP_ST_ATOMIC(insn,fname,ldname,almask) \
5c13fdfd 993static inline void op_st_##insn(TCGv arg1, TCGv arg2, int rt, DisasContext *ctx) \
590bc601
PB
994{ \
995 TCGv t0 = tcg_temp_new(); \
e7139c44 996 gen_helper_3i(insn, t0, arg1, arg2, ctx->mem_idx); \
590bc601 997 gen_store_gpr(t0, rt); \
590bc601
PB
998 tcg_temp_free(t0); \
999}
1000#endif
590bc601 1001OP_ST_ATOMIC(sc,st32,ld32s,0x3);
aaa9128a 1002#if defined(TARGET_MIPS64)
590bc601 1003OP_ST_ATOMIC(scd,st64,ld64,0x7);
aaa9128a
TS
1004#endif
1005#undef OP_ST_ATOMIC
1006
662d7485
NF
1007static void gen_base_offset_addr (DisasContext *ctx, TCGv addr,
1008 int base, int16_t offset)
1009{
1010 if (base == 0) {
1011 tcg_gen_movi_tl(addr, offset);
1012 } else if (offset == 0) {
1013 gen_load_gpr(addr, base);
1014 } else {
1015 tcg_gen_movi_tl(addr, offset);
1016 gen_op_addr_add(ctx, addr, cpu_gpr[base], addr);
1017 }
1018}
1019
364d4831
NF
1020static target_ulong pc_relative_pc (DisasContext *ctx)
1021{
1022 target_ulong pc = ctx->pc;
1023
1024 if (ctx->hflags & MIPS_HFLAG_BMASK) {
1025 int branch_bytes = ctx->hflags & MIPS_HFLAG_BDS16 ? 2 : 4;
1026
1027 pc -= branch_bytes;
1028 }
1029
1030 pc &= ~(target_ulong)3;
1031 return pc;
1032}
1033
5c13fdfd 1034/* Load */
afa88c3a
AJ
1035static void gen_ld (CPUState *env, DisasContext *ctx, uint32_t opc,
1036 int rt, int base, int16_t offset)
6af0bf9c 1037{
5c13fdfd 1038 const char *opn = "ld";
afa88c3a
AJ
1039 TCGv t0, t1;
1040
1041 if (rt == 0 && env->insn_flags & (INSN_LOONGSON2E | INSN_LOONGSON2F)) {
1042 /* Loongson CPU uses a load to zero register for prefetch.
1043 We emulate it as a NOP. On other CPU we must perform the
1044 actual memory access. */
1045 MIPS_DEBUG("NOP");
1046 return;
1047 }
6af0bf9c 1048
afa88c3a
AJ
1049 t0 = tcg_temp_new();
1050 t1 = tcg_temp_new();
662d7485 1051 gen_base_offset_addr(ctx, t0, base, offset);
afa88c3a 1052
6af0bf9c 1053 switch (opc) {
d26bc211 1054#if defined(TARGET_MIPS64)
6e473128 1055 case OPC_LWU:
d66c7132 1056 save_cpu_state(ctx, 0);
5c13fdfd 1057 op_ld_lwu(t0, t0, ctx);
78723684 1058 gen_store_gpr(t0, rt);
6e473128
TS
1059 opn = "lwu";
1060 break;
6af0bf9c 1061 case OPC_LD:
d66c7132 1062 save_cpu_state(ctx, 0);
5c13fdfd 1063 op_ld_ld(t0, t0, ctx);
78723684 1064 gen_store_gpr(t0, rt);
6af0bf9c
FB
1065 opn = "ld";
1066 break;
7a387fff 1067 case OPC_LLD:
b835e919 1068 save_cpu_state(ctx, 1);
5c13fdfd 1069 op_ld_lld(t0, t0, ctx);
78723684 1070 gen_store_gpr(t0, rt);
7a387fff
TS
1071 opn = "lld";
1072 break;
6af0bf9c 1073 case OPC_LDL:
c8c2227e 1074 save_cpu_state(ctx, 1);
78723684 1075 gen_load_gpr(t1, rt);
d9bea114 1076 gen_helper_3i(ldl, t1, t1, t0, ctx->mem_idx);
78723684 1077 gen_store_gpr(t1, rt);
6af0bf9c
FB
1078 opn = "ldl";
1079 break;
6af0bf9c 1080 case OPC_LDR:
c8c2227e 1081 save_cpu_state(ctx, 1);
78723684 1082 gen_load_gpr(t1, rt);
d9bea114 1083 gen_helper_3i(ldr, t1, t1, t0, ctx->mem_idx);
78723684 1084 gen_store_gpr(t1, rt);
6af0bf9c
FB
1085 opn = "ldr";
1086 break;
364d4831 1087 case OPC_LDPC:
b835e919 1088 save_cpu_state(ctx, 0);
364d4831
NF
1089 tcg_gen_movi_tl(t1, pc_relative_pc(ctx));
1090 gen_op_addr_add(ctx, t0, t0, t1);
5c13fdfd 1091 op_ld_ld(t0, t0, ctx);
364d4831 1092 gen_store_gpr(t0, rt);
5c13fdfd 1093 opn = "ldpc";
364d4831 1094 break;
6af0bf9c 1095#endif
364d4831 1096 case OPC_LWPC:
b835e919 1097 save_cpu_state(ctx, 0);
364d4831
NF
1098 tcg_gen_movi_tl(t1, pc_relative_pc(ctx));
1099 gen_op_addr_add(ctx, t0, t0, t1);
5c13fdfd 1100 op_ld_lw(t0, t0, ctx);
364d4831 1101 gen_store_gpr(t0, rt);
5c13fdfd 1102 opn = "lwpc";
364d4831 1103 break;
6af0bf9c 1104 case OPC_LW:
d66c7132 1105 save_cpu_state(ctx, 0);
5c13fdfd 1106 op_ld_lw(t0, t0, ctx);
78723684 1107 gen_store_gpr(t0, rt);
6af0bf9c
FB
1108 opn = "lw";
1109 break;
6af0bf9c 1110 case OPC_LH:
d66c7132 1111 save_cpu_state(ctx, 0);
5c13fdfd 1112 op_ld_lh(t0, t0, ctx);
78723684 1113 gen_store_gpr(t0, rt);
6af0bf9c
FB
1114 opn = "lh";
1115 break;
6af0bf9c 1116 case OPC_LHU:
d66c7132 1117 save_cpu_state(ctx, 0);
5c13fdfd 1118 op_ld_lhu(t0, t0, ctx);
78723684 1119 gen_store_gpr(t0, rt);
6af0bf9c
FB
1120 opn = "lhu";
1121 break;
1122 case OPC_LB:
d66c7132 1123 save_cpu_state(ctx, 0);
5c13fdfd 1124 op_ld_lb(t0, t0, ctx);
78723684 1125 gen_store_gpr(t0, rt);
6af0bf9c
FB
1126 opn = "lb";
1127 break;
6af0bf9c 1128 case OPC_LBU:
d66c7132 1129 save_cpu_state(ctx, 0);
5c13fdfd 1130 op_ld_lbu(t0, t0, ctx);
78723684 1131 gen_store_gpr(t0, rt);
6af0bf9c
FB
1132 opn = "lbu";
1133 break;
1134 case OPC_LWL:
c8c2227e 1135 save_cpu_state(ctx, 1);
6958549d 1136 gen_load_gpr(t1, rt);
d9bea114 1137 gen_helper_3i(lwl, t1, t1, t0, ctx->mem_idx);
78723684 1138 gen_store_gpr(t1, rt);
6af0bf9c
FB
1139 opn = "lwl";
1140 break;
6af0bf9c 1141 case OPC_LWR:
c8c2227e 1142 save_cpu_state(ctx, 1);
6958549d 1143 gen_load_gpr(t1, rt);
d9bea114 1144 gen_helper_3i(lwr, t1, t1, t0, ctx->mem_idx);
78723684 1145 gen_store_gpr(t1, rt);
6af0bf9c
FB
1146 opn = "lwr";
1147 break;
6af0bf9c 1148 case OPC_LL:
e7139c44 1149 save_cpu_state(ctx, 1);
5c13fdfd 1150 op_ld_ll(t0, t0, ctx);
78723684 1151 gen_store_gpr(t0, rt);
6af0bf9c
FB
1152 opn = "ll";
1153 break;
d66c7132 1154 }
2abf314d 1155 (void)opn; /* avoid a compiler warning */
d66c7132
AJ
1156 MIPS_DEBUG("%s %s, %d(%s)", opn, regnames[rt], offset, regnames[base]);
1157 tcg_temp_free(t0);
1158 tcg_temp_free(t1);
1159}
1160
5c13fdfd
AJ
1161/* Store */
1162static void gen_st (DisasContext *ctx, uint32_t opc, int rt,
1163 int base, int16_t offset)
1164{
1165 const char *opn = "st";
1166 TCGv t0 = tcg_temp_new();
1167 TCGv t1 = tcg_temp_new();
1168
1169 gen_base_offset_addr(ctx, t0, base, offset);
1170 gen_load_gpr(t1, rt);
1171 switch (opc) {
1172#if defined(TARGET_MIPS64)
1173 case OPC_SD:
1174 save_cpu_state(ctx, 0);
1175 op_st_sd(t1, t0, ctx);
1176 opn = "sd";
1177 break;
1178 case OPC_SDL:
1179 save_cpu_state(ctx, 1);
1180 gen_helper_2i(sdl, t1, t0, ctx->mem_idx);
1181 opn = "sdl";
1182 break;
1183 case OPC_SDR:
1184 save_cpu_state(ctx, 1);
1185 gen_helper_2i(sdr, t1, t0, ctx->mem_idx);
1186 opn = "sdr";
1187 break;
1188#endif
1189 case OPC_SW:
1190 save_cpu_state(ctx, 0);
1191 op_st_sw(t1, t0, ctx);
1192 opn = "sw";
1193 break;
1194 case OPC_SH:
1195 save_cpu_state(ctx, 0);
1196 op_st_sh(t1, t0, ctx);
1197 opn = "sh";
1198 break;
1199 case OPC_SB:
1200 save_cpu_state(ctx, 0);
1201 op_st_sb(t1, t0, ctx);
1202 opn = "sb";
1203 break;
1204 case OPC_SWL:
1205 save_cpu_state(ctx, 1);
1206 gen_helper_2i(swl, t1, t0, ctx->mem_idx);
1207 opn = "swl";
1208 break;
1209 case OPC_SWR:
1210 save_cpu_state(ctx, 1);
1211 gen_helper_2i(swr, t1, t0, ctx->mem_idx);
1212 opn = "swr";
1213 break;
1214 }
2abf314d 1215 (void)opn; /* avoid a compiler warning */
5c13fdfd
AJ
1216 MIPS_DEBUG("%s %s, %d(%s)", opn, regnames[rt], offset, regnames[base]);
1217 tcg_temp_free(t0);
1218 tcg_temp_free(t1);
1219}
1220
1221
d66c7132
AJ
1222/* Store conditional */
1223static void gen_st_cond (DisasContext *ctx, uint32_t opc, int rt,
1224 int base, int16_t offset)
1225{
1226 const char *opn = "st_cond";
1227 TCGv t0, t1;
1228
1229 t0 = tcg_temp_local_new();
1230
662d7485 1231 gen_base_offset_addr(ctx, t0, base, offset);
d66c7132
AJ
1232 /* Don't do NOP if destination is zero: we must perform the actual
1233 memory access. */
1234
1235 t1 = tcg_temp_local_new();
1236 gen_load_gpr(t1, rt);
1237 switch (opc) {
1238#if defined(TARGET_MIPS64)
1239 case OPC_SCD:
b835e919 1240 save_cpu_state(ctx, 1);
5c13fdfd 1241 op_st_scd(t1, t0, rt, ctx);
d66c7132
AJ
1242 opn = "scd";
1243 break;
1244#endif
6af0bf9c 1245 case OPC_SC:
e7139c44 1246 save_cpu_state(ctx, 1);
5c13fdfd 1247 op_st_sc(t1, t0, rt, ctx);
6af0bf9c
FB
1248 opn = "sc";
1249 break;
6af0bf9c 1250 }
2abf314d 1251 (void)opn; /* avoid a compiler warning */
6af0bf9c 1252 MIPS_DEBUG("%s %s, %d(%s)", opn, regnames[rt], offset, regnames[base]);
78723684 1253 tcg_temp_free(t1);
d66c7132 1254 tcg_temp_free(t0);
6af0bf9c
FB
1255}
1256
6ea83fed 1257/* Load and store */
7a387fff 1258static void gen_flt_ldst (DisasContext *ctx, uint32_t opc, int ft,
356265ae 1259 int base, int16_t offset)
6ea83fed 1260{
923617a3 1261 const char *opn = "flt_ldst";
4e2474d6 1262 TCGv t0 = tcg_temp_new();
6ea83fed 1263
662d7485 1264 gen_base_offset_addr(ctx, t0, base, offset);
6ea83fed 1265 /* Don't do NOP if destination is zero: we must perform the actual
ead9360e 1266 memory access. */
6ea83fed
FB
1267 switch (opc) {
1268 case OPC_LWC1:
b6d96bed 1269 {
a7812ae4 1270 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed 1271
c407df81
AJ
1272 tcg_gen_qemu_ld32s(t0, t0, ctx->mem_idx);
1273 tcg_gen_trunc_tl_i32(fp0, t0);
b6d96bed 1274 gen_store_fpr32(fp0, ft);
a7812ae4 1275 tcg_temp_free_i32(fp0);
b6d96bed 1276 }
6ea83fed
FB
1277 opn = "lwc1";
1278 break;
1279 case OPC_SWC1:
b6d96bed 1280 {
a7812ae4
PB
1281 TCGv_i32 fp0 = tcg_temp_new_i32();
1282 TCGv t1 = tcg_temp_new();
b6d96bed
TS
1283
1284 gen_load_fpr32(fp0, ft);
a7812ae4
PB
1285 tcg_gen_extu_i32_tl(t1, fp0);
1286 tcg_gen_qemu_st32(t1, t0, ctx->mem_idx);
1287 tcg_temp_free(t1);
1288 tcg_temp_free_i32(fp0);
b6d96bed 1289 }
6ea83fed
FB
1290 opn = "swc1";
1291 break;
1292 case OPC_LDC1:
b6d96bed 1293 {
a7812ae4 1294 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
1295
1296 tcg_gen_qemu_ld64(fp0, t0, ctx->mem_idx);
1297 gen_store_fpr64(ctx, fp0, ft);
a7812ae4 1298 tcg_temp_free_i64(fp0);
b6d96bed 1299 }
6ea83fed
FB
1300 opn = "ldc1";
1301 break;
1302 case OPC_SDC1:
b6d96bed 1303 {
a7812ae4 1304 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
1305
1306 gen_load_fpr64(ctx, fp0, ft);
1307 tcg_gen_qemu_st64(fp0, t0, ctx->mem_idx);
a7812ae4 1308 tcg_temp_free_i64(fp0);
b6d96bed 1309 }
6ea83fed
FB
1310 opn = "sdc1";
1311 break;
1312 default:
923617a3 1313 MIPS_INVAL(opn);
e397ee33 1314 generate_exception(ctx, EXCP_RI);
78723684 1315 goto out;
6ea83fed 1316 }
2abf314d 1317 (void)opn; /* avoid a compiler warning */
6ea83fed 1318 MIPS_DEBUG("%s %s, %d(%s)", opn, fregnames[ft], offset, regnames[base]);
78723684
TS
1319 out:
1320 tcg_temp_free(t0);
6ea83fed 1321}
6ea83fed 1322
26ebe468
NF
1323static void gen_cop1_ldst(CPUState *env, DisasContext *ctx,
1324 uint32_t op, int rt, int rs, int16_t imm)
1325{
1326 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
1327 check_cp1_enabled(ctx);
1328 gen_flt_ldst(ctx, op, rt, rs, imm);
1329 } else {
1330 generate_exception_err(ctx, EXCP_CpU, 1);
1331 }
1332}
1333
6af0bf9c 1334/* Arithmetic with immediate operand */
e189e748
TS
1335static void gen_arith_imm (CPUState *env, DisasContext *ctx, uint32_t opc,
1336 int rt, int rs, int16_t imm)
6af0bf9c 1337{
324d9e32 1338 target_ulong uimm = (target_long)imm; /* Sign extend to 32/64 bits */
923617a3 1339 const char *opn = "imm arith";
6af0bf9c 1340
7a387fff 1341 if (rt == 0 && opc != OPC_ADDI && opc != OPC_DADDI) {
ead9360e
TS
1342 /* If no destination, treat it as a NOP.
1343 For addi, we must generate the overflow exception when needed. */
6af0bf9c 1344 MIPS_DEBUG("NOP");
324d9e32 1345 return;
6af0bf9c
FB
1346 }
1347 switch (opc) {
1348 case OPC_ADDI:
48d38ca5 1349 {
324d9e32
AJ
1350 TCGv t0 = tcg_temp_local_new();
1351 TCGv t1 = tcg_temp_new();
1352 TCGv t2 = tcg_temp_new();
48d38ca5
TS
1353 int l1 = gen_new_label();
1354
324d9e32
AJ
1355 gen_load_gpr(t1, rs);
1356 tcg_gen_addi_tl(t0, t1, uimm);
1357 tcg_gen_ext32s_tl(t0, t0);
48d38ca5 1358
324d9e32
AJ
1359 tcg_gen_xori_tl(t1, t1, ~uimm);
1360 tcg_gen_xori_tl(t2, t0, uimm);
1361 tcg_gen_and_tl(t1, t1, t2);
1362 tcg_temp_free(t2);
1363 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
1364 tcg_temp_free(t1);
48d38ca5
TS
1365 /* operands of same sign, result different sign */
1366 generate_exception(ctx, EXCP_OVERFLOW);
1367 gen_set_label(l1);
78723684 1368 tcg_gen_ext32s_tl(t0, t0);
324d9e32
AJ
1369 gen_store_gpr(t0, rt);
1370 tcg_temp_free(t0);
48d38ca5 1371 }
6af0bf9c
FB
1372 opn = "addi";
1373 break;
1374 case OPC_ADDIU:
324d9e32
AJ
1375 if (rs != 0) {
1376 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
1377 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
1378 } else {
1379 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
1380 }
6af0bf9c
FB
1381 opn = "addiu";
1382 break;
d26bc211 1383#if defined(TARGET_MIPS64)
7a387fff 1384 case OPC_DADDI:
48d38ca5 1385 {
324d9e32
AJ
1386 TCGv t0 = tcg_temp_local_new();
1387 TCGv t1 = tcg_temp_new();
1388 TCGv t2 = tcg_temp_new();
48d38ca5
TS
1389 int l1 = gen_new_label();
1390
324d9e32
AJ
1391 gen_load_gpr(t1, rs);
1392 tcg_gen_addi_tl(t0, t1, uimm);
48d38ca5 1393
324d9e32
AJ
1394 tcg_gen_xori_tl(t1, t1, ~uimm);
1395 tcg_gen_xori_tl(t2, t0, uimm);
1396 tcg_gen_and_tl(t1, t1, t2);
1397 tcg_temp_free(t2);
1398 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
1399 tcg_temp_free(t1);
48d38ca5
TS
1400 /* operands of same sign, result different sign */
1401 generate_exception(ctx, EXCP_OVERFLOW);
1402 gen_set_label(l1);
324d9e32
AJ
1403 gen_store_gpr(t0, rt);
1404 tcg_temp_free(t0);
48d38ca5 1405 }
7a387fff
TS
1406 opn = "daddi";
1407 break;
1408 case OPC_DADDIU:
324d9e32
AJ
1409 if (rs != 0) {
1410 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
1411 } else {
1412 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
1413 }
7a387fff
TS
1414 opn = "daddiu";
1415 break;
1416#endif
324d9e32 1417 }
2abf314d 1418 (void)opn; /* avoid a compiler warning */
324d9e32
AJ
1419 MIPS_DEBUG("%s %s, %s, " TARGET_FMT_lx, opn, regnames[rt], regnames[rs], uimm);
1420}
1421
1422/* Logic with immediate operand */
1423static void gen_logic_imm (CPUState *env, uint32_t opc, int rt, int rs, int16_t imm)
1424{
1425 target_ulong uimm;
1426 const char *opn = "imm logic";
1427
1428 if (rt == 0) {
1429 /* If no destination, treat it as a NOP. */
1430 MIPS_DEBUG("NOP");
1431 return;
1432 }
1433 uimm = (uint16_t)imm;
1434 switch (opc) {
6af0bf9c 1435 case OPC_ANDI:
324d9e32
AJ
1436 if (likely(rs != 0))
1437 tcg_gen_andi_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
1438 else
1439 tcg_gen_movi_tl(cpu_gpr[rt], 0);
6af0bf9c
FB
1440 opn = "andi";
1441 break;
1442 case OPC_ORI:
324d9e32
AJ
1443 if (rs != 0)
1444 tcg_gen_ori_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
1445 else
1446 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
6af0bf9c
FB
1447 opn = "ori";
1448 break;
1449 case OPC_XORI:
324d9e32
AJ
1450 if (likely(rs != 0))
1451 tcg_gen_xori_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
1452 else
1453 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
6af0bf9c
FB
1454 opn = "xori";
1455 break;
1456 case OPC_LUI:
324d9e32 1457 tcg_gen_movi_tl(cpu_gpr[rt], imm << 16);
6af0bf9c
FB
1458 opn = "lui";
1459 break;
324d9e32 1460 }
2abf314d 1461 (void)opn; /* avoid a compiler warning */
324d9e32
AJ
1462 MIPS_DEBUG("%s %s, %s, " TARGET_FMT_lx, opn, regnames[rt], regnames[rs], uimm);
1463}
1464
1465/* Set on less than with immediate operand */
1466static void gen_slt_imm (CPUState *env, uint32_t opc, int rt, int rs, int16_t imm)
1467{
1468 target_ulong uimm = (target_long)imm; /* Sign extend to 32/64 bits */
1469 const char *opn = "imm arith";
1470 TCGv t0;
1471
1472 if (rt == 0) {
1473 /* If no destination, treat it as a NOP. */
1474 MIPS_DEBUG("NOP");
1475 return;
1476 }
1477 t0 = tcg_temp_new();
1478 gen_load_gpr(t0, rs);
1479 switch (opc) {
1480 case OPC_SLTI:
e68dd28f 1481 tcg_gen_setcondi_tl(TCG_COND_LT, cpu_gpr[rt], t0, uimm);
324d9e32
AJ
1482 opn = "slti";
1483 break;
1484 case OPC_SLTIU:
e68dd28f 1485 tcg_gen_setcondi_tl(TCG_COND_LTU, cpu_gpr[rt], t0, uimm);
324d9e32
AJ
1486 opn = "sltiu";
1487 break;
1488 }
2abf314d 1489 (void)opn; /* avoid a compiler warning */
324d9e32
AJ
1490 MIPS_DEBUG("%s %s, %s, " TARGET_FMT_lx, opn, regnames[rt], regnames[rs], uimm);
1491 tcg_temp_free(t0);
1492}
1493
1494/* Shifts with immediate operand */
1495static void gen_shift_imm(CPUState *env, DisasContext *ctx, uint32_t opc,
1496 int rt, int rs, int16_t imm)
1497{
1498 target_ulong uimm = ((uint16_t)imm) & 0x1f;
1499 const char *opn = "imm shift";
1500 TCGv t0;
1501
1502 if (rt == 0) {
1503 /* If no destination, treat it as a NOP. */
1504 MIPS_DEBUG("NOP");
1505 return;
1506 }
1507
1508 t0 = tcg_temp_new();
1509 gen_load_gpr(t0, rs);
1510 switch (opc) {
6af0bf9c 1511 case OPC_SLL:
78723684 1512 tcg_gen_shli_tl(t0, t0, uimm);
324d9e32 1513 tcg_gen_ext32s_tl(cpu_gpr[rt], t0);
6af0bf9c
FB
1514 opn = "sll";
1515 break;
1516 case OPC_SRA:
324d9e32 1517 tcg_gen_sari_tl(cpu_gpr[rt], t0, uimm);
6af0bf9c
FB
1518 opn = "sra";
1519 break;
1520 case OPC_SRL:
ea63e2c3
NF
1521 if (uimm != 0) {
1522 tcg_gen_ext32u_tl(t0, t0);
1523 tcg_gen_shri_tl(cpu_gpr[rt], t0, uimm);
1524 } else {
1525 tcg_gen_ext32s_tl(cpu_gpr[rt], t0);
5a63bcb2 1526 }
ea63e2c3
NF
1527 opn = "srl";
1528 break;
1529 case OPC_ROTR:
1530 if (uimm != 0) {
1531 TCGv_i32 t1 = tcg_temp_new_i32();
1532
1533 tcg_gen_trunc_tl_i32(t1, t0);
1534 tcg_gen_rotri_i32(t1, t1, uimm);
1535 tcg_gen_ext_i32_tl(cpu_gpr[rt], t1);
1536 tcg_temp_free_i32(t1);
3399e30f
NF
1537 } else {
1538 tcg_gen_ext32s_tl(cpu_gpr[rt], t0);
ea63e2c3
NF
1539 }
1540 opn = "rotr";
7a387fff 1541 break;
d26bc211 1542#if defined(TARGET_MIPS64)
7a387fff 1543 case OPC_DSLL:
324d9e32 1544 tcg_gen_shli_tl(cpu_gpr[rt], t0, uimm);
7a387fff
TS
1545 opn = "dsll";
1546 break;
1547 case OPC_DSRA:
324d9e32 1548 tcg_gen_sari_tl(cpu_gpr[rt], t0, uimm);
7a387fff
TS
1549 opn = "dsra";
1550 break;
1551 case OPC_DSRL:
ea63e2c3
NF
1552 tcg_gen_shri_tl(cpu_gpr[rt], t0, uimm);
1553 opn = "dsrl";
1554 break;
1555 case OPC_DROTR:
1556 if (uimm != 0) {
1557 tcg_gen_rotri_tl(cpu_gpr[rt], t0, uimm);
3399e30f
NF
1558 } else {
1559 tcg_gen_mov_tl(cpu_gpr[rt], t0);
5a63bcb2 1560 }
ea63e2c3 1561 opn = "drotr";
7a387fff
TS
1562 break;
1563 case OPC_DSLL32:
324d9e32 1564 tcg_gen_shli_tl(cpu_gpr[rt], t0, uimm + 32);
7a387fff
TS
1565 opn = "dsll32";
1566 break;
1567 case OPC_DSRA32:
324d9e32 1568 tcg_gen_sari_tl(cpu_gpr[rt], t0, uimm + 32);
7a387fff
TS
1569 opn = "dsra32";
1570 break;
1571 case OPC_DSRL32:
ea63e2c3
NF
1572 tcg_gen_shri_tl(cpu_gpr[rt], t0, uimm + 32);
1573 opn = "dsrl32";
1574 break;
1575 case OPC_DROTR32:
1576 tcg_gen_rotri_tl(cpu_gpr[rt], t0, uimm + 32);
1577 opn = "drotr32";
6af0bf9c 1578 break;
7a387fff 1579#endif
6af0bf9c 1580 }
2abf314d 1581 (void)opn; /* avoid a compiler warning */
93b12ccc 1582 MIPS_DEBUG("%s %s, %s, " TARGET_FMT_lx, opn, regnames[rt], regnames[rs], uimm);
78723684 1583 tcg_temp_free(t0);
6af0bf9c
FB
1584}
1585
1586/* Arithmetic */
e189e748 1587static void gen_arith (CPUState *env, DisasContext *ctx, uint32_t opc,
6af0bf9c
FB
1588 int rd, int rs, int rt)
1589{
923617a3 1590 const char *opn = "arith";
6af0bf9c 1591
7a387fff
TS
1592 if (rd == 0 && opc != OPC_ADD && opc != OPC_SUB
1593 && opc != OPC_DADD && opc != OPC_DSUB) {
ead9360e
TS
1594 /* If no destination, treat it as a NOP.
1595 For add & sub, we must generate the overflow exception when needed. */
6af0bf9c 1596 MIPS_DEBUG("NOP");
460f00c4 1597 return;
185f0762 1598 }
460f00c4 1599
6af0bf9c
FB
1600 switch (opc) {
1601 case OPC_ADD:
48d38ca5 1602 {
460f00c4
AJ
1603 TCGv t0 = tcg_temp_local_new();
1604 TCGv t1 = tcg_temp_new();
1605 TCGv t2 = tcg_temp_new();
48d38ca5
TS
1606 int l1 = gen_new_label();
1607
460f00c4
AJ
1608 gen_load_gpr(t1, rs);
1609 gen_load_gpr(t2, rt);
1610 tcg_gen_add_tl(t0, t1, t2);
1611 tcg_gen_ext32s_tl(t0, t0);
1612 tcg_gen_xor_tl(t1, t1, t2);
460f00c4 1613 tcg_gen_xor_tl(t2, t0, t2);
deb4203d 1614 tcg_gen_andc_tl(t1, t2, t1);
460f00c4
AJ
1615 tcg_temp_free(t2);
1616 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
1617 tcg_temp_free(t1);
48d38ca5
TS
1618 /* operands of same sign, result different sign */
1619 generate_exception(ctx, EXCP_OVERFLOW);
1620 gen_set_label(l1);
460f00c4
AJ
1621 gen_store_gpr(t0, rd);
1622 tcg_temp_free(t0);
48d38ca5 1623 }
6af0bf9c
FB
1624 opn = "add";
1625 break;
1626 case OPC_ADDU:
460f00c4
AJ
1627 if (rs != 0 && rt != 0) {
1628 tcg_gen_add_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
1629 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
1630 } else if (rs == 0 && rt != 0) {
1631 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
1632 } else if (rs != 0 && rt == 0) {
1633 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
1634 } else {
1635 tcg_gen_movi_tl(cpu_gpr[rd], 0);
1636 }
6af0bf9c
FB
1637 opn = "addu";
1638 break;
1639 case OPC_SUB:
48d38ca5 1640 {
460f00c4
AJ
1641 TCGv t0 = tcg_temp_local_new();
1642 TCGv t1 = tcg_temp_new();
1643 TCGv t2 = tcg_temp_new();
48d38ca5
TS
1644 int l1 = gen_new_label();
1645
460f00c4
AJ
1646 gen_load_gpr(t1, rs);
1647 gen_load_gpr(t2, rt);
1648 tcg_gen_sub_tl(t0, t1, t2);
1649 tcg_gen_ext32s_tl(t0, t0);
1650 tcg_gen_xor_tl(t2, t1, t2);
1651 tcg_gen_xor_tl(t1, t0, t1);
1652 tcg_gen_and_tl(t1, t1, t2);
1653 tcg_temp_free(t2);
1654 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
1655 tcg_temp_free(t1);
31e3104f 1656 /* operands of different sign, first operand and result different sign */
48d38ca5
TS
1657 generate_exception(ctx, EXCP_OVERFLOW);
1658 gen_set_label(l1);
460f00c4
AJ
1659 gen_store_gpr(t0, rd);
1660 tcg_temp_free(t0);
48d38ca5 1661 }
6af0bf9c
FB
1662 opn = "sub";
1663 break;
1664 case OPC_SUBU:
460f00c4
AJ
1665 if (rs != 0 && rt != 0) {
1666 tcg_gen_sub_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
1667 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
1668 } else if (rs == 0 && rt != 0) {
1669 tcg_gen_neg_tl(cpu_gpr[rd], cpu_gpr[rt]);
6bb72b18 1670 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
460f00c4
AJ
1671 } else if (rs != 0 && rt == 0) {
1672 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
1673 } else {
1674 tcg_gen_movi_tl(cpu_gpr[rd], 0);
1675 }
6af0bf9c
FB
1676 opn = "subu";
1677 break;
d26bc211 1678#if defined(TARGET_MIPS64)
7a387fff 1679 case OPC_DADD:
48d38ca5 1680 {
460f00c4
AJ
1681 TCGv t0 = tcg_temp_local_new();
1682 TCGv t1 = tcg_temp_new();
1683 TCGv t2 = tcg_temp_new();
48d38ca5
TS
1684 int l1 = gen_new_label();
1685
460f00c4
AJ
1686 gen_load_gpr(t1, rs);
1687 gen_load_gpr(t2, rt);
1688 tcg_gen_add_tl(t0, t1, t2);
1689 tcg_gen_xor_tl(t1, t1, t2);
460f00c4 1690 tcg_gen_xor_tl(t2, t0, t2);
deb4203d 1691 tcg_gen_andc_tl(t1, t2, t1);
460f00c4
AJ
1692 tcg_temp_free(t2);
1693 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
1694 tcg_temp_free(t1);
48d38ca5
TS
1695 /* operands of same sign, result different sign */
1696 generate_exception(ctx, EXCP_OVERFLOW);
1697 gen_set_label(l1);
460f00c4
AJ
1698 gen_store_gpr(t0, rd);
1699 tcg_temp_free(t0);
48d38ca5 1700 }
7a387fff
TS
1701 opn = "dadd";
1702 break;
1703 case OPC_DADDU:
460f00c4
AJ
1704 if (rs != 0 && rt != 0) {
1705 tcg_gen_add_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
1706 } else if (rs == 0 && rt != 0) {
1707 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
1708 } else if (rs != 0 && rt == 0) {
1709 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
1710 } else {
1711 tcg_gen_movi_tl(cpu_gpr[rd], 0);
1712 }
7a387fff
TS
1713 opn = "daddu";
1714 break;
1715 case OPC_DSUB:
48d38ca5 1716 {
460f00c4
AJ
1717 TCGv t0 = tcg_temp_local_new();
1718 TCGv t1 = tcg_temp_new();
1719 TCGv t2 = tcg_temp_new();
48d38ca5
TS
1720 int l1 = gen_new_label();
1721
460f00c4
AJ
1722 gen_load_gpr(t1, rs);
1723 gen_load_gpr(t2, rt);
1724 tcg_gen_sub_tl(t0, t1, t2);
1725 tcg_gen_xor_tl(t2, t1, t2);
1726 tcg_gen_xor_tl(t1, t0, t1);
1727 tcg_gen_and_tl(t1, t1, t2);
1728 tcg_temp_free(t2);
1729 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
1730 tcg_temp_free(t1);
31e3104f 1731 /* operands of different sign, first operand and result different sign */
48d38ca5
TS
1732 generate_exception(ctx, EXCP_OVERFLOW);
1733 gen_set_label(l1);
460f00c4
AJ
1734 gen_store_gpr(t0, rd);
1735 tcg_temp_free(t0);
48d38ca5 1736 }
7a387fff
TS
1737 opn = "dsub";
1738 break;
1739 case OPC_DSUBU:
460f00c4
AJ
1740 if (rs != 0 && rt != 0) {
1741 tcg_gen_sub_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
1742 } else if (rs == 0 && rt != 0) {
1743 tcg_gen_neg_tl(cpu_gpr[rd], cpu_gpr[rt]);
1744 } else if (rs != 0 && rt == 0) {
1745 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
1746 } else {
1747 tcg_gen_movi_tl(cpu_gpr[rd], 0);
1748 }
7a387fff
TS
1749 opn = "dsubu";
1750 break;
1751#endif
460f00c4
AJ
1752 case OPC_MUL:
1753 if (likely(rs != 0 && rt != 0)) {
1754 tcg_gen_mul_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
1755 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
1756 } else {
1757 tcg_gen_movi_tl(cpu_gpr[rd], 0);
1758 }
1759 opn = "mul";
6af0bf9c 1760 break;
460f00c4 1761 }
2abf314d 1762 (void)opn; /* avoid a compiler warning */
460f00c4
AJ
1763 MIPS_DEBUG("%s %s, %s, %s", opn, regnames[rd], regnames[rs], regnames[rt]);
1764}
1765
1766/* Conditional move */
1767static void gen_cond_move (CPUState *env, uint32_t opc, int rd, int rs, int rt)
1768{
1769 const char *opn = "cond move";
1770 int l1;
1771
1772 if (rd == 0) {
1773 /* If no destination, treat it as a NOP.
1774 For add & sub, we must generate the overflow exception when needed. */
1775 MIPS_DEBUG("NOP");
1776 return;
1777 }
1778
1779 l1 = gen_new_label();
1780 switch (opc) {
1781 case OPC_MOVN:
1782 if (likely(rt != 0))
1783 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[rt], 0, l1);
1784 else
1785 tcg_gen_br(l1);
1786 opn = "movn";
6af0bf9c 1787 break;
460f00c4
AJ
1788 case OPC_MOVZ:
1789 if (likely(rt != 0))
1790 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[rt], 0, l1);
1791 opn = "movz";
1792 break;
1793 }
1794 if (rs != 0)
1795 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
1796 else
1797 tcg_gen_movi_tl(cpu_gpr[rd], 0);
1798 gen_set_label(l1);
1799
2abf314d 1800 (void)opn; /* avoid a compiler warning */
460f00c4
AJ
1801 MIPS_DEBUG("%s %s, %s, %s", opn, regnames[rd], regnames[rs], regnames[rt]);
1802}
1803
1804/* Logic */
1805static void gen_logic (CPUState *env, uint32_t opc, int rd, int rs, int rt)
1806{
1807 const char *opn = "logic";
1808
1809 if (rd == 0) {
1810 /* If no destination, treat it as a NOP. */
1811 MIPS_DEBUG("NOP");
1812 return;
1813 }
1814
1815 switch (opc) {
6af0bf9c 1816 case OPC_AND:
460f00c4
AJ
1817 if (likely(rs != 0 && rt != 0)) {
1818 tcg_gen_and_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
1819 } else {
1820 tcg_gen_movi_tl(cpu_gpr[rd], 0);
1821 }
6af0bf9c
FB
1822 opn = "and";
1823 break;
1824 case OPC_NOR:
460f00c4
AJ
1825 if (rs != 0 && rt != 0) {
1826 tcg_gen_nor_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
1827 } else if (rs == 0 && rt != 0) {
1828 tcg_gen_not_tl(cpu_gpr[rd], cpu_gpr[rt]);
1829 } else if (rs != 0 && rt == 0) {
1830 tcg_gen_not_tl(cpu_gpr[rd], cpu_gpr[rs]);
1831 } else {
1832 tcg_gen_movi_tl(cpu_gpr[rd], ~((target_ulong)0));
1833 }
6af0bf9c
FB
1834 opn = "nor";
1835 break;
1836 case OPC_OR:
460f00c4
AJ
1837 if (likely(rs != 0 && rt != 0)) {
1838 tcg_gen_or_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
1839 } else if (rs == 0 && rt != 0) {
1840 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
1841 } else if (rs != 0 && rt == 0) {
1842 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
1843 } else {
1844 tcg_gen_movi_tl(cpu_gpr[rd], 0);
1845 }
6af0bf9c
FB
1846 opn = "or";
1847 break;
1848 case OPC_XOR:
460f00c4
AJ
1849 if (likely(rs != 0 && rt != 0)) {
1850 tcg_gen_xor_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
1851 } else if (rs == 0 && rt != 0) {
1852 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
1853 } else if (rs != 0 && rt == 0) {
1854 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
1855 } else {
1856 tcg_gen_movi_tl(cpu_gpr[rd], 0);
1857 }
6af0bf9c
FB
1858 opn = "xor";
1859 break;
460f00c4 1860 }
2abf314d 1861 (void)opn; /* avoid a compiler warning */
460f00c4
AJ
1862 MIPS_DEBUG("%s %s, %s, %s", opn, regnames[rd], regnames[rs], regnames[rt]);
1863}
1864
1865/* Set on lower than */
1866static void gen_slt (CPUState *env, uint32_t opc, int rd, int rs, int rt)
1867{
1868 const char *opn = "slt";
1869 TCGv t0, t1;
1870
1871 if (rd == 0) {
1872 /* If no destination, treat it as a NOP. */
1873 MIPS_DEBUG("NOP");
1874 return;
1875 }
1876
1877 t0 = tcg_temp_new();
1878 t1 = tcg_temp_new();
1879 gen_load_gpr(t0, rs);
1880 gen_load_gpr(t1, rt);
1881 switch (opc) {
1882 case OPC_SLT:
e68dd28f 1883 tcg_gen_setcond_tl(TCG_COND_LT, cpu_gpr[rd], t0, t1);
460f00c4 1884 opn = "slt";
6af0bf9c 1885 break;
460f00c4 1886 case OPC_SLTU:
e68dd28f 1887 tcg_gen_setcond_tl(TCG_COND_LTU, cpu_gpr[rd], t0, t1);
460f00c4
AJ
1888 opn = "sltu";
1889 break;
1890 }
2abf314d 1891 (void)opn; /* avoid a compiler warning */
460f00c4
AJ
1892 MIPS_DEBUG("%s %s, %s, %s", opn, regnames[rd], regnames[rs], regnames[rt]);
1893 tcg_temp_free(t0);
1894 tcg_temp_free(t1);
1895}
20c4c97c 1896
460f00c4
AJ
1897/* Shifts */
1898static void gen_shift (CPUState *env, DisasContext *ctx, uint32_t opc,
1899 int rd, int rs, int rt)
1900{
1901 const char *opn = "shifts";
1902 TCGv t0, t1;
20c4c97c 1903
460f00c4
AJ
1904 if (rd == 0) {
1905 /* If no destination, treat it as a NOP.
1906 For add & sub, we must generate the overflow exception when needed. */
1907 MIPS_DEBUG("NOP");
1908 return;
1909 }
1910
1911 t0 = tcg_temp_new();
1912 t1 = tcg_temp_new();
1913 gen_load_gpr(t0, rs);
1914 gen_load_gpr(t1, rt);
1915 switch (opc) {
6af0bf9c 1916 case OPC_SLLV:
78723684
TS
1917 tcg_gen_andi_tl(t0, t0, 0x1f);
1918 tcg_gen_shl_tl(t0, t1, t0);
460f00c4 1919 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
6af0bf9c
FB
1920 opn = "sllv";
1921 break;
1922 case OPC_SRAV:
78723684 1923 tcg_gen_andi_tl(t0, t0, 0x1f);
460f00c4 1924 tcg_gen_sar_tl(cpu_gpr[rd], t1, t0);
6af0bf9c
FB
1925 opn = "srav";
1926 break;
1927 case OPC_SRLV:
ea63e2c3
NF
1928 tcg_gen_ext32u_tl(t1, t1);
1929 tcg_gen_andi_tl(t0, t0, 0x1f);
1930 tcg_gen_shr_tl(t0, t1, t0);
1931 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
1932 opn = "srlv";
1933 break;
1934 case OPC_ROTRV:
1935 {
1936 TCGv_i32 t2 = tcg_temp_new_i32();
1937 TCGv_i32 t3 = tcg_temp_new_i32();
1938
1939 tcg_gen_trunc_tl_i32(t2, t0);
1940 tcg_gen_trunc_tl_i32(t3, t1);
1941 tcg_gen_andi_i32(t2, t2, 0x1f);
1942 tcg_gen_rotr_i32(t2, t3, t2);
1943 tcg_gen_ext_i32_tl(cpu_gpr[rd], t2);
1944 tcg_temp_free_i32(t2);
1945 tcg_temp_free_i32(t3);
1946 opn = "rotrv";
5a63bcb2 1947 }
7a387fff 1948 break;
d26bc211 1949#if defined(TARGET_MIPS64)
7a387fff 1950 case OPC_DSLLV:
78723684 1951 tcg_gen_andi_tl(t0, t0, 0x3f);
460f00c4 1952 tcg_gen_shl_tl(cpu_gpr[rd], t1, t0);
7a387fff
TS
1953 opn = "dsllv";
1954 break;
1955 case OPC_DSRAV:
78723684 1956 tcg_gen_andi_tl(t0, t0, 0x3f);
460f00c4 1957 tcg_gen_sar_tl(cpu_gpr[rd], t1, t0);
7a387fff
TS
1958 opn = "dsrav";
1959 break;
1960 case OPC_DSRLV:
ea63e2c3
NF
1961 tcg_gen_andi_tl(t0, t0, 0x3f);
1962 tcg_gen_shr_tl(cpu_gpr[rd], t1, t0);
1963 opn = "dsrlv";
1964 break;
1965 case OPC_DROTRV:
1966 tcg_gen_andi_tl(t0, t0, 0x3f);
1967 tcg_gen_rotr_tl(cpu_gpr[rd], t1, t0);
1968 opn = "drotrv";
6af0bf9c 1969 break;
7a387fff 1970#endif
6af0bf9c 1971 }
2abf314d 1972 (void)opn; /* avoid a compiler warning */
6af0bf9c 1973 MIPS_DEBUG("%s %s, %s, %s", opn, regnames[rd], regnames[rs], regnames[rt]);
78723684
TS
1974 tcg_temp_free(t0);
1975 tcg_temp_free(t1);
6af0bf9c
FB
1976}
1977
1978/* Arithmetic on HI/LO registers */
7a387fff 1979static void gen_HILO (DisasContext *ctx, uint32_t opc, int reg)
6af0bf9c 1980{
923617a3 1981 const char *opn = "hilo";
6af0bf9c
FB
1982
1983 if (reg == 0 && (opc == OPC_MFHI || opc == OPC_MFLO)) {
ead9360e 1984 /* Treat as NOP. */
6af0bf9c 1985 MIPS_DEBUG("NOP");
a1f6684d 1986 return;
6af0bf9c
FB
1987 }
1988 switch (opc) {
1989 case OPC_MFHI:
a1f6684d 1990 tcg_gen_mov_tl(cpu_gpr[reg], cpu_HI[0]);
6af0bf9c
FB
1991 opn = "mfhi";
1992 break;
1993 case OPC_MFLO:
a1f6684d 1994 tcg_gen_mov_tl(cpu_gpr[reg], cpu_LO[0]);
6af0bf9c
FB
1995 opn = "mflo";
1996 break;
1997 case OPC_MTHI:
a1f6684d
AJ
1998 if (reg != 0)
1999 tcg_gen_mov_tl(cpu_HI[0], cpu_gpr[reg]);
2000 else
2001 tcg_gen_movi_tl(cpu_HI[0], 0);
6af0bf9c
FB
2002 opn = "mthi";
2003 break;
2004 case OPC_MTLO:
a1f6684d
AJ
2005 if (reg != 0)
2006 tcg_gen_mov_tl(cpu_LO[0], cpu_gpr[reg]);
2007 else
2008 tcg_gen_movi_tl(cpu_LO[0], 0);
6af0bf9c
FB
2009 opn = "mtlo";
2010 break;
6af0bf9c 2011 }
2abf314d 2012 (void)opn; /* avoid a compiler warning */
6af0bf9c
FB
2013 MIPS_DEBUG("%s %s", opn, regnames[reg]);
2014}
2015
7a387fff 2016static void gen_muldiv (DisasContext *ctx, uint32_t opc,
6af0bf9c
FB
2017 int rs, int rt)
2018{
923617a3 2019 const char *opn = "mul/div";
d45f89f4
AJ
2020 TCGv t0, t1;
2021
2022 switch (opc) {
2023 case OPC_DIV:
2024 case OPC_DIVU:
2025#if defined(TARGET_MIPS64)
2026 case OPC_DDIV:
2027 case OPC_DDIVU:
2028#endif
2029 t0 = tcg_temp_local_new();
2030 t1 = tcg_temp_local_new();
2031 break;
2032 default:
2033 t0 = tcg_temp_new();
2034 t1 = tcg_temp_new();
2035 break;
2036 }
6af0bf9c 2037
78723684
TS
2038 gen_load_gpr(t0, rs);
2039 gen_load_gpr(t1, rt);
6af0bf9c
FB
2040 switch (opc) {
2041 case OPC_DIV:
48d38ca5
TS
2042 {
2043 int l1 = gen_new_label();
d45f89f4 2044 int l2 = gen_new_label();
48d38ca5 2045
d45f89f4
AJ
2046 tcg_gen_ext32s_tl(t0, t0);
2047 tcg_gen_ext32s_tl(t1, t1);
78723684 2048 tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
d45f89f4
AJ
2049 tcg_gen_brcondi_tl(TCG_COND_NE, t0, INT_MIN, l2);
2050 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1, l2);
2051
2052 tcg_gen_mov_tl(cpu_LO[0], t0);
2053 tcg_gen_movi_tl(cpu_HI[0], 0);
2054 tcg_gen_br(l1);
2055 gen_set_label(l2);
2056 tcg_gen_div_tl(cpu_LO[0], t0, t1);
2057 tcg_gen_rem_tl(cpu_HI[0], t0, t1);
2058 tcg_gen_ext32s_tl(cpu_LO[0], cpu_LO[0]);
2059 tcg_gen_ext32s_tl(cpu_HI[0], cpu_HI[0]);
48d38ca5
TS
2060 gen_set_label(l1);
2061 }
6af0bf9c
FB
2062 opn = "div";
2063 break;
2064 case OPC_DIVU:
48d38ca5
TS
2065 {
2066 int l1 = gen_new_label();
2067
0c0ed03b
AJ
2068 tcg_gen_ext32u_tl(t0, t0);
2069 tcg_gen_ext32u_tl(t1, t1);
78723684 2070 tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
d45f89f4
AJ
2071 tcg_gen_divu_tl(cpu_LO[0], t0, t1);
2072 tcg_gen_remu_tl(cpu_HI[0], t0, t1);
2073 tcg_gen_ext32s_tl(cpu_LO[0], cpu_LO[0]);
2074 tcg_gen_ext32s_tl(cpu_HI[0], cpu_HI[0]);
48d38ca5
TS
2075 gen_set_label(l1);
2076 }
6af0bf9c
FB
2077 opn = "divu";
2078 break;
2079 case OPC_MULT:
214c465f 2080 {
d45f89f4
AJ
2081 TCGv_i64 t2 = tcg_temp_new_i64();
2082 TCGv_i64 t3 = tcg_temp_new_i64();
2083
2084 tcg_gen_ext_tl_i64(t2, t0);
2085 tcg_gen_ext_tl_i64(t3, t1);
2086 tcg_gen_mul_i64(t2, t2, t3);
2087 tcg_temp_free_i64(t3);
2088 tcg_gen_trunc_i64_tl(t0, t2);
2089 tcg_gen_shri_i64(t2, t2, 32);
2090 tcg_gen_trunc_i64_tl(t1, t2);
2091 tcg_temp_free_i64(t2);
b10fa3c9
AJ
2092 tcg_gen_ext32s_tl(cpu_LO[0], t0);
2093 tcg_gen_ext32s_tl(cpu_HI[0], t1);
214c465f 2094 }
6af0bf9c
FB
2095 opn = "mult";
2096 break;
2097 case OPC_MULTU:
214c465f 2098 {
d45f89f4
AJ
2099 TCGv_i64 t2 = tcg_temp_new_i64();
2100 TCGv_i64 t3 = tcg_temp_new_i64();
214c465f 2101
78723684
TS
2102 tcg_gen_ext32u_tl(t0, t0);
2103 tcg_gen_ext32u_tl(t1, t1);
d45f89f4
AJ
2104 tcg_gen_extu_tl_i64(t2, t0);
2105 tcg_gen_extu_tl_i64(t3, t1);
2106 tcg_gen_mul_i64(t2, t2, t3);
2107 tcg_temp_free_i64(t3);
2108 tcg_gen_trunc_i64_tl(t0, t2);
2109 tcg_gen_shri_i64(t2, t2, 32);
2110 tcg_gen_trunc_i64_tl(t1, t2);
2111 tcg_temp_free_i64(t2);
b10fa3c9
AJ
2112 tcg_gen_ext32s_tl(cpu_LO[0], t0);
2113 tcg_gen_ext32s_tl(cpu_HI[0], t1);
214c465f 2114 }
6af0bf9c
FB
2115 opn = "multu";
2116 break;
d26bc211 2117#if defined(TARGET_MIPS64)
7a387fff 2118 case OPC_DDIV:
48d38ca5
TS
2119 {
2120 int l1 = gen_new_label();
d45f89f4 2121 int l2 = gen_new_label();
48d38ca5 2122
78723684 2123 tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
d45f89f4
AJ
2124 tcg_gen_brcondi_tl(TCG_COND_NE, t0, -1LL << 63, l2);
2125 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1LL, l2);
2126 tcg_gen_mov_tl(cpu_LO[0], t0);
2127 tcg_gen_movi_tl(cpu_HI[0], 0);
2128 tcg_gen_br(l1);
2129 gen_set_label(l2);
2130 tcg_gen_div_i64(cpu_LO[0], t0, t1);
2131 tcg_gen_rem_i64(cpu_HI[0], t0, t1);
48d38ca5
TS
2132 gen_set_label(l1);
2133 }
7a387fff
TS
2134 opn = "ddiv";
2135 break;
2136 case OPC_DDIVU:
48d38ca5
TS
2137 {
2138 int l1 = gen_new_label();
2139
78723684 2140 tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
b10fa3c9
AJ
2141 tcg_gen_divu_i64(cpu_LO[0], t0, t1);
2142 tcg_gen_remu_i64(cpu_HI[0], t0, t1);
48d38ca5
TS
2143 gen_set_label(l1);
2144 }
7a387fff
TS
2145 opn = "ddivu";
2146 break;
2147 case OPC_DMULT:
a7812ae4 2148 gen_helper_dmult(t0, t1);
7a387fff
TS
2149 opn = "dmult";
2150 break;
2151 case OPC_DMULTU:
a7812ae4 2152 gen_helper_dmultu(t0, t1);
7a387fff
TS
2153 opn = "dmultu";
2154 break;
2155#endif
6af0bf9c 2156 case OPC_MADD:
214c465f 2157 {
d45f89f4
AJ
2158 TCGv_i64 t2 = tcg_temp_new_i64();
2159 TCGv_i64 t3 = tcg_temp_new_i64();
2160
2161 tcg_gen_ext_tl_i64(t2, t0);
2162 tcg_gen_ext_tl_i64(t3, t1);
2163 tcg_gen_mul_i64(t2, t2, t3);
2164 tcg_gen_concat_tl_i64(t3, cpu_LO[0], cpu_HI[0]);
2165 tcg_gen_add_i64(t2, t2, t3);
2166 tcg_temp_free_i64(t3);
2167 tcg_gen_trunc_i64_tl(t0, t2);
2168 tcg_gen_shri_i64(t2, t2, 32);
2169 tcg_gen_trunc_i64_tl(t1, t2);
2170 tcg_temp_free_i64(t2);
b10fa3c9 2171 tcg_gen_ext32s_tl(cpu_LO[0], t0);
98070ce0 2172 tcg_gen_ext32s_tl(cpu_HI[0], t1);
214c465f 2173 }
6af0bf9c
FB
2174 opn = "madd";
2175 break;
2176 case OPC_MADDU:
214c465f 2177 {
d45f89f4
AJ
2178 TCGv_i64 t2 = tcg_temp_new_i64();
2179 TCGv_i64 t3 = tcg_temp_new_i64();
214c465f 2180
78723684
TS
2181 tcg_gen_ext32u_tl(t0, t0);
2182 tcg_gen_ext32u_tl(t1, t1);
d45f89f4
AJ
2183 tcg_gen_extu_tl_i64(t2, t0);
2184 tcg_gen_extu_tl_i64(t3, t1);
2185 tcg_gen_mul_i64(t2, t2, t3);
2186 tcg_gen_concat_tl_i64(t3, cpu_LO[0], cpu_HI[0]);
2187 tcg_gen_add_i64(t2, t2, t3);
2188 tcg_temp_free_i64(t3);
2189 tcg_gen_trunc_i64_tl(t0, t2);
2190 tcg_gen_shri_i64(t2, t2, 32);
2191 tcg_gen_trunc_i64_tl(t1, t2);
2192 tcg_temp_free_i64(t2);
b10fa3c9
AJ
2193 tcg_gen_ext32s_tl(cpu_LO[0], t0);
2194 tcg_gen_ext32s_tl(cpu_HI[0], t1);
214c465f 2195 }
6af0bf9c
FB
2196 opn = "maddu";
2197 break;
2198 case OPC_MSUB:
214c465f 2199 {
d45f89f4
AJ
2200 TCGv_i64 t2 = tcg_temp_new_i64();
2201 TCGv_i64 t3 = tcg_temp_new_i64();
2202
2203 tcg_gen_ext_tl_i64(t2, t0);
2204 tcg_gen_ext_tl_i64(t3, t1);
2205 tcg_gen_mul_i64(t2, t2, t3);
2206 tcg_gen_concat_tl_i64(t3, cpu_LO[0], cpu_HI[0]);
98070ce0 2207 tcg_gen_sub_i64(t2, t3, t2);
d45f89f4
AJ
2208 tcg_temp_free_i64(t3);
2209 tcg_gen_trunc_i64_tl(t0, t2);
2210 tcg_gen_shri_i64(t2, t2, 32);
2211 tcg_gen_trunc_i64_tl(t1, t2);
2212 tcg_temp_free_i64(t2);
b10fa3c9
AJ
2213 tcg_gen_ext32s_tl(cpu_LO[0], t0);
2214 tcg_gen_ext32s_tl(cpu_HI[0], t1);
214c465f 2215 }
6af0bf9c
FB
2216 opn = "msub";
2217 break;
2218 case OPC_MSUBU:
214c465f 2219 {
d45f89f4
AJ
2220 TCGv_i64 t2 = tcg_temp_new_i64();
2221 TCGv_i64 t3 = tcg_temp_new_i64();
214c465f 2222
78723684
TS
2223 tcg_gen_ext32u_tl(t0, t0);
2224 tcg_gen_ext32u_tl(t1, t1);
d45f89f4
AJ
2225 tcg_gen_extu_tl_i64(t2, t0);
2226 tcg_gen_extu_tl_i64(t3, t1);
2227 tcg_gen_mul_i64(t2, t2, t3);
2228 tcg_gen_concat_tl_i64(t3, cpu_LO[0], cpu_HI[0]);
98070ce0 2229 tcg_gen_sub_i64(t2, t3, t2);
d45f89f4
AJ
2230 tcg_temp_free_i64(t3);
2231 tcg_gen_trunc_i64_tl(t0, t2);
2232 tcg_gen_shri_i64(t2, t2, 32);
2233 tcg_gen_trunc_i64_tl(t1, t2);
2234 tcg_temp_free_i64(t2);
b10fa3c9
AJ
2235 tcg_gen_ext32s_tl(cpu_LO[0], t0);
2236 tcg_gen_ext32s_tl(cpu_HI[0], t1);
214c465f 2237 }
6af0bf9c
FB
2238 opn = "msubu";
2239 break;
2240 default:
923617a3 2241 MIPS_INVAL(opn);
6af0bf9c 2242 generate_exception(ctx, EXCP_RI);
78723684 2243 goto out;
6af0bf9c 2244 }
2abf314d 2245 (void)opn; /* avoid a compiler warning */
6af0bf9c 2246 MIPS_DEBUG("%s %s %s", opn, regnames[rs], regnames[rt]);
78723684
TS
2247 out:
2248 tcg_temp_free(t0);
2249 tcg_temp_free(t1);
6af0bf9c
FB
2250}
2251
e9c71dd1
TS
2252static void gen_mul_vr54xx (DisasContext *ctx, uint32_t opc,
2253 int rd, int rs, int rt)
2254{
2255 const char *opn = "mul vr54xx";
f157bfe1
AJ
2256 TCGv t0 = tcg_temp_new();
2257 TCGv t1 = tcg_temp_new();
e9c71dd1 2258
6c5c1e20
TS
2259 gen_load_gpr(t0, rs);
2260 gen_load_gpr(t1, rt);
e9c71dd1
TS
2261
2262 switch (opc) {
2263 case OPC_VR54XX_MULS:
a7812ae4 2264 gen_helper_muls(t0, t0, t1);
e9c71dd1 2265 opn = "muls";
6958549d 2266 break;
e9c71dd1 2267 case OPC_VR54XX_MULSU:
a7812ae4 2268 gen_helper_mulsu(t0, t0, t1);
e9c71dd1 2269 opn = "mulsu";
6958549d 2270 break;
e9c71dd1 2271 case OPC_VR54XX_MACC:
a7812ae4 2272 gen_helper_macc(t0, t0, t1);
e9c71dd1 2273 opn = "macc";
6958549d 2274 break;
e9c71dd1 2275 case OPC_VR54XX_MACCU:
a7812ae4 2276 gen_helper_maccu(t0, t0, t1);
e9c71dd1 2277 opn = "maccu";
6958549d 2278 break;
e9c71dd1 2279 case OPC_VR54XX_MSAC:
a7812ae4 2280 gen_helper_msac(t0, t0, t1);
e9c71dd1 2281 opn = "msac";
6958549d 2282 break;
e9c71dd1 2283 case OPC_VR54XX_MSACU:
a7812ae4 2284 gen_helper_msacu(t0, t0, t1);
e9c71dd1 2285 opn = "msacu";
6958549d 2286 break;
e9c71dd1 2287 case OPC_VR54XX_MULHI:
a7812ae4 2288 gen_helper_mulhi(t0, t0, t1);
e9c71dd1 2289 opn = "mulhi";
6958549d 2290 break;
e9c71dd1 2291 case OPC_VR54XX_MULHIU:
a7812ae4 2292 gen_helper_mulhiu(t0, t0, t1);
e9c71dd1 2293 opn = "mulhiu";
6958549d 2294 break;
e9c71dd1 2295 case OPC_VR54XX_MULSHI:
a7812ae4 2296 gen_helper_mulshi(t0, t0, t1);
e9c71dd1 2297 opn = "mulshi";
6958549d 2298 break;
e9c71dd1 2299 case OPC_VR54XX_MULSHIU:
a7812ae4 2300 gen_helper_mulshiu(t0, t0, t1);
e9c71dd1 2301 opn = "mulshiu";
6958549d 2302 break;
e9c71dd1 2303 case OPC_VR54XX_MACCHI:
a7812ae4 2304 gen_helper_macchi(t0, t0, t1);
e9c71dd1 2305 opn = "macchi";
6958549d 2306 break;
e9c71dd1 2307 case OPC_VR54XX_MACCHIU:
a7812ae4 2308 gen_helper_macchiu(t0, t0, t1);
e9c71dd1 2309 opn = "macchiu";
6958549d 2310 break;
e9c71dd1 2311 case OPC_VR54XX_MSACHI:
a7812ae4 2312 gen_helper_msachi(t0, t0, t1);
e9c71dd1 2313 opn = "msachi";
6958549d 2314 break;
e9c71dd1 2315 case OPC_VR54XX_MSACHIU:
a7812ae4 2316 gen_helper_msachiu(t0, t0, t1);
e9c71dd1 2317 opn = "msachiu";
6958549d 2318 break;
e9c71dd1
TS
2319 default:
2320 MIPS_INVAL("mul vr54xx");
2321 generate_exception(ctx, EXCP_RI);
6c5c1e20 2322 goto out;
e9c71dd1 2323 }
6c5c1e20 2324 gen_store_gpr(t0, rd);
2abf314d 2325 (void)opn; /* avoid a compiler warning */
e9c71dd1 2326 MIPS_DEBUG("%s %s, %s, %s", opn, regnames[rd], regnames[rs], regnames[rt]);
6c5c1e20
TS
2327
2328 out:
2329 tcg_temp_free(t0);
2330 tcg_temp_free(t1);
e9c71dd1
TS
2331}
2332
7a387fff 2333static void gen_cl (DisasContext *ctx, uint32_t opc,
6af0bf9c
FB
2334 int rd, int rs)
2335{
923617a3 2336 const char *opn = "CLx";
20e1fb52 2337 TCGv t0;
6c5c1e20 2338
6af0bf9c 2339 if (rd == 0) {
ead9360e 2340 /* Treat as NOP. */
6af0bf9c 2341 MIPS_DEBUG("NOP");
20e1fb52 2342 return;
6af0bf9c 2343 }
20e1fb52 2344 t0 = tcg_temp_new();
6c5c1e20 2345 gen_load_gpr(t0, rs);
6af0bf9c
FB
2346 switch (opc) {
2347 case OPC_CLO:
20e1fb52 2348 gen_helper_clo(cpu_gpr[rd], t0);
6af0bf9c
FB
2349 opn = "clo";
2350 break;
2351 case OPC_CLZ:
20e1fb52 2352 gen_helper_clz(cpu_gpr[rd], t0);
6af0bf9c
FB
2353 opn = "clz";
2354 break;
d26bc211 2355#if defined(TARGET_MIPS64)
7a387fff 2356 case OPC_DCLO:
20e1fb52 2357 gen_helper_dclo(cpu_gpr[rd], t0);
7a387fff
TS
2358 opn = "dclo";
2359 break;
2360 case OPC_DCLZ:
20e1fb52 2361 gen_helper_dclz(cpu_gpr[rd], t0);
7a387fff
TS
2362 opn = "dclz";
2363 break;
2364#endif
6af0bf9c 2365 }
2abf314d 2366 (void)opn; /* avoid a compiler warning */
6af0bf9c 2367 MIPS_DEBUG("%s %s, %s", opn, regnames[rd], regnames[rs]);
6c5c1e20 2368 tcg_temp_free(t0);
6af0bf9c
FB
2369}
2370
161f85e6
AJ
2371/* Godson integer instructions */
2372static void gen_loongson_integer (DisasContext *ctx, uint32_t opc,
2373 int rd, int rs, int rt)
2374{
2375 const char *opn = "loongson";
2376 TCGv t0, t1;
2377
2378 if (rd == 0) {
2379 /* Treat as NOP. */
2380 MIPS_DEBUG("NOP");
2381 return;
2382 }
2383
2384 switch (opc) {
2385 case OPC_MULT_G_2E:
2386 case OPC_MULT_G_2F:
2387 case OPC_MULTU_G_2E:
2388 case OPC_MULTU_G_2F:
2389#if defined(TARGET_MIPS64)
2390 case OPC_DMULT_G_2E:
2391 case OPC_DMULT_G_2F:
2392 case OPC_DMULTU_G_2E:
2393 case OPC_DMULTU_G_2F:
2394#endif
2395 t0 = tcg_temp_new();
2396 t1 = tcg_temp_new();
2397 break;
2398 default:
2399 t0 = tcg_temp_local_new();
2400 t1 = tcg_temp_local_new();
2401 break;
2402 }
2403
2404 gen_load_gpr(t0, rs);
2405 gen_load_gpr(t1, rt);
2406
2407 switch (opc) {
2408 case OPC_MULT_G_2E:
2409 case OPC_MULT_G_2F:
2410 tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
2411 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
2412 opn = "mult.g";
2413 break;
2414 case OPC_MULTU_G_2E:
2415 case OPC_MULTU_G_2F:
2416 tcg_gen_ext32u_tl(t0, t0);
2417 tcg_gen_ext32u_tl(t1, t1);
2418 tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
2419 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
2420 opn = "multu.g";
2421 break;
2422 case OPC_DIV_G_2E:
2423 case OPC_DIV_G_2F:
2424 {
2425 int l1 = gen_new_label();
2426 int l2 = gen_new_label();
2427 int l3 = gen_new_label();
2428 tcg_gen_ext32s_tl(t0, t0);
2429 tcg_gen_ext32s_tl(t1, t1);
2430 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
2431 tcg_gen_movi_tl(cpu_gpr[rd], 0);
2432 tcg_gen_br(l3);
2433 gen_set_label(l1);
2434 tcg_gen_brcondi_tl(TCG_COND_NE, t0, INT_MIN, l2);
2435 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1, l2);
2436 tcg_gen_mov_tl(cpu_gpr[rd], t0);
2437 tcg_gen_br(l3);
2438 gen_set_label(l2);
2439 tcg_gen_div_tl(cpu_gpr[rd], t0, t1);
2440 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
2441 gen_set_label(l3);
2442 }
2443 opn = "div.g";
2444 break;
2445 case OPC_DIVU_G_2E:
2446 case OPC_DIVU_G_2F:
2447 {
2448 int l1 = gen_new_label();
2449 int l2 = gen_new_label();
2450 tcg_gen_ext32u_tl(t0, t0);
2451 tcg_gen_ext32u_tl(t1, t1);
2452 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
2453 tcg_gen_movi_tl(cpu_gpr[rd], 0);
2454 tcg_gen_br(l2);
2455 gen_set_label(l1);
2456 tcg_gen_divu_tl(cpu_gpr[rd], t0, t1);
2457 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
2458 gen_set_label(l2);
2459 }
2460 opn = "divu.g";
2461 break;
2462 case OPC_MOD_G_2E:
2463 case OPC_MOD_G_2F:
2464 {
2465 int l1 = gen_new_label();
2466 int l2 = gen_new_label();
2467 int l3 = gen_new_label();
2468 tcg_gen_ext32u_tl(t0, t0);
2469 tcg_gen_ext32u_tl(t1, t1);
2470 tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
2471 tcg_gen_brcondi_tl(TCG_COND_NE, t0, INT_MIN, l2);
2472 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1, l2);
2473 gen_set_label(l1);
2474 tcg_gen_movi_tl(cpu_gpr[rd], 0);
2475 tcg_gen_br(l3);
2476 gen_set_label(l2);
2477 tcg_gen_rem_tl(cpu_gpr[rd], t0, t1);
2478 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
2479 gen_set_label(l3);
2480 }
2481 opn = "mod.g";
2482 break;
2483 case OPC_MODU_G_2E:
2484 case OPC_MODU_G_2F:
2485 {
2486 int l1 = gen_new_label();
2487 int l2 = gen_new_label();
2488 tcg_gen_ext32u_tl(t0, t0);
2489 tcg_gen_ext32u_tl(t1, t1);
2490 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
2491 tcg_gen_movi_tl(cpu_gpr[rd], 0);
2492 tcg_gen_br(l2);
2493 gen_set_label(l1);
2494 tcg_gen_remu_tl(cpu_gpr[rd], t0, t1);
2495 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
2496 gen_set_label(l2);
2497 }
2498 opn = "modu.g";
2499 break;
2500#if defined(TARGET_MIPS64)
2501 case OPC_DMULT_G_2E:
2502 case OPC_DMULT_G_2F:
2503 tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
2504 opn = "dmult.g";
2505 break;
2506 case OPC_DMULTU_G_2E:
2507 case OPC_DMULTU_G_2F:
2508 tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
2509 opn = "dmultu.g";
2510 break;
2511 case OPC_DDIV_G_2E:
2512 case OPC_DDIV_G_2F:
2513 {
2514 int l1 = gen_new_label();
2515 int l2 = gen_new_label();
2516 int l3 = gen_new_label();
2517 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
2518 tcg_gen_movi_tl(cpu_gpr[rd], 0);
2519 tcg_gen_br(l3);
2520 gen_set_label(l1);
2521 tcg_gen_brcondi_tl(TCG_COND_NE, t0, -1LL << 63, l2);
2522 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1LL, l2);
2523 tcg_gen_mov_tl(cpu_gpr[rd], t0);
2524 tcg_gen_br(l3);
2525 gen_set_label(l2);
2526 tcg_gen_div_tl(cpu_gpr[rd], t0, t1);
2527 gen_set_label(l3);
2528 }
2529 opn = "ddiv.g";
2530 break;
2531 case OPC_DDIVU_G_2E:
2532 case OPC_DDIVU_G_2F:
2533 {
2534 int l1 = gen_new_label();
2535 int l2 = gen_new_label();
2536 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
2537 tcg_gen_movi_tl(cpu_gpr[rd], 0);
2538 tcg_gen_br(l2);
2539 gen_set_label(l1);
2540 tcg_gen_divu_tl(cpu_gpr[rd], t0, t1);
2541 gen_set_label(l2);
2542 }
2543 opn = "ddivu.g";
2544 break;
2545 case OPC_DMOD_G_2E:
2546 case OPC_DMOD_G_2F:
2547 {
2548 int l1 = gen_new_label();
2549 int l2 = gen_new_label();
2550 int l3 = gen_new_label();
2551 tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
2552 tcg_gen_brcondi_tl(TCG_COND_NE, t0, -1LL << 63, l2);
2553 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1LL, l2);
2554 gen_set_label(l1);
2555 tcg_gen_movi_tl(cpu_gpr[rd], 0);
2556 tcg_gen_br(l3);
2557 gen_set_label(l2);
2558 tcg_gen_rem_tl(cpu_gpr[rd], t0, t1);
2559 gen_set_label(l3);
2560 }
2561 opn = "dmod.g";
2562 break;
2563 case OPC_DMODU_G_2E:
2564 case OPC_DMODU_G_2F:
2565 {
2566 int l1 = gen_new_label();
2567 int l2 = gen_new_label();
2568 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
2569 tcg_gen_movi_tl(cpu_gpr[rd], 0);
2570 tcg_gen_br(l2);
2571 gen_set_label(l1);
2572 tcg_gen_remu_tl(cpu_gpr[rd], t0, t1);
2573 gen_set_label(l2);
2574 }
2575 opn = "dmodu.g";
2576 break;
2577#endif
2578 }
2579
2abf314d 2580 (void)opn; /* avoid a compiler warning */
161f85e6
AJ
2581 MIPS_DEBUG("%s %s, %s", opn, regnames[rd], regnames[rs]);
2582 tcg_temp_free(t0);
2583 tcg_temp_free(t1);
2584}
2585
6af0bf9c 2586/* Traps */
7a387fff 2587static void gen_trap (DisasContext *ctx, uint32_t opc,
6af0bf9c
FB
2588 int rs, int rt, int16_t imm)
2589{
2590 int cond;
cdc0faa6 2591 TCGv t0 = tcg_temp_new();
1ba74fb8 2592 TCGv t1 = tcg_temp_new();
6af0bf9c
FB
2593
2594 cond = 0;
2595 /* Load needed operands */
2596 switch (opc) {
2597 case OPC_TEQ:
2598 case OPC_TGE:
2599 case OPC_TGEU:
2600 case OPC_TLT:
2601 case OPC_TLTU:
2602 case OPC_TNE:
2603 /* Compare two registers */
2604 if (rs != rt) {
be24bb4f
TS
2605 gen_load_gpr(t0, rs);
2606 gen_load_gpr(t1, rt);
6af0bf9c
FB
2607 cond = 1;
2608 }
179e32bb 2609 break;
6af0bf9c
FB
2610 case OPC_TEQI:
2611 case OPC_TGEI:
2612 case OPC_TGEIU:
2613 case OPC_TLTI:
2614 case OPC_TLTIU:
2615 case OPC_TNEI:
2616 /* Compare register to immediate */
2617 if (rs != 0 || imm != 0) {
be24bb4f
TS
2618 gen_load_gpr(t0, rs);
2619 tcg_gen_movi_tl(t1, (int32_t)imm);
6af0bf9c
FB
2620 cond = 1;
2621 }
2622 break;
2623 }
2624 if (cond == 0) {
2625 switch (opc) {
2626 case OPC_TEQ: /* rs == rs */
2627 case OPC_TEQI: /* r0 == 0 */
2628 case OPC_TGE: /* rs >= rs */
2629 case OPC_TGEI: /* r0 >= 0 */
2630 case OPC_TGEU: /* rs >= rs unsigned */
2631 case OPC_TGEIU: /* r0 >= 0 unsigned */
2632 /* Always trap */
cdc0faa6 2633 generate_exception(ctx, EXCP_TRAP);
6af0bf9c
FB
2634 break;
2635 case OPC_TLT: /* rs < rs */
2636 case OPC_TLTI: /* r0 < 0 */
2637 case OPC_TLTU: /* rs < rs unsigned */
2638 case OPC_TLTIU: /* r0 < 0 unsigned */
2639 case OPC_TNE: /* rs != rs */
2640 case OPC_TNEI: /* r0 != 0 */
ead9360e 2641 /* Never trap: treat as NOP. */
cdc0faa6 2642 break;
6af0bf9c
FB
2643 }
2644 } else {
cdc0faa6
AJ
2645 int l1 = gen_new_label();
2646
6af0bf9c
FB
2647 switch (opc) {
2648 case OPC_TEQ:
2649 case OPC_TEQI:
cdc0faa6 2650 tcg_gen_brcond_tl(TCG_COND_NE, t0, t1, l1);
6af0bf9c
FB
2651 break;
2652 case OPC_TGE:
2653 case OPC_TGEI:
cdc0faa6 2654 tcg_gen_brcond_tl(TCG_COND_LT, t0, t1, l1);
6af0bf9c
FB
2655 break;
2656 case OPC_TGEU:
2657 case OPC_TGEIU:
cdc0faa6 2658 tcg_gen_brcond_tl(TCG_COND_LTU, t0, t1, l1);
6af0bf9c
FB
2659 break;
2660 case OPC_TLT:
2661 case OPC_TLTI:
cdc0faa6 2662 tcg_gen_brcond_tl(TCG_COND_GE, t0, t1, l1);
6af0bf9c
FB
2663 break;
2664 case OPC_TLTU:
2665 case OPC_TLTIU:
cdc0faa6 2666 tcg_gen_brcond_tl(TCG_COND_GEU, t0, t1, l1);
6af0bf9c
FB
2667 break;
2668 case OPC_TNE:
2669 case OPC_TNEI:
cdc0faa6 2670 tcg_gen_brcond_tl(TCG_COND_EQ, t0, t1, l1);
6af0bf9c 2671 break;
6af0bf9c 2672 }
cdc0faa6 2673 generate_exception(ctx, EXCP_TRAP);
08ba7963
TS
2674 gen_set_label(l1);
2675 }
be24bb4f
TS
2676 tcg_temp_free(t0);
2677 tcg_temp_free(t1);
6af0bf9c
FB
2678}
2679
356265ae 2680static inline void gen_goto_tb(DisasContext *ctx, int n, target_ulong dest)
c53be334 2681{
6e256c93
FB
2682 TranslationBlock *tb;
2683 tb = ctx->tb;
7b270ef2
NF
2684 if ((tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK) &&
2685 likely(!ctx->singlestep_enabled)) {
57fec1fe 2686 tcg_gen_goto_tb(n);
9b9e4393 2687 gen_save_pc(dest);
4b4a72e5 2688 tcg_gen_exit_tb((tcg_target_long)tb + n);
6e256c93 2689 } else {
9b9e4393 2690 gen_save_pc(dest);
7b270ef2
NF
2691 if (ctx->singlestep_enabled) {
2692 save_cpu_state(ctx, 0);
2693 gen_helper_0i(raise_exception, EXCP_DEBUG);
2694 }
57fec1fe 2695 tcg_gen_exit_tb(0);
6e256c93 2696 }
c53be334
FB
2697}
2698
6af0bf9c 2699/* Branches (before delay slot) */
7a387fff 2700static void gen_compute_branch (DisasContext *ctx, uint32_t opc,
7dca4ad0 2701 int insn_bytes,
6af0bf9c
FB
2702 int rs, int rt, int32_t offset)
2703{
d077b6f7 2704 target_ulong btgt = -1;
3ad4bb2d 2705 int blink = 0;
2fdbad25 2706 int bcond_compute = 0;
1ba74fb8
AJ
2707 TCGv t0 = tcg_temp_new();
2708 TCGv t1 = tcg_temp_new();
3ad4bb2d
TS
2709
2710 if (ctx->hflags & MIPS_HFLAG_BMASK) {
923617a3 2711#ifdef MIPS_DEBUG_DISAS
d12d51d5 2712 LOG_DISAS("Branch in delay slot at PC 0x" TARGET_FMT_lx "\n", ctx->pc);
923617a3 2713#endif
3ad4bb2d 2714 generate_exception(ctx, EXCP_RI);
6c5c1e20 2715 goto out;
3ad4bb2d 2716 }
6af0bf9c 2717
6af0bf9c
FB
2718 /* Load needed operands */
2719 switch (opc) {
2720 case OPC_BEQ:
2721 case OPC_BEQL:
2722 case OPC_BNE:
2723 case OPC_BNEL:
2724 /* Compare two registers */
2725 if (rs != rt) {
6c5c1e20
TS
2726 gen_load_gpr(t0, rs);
2727 gen_load_gpr(t1, rt);
2fdbad25 2728 bcond_compute = 1;
6af0bf9c 2729 }
7dca4ad0 2730 btgt = ctx->pc + insn_bytes + offset;
6af0bf9c
FB
2731 break;
2732 case OPC_BGEZ:
2733 case OPC_BGEZAL:
3c824109 2734 case OPC_BGEZALS:
6af0bf9c
FB
2735 case OPC_BGEZALL:
2736 case OPC_BGEZL:
2737 case OPC_BGTZ:
2738 case OPC_BGTZL:
2739 case OPC_BLEZ:
2740 case OPC_BLEZL:
2741 case OPC_BLTZ:
2742 case OPC_BLTZAL:
3c824109 2743 case OPC_BLTZALS:
6af0bf9c
FB
2744 case OPC_BLTZALL:
2745 case OPC_BLTZL:
2746 /* Compare to zero */
2747 if (rs != 0) {
6c5c1e20 2748 gen_load_gpr(t0, rs);
2fdbad25 2749 bcond_compute = 1;
6af0bf9c 2750 }
7dca4ad0 2751 btgt = ctx->pc + insn_bytes + offset;
6af0bf9c
FB
2752 break;
2753 case OPC_J:
2754 case OPC_JAL:
364d4831 2755 case OPC_JALX:
620e48f6
NF
2756 case OPC_JALS:
2757 case OPC_JALXS:
6af0bf9c 2758 /* Jump to immediate */
7dca4ad0 2759 btgt = ((ctx->pc + insn_bytes) & (int32_t)0xF0000000) | (uint32_t)offset;
6af0bf9c
FB
2760 break;
2761 case OPC_JR:
2762 case OPC_JALR:
364d4831 2763 case OPC_JALRC:
620e48f6 2764 case OPC_JALRS:
6af0bf9c 2765 /* Jump to register */
7a387fff
TS
2766 if (offset != 0 && offset != 16) {
2767 /* Hint = 0 is JR/JALR, hint 16 is JR.HB/JALR.HB, the
cbeb0857 2768 others are reserved. */
923617a3 2769 MIPS_INVAL("jump hint");
6af0bf9c 2770 generate_exception(ctx, EXCP_RI);
6c5c1e20 2771 goto out;
6af0bf9c 2772 }
d077b6f7 2773 gen_load_gpr(btarget, rs);
6af0bf9c
FB
2774 break;
2775 default:
2776 MIPS_INVAL("branch/jump");
2777 generate_exception(ctx, EXCP_RI);
6c5c1e20 2778 goto out;
6af0bf9c 2779 }
2fdbad25 2780 if (bcond_compute == 0) {
6af0bf9c
FB
2781 /* No condition to be computed */
2782 switch (opc) {
2783 case OPC_BEQ: /* rx == rx */
2784 case OPC_BEQL: /* rx == rx likely */
2785 case OPC_BGEZ: /* 0 >= 0 */
2786 case OPC_BGEZL: /* 0 >= 0 likely */
2787 case OPC_BLEZ: /* 0 <= 0 */
2788 case OPC_BLEZL: /* 0 <= 0 likely */
2789 /* Always take */
4ad40f36 2790 ctx->hflags |= MIPS_HFLAG_B;
6af0bf9c
FB
2791 MIPS_DEBUG("balways");
2792 break;
3c824109 2793 case OPC_BGEZALS:
6af0bf9c
FB
2794 case OPC_BGEZAL: /* 0 >= 0 */
2795 case OPC_BGEZALL: /* 0 >= 0 likely */
3c824109
NF
2796 ctx->hflags |= (opc == OPC_BGEZALS
2797 ? MIPS_HFLAG_BDS16
2798 : MIPS_HFLAG_BDS32);
6af0bf9c
FB
2799 /* Always take and link */
2800 blink = 31;
4ad40f36 2801 ctx->hflags |= MIPS_HFLAG_B;
6af0bf9c
FB
2802 MIPS_DEBUG("balways and link");
2803 break;
2804 case OPC_BNE: /* rx != rx */
2805 case OPC_BGTZ: /* 0 > 0 */
2806 case OPC_BLTZ: /* 0 < 0 */
ead9360e 2807 /* Treat as NOP. */
6af0bf9c 2808 MIPS_DEBUG("bnever (NOP)");
6c5c1e20 2809 goto out;
3c824109 2810 case OPC_BLTZALS:
eeef26cd 2811 case OPC_BLTZAL: /* 0 < 0 */
3c824109
NF
2812 ctx->hflags |= (opc == OPC_BLTZALS
2813 ? MIPS_HFLAG_BDS16
2814 : MIPS_HFLAG_BDS32);
2815 /* Handle as an unconditional branch to get correct delay
2816 slot checking. */
2817 blink = 31;
2818 btgt = ctx->pc + (opc == OPC_BLTZALS ? 6 : 8);
2819 ctx->hflags |= MIPS_HFLAG_B;
9898128f 2820 MIPS_DEBUG("bnever and link");
3c824109 2821 break;
eeef26cd 2822 case OPC_BLTZALL: /* 0 < 0 likely */
1ba74fb8 2823 tcg_gen_movi_tl(cpu_gpr[31], ctx->pc + 8);
9898128f
TS
2824 /* Skip the instruction in the delay slot */
2825 MIPS_DEBUG("bnever, link and skip");
2826 ctx->pc += 4;
6c5c1e20 2827 goto out;
6af0bf9c
FB
2828 case OPC_BNEL: /* rx != rx likely */
2829 case OPC_BGTZL: /* 0 > 0 likely */
6af0bf9c
FB
2830 case OPC_BLTZL: /* 0 < 0 likely */
2831 /* Skip the instruction in the delay slot */
2832 MIPS_DEBUG("bnever and skip");
9898128f 2833 ctx->pc += 4;
6c5c1e20 2834 goto out;
6af0bf9c 2835 case OPC_J:
4ad40f36 2836 ctx->hflags |= MIPS_HFLAG_B;
d077b6f7 2837 MIPS_DEBUG("j " TARGET_FMT_lx, btgt);
6af0bf9c 2838 break;
620e48f6 2839 case OPC_JALXS:
364d4831
NF
2840 case OPC_JALX:
2841 ctx->hflags |= MIPS_HFLAG_BX;
2842 /* Fallthrough */
620e48f6 2843 case OPC_JALS:
6af0bf9c
FB
2844 case OPC_JAL:
2845 blink = 31;
4ad40f36 2846 ctx->hflags |= MIPS_HFLAG_B;
620e48f6 2847 ctx->hflags |= ((opc == OPC_JALS || opc == OPC_JALXS)
364d4831
NF
2848 ? MIPS_HFLAG_BDS16
2849 : MIPS_HFLAG_BDS32);
d077b6f7 2850 MIPS_DEBUG("jal " TARGET_FMT_lx, btgt);
6af0bf9c
FB
2851 break;
2852 case OPC_JR:
4ad40f36 2853 ctx->hflags |= MIPS_HFLAG_BR;
620e48f6
NF
2854 if (insn_bytes == 4)
2855 ctx->hflags |= MIPS_HFLAG_BDS32;
6af0bf9c
FB
2856 MIPS_DEBUG("jr %s", regnames[rs]);
2857 break;
620e48f6 2858 case OPC_JALRS:
6af0bf9c 2859 case OPC_JALR:
364d4831 2860 case OPC_JALRC:
6af0bf9c 2861 blink = rt;
4ad40f36 2862 ctx->hflags |= MIPS_HFLAG_BR;
620e48f6
NF
2863 ctx->hflags |= (opc == OPC_JALRS
2864 ? MIPS_HFLAG_BDS16
2865 : MIPS_HFLAG_BDS32);
6af0bf9c
FB
2866 MIPS_DEBUG("jalr %s, %s", regnames[rt], regnames[rs]);
2867 break;
2868 default:
2869 MIPS_INVAL("branch/jump");
2870 generate_exception(ctx, EXCP_RI);
6c5c1e20 2871 goto out;
6af0bf9c
FB
2872 }
2873 } else {
2874 switch (opc) {
2875 case OPC_BEQ:
e68dd28f 2876 tcg_gen_setcond_tl(TCG_COND_EQ, bcond, t0, t1);
923617a3 2877 MIPS_DEBUG("beq %s, %s, " TARGET_FMT_lx,
d077b6f7 2878 regnames[rs], regnames[rt], btgt);
6af0bf9c
FB
2879 goto not_likely;
2880 case OPC_BEQL:
e68dd28f 2881 tcg_gen_setcond_tl(TCG_COND_EQ, bcond, t0, t1);
923617a3 2882 MIPS_DEBUG("beql %s, %s, " TARGET_FMT_lx,
d077b6f7 2883 regnames[rs], regnames[rt], btgt);
6af0bf9c
FB
2884 goto likely;
2885 case OPC_BNE:
e68dd28f 2886 tcg_gen_setcond_tl(TCG_COND_NE, bcond, t0, t1);
923617a3 2887 MIPS_DEBUG("bne %s, %s, " TARGET_FMT_lx,
d077b6f7 2888 regnames[rs], regnames[rt], btgt);
6af0bf9c
FB
2889 goto not_likely;
2890 case OPC_BNEL:
e68dd28f 2891 tcg_gen_setcond_tl(TCG_COND_NE, bcond, t0, t1);
923617a3 2892 MIPS_DEBUG("bnel %s, %s, " TARGET_FMT_lx,
d077b6f7 2893 regnames[rs], regnames[rt], btgt);
6af0bf9c
FB
2894 goto likely;
2895 case OPC_BGEZ:
e68dd28f 2896 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
d077b6f7 2897 MIPS_DEBUG("bgez %s, " TARGET_FMT_lx, regnames[rs], btgt);
6af0bf9c
FB
2898 goto not_likely;
2899 case OPC_BGEZL:
e68dd28f 2900 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
d077b6f7 2901 MIPS_DEBUG("bgezl %s, " TARGET_FMT_lx, regnames[rs], btgt);
6af0bf9c 2902 goto likely;
3c824109 2903 case OPC_BGEZALS:
6af0bf9c 2904 case OPC_BGEZAL:
3c824109
NF
2905 ctx->hflags |= (opc == OPC_BGEZALS
2906 ? MIPS_HFLAG_BDS16
2907 : MIPS_HFLAG_BDS32);
e68dd28f 2908 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
d077b6f7 2909 MIPS_DEBUG("bgezal %s, " TARGET_FMT_lx, regnames[rs], btgt);
6af0bf9c
FB
2910 blink = 31;
2911 goto not_likely;
2912 case OPC_BGEZALL:
e68dd28f 2913 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
6af0bf9c 2914 blink = 31;
d077b6f7 2915 MIPS_DEBUG("bgezall %s, " TARGET_FMT_lx, regnames[rs], btgt);
6af0bf9c
FB
2916 goto likely;
2917 case OPC_BGTZ:
e68dd28f 2918 tcg_gen_setcondi_tl(TCG_COND_GT, bcond, t0, 0);
d077b6f7 2919 MIPS_DEBUG("bgtz %s, " TARGET_FMT_lx, regnames[rs], btgt);
6af0bf9c
FB
2920 goto not_likely;
2921 case OPC_BGTZL:
e68dd28f 2922 tcg_gen_setcondi_tl(TCG_COND_GT, bcond, t0, 0);
d077b6f7 2923 MIPS_DEBUG("bgtzl %s, " TARGET_FMT_lx, regnames[rs], btgt);
6af0bf9c
FB
2924 goto likely;
2925 case OPC_BLEZ:
e68dd28f 2926 tcg_gen_setcondi_tl(TCG_COND_LE, bcond, t0, 0);
d077b6f7 2927 MIPS_DEBUG("blez %s, " TARGET_FMT_lx, regnames[rs], btgt);
6af0bf9c
FB
2928 goto not_likely;
2929 case OPC_BLEZL:
e68dd28f 2930 tcg_gen_setcondi_tl(TCG_COND_LE, bcond, t0, 0);
d077b6f7 2931 MIPS_DEBUG("blezl %s, " TARGET_FMT_lx, regnames[rs], btgt);
6af0bf9c
FB
2932 goto likely;
2933 case OPC_BLTZ:
e68dd28f 2934 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
d077b6f7 2935 MIPS_DEBUG("bltz %s, " TARGET_FMT_lx, regnames[rs], btgt);
6af0bf9c
FB
2936 goto not_likely;
2937 case OPC_BLTZL:
e68dd28f 2938 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
d077b6f7 2939 MIPS_DEBUG("bltzl %s, " TARGET_FMT_lx, regnames[rs], btgt);
6af0bf9c 2940 goto likely;
3c824109 2941 case OPC_BLTZALS:
6af0bf9c 2942 case OPC_BLTZAL:
3c824109
NF
2943 ctx->hflags |= (opc == OPC_BLTZALS
2944 ? MIPS_HFLAG_BDS16
2945 : MIPS_HFLAG_BDS32);
e68dd28f 2946 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
6af0bf9c 2947 blink = 31;
d077b6f7 2948 MIPS_DEBUG("bltzal %s, " TARGET_FMT_lx, regnames[rs], btgt);
6af0bf9c 2949 not_likely:
4ad40f36 2950 ctx->hflags |= MIPS_HFLAG_BC;
6af0bf9c
FB
2951 break;
2952 case OPC_BLTZALL:
e68dd28f 2953 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
6af0bf9c 2954 blink = 31;
d077b6f7 2955 MIPS_DEBUG("bltzall %s, " TARGET_FMT_lx, regnames[rs], btgt);
6af0bf9c 2956 likely:
4ad40f36 2957 ctx->hflags |= MIPS_HFLAG_BL;
6af0bf9c 2958 break;
c53f4a62
TS
2959 default:
2960 MIPS_INVAL("conditional branch/jump");
2961 generate_exception(ctx, EXCP_RI);
6c5c1e20 2962 goto out;
6af0bf9c 2963 }
6af0bf9c 2964 }
923617a3 2965 MIPS_DEBUG("enter ds: link %d cond %02x target " TARGET_FMT_lx,
d077b6f7 2966 blink, ctx->hflags, btgt);
9b9e4393 2967
d077b6f7 2968 ctx->btarget = btgt;
6af0bf9c 2969 if (blink > 0) {
364d4831
NF
2970 int post_delay = insn_bytes;
2971 int lowbit = !!(ctx->hflags & MIPS_HFLAG_M16);
2972
2973 if (opc != OPC_JALRC)
2974 post_delay += ((ctx->hflags & MIPS_HFLAG_BDS16) ? 2 : 4);
2975
2976 tcg_gen_movi_tl(cpu_gpr[blink], ctx->pc + post_delay + lowbit);
6af0bf9c 2977 }
6c5c1e20
TS
2978
2979 out:
364d4831
NF
2980 if (insn_bytes == 2)
2981 ctx->hflags |= MIPS_HFLAG_B16;
6c5c1e20
TS
2982 tcg_temp_free(t0);
2983 tcg_temp_free(t1);
6af0bf9c
FB
2984}
2985
7a387fff
TS
2986/* special3 bitfield operations */
2987static void gen_bitops (DisasContext *ctx, uint32_t opc, int rt,
356265ae 2988 int rs, int lsb, int msb)
7a387fff 2989{
a7812ae4
PB
2990 TCGv t0 = tcg_temp_new();
2991 TCGv t1 = tcg_temp_new();
505ad7c2 2992 target_ulong mask;
6c5c1e20
TS
2993
2994 gen_load_gpr(t1, rs);
7a387fff
TS
2995 switch (opc) {
2996 case OPC_EXT:
2997 if (lsb + msb > 31)
2998 goto fail;
505ad7c2
AJ
2999 tcg_gen_shri_tl(t0, t1, lsb);
3000 if (msb != 31) {
3001 tcg_gen_andi_tl(t0, t0, (1 << (msb + 1)) - 1);
3002 } else {
3003 tcg_gen_ext32s_tl(t0, t0);
3004 }
7a387fff 3005 break;
c6d6dd7c 3006#if defined(TARGET_MIPS64)
7a387fff 3007 case OPC_DEXTM:
505ad7c2
AJ
3008 tcg_gen_shri_tl(t0, t1, lsb);
3009 if (msb != 31) {
3010 tcg_gen_andi_tl(t0, t0, (1ULL << (msb + 1 + 32)) - 1);
3011 }
7a387fff
TS
3012 break;
3013 case OPC_DEXTU:
505ad7c2
AJ
3014 tcg_gen_shri_tl(t0, t1, lsb + 32);
3015 tcg_gen_andi_tl(t0, t0, (1ULL << (msb + 1)) - 1);
7a387fff
TS
3016 break;
3017 case OPC_DEXT:
505ad7c2
AJ
3018 tcg_gen_shri_tl(t0, t1, lsb);
3019 tcg_gen_andi_tl(t0, t0, (1ULL << (msb + 1)) - 1);
7a387fff 3020 break;
c6d6dd7c 3021#endif
7a387fff
TS
3022 case OPC_INS:
3023 if (lsb > msb)
3024 goto fail;
505ad7c2 3025 mask = ((msb - lsb + 1 < 32) ? ((1 << (msb - lsb + 1)) - 1) : ~0) << lsb;
6c5c1e20 3026 gen_load_gpr(t0, rt);
505ad7c2
AJ
3027 tcg_gen_andi_tl(t0, t0, ~mask);
3028 tcg_gen_shli_tl(t1, t1, lsb);
3029 tcg_gen_andi_tl(t1, t1, mask);
3030 tcg_gen_or_tl(t0, t0, t1);
3031 tcg_gen_ext32s_tl(t0, t0);
7a387fff 3032 break;
c6d6dd7c 3033#if defined(TARGET_MIPS64)
7a387fff
TS
3034 case OPC_DINSM:
3035 if (lsb > msb)
3036 goto fail;
505ad7c2 3037 mask = ((msb - lsb + 1 + 32 < 64) ? ((1ULL << (msb - lsb + 1 + 32)) - 1) : ~0ULL) << lsb;
6c5c1e20 3038 gen_load_gpr(t0, rt);
505ad7c2
AJ
3039 tcg_gen_andi_tl(t0, t0, ~mask);
3040 tcg_gen_shli_tl(t1, t1, lsb);
3041 tcg_gen_andi_tl(t1, t1, mask);
3042 tcg_gen_or_tl(t0, t0, t1);
7a387fff
TS
3043 break;
3044 case OPC_DINSU:
3045 if (lsb > msb)
3046 goto fail;
6fbab869 3047 mask = ((1ULL << (msb - lsb + 1)) - 1) << (lsb + 32);
6c5c1e20 3048 gen_load_gpr(t0, rt);
505ad7c2
AJ
3049 tcg_gen_andi_tl(t0, t0, ~mask);
3050 tcg_gen_shli_tl(t1, t1, lsb + 32);
3051 tcg_gen_andi_tl(t1, t1, mask);
3052 tcg_gen_or_tl(t0, t0, t1);
7a387fff
TS
3053 break;
3054 case OPC_DINS:
3055 if (lsb > msb)
3056 goto fail;
6c5c1e20 3057 gen_load_gpr(t0, rt);
505ad7c2
AJ
3058 mask = ((1ULL << (msb - lsb + 1)) - 1) << lsb;
3059 gen_load_gpr(t0, rt);
3060 tcg_gen_andi_tl(t0, t0, ~mask);
3061 tcg_gen_shli_tl(t1, t1, lsb);
3062 tcg_gen_andi_tl(t1, t1, mask);
3063 tcg_gen_or_tl(t0, t0, t1);
7a387fff 3064 break;
c6d6dd7c 3065#endif
7a387fff
TS
3066 default:
3067fail:
3068 MIPS_INVAL("bitops");
3069 generate_exception(ctx, EXCP_RI);
6c5c1e20
TS
3070 tcg_temp_free(t0);
3071 tcg_temp_free(t1);
7a387fff
TS
3072 return;
3073 }
6c5c1e20
TS
3074 gen_store_gpr(t0, rt);
3075 tcg_temp_free(t0);
3076 tcg_temp_free(t1);
7a387fff
TS
3077}
3078
49bcf33c
AJ
3079static void gen_bshfl (DisasContext *ctx, uint32_t op2, int rt, int rd)
3080{
3a55fa47 3081 TCGv t0;
49bcf33c 3082
3a55fa47
AJ
3083 if (rd == 0) {
3084 /* If no destination, treat it as a NOP. */
3085 MIPS_DEBUG("NOP");
3086 return;
3087 }
3088
3089 t0 = tcg_temp_new();
3090 gen_load_gpr(t0, rt);
49bcf33c
AJ
3091 switch (op2) {
3092 case OPC_WSBH:
3a55fa47
AJ
3093 {
3094 TCGv t1 = tcg_temp_new();
3095
3096 tcg_gen_shri_tl(t1, t0, 8);
3097 tcg_gen_andi_tl(t1, t1, 0x00FF00FF);
3098 tcg_gen_shli_tl(t0, t0, 8);
3099 tcg_gen_andi_tl(t0, t0, ~0x00FF00FF);
3100 tcg_gen_or_tl(t0, t0, t1);
3101 tcg_temp_free(t1);
3102 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
3103 }
49bcf33c
AJ
3104 break;
3105 case OPC_SEB:
3a55fa47 3106 tcg_gen_ext8s_tl(cpu_gpr[rd], t0);
49bcf33c
AJ
3107 break;
3108 case OPC_SEH:
3a55fa47 3109 tcg_gen_ext16s_tl(cpu_gpr[rd], t0);
49bcf33c
AJ
3110 break;
3111#if defined(TARGET_MIPS64)
3112 case OPC_DSBH:
3a55fa47
AJ
3113 {
3114 TCGv t1 = tcg_temp_new();
3115
3116 tcg_gen_shri_tl(t1, t0, 8);
3117 tcg_gen_andi_tl(t1, t1, 0x00FF00FF00FF00FFULL);
3118 tcg_gen_shli_tl(t0, t0, 8);
3119 tcg_gen_andi_tl(t0, t0, ~0x00FF00FF00FF00FFULL);
3120 tcg_gen_or_tl(cpu_gpr[rd], t0, t1);
3121 tcg_temp_free(t1);
3122 }
49bcf33c
AJ
3123 break;
3124 case OPC_DSHD:
3a55fa47
AJ
3125 {
3126 TCGv t1 = tcg_temp_new();
3127
3128 tcg_gen_shri_tl(t1, t0, 16);
3129 tcg_gen_andi_tl(t1, t1, 0x0000FFFF0000FFFFULL);
3130 tcg_gen_shli_tl(t0, t0, 16);
3131 tcg_gen_andi_tl(t0, t0, ~0x0000FFFF0000FFFFULL);
3132 tcg_gen_or_tl(t0, t0, t1);
3133 tcg_gen_shri_tl(t1, t0, 32);
3134 tcg_gen_shli_tl(t0, t0, 32);
3135 tcg_gen_or_tl(cpu_gpr[rd], t0, t1);
3136 tcg_temp_free(t1);
3137 }
49bcf33c
AJ
3138 break;
3139#endif
3140 default:
3141 MIPS_INVAL("bsfhl");
3142 generate_exception(ctx, EXCP_RI);
3143 tcg_temp_free(t0);
49bcf33c
AJ
3144 return;
3145 }
49bcf33c 3146 tcg_temp_free(t0);
49bcf33c
AJ
3147}
3148
f1aa6320 3149#ifndef CONFIG_USER_ONLY
0eaef5aa 3150/* CP0 (MMU and control) */
d9bea114 3151static inline void gen_mfc0_load32 (TCGv arg, target_ulong off)
4f57689a 3152{
d9bea114 3153 TCGv_i32 t0 = tcg_temp_new_i32();
4f57689a 3154
d9bea114
AJ
3155 tcg_gen_ld_i32(t0, cpu_env, off);
3156 tcg_gen_ext_i32_tl(arg, t0);
3157 tcg_temp_free_i32(t0);
4f57689a
TS
3158}
3159
d9bea114 3160static inline void gen_mfc0_load64 (TCGv arg, target_ulong off)
4f57689a 3161{
d9bea114
AJ
3162 tcg_gen_ld_tl(arg, cpu_env, off);
3163 tcg_gen_ext32s_tl(arg, arg);
4f57689a
TS
3164}
3165
d9bea114 3166static inline void gen_mtc0_store32 (TCGv arg, target_ulong off)
f1aa6320 3167{
d9bea114 3168 TCGv_i32 t0 = tcg_temp_new_i32();
f1aa6320 3169
d9bea114
AJ
3170 tcg_gen_trunc_tl_i32(t0, arg);
3171 tcg_gen_st_i32(t0, cpu_env, off);
3172 tcg_temp_free_i32(t0);
f1aa6320
TS
3173}
3174
d9bea114 3175static inline void gen_mtc0_store64 (TCGv arg, target_ulong off)
f1aa6320 3176{
d9bea114
AJ
3177 tcg_gen_ext32s_tl(arg, arg);
3178 tcg_gen_st_tl(arg, cpu_env, off);
f1aa6320
TS
3179}
3180
d9bea114 3181static void gen_mfc0 (CPUState *env, DisasContext *ctx, TCGv arg, int reg, int sel)
873eb012 3182{
7a387fff 3183 const char *rn = "invalid";
873eb012 3184
e189e748
TS
3185 if (sel != 0)
3186 check_insn(env, ctx, ISA_MIPS32);
3187
873eb012
TS
3188 switch (reg) {
3189 case 0:
7a387fff
TS
3190 switch (sel) {
3191 case 0:
d9bea114 3192 gen_mfc0_load32(arg, offsetof(CPUState, CP0_Index));
7a387fff
TS
3193 rn = "Index";
3194 break;
3195 case 1:
7385ac0b 3196 check_insn(env, ctx, ASE_MT);
d9bea114 3197 gen_helper_mfc0_mvpcontrol(arg);
7a387fff 3198 rn = "MVPControl";
ead9360e 3199 break;
7a387fff 3200 case 2:
7385ac0b 3201 check_insn(env, ctx, ASE_MT);
d9bea114 3202 gen_helper_mfc0_mvpconf0(arg);
7a387fff 3203 rn = "MVPConf0";
ead9360e 3204 break;
7a387fff 3205 case 3:
7385ac0b 3206 check_insn(env, ctx, ASE_MT);
d9bea114 3207 gen_helper_mfc0_mvpconf1(arg);
7a387fff 3208 rn = "MVPConf1";
ead9360e 3209 break;
7a387fff
TS
3210 default:
3211 goto die;
3212 }
873eb012
TS
3213 break;
3214 case 1:
7a387fff
TS
3215 switch (sel) {
3216 case 0:
d9bea114 3217 gen_helper_mfc0_random(arg);
7a387fff 3218 rn = "Random";
2423f660 3219 break;
7a387fff 3220 case 1:
7385ac0b 3221 check_insn(env, ctx, ASE_MT);
d9bea114 3222 gen_mfc0_load32(arg, offsetof(CPUState, CP0_VPEControl));
7a387fff 3223 rn = "VPEControl";
ead9360e 3224 break;
7a387fff 3225 case 2:
7385ac0b 3226 check_insn(env, ctx, ASE_MT);
d9bea114 3227 gen_mfc0_load32(arg, offsetof(CPUState, CP0_VPEConf0));
7a387fff 3228 rn = "VPEConf0";
ead9360e 3229 break;
7a387fff 3230 case 3:
7385ac0b 3231 check_insn(env, ctx, ASE_MT);
d9bea114 3232 gen_mfc0_load32(arg, offsetof(CPUState, CP0_VPEConf1));
7a387fff 3233 rn = "VPEConf1";
ead9360e 3234 break;
7a387fff 3235 case 4:
7385ac0b 3236 check_insn(env, ctx, ASE_MT);
d9bea114 3237 gen_mfc0_load64(arg, offsetof(CPUState, CP0_YQMask));
7a387fff 3238 rn = "YQMask";
ead9360e 3239 break;
7a387fff 3240 case 5:
7385ac0b 3241 check_insn(env, ctx, ASE_MT);
d9bea114 3242 gen_mfc0_load64(arg, offsetof(CPUState, CP0_VPESchedule));
7a387fff 3243 rn = "VPESchedule";
ead9360e 3244 break;
7a387fff 3245 case 6:
7385ac0b 3246 check_insn(env, ctx, ASE_MT);
d9bea114 3247 gen_mfc0_load64(arg, offsetof(CPUState, CP0_VPEScheFBack));
7a387fff 3248 rn = "VPEScheFBack";
ead9360e 3249 break;
7a387fff 3250 case 7:
7385ac0b 3251 check_insn(env, ctx, ASE_MT);
d9bea114 3252 gen_mfc0_load32(arg, offsetof(CPUState, CP0_VPEOpt));
7a387fff 3253 rn = "VPEOpt";
ead9360e 3254 break;
7a387fff
TS
3255 default:
3256 goto die;
3257 }
873eb012
TS
3258 break;
3259 case 2:
7a387fff
TS
3260 switch (sel) {
3261 case 0:
d9bea114
AJ
3262 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_EntryLo0));
3263 tcg_gen_ext32s_tl(arg, arg);
2423f660
TS
3264 rn = "EntryLo0";
3265 break;
7a387fff 3266 case 1:
7385ac0b 3267 check_insn(env, ctx, ASE_MT);
d9bea114 3268 gen_helper_mfc0_tcstatus(arg);
2423f660 3269 rn = "TCStatus";
ead9360e 3270 break;
7a387fff 3271 case 2:
7385ac0b 3272 check_insn(env, ctx, ASE_MT);
d9bea114 3273 gen_helper_mfc0_tcbind(arg);
2423f660 3274 rn = "TCBind";
ead9360e 3275 break;
7a387fff 3276 case 3:
7385ac0b 3277 check_insn(env, ctx, ASE_MT);
d9bea114 3278 gen_helper_mfc0_tcrestart(arg);
2423f660 3279 rn = "TCRestart";
ead9360e 3280 break;
7a387fff 3281 case 4:
7385ac0b 3282 check_insn(env, ctx, ASE_MT);
d9bea114 3283 gen_helper_mfc0_tchalt(arg);
2423f660 3284 rn = "TCHalt";
ead9360e 3285 break;
7a387fff 3286 case 5:
7385ac0b 3287 check_insn(env, ctx, ASE_MT);
d9bea114 3288 gen_helper_mfc0_tccontext(arg);
2423f660 3289 rn = "TCContext";
ead9360e 3290 break;
7a387fff 3291 case 6:
7385ac0b 3292 check_insn(env, ctx, ASE_MT);
d9bea114 3293 gen_helper_mfc0_tcschedule(arg);
2423f660 3294 rn = "TCSchedule";
ead9360e 3295 break;
7a387fff 3296 case 7:
7385ac0b 3297 check_insn(env, ctx, ASE_MT);
d9bea114 3298 gen_helper_mfc0_tcschefback(arg);
2423f660 3299 rn = "TCScheFBack";
ead9360e 3300 break;
7a387fff
TS
3301 default:
3302 goto die;
3303 }
873eb012
TS
3304 break;
3305 case 3:
7a387fff
TS
3306 switch (sel) {
3307 case 0:
d9bea114
AJ
3308 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_EntryLo1));
3309 tcg_gen_ext32s_tl(arg, arg);
2423f660
TS
3310 rn = "EntryLo1";
3311 break;
7a387fff
TS
3312 default:
3313 goto die;
1579a72e 3314 }
873eb012
TS
3315 break;
3316 case 4:
7a387fff
TS
3317 switch (sel) {
3318 case 0:
d9bea114
AJ
3319 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_Context));
3320 tcg_gen_ext32s_tl(arg, arg);
2423f660
TS
3321 rn = "Context";
3322 break;
7a387fff 3323 case 1:
d9bea114 3324// gen_helper_mfc0_contextconfig(arg); /* SmartMIPS ASE */
2423f660
TS
3325 rn = "ContextConfig";
3326// break;
7a387fff
TS
3327 default:
3328 goto die;
1579a72e 3329 }
873eb012
TS
3330 break;
3331 case 5:
7a387fff
TS
3332 switch (sel) {
3333 case 0:
d9bea114 3334 gen_mfc0_load32(arg, offsetof(CPUState, CP0_PageMask));
2423f660
TS
3335 rn = "PageMask";
3336 break;
7a387fff 3337 case 1:
e189e748 3338 check_insn(env, ctx, ISA_MIPS32R2);
d9bea114 3339 gen_mfc0_load32(arg, offsetof(CPUState, CP0_PageGrain));
2423f660
TS
3340 rn = "PageGrain";
3341 break;
7a387fff
TS
3342 default:
3343 goto die;
1579a72e 3344 }
873eb012
TS
3345 break;
3346 case 6:
7a387fff
TS
3347 switch (sel) {
3348 case 0:
d9bea114 3349 gen_mfc0_load32(arg, offsetof(CPUState, CP0_Wired));
2423f660
TS
3350 rn = "Wired";
3351 break;
7a387fff 3352 case 1:
e189e748 3353 check_insn(env, ctx, ISA_MIPS32R2);
d9bea114 3354 gen_mfc0_load32(arg, offsetof(CPUState, CP0_SRSConf0));
2423f660 3355 rn = "SRSConf0";
ead9360e 3356 break;
7a387fff 3357 case 2:
e189e748 3358 check_insn(env, ctx, ISA_MIPS32R2);
d9bea114 3359 gen_mfc0_load32(arg, offsetof(CPUState, CP0_SRSConf1));
2423f660 3360 rn = "SRSConf1";
ead9360e 3361 break;
7a387fff 3362 case 3:
e189e748 3363 check_insn(env, ctx, ISA_MIPS32R2);
d9bea114 3364 gen_mfc0_load32(arg, offsetof(CPUState, CP0_SRSConf2));
2423f660 3365 rn = "SRSConf2";
ead9360e 3366 break;
7a387fff 3367 case 4:
e189e748 3368 check_insn(env, ctx, ISA_MIPS32R2);
d9bea114 3369 gen_mfc0_load32(arg, offsetof(CPUState, CP0_SRSConf3));
2423f660 3370 rn = "SRSConf3";
ead9360e 3371 break;
7a387fff 3372 case 5:
e189e748 3373 check_insn(env, ctx, ISA_MIPS32R2);
d9bea114 3374 gen_mfc0_load32(arg, offsetof(CPUState, CP0_SRSConf4));
2423f660 3375 rn = "SRSConf4";
ead9360e 3376 break;
7a387fff
TS
3377 default:
3378 goto die;
1579a72e 3379 }
873eb012 3380 break;
8c0fdd85 3381 case 7:
7a387fff
TS
3382 switch (sel) {
3383 case 0:
e189e748 3384 check_insn(env, ctx, ISA_MIPS32R2);
d9bea114 3385 gen_mfc0_load32(arg, offsetof(CPUState, CP0_HWREna));
2423f660
TS
3386 rn = "HWREna";
3387 break;
7a387fff
TS
3388 default:
3389 goto die;
1579a72e 3390 }
8c0fdd85 3391 break;
873eb012 3392 case 8:
7a387fff
TS
3393 switch (sel) {
3394 case 0:
d9bea114
AJ
3395 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_BadVAddr));
3396 tcg_gen_ext32s_tl(arg, arg);
f0b3f3ae 3397 rn = "BadVAddr";
2423f660 3398 break;
7a387fff
TS
3399 default:
3400 goto die;
3401 }
873eb012
TS
3402 break;
3403 case 9:
7a387fff
TS
3404 switch (sel) {
3405 case 0:
2e70f6ef
PB
3406 /* Mark as an IO operation because we read the time. */
3407 if (use_icount)
3408 gen_io_start();
d9bea114 3409 gen_helper_mfc0_count(arg);
2e70f6ef
PB
3410 if (use_icount) {
3411 gen_io_end();
2e70f6ef 3412 }
55807224
EI
3413 /* Break the TB to be able to take timer interrupts immediately
3414 after reading count. */
3415 ctx->bstate = BS_STOP;
2423f660
TS
3416 rn = "Count";
3417 break;
3418 /* 6,7 are implementation dependent */
7a387fff
TS
3419 default:
3420 goto die;
2423f660 3421 }
873eb012
TS
3422 break;
3423 case 10:
7a387fff
TS
3424 switch (sel) {
3425 case 0:
d9bea114
AJ
3426 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_EntryHi));
3427 tcg_gen_ext32s_tl(arg, arg);
2423f660
TS
3428 rn = "EntryHi";
3429 break;
7a387fff
TS
3430 default:
3431 goto die;
1579a72e 3432 }
873eb012
TS
3433 break;
3434 case 11:
7a387fff
TS
3435 switch (sel) {
3436 case 0:
d9bea114 3437 gen_mfc0_load32(arg, offsetof(CPUState, CP0_Compare));
2423f660
TS
3438 rn = "Compare";
3439 break;
3440 /* 6,7 are implementation dependent */
7a387fff
TS
3441 default:
3442 goto die;
2423f660 3443 }
873eb012
TS
3444 break;
3445 case 12:
7a387fff
TS
3446 switch (sel) {
3447 case 0:
d9bea114 3448 gen_mfc0_load32(arg, offsetof(CPUState, CP0_Status));
2423f660
TS
3449 rn = "Status";
3450 break;
7a387fff 3451 case 1:
e189e748 3452 check_insn(env, ctx, ISA_MIPS32R2);
d9bea114 3453 gen_mfc0_load32(arg, offsetof(CPUState, CP0_IntCtl));
2423f660
TS
3454 rn = "IntCtl";
3455 break;
7a387fff 3456 case 2:
e189e748 3457 check_insn(env, ctx, ISA_MIPS32R2);
d9bea114 3458 gen_mfc0_load32(arg, offsetof(CPUState, CP0_SRSCtl));
2423f660
TS
3459 rn = "SRSCtl";
3460 break;
7a387fff 3461 case 3:
e189e748 3462 check_insn(env, ctx, ISA_MIPS32R2);
d9bea114 3463 gen_mfc0_load32(arg, offsetof(CPUState, CP0_SRSMap));
2423f660 3464 rn = "SRSMap";
fd88b6ab 3465 break;
7a387fff
TS
3466 default:
3467 goto die;
3468 }
873eb012
TS
3469 break;
3470 case 13:
7a387fff
TS
3471 switch (sel) {
3472 case 0:
d9bea114 3473 gen_mfc0_load32(arg, offsetof(CPUState, CP0_Cause));
2423f660
TS
3474 rn = "Cause";
3475 break;
7a387fff
TS
3476 default:
3477 goto die;
3478 }
873eb012
TS
3479 break;
3480 case 14:
7a387fff
TS
3481 switch (sel) {
3482 case 0:
d9bea114
AJ
3483 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_EPC));
3484 tcg_gen_ext32s_tl(arg, arg);
2423f660
TS
3485 rn = "EPC";
3486 break;
7a387fff
TS
3487 default:
3488 goto die;
1579a72e 3489 }
873eb012
TS
3490 break;
3491 case 15:
7a387fff
TS
3492 switch (sel) {
3493 case 0:
d9bea114 3494 gen_mfc0_load32(arg, offsetof(CPUState, CP0_PRid));
2423f660
TS
3495 rn = "PRid";
3496 break;
7a387fff 3497 case 1:
e189e748 3498 check_insn(env, ctx, ISA_MIPS32R2);
d9bea114 3499 gen_mfc0_load32(arg, offsetof(CPUState, CP0_EBase));
2423f660
TS
3500 rn = "EBase";
3501 break;
7a387fff
TS
3502 default:
3503 goto die;
3504 }
873eb012
TS
3505 break;
3506 case 16:
3507 switch (sel) {
3508 case 0:
d9bea114 3509 gen_mfc0_load32(arg, offsetof(CPUState, CP0_Config0));
873eb012
TS
3510 rn = "Config";
3511 break;
3512 case 1:
d9bea114 3513 gen_mfc0_load32(arg, offsetof(CPUState, CP0_Config1));
873eb012
TS
3514 rn = "Config1";
3515 break;
7a387fff 3516 case 2:
d9bea114 3517 gen_mfc0_load32(arg, offsetof(CPUState, CP0_Config2));
7a387fff
TS
3518 rn = "Config2";
3519 break;
3520 case 3:
d9bea114 3521 gen_mfc0_load32(arg, offsetof(CPUState, CP0_Config3));
7a387fff
TS
3522 rn = "Config3";
3523 break;
e397ee33
TS
3524 /* 4,5 are reserved */
3525 /* 6,7 are implementation dependent */
3526 case 6:
d9bea114 3527 gen_mfc0_load32(arg, offsetof(CPUState, CP0_Config6));
e397ee33
TS
3528 rn = "Config6";
3529 break;
3530 case 7:
d9bea114 3531 gen_mfc0_load32(arg, offsetof(CPUState, CP0_Config7));
e397ee33
TS
3532 rn = "Config7";
3533 break;
873eb012 3534 default:
873eb012
TS
3535 goto die;
3536 }
3537 break;
3538 case 17:
7a387fff
TS
3539 switch (sel) {
3540 case 0:
d9bea114 3541 gen_helper_mfc0_lladdr(arg);
2423f660
TS
3542 rn = "LLAddr";
3543 break;
7a387fff
TS
3544 default:
3545 goto die;
3546 }
873eb012
TS
3547 break;
3548 case 18:
7a387fff 3549 switch (sel) {
fd88b6ab 3550 case 0 ... 7:
d9bea114 3551 gen_helper_1i(mfc0_watchlo, arg, sel);
2423f660
TS
3552 rn = "WatchLo";
3553 break;
7a387fff
TS
3554 default:
3555 goto die;
3556 }
873eb012
TS
3557 break;
3558 case 19:
7a387fff 3559 switch (sel) {
fd88b6ab 3560 case 0 ...7:
d9bea114 3561 gen_helper_1i(mfc0_watchhi, arg, sel);
2423f660
TS
3562 rn = "WatchHi";
3563 break;
7a387fff
TS
3564 default:
3565 goto die;
3566 }
873eb012 3567 break;
8c0fdd85 3568 case 20:
7a387fff
TS
3569 switch (sel) {
3570 case 0:
d26bc211 3571#if defined(TARGET_MIPS64)
e189e748 3572 check_insn(env, ctx, ISA_MIPS3);
d9bea114
AJ
3573 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_XContext));
3574 tcg_gen_ext32s_tl(arg, arg);
2423f660
TS
3575 rn = "XContext";
3576 break;
703eaf37 3577#endif
7a387fff
TS
3578 default:
3579 goto die;
3580 }
8c0fdd85
TS
3581 break;
3582 case 21:
7a387fff
TS
3583 /* Officially reserved, but sel 0 is used for R1x000 framemask */
3584 switch (sel) {
3585 case 0:
d9bea114 3586 gen_mfc0_load32(arg, offsetof(CPUState, CP0_Framemask));
2423f660
TS
3587 rn = "Framemask";
3588 break;
7a387fff
TS
3589 default:
3590 goto die;
3591 }
8c0fdd85
TS
3592 break;
3593 case 22:
d9bea114 3594 tcg_gen_movi_tl(arg, 0); /* unimplemented */
2423f660
TS
3595 rn = "'Diagnostic"; /* implementation dependent */
3596 break;
873eb012 3597 case 23:
7a387fff
TS
3598 switch (sel) {
3599 case 0:
d9bea114 3600 gen_helper_mfc0_debug(arg); /* EJTAG support */
2423f660
TS
3601 rn = "Debug";
3602 break;
7a387fff 3603 case 1:
d9bea114 3604// gen_helper_mfc0_tracecontrol(arg); /* PDtrace support */
2423f660
TS
3605 rn = "TraceControl";
3606// break;
7a387fff 3607 case 2:
d9bea114 3608// gen_helper_mfc0_tracecontrol2(arg); /* PDtrace support */
2423f660
TS
3609 rn = "TraceControl2";
3610// break;
7a387fff 3611 case 3:
d9bea114 3612// gen_helper_mfc0_usertracedata(arg); /* PDtrace support */
2423f660
TS
3613 rn = "UserTraceData";
3614// break;
7a387fff 3615 case 4:
d9bea114 3616// gen_helper_mfc0_tracebpc(arg); /* PDtrace support */
2423f660
TS
3617 rn = "TraceBPC";
3618// break;
7a387fff
TS
3619 default:
3620 goto die;
3621 }
873eb012
TS
3622 break;
3623 case 24:
7a387fff
TS
3624 switch (sel) {
3625 case 0:
f0b3f3ae 3626 /* EJTAG support */
d9bea114
AJ
3627 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_DEPC));
3628 tcg_gen_ext32s_tl(arg, arg);
2423f660
TS
3629 rn = "DEPC";
3630 break;
7a387fff
TS
3631 default:
3632 goto die;
3633 }
873eb012 3634 break;
8c0fdd85 3635 case 25:
7a387fff
TS
3636 switch (sel) {
3637 case 0:
d9bea114 3638 gen_mfc0_load32(arg, offsetof(CPUState, CP0_Performance0));
2423f660 3639 rn = "Performance0";
7a387fff
TS
3640 break;
3641 case 1:
d9bea114 3642// gen_helper_mfc0_performance1(arg);
2423f660
TS
3643 rn = "Performance1";
3644// break;
7a387fff 3645 case 2:
d9bea114 3646// gen_helper_mfc0_performance2(arg);
2423f660
TS
3647 rn = "Performance2";
3648// break;
7a387fff 3649 case 3:
d9bea114 3650// gen_helper_mfc0_performance3(arg);
2423f660
TS
3651 rn = "Performance3";
3652// break;
7a387fff 3653 case 4:
d9bea114 3654// gen_helper_mfc0_performance4(arg);
2423f660
TS
3655 rn = "Performance4";
3656// break;
7a387fff 3657 case 5:
d9bea114 3658// gen_helper_mfc0_performance5(arg);
2423f660
TS
3659 rn = "Performance5";
3660// break;
7a387fff 3661 case 6:
d9bea114 3662// gen_helper_mfc0_performance6(arg);
2423f660
TS
3663 rn = "Performance6";
3664// break;
7a387fff 3665 case 7:
d9bea114 3666// gen_helper_mfc0_performance7(arg);
2423f660
TS
3667 rn = "Performance7";
3668// break;
7a387fff
TS
3669 default:
3670 goto die;
3671 }
8c0fdd85
TS
3672 break;
3673 case 26:
d9bea114 3674 tcg_gen_movi_tl(arg, 0); /* unimplemented */
da80682b
AJ
3675 rn = "ECC";
3676 break;
8c0fdd85 3677 case 27:
7a387fff 3678 switch (sel) {
7a387fff 3679 case 0 ... 3:
d9bea114 3680 tcg_gen_movi_tl(arg, 0); /* unimplemented */
2423f660
TS
3681 rn = "CacheErr";
3682 break;
7a387fff
TS
3683 default:
3684 goto die;
3685 }
8c0fdd85 3686 break;
873eb012
TS
3687 case 28:
3688 switch (sel) {
3689 case 0:
7a387fff
TS
3690 case 2:
3691 case 4:
3692 case 6:
d9bea114 3693 gen_mfc0_load32(arg, offsetof(CPUState, CP0_TagLo));
873eb012
TS
3694 rn = "TagLo";
3695 break;
3696 case 1:
7a387fff
TS
3697 case 3:
3698 case 5:
3699 case 7:
d9bea114 3700 gen_mfc0_load32(arg, offsetof(CPUState, CP0_DataLo));
873eb012
TS
3701 rn = "DataLo";
3702 break;
3703 default:
873eb012
TS
3704 goto die;
3705 }
3706 break;
8c0fdd85 3707 case 29:
7a387fff
TS
3708 switch (sel) {
3709 case 0:
3710 case 2:
3711 case 4:
3712 case 6:
d9bea114 3713 gen_mfc0_load32(arg, offsetof(CPUState, CP0_TagHi));
7a387fff
TS
3714 rn = "TagHi";
3715 break;
3716 case 1:
3717 case 3:
3718 case 5:
3719 case 7:
d9bea114 3720 gen_mfc0_load32(arg, offsetof(CPUState, CP0_DataHi));
7a387fff
TS
3721 rn = "DataHi";
3722 break;
3723 default:
3724 goto die;
3725 }
8c0fdd85 3726 break;
873eb012 3727 case 30:
7a387fff
TS
3728 switch (sel) {
3729 case 0:
d9bea114
AJ
3730 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_ErrorEPC));
3731 tcg_gen_ext32s_tl(arg, arg);
2423f660
TS
3732 rn = "ErrorEPC";
3733 break;
7a387fff
TS
3734 default:
3735 goto die;
3736 }
873eb012
TS
3737 break;
3738 case 31:
7a387fff
TS
3739 switch (sel) {
3740 case 0:
f0b3f3ae 3741 /* EJTAG support */
d9bea114 3742 gen_mfc0_load32(arg, offsetof(CPUState, CP0_DESAVE));
2423f660
TS
3743 rn = "DESAVE";
3744 break;
7a387fff
TS
3745 default:
3746 goto die;
3747 }
873eb012
TS
3748 break;
3749 default:
873eb012
TS
3750 goto die;
3751 }
2abf314d 3752 (void)rn; /* avoid a compiler warning */
d12d51d5 3753 LOG_DISAS("mfc0 %s (reg %d sel %d)\n", rn, reg, sel);
873eb012
TS
3754 return;
3755
3756die:
d12d51d5 3757 LOG_DISAS("mfc0 %s (reg %d sel %d)\n", rn, reg, sel);
873eb012
TS
3758 generate_exception(ctx, EXCP_RI);
3759}
3760
d9bea114 3761static void gen_mtc0 (CPUState *env, DisasContext *ctx, TCGv arg, int reg, int sel)
8c0fdd85 3762{
7a387fff
TS
3763 const char *rn = "invalid";
3764
e189e748
TS
3765 if (sel != 0)
3766 check_insn(env, ctx, ISA_MIPS32);
3767
2e70f6ef
PB
3768 if (use_icount)
3769 gen_io_start();
3770
8c0fdd85
TS
3771 switch (reg) {
3772 case 0:
7a387fff
TS
3773 switch (sel) {
3774 case 0:
d9bea114 3775 gen_helper_mtc0_index(arg);
7a387fff
TS
3776 rn = "Index";
3777 break;
3778 case 1:
7385ac0b 3779 check_insn(env, ctx, ASE_MT);
d9bea114 3780 gen_helper_mtc0_mvpcontrol(arg);
7a387fff 3781 rn = "MVPControl";
ead9360e 3782 break;
7a387fff 3783 case 2:
7385ac0b 3784 check_insn(env, ctx, ASE_MT);
ead9360e 3785 /* ignored */
7a387fff 3786 rn = "MVPConf0";
ead9360e 3787 break;
7a387fff 3788 case 3:
7385ac0b 3789 check_insn(env, ctx, ASE_MT);
ead9360e 3790 /* ignored */
7a387fff 3791 rn = "MVPConf1";
ead9360e 3792 break;
7a387fff
TS
3793 default:
3794 goto die;
3795 }
8c0fdd85
TS
3796 break;
3797 case 1:
7a387fff
TS
3798 switch (sel) {
3799 case 0:
2423f660 3800 /* ignored */
7a387fff 3801 rn = "Random";
2423f660 3802 break;
7a387fff 3803 case 1:
7385ac0b 3804 check_insn(env, ctx, ASE_MT);
d9bea114 3805 gen_helper_mtc0_vpecontrol(arg);
7a387fff 3806 rn = "VPEControl";
ead9360e 3807 break;
7a387fff 3808 case 2:
7385ac0b 3809 check_insn(env, ctx, ASE_MT);
d9bea114 3810 gen_helper_mtc0_vpeconf0(arg);
7a387fff 3811 rn = "VPEConf0";
ead9360e 3812 break;
7a387fff 3813 case 3:
7385ac0b 3814 check_insn(env, ctx, ASE_MT);
d9bea114 3815 gen_helper_mtc0_vpeconf1(arg);
7a387fff 3816 rn = "VPEConf1";
ead9360e 3817 break;
7a387fff 3818 case 4:
7385ac0b 3819 check_insn(env, ctx, ASE_MT);
d9bea114 3820 gen_helper_mtc0_yqmask(arg);
7a387fff 3821 rn = "YQMask";
ead9360e 3822 break;
7a387fff 3823 case 5:
7385ac0b 3824 check_insn(env, ctx, ASE_MT);
d9bea114 3825 gen_mtc0_store64(arg, offsetof(CPUState, CP0_VPESchedule));
7a387fff 3826 rn = "VPESchedule";
ead9360e 3827 break;
7a387fff 3828 case 6:
7385ac0b 3829 check_insn(env, ctx, ASE_MT);
d9bea114 3830 gen_mtc0_store64(arg, offsetof(CPUState, CP0_VPEScheFBack));
7a387fff 3831 rn = "VPEScheFBack";
ead9360e 3832 break;
7a387fff 3833 case 7:
7385ac0b 3834 check_insn(env, ctx, ASE_MT);
d9bea114 3835 gen_helper_mtc0_vpeopt(arg);
7a387fff 3836 rn = "VPEOpt";
ead9360e 3837 break;
7a387fff
TS
3838 default:
3839 goto die;
3840 }
8c0fdd85
TS
3841 break;
3842 case 2:
7a387fff
TS
3843 switch (sel) {
3844 case 0:
d9bea114 3845 gen_helper_mtc0_entrylo0(arg);
2423f660
TS
3846 rn = "EntryLo0";
3847 break;
7a387fff 3848 case 1:
7385ac0b 3849 check_insn(env, ctx, ASE_MT);
d9bea114 3850 gen_helper_mtc0_tcstatus(arg);
2423f660 3851 rn = "TCStatus";
ead9360e 3852 break;
7a387fff 3853 case 2:
7385ac0b 3854 check_insn(env, ctx, ASE_MT);
d9bea114 3855 gen_helper_mtc0_tcbind(arg);
2423f660 3856 rn = "TCBind";
ead9360e 3857 break;
7a387fff 3858 case 3:
7385ac0b 3859 check_insn(env, ctx, ASE_MT);
d9bea114 3860 gen_helper_mtc0_tcrestart(arg);
2423f660 3861 rn = "TCRestart";
ead9360e 3862 break;
7a387fff 3863 case 4:
7385ac0b 3864 check_insn(env, ctx, ASE_MT);
d9bea114 3865 gen_helper_mtc0_tchalt(arg);
2423f660 3866 rn = "TCHalt";
ead9360e 3867 break;
7a387fff 3868 case 5:
7385ac0b 3869 check_insn(env, ctx, ASE_MT);
d9bea114 3870 gen_helper_mtc0_tccontext(arg);
2423f660 3871 rn = "TCContext";
ead9360e 3872 break;
7a387fff 3873 case 6:
7385ac0b 3874 check_insn(env, ctx, ASE_MT);
d9bea114 3875 gen_helper_mtc0_tcschedule(arg);
2423f660 3876 rn = "TCSchedule";
ead9360e 3877 break;
7a387fff 3878 case 7:
7385ac0b 3879 check_insn(env, ctx, ASE_MT);
d9bea114 3880 gen_helper_mtc0_tcschefback(arg);
2423f660 3881 rn = "TCScheFBack";
ead9360e 3882 break;
7a387fff
TS
3883 default:
3884 goto die;
3885 }
8c0fdd85
TS
3886 break;
3887 case 3:
7a387fff
TS
3888 switch (sel) {
3889 case 0:
d9bea114 3890 gen_helper_mtc0_entrylo1(arg);
2423f660
TS
3891 rn = "EntryLo1";
3892 break;
7a387fff
TS
3893 default:
3894 goto die;
876d4b07 3895 }
8c0fdd85
TS
3896 break;
3897 case 4:
7a387fff
TS
3898 switch (sel) {
3899 case 0:
d9bea114 3900 gen_helper_mtc0_context(arg);
2423f660
TS
3901 rn = "Context";
3902 break;
7a387fff 3903 case 1:
d9bea114 3904// gen_helper_mtc0_contextconfig(arg); /* SmartMIPS ASE */
2423f660
TS
3905 rn = "ContextConfig";
3906// break;
7a387fff
TS
3907 default:
3908 goto die;
876d4b07 3909 }
8c0fdd85
TS
3910 break;
3911 case 5:
7a387fff
TS
3912 switch (sel) {
3913 case 0:
d9bea114 3914 gen_helper_mtc0_pagemask(arg);
2423f660
TS
3915 rn = "PageMask";
3916 break;
7a387fff 3917 case 1:
e189e748 3918 check_insn(env, ctx, ISA_MIPS32R2);
d9bea114 3919 gen_helper_mtc0_pagegrain(arg);
2423f660
TS
3920 rn = "PageGrain";
3921 break;
7a387fff
TS
3922 default:
3923 goto die;
876d4b07 3924 }
8c0fdd85
TS
3925 break;
3926 case 6:
7a387fff
TS
3927 switch (sel) {
3928 case 0:
d9bea114 3929 gen_helper_mtc0_wired(arg);
2423f660
TS
3930 rn = "Wired";
3931 break;
7a387fff 3932 case 1:
e189e748 3933 check_insn(env, ctx, ISA_MIPS32R2);
d9bea114 3934 gen_helper_mtc0_srsconf0(arg);
2423f660 3935 rn = "SRSConf0";
ead9360e 3936 break;
7a387fff 3937 case 2:
e189e748 3938 check_insn(env, ctx, ISA_MIPS32R2);
d9bea114 3939 gen_helper_mtc0_srsconf1(arg);
2423f660 3940 rn = "SRSConf1";
ead9360e 3941 break;
7a387fff 3942 case 3:
e189e748 3943 check_insn(env, ctx, ISA_MIPS32R2);
d9bea114 3944 gen_helper_mtc0_srsconf2(arg);
2423f660 3945 rn = "SRSConf2";
ead9360e 3946 break;
7a387fff 3947 case 4:
e189e748 3948 check_insn(env, ctx, ISA_MIPS32R2);
d9bea114 3949 gen_helper_mtc0_srsconf3(arg);
2423f660 3950 rn = "SRSConf3";
ead9360e 3951 break;
7a387fff 3952 case 5:
e189e748 3953 check_insn(env, ctx, ISA_MIPS32R2);
d9bea114 3954 gen_helper_mtc0_srsconf4(arg);
2423f660 3955 rn = "SRSConf4";
ead9360e 3956 break;
7a387fff
TS
3957 default:
3958 goto die;
876d4b07 3959 }
8c0fdd85
TS
3960 break;
3961 case 7:
7a387fff
TS
3962 switch (sel) {
3963 case 0:
e189e748 3964 check_insn(env, ctx, ISA_MIPS32R2);
d9bea114 3965 gen_helper_mtc0_hwrena(arg);
2423f660
TS
3966 rn = "HWREna";
3967 break;
7a387fff
TS
3968 default:
3969 goto die;
876d4b07 3970 }
8c0fdd85
TS
3971 break;
3972 case 8:
7a387fff 3973 /* ignored */
f0b3f3ae 3974 rn = "BadVAddr";
8c0fdd85
TS
3975 break;
3976 case 9:
7a387fff
TS
3977 switch (sel) {
3978 case 0:
d9bea114 3979 gen_helper_mtc0_count(arg);
2423f660
TS
3980 rn = "Count";
3981 break;
876d4b07 3982 /* 6,7 are implementation dependent */
7a387fff
TS
3983 default:
3984 goto die;
876d4b07 3985 }
8c0fdd85
TS
3986 break;
3987 case 10:
7a387fff
TS
3988 switch (sel) {
3989 case 0:
d9bea114 3990 gen_helper_mtc0_entryhi(arg);
2423f660
TS
3991 rn = "EntryHi";
3992 break;
7a387fff
TS
3993 default:
3994 goto die;
876d4b07 3995 }
8c0fdd85
TS
3996 break;
3997 case 11:
7a387fff
TS
3998 switch (sel) {
3999 case 0:
d9bea114 4000 gen_helper_mtc0_compare(arg);
2423f660
TS
4001 rn = "Compare";
4002 break;
4003 /* 6,7 are implementation dependent */
7a387fff
TS
4004 default:
4005 goto die;
876d4b07 4006 }
8c0fdd85
TS
4007 break;
4008 case 12:
7a387fff
TS
4009 switch (sel) {
4010 case 0:
867abc7e 4011 save_cpu_state(ctx, 1);
d9bea114 4012 gen_helper_mtc0_status(arg);
8487327a
TS
4013 /* BS_STOP isn't good enough here, hflags may have changed. */
4014 gen_save_pc(ctx->pc + 4);
4015 ctx->bstate = BS_EXCP;
2423f660
TS
4016 rn = "Status";
4017 break;
7a387fff 4018 case 1:
e189e748 4019 check_insn(env, ctx, ISA_MIPS32R2);
d9bea114 4020 gen_helper_mtc0_intctl(arg);
8487327a
TS
4021 /* Stop translation as we may have switched the execution mode */
4022 ctx->bstate = BS_STOP;
2423f660
TS
4023 rn = "IntCtl";
4024 break;
7a387fff 4025 case 2:
e189e748 4026 check_insn(env, ctx, ISA_MIPS32R2);
d9bea114 4027 gen_helper_mtc0_srsctl(arg);
8487327a
TS
4028 /* Stop translation as we may have switched the execution mode */
4029 ctx->bstate = BS_STOP;
2423f660
TS
4030 rn = "SRSCtl";
4031 break;
7a387fff 4032 case 3:
e189e748 4033 check_insn(env, ctx, ISA_MIPS32R2);
d9bea114 4034 gen_mtc0_store32(arg, offsetof(CPUState, CP0_SRSMap));
8487327a
TS
4035 /* Stop translation as we may have switched the execution mode */
4036 ctx->bstate = BS_STOP;
2423f660 4037 rn = "SRSMap";
fd88b6ab 4038 break;
7a387fff
TS
4039 default:
4040 goto die;
876d4b07 4041 }
8c0fdd85
TS
4042 break;
4043 case 13:
7a387fff
TS
4044 switch (sel) {
4045 case 0:
867abc7e 4046 save_cpu_state(ctx, 1);
d9bea114 4047 gen_helper_mtc0_cause(arg);
2423f660
TS
4048 rn = "Cause";
4049 break;
7a387fff
TS
4050 default:
4051 goto die;
876d4b07 4052 }
8c0fdd85
TS
4053 break;
4054 case 14:
7a387fff
TS
4055 switch (sel) {
4056 case 0:
d9bea114 4057 gen_mtc0_store64(arg, offsetof(CPUState, CP0_EPC));
2423f660
TS
4058 rn = "EPC";
4059 break;
7a387fff
TS
4060 default:
4061 goto die;
876d4b07 4062 }
8c0fdd85
TS
4063 break;
4064 case 15:
7a387fff
TS
4065 switch (sel) {
4066 case 0:
2423f660
TS
4067 /* ignored */
4068 rn = "PRid";
4069 break;
7a387fff 4070 case 1:
e189e748 4071 check_insn(env, ctx, ISA_MIPS32R2);
d9bea114 4072 gen_helper_mtc0_ebase(arg);
2423f660
TS
4073 rn = "EBase";
4074 break;
7a387fff
TS
4075 default:
4076 goto die;
1579a72e 4077 }
8c0fdd85
TS
4078 break;
4079 case 16:
4080 switch (sel) {
4081 case 0:
d9bea114 4082 gen_helper_mtc0_config0(arg);
7a387fff 4083 rn = "Config";
2423f660
TS
4084 /* Stop translation as we may have switched the execution mode */
4085 ctx->bstate = BS_STOP;
7a387fff
TS
4086 break;
4087 case 1:
e397ee33 4088 /* ignored, read only */
7a387fff
TS
4089 rn = "Config1";
4090 break;
4091 case 2:
d9bea114 4092 gen_helper_mtc0_config2(arg);
7a387fff 4093 rn = "Config2";
2423f660
TS
4094 /* Stop translation as we may have switched the execution mode */
4095 ctx->bstate = BS_STOP;
8c0fdd85 4096 break;
7a387fff 4097 case 3:
e397ee33 4098 /* ignored, read only */
7a387fff
TS
4099 rn = "Config3";
4100 break;
e397ee33
TS
4101 /* 4,5 are reserved */
4102 /* 6,7 are implementation dependent */
4103 case 6:
4104 /* ignored */
4105 rn = "Config6";
4106 break;
4107 case 7:
4108 /* ignored */
4109 rn = "Config7";
4110 break;
8c0fdd85
TS
4111 default:
4112 rn = "Invalid config selector";
4113 goto die;
4114 }
4115 break;
4116 case 17:
7a387fff
TS
4117 switch (sel) {
4118 case 0:
2a6e32dd 4119 gen_helper_mtc0_lladdr(arg);
2423f660
TS
4120 rn = "LLAddr";
4121 break;
7a387fff
TS
4122 default:
4123 goto die;
4124 }
8c0fdd85
TS
4125 break;
4126 case 18:
7a387fff 4127 switch (sel) {
fd88b6ab 4128 case 0 ... 7:
d9bea114 4129 gen_helper_1i(mtc0_watchlo, arg, sel);
2423f660
TS
4130 rn = "WatchLo";
4131 break;
7a387fff
TS
4132 default:
4133 goto die;
4134 }
8c0fdd85
TS
4135 break;
4136 case 19:
7a387fff 4137 switch (sel) {
fd88b6ab 4138 case 0 ... 7:
d9bea114 4139 gen_helper_1i(mtc0_watchhi, arg, sel);
2423f660
TS
4140 rn = "WatchHi";
4141 break;
7a387fff
TS
4142 default:
4143 goto die;
4144 }
8c0fdd85
TS
4145 break;
4146 case 20:
7a387fff
TS
4147 switch (sel) {
4148 case 0:
d26bc211 4149#if defined(TARGET_MIPS64)
e189e748 4150 check_insn(env, ctx, ISA_MIPS3);
d9bea114 4151 gen_helper_mtc0_xcontext(arg);
2423f660
TS
4152 rn = "XContext";
4153 break;
703eaf37 4154#endif
7a387fff
TS
4155 default:
4156 goto die;
4157 }
8c0fdd85
TS
4158 break;
4159 case 21:
7a387fff
TS
4160 /* Officially reserved, but sel 0 is used for R1x000 framemask */
4161 switch (sel) {
4162 case 0:
d9bea114 4163 gen_helper_mtc0_framemask(arg);
2423f660
TS
4164 rn = "Framemask";
4165 break;
7a387fff
TS
4166 default:
4167 goto die;
4168 }
4169 break;
8c0fdd85 4170 case 22:
7a387fff
TS
4171 /* ignored */
4172 rn = "Diagnostic"; /* implementation dependent */
2423f660 4173 break;
8c0fdd85 4174 case 23:
7a387fff
TS
4175 switch (sel) {
4176 case 0:
d9bea114 4177 gen_helper_mtc0_debug(arg); /* EJTAG support */
8487327a
TS
4178 /* BS_STOP isn't good enough here, hflags may have changed. */
4179 gen_save_pc(ctx->pc + 4);
4180 ctx->bstate = BS_EXCP;
2423f660
TS
4181 rn = "Debug";
4182 break;
7a387fff 4183 case 1:
d9bea114 4184// gen_helper_mtc0_tracecontrol(arg); /* PDtrace support */
2423f660 4185 rn = "TraceControl";
8487327a
TS
4186 /* Stop translation as we may have switched the execution mode */
4187 ctx->bstate = BS_STOP;
2423f660 4188// break;
7a387fff 4189 case 2:
d9bea114 4190// gen_helper_mtc0_tracecontrol2(arg); /* PDtrace support */
2423f660 4191 rn = "TraceControl2";
8487327a
TS
4192 /* Stop translation as we may have switched the execution mode */
4193 ctx->bstate = BS_STOP;
2423f660 4194// break;
7a387fff 4195 case 3:
8487327a
TS
4196 /* Stop translation as we may have switched the execution mode */
4197 ctx->bstate = BS_STOP;
d9bea114 4198// gen_helper_mtc0_usertracedata(arg); /* PDtrace support */
2423f660 4199 rn = "UserTraceData";
8487327a
TS
4200 /* Stop translation as we may have switched the execution mode */
4201 ctx->bstate = BS_STOP;
2423f660 4202// break;
7a387fff 4203 case 4:
d9bea114 4204// gen_helper_mtc0_tracebpc(arg); /* PDtrace support */
8487327a
TS
4205 /* Stop translation as we may have switched the execution mode */
4206 ctx->bstate = BS_STOP;
2423f660
TS
4207 rn = "TraceBPC";
4208// break;
7a387fff
TS
4209 default:
4210 goto die;
4211 }
8c0fdd85
TS
4212 break;
4213 case 24:
7a387fff
TS
4214 switch (sel) {
4215 case 0:
f1aa6320 4216 /* EJTAG support */
d9bea114 4217 gen_mtc0_store64(arg, offsetof(CPUState, CP0_DEPC));
2423f660
TS
4218 rn = "DEPC";
4219 break;
7a387fff
TS
4220 default:
4221 goto die;
4222 }
8c0fdd85
TS
4223 break;
4224 case 25:
7a387fff
TS
4225 switch (sel) {
4226 case 0:
d9bea114 4227 gen_helper_mtc0_performance0(arg);
2423f660
TS
4228 rn = "Performance0";
4229 break;
7a387fff 4230 case 1:
d9bea114 4231// gen_helper_mtc0_performance1(arg);
2423f660
TS
4232 rn = "Performance1";
4233// break;
7a387fff 4234 case 2:
d9bea114 4235// gen_helper_mtc0_performance2(arg);
2423f660
TS
4236 rn = "Performance2";
4237// break;
7a387fff 4238 case 3:
d9bea114 4239// gen_helper_mtc0_performance3(arg);
2423f660
TS
4240 rn = "Performance3";
4241// break;
7a387fff 4242 case 4:
d9bea114 4243// gen_helper_mtc0_performance4(arg);
2423f660
TS
4244 rn = "Performance4";
4245// break;
7a387fff 4246 case 5:
d9bea114 4247// gen_helper_mtc0_performance5(arg);
2423f660
TS
4248 rn = "Performance5";
4249// break;
7a387fff 4250 case 6:
d9bea114 4251// gen_helper_mtc0_performance6(arg);
2423f660
TS
4252 rn = "Performance6";
4253// break;
7a387fff 4254 case 7:
d9bea114 4255// gen_helper_mtc0_performance7(arg);
2423f660
TS
4256 rn = "Performance7";
4257// break;
7a387fff
TS
4258 default:
4259 goto die;
4260 }
8c0fdd85
TS
4261 break;
4262 case 26:
2423f660 4263 /* ignored */
8c0fdd85 4264 rn = "ECC";
2423f660 4265 break;
8c0fdd85 4266 case 27:
7a387fff
TS
4267 switch (sel) {
4268 case 0 ... 3:
2423f660
TS
4269 /* ignored */
4270 rn = "CacheErr";
4271 break;
7a387fff
TS
4272 default:
4273 goto die;
4274 }
8c0fdd85
TS
4275 break;
4276 case 28:
4277 switch (sel) {
4278 case 0:
7a387fff
TS
4279 case 2:
4280 case 4:
4281 case 6:
d9bea114 4282 gen_helper_mtc0_taglo(arg);
8c0fdd85
TS
4283 rn = "TagLo";
4284 break;
7a387fff
TS
4285 case 1:
4286 case 3:
4287 case 5:
4288 case 7:
d9bea114 4289 gen_helper_mtc0_datalo(arg);
7a387fff
TS
4290 rn = "DataLo";
4291 break;
8c0fdd85 4292 default:
8c0fdd85
TS
4293 goto die;
4294 }
4295 break;
4296 case 29:
7a387fff
TS
4297 switch (sel) {
4298 case 0:
4299 case 2:
4300 case 4:
4301 case 6:
d9bea114 4302 gen_helper_mtc0_taghi(arg);
7a387fff
TS
4303 rn = "TagHi";
4304 break;
4305 case 1:
4306 case 3:
4307 case 5:
4308 case 7:
d9bea114 4309 gen_helper_mtc0_datahi(arg);
7a387fff
TS
4310 rn = "DataHi";
4311 break;
4312 default:
4313 rn = "invalid sel";
4314 goto die;
4315 }
8c0fdd85
TS
4316 break;
4317 case 30:
7a387fff
TS
4318 switch (sel) {
4319 case 0:
d9bea114 4320 gen_mtc0_store64(arg, offsetof(CPUState, CP0_ErrorEPC));
2423f660
TS
4321 rn = "ErrorEPC";
4322 break;
7a387fff
TS
4323 default:
4324 goto die;
4325 }
8c0fdd85
TS
4326 break;
4327 case 31:
7a387fff
TS
4328 switch (sel) {
4329 case 0:
f1aa6320 4330 /* EJTAG support */
d9bea114 4331 gen_mtc0_store32(arg, offsetof(CPUState, CP0_DESAVE));
2423f660
TS
4332 rn = "DESAVE";
4333 break;
7a387fff
TS
4334 default:
4335 goto die;
4336 }
2423f660
TS
4337 /* Stop translation as we may have switched the execution mode */
4338 ctx->bstate = BS_STOP;
8c0fdd85
TS
4339 break;
4340 default:
8c0fdd85
TS
4341 goto die;
4342 }
2abf314d 4343 (void)rn; /* avoid a compiler warning */
d12d51d5 4344 LOG_DISAS("mtc0 %s (reg %d sel %d)\n", rn, reg, sel);
bf20dc07 4345 /* For simplicity assume that all writes can cause interrupts. */
2e70f6ef
PB
4346 if (use_icount) {
4347 gen_io_end();
4348 ctx->bstate = BS_STOP;
4349 }
8c0fdd85
TS
4350 return;
4351
4352die:
d12d51d5 4353 LOG_DISAS("mtc0 %s (reg %d sel %d)\n", rn, reg, sel);
8c0fdd85
TS
4354 generate_exception(ctx, EXCP_RI);
4355}
4356
d26bc211 4357#if defined(TARGET_MIPS64)
d9bea114 4358static void gen_dmfc0 (CPUState *env, DisasContext *ctx, TCGv arg, int reg, int sel)
9c2149c8
TS
4359{
4360 const char *rn = "invalid";
4361
e189e748
TS
4362 if (sel != 0)
4363 check_insn(env, ctx, ISA_MIPS64);
4364
9c2149c8
TS
4365 switch (reg) {
4366 case 0:
4367 switch (sel) {
4368 case 0:
d9bea114 4369 gen_mfc0_load32(arg, offsetof(CPUState, CP0_Index));
9c2149c8
TS
4370 rn = "Index";
4371 break;
4372 case 1:
7385ac0b 4373 check_insn(env, ctx, ASE_MT);
d9bea114 4374 gen_helper_mfc0_mvpcontrol(arg);
9c2149c8 4375 rn = "MVPControl";
ead9360e 4376 break;
9c2149c8 4377 case 2:
7385ac0b 4378 check_insn(env, ctx, ASE_MT);
d9bea114 4379 gen_helper_mfc0_mvpconf0(arg);
9c2149c8 4380 rn = "MVPConf0";
ead9360e 4381 break;
9c2149c8 4382 case 3:
7385ac0b 4383 check_insn(env, ctx, ASE_MT);
d9bea114 4384 gen_helper_mfc0_mvpconf1(arg);
9c2149c8 4385 rn = "MVPConf1";
ead9360e 4386 break;
9c2149c8
TS
4387 default:
4388 goto die;
4389 }
4390 break;
4391 case 1:
4392 switch (sel) {
4393 case 0:
d9bea114 4394 gen_helper_mfc0_random(arg);
9c2149c8 4395 rn = "Random";
2423f660 4396 break;
9c2149c8 4397 case 1:
7385ac0b 4398 check_insn(env, ctx, ASE_MT);
d9bea114 4399 gen_mfc0_load32(arg, offsetof(CPUState, CP0_VPEControl));
9c2149c8 4400 rn = "VPEControl";
ead9360e 4401 break;
9c2149c8 4402 case 2:
7385ac0b 4403 check_insn(env, ctx, ASE_MT);
d9bea114 4404 gen_mfc0_load32(arg, offsetof(CPUState, CP0_VPEConf0));
9c2149c8 4405 rn = "VPEConf0";
ead9360e 4406 break;
9c2149c8 4407 case 3:
7385ac0b 4408 check_insn(env, ctx, ASE_MT);
d9bea114 4409 gen_mfc0_load32(arg, offsetof(CPUState, CP0_VPEConf1));
9c2149c8 4410 rn = "VPEConf1";
ead9360e 4411 break;
9c2149c8 4412 case 4:
7385ac0b 4413 check_insn(env, ctx, ASE_MT);
d9bea114 4414 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_YQMask));
9c2149c8 4415 rn = "YQMask";
ead9360e 4416 break;
9c2149c8 4417 case 5:
7385ac0b 4418 check_insn(env, ctx, ASE_MT);
d9bea114 4419 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_VPESchedule));
9c2149c8 4420 rn = "VPESchedule";
ead9360e 4421 break;
9c2149c8 4422 case 6:
7385ac0b 4423 check_insn(env, ctx, ASE_MT);
d9bea114 4424 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_VPEScheFBack));
9c2149c8 4425 rn = "VPEScheFBack";
ead9360e 4426 break;
9c2149c8 4427 case 7:
7385ac0b 4428 check_insn(env, ctx, ASE_MT);
d9bea114 4429 gen_mfc0_load32(arg, offsetof(CPUState, CP0_VPEOpt));
9c2149c8 4430 rn = "VPEOpt";
ead9360e 4431 break;
9c2149c8
TS
4432 default:
4433 goto die;
4434 }
4435 break;
4436 case 2:
4437 switch (sel) {
4438 case 0:
d9bea114 4439 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_EntryLo0));
2423f660
TS
4440 rn = "EntryLo0";
4441 break;
9c2149c8 4442 case 1:
7385ac0b 4443 check_insn(env, ctx, ASE_MT);
d9bea114 4444 gen_helper_mfc0_tcstatus(arg);
2423f660 4445 rn = "TCStatus";
ead9360e 4446 break;
9c2149c8 4447 case 2:
7385ac0b 4448 check_insn(env, ctx, ASE_MT);
d9bea114 4449 gen_helper_mfc0_tcbind(arg);
2423f660 4450 rn = "TCBind";
ead9360e 4451 break;
9c2149c8 4452 case 3:
7385ac0b 4453 check_insn(env, ctx, ASE_MT);
d9bea114 4454 gen_helper_dmfc0_tcrestart(arg);
2423f660 4455 rn = "TCRestart";
ead9360e 4456 break;
9c2149c8 4457 case 4:
7385ac0b 4458 check_insn(env, ctx, ASE_MT);
d9bea114 4459 gen_helper_dmfc0_tchalt(arg);
2423f660 4460 rn = "TCHalt";
ead9360e 4461 break;
9c2149c8 4462 case 5:
7385ac0b 4463 check_insn(env, ctx, ASE_MT);
d9bea114 4464 gen_helper_dmfc0_tccontext(arg);
2423f660 4465 rn = "TCContext";
ead9360e 4466 break;
9c2149c8 4467 case 6:
7385ac0b 4468 check_insn(env, ctx, ASE_MT);
d9bea114 4469 gen_helper_dmfc0_tcschedule(arg);
2423f660 4470 rn = "TCSchedule";
ead9360e 4471 break;
9c2149c8 4472 case 7:
7385ac0b 4473 check_insn(env, ctx, ASE_MT);
d9bea114 4474 gen_helper_dmfc0_tcschefback(arg);
2423f660 4475 rn = "TCScheFBack";
ead9360e 4476 break;
9c2149c8
TS
4477 default:
4478 goto die;
4479 }
4480 break;
4481 case 3:
4482 switch (sel) {
4483 case 0:
d9bea114 4484 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_EntryLo1));
2423f660
TS
4485 rn = "EntryLo1";
4486 break;
9c2149c8
TS
4487 default:
4488 goto die;
1579a72e 4489 }
9c2149c8
TS
4490 break;
4491 case 4:
4492 switch (sel) {
4493 case 0:
d9bea114 4494 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_Context));
2423f660
TS
4495 rn = "Context";
4496 break;
9c2149c8 4497 case 1:
d9bea114 4498// gen_helper_dmfc0_contextconfig(arg); /* SmartMIPS ASE */
2423f660
TS
4499 rn = "ContextConfig";
4500// break;
9c2149c8
TS
4501 default:
4502 goto die;
876d4b07 4503 }
9c2149c8
TS
4504 break;
4505 case 5:
4506 switch (sel) {
4507 case 0:
d9bea114 4508 gen_mfc0_load32(arg, offsetof(CPUState, CP0_PageMask));
2423f660
TS
4509 rn = "PageMask";
4510 break;
9c2149c8 4511 case 1:
e189e748 4512 check_insn(env, ctx, ISA_MIPS32R2);
d9bea114 4513 gen_mfc0_load32(arg, offsetof(CPUState, CP0_PageGrain));
2423f660
TS
4514 rn = "PageGrain";
4515 break;
9c2149c8
TS
4516 default:
4517 goto die;
876d4b07 4518 }
9c2149c8
TS
4519 break;
4520 case 6:
4521 switch (sel) {
4522 case 0:
d9bea114 4523 gen_mfc0_load32(arg, offsetof(CPUState, CP0_Wired));
2423f660
TS
4524 rn = "Wired";
4525 break;
9c2149c8 4526 case 1:
e189e748 4527 check_insn(env, ctx, ISA_MIPS32R2);
d9bea114 4528 gen_mfc0_load32(arg, offsetof(CPUState, CP0_SRSConf0));
2423f660 4529 rn = "SRSConf0";
ead9360e 4530 break;
9c2149c8 4531 case 2:
e189e748 4532 check_insn(env, ctx, ISA_MIPS32R2);
d9bea114 4533 gen_mfc0_load32(arg, offsetof(CPUState, CP0_SRSConf1));
2423f660 4534 rn = "SRSConf1";
ead9360e 4535 break;
9c2149c8 4536 case 3:
e189e748 4537 check_insn(env, ctx, ISA_MIPS32R2);
d9bea114 4538 gen_mfc0_load32(arg, offsetof(CPUState, CP0_SRSConf2));
2423f660 4539 rn = "SRSConf2";
ead9360e 4540 break;
9c2149c8 4541 case 4:
e189e748 4542 check_insn(env, ctx, ISA_MIPS32R2);
d9bea114 4543 gen_mfc0_load32(arg, offsetof(CPUState, CP0_SRSConf3));
2423f660 4544 rn = "SRSConf3";
ead9360e 4545 break;
9c2149c8 4546 case 5:
e189e748 4547 check_insn(env, ctx, ISA_MIPS32R2);
d9bea114 4548 gen_mfc0_load32(arg, offsetof(CPUState, CP0_SRSConf4));
2423f660 4549 rn = "SRSConf4";
ead9360e 4550 break;
9c2149c8
TS
4551 default:
4552 goto die;
876d4b07 4553 }
9c2149c8
TS
4554 break;
4555 case 7:
4556 switch (sel) {
4557 case 0:
e189e748 4558 check_insn(env, ctx, ISA_MIPS32R2);
d9bea114 4559 gen_mfc0_load32(arg, offsetof(CPUState, CP0_HWREna));
2423f660
TS
4560 rn = "HWREna";
4561 break;
9c2149c8
TS
4562 default:
4563 goto die;
876d4b07 4564 }
9c2149c8
TS
4565 break;
4566 case 8:
4567 switch (sel) {
4568 case 0:
d9bea114 4569 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_BadVAddr));
f0b3f3ae 4570 rn = "BadVAddr";
2423f660 4571 break;
9c2149c8
TS
4572 default:
4573 goto die;
876d4b07 4574 }
9c2149c8
TS
4575 break;
4576 case 9:
4577 switch (sel) {
4578 case 0:
2e70f6ef
PB
4579 /* Mark as an IO operation because we read the time. */
4580 if (use_icount)
4581 gen_io_start();
d9bea114 4582 gen_helper_mfc0_count(arg);
2e70f6ef
PB
4583 if (use_icount) {
4584 gen_io_end();
2e70f6ef 4585 }
55807224
EI
4586 /* Break the TB to be able to take timer interrupts immediately
4587 after reading count. */
4588 ctx->bstate = BS_STOP;
2423f660
TS
4589 rn = "Count";
4590 break;
4591 /* 6,7 are implementation dependent */
9c2149c8
TS
4592 default:
4593 goto die;
876d4b07 4594 }
9c2149c8
TS
4595 break;
4596 case 10:
4597 switch (sel) {
4598 case 0:
d9bea114 4599 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_EntryHi));
2423f660
TS
4600 rn = "EntryHi";
4601 break;
9c2149c8
TS
4602 default:
4603 goto die;
876d4b07 4604 }
9c2149c8
TS
4605 break;
4606 case 11:
4607 switch (sel) {
4608 case 0:
d9bea114 4609 gen_mfc0_load32(arg, offsetof(CPUState, CP0_Compare));
2423f660
TS
4610 rn = "Compare";
4611 break;
876d4b07 4612 /* 6,7 are implementation dependent */
9c2149c8
TS
4613 default:
4614 goto die;
876d4b07 4615 }
9c2149c8
TS
4616 break;
4617 case 12:
4618 switch (sel) {
4619 case 0:
d9bea114 4620 gen_mfc0_load32(arg, offsetof(CPUState, CP0_Status));
2423f660
TS
4621 rn = "Status";
4622 break;
9c2149c8 4623 case 1:
e189e748 4624 check_insn(env, ctx, ISA_MIPS32R2);
d9bea114 4625 gen_mfc0_load32(arg, offsetof(CPUState, CP0_IntCtl));
2423f660
TS
4626 rn = "IntCtl";
4627 break;
9c2149c8 4628 case 2:
e189e748 4629 check_insn(env, ctx, ISA_MIPS32R2);
d9bea114 4630 gen_mfc0_load32(arg, offsetof(CPUState, CP0_SRSCtl));
2423f660
TS
4631 rn = "SRSCtl";
4632 break;
9c2149c8 4633 case 3:
e189e748 4634 check_insn(env, ctx, ISA_MIPS32R2);
d9bea114 4635 gen_mfc0_load32(arg, offsetof(CPUState, CP0_SRSMap));
2423f660
TS
4636 rn = "SRSMap";
4637 break;
9c2149c8
TS
4638 default:
4639 goto die;
876d4b07 4640 }
9c2149c8
TS
4641 break;
4642 case 13:
4643 switch (sel) {
4644 case 0:
d9bea114 4645 gen_mfc0_load32(arg, offsetof(CPUState, CP0_Cause));
2423f660
TS
4646 rn = "Cause";
4647 break;
9c2149c8
TS
4648 default:
4649 goto die;
876d4b07 4650 }
9c2149c8
TS
4651 break;
4652 case 14:
4653 switch (sel) {
4654 case 0:
d9bea114 4655 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_EPC));
2423f660
TS
4656 rn = "EPC";
4657 break;
9c2149c8
TS
4658 default:
4659 goto die;
876d4b07 4660 }
9c2149c8
TS
4661 break;
4662 case 15:
4663 switch (sel) {
4664 case 0:
d9bea114 4665 gen_mfc0_load32(arg, offsetof(CPUState, CP0_PRid));
2423f660
TS
4666 rn = "PRid";
4667 break;
9c2149c8 4668 case 1:
e189e748 4669 check_insn(env, ctx, ISA_MIPS32R2);
d9bea114 4670 gen_mfc0_load32(arg, offsetof(CPUState, CP0_EBase));
2423f660
TS
4671 rn = "EBase";
4672 break;
9c2149c8
TS
4673 default:
4674 goto die;
876d4b07 4675 }
9c2149c8
TS
4676 break;
4677 case 16:
4678 switch (sel) {
4679 case 0:
d9bea114 4680 gen_mfc0_load32(arg, offsetof(CPUState, CP0_Config0));
9c2149c8
TS
4681 rn = "Config";
4682 break;
4683 case 1:
d9bea114 4684 gen_mfc0_load32(arg, offsetof(CPUState, CP0_Config1));
9c2149c8
TS
4685 rn = "Config1";
4686 break;
4687 case 2:
d9bea114 4688 gen_mfc0_load32(arg, offsetof(CPUState, CP0_Config2));
9c2149c8
TS
4689 rn = "Config2";
4690 break;
4691 case 3:
d9bea114 4692 gen_mfc0_load32(arg, offsetof(CPUState, CP0_Config3));
9c2149c8
TS
4693 rn = "Config3";
4694 break;
4695 /* 6,7 are implementation dependent */
f0b3f3ae 4696 case 6:
d9bea114 4697 gen_mfc0_load32(arg, offsetof(CPUState, CP0_Config6));
f0b3f3ae
TS
4698 rn = "Config6";
4699 break;
4700 case 7:
d9bea114 4701 gen_mfc0_load32(arg, offsetof(CPUState, CP0_Config7));
f0b3f3ae
TS
4702 rn = "Config7";
4703 break;
9c2149c8
TS
4704 default:
4705 goto die;
4706 }
4707 break;
4708 case 17:
4709 switch (sel) {
4710 case 0:
d9bea114 4711 gen_helper_dmfc0_lladdr(arg);
2423f660
TS
4712 rn = "LLAddr";
4713 break;
9c2149c8
TS
4714 default:
4715 goto die;
4716 }
4717 break;
4718 case 18:
4719 switch (sel) {
fd88b6ab 4720 case 0 ... 7:
d9bea114 4721 gen_helper_1i(dmfc0_watchlo, arg, sel);
2423f660
TS
4722 rn = "WatchLo";
4723 break;
9c2149c8
TS
4724 default:
4725 goto die;
4726 }
4727 break;
4728 case 19:
4729 switch (sel) {
fd88b6ab 4730 case 0 ... 7:
d9bea114 4731 gen_helper_1i(mfc0_watchhi, arg, sel);
2423f660
TS
4732 rn = "WatchHi";
4733 break;
9c2149c8
TS
4734 default:
4735 goto die;
4736 }
4737 break;
4738 case 20:
4739 switch (sel) {
4740 case 0:
e189e748 4741 check_insn(env, ctx, ISA_MIPS3);
d9bea114 4742 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_XContext));
2423f660
TS
4743 rn = "XContext";
4744 break;
9c2149c8
TS
4745 default:
4746 goto die;
4747 }
4748 break;
4749 case 21:
4750 /* Officially reserved, but sel 0 is used for R1x000 framemask */
4751 switch (sel) {
4752 case 0:
d9bea114 4753 gen_mfc0_load32(arg, offsetof(CPUState, CP0_Framemask));
2423f660
TS
4754 rn = "Framemask";
4755 break;
9c2149c8
TS
4756 default:
4757 goto die;
4758 }
4759 break;
4760 case 22:
d9bea114 4761 tcg_gen_movi_tl(arg, 0); /* unimplemented */
2423f660
TS
4762 rn = "'Diagnostic"; /* implementation dependent */
4763 break;
9c2149c8
TS
4764 case 23:
4765 switch (sel) {
4766 case 0:
d9bea114 4767 gen_helper_mfc0_debug(arg); /* EJTAG support */
2423f660
TS
4768 rn = "Debug";
4769 break;
9c2149c8 4770 case 1:
d9bea114 4771// gen_helper_dmfc0_tracecontrol(arg); /* PDtrace support */
2423f660
TS
4772 rn = "TraceControl";
4773// break;
9c2149c8 4774 case 2:
d9bea114 4775// gen_helper_dmfc0_tracecontrol2(arg); /* PDtrace support */
2423f660
TS
4776 rn = "TraceControl2";
4777// break;
9c2149c8 4778 case 3:
d9bea114 4779// gen_helper_dmfc0_usertracedata(arg); /* PDtrace support */
2423f660
TS
4780 rn = "UserTraceData";
4781// break;
9c2149c8 4782 case 4:
d9bea114 4783// gen_helper_dmfc0_tracebpc(arg); /* PDtrace support */
2423f660
TS
4784 rn = "TraceBPC";
4785// break;
9c2149c8
TS
4786 default:
4787 goto die;
4788 }
4789 break;
4790 case 24:
4791 switch (sel) {
4792 case 0:
f0b3f3ae 4793 /* EJTAG support */
d9bea114 4794 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_DEPC));
2423f660
TS
4795 rn = "DEPC";
4796 break;
9c2149c8
TS
4797 default:
4798 goto die;
4799 }
4800 break;
4801 case 25:
4802 switch (sel) {
4803 case 0:
d9bea114 4804 gen_mfc0_load32(arg, offsetof(CPUState, CP0_Performance0));
2423f660 4805 rn = "Performance0";
9c2149c8
TS
4806 break;
4807 case 1:
d9bea114 4808// gen_helper_dmfc0_performance1(arg);
2423f660
TS
4809 rn = "Performance1";
4810// break;
9c2149c8 4811 case 2:
d9bea114 4812// gen_helper_dmfc0_performance2(arg);
2423f660
TS
4813 rn = "Performance2";
4814// break;
9c2149c8 4815 case 3:
d9bea114 4816// gen_helper_dmfc0_performance3(arg);
2423f660
TS
4817 rn = "Performance3";
4818// break;
9c2149c8 4819 case 4:
d9bea114 4820// gen_helper_dmfc0_performance4(arg);
2423f660
TS
4821 rn = "Performance4";
4822// break;
9c2149c8 4823 case 5:
d9bea114 4824// gen_helper_dmfc0_performance5(arg);
2423f660
TS
4825 rn = "Performance5";
4826// break;
9c2149c8 4827 case 6:
d9bea114 4828// gen_helper_dmfc0_performance6(arg);
2423f660
TS
4829 rn = "Performance6";
4830// break;
9c2149c8 4831 case 7:
d9bea114 4832// gen_helper_dmfc0_performance7(arg);
2423f660
TS
4833 rn = "Performance7";
4834// break;
9c2149c8
TS
4835 default:
4836 goto die;
4837 }
4838 break;
4839 case 26:
d9bea114 4840 tcg_gen_movi_tl(arg, 0); /* unimplemented */
da80682b
AJ
4841 rn = "ECC";
4842 break;
9c2149c8
TS
4843 case 27:
4844 switch (sel) {
4845 /* ignored */
4846 case 0 ... 3:
d9bea114 4847 tcg_gen_movi_tl(arg, 0); /* unimplemented */
2423f660
TS
4848 rn = "CacheErr";
4849 break;
9c2149c8
TS
4850 default:
4851 goto die;
4852 }
4853 break;
4854 case 28:
4855 switch (sel) {
4856 case 0:
4857 case 2:
4858 case 4:
4859 case 6:
d9bea114 4860 gen_mfc0_load32(arg, offsetof(CPUState, CP0_TagLo));
9c2149c8
TS
4861 rn = "TagLo";
4862 break;
4863 case 1:
4864 case 3:
4865 case 5:
4866 case 7:
d9bea114 4867 gen_mfc0_load32(arg, offsetof(CPUState, CP0_DataLo));
9c2149c8
TS
4868 rn = "DataLo";
4869 break;
4870 default:
4871 goto die;
4872 }
4873 break;
4874 case 29:
4875 switch (sel) {
4876 case 0:
4877 case 2:
4878 case 4:
4879 case 6:
d9bea114 4880 gen_mfc0_load32(arg, offsetof(CPUState, CP0_TagHi));
9c2149c8
TS
4881 rn = "TagHi";
4882 break;
4883 case 1:
4884 case 3:
4885 case 5:
4886 case 7:
d9bea114 4887 gen_mfc0_load32(arg, offsetof(CPUState, CP0_DataHi));
9c2149c8
TS
4888 rn = "DataHi";
4889 break;
4890 default:
4891 goto die;
4892 }
4893 break;
4894 case 30:
4895 switch (sel) {
4896 case 0:
d9bea114 4897 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_ErrorEPC));
2423f660
TS
4898 rn = "ErrorEPC";
4899 break;
9c2149c8
TS
4900 default:
4901 goto die;
4902 }
4903 break;
4904 case 31:
4905 switch (sel) {
4906 case 0:
f0b3f3ae 4907 /* EJTAG support */
d9bea114 4908 gen_mfc0_load32(arg, offsetof(CPUState, CP0_DESAVE));
2423f660
TS
4909 rn = "DESAVE";
4910 break;
9c2149c8
TS
4911 default:
4912 goto die;
4913 }
4914 break;
4915 default:
876d4b07 4916 goto die;
9c2149c8 4917 }
2abf314d 4918 (void)rn; /* avoid a compiler warning */
d12d51d5 4919 LOG_DISAS("dmfc0 %s (reg %d sel %d)\n", rn, reg, sel);
9c2149c8
TS
4920 return;
4921
4922die:
d12d51d5 4923 LOG_DISAS("dmfc0 %s (reg %d sel %d)\n", rn, reg, sel);
9c2149c8
TS
4924 generate_exception(ctx, EXCP_RI);
4925}
4926
d9bea114 4927static void gen_dmtc0 (CPUState *env, DisasContext *ctx, TCGv arg, int reg, int sel)
9c2149c8
TS
4928{
4929 const char *rn = "invalid";
4930
e189e748
TS
4931 if (sel != 0)
4932 check_insn(env, ctx, ISA_MIPS64);
4933
2e70f6ef
PB
4934 if (use_icount)
4935 gen_io_start();
4936
9c2149c8
TS
4937 switch (reg) {
4938 case 0:
4939 switch (sel) {
4940 case 0:
d9bea114 4941 gen_helper_mtc0_index(arg);
9c2149c8
TS
4942 rn = "Index";
4943 break;
4944 case 1:
7385ac0b 4945 check_insn(env, ctx, ASE_MT);
d9bea114 4946 gen_helper_mtc0_mvpcontrol(arg);
9c2149c8 4947 rn = "MVPControl";
ead9360e 4948 break;
9c2149c8 4949 case 2:
7385ac0b 4950 check_insn(env, ctx, ASE_MT);
ead9360e 4951 /* ignored */
9c2149c8 4952 rn = "MVPConf0";
ead9360e 4953 break;
9c2149c8 4954 case 3:
7385ac0b 4955 check_insn(env, ctx, ASE_MT);
ead9360e 4956 /* ignored */
9c2149c8 4957 rn = "MVPConf1";
ead9360e 4958 break;
9c2149c8
TS
4959 default:
4960 goto die;
4961 }
4962 break;
4963 case 1:
4964 switch (sel) {
4965 case 0:
2423f660 4966 /* ignored */
9c2149c8 4967 rn = "Random";
2423f660 4968 break;
9c2149c8 4969 case 1:
7385ac0b 4970 check_insn(env, ctx, ASE_MT);
d9bea114 4971 gen_helper_mtc0_vpecontrol(arg);
9c2149c8 4972 rn = "VPEControl";
ead9360e 4973 break;
9c2149c8 4974 case 2:
7385ac0b 4975 check_insn(env, ctx, ASE_MT);
d9bea114 4976 gen_helper_mtc0_vpeconf0(arg);
9c2149c8 4977 rn = "VPEConf0";
ead9360e 4978 break;
9c2149c8 4979 case 3:
7385ac0b 4980 check_insn(env, ctx, ASE_MT);
d9bea114 4981 gen_helper_mtc0_vpeconf1(arg);
9c2149c8 4982 rn = "VPEConf1";
ead9360e 4983 break;
9c2149c8 4984 case 4:
7385ac0b 4985 check_insn(env, ctx, ASE_MT);
d9bea114 4986 gen_helper_mtc0_yqmask(arg);
9c2149c8 4987 rn = "YQMask";
ead9360e 4988 break;
9c2149c8 4989 case 5:
7385ac0b 4990 check_insn(env, ctx, ASE_MT);
d9bea114 4991 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUState, CP0_VPESchedule));
9c2149c8 4992 rn = "VPESchedule";
ead9360e 4993 break;
9c2149c8 4994 case 6:
7385ac0b 4995 check_insn(env, ctx, ASE_MT);
d9bea114 4996 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUState, CP0_VPEScheFBack));
9c2149c8 4997 rn = "VPEScheFBack";
ead9360e 4998 break;
9c2149c8 4999 case 7:
7385ac0b 5000 check_insn(env, ctx, ASE_MT);
d9bea114 5001 gen_helper_mtc0_vpeopt(arg);
9c2149c8 5002 rn = "VPEOpt";
ead9360e 5003 break;
9c2149c8
TS
5004 default:
5005 goto die;
5006 }
5007 break;
5008 case 2:
5009 switch (sel) {
5010 case 0:
d9bea114 5011 gen_helper_mtc0_entrylo0(arg);
2423f660
TS
5012 rn = "EntryLo0";
5013 break;
9c2149c8 5014 case 1:
7385ac0b 5015 check_insn(env, ctx, ASE_MT);
d9bea114 5016 gen_helper_mtc0_tcstatus(arg);
2423f660 5017 rn = "TCStatus";
ead9360e 5018 break;
9c2149c8 5019 case 2:
7385ac0b 5020 check_insn(env, ctx, ASE_MT);
d9bea114 5021 gen_helper_mtc0_tcbind(arg);
2423f660 5022 rn = "TCBind";
ead9360e 5023 break;
9c2149c8 5024 case 3:
7385ac0b 5025 check_insn(env, ctx, ASE_MT);
d9bea114 5026 gen_helper_mtc0_tcrestart(arg);
2423f660 5027 rn = "TCRestart";
ead9360e 5028 break;
9c2149c8 5029 case 4:
7385ac0b 5030 check_insn(env, ctx, ASE_MT);
d9bea114 5031 gen_helper_mtc0_tchalt(arg);
2423f660 5032 rn = "TCHalt";
ead9360e 5033 break;
9c2149c8 5034 case 5:
7385ac0b 5035 check_insn(env, ctx, ASE_MT);
d9bea114 5036 gen_helper_mtc0_tccontext(arg);
2423f660 5037 rn = "TCContext";
ead9360e 5038 break;
9c2149c8 5039 case 6:
7385ac0b 5040 check_insn(env, ctx, ASE_MT);
d9bea114 5041 gen_helper_mtc0_tcschedule(arg);
2423f660 5042 rn = "TCSchedule";
ead9360e 5043 break;
9c2149c8 5044 case 7:
7385ac0b 5045 check_insn(env, ctx, ASE_MT);
d9bea114 5046 gen_helper_mtc0_tcschefback(arg);
2423f660 5047 rn = "TCScheFBack";
ead9360e 5048 break;
9c2149c8
TS
5049 default:
5050 goto die;
5051 }
5052 break;
5053 case 3:
5054 switch (sel) {
5055 case 0:
d9bea114 5056 gen_helper_mtc0_entrylo1(arg);
2423f660
TS
5057 rn = "EntryLo1";
5058 break;
9c2149c8
TS
5059 default:
5060 goto die;
876d4b07 5061 }
9c2149c8
TS
5062 break;
5063 case 4:
5064 switch (sel) {
5065 case 0:
d9bea114 5066 gen_helper_mtc0_context(arg);
2423f660
TS
5067 rn = "Context";
5068 break;
9c2149c8 5069 case 1:
d9bea114 5070// gen_helper_mtc0_contextconfig(arg); /* SmartMIPS ASE */
2423f660
TS
5071 rn = "ContextConfig";
5072// break;
9c2149c8
TS
5073 default:
5074 goto die;
876d4b07 5075 }
9c2149c8
TS
5076 break;
5077 case 5:
5078 switch (sel) {
5079 case 0:
d9bea114 5080 gen_helper_mtc0_pagemask(arg);
2423f660
TS
5081 rn = "PageMask";
5082 break;
9c2149c8 5083 case 1:
e189e748 5084 check_insn(env, ctx, ISA_MIPS32R2);
d9bea114 5085 gen_helper_mtc0_pagegrain(arg);
2423f660
TS
5086 rn = "PageGrain";
5087 break;
9c2149c8
TS
5088 default:
5089 goto die;
876d4b07 5090 }
9c2149c8
TS
5091 break;
5092 case 6:
5093 switch (sel) {
5094 case 0:
d9bea114 5095 gen_helper_mtc0_wired(arg);
2423f660
TS
5096 rn = "Wired";
5097 break;
9c2149c8 5098 case 1:
e189e748 5099 check_insn(env, ctx, ISA_MIPS32R2);
d9bea114 5100 gen_helper_mtc0_srsconf0(arg);
2423f660 5101 rn = "SRSConf0";
ead9360e 5102 break;
9c2149c8 5103 case 2:
e189e748 5104 check_insn(env, ctx, ISA_MIPS32R2);
d9bea114 5105 gen_helper_mtc0_srsconf1(arg);
2423f660 5106 rn = "SRSConf1";
ead9360e 5107 break;
9c2149c8 5108 case 3:
e189e748 5109 check_insn(env, ctx, ISA_MIPS32R2);
d9bea114 5110 gen_helper_mtc0_srsconf2(arg);
2423f660 5111 rn = "SRSConf2";
ead9360e 5112 break;
9c2149c8 5113 case 4:
e189e748 5114 check_insn(env, ctx, ISA_MIPS32R2);
d9bea114 5115 gen_helper_mtc0_srsconf3(arg);
2423f660 5116 rn = "SRSConf3";
ead9360e 5117 break;
9c2149c8 5118 case 5:
e189e748 5119 check_insn(env, ctx, ISA_MIPS32R2);
d9bea114 5120 gen_helper_mtc0_srsconf4(arg);
2423f660 5121 rn = "SRSConf4";
ead9360e 5122 break;
9c2149c8
TS
5123 default:
5124 goto die;
876d4b07 5125 }
9c2149c8
TS
5126 break;
5127 case 7:
5128 switch (sel) {
5129 case 0:
e189e748 5130 check_insn(env, ctx, ISA_MIPS32R2);
d9bea114 5131 gen_helper_mtc0_hwrena(arg);
2423f660
TS
5132 rn = "HWREna";
5133 break;
9c2149c8
TS
5134 default:
5135 goto die;
876d4b07 5136 }
9c2149c8
TS
5137 break;
5138 case 8:
5139 /* ignored */
f0b3f3ae 5140 rn = "BadVAddr";
9c2149c8
TS
5141 break;
5142 case 9:
5143 switch (sel) {
5144 case 0:
d9bea114 5145 gen_helper_mtc0_count(arg);
2423f660
TS
5146 rn = "Count";
5147 break;
876d4b07 5148 /* 6,7 are implementation dependent */
9c2149c8
TS
5149 default:
5150 goto die;
876d4b07
TS
5151 }
5152 /* Stop translation as we may have switched the execution mode */
5153 ctx->bstate = BS_STOP;
9c2149c8
TS
5154 break;
5155 case 10:
5156 switch (sel) {
5157 case 0:
d9bea114 5158 gen_helper_mtc0_entryhi(arg);
2423f660
TS
5159 rn = "EntryHi";
5160 break;
9c2149c8
TS
5161 default:
5162 goto die;
876d4b07 5163 }
9c2149c8
TS
5164 break;
5165 case 11:
5166 switch (sel) {
5167 case 0:
d9bea114 5168 gen_helper_mtc0_compare(arg);
2423f660
TS
5169 rn = "Compare";
5170 break;
876d4b07 5171 /* 6,7 are implementation dependent */
9c2149c8
TS
5172 default:
5173 goto die;
876d4b07 5174 }
de9a95f0
AJ
5175 /* Stop translation as we may have switched the execution mode */
5176 ctx->bstate = BS_STOP;
9c2149c8
TS
5177 break;
5178 case 12:
5179 switch (sel) {
5180 case 0:
867abc7e 5181 save_cpu_state(ctx, 1);
d9bea114 5182 gen_helper_mtc0_status(arg);
8487327a
TS
5183 /* BS_STOP isn't good enough here, hflags may have changed. */
5184 gen_save_pc(ctx->pc + 4);
5185 ctx->bstate = BS_EXCP;
2423f660
TS
5186 rn = "Status";
5187 break;
9c2149c8 5188 case 1:
e189e748 5189 check_insn(env, ctx, ISA_MIPS32R2);
d9bea114 5190 gen_helper_mtc0_intctl(arg);
8487327a
TS
5191 /* Stop translation as we may have switched the execution mode */
5192 ctx->bstate = BS_STOP;
2423f660
TS
5193 rn = "IntCtl";
5194 break;
9c2149c8 5195 case 2:
e189e748 5196 check_insn(env, ctx, ISA_MIPS32R2);
d9bea114 5197 gen_helper_mtc0_srsctl(arg);
8487327a
TS
5198 /* Stop translation as we may have switched the execution mode */
5199 ctx->bstate = BS_STOP;
2423f660
TS
5200 rn = "SRSCtl";
5201 break;
9c2149c8 5202 case 3:
e189e748 5203 check_insn(env, ctx, ISA_MIPS32R2);
d9bea114 5204 gen_mtc0_store32(arg, offsetof(CPUState, CP0_SRSMap));
8487327a
TS
5205 /* Stop translation as we may have switched the execution mode */
5206 ctx->bstate = BS_STOP;
2423f660
TS
5207 rn = "SRSMap";
5208 break;
5209 default:
9c2149c8 5210 goto die;
876d4b07 5211 }
9c2149c8
TS
5212 break;
5213 case 13:
5214 switch (sel) {
5215 case 0:
867abc7e 5216 save_cpu_state(ctx, 1);
5dc5d9f0
AJ
5217 /* Mark as an IO operation because we may trigger a software
5218 interrupt. */
5219 if (use_icount) {
5220 gen_io_start();
5221 }
d9bea114 5222 gen_helper_mtc0_cause(arg);
5dc5d9f0
AJ
5223 if (use_icount) {
5224 gen_io_end();
5225 }
5226 /* Stop translation as we may have triggered an intetrupt */
5227 ctx->bstate = BS_STOP;
2423f660
TS
5228 rn = "Cause";
5229 break;
9c2149c8
TS
5230 default:
5231 goto die;
876d4b07 5232 }
9c2149c8
TS
5233 break;
5234 case 14:
5235 switch (sel) {
5236 case 0:
d9bea114 5237 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUState, CP0_EPC));
2423f660
TS
5238 rn = "EPC";
5239 break;
9c2149c8
TS
5240 default:
5241 goto die;
876d4b07 5242 }
9c2149c8
TS
5243 break;
5244 case 15:
5245 switch (sel) {
5246 case 0:
2423f660
TS
5247 /* ignored */
5248 rn = "PRid";
5249 break;
9c2149c8 5250 case 1:
e189e748 5251 check_insn(env, ctx, ISA_MIPS32R2);
d9bea114 5252 gen_helper_mtc0_ebase(arg);
2423f660
TS
5253 rn = "EBase";
5254 break;
9c2149c8
TS
5255 default:
5256 goto die;
876d4b07 5257 }
9c2149c8
TS
5258 break;
5259 case 16:
5260 switch (sel) {
5261 case 0:
d9bea114 5262 gen_helper_mtc0_config0(arg);
9c2149c8 5263 rn = "Config";
2423f660
TS
5264 /* Stop translation as we may have switched the execution mode */
5265 ctx->bstate = BS_STOP;
9c2149c8
TS
5266 break;
5267 case 1:
1fc7bf6e 5268 /* ignored, read only */
9c2149c8
TS
5269 rn = "Config1";
5270 break;
5271 case 2:
d9bea114 5272 gen_helper_mtc0_config2(arg);
9c2149c8 5273 rn = "Config2";
2423f660
TS
5274 /* Stop translation as we may have switched the execution mode */
5275 ctx->bstate = BS_STOP;
9c2149c8
TS
5276 break;
5277 case 3:
2423f660 5278 /* ignored */
9c2149c8
TS
5279 rn = "Config3";
5280 break;
5281 /* 6,7 are implementation dependent */
5282 default:
5283 rn = "Invalid config selector";
5284 goto die;
5285 }
9c2149c8
TS
5286 break;
5287 case 17:
5288 switch (sel) {
5289 case 0:
2a6e32dd 5290 gen_helper_mtc0_lladdr(arg);
2423f660
TS
5291 rn = "LLAddr";
5292 break;
9c2149c8
TS
5293 default:
5294 goto die;
5295 }
5296 break;
5297 case 18:
5298 switch (sel) {
fd88b6ab 5299 case 0 ... 7:
d9bea114 5300 gen_helper_1i(mtc0_watchlo, arg, sel);
2423f660
TS
5301 rn = "WatchLo";
5302 break;
9c2149c8
TS
5303 default:
5304 goto die;
5305 }
5306 break;
5307 case 19:
5308 switch (sel) {
fd88b6ab 5309 case 0 ... 7:
d9bea114 5310 gen_helper_1i(mtc0_watchhi, arg, sel);
2423f660
TS
5311 rn = "WatchHi";
5312 break;
9c2149c8
TS
5313 default:
5314 goto die;
5315 }
5316 break;
5317 case 20:
5318 switch (sel) {
5319 case 0:
e189e748 5320 check_insn(env, ctx, ISA_MIPS3);
d9bea114 5321 gen_helper_mtc0_xcontext(arg);
2423f660
TS
5322 rn = "XContext";
5323 break;
9c2149c8
TS
5324 default:
5325 goto die;
5326 }
5327 break;
5328 case 21:
5329 /* Officially reserved, but sel 0 is used for R1x000 framemask */
5330 switch (sel) {
5331 case 0:
d9bea114 5332 gen_helper_mtc0_framemask(arg);
2423f660
TS
5333 rn = "Framemask";
5334 break;
9c2149c8
TS
5335 default:
5336 goto die;
5337 }
5338 break;
5339 case 22:
5340 /* ignored */
5341 rn = "Diagnostic"; /* implementation dependent */
876d4b07 5342 break;
9c2149c8
TS
5343 case 23:
5344 switch (sel) {
5345 case 0:
d9bea114 5346 gen_helper_mtc0_debug(arg); /* EJTAG support */
8487327a
TS
5347 /* BS_STOP isn't good enough here, hflags may have changed. */
5348 gen_save_pc(ctx->pc + 4);
5349 ctx->bstate = BS_EXCP;
2423f660
TS
5350 rn = "Debug";
5351 break;
9c2149c8 5352 case 1:
d9bea114 5353// gen_helper_mtc0_tracecontrol(arg); /* PDtrace support */
8487327a
TS
5354 /* Stop translation as we may have switched the execution mode */
5355 ctx->bstate = BS_STOP;
2423f660
TS
5356 rn = "TraceControl";
5357// break;
9c2149c8 5358 case 2:
d9bea114 5359// gen_helper_mtc0_tracecontrol2(arg); /* PDtrace support */
8487327a
TS
5360 /* Stop translation as we may have switched the execution mode */
5361 ctx->bstate = BS_STOP;
2423f660
TS
5362 rn = "TraceControl2";
5363// break;
9c2149c8 5364 case 3:
d9bea114 5365// gen_helper_mtc0_usertracedata(arg); /* PDtrace support */
8487327a
TS
5366 /* Stop translation as we may have switched the execution mode */
5367 ctx->bstate = BS_STOP;
2423f660
TS
5368 rn = "UserTraceData";
5369// break;
9c2149c8 5370 case 4:
d9bea114 5371// gen_helper_mtc0_tracebpc(arg); /* PDtrace support */
8487327a
TS
5372 /* Stop translation as we may have switched the execution mode */
5373 ctx->bstate = BS_STOP;
2423f660
TS
5374 rn = "TraceBPC";
5375// break;
9c2149c8
TS
5376 default:
5377 goto die;
5378 }
9c2149c8
TS
5379 break;
5380 case 24:
5381 switch (sel) {
5382 case 0:
f1aa6320 5383 /* EJTAG support */
d9bea114 5384 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUState, CP0_DEPC));
2423f660
TS
5385 rn = "DEPC";
5386 break;
9c2149c8
TS
5387 default:
5388 goto die;
5389 }
5390 break;
5391 case 25:
5392 switch (sel) {
5393 case 0:
d9bea114 5394 gen_helper_mtc0_performance0(arg);
2423f660
TS
5395 rn = "Performance0";
5396 break;
9c2149c8 5397 case 1:
d9bea114 5398// gen_helper_mtc0_performance1(arg);
2423f660
TS
5399 rn = "Performance1";
5400// break;
9c2149c8 5401 case 2:
d9bea114 5402// gen_helper_mtc0_performance2(arg);
2423f660
TS
5403 rn = "Performance2";
5404// break;
9c2149c8 5405 case 3:
d9bea114 5406// gen_helper_mtc0_performance3(arg);
2423f660
TS
5407 rn = "Performance3";
5408// break;
9c2149c8 5409 case 4:
d9bea114 5410// gen_helper_mtc0_performance4(arg);
2423f660
TS
5411 rn = "Performance4";
5412// break;
9c2149c8 5413 case 5:
d9bea114 5414// gen_helper_mtc0_performance5(arg);
2423f660
TS
5415 rn = "Performance5";
5416// break;
9c2149c8 5417 case 6:
d9bea114 5418// gen_helper_mtc0_performance6(arg);
2423f660
TS
5419 rn = "Performance6";
5420// break;
9c2149c8 5421 case 7:
d9bea114 5422// gen_helper_mtc0_performance7(arg);
2423f660
TS
5423 rn = "Performance7";
5424// break;
9c2149c8
TS
5425 default:
5426 goto die;
5427 }
876d4b07 5428 break;
9c2149c8 5429 case 26:
876d4b07 5430 /* ignored */
9c2149c8 5431 rn = "ECC";
876d4b07 5432 break;
9c2149c8
TS
5433 case 27:
5434 switch (sel) {
5435 case 0 ... 3:
2423f660
TS
5436 /* ignored */
5437 rn = "CacheErr";
5438 break;
9c2149c8
TS
5439 default:
5440 goto die;
5441 }
876d4b07 5442 break;
9c2149c8
TS
5443 case 28:
5444 switch (sel) {
5445 case 0:
5446 case 2:
5447 case 4:
5448 case 6:
d9bea114 5449 gen_helper_mtc0_taglo(arg);
9c2149c8
TS
5450 rn = "TagLo";
5451 break;
5452 case 1:
5453 case 3:
5454 case 5:
5455 case 7:
d9bea114 5456 gen_helper_mtc0_datalo(arg);
9c2149c8
TS
5457 rn = "DataLo";
5458 break;
5459 default:
5460 goto die;
5461 }
5462 break;
5463 case 29:
5464 switch (sel) {
5465 case 0:
5466 case 2:
5467 case 4:
5468 case 6:
d9bea114 5469 gen_helper_mtc0_taghi(arg);
9c2149c8
TS
5470 rn = "TagHi";
5471 break;
5472 case 1:
5473 case 3:
5474 case 5:
5475 case 7:
d9bea114 5476 gen_helper_mtc0_datahi(arg);
9c2149c8
TS
5477 rn = "DataHi";
5478 break;
5479 default:
5480 rn = "invalid sel";
5481 goto die;
5482 }
876d4b07 5483 break;
9c2149c8
TS
5484 case 30:
5485 switch (sel) {
5486 case 0:
d9bea114 5487 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUState, CP0_ErrorEPC));
2423f660
TS
5488 rn = "ErrorEPC";
5489 break;
9c2149c8
TS
5490 default:
5491 goto die;
5492 }
5493 break;
5494 case 31:
5495 switch (sel) {
5496 case 0:
f1aa6320 5497 /* EJTAG support */
d9bea114 5498 gen_mtc0_store32(arg, offsetof(CPUState, CP0_DESAVE));
2423f660
TS
5499 rn = "DESAVE";
5500 break;
9c2149c8
TS
5501 default:
5502 goto die;
5503 }
876d4b07
TS
5504 /* Stop translation as we may have switched the execution mode */
5505 ctx->bstate = BS_STOP;
9c2149c8
TS
5506 break;
5507 default:
876d4b07 5508 goto die;
9c2149c8 5509 }
2abf314d 5510 (void)rn; /* avoid a compiler warning */
d12d51d5 5511 LOG_DISAS("dmtc0 %s (reg %d sel %d)\n", rn, reg, sel);
bf20dc07 5512 /* For simplicity assume that all writes can cause interrupts. */
2e70f6ef
PB
5513 if (use_icount) {
5514 gen_io_end();
5515 ctx->bstate = BS_STOP;
5516 }
9c2149c8
TS
5517 return;
5518
5519die:
d12d51d5 5520 LOG_DISAS("dmtc0 %s (reg %d sel %d)\n", rn, reg, sel);
9c2149c8
TS
5521 generate_exception(ctx, EXCP_RI);
5522}
d26bc211 5523#endif /* TARGET_MIPS64 */
9c2149c8 5524
6c5c1e20 5525static void gen_mftr(CPUState *env, DisasContext *ctx, int rt, int rd,
ead9360e
TS
5526 int u, int sel, int h)
5527{
5528 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
a7812ae4 5529 TCGv t0 = tcg_temp_local_new();
ead9360e
TS
5530
5531 if ((env->CP0_VPEConf0 & (1 << CP0VPEC0_MVP)) == 0 &&
b5dc7732
TS
5532 ((env->tcs[other_tc].CP0_TCBind & (0xf << CP0TCBd_CurVPE)) !=
5533 (env->active_tc.CP0_TCBind & (0xf << CP0TCBd_CurVPE))))
1a3fd9c3 5534 tcg_gen_movi_tl(t0, -1);
ead9360e
TS
5535 else if ((env->CP0_VPEControl & (0xff << CP0VPECo_TargTC)) >
5536 (env->mvp->CP0_MVPConf0 & (0xff << CP0MVPC0_PTC)))
1a3fd9c3 5537 tcg_gen_movi_tl(t0, -1);
ead9360e
TS
5538 else if (u == 0) {
5539 switch (rt) {
5540 case 2:
5541 switch (sel) {
5542 case 1:
a7812ae4 5543 gen_helper_mftc0_tcstatus(t0);
ead9360e
TS
5544 break;
5545 case 2:
a7812ae4 5546 gen_helper_mftc0_tcbind(t0);
ead9360e
TS
5547 break;
5548 case 3:
a7812ae4 5549 gen_helper_mftc0_tcrestart(t0);
ead9360e
TS
5550 break;
5551 case 4:
a7812ae4 5552 gen_helper_mftc0_tchalt(t0);
ead9360e
TS
5553 break;
5554 case 5:
a7812ae4 5555 gen_helper_mftc0_tccontext(t0);
ead9360e
TS
5556 break;
5557 case 6:
a7812ae4 5558 gen_helper_mftc0_tcschedule(t0);
ead9360e
TS
5559 break;
5560 case 7:
a7812ae4 5561 gen_helper_mftc0_tcschefback(t0);
ead9360e
TS
5562 break;
5563 default:
1a3fd9c3 5564 gen_mfc0(env, ctx, t0, rt, sel);
ead9360e
TS
5565 break;
5566 }
5567 break;
5568 case 10:
5569 switch (sel) {
5570 case 0:
a7812ae4 5571 gen_helper_mftc0_entryhi(t0);
ead9360e
TS
5572 break;
5573 default:
1a3fd9c3 5574 gen_mfc0(env, ctx, t0, rt, sel);
ead9360e
TS
5575 break;
5576 }
5577 case 12:
5578 switch (sel) {
5579 case 0:
a7812ae4 5580 gen_helper_mftc0_status(t0);
ead9360e
TS
5581 break;
5582 default:
1a3fd9c3 5583 gen_mfc0(env, ctx, t0, rt, sel);
ead9360e
TS
5584 break;
5585 }
5586 case 23:
5587 switch (sel) {
5588 case 0:
a7812ae4 5589 gen_helper_mftc0_debug(t0);
ead9360e
TS
5590 break;
5591 default:
1a3fd9c3 5592 gen_mfc0(env, ctx, t0, rt, sel);
ead9360e
TS
5593 break;
5594 }
5595 break;
5596 default:
1a3fd9c3 5597 gen_mfc0(env, ctx, t0, rt, sel);
ead9360e
TS
5598 }
5599 } else switch (sel) {
5600 /* GPR registers. */
5601 case 0:
a7812ae4 5602 gen_helper_1i(mftgpr, t0, rt);
ead9360e
TS
5603 break;
5604 /* Auxiliary CPU registers */
5605 case 1:
5606 switch (rt) {
5607 case 0:
a7812ae4 5608 gen_helper_1i(mftlo, t0, 0);
ead9360e
TS
5609 break;
5610 case 1:
a7812ae4 5611 gen_helper_1i(mfthi, t0, 0);
ead9360e
TS
5612 break;
5613 case 2:
a7812ae4 5614 gen_helper_1i(mftacx, t0, 0);
ead9360e
TS
5615 break;
5616 case 4:
a7812ae4 5617 gen_helper_1i(mftlo, t0, 1);
ead9360e
TS
5618 break;
5619 case 5:
a7812ae4 5620 gen_helper_1i(mfthi, t0, 1);
ead9360e
TS
5621 break;
5622 case 6:
a7812ae4 5623 gen_helper_1i(mftacx, t0, 1);
ead9360e
TS
5624 break;
5625 case 8:
a7812ae4 5626 gen_helper_1i(mftlo, t0, 2);
ead9360e
TS
5627 break;
5628 case 9:
a7812ae4 5629 gen_helper_1i(mfthi, t0, 2);
ead9360e
TS
5630 break;
5631 case 10:
a7812ae4 5632 gen_helper_1i(mftacx, t0, 2);
ead9360e
TS
5633 break;
5634 case 12:
a7812ae4 5635 gen_helper_1i(mftlo, t0, 3);
ead9360e
TS
5636 break;
5637 case 13:
a7812ae4 5638 gen_helper_1i(mfthi, t0, 3);
ead9360e
TS
5639 break;
5640 case 14:
a7812ae4 5641 gen_helper_1i(mftacx, t0, 3);
ead9360e
TS
5642 break;
5643 case 16:
a7812ae4 5644 gen_helper_mftdsp(t0);
ead9360e
TS
5645 break;
5646 default:
5647 goto die;
5648 }
5649 break;
5650 /* Floating point (COP1). */
5651 case 2:
5652 /* XXX: For now we support only a single FPU context. */
5653 if (h == 0) {
a7812ae4 5654 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed
TS
5655
5656 gen_load_fpr32(fp0, rt);
5657 tcg_gen_ext_i32_tl(t0, fp0);
a7812ae4 5658 tcg_temp_free_i32(fp0);
ead9360e 5659 } else {
a7812ae4 5660 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed
TS
5661
5662 gen_load_fpr32h(fp0, rt);
5663 tcg_gen_ext_i32_tl(t0, fp0);
a7812ae4 5664 tcg_temp_free_i32(fp0);
ead9360e
TS
5665 }
5666 break;
5667 case 3:
5668 /* XXX: For now we support only a single FPU context. */
a7812ae4 5669 gen_helper_1i(cfc1, t0, rt);
ead9360e
TS
5670 break;
5671 /* COP2: Not implemented. */
5672 case 4:
5673 case 5:
5674 /* fall through */
5675 default:
5676 goto die;
5677 }
d12d51d5 5678 LOG_DISAS("mftr (reg %d u %d sel %d h %d)\n", rt, u, sel, h);
1a3fd9c3
TS
5679 gen_store_gpr(t0, rd);
5680 tcg_temp_free(t0);
ead9360e
TS
5681 return;
5682
5683die:
1a3fd9c3 5684 tcg_temp_free(t0);
d12d51d5 5685 LOG_DISAS("mftr (reg %d u %d sel %d h %d)\n", rt, u, sel, h);
ead9360e
TS
5686 generate_exception(ctx, EXCP_RI);
5687}
5688
6c5c1e20 5689static void gen_mttr(CPUState *env, DisasContext *ctx, int rd, int rt,
ead9360e
TS
5690 int u, int sel, int h)
5691{
5692 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
a7812ae4 5693 TCGv t0 = tcg_temp_local_new();
ead9360e 5694
1a3fd9c3 5695 gen_load_gpr(t0, rt);
ead9360e 5696 if ((env->CP0_VPEConf0 & (1 << CP0VPEC0_MVP)) == 0 &&
b5dc7732
TS
5697 ((env->tcs[other_tc].CP0_TCBind & (0xf << CP0TCBd_CurVPE)) !=
5698 (env->active_tc.CP0_TCBind & (0xf << CP0TCBd_CurVPE))))
ead9360e
TS
5699 /* NOP */ ;
5700 else if ((env->CP0_VPEControl & (0xff << CP0VPECo_TargTC)) >
5701 (env->mvp->CP0_MVPConf0 & (0xff << CP0MVPC0_PTC)))
5702 /* NOP */ ;
5703 else if (u == 0) {
5704 switch (rd) {
5705 case 2:
5706 switch (sel) {
5707 case 1:
a7812ae4 5708 gen_helper_mttc0_tcstatus(t0);
ead9360e
TS
5709 break;
5710 case 2:
a7812ae4 5711 gen_helper_mttc0_tcbind(t0);
ead9360e
TS
5712 break;
5713 case 3:
a7812ae4 5714 gen_helper_mttc0_tcrestart(t0);
ead9360e
TS
5715 break;
5716 case 4:
a7812ae4 5717 gen_helper_mttc0_tchalt(t0);
ead9360e
TS
5718 break;
5719 case 5:
a7812ae4 5720 gen_helper_mttc0_tccontext(t0);
ead9360e
TS
5721 break;
5722 case 6:
a7812ae4 5723 gen_helper_mttc0_tcschedule(t0);
ead9360e
TS
5724 break;
5725 case 7:
a7812ae4 5726 gen_helper_mttc0_tcschefback(t0);
ead9360e
TS
5727 break;
5728 default:
1a3fd9c3 5729 gen_mtc0(env, ctx, t0, rd, sel);
ead9360e
TS
5730 break;
5731 }
5732 break;
5733 case 10:
5734 switch (sel) {
5735 case 0:
a7812ae4 5736 gen_helper_mttc0_entryhi(t0);
ead9360e
TS
5737 break;
5738 default:
1a3fd9c3 5739 gen_mtc0(env, ctx, t0, rd, sel);
ead9360e
TS
5740 break;
5741 }
5742 case 12:
5743 switch (sel) {
5744 case 0:
a7812ae4 5745 gen_helper_mttc0_status(t0);
ead9360e
TS
5746 break;
5747 default:
1a3fd9c3 5748 gen_mtc0(env, ctx, t0, rd, sel);
ead9360e
TS
5749 break;
5750 }
5751 case 23:
5752 switch (sel) {
5753 case 0:
a7812ae4 5754 gen_helper_mttc0_debug(t0);
ead9360e
TS
5755 break;
5756 default:
1a3fd9c3 5757 gen_mtc0(env, ctx, t0, rd, sel);
ead9360e
TS
5758 break;
5759 }
5760 break;
5761 default:
1a3fd9c3 5762 gen_mtc0(env, ctx, t0, rd, sel);
ead9360e
TS
5763 }
5764 } else switch (sel) {
5765 /* GPR registers. */
5766 case 0:
a7812ae4 5767 gen_helper_1i(mttgpr, t0, rd);
ead9360e
TS
5768 break;
5769 /* Auxiliary CPU registers */
5770 case 1:
5771 switch (rd) {
5772 case 0:
a7812ae4 5773 gen_helper_1i(mttlo, t0, 0);
ead9360e
TS
5774 break;
5775 case 1:
a7812ae4 5776 gen_helper_1i(mtthi, t0, 0);
ead9360e
TS
5777 break;
5778 case 2:
a7812ae4 5779 gen_helper_1i(mttacx, t0, 0);
ead9360e
TS
5780 break;
5781 case 4:
a7812ae4 5782 gen_helper_1i(mttlo, t0, 1);
ead9360e
TS
5783 break;
5784 case 5:
a7812ae4 5785 gen_helper_1i(mtthi, t0, 1);
ead9360e
TS
5786 break;
5787 case 6:
a7812ae4 5788 gen_helper_1i(mttacx, t0, 1);
ead9360e
TS
5789 break;
5790 case 8:
a7812ae4 5791 gen_helper_1i(mttlo, t0, 2);
ead9360e
TS
5792 break;
5793 case 9:
a7812ae4 5794 gen_helper_1i(mtthi, t0, 2);
ead9360e
TS
5795 break;
5796 case 10:
a7812ae4 5797 gen_helper_1i(mttacx, t0, 2);
ead9360e
TS
5798 break;
5799 case 12:
a7812ae4 5800 gen_helper_1i(mttlo, t0, 3);
ead9360e
TS
5801 break;
5802 case 13:
a7812ae4 5803 gen_helper_1i(mtthi, t0, 3);
ead9360e
TS
5804 break;
5805 case 14:
a7812ae4 5806 gen_helper_1i(mttacx, t0, 3);
ead9360e
TS
5807 break;
5808 case 16:
a7812ae4 5809 gen_helper_mttdsp(t0);
ead9360e
TS
5810 break;
5811 default:
5812 goto die;
5813 }
5814 break;
5815 /* Floating point (COP1). */
5816 case 2:
5817 /* XXX: For now we support only a single FPU context. */
5818 if (h == 0) {
a7812ae4 5819 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed
TS
5820
5821 tcg_gen_trunc_tl_i32(fp0, t0);
5822 gen_store_fpr32(fp0, rd);
a7812ae4 5823 tcg_temp_free_i32(fp0);
ead9360e 5824 } else {
a7812ae4 5825 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed
TS
5826
5827 tcg_gen_trunc_tl_i32(fp0, t0);
5828 gen_store_fpr32h(fp0, rd);
a7812ae4 5829 tcg_temp_free_i32(fp0);
ead9360e
TS
5830 }
5831 break;
5832 case 3:
5833 /* XXX: For now we support only a single FPU context. */
a7812ae4 5834 gen_helper_1i(ctc1, t0, rd);
ead9360e
TS
5835 break;
5836 /* COP2: Not implemented. */
5837 case 4:
5838 case 5:
5839 /* fall through */
5840 default:
5841 goto die;
5842 }
d12d51d5 5843 LOG_DISAS("mttr (reg %d u %d sel %d h %d)\n", rd, u, sel, h);
1a3fd9c3 5844 tcg_temp_free(t0);
ead9360e
TS
5845 return;
5846
5847die:
1a3fd9c3 5848 tcg_temp_free(t0);
d12d51d5 5849 LOG_DISAS("mttr (reg %d u %d sel %d h %d)\n", rd, u, sel, h);
ead9360e
TS
5850 generate_exception(ctx, EXCP_RI);
5851}
5852
29929e34 5853static void gen_cp0 (CPUState *env, DisasContext *ctx, uint32_t opc, int rt, int rd)
6af0bf9c 5854{
287c4b84 5855 const char *opn = "ldst";
6af0bf9c 5856
6af0bf9c
FB
5857 switch (opc) {
5858 case OPC_MFC0:
5859 if (rt == 0) {
ead9360e 5860 /* Treat as NOP. */
6af0bf9c
FB
5861 return;
5862 }
1fc7bf6e 5863 gen_mfc0(env, ctx, cpu_gpr[rt], rd, ctx->opcode & 0x7);
6af0bf9c
FB
5864 opn = "mfc0";
5865 break;
5866 case OPC_MTC0:
1a3fd9c3 5867 {
1fc7bf6e 5868 TCGv t0 = tcg_temp_new();
1a3fd9c3
TS
5869
5870 gen_load_gpr(t0, rt);
1a3fd9c3
TS
5871 gen_mtc0(env, ctx, t0, rd, ctx->opcode & 0x7);
5872 tcg_temp_free(t0);
5873 }
6af0bf9c
FB
5874 opn = "mtc0";
5875 break;
d26bc211 5876#if defined(TARGET_MIPS64)
9c2149c8 5877 case OPC_DMFC0:
e189e748 5878 check_insn(env, ctx, ISA_MIPS3);
9c2149c8 5879 if (rt == 0) {
ead9360e 5880 /* Treat as NOP. */
9c2149c8
TS
5881 return;
5882 }
1fc7bf6e 5883 gen_dmfc0(env, ctx, cpu_gpr[rt], rd, ctx->opcode & 0x7);
9c2149c8
TS
5884 opn = "dmfc0";
5885 break;
5886 case OPC_DMTC0:
e189e748 5887 check_insn(env, ctx, ISA_MIPS3);
1a3fd9c3 5888 {
1fc7bf6e 5889 TCGv t0 = tcg_temp_new();
1a3fd9c3
TS
5890
5891 gen_load_gpr(t0, rt);
1a3fd9c3
TS
5892 gen_dmtc0(env, ctx, t0, rd, ctx->opcode & 0x7);
5893 tcg_temp_free(t0);
5894 }
9c2149c8
TS
5895 opn = "dmtc0";
5896 break;
534ce69f 5897#endif
ead9360e 5898 case OPC_MFTR:
7385ac0b 5899 check_insn(env, ctx, ASE_MT);
ead9360e
TS
5900 if (rd == 0) {
5901 /* Treat as NOP. */
5902 return;
5903 }
6c5c1e20 5904 gen_mftr(env, ctx, rt, rd, (ctx->opcode >> 5) & 1,
ead9360e 5905 ctx->opcode & 0x7, (ctx->opcode >> 4) & 1);
ead9360e
TS
5906 opn = "mftr";
5907 break;
5908 case OPC_MTTR:
7385ac0b 5909 check_insn(env, ctx, ASE_MT);
6c5c1e20 5910 gen_mttr(env, ctx, rd, rt, (ctx->opcode >> 5) & 1,
ead9360e
TS
5911 ctx->opcode & 0x7, (ctx->opcode >> 4) & 1);
5912 opn = "mttr";
5913 break;
6af0bf9c 5914 case OPC_TLBWI:
6af0bf9c 5915 opn = "tlbwi";
c01fccd2 5916 if (!env->tlb->helper_tlbwi)
29929e34 5917 goto die;
a7812ae4 5918 gen_helper_tlbwi();
6af0bf9c
FB
5919 break;
5920 case OPC_TLBWR:
6af0bf9c 5921 opn = "tlbwr";
c01fccd2 5922 if (!env->tlb->helper_tlbwr)
29929e34 5923 goto die;
a7812ae4 5924 gen_helper_tlbwr();
6af0bf9c
FB
5925 break;
5926 case OPC_TLBP:
6af0bf9c 5927 opn = "tlbp";
c01fccd2 5928 if (!env->tlb->helper_tlbp)
29929e34 5929 goto die;
a7812ae4 5930 gen_helper_tlbp();
6af0bf9c
FB
5931 break;
5932 case OPC_TLBR:
6af0bf9c 5933 opn = "tlbr";
c01fccd2 5934 if (!env->tlb->helper_tlbr)
29929e34 5935 goto die;
a7812ae4 5936 gen_helper_tlbr();
6af0bf9c 5937 break;
6af0bf9c
FB
5938 case OPC_ERET:
5939 opn = "eret";
e189e748 5940 check_insn(env, ctx, ISA_MIPS2);
a7812ae4 5941 gen_helper_eret();
6af0bf9c
FB
5942 ctx->bstate = BS_EXCP;
5943 break;
5944 case OPC_DERET:
5945 opn = "deret";
e189e748 5946 check_insn(env, ctx, ISA_MIPS32);
6af0bf9c 5947 if (!(ctx->hflags & MIPS_HFLAG_DM)) {
923617a3 5948 MIPS_INVAL(opn);
6af0bf9c
FB
5949 generate_exception(ctx, EXCP_RI);
5950 } else {
a7812ae4 5951 gen_helper_deret();
6af0bf9c
FB
5952 ctx->bstate = BS_EXCP;
5953 }
5954 break;
4ad40f36
FB
5955 case OPC_WAIT:
5956 opn = "wait";
e189e748 5957 check_insn(env, ctx, ISA_MIPS3 | ISA_MIPS32);
4ad40f36
FB
5958 /* If we get an exception, we want to restart at next instruction */
5959 ctx->pc += 4;
5960 save_cpu_state(ctx, 1);
5961 ctx->pc -= 4;
a7812ae4 5962 gen_helper_wait();
4ad40f36
FB
5963 ctx->bstate = BS_EXCP;
5964 break;
6af0bf9c 5965 default:
29929e34 5966 die:
923617a3 5967 MIPS_INVAL(opn);
6af0bf9c
FB
5968 generate_exception(ctx, EXCP_RI);
5969 return;
5970 }
2abf314d 5971 (void)opn; /* avoid a compiler warning */
6af0bf9c
FB
5972 MIPS_DEBUG("%s %s %d", opn, regnames[rt], rd);
5973}
f1aa6320 5974#endif /* !CONFIG_USER_ONLY */
6af0bf9c 5975
6ea83fed 5976/* CP1 Branches (before delay slot) */
e189e748 5977static void gen_compute_branch1 (CPUState *env, DisasContext *ctx, uint32_t op,
5a5012ec 5978 int32_t cc, int32_t offset)
6ea83fed
FB
5979{
5980 target_ulong btarget;
923617a3 5981 const char *opn = "cp1 cond branch";
a7812ae4 5982 TCGv_i32 t0 = tcg_temp_new_i32();
6ea83fed 5983
e189e748
TS
5984 if (cc != 0)
5985 check_insn(env, ctx, ISA_MIPS4 | ISA_MIPS32);
5986
6ea83fed
FB
5987 btarget = ctx->pc + 4 + offset;
5988
7a387fff
TS
5989 switch (op) {
5990 case OPC_BC1F:
d94536f4
AJ
5991 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
5992 tcg_gen_not_i32(t0, t0);
5993 tcg_gen_andi_i32(t0, t0, 1);
5994 tcg_gen_extu_i32_tl(bcond, t0);
923617a3 5995 opn = "bc1f";
6ea83fed 5996 goto not_likely;
7a387fff 5997 case OPC_BC1FL:
d94536f4
AJ
5998 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
5999 tcg_gen_not_i32(t0, t0);
6000 tcg_gen_andi_i32(t0, t0, 1);
6001 tcg_gen_extu_i32_tl(bcond, t0);
923617a3 6002 opn = "bc1fl";
6ea83fed 6003 goto likely;
7a387fff 6004 case OPC_BC1T:
d94536f4
AJ
6005 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
6006 tcg_gen_andi_i32(t0, t0, 1);
6007 tcg_gen_extu_i32_tl(bcond, t0);
923617a3 6008 opn = "bc1t";
5a5012ec 6009 goto not_likely;
7a387fff 6010 case OPC_BC1TL:
d94536f4
AJ
6011 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
6012 tcg_gen_andi_i32(t0, t0, 1);
6013 tcg_gen_extu_i32_tl(bcond, t0);
923617a3 6014 opn = "bc1tl";
6ea83fed
FB
6015 likely:
6016 ctx->hflags |= MIPS_HFLAG_BL;
6017 break;
5a5012ec 6018 case OPC_BC1FANY2:
a16336e4 6019 {
d94536f4
AJ
6020 TCGv_i32 t1 = tcg_temp_new_i32();
6021 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
6022 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+1));
deb4203d 6023 tcg_gen_nor_i32(t0, t0, t1);
d94536f4 6024 tcg_temp_free_i32(t1);
d94536f4
AJ
6025 tcg_gen_andi_i32(t0, t0, 1);
6026 tcg_gen_extu_i32_tl(bcond, t0);
a16336e4 6027 }
fd4a04eb 6028 opn = "bc1any2f";
5a5012ec
TS
6029 goto not_likely;
6030 case OPC_BC1TANY2:
a16336e4 6031 {
d94536f4
AJ
6032 TCGv_i32 t1 = tcg_temp_new_i32();
6033 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
6034 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+1));
6035 tcg_gen_or_i32(t0, t0, t1);
6036 tcg_temp_free_i32(t1);
6037 tcg_gen_andi_i32(t0, t0, 1);
6038 tcg_gen_extu_i32_tl(bcond, t0);
a16336e4 6039 }
fd4a04eb 6040 opn = "bc1any2t";
5a5012ec
TS
6041 goto not_likely;
6042 case OPC_BC1FANY4:
a16336e4 6043 {
d94536f4
AJ
6044 TCGv_i32 t1 = tcg_temp_new_i32();
6045 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
6046 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+1));
6047 tcg_gen_or_i32(t0, t0, t1);
6048 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+2));
6049 tcg_gen_or_i32(t0, t0, t1);
6050 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+3));
deb4203d 6051 tcg_gen_nor_i32(t0, t0, t1);
d94536f4 6052 tcg_temp_free_i32(t1);
d94536f4
AJ
6053 tcg_gen_andi_i32(t0, t0, 1);
6054 tcg_gen_extu_i32_tl(bcond, t0);
a16336e4 6055 }
fd4a04eb 6056 opn = "bc1any4f";
5a5012ec
TS
6057 goto not_likely;
6058 case OPC_BC1TANY4:
a16336e4 6059 {
d94536f4
AJ
6060 TCGv_i32 t1 = tcg_temp_new_i32();
6061 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
6062 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+1));
6063 tcg_gen_or_i32(t0, t0, t1);
6064 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+2));
6065 tcg_gen_or_i32(t0, t0, t1);
6066 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+3));
6067 tcg_gen_or_i32(t0, t0, t1);
6068 tcg_temp_free_i32(t1);
6069 tcg_gen_andi_i32(t0, t0, 1);
6070 tcg_gen_extu_i32_tl(bcond, t0);
a16336e4 6071 }
fd4a04eb 6072 opn = "bc1any4t";
5a5012ec
TS
6073 not_likely:
6074 ctx->hflags |= MIPS_HFLAG_BC;
5a5012ec
TS
6075 break;
6076 default:
923617a3 6077 MIPS_INVAL(opn);
e397ee33 6078 generate_exception (ctx, EXCP_RI);
6c5c1e20 6079 goto out;
6ea83fed 6080 }
2abf314d 6081 (void)opn; /* avoid a compiler warning */
923617a3 6082 MIPS_DEBUG("%s: cond %02x target " TARGET_FMT_lx, opn,
6ea83fed
FB
6083 ctx->hflags, btarget);
6084 ctx->btarget = btarget;
6c5c1e20
TS
6085
6086 out:
a7812ae4 6087 tcg_temp_free_i32(t0);
6ea83fed
FB
6088}
6089
6af0bf9c 6090/* Coprocessor 1 (FPU) */
5a5012ec 6091
5a5012ec
TS
6092#define FOP(func, fmt) (((fmt) << 21) | (func))
6093
bf4120ad
NF
6094enum fopcode {
6095 OPC_ADD_S = FOP(0, FMT_S),
6096 OPC_SUB_S = FOP(1, FMT_S),
6097 OPC_MUL_S = FOP(2, FMT_S),
6098 OPC_DIV_S = FOP(3, FMT_S),
6099 OPC_SQRT_S = FOP(4, FMT_S),
6100 OPC_ABS_S = FOP(5, FMT_S),
6101 OPC_MOV_S = FOP(6, FMT_S),
6102 OPC_NEG_S = FOP(7, FMT_S),
6103 OPC_ROUND_L_S = FOP(8, FMT_S),
6104 OPC_TRUNC_L_S = FOP(9, FMT_S),
6105 OPC_CEIL_L_S = FOP(10, FMT_S),
6106 OPC_FLOOR_L_S = FOP(11, FMT_S),
6107 OPC_ROUND_W_S = FOP(12, FMT_S),
6108 OPC_TRUNC_W_S = FOP(13, FMT_S),
6109 OPC_CEIL_W_S = FOP(14, FMT_S),
6110 OPC_FLOOR_W_S = FOP(15, FMT_S),
6111 OPC_MOVCF_S = FOP(17, FMT_S),
6112 OPC_MOVZ_S = FOP(18, FMT_S),
6113 OPC_MOVN_S = FOP(19, FMT_S),
6114 OPC_RECIP_S = FOP(21, FMT_S),
6115 OPC_RSQRT_S = FOP(22, FMT_S),
6116 OPC_RECIP2_S = FOP(28, FMT_S),
6117 OPC_RECIP1_S = FOP(29, FMT_S),
6118 OPC_RSQRT1_S = FOP(30, FMT_S),
6119 OPC_RSQRT2_S = FOP(31, FMT_S),
6120 OPC_CVT_D_S = FOP(33, FMT_S),
6121 OPC_CVT_W_S = FOP(36, FMT_S),
6122 OPC_CVT_L_S = FOP(37, FMT_S),
6123 OPC_CVT_PS_S = FOP(38, FMT_S),
6124 OPC_CMP_F_S = FOP (48, FMT_S),
6125 OPC_CMP_UN_S = FOP (49, FMT_S),
6126 OPC_CMP_EQ_S = FOP (50, FMT_S),
6127 OPC_CMP_UEQ_S = FOP (51, FMT_S),
6128 OPC_CMP_OLT_S = FOP (52, FMT_S),
6129 OPC_CMP_ULT_S = FOP (53, FMT_S),
6130 OPC_CMP_OLE_S = FOP (54, FMT_S),
6131 OPC_CMP_ULE_S = FOP (55, FMT_S),
6132 OPC_CMP_SF_S = FOP (56, FMT_S),
6133 OPC_CMP_NGLE_S = FOP (57, FMT_S),
6134 OPC_CMP_SEQ_S = FOP (58, FMT_S),
6135 OPC_CMP_NGL_S = FOP (59, FMT_S),
6136 OPC_CMP_LT_S = FOP (60, FMT_S),
6137 OPC_CMP_NGE_S = FOP (61, FMT_S),
6138 OPC_CMP_LE_S = FOP (62, FMT_S),
6139 OPC_CMP_NGT_S = FOP (63, FMT_S),
6140
6141 OPC_ADD_D = FOP(0, FMT_D),
6142 OPC_SUB_D = FOP(1, FMT_D),
6143 OPC_MUL_D = FOP(2, FMT_D),
6144 OPC_DIV_D = FOP(3, FMT_D),
6145 OPC_SQRT_D = FOP(4, FMT_D),
6146 OPC_ABS_D = FOP(5, FMT_D),
6147 OPC_MOV_D = FOP(6, FMT_D),
6148 OPC_NEG_D = FOP(7, FMT_D),
6149 OPC_ROUND_L_D = FOP(8, FMT_D),
6150 OPC_TRUNC_L_D = FOP(9, FMT_D),
6151 OPC_CEIL_L_D = FOP(10, FMT_D),
6152 OPC_FLOOR_L_D = FOP(11, FMT_D),
6153 OPC_ROUND_W_D = FOP(12, FMT_D),
6154 OPC_TRUNC_W_D = FOP(13, FMT_D),
6155 OPC_CEIL_W_D = FOP(14, FMT_D),
6156 OPC_FLOOR_W_D = FOP(15, FMT_D),
6157 OPC_MOVCF_D = FOP(17, FMT_D),
6158 OPC_MOVZ_D = FOP(18, FMT_D),
6159 OPC_MOVN_D = FOP(19, FMT_D),
6160 OPC_RECIP_D = FOP(21, FMT_D),
6161 OPC_RSQRT_D = FOP(22, FMT_D),
6162 OPC_RECIP2_D = FOP(28, FMT_D),
6163 OPC_RECIP1_D = FOP(29, FMT_D),
6164 OPC_RSQRT1_D = FOP(30, FMT_D),
6165 OPC_RSQRT2_D = FOP(31, FMT_D),
6166 OPC_CVT_S_D = FOP(32, FMT_D),
6167 OPC_CVT_W_D = FOP(36, FMT_D),
6168 OPC_CVT_L_D = FOP(37, FMT_D),
6169 OPC_CMP_F_D = FOP (48, FMT_D),
6170 OPC_CMP_UN_D = FOP (49, FMT_D),
6171 OPC_CMP_EQ_D = FOP (50, FMT_D),
6172 OPC_CMP_UEQ_D = FOP (51, FMT_D),
6173 OPC_CMP_OLT_D = FOP (52, FMT_D),
6174 OPC_CMP_ULT_D = FOP (53, FMT_D),
6175 OPC_CMP_OLE_D = FOP (54, FMT_D),
6176 OPC_CMP_ULE_D = FOP (55, FMT_D),
6177 OPC_CMP_SF_D = FOP (56, FMT_D),
6178 OPC_CMP_NGLE_D = FOP (57, FMT_D),
6179 OPC_CMP_SEQ_D = FOP (58, FMT_D),
6180 OPC_CMP_NGL_D = FOP (59, FMT_D),
6181 OPC_CMP_LT_D = FOP (60, FMT_D),
6182 OPC_CMP_NGE_D = FOP (61, FMT_D),
6183 OPC_CMP_LE_D = FOP (62, FMT_D),
6184 OPC_CMP_NGT_D = FOP (63, FMT_D),
6185
6186 OPC_CVT_S_W = FOP(32, FMT_W),
6187 OPC_CVT_D_W = FOP(33, FMT_W),
6188 OPC_CVT_S_L = FOP(32, FMT_L),
6189 OPC_CVT_D_L = FOP(33, FMT_L),
6190 OPC_CVT_PS_PW = FOP(38, FMT_W),
6191
6192 OPC_ADD_PS = FOP(0, FMT_PS),
6193 OPC_SUB_PS = FOP(1, FMT_PS),
6194 OPC_MUL_PS = FOP(2, FMT_PS),
6195 OPC_DIV_PS = FOP(3, FMT_PS),
6196 OPC_ABS_PS = FOP(5, FMT_PS),
6197 OPC_MOV_PS = FOP(6, FMT_PS),
6198 OPC_NEG_PS = FOP(7, FMT_PS),
6199 OPC_MOVCF_PS = FOP(17, FMT_PS),
6200 OPC_MOVZ_PS = FOP(18, FMT_PS),
6201 OPC_MOVN_PS = FOP(19, FMT_PS),
6202 OPC_ADDR_PS = FOP(24, FMT_PS),
6203 OPC_MULR_PS = FOP(26, FMT_PS),
6204 OPC_RECIP2_PS = FOP(28, FMT_PS),
6205 OPC_RECIP1_PS = FOP(29, FMT_PS),
6206 OPC_RSQRT1_PS = FOP(30, FMT_PS),
6207 OPC_RSQRT2_PS = FOP(31, FMT_PS),
6208
6209 OPC_CVT_S_PU = FOP(32, FMT_PS),
6210 OPC_CVT_PW_PS = FOP(36, FMT_PS),
6211 OPC_CVT_S_PL = FOP(40, FMT_PS),
6212 OPC_PLL_PS = FOP(44, FMT_PS),
6213 OPC_PLU_PS = FOP(45, FMT_PS),
6214 OPC_PUL_PS = FOP(46, FMT_PS),
6215 OPC_PUU_PS = FOP(47, FMT_PS),
6216 OPC_CMP_F_PS = FOP (48, FMT_PS),
6217 OPC_CMP_UN_PS = FOP (49, FMT_PS),
6218 OPC_CMP_EQ_PS = FOP (50, FMT_PS),
6219 OPC_CMP_UEQ_PS = FOP (51, FMT_PS),
6220 OPC_CMP_OLT_PS = FOP (52, FMT_PS),
6221 OPC_CMP_ULT_PS = FOP (53, FMT_PS),
6222 OPC_CMP_OLE_PS = FOP (54, FMT_PS),
6223 OPC_CMP_ULE_PS = FOP (55, FMT_PS),
6224 OPC_CMP_SF_PS = FOP (56, FMT_PS),
6225 OPC_CMP_NGLE_PS = FOP (57, FMT_PS),
6226 OPC_CMP_SEQ_PS = FOP (58, FMT_PS),
6227 OPC_CMP_NGL_PS = FOP (59, FMT_PS),
6228 OPC_CMP_LT_PS = FOP (60, FMT_PS),
6229 OPC_CMP_NGE_PS = FOP (61, FMT_PS),
6230 OPC_CMP_LE_PS = FOP (62, FMT_PS),
6231 OPC_CMP_NGT_PS = FOP (63, FMT_PS),
6232};
6233
7a387fff 6234static void gen_cp1 (DisasContext *ctx, uint32_t opc, int rt, int fs)
6ea83fed 6235{
923617a3 6236 const char *opn = "cp1 move";
72c3a3ee 6237 TCGv t0 = tcg_temp_new();
6ea83fed
FB
6238
6239 switch (opc) {
6240 case OPC_MFC1:
b6d96bed 6241 {
a7812ae4 6242 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed
TS
6243
6244 gen_load_fpr32(fp0, fs);
6245 tcg_gen_ext_i32_tl(t0, fp0);
a7812ae4 6246 tcg_temp_free_i32(fp0);
6958549d 6247 }
6c5c1e20 6248 gen_store_gpr(t0, rt);
6ea83fed
FB
6249 opn = "mfc1";
6250 break;
6251 case OPC_MTC1:
6c5c1e20 6252 gen_load_gpr(t0, rt);
b6d96bed 6253 {
a7812ae4 6254 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed
TS
6255
6256 tcg_gen_trunc_tl_i32(fp0, t0);
6257 gen_store_fpr32(fp0, fs);
a7812ae4 6258 tcg_temp_free_i32(fp0);
6958549d 6259 }
6ea83fed
FB
6260 opn = "mtc1";
6261 break;
6262 case OPC_CFC1:
a7812ae4 6263 gen_helper_1i(cfc1, t0, fs);
6c5c1e20 6264 gen_store_gpr(t0, rt);
6ea83fed
FB
6265 opn = "cfc1";
6266 break;
6267 case OPC_CTC1:
6c5c1e20 6268 gen_load_gpr(t0, rt);
a7812ae4 6269 gen_helper_1i(ctc1, t0, fs);
6ea83fed
FB
6270 opn = "ctc1";
6271 break;
72c3a3ee 6272#if defined(TARGET_MIPS64)
9c2149c8 6273 case OPC_DMFC1:
72c3a3ee 6274 gen_load_fpr64(ctx, t0, fs);
6c5c1e20 6275 gen_store_gpr(t0, rt);
5a5012ec
TS
6276 opn = "dmfc1";
6277 break;
9c2149c8 6278 case OPC_DMTC1:
6c5c1e20 6279 gen_load_gpr(t0, rt);
72c3a3ee 6280 gen_store_fpr64(ctx, t0, fs);
5a5012ec
TS
6281 opn = "dmtc1";
6282 break;
72c3a3ee 6283#endif
5a5012ec 6284 case OPC_MFHC1:
b6d96bed 6285 {
a7812ae4 6286 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed
TS
6287
6288 gen_load_fpr32h(fp0, fs);
6289 tcg_gen_ext_i32_tl(t0, fp0);
a7812ae4 6290 tcg_temp_free_i32(fp0);
6958549d 6291 }
6c5c1e20 6292 gen_store_gpr(t0, rt);
5a5012ec
TS
6293 opn = "mfhc1";
6294 break;
6295 case OPC_MTHC1:
6c5c1e20 6296 gen_load_gpr(t0, rt);
b6d96bed 6297 {
a7812ae4 6298 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed
TS
6299
6300 tcg_gen_trunc_tl_i32(fp0, t0);
6301 gen_store_fpr32h(fp0, fs);
a7812ae4 6302 tcg_temp_free_i32(fp0);
6958549d 6303 }
5a5012ec
TS
6304 opn = "mthc1";
6305 break;
6ea83fed 6306 default:
923617a3 6307 MIPS_INVAL(opn);
e397ee33 6308 generate_exception (ctx, EXCP_RI);
6c5c1e20 6309 goto out;
6ea83fed 6310 }
2abf314d 6311 (void)opn; /* avoid a compiler warning */
6ea83fed 6312 MIPS_DEBUG("%s %s %s", opn, regnames[rt], fregnames[fs]);
6c5c1e20
TS
6313
6314 out:
6315 tcg_temp_free(t0);
6ea83fed
FB
6316}
6317
5a5012ec
TS
6318static void gen_movci (DisasContext *ctx, int rd, int rs, int cc, int tf)
6319{
af58f9ca 6320 int l1;
e214b9bb 6321 TCGCond cond;
af58f9ca
AJ
6322 TCGv_i32 t0;
6323
6324 if (rd == 0) {
6325 /* Treat as NOP. */
6326 return;
6327 }
6ea83fed 6328
e214b9bb 6329 if (tf)
e214b9bb 6330 cond = TCG_COND_EQ;
27848470
TS
6331 else
6332 cond = TCG_COND_NE;
6333
af58f9ca
AJ
6334 l1 = gen_new_label();
6335 t0 = tcg_temp_new_i32();
fa31af0e 6336 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
af58f9ca 6337 tcg_gen_brcondi_i32(cond, t0, 0, l1);
a4e8338d 6338 tcg_temp_free_i32(t0);
af58f9ca
AJ
6339 if (rs == 0) {
6340 tcg_gen_movi_tl(cpu_gpr[rd], 0);
6341 } else {
6342 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
6343 }
e214b9bb 6344 gen_set_label(l1);
5a5012ec
TS
6345}
6346
b6d96bed 6347static inline void gen_movcf_s (int fs, int fd, int cc, int tf)
a16336e4 6348{
a16336e4 6349 int cond;
cbc37b28 6350 TCGv_i32 t0 = tcg_temp_new_i32();
a16336e4
TS
6351 int l1 = gen_new_label();
6352
a16336e4
TS
6353 if (tf)
6354 cond = TCG_COND_EQ;
6355 else
6356 cond = TCG_COND_NE;
6357
fa31af0e 6358 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
cbc37b28
AJ
6359 tcg_gen_brcondi_i32(cond, t0, 0, l1);
6360 gen_load_fpr32(t0, fs);
6361 gen_store_fpr32(t0, fd);
a16336e4 6362 gen_set_label(l1);
cbc37b28 6363 tcg_temp_free_i32(t0);
5a5012ec 6364}
a16336e4 6365
b6d96bed 6366static inline void gen_movcf_d (DisasContext *ctx, int fs, int fd, int cc, int tf)
a16336e4 6367{
a16336e4 6368 int cond;
cbc37b28
AJ
6369 TCGv_i32 t0 = tcg_temp_new_i32();
6370 TCGv_i64 fp0;
a16336e4
TS
6371 int l1 = gen_new_label();
6372
a16336e4
TS
6373 if (tf)
6374 cond = TCG_COND_EQ;
6375 else
6376 cond = TCG_COND_NE;
6377
fa31af0e 6378 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
cbc37b28 6379 tcg_gen_brcondi_i32(cond, t0, 0, l1);
a4e8338d 6380 tcg_temp_free_i32(t0);
11f94258 6381 fp0 = tcg_temp_new_i64();
9bf3eb2c 6382 gen_load_fpr64(ctx, fp0, fs);
9bf3eb2c 6383 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 6384 tcg_temp_free_i64(fp0);
cbc37b28 6385 gen_set_label(l1);
a16336e4
TS
6386}
6387
b6d96bed 6388static inline void gen_movcf_ps (int fs, int fd, int cc, int tf)
a16336e4
TS
6389{
6390 int cond;
cbc37b28 6391 TCGv_i32 t0 = tcg_temp_new_i32();
a16336e4
TS
6392 int l1 = gen_new_label();
6393 int l2 = gen_new_label();
6394
6395 if (tf)
6396 cond = TCG_COND_EQ;
6397 else
6398 cond = TCG_COND_NE;
6399
fa31af0e 6400 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
cbc37b28
AJ
6401 tcg_gen_brcondi_i32(cond, t0, 0, l1);
6402 gen_load_fpr32(t0, fs);
6403 gen_store_fpr32(t0, fd);
a16336e4 6404 gen_set_label(l1);
9bf3eb2c 6405
fa31af0e 6406 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc+1));
cbc37b28
AJ
6407 tcg_gen_brcondi_i32(cond, t0, 0, l2);
6408 gen_load_fpr32h(t0, fs);
6409 gen_store_fpr32h(t0, fd);
52a0e9eb 6410 tcg_temp_free_i32(t0);
a16336e4 6411 gen_set_label(l2);
a16336e4
TS
6412}
6413
6ea83fed 6414
bf4120ad 6415static void gen_farith (DisasContext *ctx, enum fopcode op1,
5e755519 6416 int ft, int fs, int fd, int cc)
6ea83fed 6417{
923617a3 6418 const char *opn = "farith";
6ea83fed
FB
6419 const char *condnames[] = {
6420 "c.f",
6421 "c.un",
6422 "c.eq",
6423 "c.ueq",
6424 "c.olt",
6425 "c.ult",
6426 "c.ole",
6427 "c.ule",
6428 "c.sf",
6429 "c.ngle",
6430 "c.seq",
6431 "c.ngl",
6432 "c.lt",
6433 "c.nge",
6434 "c.le",
6435 "c.ngt",
6436 };
5a1e8ffb
TS
6437 const char *condnames_abs[] = {
6438 "cabs.f",
6439 "cabs.un",
6440 "cabs.eq",
6441 "cabs.ueq",
6442 "cabs.olt",
6443 "cabs.ult",
6444 "cabs.ole",
6445 "cabs.ule",
6446 "cabs.sf",
6447 "cabs.ngle",
6448 "cabs.seq",
6449 "cabs.ngl",
6450 "cabs.lt",
6451 "cabs.nge",
6452 "cabs.le",
6453 "cabs.ngt",
6454 };
6455 enum { BINOP, CMPOP, OTHEROP } optype = OTHEROP;
7a387fff
TS
6456 uint32_t func = ctx->opcode & 0x3f;
6457
bf4120ad
NF
6458 switch (op1) {
6459 case OPC_ADD_S:
b6d96bed 6460 {
a7812ae4
PB
6461 TCGv_i32 fp0 = tcg_temp_new_i32();
6462 TCGv_i32 fp1 = tcg_temp_new_i32();
b6d96bed
TS
6463
6464 gen_load_fpr32(fp0, fs);
6465 gen_load_fpr32(fp1, ft);
a7812ae4
PB
6466 gen_helper_float_add_s(fp0, fp0, fp1);
6467 tcg_temp_free_i32(fp1);
b6d96bed 6468 gen_store_fpr32(fp0, fd);
a7812ae4 6469 tcg_temp_free_i32(fp0);
b6d96bed 6470 }
5a5012ec 6471 opn = "add.s";
5a1e8ffb 6472 optype = BINOP;
5a5012ec 6473 break;
bf4120ad 6474 case OPC_SUB_S:
b6d96bed 6475 {
a7812ae4
PB
6476 TCGv_i32 fp0 = tcg_temp_new_i32();
6477 TCGv_i32 fp1 = tcg_temp_new_i32();
b6d96bed
TS
6478
6479 gen_load_fpr32(fp0, fs);
6480 gen_load_fpr32(fp1, ft);
a7812ae4
PB
6481 gen_helper_float_sub_s(fp0, fp0, fp1);
6482 tcg_temp_free_i32(fp1);
b6d96bed 6483 gen_store_fpr32(fp0, fd);
a7812ae4 6484 tcg_temp_free_i32(fp0);
b6d96bed 6485 }
5a5012ec 6486 opn = "sub.s";
5a1e8ffb 6487 optype = BINOP;
5a5012ec 6488 break;
bf4120ad 6489 case OPC_MUL_S:
b6d96bed 6490 {
a7812ae4
PB
6491 TCGv_i32 fp0 = tcg_temp_new_i32();
6492 TCGv_i32 fp1 = tcg_temp_new_i32();
b6d96bed
TS
6493
6494 gen_load_fpr32(fp0, fs);
6495 gen_load_fpr32(fp1, ft);
a7812ae4
PB
6496 gen_helper_float_mul_s(fp0, fp0, fp1);
6497 tcg_temp_free_i32(fp1);
b6d96bed 6498 gen_store_fpr32(fp0, fd);
a7812ae4 6499 tcg_temp_free_i32(fp0);
b6d96bed 6500 }
5a5012ec 6501 opn = "mul.s";
5a1e8ffb 6502 optype = BINOP;
5a5012ec 6503 break;
bf4120ad 6504 case OPC_DIV_S:
b6d96bed 6505 {
a7812ae4
PB
6506 TCGv_i32 fp0 = tcg_temp_new_i32();
6507 TCGv_i32 fp1 = tcg_temp_new_i32();
b6d96bed
TS
6508
6509 gen_load_fpr32(fp0, fs);
6510 gen_load_fpr32(fp1, ft);
a7812ae4
PB
6511 gen_helper_float_div_s(fp0, fp0, fp1);
6512 tcg_temp_free_i32(fp1);
b6d96bed 6513 gen_store_fpr32(fp0, fd);
a7812ae4 6514 tcg_temp_free_i32(fp0);
b6d96bed 6515 }
5a5012ec 6516 opn = "div.s";
5a1e8ffb 6517 optype = BINOP;
5a5012ec 6518 break;
bf4120ad 6519 case OPC_SQRT_S:
b6d96bed 6520 {
a7812ae4 6521 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed
TS
6522
6523 gen_load_fpr32(fp0, fs);
a7812ae4 6524 gen_helper_float_sqrt_s(fp0, fp0);
b6d96bed 6525 gen_store_fpr32(fp0, fd);
a7812ae4 6526 tcg_temp_free_i32(fp0);
b6d96bed 6527 }
5a5012ec
TS
6528 opn = "sqrt.s";
6529 break;
bf4120ad 6530 case OPC_ABS_S:
b6d96bed 6531 {
a7812ae4 6532 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed
TS
6533
6534 gen_load_fpr32(fp0, fs);
a7812ae4 6535 gen_helper_float_abs_s(fp0, fp0);
b6d96bed 6536 gen_store_fpr32(fp0, fd);
a7812ae4 6537 tcg_temp_free_i32(fp0);
b6d96bed 6538 }
5a5012ec
TS
6539 opn = "abs.s";
6540 break;
bf4120ad 6541 case OPC_MOV_S:
b6d96bed 6542 {
a7812ae4 6543 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed
TS
6544
6545 gen_load_fpr32(fp0, fs);
6546 gen_store_fpr32(fp0, fd);
a7812ae4 6547 tcg_temp_free_i32(fp0);
b6d96bed 6548 }
5a5012ec
TS
6549 opn = "mov.s";
6550 break;
bf4120ad 6551 case OPC_NEG_S:
b6d96bed 6552 {
a7812ae4 6553 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed
TS
6554
6555 gen_load_fpr32(fp0, fs);
a7812ae4 6556 gen_helper_float_chs_s(fp0, fp0);
b6d96bed 6557 gen_store_fpr32(fp0, fd);
a7812ae4 6558 tcg_temp_free_i32(fp0);
b6d96bed 6559 }
5a5012ec
TS
6560 opn = "neg.s";
6561 break;
bf4120ad 6562 case OPC_ROUND_L_S:
5e755519 6563 check_cp1_64bitmode(ctx);
b6d96bed 6564 {
a7812ae4
PB
6565 TCGv_i32 fp32 = tcg_temp_new_i32();
6566 TCGv_i64 fp64 = tcg_temp_new_i64();
b6d96bed
TS
6567
6568 gen_load_fpr32(fp32, fs);
a7812ae4
PB
6569 gen_helper_float_roundl_s(fp64, fp32);
6570 tcg_temp_free_i32(fp32);
b6d96bed 6571 gen_store_fpr64(ctx, fp64, fd);
a7812ae4 6572 tcg_temp_free_i64(fp64);
b6d96bed 6573 }
5a5012ec
TS
6574 opn = "round.l.s";
6575 break;
bf4120ad 6576 case OPC_TRUNC_L_S:
5e755519 6577 check_cp1_64bitmode(ctx);
b6d96bed 6578 {
a7812ae4
PB
6579 TCGv_i32 fp32 = tcg_temp_new_i32();
6580 TCGv_i64 fp64 = tcg_temp_new_i64();
b6d96bed
TS
6581
6582 gen_load_fpr32(fp32, fs);
a7812ae4
PB
6583 gen_helper_float_truncl_s(fp64, fp32);
6584 tcg_temp_free_i32(fp32);
b6d96bed 6585 gen_store_fpr64(ctx, fp64, fd);
a7812ae4 6586 tcg_temp_free_i64(fp64);
b6d96bed 6587 }
5a5012ec
TS
6588 opn = "trunc.l.s";
6589 break;
bf4120ad 6590 case OPC_CEIL_L_S:
5e755519 6591 check_cp1_64bitmode(ctx);
b6d96bed 6592 {
a7812ae4
PB
6593 TCGv_i32 fp32 = tcg_temp_new_i32();
6594 TCGv_i64 fp64 = tcg_temp_new_i64();
b6d96bed
TS
6595
6596 gen_load_fpr32(fp32, fs);
a7812ae4
PB
6597 gen_helper_float_ceill_s(fp64, fp32);
6598 tcg_temp_free_i32(fp32);
b6d96bed 6599 gen_store_fpr64(ctx, fp64, fd);
a7812ae4 6600 tcg_temp_free_i64(fp64);
b6d96bed 6601 }
5a5012ec
TS
6602 opn = "ceil.l.s";
6603 break;
bf4120ad 6604 case OPC_FLOOR_L_S:
5e755519 6605 check_cp1_64bitmode(ctx);
b6d96bed 6606 {
a7812ae4
PB
6607 TCGv_i32 fp32 = tcg_temp_new_i32();
6608 TCGv_i64 fp64 = tcg_temp_new_i64();
b6d96bed
TS
6609
6610 gen_load_fpr32(fp32, fs);
a7812ae4
PB
6611 gen_helper_float_floorl_s(fp64, fp32);
6612 tcg_temp_free_i32(fp32);
b6d96bed 6613 gen_store_fpr64(ctx, fp64, fd);
a7812ae4 6614 tcg_temp_free_i64(fp64);
b6d96bed 6615 }
5a5012ec
TS
6616 opn = "floor.l.s";
6617 break;
bf4120ad 6618 case OPC_ROUND_W_S:
b6d96bed 6619 {
a7812ae4 6620 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed
TS
6621
6622 gen_load_fpr32(fp0, fs);
a7812ae4 6623 gen_helper_float_roundw_s(fp0, fp0);
b6d96bed 6624 gen_store_fpr32(fp0, fd);
a7812ae4 6625 tcg_temp_free_i32(fp0);
b6d96bed 6626 }
5a5012ec
TS
6627 opn = "round.w.s";
6628 break;
bf4120ad 6629 case OPC_TRUNC_W_S:
b6d96bed 6630 {
a7812ae4 6631 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed
TS
6632
6633 gen_load_fpr32(fp0, fs);
a7812ae4 6634 gen_helper_float_truncw_s(fp0, fp0);
b6d96bed 6635 gen_store_fpr32(fp0, fd);
a7812ae4 6636 tcg_temp_free_i32(fp0);
b6d96bed 6637 }
5a5012ec
TS
6638 opn = "trunc.w.s";
6639 break;
bf4120ad 6640 case OPC_CEIL_W_S:
b6d96bed 6641 {
a7812ae4 6642 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed
TS
6643
6644 gen_load_fpr32(fp0, fs);
a7812ae4 6645 gen_helper_float_ceilw_s(fp0, fp0);
b6d96bed 6646 gen_store_fpr32(fp0, fd);
a7812ae4 6647 tcg_temp_free_i32(fp0);
b6d96bed 6648 }
5a5012ec
TS
6649 opn = "ceil.w.s";
6650 break;
bf4120ad 6651 case OPC_FLOOR_W_S:
b6d96bed 6652 {
a7812ae4 6653 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed
TS
6654
6655 gen_load_fpr32(fp0, fs);
a7812ae4 6656 gen_helper_float_floorw_s(fp0, fp0);
b6d96bed 6657 gen_store_fpr32(fp0, fd);
a7812ae4 6658 tcg_temp_free_i32(fp0);
b6d96bed 6659 }
5a5012ec
TS
6660 opn = "floor.w.s";
6661 break;
bf4120ad 6662 case OPC_MOVCF_S:
b6d96bed 6663 gen_movcf_s(fs, fd, (ft >> 2) & 0x7, ft & 0x1);
5a5012ec
TS
6664 opn = "movcf.s";
6665 break;
bf4120ad 6666 case OPC_MOVZ_S:
a16336e4
TS
6667 {
6668 int l1 = gen_new_label();
c9297f4d 6669 TCGv_i32 fp0;
a16336e4 6670
c9297f4d
AJ
6671 if (ft != 0) {
6672 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[ft], 0, l1);
6673 }
6674 fp0 = tcg_temp_new_i32();
b6d96bed
TS
6675 gen_load_fpr32(fp0, fs);
6676 gen_store_fpr32(fp0, fd);
a7812ae4 6677 tcg_temp_free_i32(fp0);
a16336e4
TS
6678 gen_set_label(l1);
6679 }
5a5012ec
TS
6680 opn = "movz.s";
6681 break;
bf4120ad 6682 case OPC_MOVN_S:
a16336e4
TS
6683 {
6684 int l1 = gen_new_label();
c9297f4d
AJ
6685 TCGv_i32 fp0;
6686
6687 if (ft != 0) {
6688 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[ft], 0, l1);
6689 fp0 = tcg_temp_new_i32();
6690 gen_load_fpr32(fp0, fs);
6691 gen_store_fpr32(fp0, fd);
6692 tcg_temp_free_i32(fp0);
6693 gen_set_label(l1);
6694 }
a16336e4 6695 }
5a5012ec
TS
6696 opn = "movn.s";
6697 break;
bf4120ad 6698 case OPC_RECIP_S:
b8aa4598 6699 check_cop1x(ctx);
b6d96bed 6700 {
a7812ae4 6701 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed
TS
6702
6703 gen_load_fpr32(fp0, fs);
a7812ae4 6704 gen_helper_float_recip_s(fp0, fp0);
b6d96bed 6705 gen_store_fpr32(fp0, fd);
a7812ae4 6706 tcg_temp_free_i32(fp0);
b6d96bed 6707 }
57fa1fb3
TS
6708 opn = "recip.s";
6709 break;
bf4120ad 6710 case OPC_RSQRT_S:
b8aa4598 6711 check_cop1x(ctx);
b6d96bed 6712 {
a7812ae4 6713 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed
TS
6714
6715 gen_load_fpr32(fp0, fs);
a7812ae4 6716 gen_helper_float_rsqrt_s(fp0, fp0);
b6d96bed 6717 gen_store_fpr32(fp0, fd);
a7812ae4 6718 tcg_temp_free_i32(fp0);
b6d96bed 6719 }
57fa1fb3
TS
6720 opn = "rsqrt.s";
6721 break;
bf4120ad 6722 case OPC_RECIP2_S:
5e755519 6723 check_cp1_64bitmode(ctx);
b6d96bed 6724 {
a7812ae4
PB
6725 TCGv_i32 fp0 = tcg_temp_new_i32();
6726 TCGv_i32 fp1 = tcg_temp_new_i32();
b6d96bed
TS
6727
6728 gen_load_fpr32(fp0, fs);
6729 gen_load_fpr32(fp1, fd);
a7812ae4
PB
6730 gen_helper_float_recip2_s(fp0, fp0, fp1);
6731 tcg_temp_free_i32(fp1);
b6d96bed 6732 gen_store_fpr32(fp0, fd);
a7812ae4 6733 tcg_temp_free_i32(fp0);
b6d96bed 6734 }
57fa1fb3
TS
6735 opn = "recip2.s";
6736 break;
bf4120ad 6737 case OPC_RECIP1_S:
5e755519 6738 check_cp1_64bitmode(ctx);
b6d96bed 6739 {
a7812ae4 6740 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed
TS
6741
6742 gen_load_fpr32(fp0, fs);
a7812ae4 6743 gen_helper_float_recip1_s(fp0, fp0);
b6d96bed 6744 gen_store_fpr32(fp0, fd);
a7812ae4 6745 tcg_temp_free_i32(fp0);
b6d96bed 6746 }
57fa1fb3
TS
6747 opn = "recip1.s";
6748 break;
bf4120ad 6749 case OPC_RSQRT1_S:
5e755519 6750 check_cp1_64bitmode(ctx);
b6d96bed 6751 {
a7812ae4 6752 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed
TS
6753
6754 gen_load_fpr32(fp0, fs);
a7812ae4 6755 gen_helper_float_rsqrt1_s(fp0, fp0);
b6d96bed 6756 gen_store_fpr32(fp0, fd);
a7812ae4 6757 tcg_temp_free_i32(fp0);
b6d96bed 6758 }
57fa1fb3
TS
6759 opn = "rsqrt1.s";
6760 break;
bf4120ad 6761 case OPC_RSQRT2_S:
5e755519 6762 check_cp1_64bitmode(ctx);
b6d96bed 6763 {
a7812ae4
PB
6764 TCGv_i32 fp0 = tcg_temp_new_i32();
6765 TCGv_i32 fp1 = tcg_temp_new_i32();
b6d96bed
TS
6766
6767 gen_load_fpr32(fp0, fs);
6768 gen_load_fpr32(fp1, ft);
a7812ae4
PB
6769 gen_helper_float_rsqrt2_s(fp0, fp0, fp1);
6770 tcg_temp_free_i32(fp1);
b6d96bed 6771 gen_store_fpr32(fp0, fd);
a7812ae4 6772 tcg_temp_free_i32(fp0);
b6d96bed 6773 }
57fa1fb3
TS
6774 opn = "rsqrt2.s";
6775 break;
bf4120ad 6776 case OPC_CVT_D_S:
5e755519 6777 check_cp1_registers(ctx, fd);
b6d96bed 6778 {
a7812ae4
PB
6779 TCGv_i32 fp32 = tcg_temp_new_i32();
6780 TCGv_i64 fp64 = tcg_temp_new_i64();
b6d96bed
TS
6781
6782 gen_load_fpr32(fp32, fs);
a7812ae4
PB
6783 gen_helper_float_cvtd_s(fp64, fp32);
6784 tcg_temp_free_i32(fp32);
b6d96bed 6785 gen_store_fpr64(ctx, fp64, fd);
a7812ae4 6786 tcg_temp_free_i64(fp64);
b6d96bed 6787 }
5a5012ec
TS
6788 opn = "cvt.d.s";
6789 break;
bf4120ad 6790 case OPC_CVT_W_S:
b6d96bed 6791 {
a7812ae4 6792 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed
TS
6793
6794 gen_load_fpr32(fp0, fs);
a7812ae4 6795 gen_helper_float_cvtw_s(fp0, fp0);
b6d96bed 6796 gen_store_fpr32(fp0, fd);
a7812ae4 6797 tcg_temp_free_i32(fp0);
b6d96bed 6798 }
5a5012ec
TS
6799 opn = "cvt.w.s";
6800 break;
bf4120ad 6801 case OPC_CVT_L_S:
5e755519 6802 check_cp1_64bitmode(ctx);
b6d96bed 6803 {
a7812ae4
PB
6804 TCGv_i32 fp32 = tcg_temp_new_i32();
6805 TCGv_i64 fp64 = tcg_temp_new_i64();
b6d96bed
TS
6806
6807 gen_load_fpr32(fp32, fs);
a7812ae4
PB
6808 gen_helper_float_cvtl_s(fp64, fp32);
6809 tcg_temp_free_i32(fp32);
b6d96bed 6810 gen_store_fpr64(ctx, fp64, fd);
a7812ae4 6811 tcg_temp_free_i64(fp64);
b6d96bed 6812 }
5a5012ec
TS
6813 opn = "cvt.l.s";
6814 break;
bf4120ad 6815 case OPC_CVT_PS_S:
5e755519 6816 check_cp1_64bitmode(ctx);
b6d96bed 6817 {
a7812ae4
PB
6818 TCGv_i64 fp64 = tcg_temp_new_i64();
6819 TCGv_i32 fp32_0 = tcg_temp_new_i32();
6820 TCGv_i32 fp32_1 = tcg_temp_new_i32();
b6d96bed
TS
6821
6822 gen_load_fpr32(fp32_0, fs);
6823 gen_load_fpr32(fp32_1, ft);
36aa55dc 6824 tcg_gen_concat_i32_i64(fp64, fp32_0, fp32_1);
a7812ae4
PB
6825 tcg_temp_free_i32(fp32_1);
6826 tcg_temp_free_i32(fp32_0);
36aa55dc 6827 gen_store_fpr64(ctx, fp64, fd);
a7812ae4 6828 tcg_temp_free_i64(fp64);
b6d96bed 6829 }
5a5012ec
TS
6830 opn = "cvt.ps.s";
6831 break;
bf4120ad
NF
6832 case OPC_CMP_F_S:
6833 case OPC_CMP_UN_S:
6834 case OPC_CMP_EQ_S:
6835 case OPC_CMP_UEQ_S:
6836 case OPC_CMP_OLT_S:
6837 case OPC_CMP_ULT_S:
6838 case OPC_CMP_OLE_S:
6839 case OPC_CMP_ULE_S:
6840 case OPC_CMP_SF_S:
6841 case OPC_CMP_NGLE_S:
6842 case OPC_CMP_SEQ_S:
6843 case OPC_CMP_NGL_S:
6844 case OPC_CMP_LT_S:
6845 case OPC_CMP_NGE_S:
6846 case OPC_CMP_LE_S:
6847 case OPC_CMP_NGT_S:
8153667c
NF
6848 if (ctx->opcode & (1 << 6)) {
6849 gen_cmpabs_s(ctx, func-48, ft, fs, cc);
6850 opn = condnames_abs[func-48];
6851 } else {
6852 gen_cmp_s(ctx, func-48, ft, fs, cc);
6853 opn = condnames[func-48];
5a1e8ffb 6854 }
5a5012ec 6855 break;
bf4120ad 6856 case OPC_ADD_D:
5e755519 6857 check_cp1_registers(ctx, fs | ft | fd);
b6d96bed 6858 {
a7812ae4
PB
6859 TCGv_i64 fp0 = tcg_temp_new_i64();
6860 TCGv_i64 fp1 = tcg_temp_new_i64();
b6d96bed
TS
6861
6862 gen_load_fpr64(ctx, fp0, fs);
6863 gen_load_fpr64(ctx, fp1, ft);
a7812ae4
PB
6864 gen_helper_float_add_d(fp0, fp0, fp1);
6865 tcg_temp_free_i64(fp1);
b6d96bed 6866 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 6867 tcg_temp_free_i64(fp0);
b6d96bed 6868 }
6ea83fed 6869 opn = "add.d";
5a1e8ffb 6870 optype = BINOP;
6ea83fed 6871 break;
bf4120ad 6872 case OPC_SUB_D:
5e755519 6873 check_cp1_registers(ctx, fs | ft | fd);
b6d96bed 6874 {
a7812ae4
PB
6875 TCGv_i64 fp0 = tcg_temp_new_i64();
6876 TCGv_i64 fp1 = tcg_temp_new_i64();
b6d96bed
TS
6877
6878 gen_load_fpr64(ctx, fp0, fs);
6879 gen_load_fpr64(ctx, fp1, ft);
a7812ae4
PB
6880 gen_helper_float_sub_d(fp0, fp0, fp1);
6881 tcg_temp_free_i64(fp1);
b6d96bed 6882 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 6883 tcg_temp_free_i64(fp0);
b6d96bed 6884 }
6ea83fed 6885 opn = "sub.d";
5a1e8ffb 6886 optype = BINOP;
6ea83fed 6887 break;
bf4120ad 6888 case OPC_MUL_D:
5e755519 6889 check_cp1_registers(ctx, fs | ft | fd);
b6d96bed 6890 {
a7812ae4
PB
6891 TCGv_i64 fp0 = tcg_temp_new_i64();
6892 TCGv_i64 fp1 = tcg_temp_new_i64();
b6d96bed
TS
6893
6894 gen_load_fpr64(ctx, fp0, fs);
6895 gen_load_fpr64(ctx, fp1, ft);
a7812ae4
PB
6896 gen_helper_float_mul_d(fp0, fp0, fp1);
6897 tcg_temp_free_i64(fp1);
b6d96bed 6898 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 6899 tcg_temp_free_i64(fp0);
b6d96bed 6900 }
6ea83fed 6901 opn = "mul.d";
5a1e8ffb 6902 optype = BINOP;
6ea83fed 6903 break;
bf4120ad 6904 case OPC_DIV_D:
5e755519 6905 check_cp1_registers(ctx, fs | ft | fd);
b6d96bed 6906 {
a7812ae4
PB
6907 TCGv_i64 fp0 = tcg_temp_new_i64();
6908 TCGv_i64 fp1 = tcg_temp_new_i64();
b6d96bed
TS
6909
6910 gen_load_fpr64(ctx, fp0, fs);
6911 gen_load_fpr64(ctx, fp1, ft);
a7812ae4
PB
6912 gen_helper_float_div_d(fp0, fp0, fp1);
6913 tcg_temp_free_i64(fp1);
b6d96bed 6914 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 6915 tcg_temp_free_i64(fp0);
b6d96bed 6916 }
6ea83fed 6917 opn = "div.d";
5a1e8ffb 6918 optype = BINOP;
6ea83fed 6919 break;
bf4120ad 6920 case OPC_SQRT_D:
5e755519 6921 check_cp1_registers(ctx, fs | fd);
b6d96bed 6922 {
a7812ae4 6923 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
6924
6925 gen_load_fpr64(ctx, fp0, fs);
a7812ae4 6926 gen_helper_float_sqrt_d(fp0, fp0);
b6d96bed 6927 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 6928 tcg_temp_free_i64(fp0);
b6d96bed 6929 }
6ea83fed
FB
6930 opn = "sqrt.d";
6931 break;
bf4120ad 6932 case OPC_ABS_D:
5e755519 6933 check_cp1_registers(ctx, fs | fd);
b6d96bed 6934 {
a7812ae4 6935 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
6936
6937 gen_load_fpr64(ctx, fp0, fs);
a7812ae4 6938 gen_helper_float_abs_d(fp0, fp0);
b6d96bed 6939 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 6940 tcg_temp_free_i64(fp0);
b6d96bed 6941 }
6ea83fed
FB
6942 opn = "abs.d";
6943 break;
bf4120ad 6944 case OPC_MOV_D:
5e755519 6945 check_cp1_registers(ctx, fs | fd);
b6d96bed 6946 {
a7812ae4 6947 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
6948
6949 gen_load_fpr64(ctx, fp0, fs);
6950 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 6951 tcg_temp_free_i64(fp0);
b6d96bed 6952 }
6ea83fed
FB
6953 opn = "mov.d";
6954 break;
bf4120ad 6955 case OPC_NEG_D:
5e755519 6956 check_cp1_registers(ctx, fs | fd);
b6d96bed 6957 {
a7812ae4 6958 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
6959
6960 gen_load_fpr64(ctx, fp0, fs);
a7812ae4 6961 gen_helper_float_chs_d(fp0, fp0);
b6d96bed 6962 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 6963 tcg_temp_free_i64(fp0);
b6d96bed 6964 }
6ea83fed
FB
6965 opn = "neg.d";
6966 break;
bf4120ad 6967 case OPC_ROUND_L_D:
5e755519 6968 check_cp1_64bitmode(ctx);
b6d96bed 6969 {
a7812ae4 6970 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
6971
6972 gen_load_fpr64(ctx, fp0, fs);
a7812ae4 6973 gen_helper_float_roundl_d(fp0, fp0);
b6d96bed 6974 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 6975 tcg_temp_free_i64(fp0);
b6d96bed 6976 }
5a5012ec
TS
6977 opn = "round.l.d";
6978 break;
bf4120ad 6979 case OPC_TRUNC_L_D:
5e755519 6980 check_cp1_64bitmode(ctx);
b6d96bed 6981 {
a7812ae4 6982 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
6983
6984 gen_load_fpr64(ctx, fp0, fs);
a7812ae4 6985 gen_helper_float_truncl_d(fp0, fp0);
b6d96bed 6986 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 6987 tcg_temp_free_i64(fp0);
b6d96bed 6988 }
5a5012ec
TS
6989 opn = "trunc.l.d";
6990 break;
bf4120ad 6991 case OPC_CEIL_L_D:
5e755519 6992 check_cp1_64bitmode(ctx);
b6d96bed 6993 {
a7812ae4 6994 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
6995
6996 gen_load_fpr64(ctx, fp0, fs);
a7812ae4 6997 gen_helper_float_ceill_d(fp0, fp0);
b6d96bed 6998 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 6999 tcg_temp_free_i64(fp0);
b6d96bed 7000 }
5a5012ec
TS
7001 opn = "ceil.l.d";
7002 break;
bf4120ad 7003 case OPC_FLOOR_L_D:
5e755519 7004 check_cp1_64bitmode(ctx);
b6d96bed 7005 {
a7812ae4 7006 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
7007
7008 gen_load_fpr64(ctx, fp0, fs);
a7812ae4 7009 gen_helper_float_floorl_d(fp0, fp0);
b6d96bed 7010 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 7011 tcg_temp_free_i64(fp0);
b6d96bed 7012 }
5a5012ec
TS
7013 opn = "floor.l.d";
7014 break;
bf4120ad 7015 case OPC_ROUND_W_D:
5e755519 7016 check_cp1_registers(ctx, fs);
b6d96bed 7017 {
a7812ae4
PB
7018 TCGv_i32 fp32 = tcg_temp_new_i32();
7019 TCGv_i64 fp64 = tcg_temp_new_i64();
b6d96bed
TS
7020
7021 gen_load_fpr64(ctx, fp64, fs);
a7812ae4
PB
7022 gen_helper_float_roundw_d(fp32, fp64);
7023 tcg_temp_free_i64(fp64);
b6d96bed 7024 gen_store_fpr32(fp32, fd);
a7812ae4 7025 tcg_temp_free_i32(fp32);
b6d96bed 7026 }
6ea83fed
FB
7027 opn = "round.w.d";
7028 break;
bf4120ad 7029 case OPC_TRUNC_W_D:
5e755519 7030 check_cp1_registers(ctx, fs);
b6d96bed 7031 {
a7812ae4
PB
7032 TCGv_i32 fp32 = tcg_temp_new_i32();
7033 TCGv_i64 fp64 = tcg_temp_new_i64();
b6d96bed
TS
7034
7035 gen_load_fpr64(ctx, fp64, fs);
a7812ae4
PB
7036 gen_helper_float_truncw_d(fp32, fp64);
7037 tcg_temp_free_i64(fp64);
b6d96bed 7038 gen_store_fpr32(fp32, fd);
a7812ae4 7039 tcg_temp_free_i32(fp32);
b6d96bed 7040 }
6ea83fed
FB
7041 opn = "trunc.w.d";
7042 break;
bf4120ad 7043 case OPC_CEIL_W_D:
5e755519 7044 check_cp1_registers(ctx, fs);
b6d96bed 7045 {
a7812ae4
PB
7046 TCGv_i32 fp32 = tcg_temp_new_i32();
7047 TCGv_i64 fp64 = tcg_temp_new_i64();
b6d96bed
TS
7048
7049 gen_load_fpr64(ctx, fp64, fs);
a7812ae4
PB
7050 gen_helper_float_ceilw_d(fp32, fp64);
7051 tcg_temp_free_i64(fp64);
b6d96bed 7052 gen_store_fpr32(fp32, fd);
a7812ae4 7053 tcg_temp_free_i32(fp32);
b6d96bed 7054 }
6ea83fed
FB
7055 opn = "ceil.w.d";
7056 break;
bf4120ad 7057 case OPC_FLOOR_W_D:
5e755519 7058 check_cp1_registers(ctx, fs);
b6d96bed 7059 {
a7812ae4
PB
7060 TCGv_i32 fp32 = tcg_temp_new_i32();
7061 TCGv_i64 fp64 = tcg_temp_new_i64();
b6d96bed
TS
7062
7063 gen_load_fpr64(ctx, fp64, fs);
a7812ae4
PB
7064 gen_helper_float_floorw_d(fp32, fp64);
7065 tcg_temp_free_i64(fp64);
b6d96bed 7066 gen_store_fpr32(fp32, fd);
a7812ae4 7067 tcg_temp_free_i32(fp32);
b6d96bed 7068 }
7a387fff 7069 opn = "floor.w.d";
6ea83fed 7070 break;
bf4120ad 7071 case OPC_MOVCF_D:
b6d96bed 7072 gen_movcf_d(ctx, fs, fd, (ft >> 2) & 0x7, ft & 0x1);
5a5012ec 7073 opn = "movcf.d";
dd016883 7074 break;
bf4120ad 7075 case OPC_MOVZ_D:
a16336e4
TS
7076 {
7077 int l1 = gen_new_label();
c9297f4d 7078 TCGv_i64 fp0;
a16336e4 7079
c9297f4d
AJ
7080 if (ft != 0) {
7081 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[ft], 0, l1);
7082 }
7083 fp0 = tcg_temp_new_i64();
b6d96bed
TS
7084 gen_load_fpr64(ctx, fp0, fs);
7085 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 7086 tcg_temp_free_i64(fp0);
a16336e4
TS
7087 gen_set_label(l1);
7088 }
5a5012ec
TS
7089 opn = "movz.d";
7090 break;
bf4120ad 7091 case OPC_MOVN_D:
a16336e4
TS
7092 {
7093 int l1 = gen_new_label();
c9297f4d
AJ
7094 TCGv_i64 fp0;
7095
7096 if (ft != 0) {
7097 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[ft], 0, l1);
7098 fp0 = tcg_temp_new_i64();
7099 gen_load_fpr64(ctx, fp0, fs);
7100 gen_store_fpr64(ctx, fp0, fd);
7101 tcg_temp_free_i64(fp0);
7102 gen_set_label(l1);
7103 }
a16336e4 7104 }
5a5012ec 7105 opn = "movn.d";
6ea83fed 7106 break;
bf4120ad 7107 case OPC_RECIP_D:
b8aa4598 7108 check_cp1_64bitmode(ctx);
b6d96bed 7109 {
a7812ae4 7110 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
7111
7112 gen_load_fpr64(ctx, fp0, fs);
a7812ae4 7113 gen_helper_float_recip_d(fp0, fp0);
b6d96bed 7114 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 7115 tcg_temp_free_i64(fp0);
b6d96bed 7116 }
57fa1fb3
TS
7117 opn = "recip.d";
7118 break;
bf4120ad 7119 case OPC_RSQRT_D:
b8aa4598 7120 check_cp1_64bitmode(ctx);
b6d96bed 7121 {
a7812ae4 7122 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
7123
7124 gen_load_fpr64(ctx, fp0, fs);
a7812ae4 7125 gen_helper_float_rsqrt_d(fp0, fp0);
b6d96bed 7126 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 7127 tcg_temp_free_i64(fp0);
b6d96bed 7128 }
57fa1fb3
TS
7129 opn = "rsqrt.d";
7130 break;
bf4120ad 7131 case OPC_RECIP2_D:
5e755519 7132 check_cp1_64bitmode(ctx);
b6d96bed 7133 {
a7812ae4
PB
7134 TCGv_i64 fp0 = tcg_temp_new_i64();
7135 TCGv_i64 fp1 = tcg_temp_new_i64();
b6d96bed
TS
7136
7137 gen_load_fpr64(ctx, fp0, fs);
7138 gen_load_fpr64(ctx, fp1, ft);
a7812ae4
PB
7139 gen_helper_float_recip2_d(fp0, fp0, fp1);
7140 tcg_temp_free_i64(fp1);
b6d96bed 7141 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 7142 tcg_temp_free_i64(fp0);
b6d96bed 7143 }
57fa1fb3
TS
7144 opn = "recip2.d";
7145 break;
bf4120ad 7146 case OPC_RECIP1_D:
5e755519 7147 check_cp1_64bitmode(ctx);
b6d96bed 7148 {
a7812ae4 7149 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
7150
7151 gen_load_fpr64(ctx, fp0, fs);
a7812ae4 7152 gen_helper_float_recip1_d(fp0, fp0);
b6d96bed 7153 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 7154 tcg_temp_free_i64(fp0);
b6d96bed 7155 }
57fa1fb3
TS
7156 opn = "recip1.d";
7157 break;
bf4120ad 7158 case OPC_RSQRT1_D:
5e755519 7159 check_cp1_64bitmode(ctx);
b6d96bed 7160 {
a7812ae4 7161 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
7162
7163 gen_load_fpr64(ctx, fp0, fs);
a7812ae4 7164 gen_helper_float_rsqrt1_d(fp0, fp0);
b6d96bed 7165 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 7166 tcg_temp_free_i64(fp0);
b6d96bed 7167 }
57fa1fb3
TS
7168 opn = "rsqrt1.d";
7169 break;
bf4120ad 7170 case OPC_RSQRT2_D:
5e755519 7171 check_cp1_64bitmode(ctx);
b6d96bed 7172 {
a7812ae4
PB
7173 TCGv_i64 fp0 = tcg_temp_new_i64();
7174 TCGv_i64 fp1 = tcg_temp_new_i64();
b6d96bed
TS
7175
7176 gen_load_fpr64(ctx, fp0, fs);
7177 gen_load_fpr64(ctx, fp1, ft);
a7812ae4
PB
7178 gen_helper_float_rsqrt2_d(fp0, fp0, fp1);
7179 tcg_temp_free_i64(fp1);
b6d96bed 7180 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 7181 tcg_temp_free_i64(fp0);
b6d96bed 7182 }
57fa1fb3
TS
7183 opn = "rsqrt2.d";
7184 break;
bf4120ad
NF
7185 case OPC_CMP_F_D:
7186 case OPC_CMP_UN_D:
7187 case OPC_CMP_EQ_D:
7188 case OPC_CMP_UEQ_D:
7189 case OPC_CMP_OLT_D:
7190 case OPC_CMP_ULT_D:
7191 case OPC_CMP_OLE_D:
7192 case OPC_CMP_ULE_D:
7193 case OPC_CMP_SF_D:
7194 case OPC_CMP_NGLE_D:
7195 case OPC_CMP_SEQ_D:
7196 case OPC_CMP_NGL_D:
7197 case OPC_CMP_LT_D:
7198 case OPC_CMP_NGE_D:
7199 case OPC_CMP_LE_D:
7200 case OPC_CMP_NGT_D:
8153667c
NF
7201 if (ctx->opcode & (1 << 6)) {
7202 gen_cmpabs_d(ctx, func-48, ft, fs, cc);
7203 opn = condnames_abs[func-48];
7204 } else {
7205 gen_cmp_d(ctx, func-48, ft, fs, cc);
7206 opn = condnames[func-48];
5a1e8ffb 7207 }
6ea83fed 7208 break;
bf4120ad 7209 case OPC_CVT_S_D:
5e755519 7210 check_cp1_registers(ctx, fs);
b6d96bed 7211 {
a7812ae4
PB
7212 TCGv_i32 fp32 = tcg_temp_new_i32();
7213 TCGv_i64 fp64 = tcg_temp_new_i64();
b6d96bed
TS
7214
7215 gen_load_fpr64(ctx, fp64, fs);
a7812ae4
PB
7216 gen_helper_float_cvts_d(fp32, fp64);
7217 tcg_temp_free_i64(fp64);
b6d96bed 7218 gen_store_fpr32(fp32, fd);
a7812ae4 7219 tcg_temp_free_i32(fp32);
b6d96bed 7220 }
5a5012ec
TS
7221 opn = "cvt.s.d";
7222 break;
bf4120ad 7223 case OPC_CVT_W_D:
5e755519 7224 check_cp1_registers(ctx, fs);
b6d96bed 7225 {
a7812ae4
PB
7226 TCGv_i32 fp32 = tcg_temp_new_i32();
7227 TCGv_i64 fp64 = tcg_temp_new_i64();
b6d96bed
TS
7228
7229 gen_load_fpr64(ctx, fp64, fs);
a7812ae4
PB
7230 gen_helper_float_cvtw_d(fp32, fp64);
7231 tcg_temp_free_i64(fp64);
b6d96bed 7232 gen_store_fpr32(fp32, fd);
a7812ae4 7233 tcg_temp_free_i32(fp32);
b6d96bed 7234 }
5a5012ec
TS
7235 opn = "cvt.w.d";
7236 break;
bf4120ad 7237 case OPC_CVT_L_D:
5e755519 7238 check_cp1_64bitmode(ctx);
b6d96bed 7239 {
a7812ae4 7240 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
7241
7242 gen_load_fpr64(ctx, fp0, fs);
a7812ae4 7243 gen_helper_float_cvtl_d(fp0, fp0);
b6d96bed 7244 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 7245 tcg_temp_free_i64(fp0);
b6d96bed 7246 }
5a5012ec
TS
7247 opn = "cvt.l.d";
7248 break;
bf4120ad 7249 case OPC_CVT_S_W:
b6d96bed 7250 {
a7812ae4 7251 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed
TS
7252
7253 gen_load_fpr32(fp0, fs);
a7812ae4 7254 gen_helper_float_cvts_w(fp0, fp0);
b6d96bed 7255 gen_store_fpr32(fp0, fd);
a7812ae4 7256 tcg_temp_free_i32(fp0);
b6d96bed 7257 }
5a5012ec 7258 opn = "cvt.s.w";
6ea83fed 7259 break;
bf4120ad 7260 case OPC_CVT_D_W:
5e755519 7261 check_cp1_registers(ctx, fd);
b6d96bed 7262 {
a7812ae4
PB
7263 TCGv_i32 fp32 = tcg_temp_new_i32();
7264 TCGv_i64 fp64 = tcg_temp_new_i64();
b6d96bed
TS
7265
7266 gen_load_fpr32(fp32, fs);
a7812ae4
PB
7267 gen_helper_float_cvtd_w(fp64, fp32);
7268 tcg_temp_free_i32(fp32);
b6d96bed 7269 gen_store_fpr64(ctx, fp64, fd);
a7812ae4 7270 tcg_temp_free_i64(fp64);
b6d96bed 7271 }
5a5012ec
TS
7272 opn = "cvt.d.w";
7273 break;
bf4120ad 7274 case OPC_CVT_S_L:
5e755519 7275 check_cp1_64bitmode(ctx);
b6d96bed 7276 {
a7812ae4
PB
7277 TCGv_i32 fp32 = tcg_temp_new_i32();
7278 TCGv_i64 fp64 = tcg_temp_new_i64();
b6d96bed
TS
7279
7280 gen_load_fpr64(ctx, fp64, fs);
a7812ae4
PB
7281 gen_helper_float_cvts_l(fp32, fp64);
7282 tcg_temp_free_i64(fp64);
b6d96bed 7283 gen_store_fpr32(fp32, fd);
a7812ae4 7284 tcg_temp_free_i32(fp32);
b6d96bed 7285 }
5a5012ec
TS
7286 opn = "cvt.s.l";
7287 break;
bf4120ad 7288 case OPC_CVT_D_L:
5e755519 7289 check_cp1_64bitmode(ctx);
b6d96bed 7290 {
a7812ae4 7291 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
7292
7293 gen_load_fpr64(ctx, fp0, fs);
a7812ae4 7294 gen_helper_float_cvtd_l(fp0, fp0);
b6d96bed 7295 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 7296 tcg_temp_free_i64(fp0);
b6d96bed 7297 }
5a5012ec
TS
7298 opn = "cvt.d.l";
7299 break;
bf4120ad 7300 case OPC_CVT_PS_PW:
5e755519 7301 check_cp1_64bitmode(ctx);
b6d96bed 7302 {
a7812ae4 7303 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
7304
7305 gen_load_fpr64(ctx, fp0, fs);
a7812ae4 7306 gen_helper_float_cvtps_pw(fp0, fp0);
b6d96bed 7307 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 7308 tcg_temp_free_i64(fp0);
b6d96bed 7309 }
5a5012ec
TS
7310 opn = "cvt.ps.pw";
7311 break;
bf4120ad 7312 case OPC_ADD_PS:
5e755519 7313 check_cp1_64bitmode(ctx);
b6d96bed 7314 {
a7812ae4
PB
7315 TCGv_i64 fp0 = tcg_temp_new_i64();
7316 TCGv_i64 fp1 = tcg_temp_new_i64();
b6d96bed
TS
7317
7318 gen_load_fpr64(ctx, fp0, fs);
7319 gen_load_fpr64(ctx, fp1, ft);
a7812ae4
PB
7320 gen_helper_float_add_ps(fp0, fp0, fp1);
7321 tcg_temp_free_i64(fp1);
b6d96bed 7322 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 7323 tcg_temp_free_i64(fp0);
b6d96bed 7324 }
5a5012ec 7325 opn = "add.ps";
6ea83fed 7326 break;
bf4120ad 7327 case OPC_SUB_PS:
5e755519 7328 check_cp1_64bitmode(ctx);
b6d96bed 7329 {
a7812ae4
PB
7330 TCGv_i64 fp0 = tcg_temp_new_i64();
7331 TCGv_i64 fp1 = tcg_temp_new_i64();
b6d96bed
TS
7332
7333 gen_load_fpr64(ctx, fp0, fs);
7334 gen_load_fpr64(ctx, fp1, ft);
a7812ae4
PB
7335 gen_helper_float_sub_ps(fp0, fp0, fp1);
7336 tcg_temp_free_i64(fp1);
b6d96bed 7337 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 7338 tcg_temp_free_i64(fp0);
b6d96bed 7339 }
5a5012ec 7340 opn = "sub.ps";
6ea83fed 7341 break;
bf4120ad 7342 case OPC_MUL_PS:
5e755519 7343 check_cp1_64bitmode(ctx);
b6d96bed 7344 {
a7812ae4
PB
7345 TCGv_i64 fp0 = tcg_temp_new_i64();
7346 TCGv_i64 fp1 = tcg_temp_new_i64();
b6d96bed
TS
7347
7348 gen_load_fpr64(ctx, fp0, fs);
7349 gen_load_fpr64(ctx, fp1, ft);
a7812ae4
PB
7350 gen_helper_float_mul_ps(fp0, fp0, fp1);
7351 tcg_temp_free_i64(fp1);
b6d96bed 7352 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 7353 tcg_temp_free_i64(fp0);
b6d96bed 7354 }
5a5012ec 7355 opn = "mul.ps";
6ea83fed 7356 break;
bf4120ad 7357 case OPC_ABS_PS:
5e755519 7358 check_cp1_64bitmode(ctx);
b6d96bed 7359 {
a7812ae4 7360 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
7361
7362 gen_load_fpr64(ctx, fp0, fs);
a7812ae4 7363 gen_helper_float_abs_ps(fp0, fp0);
b6d96bed 7364 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 7365 tcg_temp_free_i64(fp0);
b6d96bed 7366 }
5a5012ec 7367 opn = "abs.ps";
6ea83fed 7368 break;
bf4120ad 7369 case OPC_MOV_PS:
5e755519 7370 check_cp1_64bitmode(ctx);
b6d96bed 7371 {
a7812ae4 7372 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
7373
7374 gen_load_fpr64(ctx, fp0, fs);
7375 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 7376 tcg_temp_free_i64(fp0);
b6d96bed 7377 }
5a5012ec 7378 opn = "mov.ps";
6ea83fed 7379 break;
bf4120ad 7380 case OPC_NEG_PS:
5e755519 7381 check_cp1_64bitmode(ctx);
b6d96bed 7382 {
a7812ae4 7383 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
7384
7385 gen_load_fpr64(ctx, fp0, fs);
a7812ae4 7386 gen_helper_float_chs_ps(fp0, fp0);
b6d96bed 7387 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 7388 tcg_temp_free_i64(fp0);
b6d96bed 7389 }
5a5012ec 7390 opn = "neg.ps";
6ea83fed 7391 break;
bf4120ad 7392 case OPC_MOVCF_PS:
5e755519 7393 check_cp1_64bitmode(ctx);
b6d96bed 7394 gen_movcf_ps(fs, fd, (ft >> 2) & 0x7, ft & 0x1);
5a5012ec 7395 opn = "movcf.ps";
6ea83fed 7396 break;
bf4120ad 7397 case OPC_MOVZ_PS:
5e755519 7398 check_cp1_64bitmode(ctx);
a16336e4
TS
7399 {
7400 int l1 = gen_new_label();
30a3848b 7401 TCGv_i64 fp0;
a16336e4 7402
c9297f4d
AJ
7403 if (ft != 0)
7404 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[ft], 0, l1);
7405 fp0 = tcg_temp_new_i64();
7406 gen_load_fpr64(ctx, fp0, fs);
7407 gen_store_fpr64(ctx, fp0, fd);
7408 tcg_temp_free_i64(fp0);
a16336e4
TS
7409 gen_set_label(l1);
7410 }
5a5012ec 7411 opn = "movz.ps";
6ea83fed 7412 break;
bf4120ad 7413 case OPC_MOVN_PS:
5e755519 7414 check_cp1_64bitmode(ctx);
a16336e4
TS
7415 {
7416 int l1 = gen_new_label();
30a3848b 7417 TCGv_i64 fp0;
c9297f4d
AJ
7418
7419 if (ft != 0) {
7420 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[ft], 0, l1);
7421 fp0 = tcg_temp_new_i64();
7422 gen_load_fpr64(ctx, fp0, fs);
7423 gen_store_fpr64(ctx, fp0, fd);
7424 tcg_temp_free_i64(fp0);
7425 gen_set_label(l1);
7426 }
a16336e4 7427 }
5a5012ec 7428 opn = "movn.ps";
6ea83fed 7429 break;
bf4120ad 7430 case OPC_ADDR_PS:
5e755519 7431 check_cp1_64bitmode(ctx);
b6d96bed 7432 {
a7812ae4
PB
7433 TCGv_i64 fp0 = tcg_temp_new_i64();
7434 TCGv_i64 fp1 = tcg_temp_new_i64();
b6d96bed
TS
7435
7436 gen_load_fpr64(ctx, fp0, ft);
7437 gen_load_fpr64(ctx, fp1, fs);
a7812ae4
PB
7438 gen_helper_float_addr_ps(fp0, fp0, fp1);
7439 tcg_temp_free_i64(fp1);
b6d96bed 7440 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 7441 tcg_temp_free_i64(fp0);
b6d96bed 7442 }
fbcc6828
TS
7443 opn = "addr.ps";
7444 break;
bf4120ad 7445 case OPC_MULR_PS:
5e755519 7446 check_cp1_64bitmode(ctx);
b6d96bed 7447 {
a7812ae4
PB
7448 TCGv_i64 fp0 = tcg_temp_new_i64();
7449 TCGv_i64 fp1 = tcg_temp_new_i64();
b6d96bed
TS
7450
7451 gen_load_fpr64(ctx, fp0, ft);
7452 gen_load_fpr64(ctx, fp1, fs);
a7812ae4
PB
7453 gen_helper_float_mulr_ps(fp0, fp0, fp1);
7454 tcg_temp_free_i64(fp1);
b6d96bed 7455 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 7456 tcg_temp_free_i64(fp0);
b6d96bed 7457 }
57fa1fb3
TS
7458 opn = "mulr.ps";
7459 break;
bf4120ad 7460 case OPC_RECIP2_PS:
5e755519 7461 check_cp1_64bitmode(ctx);
b6d96bed 7462 {
a7812ae4
PB
7463 TCGv_i64 fp0 = tcg_temp_new_i64();
7464 TCGv_i64 fp1 = tcg_temp_new_i64();
b6d96bed
TS
7465
7466 gen_load_fpr64(ctx, fp0, fs);
7467 gen_load_fpr64(ctx, fp1, fd);
a7812ae4
PB
7468 gen_helper_float_recip2_ps(fp0, fp0, fp1);
7469 tcg_temp_free_i64(fp1);
b6d96bed 7470 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 7471 tcg_temp_free_i64(fp0);
b6d96bed 7472 }
57fa1fb3
TS
7473 opn = "recip2.ps";
7474 break;
bf4120ad 7475 case OPC_RECIP1_PS:
5e755519 7476 check_cp1_64bitmode(ctx);
b6d96bed 7477 {
a7812ae4 7478 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
7479
7480 gen_load_fpr64(ctx, fp0, fs);
a7812ae4 7481 gen_helper_float_recip1_ps(fp0, fp0);
b6d96bed 7482 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 7483 tcg_temp_free_i64(fp0);
b6d96bed 7484 }
57fa1fb3
TS
7485 opn = "recip1.ps";
7486 break;
bf4120ad 7487 case OPC_RSQRT1_PS:
5e755519 7488 check_cp1_64bitmode(ctx);
b6d96bed 7489 {
a7812ae4 7490 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
7491
7492 gen_load_fpr64(ctx, fp0, fs);
a7812ae4 7493 gen_helper_float_rsqrt1_ps(fp0, fp0);
b6d96bed 7494 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 7495 tcg_temp_free_i64(fp0);
b6d96bed 7496 }
57fa1fb3
TS
7497 opn = "rsqrt1.ps";
7498 break;
bf4120ad 7499 case OPC_RSQRT2_PS:
5e755519 7500 check_cp1_64bitmode(ctx);
b6d96bed 7501 {
a7812ae4
PB
7502 TCGv_i64 fp0 = tcg_temp_new_i64();
7503 TCGv_i64 fp1 = tcg_temp_new_i64();
b6d96bed
TS
7504
7505 gen_load_fpr64(ctx, fp0, fs);
7506 gen_load_fpr64(ctx, fp1, ft);
a7812ae4
PB
7507 gen_helper_float_rsqrt2_ps(fp0, fp0, fp1);
7508 tcg_temp_free_i64(fp1);
b6d96bed 7509 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 7510 tcg_temp_free_i64(fp0);
b6d96bed 7511 }
57fa1fb3
TS
7512 opn = "rsqrt2.ps";
7513 break;
bf4120ad 7514 case OPC_CVT_S_PU:
5e755519 7515 check_cp1_64bitmode(ctx);
b6d96bed 7516 {
a7812ae4 7517 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed
TS
7518
7519 gen_load_fpr32h(fp0, fs);
a7812ae4 7520 gen_helper_float_cvts_pu(fp0, fp0);
b6d96bed 7521 gen_store_fpr32(fp0, fd);
a7812ae4 7522 tcg_temp_free_i32(fp0);
b6d96bed 7523 }
5a5012ec 7524 opn = "cvt.s.pu";
dd016883 7525 break;
bf4120ad 7526 case OPC_CVT_PW_PS:
5e755519 7527 check_cp1_64bitmode(ctx);
b6d96bed 7528 {
a7812ae4 7529 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
7530
7531 gen_load_fpr64(ctx, fp0, fs);
a7812ae4 7532 gen_helper_float_cvtpw_ps(fp0, fp0);
b6d96bed 7533 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 7534 tcg_temp_free_i64(fp0);
b6d96bed 7535 }
5a5012ec 7536 opn = "cvt.pw.ps";
6ea83fed 7537 break;
bf4120ad 7538 case OPC_CVT_S_PL:
5e755519 7539 check_cp1_64bitmode(ctx);
b6d96bed 7540 {
a7812ae4 7541 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed
TS
7542
7543 gen_load_fpr32(fp0, fs);
a7812ae4 7544 gen_helper_float_cvts_pl(fp0, fp0);
b6d96bed 7545 gen_store_fpr32(fp0, fd);
a7812ae4 7546 tcg_temp_free_i32(fp0);
b6d96bed 7547 }
5a5012ec 7548 opn = "cvt.s.pl";
6ea83fed 7549 break;
bf4120ad 7550 case OPC_PLL_PS:
5e755519 7551 check_cp1_64bitmode(ctx);
b6d96bed 7552 {
a7812ae4
PB
7553 TCGv_i32 fp0 = tcg_temp_new_i32();
7554 TCGv_i32 fp1 = tcg_temp_new_i32();
b6d96bed
TS
7555
7556 gen_load_fpr32(fp0, fs);
7557 gen_load_fpr32(fp1, ft);
7558 gen_store_fpr32h(fp0, fd);
7559 gen_store_fpr32(fp1, fd);
a7812ae4
PB
7560 tcg_temp_free_i32(fp0);
7561 tcg_temp_free_i32(fp1);
b6d96bed 7562 }
5a5012ec 7563 opn = "pll.ps";
6ea83fed 7564 break;
bf4120ad 7565 case OPC_PLU_PS:
5e755519 7566 check_cp1_64bitmode(ctx);
b6d96bed 7567 {
a7812ae4
PB
7568 TCGv_i32 fp0 = tcg_temp_new_i32();
7569 TCGv_i32 fp1 = tcg_temp_new_i32();
b6d96bed
TS
7570
7571 gen_load_fpr32(fp0, fs);
7572 gen_load_fpr32h(fp1, ft);
7573 gen_store_fpr32(fp1, fd);
7574 gen_store_fpr32h(fp0, fd);
a7812ae4
PB
7575 tcg_temp_free_i32(fp0);
7576 tcg_temp_free_i32(fp1);
b6d96bed 7577 }
5a5012ec
TS
7578 opn = "plu.ps";
7579 break;
bf4120ad 7580 case OPC_PUL_PS:
5e755519 7581 check_cp1_64bitmode(ctx);
b6d96bed 7582 {
a7812ae4
PB
7583 TCGv_i32 fp0 = tcg_temp_new_i32();
7584 TCGv_i32 fp1 = tcg_temp_new_i32();
b6d96bed
TS
7585
7586 gen_load_fpr32h(fp0, fs);
7587 gen_load_fpr32(fp1, ft);
7588 gen_store_fpr32(fp1, fd);
7589 gen_store_fpr32h(fp0, fd);
a7812ae4
PB
7590 tcg_temp_free_i32(fp0);
7591 tcg_temp_free_i32(fp1);
b6d96bed 7592 }
5a5012ec
TS
7593 opn = "pul.ps";
7594 break;
bf4120ad 7595 case OPC_PUU_PS:
5e755519 7596 check_cp1_64bitmode(ctx);
b6d96bed 7597 {
a7812ae4
PB
7598 TCGv_i32 fp0 = tcg_temp_new_i32();
7599 TCGv_i32 fp1 = tcg_temp_new_i32();
b6d96bed
TS
7600
7601 gen_load_fpr32h(fp0, fs);
7602 gen_load_fpr32h(fp1, ft);
7603 gen_store_fpr32(fp1, fd);
7604 gen_store_fpr32h(fp0, fd);
a7812ae4
PB
7605 tcg_temp_free_i32(fp0);
7606 tcg_temp_free_i32(fp1);
b6d96bed 7607 }
5a5012ec
TS
7608 opn = "puu.ps";
7609 break;
bf4120ad
NF
7610 case OPC_CMP_F_PS:
7611 case OPC_CMP_UN_PS:
7612 case OPC_CMP_EQ_PS:
7613 case OPC_CMP_UEQ_PS:
7614 case OPC_CMP_OLT_PS:
7615 case OPC_CMP_ULT_PS:
7616 case OPC_CMP_OLE_PS:
7617 case OPC_CMP_ULE_PS:
7618 case OPC_CMP_SF_PS:
7619 case OPC_CMP_NGLE_PS:
7620 case OPC_CMP_SEQ_PS:
7621 case OPC_CMP_NGL_PS:
7622 case OPC_CMP_LT_PS:
7623 case OPC_CMP_NGE_PS:
7624 case OPC_CMP_LE_PS:
7625 case OPC_CMP_NGT_PS:
8153667c
NF
7626 if (ctx->opcode & (1 << 6)) {
7627 gen_cmpabs_ps(ctx, func-48, ft, fs, cc);
7628 opn = condnames_abs[func-48];
7629 } else {
7630 gen_cmp_ps(ctx, func-48, ft, fs, cc);
7631 opn = condnames[func-48];
5a1e8ffb 7632 }
6ea83fed 7633 break;
5a5012ec 7634 default:
923617a3 7635 MIPS_INVAL(opn);
e397ee33 7636 generate_exception (ctx, EXCP_RI);
6ea83fed
FB
7637 return;
7638 }
2abf314d 7639 (void)opn; /* avoid a compiler warning */
5a1e8ffb
TS
7640 switch (optype) {
7641 case BINOP:
6ea83fed 7642 MIPS_DEBUG("%s %s, %s, %s", opn, fregnames[fd], fregnames[fs], fregnames[ft]);
5a1e8ffb
TS
7643 break;
7644 case CMPOP:
7645 MIPS_DEBUG("%s %s,%s", opn, fregnames[fs], fregnames[ft]);
7646 break;
7647 default:
6ea83fed 7648 MIPS_DEBUG("%s %s,%s", opn, fregnames[fd], fregnames[fs]);
5a1e8ffb
TS
7649 break;
7650 }
6ea83fed 7651}
6af0bf9c 7652
5a5012ec 7653/* Coprocessor 3 (FPU) */
5e755519
TS
7654static void gen_flt3_ldst (DisasContext *ctx, uint32_t opc,
7655 int fd, int fs, int base, int index)
7a387fff 7656{
923617a3 7657 const char *opn = "extended float load/store";
93b12ccc 7658 int store = 0;
4e2474d6 7659 TCGv t0 = tcg_temp_new();
7a387fff 7660
93b12ccc 7661 if (base == 0) {
6c5c1e20 7662 gen_load_gpr(t0, index);
93b12ccc 7663 } else if (index == 0) {
6c5c1e20 7664 gen_load_gpr(t0, base);
93b12ccc 7665 } else {
e9203484 7666 gen_load_gpr(t0, index);
941694d0 7667 gen_op_addr_add(ctx, t0, cpu_gpr[base], t0);
93b12ccc 7668 }
5a5012ec 7669 /* Don't do NOP if destination is zero: we must perform the actual
ead9360e 7670 memory access. */
4e2474d6 7671 save_cpu_state(ctx, 0);
5a5012ec
TS
7672 switch (opc) {
7673 case OPC_LWXC1:
8c0ab41f 7674 check_cop1x(ctx);
b6d96bed 7675 {
a7812ae4 7676 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed 7677
585c88d5
AJ
7678 tcg_gen_qemu_ld32s(t0, t0, ctx->mem_idx);
7679 tcg_gen_trunc_tl_i32(fp0, t0);
b6d96bed 7680 gen_store_fpr32(fp0, fd);
a7812ae4 7681 tcg_temp_free_i32(fp0);
b6d96bed 7682 }
5a5012ec
TS
7683 opn = "lwxc1";
7684 break;
7685 case OPC_LDXC1:
8c0ab41f
AJ
7686 check_cop1x(ctx);
7687 check_cp1_registers(ctx, fd);
b6d96bed 7688 {
a7812ae4 7689 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
7690
7691 tcg_gen_qemu_ld64(fp0, t0, ctx->mem_idx);
7692 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 7693 tcg_temp_free_i64(fp0);
b6d96bed 7694 }
5a5012ec
TS
7695 opn = "ldxc1";
7696 break;
7697 case OPC_LUXC1:
8c0ab41f 7698 check_cp1_64bitmode(ctx);
6c5c1e20 7699 tcg_gen_andi_tl(t0, t0, ~0x7);
b6d96bed 7700 {
a7812ae4 7701 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
7702
7703 tcg_gen_qemu_ld64(fp0, t0, ctx->mem_idx);
7704 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 7705 tcg_temp_free_i64(fp0);
b6d96bed 7706 }
5a5012ec
TS
7707 opn = "luxc1";
7708 break;
7709 case OPC_SWXC1:
8c0ab41f 7710 check_cop1x(ctx);
b6d96bed 7711 {
a7812ae4 7712 TCGv_i32 fp0 = tcg_temp_new_i32();
585c88d5 7713 TCGv t1 = tcg_temp_new();
b6d96bed
TS
7714
7715 gen_load_fpr32(fp0, fs);
a7812ae4
PB
7716 tcg_gen_extu_i32_tl(t1, fp0);
7717 tcg_gen_qemu_st32(t1, t0, ctx->mem_idx);
7718 tcg_temp_free_i32(fp0);
a6035857 7719 tcg_temp_free(t1);
b6d96bed 7720 }
5a5012ec 7721 opn = "swxc1";
93b12ccc 7722 store = 1;
5a5012ec
TS
7723 break;
7724 case OPC_SDXC1:
8c0ab41f
AJ
7725 check_cop1x(ctx);
7726 check_cp1_registers(ctx, fs);
b6d96bed 7727 {
a7812ae4 7728 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
7729
7730 gen_load_fpr64(ctx, fp0, fs);
7731 tcg_gen_qemu_st64(fp0, t0, ctx->mem_idx);
a7812ae4 7732 tcg_temp_free_i64(fp0);
b6d96bed 7733 }
5a5012ec 7734 opn = "sdxc1";
93b12ccc 7735 store = 1;
5a5012ec
TS
7736 break;
7737 case OPC_SUXC1:
8c0ab41f 7738 check_cp1_64bitmode(ctx);
6c5c1e20 7739 tcg_gen_andi_tl(t0, t0, ~0x7);
b6d96bed 7740 {
a7812ae4 7741 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
7742
7743 gen_load_fpr64(ctx, fp0, fs);
7744 tcg_gen_qemu_st64(fp0, t0, ctx->mem_idx);
a7812ae4 7745 tcg_temp_free_i64(fp0);
b6d96bed 7746 }
5a5012ec 7747 opn = "suxc1";
93b12ccc 7748 store = 1;
5a5012ec 7749 break;
5a5012ec 7750 }
6c5c1e20 7751 tcg_temp_free(t0);
2abf314d 7752 (void)opn; (void)store; /* avoid compiler warnings */
93b12ccc
TS
7753 MIPS_DEBUG("%s %s, %s(%s)", opn, fregnames[store ? fs : fd],
7754 regnames[index], regnames[base]);
5a5012ec
TS
7755}
7756
5e755519
TS
7757static void gen_flt3_arith (DisasContext *ctx, uint32_t opc,
7758 int fd, int fr, int fs, int ft)
5a5012ec 7759{
923617a3 7760 const char *opn = "flt3_arith";
5a5012ec 7761
5a5012ec
TS
7762 switch (opc) {
7763 case OPC_ALNV_PS:
b8aa4598 7764 check_cp1_64bitmode(ctx);
a16336e4 7765 {
a7812ae4 7766 TCGv t0 = tcg_temp_local_new();
c905fdac
AJ
7767 TCGv_i32 fp = tcg_temp_new_i32();
7768 TCGv_i32 fph = tcg_temp_new_i32();
a16336e4
TS
7769 int l1 = gen_new_label();
7770 int l2 = gen_new_label();
7771
6c5c1e20
TS
7772 gen_load_gpr(t0, fr);
7773 tcg_gen_andi_tl(t0, t0, 0x7);
6c5c1e20
TS
7774
7775 tcg_gen_brcondi_tl(TCG_COND_NE, t0, 0, l1);
c905fdac
AJ
7776 gen_load_fpr32(fp, fs);
7777 gen_load_fpr32h(fph, fs);
7778 gen_store_fpr32(fp, fd);
7779 gen_store_fpr32h(fph, fd);
a16336e4
TS
7780 tcg_gen_br(l2);
7781 gen_set_label(l1);
6c5c1e20
TS
7782 tcg_gen_brcondi_tl(TCG_COND_NE, t0, 4, l2);
7783 tcg_temp_free(t0);
a16336e4 7784#ifdef TARGET_WORDS_BIGENDIAN
c905fdac
AJ
7785 gen_load_fpr32(fp, fs);
7786 gen_load_fpr32h(fph, ft);
7787 gen_store_fpr32h(fp, fd);
7788 gen_store_fpr32(fph, fd);
a16336e4 7789#else
c905fdac
AJ
7790 gen_load_fpr32h(fph, fs);
7791 gen_load_fpr32(fp, ft);
7792 gen_store_fpr32(fph, fd);
7793 gen_store_fpr32h(fp, fd);
a16336e4
TS
7794#endif
7795 gen_set_label(l2);
c905fdac
AJ
7796 tcg_temp_free_i32(fp);
7797 tcg_temp_free_i32(fph);
a16336e4 7798 }
5a5012ec
TS
7799 opn = "alnv.ps";
7800 break;
7801 case OPC_MADD_S:
b8aa4598 7802 check_cop1x(ctx);
b6d96bed 7803 {
a7812ae4
PB
7804 TCGv_i32 fp0 = tcg_temp_new_i32();
7805 TCGv_i32 fp1 = tcg_temp_new_i32();
7806 TCGv_i32 fp2 = tcg_temp_new_i32();
b6d96bed
TS
7807
7808 gen_load_fpr32(fp0, fs);
7809 gen_load_fpr32(fp1, ft);
7810 gen_load_fpr32(fp2, fr);
a7812ae4
PB
7811 gen_helper_float_muladd_s(fp2, fp0, fp1, fp2);
7812 tcg_temp_free_i32(fp0);
7813 tcg_temp_free_i32(fp1);
b6d96bed 7814 gen_store_fpr32(fp2, fd);
a7812ae4 7815 tcg_temp_free_i32(fp2);
b6d96bed 7816 }
5a5012ec
TS
7817 opn = "madd.s";
7818 break;
7819 case OPC_MADD_D:
b8aa4598
TS
7820 check_cop1x(ctx);
7821 check_cp1_registers(ctx, fd | fs | ft | fr);
b6d96bed 7822 {
a7812ae4
PB
7823 TCGv_i64 fp0 = tcg_temp_new_i64();
7824 TCGv_i64 fp1 = tcg_temp_new_i64();
7825 TCGv_i64 fp2 = tcg_temp_new_i64();
b6d96bed
TS
7826
7827 gen_load_fpr64(ctx, fp0, fs);
7828 gen_load_fpr64(ctx, fp1, ft);
7829 gen_load_fpr64(ctx, fp2, fr);
a7812ae4
PB
7830 gen_helper_float_muladd_d(fp2, fp0, fp1, fp2);
7831 tcg_temp_free_i64(fp0);
7832 tcg_temp_free_i64(fp1);
b6d96bed 7833 gen_store_fpr64(ctx, fp2, fd);
a7812ae4 7834 tcg_temp_free_i64(fp2);
b6d96bed 7835 }
5a5012ec
TS
7836 opn = "madd.d";
7837 break;
7838 case OPC_MADD_PS:
b8aa4598 7839 check_cp1_64bitmode(ctx);
b6d96bed 7840 {
a7812ae4
PB
7841 TCGv_i64 fp0 = tcg_temp_new_i64();
7842 TCGv_i64 fp1 = tcg_temp_new_i64();
7843 TCGv_i64 fp2 = tcg_temp_new_i64();
b6d96bed
TS
7844
7845 gen_load_fpr64(ctx, fp0, fs);
7846 gen_load_fpr64(ctx, fp1, ft);
7847 gen_load_fpr64(ctx, fp2, fr);
a7812ae4
PB
7848 gen_helper_float_muladd_ps(fp2, fp0, fp1, fp2);
7849 tcg_temp_free_i64(fp0);
7850 tcg_temp_free_i64(fp1);
b6d96bed 7851 gen_store_fpr64(ctx, fp2, fd);
a7812ae4 7852 tcg_temp_free_i64(fp2);
b6d96bed 7853 }
5a5012ec
TS
7854 opn = "madd.ps";
7855 break;
7856 case OPC_MSUB_S:
b8aa4598 7857 check_cop1x(ctx);
b6d96bed 7858 {
a7812ae4
PB
7859 TCGv_i32 fp0 = tcg_temp_new_i32();
7860 TCGv_i32 fp1 = tcg_temp_new_i32();
7861 TCGv_i32 fp2 = tcg_temp_new_i32();
b6d96bed
TS
7862
7863 gen_load_fpr32(fp0, fs);
7864 gen_load_fpr32(fp1, ft);
7865 gen_load_fpr32(fp2, fr);
a7812ae4
PB
7866 gen_helper_float_mulsub_s(fp2, fp0, fp1, fp2);
7867 tcg_temp_free_i32(fp0);
7868 tcg_temp_free_i32(fp1);
b6d96bed 7869 gen_store_fpr32(fp2, fd);
a7812ae4 7870 tcg_temp_free_i32(fp2);
b6d96bed 7871 }
5a5012ec
TS
7872 opn = "msub.s";
7873 break;
7874 case OPC_MSUB_D:
b8aa4598
TS
7875 check_cop1x(ctx);
7876 check_cp1_registers(ctx, fd | fs | ft | fr);
b6d96bed 7877 {
a7812ae4
PB
7878 TCGv_i64 fp0 = tcg_temp_new_i64();
7879 TCGv_i64 fp1 = tcg_temp_new_i64();
7880 TCGv_i64 fp2 = tcg_temp_new_i64();
b6d96bed
TS
7881
7882 gen_load_fpr64(ctx, fp0, fs);
7883 gen_load_fpr64(ctx, fp1, ft);
7884 gen_load_fpr64(ctx, fp2, fr);
a7812ae4
PB
7885 gen_helper_float_mulsub_d(fp2, fp0, fp1, fp2);
7886 tcg_temp_free_i64(fp0);
7887 tcg_temp_free_i64(fp1);
b6d96bed 7888 gen_store_fpr64(ctx, fp2, fd);
a7812ae4 7889 tcg_temp_free_i64(fp2);
b6d96bed 7890 }
5a5012ec
TS
7891 opn = "msub.d";
7892 break;
7893 case OPC_MSUB_PS:
b8aa4598 7894 check_cp1_64bitmode(ctx);
b6d96bed 7895 {
a7812ae4
PB
7896 TCGv_i64 fp0 = tcg_temp_new_i64();
7897 TCGv_i64 fp1 = tcg_temp_new_i64();
7898 TCGv_i64 fp2 = tcg_temp_new_i64();
b6d96bed
TS
7899
7900 gen_load_fpr64(ctx, fp0, fs);
7901 gen_load_fpr64(ctx, fp1, ft);
7902 gen_load_fpr64(ctx, fp2, fr);
a7812ae4
PB
7903 gen_helper_float_mulsub_ps(fp2, fp0, fp1, fp2);
7904 tcg_temp_free_i64(fp0);
7905 tcg_temp_free_i64(fp1);
b6d96bed 7906 gen_store_fpr64(ctx, fp2, fd);
a7812ae4 7907 tcg_temp_free_i64(fp2);
b6d96bed 7908 }
5a5012ec
TS
7909 opn = "msub.ps";
7910 break;
7911 case OPC_NMADD_S:
b8aa4598 7912 check_cop1x(ctx);
b6d96bed 7913 {
a7812ae4
PB
7914 TCGv_i32 fp0 = tcg_temp_new_i32();
7915 TCGv_i32 fp1 = tcg_temp_new_i32();
7916 TCGv_i32 fp2 = tcg_temp_new_i32();
b6d96bed
TS
7917
7918 gen_load_fpr32(fp0, fs);
7919 gen_load_fpr32(fp1, ft);
7920 gen_load_fpr32(fp2, fr);
a7812ae4
PB
7921 gen_helper_float_nmuladd_s(fp2, fp0, fp1, fp2);
7922 tcg_temp_free_i32(fp0);
7923 tcg_temp_free_i32(fp1);
b6d96bed 7924 gen_store_fpr32(fp2, fd);
a7812ae4 7925 tcg_temp_free_i32(fp2);
b6d96bed 7926 }
5a5012ec
TS
7927 opn = "nmadd.s";
7928 break;
7929 case OPC_NMADD_D:
b8aa4598
TS
7930 check_cop1x(ctx);
7931 check_cp1_registers(ctx, fd | fs | ft | fr);
b6d96bed 7932 {
a7812ae4
PB
7933 TCGv_i64 fp0 = tcg_temp_new_i64();
7934 TCGv_i64 fp1 = tcg_temp_new_i64();
7935 TCGv_i64 fp2 = tcg_temp_new_i64();
b6d96bed
TS
7936
7937 gen_load_fpr64(ctx, fp0, fs);
7938 gen_load_fpr64(ctx, fp1, ft);
7939 gen_load_fpr64(ctx, fp2, fr);
a7812ae4
PB
7940 gen_helper_float_nmuladd_d(fp2, fp0, fp1, fp2);
7941 tcg_temp_free_i64(fp0);
7942 tcg_temp_free_i64(fp1);
b6d96bed 7943 gen_store_fpr64(ctx, fp2, fd);
a7812ae4 7944 tcg_temp_free_i64(fp2);
b6d96bed 7945 }
5a5012ec
TS
7946 opn = "nmadd.d";
7947 break;
7948 case OPC_NMADD_PS:
b8aa4598 7949 check_cp1_64bitmode(ctx);
b6d96bed 7950 {
a7812ae4
PB
7951 TCGv_i64 fp0 = tcg_temp_new_i64();
7952 TCGv_i64 fp1 = tcg_temp_new_i64();
7953 TCGv_i64 fp2 = tcg_temp_new_i64();
b6d96bed
TS
7954
7955 gen_load_fpr64(ctx, fp0, fs);
7956 gen_load_fpr64(ctx, fp1, ft);
7957 gen_load_fpr64(ctx, fp2, fr);
a7812ae4
PB
7958 gen_helper_float_nmuladd_ps(fp2, fp0, fp1, fp2);
7959 tcg_temp_free_i64(fp0);
7960 tcg_temp_free_i64(fp1);
b6d96bed 7961 gen_store_fpr64(ctx, fp2, fd);
a7812ae4 7962 tcg_temp_free_i64(fp2);
b6d96bed 7963 }
5a5012ec
TS
7964 opn = "nmadd.ps";
7965 break;
7966 case OPC_NMSUB_S:
b8aa4598 7967 check_cop1x(ctx);
b6d96bed 7968 {
a7812ae4
PB
7969 TCGv_i32 fp0 = tcg_temp_new_i32();
7970 TCGv_i32 fp1 = tcg_temp_new_i32();
7971 TCGv_i32 fp2 = tcg_temp_new_i32();
b6d96bed
TS
7972
7973 gen_load_fpr32(fp0, fs);
7974 gen_load_fpr32(fp1, ft);
7975 gen_load_fpr32(fp2, fr);
a7812ae4
PB
7976 gen_helper_float_nmulsub_s(fp2, fp0, fp1, fp2);
7977 tcg_temp_free_i32(fp0);
7978 tcg_temp_free_i32(fp1);
b6d96bed 7979 gen_store_fpr32(fp2, fd);
a7812ae4 7980 tcg_temp_free_i32(fp2);
b6d96bed 7981 }
5a5012ec
TS
7982 opn = "nmsub.s";
7983 break;
7984 case OPC_NMSUB_D:
b8aa4598
TS
7985 check_cop1x(ctx);
7986 check_cp1_registers(ctx, fd | fs | ft | fr);
b6d96bed 7987 {
a7812ae4
PB
7988 TCGv_i64 fp0 = tcg_temp_new_i64();
7989 TCGv_i64 fp1 = tcg_temp_new_i64();
7990 TCGv_i64 fp2 = tcg_temp_new_i64();
b6d96bed
TS
7991
7992 gen_load_fpr64(ctx, fp0, fs);
7993 gen_load_fpr64(ctx, fp1, ft);
7994 gen_load_fpr64(ctx, fp2, fr);
a7812ae4
PB
7995 gen_helper_float_nmulsub_d(fp2, fp0, fp1, fp2);
7996 tcg_temp_free_i64(fp0);
7997 tcg_temp_free_i64(fp1);
b6d96bed 7998 gen_store_fpr64(ctx, fp2, fd);
a7812ae4 7999 tcg_temp_free_i64(fp2);
b6d96bed 8000 }
5a5012ec
TS
8001 opn = "nmsub.d";
8002 break;
8003 case OPC_NMSUB_PS:
b8aa4598 8004 check_cp1_64bitmode(ctx);
b6d96bed 8005 {
a7812ae4
PB
8006 TCGv_i64 fp0 = tcg_temp_new_i64();
8007 TCGv_i64 fp1 = tcg_temp_new_i64();
8008 TCGv_i64 fp2 = tcg_temp_new_i64();
b6d96bed
TS
8009
8010 gen_load_fpr64(ctx, fp0, fs);
8011 gen_load_fpr64(ctx, fp1, ft);
8012 gen_load_fpr64(ctx, fp2, fr);
a7812ae4
PB
8013 gen_helper_float_nmulsub_ps(fp2, fp0, fp1, fp2);
8014 tcg_temp_free_i64(fp0);
8015 tcg_temp_free_i64(fp1);
b6d96bed 8016 gen_store_fpr64(ctx, fp2, fd);
a7812ae4 8017 tcg_temp_free_i64(fp2);
b6d96bed 8018 }
5a5012ec
TS
8019 opn = "nmsub.ps";
8020 break;
923617a3
TS
8021 default:
8022 MIPS_INVAL(opn);
5a5012ec
TS
8023 generate_exception (ctx, EXCP_RI);
8024 return;
8025 }
2abf314d 8026 (void)opn; /* avoid a compiler warning */
5a5012ec
TS
8027 MIPS_DEBUG("%s %s, %s, %s, %s", opn, fregnames[fd], fregnames[fr],
8028 fregnames[fs], fregnames[ft]);
7a387fff
TS
8029}
8030
26ebe468
NF
8031static void
8032gen_rdhwr (CPUState *env, DisasContext *ctx, int rt, int rd)
8033{
8034 TCGv t0;
8035
8036 check_insn(env, ctx, ISA_MIPS32R2);
8037 t0 = tcg_temp_new();
8038
8039 switch (rd) {
8040 case 0:
8041 save_cpu_state(ctx, 1);
8042 gen_helper_rdhwr_cpunum(t0);
8043 gen_store_gpr(t0, rt);
8044 break;
8045 case 1:
8046 save_cpu_state(ctx, 1);
8047 gen_helper_rdhwr_synci_step(t0);
8048 gen_store_gpr(t0, rt);
8049 break;
8050 case 2:
8051 save_cpu_state(ctx, 1);
8052 gen_helper_rdhwr_cc(t0);
8053 gen_store_gpr(t0, rt);
8054 break;
8055 case 3:
8056 save_cpu_state(ctx, 1);
8057 gen_helper_rdhwr_ccres(t0);
8058 gen_store_gpr(t0, rt);
8059 break;
8060 case 29:
8061#if defined(CONFIG_USER_ONLY)
8062 tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUState, tls_value));
8063 gen_store_gpr(t0, rt);
8064 break;
8065#else
8066 /* XXX: Some CPUs implement this in hardware.
8067 Not supported yet. */
8068#endif
8069 default: /* Invalid */
8070 MIPS_INVAL("rdhwr");
8071 generate_exception(ctx, EXCP_RI);
8072 break;
8073 }
8074 tcg_temp_free(t0);
8075}
8076
c9602061
NF
8077static void handle_delay_slot (CPUState *env, DisasContext *ctx,
8078 int insn_bytes)
8079{
8080 if (ctx->hflags & MIPS_HFLAG_BMASK) {
364d4831 8081 int proc_hflags = ctx->hflags & MIPS_HFLAG_BMASK;
c9602061
NF
8082 /* Branches completion */
8083 ctx->hflags &= ~MIPS_HFLAG_BMASK;
8084 ctx->bstate = BS_BRANCH;
8085 save_cpu_state(ctx, 0);
8086 /* FIXME: Need to clear can_do_io. */
364d4831 8087 switch (proc_hflags & MIPS_HFLAG_BMASK_BASE) {
c9602061
NF
8088 case MIPS_HFLAG_B:
8089 /* unconditional branch */
8090 MIPS_DEBUG("unconditional branch");
364d4831
NF
8091 if (proc_hflags & MIPS_HFLAG_BX) {
8092 tcg_gen_xori_i32(hflags, hflags, MIPS_HFLAG_M16);
8093 }
c9602061
NF
8094 gen_goto_tb(ctx, 0, ctx->btarget);
8095 break;
8096 case MIPS_HFLAG_BL:
8097 /* blikely taken case */
8098 MIPS_DEBUG("blikely branch taken");
8099 gen_goto_tb(ctx, 0, ctx->btarget);
8100 break;
8101 case MIPS_HFLAG_BC:
8102 /* Conditional branch */
8103 MIPS_DEBUG("conditional branch");
8104 {
8105 int l1 = gen_new_label();
8106
8107 tcg_gen_brcondi_tl(TCG_COND_NE, bcond, 0, l1);
8108 gen_goto_tb(ctx, 1, ctx->pc + insn_bytes);
8109 gen_set_label(l1);
8110 gen_goto_tb(ctx, 0, ctx->btarget);
8111 }
8112 break;
8113 case MIPS_HFLAG_BR:
8114 /* unconditional branch to register */
8115 MIPS_DEBUG("branch to register");
3c824109 8116 if (env->insn_flags & (ASE_MIPS16 | ASE_MICROMIPS)) {
364d4831
NF
8117 TCGv t0 = tcg_temp_new();
8118 TCGv_i32 t1 = tcg_temp_new_i32();
8119
8120 tcg_gen_andi_tl(t0, btarget, 0x1);
8121 tcg_gen_trunc_tl_i32(t1, t0);
8122 tcg_temp_free(t0);
8123 tcg_gen_andi_i32(hflags, hflags, ~(uint32_t)MIPS_HFLAG_M16);
8124 tcg_gen_shli_i32(t1, t1, MIPS_HFLAG_M16_SHIFT);
8125 tcg_gen_or_i32(hflags, hflags, t1);
8126 tcg_temp_free_i32(t1);
8127
8128 tcg_gen_andi_tl(cpu_PC, btarget, ~(target_ulong)0x1);
8129 } else {
8130 tcg_gen_mov_tl(cpu_PC, btarget);
8131 }
c9602061
NF
8132 if (ctx->singlestep_enabled) {
8133 save_cpu_state(ctx, 0);
8134 gen_helper_0i(raise_exception, EXCP_DEBUG);
8135 }
8136 tcg_gen_exit_tb(0);
8137 break;
8138 default:
8139 MIPS_DEBUG("unknown branch");
8140 break;
8141 }
8142 }
8143}
8144
7a387fff 8145/* ISA extensions (ASEs) */
6af0bf9c 8146/* MIPS16 extension to MIPS32 */
6ea219d0
NF
8147
8148/* MIPS16 major opcodes */
8149enum {
8150 M16_OPC_ADDIUSP = 0x00,
8151 M16_OPC_ADDIUPC = 0x01,
8152 M16_OPC_B = 0x02,
8153 M16_OPC_JAL = 0x03,
8154 M16_OPC_BEQZ = 0x04,
8155 M16_OPC_BNEQZ = 0x05,
8156 M16_OPC_SHIFT = 0x06,
8157 M16_OPC_LD = 0x07,
8158 M16_OPC_RRIA = 0x08,
8159 M16_OPC_ADDIU8 = 0x09,
8160 M16_OPC_SLTI = 0x0a,
8161 M16_OPC_SLTIU = 0x0b,
8162 M16_OPC_I8 = 0x0c,
8163 M16_OPC_LI = 0x0d,
8164 M16_OPC_CMPI = 0x0e,
8165 M16_OPC_SD = 0x0f,
8166 M16_OPC_LB = 0x10,
8167 M16_OPC_LH = 0x11,
8168 M16_OPC_LWSP = 0x12,
8169 M16_OPC_LW = 0x13,
8170 M16_OPC_LBU = 0x14,
8171 M16_OPC_LHU = 0x15,
8172 M16_OPC_LWPC = 0x16,
8173 M16_OPC_LWU = 0x17,
8174 M16_OPC_SB = 0x18,
8175 M16_OPC_SH = 0x19,
8176 M16_OPC_SWSP = 0x1a,
8177 M16_OPC_SW = 0x1b,
8178 M16_OPC_RRR = 0x1c,
8179 M16_OPC_RR = 0x1d,
8180 M16_OPC_EXTEND = 0x1e,
8181 M16_OPC_I64 = 0x1f
8182};
8183
8184/* I8 funct field */
8185enum {
8186 I8_BTEQZ = 0x0,
8187 I8_BTNEZ = 0x1,
8188 I8_SWRASP = 0x2,
8189 I8_ADJSP = 0x3,
8190 I8_SVRS = 0x4,
8191 I8_MOV32R = 0x5,
8192 I8_MOVR32 = 0x7
8193};
8194
8195/* RRR f field */
8196enum {
8197 RRR_DADDU = 0x0,
8198 RRR_ADDU = 0x1,
8199 RRR_DSUBU = 0x2,
8200 RRR_SUBU = 0x3
8201};
8202
8203/* RR funct field */
8204enum {
8205 RR_JR = 0x00,
8206 RR_SDBBP = 0x01,
8207 RR_SLT = 0x02,
8208 RR_SLTU = 0x03,
8209 RR_SLLV = 0x04,
8210 RR_BREAK = 0x05,
8211 RR_SRLV = 0x06,
8212 RR_SRAV = 0x07,
8213 RR_DSRL = 0x08,
8214 RR_CMP = 0x0a,
8215 RR_NEG = 0x0b,
8216 RR_AND = 0x0c,
8217 RR_OR = 0x0d,
8218 RR_XOR = 0x0e,
8219 RR_NOT = 0x0f,
8220 RR_MFHI = 0x10,
8221 RR_CNVT = 0x11,
8222 RR_MFLO = 0x12,
8223 RR_DSRA = 0x13,
8224 RR_DSLLV = 0x14,
8225 RR_DSRLV = 0x16,
8226 RR_DSRAV = 0x17,
8227 RR_MULT = 0x18,
8228 RR_MULTU = 0x19,
8229 RR_DIV = 0x1a,
8230 RR_DIVU = 0x1b,
8231 RR_DMULT = 0x1c,
8232 RR_DMULTU = 0x1d,
8233 RR_DDIV = 0x1e,
8234 RR_DDIVU = 0x1f
8235};
8236
8237/* I64 funct field */
8238enum {
8239 I64_LDSP = 0x0,
8240 I64_SDSP = 0x1,
8241 I64_SDRASP = 0x2,
8242 I64_DADJSP = 0x3,
8243 I64_LDPC = 0x4,
364d4831 8244 I64_DADDIU5 = 0x5,
6ea219d0
NF
8245 I64_DADDIUPC = 0x6,
8246 I64_DADDIUSP = 0x7
8247};
8248
8249/* RR ry field for CNVT */
8250enum {
8251 RR_RY_CNVT_ZEB = 0x0,
8252 RR_RY_CNVT_ZEH = 0x1,
8253 RR_RY_CNVT_ZEW = 0x2,
8254 RR_RY_CNVT_SEB = 0x4,
8255 RR_RY_CNVT_SEH = 0x5,
8256 RR_RY_CNVT_SEW = 0x6,
8257};
8258
364d4831
NF
8259static int xlat (int r)
8260{
8261 static int map[] = { 16, 17, 2, 3, 4, 5, 6, 7 };
8262
8263 return map[r];
8264}
8265
8266static void gen_mips16_save (DisasContext *ctx,
8267 int xsregs, int aregs,
8268 int do_ra, int do_s0, int do_s1,
8269 int framesize)
8270{
8271 TCGv t0 = tcg_temp_new();
8272 TCGv t1 = tcg_temp_new();
8273 int args, astatic;
8274
8275 switch (aregs) {
8276 case 0:
8277 case 1:
8278 case 2:
8279 case 3:
8280 case 11:
8281 args = 0;
8282 break;
8283 case 4:
8284 case 5:
8285 case 6:
8286 case 7:
8287 args = 1;
8288 break;
8289 case 8:
8290 case 9:
8291 case 10:
8292 args = 2;
8293 break;
8294 case 12:
8295 case 13:
8296 args = 3;
8297 break;
8298 case 14:
8299 args = 4;
8300 break;
8301 default:
8302 generate_exception(ctx, EXCP_RI);
8303 return;
8304 }
8305
8306 switch (args) {
8307 case 4:
8308 gen_base_offset_addr(ctx, t0, 29, 12);
8309 gen_load_gpr(t1, 7);
5c13fdfd 8310 op_st_sw(t1, t0, ctx);
364d4831
NF
8311 /* Fall through */
8312 case 3:
8313 gen_base_offset_addr(ctx, t0, 29, 8);
8314 gen_load_gpr(t1, 6);
5c13fdfd 8315 op_st_sw(t1, t0, ctx);
364d4831
NF
8316 /* Fall through */
8317 case 2:
8318 gen_base_offset_addr(ctx, t0, 29, 4);
8319 gen_load_gpr(t1, 5);
5c13fdfd 8320 op_st_sw(t1, t0, ctx);
364d4831
NF
8321 /* Fall through */
8322 case 1:
8323 gen_base_offset_addr(ctx, t0, 29, 0);
8324 gen_load_gpr(t1, 4);
5c13fdfd 8325 op_st_sw(t1, t0, ctx);
364d4831
NF
8326 }
8327
8328 gen_load_gpr(t0, 29);
8329
8330#define DECR_AND_STORE(reg) do { \
8331 tcg_gen_subi_tl(t0, t0, 4); \
8332 gen_load_gpr(t1, reg); \
5c13fdfd 8333 op_st_sw(t1, t0, ctx); \
364d4831
NF
8334 } while (0)
8335
8336 if (do_ra) {
8337 DECR_AND_STORE(31);
8338 }
8339
8340 switch (xsregs) {
8341 case 7:
8342 DECR_AND_STORE(30);
8343 /* Fall through */
8344 case 6:
8345 DECR_AND_STORE(23);
8346 /* Fall through */
8347 case 5:
8348 DECR_AND_STORE(22);
8349 /* Fall through */
8350 case 4:
8351 DECR_AND_STORE(21);
8352 /* Fall through */
8353 case 3:
8354 DECR_AND_STORE(20);
8355 /* Fall through */
8356 case 2:
8357 DECR_AND_STORE(19);
8358 /* Fall through */
8359 case 1:
8360 DECR_AND_STORE(18);
8361 }
8362
8363 if (do_s1) {
8364 DECR_AND_STORE(17);
8365 }
8366 if (do_s0) {
8367 DECR_AND_STORE(16);
8368 }
8369
8370 switch (aregs) {
8371 case 0:
8372 case 4:
8373 case 8:
8374 case 12:
8375 case 14:
8376 astatic = 0;
8377 break;
8378 case 1:
8379 case 5:
8380 case 9:
8381 case 13:
8382 astatic = 1;
8383 break;
8384 case 2:
8385 case 6:
8386 case 10:
8387 astatic = 2;
8388 break;
8389 case 3:
8390 case 7:
8391 astatic = 3;
8392 break;
8393 case 11:
8394 astatic = 4;
8395 break;
8396 default:
8397 generate_exception(ctx, EXCP_RI);
8398 return;
8399 }
8400
8401 if (astatic > 0) {
8402 DECR_AND_STORE(7);
8403 if (astatic > 1) {
8404 DECR_AND_STORE(6);
8405 if (astatic > 2) {
8406 DECR_AND_STORE(5);
8407 if (astatic > 3) {
8408 DECR_AND_STORE(4);
8409 }
8410 }
8411 }
8412 }
8413#undef DECR_AND_STORE
8414
8415 tcg_gen_subi_tl(cpu_gpr[29], cpu_gpr[29], framesize);
8416 tcg_temp_free(t0);
8417 tcg_temp_free(t1);
8418}
8419
8420static void gen_mips16_restore (DisasContext *ctx,
8421 int xsregs, int aregs,
8422 int do_ra, int do_s0, int do_s1,
8423 int framesize)
8424{
8425 int astatic;
8426 TCGv t0 = tcg_temp_new();
8427 TCGv t1 = tcg_temp_new();
8428
8429 tcg_gen_addi_tl(t0, cpu_gpr[29], framesize);
8430
8431#define DECR_AND_LOAD(reg) do { \
8432 tcg_gen_subi_tl(t0, t0, 4); \
5c13fdfd 8433 op_ld_lw(t1, t0, ctx); \
364d4831
NF
8434 gen_store_gpr(t1, reg); \
8435 } while (0)
8436
8437 if (do_ra) {
8438 DECR_AND_LOAD(31);
8439 }
8440
8441 switch (xsregs) {
8442 case 7:
8443 DECR_AND_LOAD(30);
8444 /* Fall through */
8445 case 6:
8446 DECR_AND_LOAD(23);
8447 /* Fall through */
8448 case 5:
8449 DECR_AND_LOAD(22);
8450 /* Fall through */
8451 case 4:
8452 DECR_AND_LOAD(21);
8453 /* Fall through */
8454 case 3:
8455 DECR_AND_LOAD(20);
8456 /* Fall through */
8457 case 2:
8458 DECR_AND_LOAD(19);
8459 /* Fall through */
8460 case 1:
8461 DECR_AND_LOAD(18);
8462 }
8463
8464 if (do_s1) {
8465 DECR_AND_LOAD(17);
8466 }
8467 if (do_s0) {
8468 DECR_AND_LOAD(16);
8469 }
8470
8471 switch (aregs) {
8472 case 0:
8473 case 4:
8474 case 8:
8475 case 12:
8476 case 14:
8477 astatic = 0;
8478 break;
8479 case 1:
8480 case 5:
8481 case 9:
8482 case 13:
8483 astatic = 1;
8484 break;
8485 case 2:
8486 case 6:
8487 case 10:
8488 astatic = 2;
8489 break;
8490 case 3:
8491 case 7:
8492 astatic = 3;
8493 break;
8494 case 11:
8495 astatic = 4;
8496 break;
8497 default:
8498 generate_exception(ctx, EXCP_RI);
8499 return;
8500 }
8501
8502 if (astatic > 0) {
8503 DECR_AND_LOAD(7);
8504 if (astatic > 1) {
8505 DECR_AND_LOAD(6);
8506 if (astatic > 2) {
8507 DECR_AND_LOAD(5);
8508 if (astatic > 3) {
8509 DECR_AND_LOAD(4);
8510 }
8511 }
8512 }
8513 }
8514#undef DECR_AND_LOAD
8515
8516 tcg_gen_addi_tl(cpu_gpr[29], cpu_gpr[29], framesize);
8517 tcg_temp_free(t0);
8518 tcg_temp_free(t1);
8519}
8520
8521static void gen_addiupc (DisasContext *ctx, int rx, int imm,
8522 int is_64_bit, int extended)
8523{
8524 TCGv t0;
8525
8526 if (extended && (ctx->hflags & MIPS_HFLAG_BMASK)) {
8527 generate_exception(ctx, EXCP_RI);
8528 return;
8529 }
8530
8531 t0 = tcg_temp_new();
8532
8533 tcg_gen_movi_tl(t0, pc_relative_pc(ctx));
8534 tcg_gen_addi_tl(cpu_gpr[rx], t0, imm);
8535 if (!is_64_bit) {
8536 tcg_gen_ext32s_tl(cpu_gpr[rx], cpu_gpr[rx]);
8537 }
8538
8539 tcg_temp_free(t0);
8540}
8541
8542#if defined(TARGET_MIPS64)
8543static void decode_i64_mips16 (CPUState *env, DisasContext *ctx,
8544 int ry, int funct, int16_t offset,
8545 int extended)
8546{
8547 switch (funct) {
8548 case I64_LDSP:
8549 check_mips_64(ctx);
8550 offset = extended ? offset : offset << 3;
afa88c3a 8551 gen_ld(env, ctx, OPC_LD, ry, 29, offset);
364d4831
NF
8552 break;
8553 case I64_SDSP:
8554 check_mips_64(ctx);
8555 offset = extended ? offset : offset << 3;
5c13fdfd 8556 gen_st(ctx, OPC_SD, ry, 29, offset);
364d4831
NF
8557 break;
8558 case I64_SDRASP:
8559 check_mips_64(ctx);
8560 offset = extended ? offset : (ctx->opcode & 0xff) << 3;
5c13fdfd 8561 gen_st(ctx, OPC_SD, 31, 29, offset);
364d4831
NF
8562 break;
8563 case I64_DADJSP:
8564 check_mips_64(ctx);
8565 offset = extended ? offset : ((int8_t)ctx->opcode) << 3;
8566 gen_arith_imm(env, ctx, OPC_DADDIU, 29, 29, offset);
8567 break;
8568 case I64_LDPC:
8569 if (extended && (ctx->hflags & MIPS_HFLAG_BMASK)) {
8570 generate_exception(ctx, EXCP_RI);
8571 } else {
8572 offset = extended ? offset : offset << 3;
afa88c3a 8573 gen_ld(env, ctx, OPC_LDPC, ry, 0, offset);
364d4831
NF
8574 }
8575 break;
8576 case I64_DADDIU5:
8577 check_mips_64(ctx);
8578 offset = extended ? offset : ((int8_t)(offset << 3)) >> 3;
8579 gen_arith_imm(env, ctx, OPC_DADDIU, ry, ry, offset);
8580 break;
8581 case I64_DADDIUPC:
8582 check_mips_64(ctx);
8583 offset = extended ? offset : offset << 2;
8584 gen_addiupc(ctx, ry, offset, 1, extended);
8585 break;
8586 case I64_DADDIUSP:
8587 check_mips_64(ctx);
8588 offset = extended ? offset : offset << 2;
8589 gen_arith_imm(env, ctx, OPC_DADDIU, ry, 29, offset);
8590 break;
8591 }
8592}
8593#endif
8594
8595static int decode_extended_mips16_opc (CPUState *env, DisasContext *ctx,
8596 int *is_branch)
8597{
8598 int extend = lduw_code(ctx->pc + 2);
8599 int op, rx, ry, funct, sa;
8600 int16_t imm, offset;
8601
8602 ctx->opcode = (ctx->opcode << 16) | extend;
8603 op = (ctx->opcode >> 11) & 0x1f;
8604 sa = (ctx->opcode >> 22) & 0x1f;
8605 funct = (ctx->opcode >> 8) & 0x7;
8606 rx = xlat((ctx->opcode >> 8) & 0x7);
8607 ry = xlat((ctx->opcode >> 5) & 0x7);
8608 offset = imm = (int16_t) (((ctx->opcode >> 16) & 0x1f) << 11
8609 | ((ctx->opcode >> 21) & 0x3f) << 5
8610 | (ctx->opcode & 0x1f));
8611
8612 /* The extended opcodes cleverly reuse the opcodes from their 16-bit
8613 counterparts. */
8614 switch (op) {
8615 case M16_OPC_ADDIUSP:
8616 gen_arith_imm(env, ctx, OPC_ADDIU, rx, 29, imm);
8617 break;
8618 case M16_OPC_ADDIUPC:
8619 gen_addiupc(ctx, rx, imm, 0, 1);
8620 break;
8621 case M16_OPC_B:
8622 gen_compute_branch(ctx, OPC_BEQ, 4, 0, 0, offset << 1);
8623 /* No delay slot, so just process as a normal instruction */
8624 break;
8625 case M16_OPC_BEQZ:
8626 gen_compute_branch(ctx, OPC_BEQ, 4, rx, 0, offset << 1);
8627 /* No delay slot, so just process as a normal instruction */
8628 break;
8629 case M16_OPC_BNEQZ:
8630 gen_compute_branch(ctx, OPC_BNE, 4, rx, 0, offset << 1);
8631 /* No delay slot, so just process as a normal instruction */
8632 break;
8633 case M16_OPC_SHIFT:
8634 switch (ctx->opcode & 0x3) {
8635 case 0x0:
8636 gen_shift_imm(env, ctx, OPC_SLL, rx, ry, sa);
8637 break;
8638 case 0x1:
8639#if defined(TARGET_MIPS64)
8640 check_mips_64(ctx);
8641 gen_shift_imm(env, ctx, OPC_DSLL, rx, ry, sa);
8642#else
8643 generate_exception(ctx, EXCP_RI);
8644#endif
8645 break;
8646 case 0x2:
8647 gen_shift_imm(env, ctx, OPC_SRL, rx, ry, sa);
8648 break;
8649 case 0x3:
8650 gen_shift_imm(env, ctx, OPC_SRA, rx, ry, sa);
8651 break;
8652 }
8653 break;
8654#if defined(TARGET_MIPS64)
8655 case M16_OPC_LD:
8656 check_mips_64(ctx);
afa88c3a 8657 gen_ld(env, ctx, OPC_LD, ry, rx, offset);
364d4831
NF
8658 break;
8659#endif
8660 case M16_OPC_RRIA:
8661 imm = ctx->opcode & 0xf;
8662 imm = imm | ((ctx->opcode >> 20) & 0x7f) << 4;
8663 imm = imm | ((ctx->opcode >> 16) & 0xf) << 11;
8664 imm = (int16_t) (imm << 1) >> 1;
8665 if ((ctx->opcode >> 4) & 0x1) {
8666#if defined(TARGET_MIPS64)
8667 check_mips_64(ctx);
8668 gen_arith_imm(env, ctx, OPC_DADDIU, ry, rx, imm);
8669#else
8670 generate_exception(ctx, EXCP_RI);
8671#endif
8672 } else {
8673 gen_arith_imm(env, ctx, OPC_ADDIU, ry, rx, imm);
8674 }
8675 break;
8676 case M16_OPC_ADDIU8:
8677 gen_arith_imm(env, ctx, OPC_ADDIU, rx, rx, imm);
8678 break;
8679 case M16_OPC_SLTI:
8680 gen_slt_imm(env, OPC_SLTI, 24, rx, imm);
8681 break;
8682 case M16_OPC_SLTIU:
8683 gen_slt_imm(env, OPC_SLTIU, 24, rx, imm);
8684 break;
8685 case M16_OPC_I8:
8686 switch (funct) {
8687 case I8_BTEQZ:
8688 gen_compute_branch(ctx, OPC_BEQ, 4, 24, 0, offset << 1);
8689 break;
8690 case I8_BTNEZ:
8691 gen_compute_branch(ctx, OPC_BNE, 4, 24, 0, offset << 1);
8692 break;
8693 case I8_SWRASP:
5c13fdfd 8694 gen_st(ctx, OPC_SW, 31, 29, imm);
364d4831
NF
8695 break;
8696 case I8_ADJSP:
8697 gen_arith_imm(env, ctx, OPC_ADDIU, 29, 29, imm);
8698 break;
8699 case I8_SVRS:
8700 {
8701 int xsregs = (ctx->opcode >> 24) & 0x7;
8702 int aregs = (ctx->opcode >> 16) & 0xf;
8703 int do_ra = (ctx->opcode >> 6) & 0x1;
8704 int do_s0 = (ctx->opcode >> 5) & 0x1;
8705 int do_s1 = (ctx->opcode >> 4) & 0x1;
8706 int framesize = (((ctx->opcode >> 20) & 0xf) << 4
8707 | (ctx->opcode & 0xf)) << 3;
8708
8709 if (ctx->opcode & (1 << 7)) {
8710 gen_mips16_save(ctx, xsregs, aregs,
8711 do_ra, do_s0, do_s1,
8712 framesize);
8713 } else {
8714 gen_mips16_restore(ctx, xsregs, aregs,
8715 do_ra, do_s0, do_s1,
8716 framesize);
8717 }
8718 }
8719 break;
8720 default:
8721 generate_exception(ctx, EXCP_RI);
8722 break;
8723 }
8724 break;
8725 case M16_OPC_LI:
8726 tcg_gen_movi_tl(cpu_gpr[rx], (uint16_t) imm);
8727 break;
8728 case M16_OPC_CMPI:
8729 tcg_gen_xori_tl(cpu_gpr[24], cpu_gpr[rx], (uint16_t) imm);
8730 break;
8731#if defined(TARGET_MIPS64)
8732 case M16_OPC_SD:
5c13fdfd 8733 gen_st(ctx, OPC_SD, ry, rx, offset);
364d4831
NF
8734 break;
8735#endif
8736 case M16_OPC_LB:
afa88c3a 8737 gen_ld(env, ctx, OPC_LB, ry, rx, offset);
364d4831
NF
8738 break;
8739 case M16_OPC_LH:
afa88c3a 8740 gen_ld(env, ctx, OPC_LH, ry, rx, offset);
364d4831
NF
8741 break;
8742 case M16_OPC_LWSP:
afa88c3a 8743 gen_ld(env, ctx, OPC_LW, rx, 29, offset);
364d4831
NF
8744 break;
8745 case M16_OPC_LW:
afa88c3a 8746 gen_ld(env, ctx, OPC_LW, ry, rx, offset);
364d4831
NF
8747 break;
8748 case M16_OPC_LBU:
afa88c3a 8749 gen_ld(env, ctx, OPC_LBU, ry, rx, offset);
364d4831
NF
8750 break;
8751 case M16_OPC_LHU:
afa88c3a 8752 gen_ld(env, ctx, OPC_LHU, ry, rx, offset);
364d4831
NF
8753 break;
8754 case M16_OPC_LWPC:
afa88c3a 8755 gen_ld(env, ctx, OPC_LWPC, rx, 0, offset);
364d4831
NF
8756 break;
8757#if defined(TARGET_MIPS64)
8758 case M16_OPC_LWU:
afa88c3a 8759 gen_ld(env, ctx, OPC_LWU, ry, rx, offset);
364d4831
NF
8760 break;
8761#endif
8762 case M16_OPC_SB:
5c13fdfd 8763 gen_st(ctx, OPC_SB, ry, rx, offset);
364d4831
NF
8764 break;
8765 case M16_OPC_SH:
5c13fdfd 8766 gen_st(ctx, OPC_SH, ry, rx, offset);
364d4831
NF
8767 break;
8768 case M16_OPC_SWSP:
5c13fdfd 8769 gen_st(ctx, OPC_SW, rx, 29, offset);
364d4831
NF
8770 break;
8771 case M16_OPC_SW:
5c13fdfd 8772 gen_st(ctx, OPC_SW, ry, rx, offset);
364d4831
NF
8773 break;
8774#if defined(TARGET_MIPS64)
8775 case M16_OPC_I64:
8776 decode_i64_mips16(env, ctx, ry, funct, offset, 1);
8777 break;
8778#endif
8779 default:
8780 generate_exception(ctx, EXCP_RI);
8781 break;
8782 }
8783
8784 return 4;
8785}
8786
8787static int decode_mips16_opc (CPUState *env, DisasContext *ctx,
8788 int *is_branch)
8789{
8790 int rx, ry;
8791 int sa;
8792 int op, cnvt_op, op1, offset;
8793 int funct;
8794 int n_bytes;
8795
8796 op = (ctx->opcode >> 11) & 0x1f;
8797 sa = (ctx->opcode >> 2) & 0x7;
8798 sa = sa == 0 ? 8 : sa;
8799 rx = xlat((ctx->opcode >> 8) & 0x7);
8800 cnvt_op = (ctx->opcode >> 5) & 0x7;
8801 ry = xlat((ctx->opcode >> 5) & 0x7);
8802 op1 = offset = ctx->opcode & 0x1f;
8803
8804 n_bytes = 2;
8805
8806 switch (op) {
8807 case M16_OPC_ADDIUSP:
8808 {
8809 int16_t imm = ((uint8_t) ctx->opcode) << 2;
8810
8811 gen_arith_imm(env, ctx, OPC_ADDIU, rx, 29, imm);
8812 }
8813 break;
8814 case M16_OPC_ADDIUPC:
8815 gen_addiupc(ctx, rx, ((uint8_t) ctx->opcode) << 2, 0, 0);
8816 break;
8817 case M16_OPC_B:
8818 offset = (ctx->opcode & 0x7ff) << 1;
8819 offset = (int16_t)(offset << 4) >> 4;
8820 gen_compute_branch(ctx, OPC_BEQ, 2, 0, 0, offset);
8821 /* No delay slot, so just process as a normal instruction */
8822 break;
8823 case M16_OPC_JAL:
8824 offset = lduw_code(ctx->pc + 2);
8825 offset = (((ctx->opcode & 0x1f) << 21)
8826 | ((ctx->opcode >> 5) & 0x1f) << 16
8827 | offset) << 2;
620e48f6 8828 op = ((ctx->opcode >> 10) & 0x1) ? OPC_JALXS : OPC_JALS;
364d4831
NF
8829 gen_compute_branch(ctx, op, 4, rx, ry, offset);
8830 n_bytes = 4;
8831 *is_branch = 1;
8832 break;
8833 case M16_OPC_BEQZ:
8834 gen_compute_branch(ctx, OPC_BEQ, 2, rx, 0, ((int8_t)ctx->opcode) << 1);
8835 /* No delay slot, so just process as a normal instruction */
8836 break;
8837 case M16_OPC_BNEQZ:
8838 gen_compute_branch(ctx, OPC_BNE, 2, rx, 0, ((int8_t)ctx->opcode) << 1);
8839 /* No delay slot, so just process as a normal instruction */
8840 break;
8841 case M16_OPC_SHIFT:
8842 switch (ctx->opcode & 0x3) {
8843 case 0x0:
8844 gen_shift_imm(env, ctx, OPC_SLL, rx, ry, sa);
8845 break;
8846 case 0x1:
8847#if defined(TARGET_MIPS64)
8848 check_mips_64(ctx);
8849 gen_shift_imm(env, ctx, OPC_DSLL, rx, ry, sa);
8850#else
8851 generate_exception(ctx, EXCP_RI);
8852#endif
8853 break;
8854 case 0x2:
8855 gen_shift_imm(env, ctx, OPC_SRL, rx, ry, sa);
8856 break;
8857 case 0x3:
8858 gen_shift_imm(env, ctx, OPC_SRA, rx, ry, sa);
8859 break;
8860 }
8861 break;
8862#if defined(TARGET_MIPS64)
8863 case M16_OPC_LD:
8864 check_mips_64(ctx);
afa88c3a 8865 gen_ld(env, ctx, OPC_LD, ry, rx, offset << 3);
364d4831
NF
8866 break;
8867#endif
8868 case M16_OPC_RRIA:
8869 {
8870 int16_t imm = (int8_t)((ctx->opcode & 0xf) << 4) >> 4;
8871
8872 if ((ctx->opcode >> 4) & 1) {
8873#if defined(TARGET_MIPS64)
8874 check_mips_64(ctx);
8875 gen_arith_imm(env, ctx, OPC_DADDIU, ry, rx, imm);
8876#else
8877 generate_exception(ctx, EXCP_RI);
8878#endif
8879 } else {
8880 gen_arith_imm(env, ctx, OPC_ADDIU, ry, rx, imm);
8881 }
8882 }
8883 break;
8884 case M16_OPC_ADDIU8:
8885 {
8886 int16_t imm = (int8_t) ctx->opcode;
8887
8888 gen_arith_imm(env, ctx, OPC_ADDIU, rx, rx, imm);
8889 }
8890 break;
8891 case M16_OPC_SLTI:
8892 {
8893 int16_t imm = (uint8_t) ctx->opcode;
8894
8895 gen_slt_imm(env, OPC_SLTI, 24, rx, imm);
8896 }
8897 break;
8898 case M16_OPC_SLTIU:
8899 {
8900 int16_t imm = (uint8_t) ctx->opcode;
8901
8902 gen_slt_imm(env, OPC_SLTIU, 24, rx, imm);
8903 }
8904 break;
8905 case M16_OPC_I8:
8906 {
8907 int reg32;
8908
8909 funct = (ctx->opcode >> 8) & 0x7;
8910 switch (funct) {
8911 case I8_BTEQZ:
8912 gen_compute_branch(ctx, OPC_BEQ, 2, 24, 0,
8913 ((int8_t)ctx->opcode) << 1);
8914 break;
8915 case I8_BTNEZ:
8916 gen_compute_branch(ctx, OPC_BNE, 2, 24, 0,
8917 ((int8_t)ctx->opcode) << 1);
8918 break;
8919 case I8_SWRASP:
5c13fdfd 8920 gen_st(ctx, OPC_SW, 31, 29, (ctx->opcode & 0xff) << 2);
364d4831
NF
8921 break;
8922 case I8_ADJSP:
8923 gen_arith_imm(env, ctx, OPC_ADDIU, 29, 29,
8924 ((int8_t)ctx->opcode) << 3);
8925 break;
8926 case I8_SVRS:
8927 {
8928 int do_ra = ctx->opcode & (1 << 6);
8929 int do_s0 = ctx->opcode & (1 << 5);
8930 int do_s1 = ctx->opcode & (1 << 4);
8931 int framesize = ctx->opcode & 0xf;
8932
8933 if (framesize == 0) {
8934 framesize = 128;
8935 } else {
8936 framesize = framesize << 3;
8937 }
8938
8939 if (ctx->opcode & (1 << 7)) {
8940 gen_mips16_save(ctx, 0, 0,
8941 do_ra, do_s0, do_s1, framesize);
8942 } else {
8943 gen_mips16_restore(ctx, 0, 0,
8944 do_ra, do_s0, do_s1, framesize);
8945 }
8946 }
8947 break;
8948 case I8_MOV32R:
8949 {
8950 int rz = xlat(ctx->opcode & 0x7);
8951
8952 reg32 = (((ctx->opcode >> 3) & 0x3) << 3) |
8953 ((ctx->opcode >> 5) & 0x7);
8954 gen_arith(env, ctx, OPC_ADDU, reg32, rz, 0);
8955 }
8956 break;
8957 case I8_MOVR32:
8958 reg32 = ctx->opcode & 0x1f;
8959 gen_arith(env, ctx, OPC_ADDU, ry, reg32, 0);
8960 break;
8961 default:
8962 generate_exception(ctx, EXCP_RI);
8963 break;
8964 }
8965 }
8966 break;
8967 case M16_OPC_LI:
8968 {
8969 int16_t imm = (uint8_t) ctx->opcode;
8970
8971 gen_arith_imm(env, ctx, OPC_ADDIU, rx, 0, imm);
8972 }
8973 break;
8974 case M16_OPC_CMPI:
8975 {
8976 int16_t imm = (uint8_t) ctx->opcode;
8977
8978 gen_logic_imm(env, OPC_XORI, 24, rx, imm);
8979 }
8980 break;
8981#if defined(TARGET_MIPS64)
8982 case M16_OPC_SD:
8983 check_mips_64(ctx);
5c13fdfd 8984 gen_st(ctx, OPC_SD, ry, rx, offset << 3);
364d4831
NF
8985 break;
8986#endif
8987 case M16_OPC_LB:
afa88c3a 8988 gen_ld(env, ctx, OPC_LB, ry, rx, offset);
364d4831
NF
8989 break;
8990 case M16_OPC_LH:
afa88c3a 8991 gen_ld(env, ctx, OPC_LH, ry, rx, offset << 1);
364d4831
NF
8992 break;
8993 case M16_OPC_LWSP:
afa88c3a 8994 gen_ld(env, ctx, OPC_LW, rx, 29, ((uint8_t)ctx->opcode) << 2);
364d4831
NF
8995 break;
8996 case M16_OPC_LW:
afa88c3a 8997 gen_ld(env, ctx, OPC_LW, ry, rx, offset << 2);
364d4831
NF
8998 break;
8999 case M16_OPC_LBU:
afa88c3a 9000 gen_ld(env, ctx, OPC_LBU, ry, rx, offset);
364d4831
NF
9001 break;
9002 case M16_OPC_LHU:
afa88c3a 9003 gen_ld(env, ctx, OPC_LHU, ry, rx, offset << 1);
364d4831
NF
9004 break;
9005 case M16_OPC_LWPC:
afa88c3a 9006 gen_ld(env, ctx, OPC_LWPC, rx, 0, ((uint8_t)ctx->opcode) << 2);
364d4831
NF
9007 break;
9008#if defined (TARGET_MIPS64)
9009 case M16_OPC_LWU:
9010 check_mips_64(ctx);
afa88c3a 9011 gen_ld(env, ctx, OPC_LWU, ry, rx, offset << 2);
364d4831
NF
9012 break;
9013#endif
9014 case M16_OPC_SB:
5c13fdfd 9015 gen_st(ctx, OPC_SB, ry, rx, offset);
364d4831
NF
9016 break;
9017 case M16_OPC_SH:
5c13fdfd 9018 gen_st(ctx, OPC_SH, ry, rx, offset << 1);
364d4831
NF
9019 break;
9020 case M16_OPC_SWSP:
5c13fdfd 9021 gen_st(ctx, OPC_SW, rx, 29, ((uint8_t)ctx->opcode) << 2);
364d4831
NF
9022 break;
9023 case M16_OPC_SW:
5c13fdfd 9024 gen_st(ctx, OPC_SW, ry, rx, offset << 2);
364d4831
NF
9025 break;
9026 case M16_OPC_RRR:
9027 {
9028 int rz = xlat((ctx->opcode >> 2) & 0x7);
9029 int mips32_op;
9030
9031 switch (ctx->opcode & 0x3) {
9032 case RRR_ADDU:
9033 mips32_op = OPC_ADDU;
9034 break;
9035 case RRR_SUBU:
9036 mips32_op = OPC_SUBU;
9037 break;
9038#if defined(TARGET_MIPS64)
9039 case RRR_DADDU:
9040 mips32_op = OPC_DADDU;
9041 check_mips_64(ctx);
9042 break;
9043 case RRR_DSUBU:
9044 mips32_op = OPC_DSUBU;
9045 check_mips_64(ctx);
9046 break;
9047#endif
9048 default:
9049 generate_exception(ctx, EXCP_RI);
9050 goto done;
9051 }
9052
9053 gen_arith(env, ctx, mips32_op, rz, rx, ry);
9054 done:
9055 ;
9056 }
9057 break;
9058 case M16_OPC_RR:
9059 switch (op1) {
9060 case RR_JR:
9061 {
9062 int nd = (ctx->opcode >> 7) & 0x1;
9063 int link = (ctx->opcode >> 6) & 0x1;
9064 int ra = (ctx->opcode >> 5) & 0x1;
9065
9066 if (link) {
620e48f6 9067 op = nd ? OPC_JALRC : OPC_JALRS;
364d4831
NF
9068 } else {
9069 op = OPC_JR;
9070 }
9071
9072 gen_compute_branch(ctx, op, 2, ra ? 31 : rx, 31, 0);
9073 if (!nd) {
9074 *is_branch = 1;
9075 }
9076 }
9077 break;
9078 case RR_SDBBP:
9079 /* XXX: not clear which exception should be raised
9080 * when in debug mode...
9081 */
9082 check_insn(env, ctx, ISA_MIPS32);
9083 if (!(ctx->hflags & MIPS_HFLAG_DM)) {
9084 generate_exception(ctx, EXCP_DBp);
9085 } else {
9086 generate_exception(ctx, EXCP_DBp);
9087 }
9088 break;
9089 case RR_SLT:
9090 gen_slt(env, OPC_SLT, 24, rx, ry);
9091 break;
9092 case RR_SLTU:
9093 gen_slt(env, OPC_SLTU, 24, rx, ry);
9094 break;
9095 case RR_BREAK:
9096 generate_exception(ctx, EXCP_BREAK);
9097 break;
9098 case RR_SLLV:
9099 gen_shift(env, ctx, OPC_SLLV, ry, rx, ry);
9100 break;
9101 case RR_SRLV:
9102 gen_shift(env, ctx, OPC_SRLV, ry, rx, ry);
9103 break;
9104 case RR_SRAV:
9105 gen_shift(env, ctx, OPC_SRAV, ry, rx, ry);
9106 break;
9107#if defined (TARGET_MIPS64)
9108 case RR_DSRL:
9109 check_mips_64(ctx);
9110 gen_shift_imm(env, ctx, OPC_DSRL, ry, ry, sa);
9111 break;
9112#endif
9113 case RR_CMP:
9114 gen_logic(env, OPC_XOR, 24, rx, ry);
9115 break;
9116 case RR_NEG:
9117 gen_arith(env, ctx, OPC_SUBU, rx, 0, ry);
9118 break;
9119 case RR_AND:
9120 gen_logic(env, OPC_AND, rx, rx, ry);
9121 break;
9122 case RR_OR:
9123 gen_logic(env, OPC_OR, rx, rx, ry);
9124 break;
9125 case RR_XOR:
9126 gen_logic(env, OPC_XOR, rx, rx, ry);
9127 break;
9128 case RR_NOT:
9129 gen_logic(env, OPC_NOR, rx, ry, 0);
9130 break;
9131 case RR_MFHI:
9132 gen_HILO(ctx, OPC_MFHI, rx);
9133 break;
9134 case RR_CNVT:
9135 switch (cnvt_op) {
9136 case RR_RY_CNVT_ZEB:
9137 tcg_gen_ext8u_tl(cpu_gpr[rx], cpu_gpr[rx]);
9138 break;
9139 case RR_RY_CNVT_ZEH:
9140 tcg_gen_ext16u_tl(cpu_gpr[rx], cpu_gpr[rx]);
9141 break;
9142 case RR_RY_CNVT_SEB:
9143 tcg_gen_ext8s_tl(cpu_gpr[rx], cpu_gpr[rx]);
9144 break;
9145 case RR_RY_CNVT_SEH:
9146 tcg_gen_ext16s_tl(cpu_gpr[rx], cpu_gpr[rx]);
9147 break;
9148#if defined (TARGET_MIPS64)
9149 case RR_RY_CNVT_ZEW:
9150 check_mips_64(ctx);
9151 tcg_gen_ext32u_tl(cpu_gpr[rx], cpu_gpr[rx]);
9152 break;
9153 case RR_RY_CNVT_SEW:
9154 check_mips_64(ctx);
9155 tcg_gen_ext32s_tl(cpu_gpr[rx], cpu_gpr[rx]);
9156 break;
9157#endif
9158 default:
9159 generate_exception(ctx, EXCP_RI);
9160 break;
9161 }
9162 break;
9163 case RR_MFLO:
9164 gen_HILO(ctx, OPC_MFLO, rx);
9165 break;
9166#if defined (TARGET_MIPS64)
9167 case RR_DSRA:
9168 check_mips_64(ctx);
9169 gen_shift_imm(env, ctx, OPC_DSRA, ry, ry, sa);
9170 break;
9171 case RR_DSLLV:
9172 check_mips_64(ctx);
9173 gen_shift(env, ctx, OPC_DSLLV, ry, rx, ry);
9174 break;
9175 case RR_DSRLV:
9176 check_mips_64(ctx);
9177 gen_shift(env, ctx, OPC_DSRLV, ry, rx, ry);
9178 break;
9179 case RR_DSRAV:
9180 check_mips_64(ctx);
9181 gen_shift(env, ctx, OPC_DSRAV, ry, rx, ry);
9182 break;
9183#endif
9184 case RR_MULT:
9185 gen_muldiv(ctx, OPC_MULT, rx, ry);
9186 break;
9187 case RR_MULTU:
9188 gen_muldiv(ctx, OPC_MULTU, rx, ry);
9189 break;
9190 case RR_DIV:
9191 gen_muldiv(ctx, OPC_DIV, rx, ry);
9192 break;
9193 case RR_DIVU:
9194 gen_muldiv(ctx, OPC_DIVU, rx, ry);
9195 break;
9196#if defined (TARGET_MIPS64)
9197 case RR_DMULT:
9198 check_mips_64(ctx);
9199 gen_muldiv(ctx, OPC_DMULT, rx, ry);
9200 break;
9201 case RR_DMULTU:
9202 check_mips_64(ctx);
9203 gen_muldiv(ctx, OPC_DMULTU, rx, ry);
9204 break;
9205 case RR_DDIV:
9206 check_mips_64(ctx);
9207 gen_muldiv(ctx, OPC_DDIV, rx, ry);
9208 break;
9209 case RR_DDIVU:
9210 check_mips_64(ctx);
9211 gen_muldiv(ctx, OPC_DDIVU, rx, ry);
9212 break;
9213#endif
9214 default:
9215 generate_exception(ctx, EXCP_RI);
9216 break;
9217 }
9218 break;
9219 case M16_OPC_EXTEND:
9220 decode_extended_mips16_opc(env, ctx, is_branch);
9221 n_bytes = 4;
9222 break;
9223#if defined(TARGET_MIPS64)
9224 case M16_OPC_I64:
9225 funct = (ctx->opcode >> 8) & 0x7;
9226 decode_i64_mips16(env, ctx, ry, funct, offset, 0);
9227 break;
9228#endif
9229 default:
9230 generate_exception(ctx, EXCP_RI);
9231 break;
9232 }
9233
9234 return n_bytes;
9235}
9236
3c824109 9237/* microMIPS extension to MIPS32 */
6af0bf9c 9238
3c824109 9239/* microMIPS32 major opcodes */
6af0bf9c 9240
3c824109
NF
9241enum {
9242 POOL32A = 0x00,
9243 POOL16A = 0x01,
9244 LBU16 = 0x02,
9245 MOVE16 = 0x03,
9246 ADDI32 = 0x04,
9247 LBU32 = 0x05,
9248 SB32 = 0x06,
9249 LB32 = 0x07,
9250
9251 POOL32B = 0x08,
9252 POOL16B = 0x09,
9253 LHU16 = 0x0a,
9254 ANDI16 = 0x0b,
9255 ADDIU32 = 0x0c,
9256 LHU32 = 0x0d,
9257 SH32 = 0x0e,
9258 LH32 = 0x0f,
9259
9260 POOL32I = 0x10,
9261 POOL16C = 0x11,
9262 LWSP16 = 0x12,
9263 POOL16D = 0x13,
9264 ORI32 = 0x14,
9265 POOL32F = 0x15,
9266 POOL32S = 0x16,
9267 DADDIU32 = 0x17,
9268
9269 POOL32C = 0x18,
9270 LWGP16 = 0x19,
9271 LW16 = 0x1a,
9272 POOL16E = 0x1b,
9273 XORI32 = 0x1c,
9274 JALS32 = 0x1d,
9275 ADDIUPC = 0x1e,
9276 POOL48A = 0x1f,
9277
9278 /* 0x20 is reserved */
9279 RES_20 = 0x20,
9280 POOL16F = 0x21,
9281 SB16 = 0x22,
9282 BEQZ16 = 0x23,
9283 SLTI32 = 0x24,
9284 BEQ32 = 0x25,
9285 SWC132 = 0x26,
9286 LWC132 = 0x27,
9287
9288 /* 0x28 and 0x29 are reserved */
9289 RES_28 = 0x28,
9290 RES_29 = 0x29,
9291 SH16 = 0x2a,
9292 BNEZ16 = 0x2b,
9293 SLTIU32 = 0x2c,
9294 BNE32 = 0x2d,
9295 SDC132 = 0x2e,
9296 LDC132 = 0x2f,
9297
9298 /* 0x30 and 0x31 are reserved */
9299 RES_30 = 0x30,
9300 RES_31 = 0x31,
9301 SWSP16 = 0x32,
9302 B16 = 0x33,
9303 ANDI32 = 0x34,
9304 J32 = 0x35,
9305 SD32 = 0x36,
9306 LD32 = 0x37,
9307
9308 /* 0x38 and 0x39 are reserved */
9309 RES_38 = 0x38,
9310 RES_39 = 0x39,
9311 SW16 = 0x3a,
9312 LI16 = 0x3b,
9313 JALX32 = 0x3c,
9314 JAL32 = 0x3d,
9315 SW32 = 0x3e,
9316 LW32 = 0x3f
9317};
9318
9319/* POOL32A encoding of minor opcode field */
9320
9321enum {
9322 /* These opcodes are distinguished only by bits 9..6; those bits are
9323 * what are recorded below. */
9324 SLL32 = 0x0,
9325 SRL32 = 0x1,
9326 SRA = 0x2,
9327 ROTR = 0x3,
9328
9329 SLLV = 0x0,
9330 SRLV = 0x1,
9331 SRAV = 0x2,
9332 ROTRV = 0x3,
9333 ADD = 0x4,
9334 ADDU32 = 0x5,
9335 SUB = 0x6,
9336 SUBU32 = 0x7,
9337 MUL = 0x8,
9338 AND = 0x9,
9339 OR32 = 0xa,
9340 NOR = 0xb,
9341 XOR32 = 0xc,
9342 SLT = 0xd,
9343 SLTU = 0xe,
9344
9345 MOVN = 0x0,
9346 MOVZ = 0x1,
9347 LWXS = 0x4,
9348
9349 /* The following can be distinguished by their lower 6 bits. */
9350 INS = 0x0c,
9351 EXT = 0x2c,
9352 POOL32AXF = 0x3c
9353};
9354
9355/* POOL32AXF encoding of minor opcode field extension */
9356
9357enum {
9358 /* bits 11..6 */
9359 TEQ = 0x00,
9360 TGE = 0x08,
9361 TGEU = 0x10,
9362 TLT = 0x20,
9363 TLTU = 0x28,
9364 TNE = 0x30,
9365
9366 MFC0 = 0x03,
9367 MTC0 = 0x0b,
9368
9369 /* bits 13..12 for 0x01 */
9370 MFHI_ACC = 0x0,
9371 MFLO_ACC = 0x1,
9372 MTHI_ACC = 0x2,
9373 MTLO_ACC = 0x3,
9374
9375 /* bits 13..12 for 0x2a */
9376 MADD_ACC = 0x0,
9377 MADDU_ACC = 0x1,
9378 MSUB_ACC = 0x2,
9379 MSUBU_ACC = 0x3,
9380
9381 /* bits 13..12 for 0x32 */
9382 MULT_ACC = 0x0,
9383 MULTU_ACC = 0x0,
9384
9385 /* bits 15..12 for 0x2c */
9386 SEB = 0x2,
9387 SEH = 0x3,
9388 CLO = 0x4,
9389 CLZ = 0x5,
9390 RDHWR = 0x6,
9391 WSBH = 0x7,
9392 MULT = 0x8,
9393 MULTU = 0x9,
9394 DIV = 0xa,
9395 DIVU = 0xb,
9396 MADD = 0xc,
9397 MADDU = 0xd,
9398 MSUB = 0xe,
9399 MSUBU = 0xf,
9400
9401 /* bits 15..12 for 0x34 */
9402 MFC2 = 0x4,
9403 MTC2 = 0x5,
9404 MFHC2 = 0x8,
9405 MTHC2 = 0x9,
9406 CFC2 = 0xc,
9407 CTC2 = 0xd,
9408
9409 /* bits 15..12 for 0x3c */
9410 JALR = 0x0,
9411 JR = 0x0, /* alias */
9412 JALR_HB = 0x1,
9413 JALRS = 0x4,
9414 JALRS_HB = 0x5,
9415
9416 /* bits 15..12 for 0x05 */
9417 RDPGPR = 0xe,
9418 WRPGPR = 0xf,
9419
9420 /* bits 15..12 for 0x0d */
9421 TLBP = 0x0,
9422 TLBR = 0x1,
9423 TLBWI = 0x2,
9424 TLBWR = 0x3,
9425 WAIT = 0x9,
9426 IRET = 0xd,
9427 DERET = 0xe,
9428 ERET = 0xf,
9429
9430 /* bits 15..12 for 0x15 */
9431 DMT = 0x0,
9432 DVPE = 0x1,
9433 EMT = 0x2,
9434 EVPE = 0x3,
9435
9436 /* bits 15..12 for 0x1d */
9437 DI = 0x4,
9438 EI = 0x5,
9439
9440 /* bits 15..12 for 0x2d */
9441 SYNC = 0x6,
9442 SYSCALL = 0x8,
9443 SDBBP = 0xd,
9444
9445 /* bits 15..12 for 0x35 */
9446 MFHI32 = 0x0,
9447 MFLO32 = 0x1,
9448 MTHI32 = 0x2,
9449 MTLO32 = 0x3,
9450};
9451
9452/* POOL32B encoding of minor opcode field (bits 15..12) */
9453
9454enum {
9455 LWC2 = 0x0,
9456 LWP = 0x1,
9457 LDP = 0x4,
9458 LWM32 = 0x5,
9459 CACHE = 0x6,
9460 LDM = 0x7,
9461 SWC2 = 0x8,
9462 SWP = 0x9,
9463 SDP = 0xc,
9464 SWM32 = 0xd,
9465 SDM = 0xf
9466};
9467
9468/* POOL32C encoding of minor opcode field (bits 15..12) */
9469
9470enum {
9471 LWL = 0x0,
9472 SWL = 0x8,
9473 LWR = 0x1,
9474 SWR = 0x9,
9475 PREF = 0x2,
9476 /* 0xa is reserved */
9477 LL = 0x3,
9478 SC = 0xb,
9479 LDL = 0x4,
9480 SDL = 0xc,
9481 LDR = 0x5,
9482 SDR = 0xd,
9483 /* 0x6 is reserved */
9484 LWU = 0xe,
9485 LLD = 0x7,
9486 SCD = 0xf
9487};
9488
9489/* POOL32F encoding of minor opcode field (bits 5..0) */
9490
9491enum {
9492 /* These are the bit 7..6 values */
9493 ADD_FMT = 0x0,
9494 MOVN_FMT = 0x0,
9495
9496 SUB_FMT = 0x1,
9497 MOVZ_FMT = 0x1,
9498
9499 MUL_FMT = 0x2,
9500
9501 DIV_FMT = 0x3,
9502
9503 /* These are the bit 8..6 values */
9504 RSQRT2_FMT = 0x0,
9505 MOVF_FMT = 0x0,
9506
9507 LWXC1 = 0x1,
9508 MOVT_FMT = 0x1,
9509
9510 PLL_PS = 0x2,
9511 SWXC1 = 0x2,
9512
9513 PLU_PS = 0x3,
9514 LDXC1 = 0x3,
9515
9516 PUL_PS = 0x4,
9517 SDXC1 = 0x4,
9518 RECIP2_FMT = 0x4,
9519
9520 PUU_PS = 0x5,
9521 LUXC1 = 0x5,
9522
9523 CVT_PS_S = 0x6,
9524 SUXC1 = 0x6,
9525 ADDR_PS = 0x6,
9526 PREFX = 0x6,
9527
9528 MULR_PS = 0x7,
9529
9530 MADD_S = 0x01,
9531 MADD_D = 0x09,
9532 MADD_PS = 0x11,
9533 ALNV_PS = 0x19,
9534 MSUB_S = 0x21,
9535 MSUB_D = 0x29,
9536 MSUB_PS = 0x31,
9537
9538 NMADD_S = 0x02,
9539 NMADD_D = 0x0a,
9540 NMADD_PS = 0x12,
9541 NMSUB_S = 0x22,
9542 NMSUB_D = 0x2a,
9543 NMSUB_PS = 0x32,
9544
9545 POOL32FXF = 0x3b,
9546
9547 CABS_COND_FMT = 0x1c, /* MIPS3D */
9548 C_COND_FMT = 0x3c
9549};
9550
9551/* POOL32Fxf encoding of minor opcode extension field */
9552
9553enum {
9554 CVT_L = 0x04,
9555 RSQRT_FMT = 0x08,
9556 FLOOR_L = 0x0c,
9557 CVT_PW_PS = 0x1c,
9558 CVT_W = 0x24,
9559 SQRT_FMT = 0x28,
9560 FLOOR_W = 0x2c,
9561 CVT_PS_PW = 0x3c,
9562 CFC1 = 0x40,
9563 RECIP_FMT = 0x48,
9564 CEIL_L = 0x4c,
9565 CTC1 = 0x60,
9566 CEIL_W = 0x6c,
9567 MFC1 = 0x80,
9568 CVT_S_PL = 0x84,
9569 TRUNC_L = 0x8c,
9570 MTC1 = 0xa0,
9571 CVT_S_PU = 0xa4,
9572 TRUNC_W = 0xac,
9573 MFHC1 = 0xc0,
9574 ROUND_L = 0xcc,
9575 MTHC1 = 0xe0,
9576 ROUND_W = 0xec,
9577
9578 MOV_FMT = 0x01,
9579 MOVF = 0x05,
9580 ABS_FMT = 0x0d,
9581 RSQRT1_FMT = 0x1d,
9582 MOVT = 0x25,
9583 NEG_FMT = 0x2d,
9584 CVT_D = 0x4d,
9585 RECIP1_FMT = 0x5d,
9586 CVT_S = 0x6d
9587};
9588
9589/* POOL32I encoding of minor opcode field (bits 25..21) */
9590
9591enum {
9592 BLTZ = 0x00,
9593 BLTZAL = 0x01,
9594 BGEZ = 0x02,
9595 BGEZAL = 0x03,
9596 BLEZ = 0x04,
9597 BNEZC = 0x05,
9598 BGTZ = 0x06,
9599 BEQZC = 0x07,
9600 TLTI = 0x08,
9601 TGEI = 0x09,
9602 TLTIU = 0x0a,
9603 TGEIU = 0x0b,
9604 TNEI = 0x0c,
9605 LUI = 0x0d,
9606 TEQI = 0x0e,
9607 SYNCI = 0x10,
9608 BLTZALS = 0x11,
9609 BGEZALS = 0x13,
9610 BC2F = 0x14,
9611 BC2T = 0x15,
9612 BPOSGE64 = 0x1a,
9613 BPOSGE32 = 0x1b,
9614 /* These overlap and are distinguished by bit16 of the instruction */
9615 BC1F = 0x1c,
9616 BC1T = 0x1d,
9617 BC1ANY2F = 0x1c,
9618 BC1ANY2T = 0x1d,
9619 BC1ANY4F = 0x1e,
9620 BC1ANY4T = 0x1f
9621};
9622
9623/* POOL16A encoding of minor opcode field */
9624
9625enum {
9626 ADDU16 = 0x0,
9627 SUBU16 = 0x1
9628};
9629
9630/* POOL16B encoding of minor opcode field */
9631
9632enum {
9633 SLL16 = 0x0,
9634 SRL16 = 0x1
9635};
9636
9637/* POOL16C encoding of minor opcode field */
9638
9639enum {
9640 NOT16 = 0x00,
9641 XOR16 = 0x04,
9642 AND16 = 0x08,
9643 OR16 = 0x0c,
9644 LWM16 = 0x10,
9645 SWM16 = 0x14,
9646 JR16 = 0x18,
9647 JRC16 = 0x1a,
9648 JALR16 = 0x1c,
9649 JALR16S = 0x1e,
9650 MFHI16 = 0x20,
9651 MFLO16 = 0x24,
9652 BREAK16 = 0x28,
9653 SDBBP16 = 0x2c,
9654 JRADDIUSP = 0x30
9655};
9656
9657/* POOL16D encoding of minor opcode field */
9658
9659enum {
9660 ADDIUS5 = 0x0,
9661 ADDIUSP = 0x1
9662};
9663
9664/* POOL16E encoding of minor opcode field */
9665
9666enum {
9667 ADDIUR2 = 0x0,
9668 ADDIUR1SP = 0x1
9669};
9670
9671static int mmreg (int r)
9672{
9673 static const int map[] = { 16, 17, 2, 3, 4, 5, 6, 7 };
9674
9675 return map[r];
9676}
9677
9678/* Used for 16-bit store instructions. */
9679static int mmreg2 (int r)
9680{
9681 static const int map[] = { 0, 17, 2, 3, 4, 5, 6, 7 };
9682
9683 return map[r];
9684}
9685
9686#define uMIPS_RD(op) ((op >> 7) & 0x7)
9687#define uMIPS_RS(op) ((op >> 4) & 0x7)
9688#define uMIPS_RS2(op) uMIPS_RS(op)
9689#define uMIPS_RS1(op) ((op >> 1) & 0x7)
9690#define uMIPS_RD5(op) ((op >> 5) & 0x1f)
9691#define uMIPS_RS5(op) (op & 0x1f)
9692
9693/* Signed immediate */
9694#define SIMM(op, start, width) \
9695 ((int32_t)(((op >> start) & ((~0U) >> (32-width))) \
9696 << (32-width)) \
9697 >> (32-width))
9698/* Zero-extended immediate */
9699#define ZIMM(op, start, width) ((op >> start) & ((~0U) >> (32-width)))
9700
9701static void gen_addiur1sp (CPUState *env, DisasContext *ctx)
9702{
9703 int rd = mmreg(uMIPS_RD(ctx->opcode));
9704
9705 gen_arith_imm(env, ctx, OPC_ADDIU, rd, 29, ((ctx->opcode >> 1) & 0x3f) << 2);
9706}
9707
9708static void gen_addiur2 (CPUState *env, DisasContext *ctx)
9709{
9710 static const int decoded_imm[] = { 1, 4, 8, 12, 16, 20, 24, -1 };
9711 int rd = mmreg(uMIPS_RD(ctx->opcode));
9712 int rs = mmreg(uMIPS_RS(ctx->opcode));
9713
9714 gen_arith_imm(env, ctx, OPC_ADDIU, rd, rs, decoded_imm[ZIMM(ctx->opcode, 1, 3)]);
9715}
9716
9717static void gen_addiusp (CPUState *env, DisasContext *ctx)
9718{
9719 int encoded = ZIMM(ctx->opcode, 1, 9);
9720 int decoded;
9721
9722 if (encoded <= 1) {
9723 decoded = 256 + encoded;
9724 } else if (encoded <= 255) {
9725 decoded = encoded;
9726 } else if (encoded <= 509) {
9727 decoded = encoded - 512;
9728 } else {
9729 decoded = encoded - 768;
9730 }
9731
9732 gen_arith_imm(env, ctx, OPC_ADDIU, 29, 29, decoded << 2);
9733}
9734
9735static void gen_addius5 (CPUState *env, DisasContext *ctx)
9736{
9737 int imm = SIMM(ctx->opcode, 1, 4);
9738 int rd = (ctx->opcode >> 5) & 0x1f;
9739
9740 gen_arith_imm(env, ctx, OPC_ADDIU, rd, rd, imm);
9741}
9742
9743static void gen_andi16 (CPUState *env, DisasContext *ctx)
9744{
9745 static const int decoded_imm[] = { 128, 1, 2, 3, 4, 7, 8, 15, 16,
9746 31, 32, 63, 64, 255, 32768, 65535 };
9747 int rd = mmreg(uMIPS_RD(ctx->opcode));
9748 int rs = mmreg(uMIPS_RS(ctx->opcode));
9749 int encoded = ZIMM(ctx->opcode, 0, 4);
9750
9751 gen_logic_imm(env, OPC_ANDI, rd, rs, decoded_imm[encoded]);
9752}
9753
9754static void gen_ldst_multiple (DisasContext *ctx, uint32_t opc, int reglist,
9755 int base, int16_t offset)
9756{
9757 TCGv t0, t1;
9758 TCGv_i32 t2;
9759
9760 if (ctx->hflags & MIPS_HFLAG_BMASK) {
9761 generate_exception(ctx, EXCP_RI);
9762 return;
9763 }
9764
9765 t0 = tcg_temp_new();
9766
9767 gen_base_offset_addr(ctx, t0, base, offset);
9768
9769 t1 = tcg_const_tl(reglist);
9770 t2 = tcg_const_i32(ctx->mem_idx);
6af0bf9c 9771
3c824109
NF
9772 save_cpu_state(ctx, 1);
9773 switch (opc) {
9774 case LWM32:
9775 gen_helper_lwm(t0, t1, t2);
9776 break;
9777 case SWM32:
9778 gen_helper_swm(t0, t1, t2);
9779 break;
9780#ifdef TARGET_MIPS64
9781 case LDM:
9782 gen_helper_ldm(t0, t1, t2);
9783 break;
9784 case SDM:
9785 gen_helper_sdm(t0, t1, t2);
9786 break;
6af0bf9c 9787#endif
3c824109
NF
9788 }
9789 MIPS_DEBUG("%s, %x, %d(%s)", opn, reglist, offset, regnames[base]);
9790 tcg_temp_free(t0);
33087598 9791 tcg_temp_free(t1);
3c824109
NF
9792 tcg_temp_free_i32(t2);
9793}
6af0bf9c 9794
3c824109
NF
9795
9796static void gen_pool16c_insn (CPUState *env, DisasContext *ctx, int *is_branch)
6af0bf9c 9797{
3c824109
NF
9798 int rd = mmreg((ctx->opcode >> 3) & 0x7);
9799 int rs = mmreg(ctx->opcode & 0x7);
9800 int opc;
6af0bf9c 9801
3c824109
NF
9802 switch (((ctx->opcode) >> 4) & 0x3f) {
9803 case NOT16 + 0:
9804 case NOT16 + 1:
9805 case NOT16 + 2:
9806 case NOT16 + 3:
9807 gen_logic(env, OPC_NOR, rd, rs, 0);
9808 break;
9809 case XOR16 + 0:
9810 case XOR16 + 1:
9811 case XOR16 + 2:
9812 case XOR16 + 3:
9813 gen_logic(env, OPC_XOR, rd, rd, rs);
9814 break;
9815 case AND16 + 0:
9816 case AND16 + 1:
9817 case AND16 + 2:
9818 case AND16 + 3:
9819 gen_logic(env, OPC_AND, rd, rd, rs);
9820 break;
9821 case OR16 + 0:
9822 case OR16 + 1:
9823 case OR16 + 2:
9824 case OR16 + 3:
9825 gen_logic(env, OPC_OR, rd, rd, rs);
9826 break;
9827 case LWM16 + 0:
9828 case LWM16 + 1:
9829 case LWM16 + 2:
9830 case LWM16 + 3:
9831 {
9832 static const int lwm_convert[] = { 0x11, 0x12, 0x13, 0x14 };
9833 int offset = ZIMM(ctx->opcode, 0, 4);
9834
9835 gen_ldst_multiple(ctx, LWM32, lwm_convert[(ctx->opcode >> 4) & 0x3],
9836 29, offset << 2);
9837 }
9838 break;
9839 case SWM16 + 0:
9840 case SWM16 + 1:
9841 case SWM16 + 2:
9842 case SWM16 + 3:
9843 {
9844 static const int swm_convert[] = { 0x11, 0x12, 0x13, 0x14 };
9845 int offset = ZIMM(ctx->opcode, 0, 4);
9846
9847 gen_ldst_multiple(ctx, SWM32, swm_convert[(ctx->opcode >> 4) & 0x3],
9848 29, offset << 2);
9849 }
9850 break;
9851 case JR16 + 0:
9852 case JR16 + 1:
9853 {
9854 int reg = ctx->opcode & 0x1f;
9855
9856 gen_compute_branch(ctx, OPC_JR, 2, reg, 0, 0);
9857 }
9858 *is_branch = 1;
9859 break;
9860 case JRC16 + 0:
9861 case JRC16 + 1:
9862 {
9863 int reg = ctx->opcode & 0x1f;
9864
9865 gen_compute_branch(ctx, OPC_JR, 2, reg, 0, 0);
9866 /* Let normal delay slot handling in our caller take us
9867 to the branch target. */
9868 }
9869 break;
9870 case JALR16 + 0:
9871 case JALR16 + 1:
9872 opc = OPC_JALR;
9873 goto do_jalr;
9874 case JALR16S + 0:
9875 case JALR16S + 1:
9876 opc = OPC_JALRS;
9877 do_jalr:
9878 {
9879 int reg = ctx->opcode & 0x1f;
9880
9881 gen_compute_branch(ctx, opc, 2, reg, 31, 0);
9882 }
9883 *is_branch = 1;
9884 break;
9885 case MFHI16 + 0:
9886 case MFHI16 + 1:
9887 gen_HILO(ctx, OPC_MFHI, uMIPS_RS5(ctx->opcode));
9888 break;
9889 case MFLO16 + 0:
9890 case MFLO16 + 1:
9891 gen_HILO(ctx, OPC_MFLO, uMIPS_RS5(ctx->opcode));
9892 break;
9893 case BREAK16:
9894 generate_exception(ctx, EXCP_BREAK);
9895 break;
9896 case SDBBP16:
9897 /* XXX: not clear which exception should be raised
9898 * when in debug mode...
9899 */
9900 check_insn(env, ctx, ISA_MIPS32);
9901 if (!(ctx->hflags & MIPS_HFLAG_DM)) {
9902 generate_exception(ctx, EXCP_DBp);
9903 } else {
9904 generate_exception(ctx, EXCP_DBp);
9905 }
9906 break;
9907 case JRADDIUSP + 0:
9908 case JRADDIUSP + 1:
9909 {
9910 int imm = ZIMM(ctx->opcode, 0, 5);
9911
9912 gen_compute_branch(ctx, OPC_JR, 2, 31, 0, 0);
9913 gen_arith_imm(env, ctx, OPC_ADDIU, 29, 29, imm << 2);
9914 /* Let normal delay slot handling in our caller take us
9915 to the branch target. */
9916 }
9917 break;
9918 default:
9919 generate_exception(ctx, EXCP_RI);
9920 break;
9921 }
9922}
9923
9924static void gen_ldxs (DisasContext *ctx, int base, int index, int rd)
9925{
9926 TCGv t0 = tcg_temp_new();
9927 TCGv t1 = tcg_temp_new();
9928
9929 gen_load_gpr(t0, base);
9930
9931 if (index != 0) {
9932 gen_load_gpr(t1, index);
9933 tcg_gen_shli_tl(t1, t1, 2);
9934 gen_op_addr_add(ctx, t0, t1, t0);
9935 }
9936
9937 save_cpu_state(ctx, 0);
5c13fdfd 9938 op_ld_lw(t1, t0, ctx);
3c824109
NF
9939 gen_store_gpr(t1, rd);
9940
9941 tcg_temp_free(t0);
9942 tcg_temp_free(t1);
9943}
9944
9945static void gen_ldst_pair (DisasContext *ctx, uint32_t opc, int rd,
9946 int base, int16_t offset)
9947{
9948 const char *opn = "ldst_pair";
9949 TCGv t0, t1;
9950
9951 if (ctx->hflags & MIPS_HFLAG_BMASK || rd == 31 || rd == base) {
9952 generate_exception(ctx, EXCP_RI);
d796321b
FB
9953 return;
9954 }
9955
3c824109
NF
9956 t0 = tcg_temp_new();
9957 t1 = tcg_temp_new();
8e9ade68 9958
3c824109
NF
9959 gen_base_offset_addr(ctx, t0, base, offset);
9960
9961 switch (opc) {
9962 case LWP:
9963 save_cpu_state(ctx, 0);
5c13fdfd 9964 op_ld_lw(t1, t0, ctx);
3c824109
NF
9965 gen_store_gpr(t1, rd);
9966 tcg_gen_movi_tl(t1, 4);
9967 gen_op_addr_add(ctx, t0, t0, t1);
5c13fdfd 9968 op_ld_lw(t1, t0, ctx);
3c824109
NF
9969 gen_store_gpr(t1, rd+1);
9970 opn = "lwp";
9971 break;
9972 case SWP:
b835e919 9973 save_cpu_state(ctx, 0);
3c824109 9974 gen_load_gpr(t1, rd);
5c13fdfd 9975 op_st_sw(t1, t0, ctx);
3c824109
NF
9976 tcg_gen_movi_tl(t1, 4);
9977 gen_op_addr_add(ctx, t0, t0, t1);
9978 gen_load_gpr(t1, rd+1);
5c13fdfd 9979 op_st_sw(t1, t0, ctx);
3c824109
NF
9980 opn = "swp";
9981 break;
9982#ifdef TARGET_MIPS64
9983 case LDP:
9984 save_cpu_state(ctx, 0);
5c13fdfd 9985 op_ld_ld(t1, t0, ctx);
3c824109
NF
9986 gen_store_gpr(t1, rd);
9987 tcg_gen_movi_tl(t1, 8);
9988 gen_op_addr_add(ctx, t0, t0, t1);
5c13fdfd 9989 op_ld_ld(t1, t0, ctx);
3c824109
NF
9990 gen_store_gpr(t1, rd+1);
9991 opn = "ldp";
9992 break;
9993 case SDP:
b835e919 9994 save_cpu_state(ctx, 0);
3c824109 9995 gen_load_gpr(t1, rd);
5c13fdfd 9996 op_st_sd(t1, t0, ctx);
3c824109
NF
9997 tcg_gen_movi_tl(t1, 8);
9998 gen_op_addr_add(ctx, t0, t0, t1);
9999 gen_load_gpr(t1, rd+1);
5c13fdfd 10000 op_st_sd(t1, t0, ctx);
3c824109
NF
10001 opn = "sdp";
10002 break;
10003#endif
6af0bf9c 10004 }
2abf314d 10005 (void)opn; /* avoid a compiler warning */
3c824109
NF
10006 MIPS_DEBUG("%s, %s, %d(%s)", opn, regnames[rd], offset, regnames[base]);
10007 tcg_temp_free(t0);
10008 tcg_temp_free(t1);
10009}
618b0fe9 10010
3c824109
NF
10011static void gen_pool32axf (CPUState *env, DisasContext *ctx, int rt, int rs,
10012 int *is_branch)
10013{
10014 int extension = (ctx->opcode >> 6) & 0x3f;
10015 int minor = (ctx->opcode >> 12) & 0xf;
10016 uint32_t mips32_op;
10017
10018 switch (extension) {
10019 case TEQ:
10020 mips32_op = OPC_TEQ;
10021 goto do_trap;
10022 case TGE:
10023 mips32_op = OPC_TGE;
10024 goto do_trap;
10025 case TGEU:
10026 mips32_op = OPC_TGEU;
10027 goto do_trap;
10028 case TLT:
10029 mips32_op = OPC_TLT;
10030 goto do_trap;
10031 case TLTU:
10032 mips32_op = OPC_TLTU;
10033 goto do_trap;
10034 case TNE:
10035 mips32_op = OPC_TNE;
10036 do_trap:
10037 gen_trap(ctx, mips32_op, rs, rt, -1);
10038 break;
10039#ifndef CONFIG_USER_ONLY
10040 case MFC0:
10041 case MFC0 + 32:
10042 if (rt == 0) {
10043 /* Treat as NOP. */
10044 break;
10045 }
10046 gen_mfc0(env, ctx, cpu_gpr[rt], rs, (ctx->opcode >> 11) & 0x7);
10047 break;
10048 case MTC0:
10049 case MTC0 + 32:
10050 {
10051 TCGv t0 = tcg_temp_new();
618b0fe9 10052
3c824109
NF
10053 gen_load_gpr(t0, rt);
10054 gen_mtc0(env, ctx, t0, rs, (ctx->opcode >> 11) & 0x7);
10055 tcg_temp_free(t0);
10056 }
10057 break;
10058#endif
10059 case 0x2c:
10060 switch (minor) {
10061 case SEB:
10062 gen_bshfl(ctx, OPC_SEB, rs, rt);
10063 break;
10064 case SEH:
10065 gen_bshfl(ctx, OPC_SEH, rs, rt);
10066 break;
10067 case CLO:
10068 mips32_op = OPC_CLO;
10069 goto do_cl;
10070 case CLZ:
10071 mips32_op = OPC_CLZ;
10072 do_cl:
10073 check_insn(env, ctx, ISA_MIPS32);
10074 gen_cl(ctx, mips32_op, rt, rs);
10075 break;
10076 case RDHWR:
10077 gen_rdhwr(env, ctx, rt, rs);
10078 break;
10079 case WSBH:
10080 gen_bshfl(ctx, OPC_WSBH, rs, rt);
10081 break;
10082 case MULT:
10083 mips32_op = OPC_MULT;
10084 goto do_muldiv;
10085 case MULTU:
10086 mips32_op = OPC_MULTU;
10087 goto do_muldiv;
10088 case DIV:
10089 mips32_op = OPC_DIV;
10090 goto do_muldiv;
10091 case DIVU:
10092 mips32_op = OPC_DIVU;
10093 goto do_muldiv;
10094 case MADD:
10095 mips32_op = OPC_MADD;
10096 goto do_muldiv;
10097 case MADDU:
10098 mips32_op = OPC_MADDU;
10099 goto do_muldiv;
10100 case MSUB:
10101 mips32_op = OPC_MSUB;
10102 goto do_muldiv;
10103 case MSUBU:
10104 mips32_op = OPC_MSUBU;
10105 do_muldiv:
10106 check_insn(env, ctx, ISA_MIPS32);
10107 gen_muldiv(ctx, mips32_op, rs, rt);
10108 break;
10109 default:
10110 goto pool32axf_invalid;
10111 }
10112 break;
10113 case 0x34:
10114 switch (minor) {
10115 case MFC2:
10116 case MTC2:
10117 case MFHC2:
10118 case MTHC2:
10119 case CFC2:
10120 case CTC2:
10121 generate_exception_err(ctx, EXCP_CpU, 2);
10122 break;
10123 default:
10124 goto pool32axf_invalid;
10125 }
10126 break;
10127 case 0x3c:
10128 switch (minor) {
10129 case JALR:
10130 case JALR_HB:
10131 gen_compute_branch (ctx, OPC_JALR, 4, rs, rt, 0);
10132 *is_branch = 1;
10133 break;
10134 case JALRS:
10135 case JALRS_HB:
10136 gen_compute_branch (ctx, OPC_JALRS, 4, rs, rt, 0);
10137 *is_branch = 1;
10138 break;
10139 default:
10140 goto pool32axf_invalid;
10141 }
10142 break;
10143 case 0x05:
10144 switch (minor) {
10145 case RDPGPR:
10146 check_insn(env, ctx, ISA_MIPS32R2);
10147 gen_load_srsgpr(rt, rs);
10148 break;
10149 case WRPGPR:
10150 check_insn(env, ctx, ISA_MIPS32R2);
10151 gen_store_srsgpr(rt, rs);
10152 break;
10153 default:
10154 goto pool32axf_invalid;
10155 }
10156 break;
10157#ifndef CONFIG_USER_ONLY
10158 case 0x0d:
10159 switch (minor) {
10160 case TLBP:
10161 mips32_op = OPC_TLBP;
10162 goto do_cp0;
10163 case TLBR:
10164 mips32_op = OPC_TLBR;
10165 goto do_cp0;
10166 case TLBWI:
10167 mips32_op = OPC_TLBWI;
10168 goto do_cp0;
10169 case TLBWR:
10170 mips32_op = OPC_TLBWR;
10171 goto do_cp0;
10172 case WAIT:
10173 mips32_op = OPC_WAIT;
10174 goto do_cp0;
10175 case DERET:
10176 mips32_op = OPC_DERET;
10177 goto do_cp0;
10178 case ERET:
10179 mips32_op = OPC_ERET;
10180 do_cp0:
10181 gen_cp0(env, ctx, mips32_op, rt, rs);
10182 break;
10183 default:
10184 goto pool32axf_invalid;
10185 }
10186 break;
10187 case 0x1d:
10188 switch (minor) {
10189 case DI:
10190 {
10191 TCGv t0 = tcg_temp_new();
10192
10193 save_cpu_state(ctx, 1);
10194 gen_helper_di(t0);
10195 gen_store_gpr(t0, rs);
10196 /* Stop translation as we may have switched the execution mode */
10197 ctx->bstate = BS_STOP;
10198 tcg_temp_free(t0);
10199 }
10200 break;
10201 case EI:
10202 {
10203 TCGv t0 = tcg_temp_new();
10204
10205 save_cpu_state(ctx, 1);
10206 gen_helper_ei(t0);
10207 gen_store_gpr(t0, rs);
10208 /* Stop translation as we may have switched the execution mode */
10209 ctx->bstate = BS_STOP;
10210 tcg_temp_free(t0);
10211 }
10212 break;
10213 default:
10214 goto pool32axf_invalid;
10215 }
10216 break;
10217#endif
10218 case 0x2d:
10219 switch (minor) {
10220 case SYNC:
10221 /* NOP */
10222 break;
10223 case SYSCALL:
10224 generate_exception(ctx, EXCP_SYSCALL);
10225 ctx->bstate = BS_STOP;
10226 break;
10227 case SDBBP:
10228 check_insn(env, ctx, ISA_MIPS32);
10229 if (!(ctx->hflags & MIPS_HFLAG_DM)) {
10230 generate_exception(ctx, EXCP_DBp);
10231 } else {
10232 generate_exception(ctx, EXCP_DBp);
10233 }
10234 break;
10235 default:
10236 goto pool32axf_invalid;
10237 }
10238 break;
10239 case 0x35:
10240 switch (minor) {
10241 case MFHI32:
10242 gen_HILO(ctx, OPC_MFHI, rs);
10243 break;
10244 case MFLO32:
10245 gen_HILO(ctx, OPC_MFLO, rs);
10246 break;
10247 case MTHI32:
10248 gen_HILO(ctx, OPC_MTHI, rs);
10249 break;
10250 case MTLO32:
10251 gen_HILO(ctx, OPC_MTLO, rs);
10252 break;
10253 default:
10254 goto pool32axf_invalid;
10255 }
10256 break;
10257 default:
10258 pool32axf_invalid:
10259 MIPS_INVAL("pool32axf");
10260 generate_exception(ctx, EXCP_RI);
10261 break;
10262 }
10263}
10264
10265/* Values for microMIPS fmt field. Variable-width, depending on which
10266 formats the instruction supports. */
10267
10268enum {
10269 FMT_SD_S = 0,
10270 FMT_SD_D = 1,
10271
10272 FMT_SDPS_S = 0,
10273 FMT_SDPS_D = 1,
10274 FMT_SDPS_PS = 2,
10275
10276 FMT_SWL_S = 0,
10277 FMT_SWL_W = 1,
10278 FMT_SWL_L = 2,
10279
10280 FMT_DWL_D = 0,
10281 FMT_DWL_W = 1,
10282 FMT_DWL_L = 2
10283};
10284
10285static void gen_pool32fxf (CPUState *env, DisasContext *ctx, int rt, int rs)
10286{
10287 int extension = (ctx->opcode >> 6) & 0x3ff;
10288 uint32_t mips32_op;
10289
10290#define FLOAT_1BIT_FMT(opc, fmt) (fmt << 8) | opc
10291#define FLOAT_2BIT_FMT(opc, fmt) (fmt << 7) | opc
10292#define COND_FLOAT_MOV(opc, cond) (cond << 7) | opc
10293
10294 switch (extension) {
10295 case FLOAT_1BIT_FMT(CFC1, 0):
10296 mips32_op = OPC_CFC1;
10297 goto do_cp1;
10298 case FLOAT_1BIT_FMT(CTC1, 0):
10299 mips32_op = OPC_CTC1;
10300 goto do_cp1;
10301 case FLOAT_1BIT_FMT(MFC1, 0):
10302 mips32_op = OPC_MFC1;
10303 goto do_cp1;
10304 case FLOAT_1BIT_FMT(MTC1, 0):
10305 mips32_op = OPC_MTC1;
10306 goto do_cp1;
10307 case FLOAT_1BIT_FMT(MFHC1, 0):
10308 mips32_op = OPC_MFHC1;
10309 goto do_cp1;
10310 case FLOAT_1BIT_FMT(MTHC1, 0):
10311 mips32_op = OPC_MTHC1;
10312 do_cp1:
10313 gen_cp1(ctx, mips32_op, rt, rs);
10314 break;
10315
10316 /* Reciprocal square root */
10317 case FLOAT_1BIT_FMT(RSQRT_FMT, FMT_SD_S):
10318 mips32_op = OPC_RSQRT_S;
10319 goto do_unaryfp;
10320 case FLOAT_1BIT_FMT(RSQRT_FMT, FMT_SD_D):
10321 mips32_op = OPC_RSQRT_D;
10322 goto do_unaryfp;
10323
10324 /* Square root */
10325 case FLOAT_1BIT_FMT(SQRT_FMT, FMT_SD_S):
10326 mips32_op = OPC_SQRT_S;
10327 goto do_unaryfp;
10328 case FLOAT_1BIT_FMT(SQRT_FMT, FMT_SD_D):
10329 mips32_op = OPC_SQRT_D;
10330 goto do_unaryfp;
10331
10332 /* Reciprocal */
10333 case FLOAT_1BIT_FMT(RECIP_FMT, FMT_SD_S):
10334 mips32_op = OPC_RECIP_S;
10335 goto do_unaryfp;
10336 case FLOAT_1BIT_FMT(RECIP_FMT, FMT_SD_D):
10337 mips32_op = OPC_RECIP_D;
10338 goto do_unaryfp;
10339
10340 /* Floor */
10341 case FLOAT_1BIT_FMT(FLOOR_L, FMT_SD_S):
10342 mips32_op = OPC_FLOOR_L_S;
10343 goto do_unaryfp;
10344 case FLOAT_1BIT_FMT(FLOOR_L, FMT_SD_D):
10345 mips32_op = OPC_FLOOR_L_D;
10346 goto do_unaryfp;
10347 case FLOAT_1BIT_FMT(FLOOR_W, FMT_SD_S):
10348 mips32_op = OPC_FLOOR_W_S;
10349 goto do_unaryfp;
10350 case FLOAT_1BIT_FMT(FLOOR_W, FMT_SD_D):
10351 mips32_op = OPC_FLOOR_W_D;
10352 goto do_unaryfp;
10353
10354 /* Ceiling */
10355 case FLOAT_1BIT_FMT(CEIL_L, FMT_SD_S):
10356 mips32_op = OPC_CEIL_L_S;
10357 goto do_unaryfp;
10358 case FLOAT_1BIT_FMT(CEIL_L, FMT_SD_D):
10359 mips32_op = OPC_CEIL_L_D;
10360 goto do_unaryfp;
10361 case FLOAT_1BIT_FMT(CEIL_W, FMT_SD_S):
10362 mips32_op = OPC_CEIL_W_S;
10363 goto do_unaryfp;
10364 case FLOAT_1BIT_FMT(CEIL_W, FMT_SD_D):
10365 mips32_op = OPC_CEIL_W_D;
10366 goto do_unaryfp;
10367
10368 /* Truncation */
10369 case FLOAT_1BIT_FMT(TRUNC_L, FMT_SD_S):
10370 mips32_op = OPC_TRUNC_L_S;
10371 goto do_unaryfp;
10372 case FLOAT_1BIT_FMT(TRUNC_L, FMT_SD_D):
10373 mips32_op = OPC_TRUNC_L_D;
10374 goto do_unaryfp;
10375 case FLOAT_1BIT_FMT(TRUNC_W, FMT_SD_S):
10376 mips32_op = OPC_TRUNC_W_S;
10377 goto do_unaryfp;
10378 case FLOAT_1BIT_FMT(TRUNC_W, FMT_SD_D):
10379 mips32_op = OPC_TRUNC_W_D;
10380 goto do_unaryfp;
10381
10382 /* Round */
10383 case FLOAT_1BIT_FMT(ROUND_L, FMT_SD_S):
10384 mips32_op = OPC_ROUND_L_S;
10385 goto do_unaryfp;
10386 case FLOAT_1BIT_FMT(ROUND_L, FMT_SD_D):
10387 mips32_op = OPC_ROUND_L_D;
10388 goto do_unaryfp;
10389 case FLOAT_1BIT_FMT(ROUND_W, FMT_SD_S):
10390 mips32_op = OPC_ROUND_W_S;
10391 goto do_unaryfp;
10392 case FLOAT_1BIT_FMT(ROUND_W, FMT_SD_D):
10393 mips32_op = OPC_ROUND_W_D;
10394 goto do_unaryfp;
10395
10396 /* Integer to floating-point conversion */
10397 case FLOAT_1BIT_FMT(CVT_L, FMT_SD_S):
10398 mips32_op = OPC_CVT_L_S;
10399 goto do_unaryfp;
10400 case FLOAT_1BIT_FMT(CVT_L, FMT_SD_D):
10401 mips32_op = OPC_CVT_L_D;
10402 goto do_unaryfp;
10403 case FLOAT_1BIT_FMT(CVT_W, FMT_SD_S):
10404 mips32_op = OPC_CVT_W_S;
10405 goto do_unaryfp;
10406 case FLOAT_1BIT_FMT(CVT_W, FMT_SD_D):
10407 mips32_op = OPC_CVT_W_D;
10408 goto do_unaryfp;
10409
10410 /* Paired-foo conversions */
10411 case FLOAT_1BIT_FMT(CVT_S_PL, 0):
10412 mips32_op = OPC_CVT_S_PL;
10413 goto do_unaryfp;
10414 case FLOAT_1BIT_FMT(CVT_S_PU, 0):
10415 mips32_op = OPC_CVT_S_PU;
10416 goto do_unaryfp;
10417 case FLOAT_1BIT_FMT(CVT_PW_PS, 0):
10418 mips32_op = OPC_CVT_PW_PS;
10419 goto do_unaryfp;
10420 case FLOAT_1BIT_FMT(CVT_PS_PW, 0):
10421 mips32_op = OPC_CVT_PS_PW;
10422 goto do_unaryfp;
10423
10424 /* Floating-point moves */
10425 case FLOAT_2BIT_FMT(MOV_FMT, FMT_SDPS_S):
10426 mips32_op = OPC_MOV_S;
10427 goto do_unaryfp;
10428 case FLOAT_2BIT_FMT(MOV_FMT, FMT_SDPS_D):
10429 mips32_op = OPC_MOV_D;
10430 goto do_unaryfp;
10431 case FLOAT_2BIT_FMT(MOV_FMT, FMT_SDPS_PS):
10432 mips32_op = OPC_MOV_PS;
10433 goto do_unaryfp;
10434
10435 /* Absolute value */
10436 case FLOAT_2BIT_FMT(ABS_FMT, FMT_SDPS_S):
10437 mips32_op = OPC_ABS_S;
10438 goto do_unaryfp;
10439 case FLOAT_2BIT_FMT(ABS_FMT, FMT_SDPS_D):
10440 mips32_op = OPC_ABS_D;
10441 goto do_unaryfp;
10442 case FLOAT_2BIT_FMT(ABS_FMT, FMT_SDPS_PS):
10443 mips32_op = OPC_ABS_PS;
10444 goto do_unaryfp;
10445
10446 /* Negation */
10447 case FLOAT_2BIT_FMT(NEG_FMT, FMT_SDPS_S):
10448 mips32_op = OPC_NEG_S;
10449 goto do_unaryfp;
10450 case FLOAT_2BIT_FMT(NEG_FMT, FMT_SDPS_D):
10451 mips32_op = OPC_NEG_D;
10452 goto do_unaryfp;
10453 case FLOAT_2BIT_FMT(NEG_FMT, FMT_SDPS_PS):
10454 mips32_op = OPC_NEG_PS;
10455 goto do_unaryfp;
10456
10457 /* Reciprocal square root step */
10458 case FLOAT_2BIT_FMT(RSQRT1_FMT, FMT_SDPS_S):
10459 mips32_op = OPC_RSQRT1_S;
10460 goto do_unaryfp;
10461 case FLOAT_2BIT_FMT(RSQRT1_FMT, FMT_SDPS_D):
10462 mips32_op = OPC_RSQRT1_D;
10463 goto do_unaryfp;
10464 case FLOAT_2BIT_FMT(RSQRT1_FMT, FMT_SDPS_PS):
10465 mips32_op = OPC_RSQRT1_PS;
10466 goto do_unaryfp;
10467
10468 /* Reciprocal step */
10469 case FLOAT_2BIT_FMT(RECIP1_FMT, FMT_SDPS_S):
10470 mips32_op = OPC_RECIP1_S;
10471 goto do_unaryfp;
10472 case FLOAT_2BIT_FMT(RECIP1_FMT, FMT_SDPS_D):
10473 mips32_op = OPC_RECIP1_S;
10474 goto do_unaryfp;
10475 case FLOAT_2BIT_FMT(RECIP1_FMT, FMT_SDPS_PS):
10476 mips32_op = OPC_RECIP1_PS;
10477 goto do_unaryfp;
10478
10479 /* Conversions from double */
10480 case FLOAT_2BIT_FMT(CVT_D, FMT_SWL_S):
10481 mips32_op = OPC_CVT_D_S;
10482 goto do_unaryfp;
10483 case FLOAT_2BIT_FMT(CVT_D, FMT_SWL_W):
10484 mips32_op = OPC_CVT_D_W;
10485 goto do_unaryfp;
10486 case FLOAT_2BIT_FMT(CVT_D, FMT_SWL_L):
10487 mips32_op = OPC_CVT_D_L;
10488 goto do_unaryfp;
10489
10490 /* Conversions from single */
10491 case FLOAT_2BIT_FMT(CVT_S, FMT_DWL_D):
10492 mips32_op = OPC_CVT_S_D;
10493 goto do_unaryfp;
10494 case FLOAT_2BIT_FMT(CVT_S, FMT_DWL_W):
10495 mips32_op = OPC_CVT_S_W;
10496 goto do_unaryfp;
10497 case FLOAT_2BIT_FMT(CVT_S, FMT_DWL_L):
10498 mips32_op = OPC_CVT_S_L;
10499 do_unaryfp:
10500 gen_farith(ctx, mips32_op, -1, rs, rt, 0);
10501 break;
10502
10503 /* Conditional moves on floating-point codes */
10504 case COND_FLOAT_MOV(MOVT, 0):
10505 case COND_FLOAT_MOV(MOVT, 1):
10506 case COND_FLOAT_MOV(MOVT, 2):
10507 case COND_FLOAT_MOV(MOVT, 3):
10508 case COND_FLOAT_MOV(MOVT, 4):
10509 case COND_FLOAT_MOV(MOVT, 5):
10510 case COND_FLOAT_MOV(MOVT, 6):
10511 case COND_FLOAT_MOV(MOVT, 7):
10512 gen_movci(ctx, rt, rs, (ctx->opcode >> 13) & 0x7, 1);
10513 break;
10514 case COND_FLOAT_MOV(MOVF, 0):
10515 case COND_FLOAT_MOV(MOVF, 1):
10516 case COND_FLOAT_MOV(MOVF, 2):
10517 case COND_FLOAT_MOV(MOVF, 3):
10518 case COND_FLOAT_MOV(MOVF, 4):
10519 case COND_FLOAT_MOV(MOVF, 5):
10520 case COND_FLOAT_MOV(MOVF, 6):
10521 case COND_FLOAT_MOV(MOVF, 7):
10522 gen_movci(ctx, rt, rs, (ctx->opcode >> 13) & 0x7, 0);
10523 break;
10524 default:
10525 MIPS_INVAL("pool32fxf");
10526 generate_exception(ctx, EXCP_RI);
10527 break;
10528 }
10529}
10530
10531static void decode_micromips32_opc (CPUState *env, DisasContext *ctx,
10532 uint16_t insn_hw1, int *is_branch)
10533{
10534 int32_t offset;
10535 uint16_t insn;
10536 int rt, rs, rd, rr;
10537 int16_t imm;
10538 uint32_t op, minor, mips32_op;
10539 uint32_t cond, fmt, cc;
10540
10541 insn = lduw_code(ctx->pc + 2);
10542 ctx->opcode = (ctx->opcode << 16) | insn;
10543
10544 rt = (ctx->opcode >> 21) & 0x1f;
10545 rs = (ctx->opcode >> 16) & 0x1f;
10546 rd = (ctx->opcode >> 11) & 0x1f;
10547 rr = (ctx->opcode >> 6) & 0x1f;
10548 imm = (int16_t) ctx->opcode;
10549
10550 op = (ctx->opcode >> 26) & 0x3f;
10551 switch (op) {
10552 case POOL32A:
10553 minor = ctx->opcode & 0x3f;
10554 switch (minor) {
10555 case 0x00:
10556 minor = (ctx->opcode >> 6) & 0xf;
10557 switch (minor) {
10558 case SLL32:
10559 mips32_op = OPC_SLL;
10560 goto do_shifti;
10561 case SRA:
10562 mips32_op = OPC_SRA;
10563 goto do_shifti;
10564 case SRL32:
10565 mips32_op = OPC_SRL;
10566 goto do_shifti;
10567 case ROTR:
10568 mips32_op = OPC_ROTR;
10569 do_shifti:
10570 gen_shift_imm(env, ctx, mips32_op, rt, rs, rd);
10571 break;
10572 default:
10573 goto pool32a_invalid;
10574 }
10575 break;
10576 case 0x10:
10577 minor = (ctx->opcode >> 6) & 0xf;
10578 switch (minor) {
10579 /* Arithmetic */
10580 case ADD:
10581 mips32_op = OPC_ADD;
10582 goto do_arith;
10583 case ADDU32:
10584 mips32_op = OPC_ADDU;
10585 goto do_arith;
10586 case SUB:
10587 mips32_op = OPC_SUB;
10588 goto do_arith;
10589 case SUBU32:
10590 mips32_op = OPC_SUBU;
10591 goto do_arith;
10592 case MUL:
10593 mips32_op = OPC_MUL;
10594 do_arith:
10595 gen_arith(env, ctx, mips32_op, rd, rs, rt);
10596 break;
10597 /* Shifts */
10598 case SLLV:
10599 mips32_op = OPC_SLLV;
10600 goto do_shift;
10601 case SRLV:
10602 mips32_op = OPC_SRLV;
10603 goto do_shift;
10604 case SRAV:
10605 mips32_op = OPC_SRAV;
10606 goto do_shift;
10607 case ROTRV:
10608 mips32_op = OPC_ROTRV;
10609 do_shift:
10610 gen_shift(env, ctx, mips32_op, rd, rs, rt);
10611 break;
10612 /* Logical operations */
10613 case AND:
10614 mips32_op = OPC_AND;
10615 goto do_logic;
10616 case OR32:
10617 mips32_op = OPC_OR;
10618 goto do_logic;
10619 case NOR:
10620 mips32_op = OPC_NOR;
10621 goto do_logic;
10622 case XOR32:
10623 mips32_op = OPC_XOR;
10624 do_logic:
10625 gen_logic(env, mips32_op, rd, rs, rt);
10626 break;
10627 /* Set less than */
10628 case SLT:
10629 mips32_op = OPC_SLT;
10630 goto do_slt;
10631 case SLTU:
10632 mips32_op = OPC_SLTU;
10633 do_slt:
10634 gen_slt(env, mips32_op, rd, rs, rt);
10635 break;
10636 default:
10637 goto pool32a_invalid;
10638 }
10639 break;
10640 case 0x18:
10641 minor = (ctx->opcode >> 6) & 0xf;
10642 switch (minor) {
10643 /* Conditional moves */
10644 case MOVN:
10645 mips32_op = OPC_MOVN;
10646 goto do_cmov;
10647 case MOVZ:
10648 mips32_op = OPC_MOVZ;
10649 do_cmov:
10650 gen_cond_move(env, mips32_op, rd, rs, rt);
10651 break;
10652 case LWXS:
10653 gen_ldxs(ctx, rs, rt, rd);
10654 break;
10655 default:
10656 goto pool32a_invalid;
10657 }
10658 break;
10659 case INS:
10660 gen_bitops(ctx, OPC_INS, rt, rs, rr, rd);
10661 return;
10662 case EXT:
10663 gen_bitops(ctx, OPC_EXT, rt, rs, rr, rd);
10664 return;
10665 case POOL32AXF:
10666 gen_pool32axf(env, ctx, rt, rs, is_branch);
10667 break;
10668 case 0x07:
10669 generate_exception(ctx, EXCP_BREAK);
10670 break;
10671 default:
10672 pool32a_invalid:
10673 MIPS_INVAL("pool32a");
10674 generate_exception(ctx, EXCP_RI);
10675 break;
10676 }
10677 break;
10678 case POOL32B:
10679 minor = (ctx->opcode >> 12) & 0xf;
10680 switch (minor) {
10681 case CACHE:
10682 /* Treat as no-op. */
10683 break;
10684 case LWC2:
10685 case SWC2:
10686 /* COP2: Not implemented. */
10687 generate_exception_err(ctx, EXCP_CpU, 2);
10688 break;
10689 case LWP:
10690 case SWP:
10691#ifdef TARGET_MIPS64
10692 case LDP:
10693 case SDP:
10694#endif
10695 gen_ldst_pair(ctx, minor, rt, rs, SIMM(ctx->opcode, 0, 12));
10696 break;
10697 case LWM32:
10698 case SWM32:
10699#ifdef TARGET_MIPS64
10700 case LDM:
10701 case SDM:
10702#endif
10703 gen_ldst_multiple(ctx, minor, rt, rs, SIMM(ctx->opcode, 0, 12));
10704 break;
10705 default:
10706 MIPS_INVAL("pool32b");
10707 generate_exception(ctx, EXCP_RI);
10708 break;
10709 }
10710 break;
10711 case POOL32F:
10712 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
10713 minor = ctx->opcode & 0x3f;
10714 check_cp1_enabled(ctx);
10715 switch (minor) {
10716 case ALNV_PS:
10717 mips32_op = OPC_ALNV_PS;
10718 goto do_madd;
10719 case MADD_S:
10720 mips32_op = OPC_MADD_S;
10721 goto do_madd;
10722 case MADD_D:
10723 mips32_op = OPC_MADD_D;
10724 goto do_madd;
10725 case MADD_PS:
10726 mips32_op = OPC_MADD_PS;
10727 goto do_madd;
10728 case MSUB_S:
10729 mips32_op = OPC_MSUB_S;
10730 goto do_madd;
10731 case MSUB_D:
10732 mips32_op = OPC_MSUB_D;
10733 goto do_madd;
10734 case MSUB_PS:
10735 mips32_op = OPC_MSUB_PS;
10736 goto do_madd;
10737 case NMADD_S:
10738 mips32_op = OPC_NMADD_S;
10739 goto do_madd;
10740 case NMADD_D:
10741 mips32_op = OPC_NMADD_D;
10742 goto do_madd;
10743 case NMADD_PS:
10744 mips32_op = OPC_NMADD_PS;
10745 goto do_madd;
10746 case NMSUB_S:
10747 mips32_op = OPC_NMSUB_S;
10748 goto do_madd;
10749 case NMSUB_D:
10750 mips32_op = OPC_NMSUB_D;
10751 goto do_madd;
10752 case NMSUB_PS:
10753 mips32_op = OPC_NMSUB_PS;
10754 do_madd:
10755 gen_flt3_arith(ctx, mips32_op, rd, rr, rs, rt);
10756 break;
10757 case CABS_COND_FMT:
10758 cond = (ctx->opcode >> 6) & 0xf;
10759 cc = (ctx->opcode >> 13) & 0x7;
10760 fmt = (ctx->opcode >> 10) & 0x3;
10761 switch (fmt) {
10762 case 0x0:
10763 gen_cmpabs_s(ctx, cond, rt, rs, cc);
10764 break;
10765 case 0x1:
10766 gen_cmpabs_d(ctx, cond, rt, rs, cc);
10767 break;
10768 case 0x2:
10769 gen_cmpabs_ps(ctx, cond, rt, rs, cc);
10770 break;
10771 default:
10772 goto pool32f_invalid;
10773 }
10774 break;
10775 case C_COND_FMT:
10776 cond = (ctx->opcode >> 6) & 0xf;
10777 cc = (ctx->opcode >> 13) & 0x7;
10778 fmt = (ctx->opcode >> 10) & 0x3;
10779 switch (fmt) {
10780 case 0x0:
10781 gen_cmp_s(ctx, cond, rt, rs, cc);
10782 break;
10783 case 0x1:
10784 gen_cmp_d(ctx, cond, rt, rs, cc);
10785 break;
10786 case 0x2:
10787 gen_cmp_ps(ctx, cond, rt, rs, cc);
10788 break;
10789 default:
10790 goto pool32f_invalid;
10791 }
10792 break;
10793 case POOL32FXF:
10794 gen_pool32fxf(env, ctx, rt, rs);
10795 break;
10796 case 0x00:
10797 /* PLL foo */
10798 switch ((ctx->opcode >> 6) & 0x7) {
10799 case PLL_PS:
10800 mips32_op = OPC_PLL_PS;
10801 goto do_ps;
10802 case PLU_PS:
10803 mips32_op = OPC_PLU_PS;
10804 goto do_ps;
10805 case PUL_PS:
10806 mips32_op = OPC_PUL_PS;
10807 goto do_ps;
10808 case PUU_PS:
10809 mips32_op = OPC_PUU_PS;
10810 goto do_ps;
10811 case CVT_PS_S:
10812 mips32_op = OPC_CVT_PS_S;
10813 do_ps:
10814 gen_farith(ctx, mips32_op, rt, rs, rd, 0);
10815 break;
10816 default:
10817 goto pool32f_invalid;
10818 }
10819 break;
10820 case 0x08:
10821 /* [LS][WDU]XC1 */
10822 switch ((ctx->opcode >> 6) & 0x7) {
10823 case LWXC1:
10824 mips32_op = OPC_LWXC1;
10825 goto do_ldst_cp1;
10826 case SWXC1:
10827 mips32_op = OPC_SWXC1;
10828 goto do_ldst_cp1;
10829 case LDXC1:
10830 mips32_op = OPC_LDXC1;
10831 goto do_ldst_cp1;
10832 case SDXC1:
10833 mips32_op = OPC_SDXC1;
10834 goto do_ldst_cp1;
10835 case LUXC1:
10836 mips32_op = OPC_LUXC1;
10837 goto do_ldst_cp1;
10838 case SUXC1:
10839 mips32_op = OPC_SUXC1;
10840 do_ldst_cp1:
10841 gen_flt3_ldst(ctx, mips32_op, rd, rd, rt, rs);
10842 break;
10843 default:
10844 goto pool32f_invalid;
10845 }
10846 break;
10847 case 0x18:
10848 /* 3D insns */
10849 fmt = (ctx->opcode >> 9) & 0x3;
10850 switch ((ctx->opcode >> 6) & 0x7) {
10851 case RSQRT2_FMT:
10852 switch (fmt) {
10853 case FMT_SDPS_S:
10854 mips32_op = OPC_RSQRT2_S;
10855 goto do_3d;
10856 case FMT_SDPS_D:
10857 mips32_op = OPC_RSQRT2_D;
10858 goto do_3d;
10859 case FMT_SDPS_PS:
10860 mips32_op = OPC_RSQRT2_PS;
10861 goto do_3d;
10862 default:
10863 goto pool32f_invalid;
10864 }
10865 break;
10866 case RECIP2_FMT:
10867 switch (fmt) {
10868 case FMT_SDPS_S:
10869 mips32_op = OPC_RECIP2_S;
10870 goto do_3d;
10871 case FMT_SDPS_D:
10872 mips32_op = OPC_RECIP2_D;
10873 goto do_3d;
10874 case FMT_SDPS_PS:
10875 mips32_op = OPC_RECIP2_PS;
10876 goto do_3d;
10877 default:
10878 goto pool32f_invalid;
10879 }
10880 break;
10881 case ADDR_PS:
10882 mips32_op = OPC_ADDR_PS;
10883 goto do_3d;
10884 case MULR_PS:
10885 mips32_op = OPC_MULR_PS;
10886 do_3d:
10887 gen_farith(ctx, mips32_op, rt, rs, rd, 0);
10888 break;
10889 default:
10890 goto pool32f_invalid;
10891 }
10892 break;
10893 case 0x20:
10894 /* MOV[FT].fmt and PREFX */
10895 cc = (ctx->opcode >> 13) & 0x7;
10896 fmt = (ctx->opcode >> 9) & 0x3;
10897 switch ((ctx->opcode >> 6) & 0x7) {
10898 case MOVF_FMT:
10899 switch (fmt) {
10900 case FMT_SDPS_S:
10901 gen_movcf_s(rs, rt, cc, 0);
10902 break;
10903 case FMT_SDPS_D:
10904 gen_movcf_d(ctx, rs, rt, cc, 0);
10905 break;
10906 case FMT_SDPS_PS:
10907 gen_movcf_ps(rs, rt, cc, 0);
10908 break;
10909 default:
10910 goto pool32f_invalid;
10911 }
10912 break;
10913 case MOVT_FMT:
10914 switch (fmt) {
10915 case FMT_SDPS_S:
10916 gen_movcf_s(rs, rt, cc, 1);
10917 break;
10918 case FMT_SDPS_D:
10919 gen_movcf_d(ctx, rs, rt, cc, 1);
10920 break;
10921 case FMT_SDPS_PS:
10922 gen_movcf_ps(rs, rt, cc, 1);
10923 break;
10924 default:
10925 goto pool32f_invalid;
10926 }
10927 break;
10928 case PREFX:
10929 break;
10930 default:
10931 goto pool32f_invalid;
10932 }
10933 break;
10934#define FINSN_3ARG_SDPS(prfx) \
10935 switch ((ctx->opcode >> 8) & 0x3) { \
10936 case FMT_SDPS_S: \
10937 mips32_op = OPC_##prfx##_S; \
10938 goto do_fpop; \
10939 case FMT_SDPS_D: \
10940 mips32_op = OPC_##prfx##_D; \
10941 goto do_fpop; \
10942 case FMT_SDPS_PS: \
10943 mips32_op = OPC_##prfx##_PS; \
10944 goto do_fpop; \
10945 default: \
10946 goto pool32f_invalid; \
10947 }
10948 case 0x30:
10949 /* regular FP ops */
10950 switch ((ctx->opcode >> 6) & 0x3) {
10951 case ADD_FMT:
10952 FINSN_3ARG_SDPS(ADD);
10953 break;
10954 case SUB_FMT:
10955 FINSN_3ARG_SDPS(SUB);
10956 break;
10957 case MUL_FMT:
10958 FINSN_3ARG_SDPS(MUL);
10959 break;
10960 case DIV_FMT:
10961 fmt = (ctx->opcode >> 8) & 0x3;
10962 if (fmt == 1) {
10963 mips32_op = OPC_DIV_D;
10964 } else if (fmt == 0) {
10965 mips32_op = OPC_DIV_S;
10966 } else {
10967 goto pool32f_invalid;
10968 }
10969 goto do_fpop;
10970 default:
10971 goto pool32f_invalid;
10972 }
10973 break;
10974 case 0x38:
10975 /* cmovs */
10976 switch ((ctx->opcode >> 6) & 0x3) {
10977 case MOVN_FMT:
10978 FINSN_3ARG_SDPS(MOVN);
10979 break;
10980 case MOVZ_FMT:
10981 FINSN_3ARG_SDPS(MOVZ);
10982 break;
10983 default:
10984 goto pool32f_invalid;
10985 }
10986 break;
10987 do_fpop:
10988 gen_farith(ctx, mips32_op, rt, rs, rd, 0);
10989 break;
10990 default:
10991 pool32f_invalid:
10992 MIPS_INVAL("pool32f");
10993 generate_exception(ctx, EXCP_RI);
10994 break;
10995 }
10996 } else {
10997 generate_exception_err(ctx, EXCP_CpU, 1);
10998 }
10999 break;
11000 case POOL32I:
11001 minor = (ctx->opcode >> 21) & 0x1f;
11002 switch (minor) {
11003 case BLTZ:
11004 mips32_op = OPC_BLTZ;
11005 goto do_branch;
11006 case BLTZAL:
11007 mips32_op = OPC_BLTZAL;
11008 goto do_branch;
11009 case BLTZALS:
11010 mips32_op = OPC_BLTZALS;
11011 goto do_branch;
11012 case BGEZ:
11013 mips32_op = OPC_BGEZ;
11014 goto do_branch;
11015 case BGEZAL:
11016 mips32_op = OPC_BGEZAL;
11017 goto do_branch;
11018 case BGEZALS:
11019 mips32_op = OPC_BGEZALS;
11020 goto do_branch;
11021 case BLEZ:
11022 mips32_op = OPC_BLEZ;
11023 goto do_branch;
11024 case BGTZ:
11025 mips32_op = OPC_BGTZ;
11026 do_branch:
11027 gen_compute_branch(ctx, mips32_op, 4, rs, -1, imm << 1);
11028 *is_branch = 1;
11029 break;
11030
11031 /* Traps */
11032 case TLTI:
11033 mips32_op = OPC_TLTI;
11034 goto do_trapi;
11035 case TGEI:
11036 mips32_op = OPC_TGEI;
11037 goto do_trapi;
11038 case TLTIU:
11039 mips32_op = OPC_TLTIU;
11040 goto do_trapi;
11041 case TGEIU:
11042 mips32_op = OPC_TGEIU;
11043 goto do_trapi;
11044 case TNEI:
11045 mips32_op = OPC_TNEI;
11046 goto do_trapi;
11047 case TEQI:
11048 mips32_op = OPC_TEQI;
11049 do_trapi:
11050 gen_trap(ctx, mips32_op, rs, -1, imm);
11051 break;
11052
11053 case BNEZC:
11054 case BEQZC:
11055 gen_compute_branch(ctx, minor == BNEZC ? OPC_BNE : OPC_BEQ,
11056 4, rs, 0, imm << 1);
11057 /* Compact branches don't have a delay slot, so just let
11058 the normal delay slot handling take us to the branch
11059 target. */
11060 break;
11061 case LUI:
11062 gen_logic_imm(env, OPC_LUI, rs, -1, imm);
11063 break;
11064 case SYNCI:
11065 break;
11066 case BC2F:
11067 case BC2T:
11068 /* COP2: Not implemented. */
11069 generate_exception_err(ctx, EXCP_CpU, 2);
11070 break;
11071 case BC1F:
11072 mips32_op = (ctx->opcode & (1 << 16)) ? OPC_BC1FANY2 : OPC_BC1F;
11073 goto do_cp1branch;
11074 case BC1T:
11075 mips32_op = (ctx->opcode & (1 << 16)) ? OPC_BC1TANY2 : OPC_BC1T;
11076 goto do_cp1branch;
11077 case BC1ANY4F:
11078 mips32_op = OPC_BC1FANY4;
11079 goto do_cp1mips3d;
11080 case BC1ANY4T:
11081 mips32_op = OPC_BC1TANY4;
11082 do_cp1mips3d:
11083 check_cop1x(ctx);
11084 check_insn(env, ctx, ASE_MIPS3D);
11085 /* Fall through */
11086 do_cp1branch:
11087 gen_compute_branch1(env, ctx, mips32_op,
11088 (ctx->opcode >> 18) & 0x7, imm << 1);
11089 *is_branch = 1;
11090 break;
11091 case BPOSGE64:
11092 case BPOSGE32:
11093 /* MIPS DSP: not implemented */
11094 /* Fall through */
11095 default:
11096 MIPS_INVAL("pool32i");
11097 generate_exception(ctx, EXCP_RI);
11098 break;
11099 }
11100 break;
11101 case POOL32C:
11102 minor = (ctx->opcode >> 12) & 0xf;
11103 switch (minor) {
11104 case LWL:
11105 mips32_op = OPC_LWL;
5c13fdfd 11106 goto do_ld_lr;
3c824109
NF
11107 case SWL:
11108 mips32_op = OPC_SWL;
5c13fdfd 11109 goto do_st_lr;
3c824109
NF
11110 case LWR:
11111 mips32_op = OPC_LWR;
5c13fdfd 11112 goto do_ld_lr;
3c824109
NF
11113 case SWR:
11114 mips32_op = OPC_SWR;
5c13fdfd 11115 goto do_st_lr;
3c824109
NF
11116#if defined(TARGET_MIPS64)
11117 case LDL:
11118 mips32_op = OPC_LDL;
5c13fdfd 11119 goto do_ld_lr;
3c824109
NF
11120 case SDL:
11121 mips32_op = OPC_SDL;
5c13fdfd 11122 goto do_st_lr;
3c824109
NF
11123 case LDR:
11124 mips32_op = OPC_LDR;
5c13fdfd 11125 goto do_ld_lr;
3c824109
NF
11126 case SDR:
11127 mips32_op = OPC_SDR;
5c13fdfd 11128 goto do_st_lr;
3c824109
NF
11129 case LWU:
11130 mips32_op = OPC_LWU;
5c13fdfd 11131 goto do_ld_lr;
3c824109
NF
11132 case LLD:
11133 mips32_op = OPC_LLD;
5c13fdfd 11134 goto do_ld_lr;
3c824109
NF
11135#endif
11136 case LL:
11137 mips32_op = OPC_LL;
5c13fdfd
AJ
11138 goto do_ld_lr;
11139 do_ld_lr:
afa88c3a 11140 gen_ld(env, ctx, mips32_op, rt, rs, SIMM(ctx->opcode, 0, 12));
5c13fdfd
AJ
11141 break;
11142 do_st_lr:
11143 gen_st(ctx, mips32_op, rt, rs, SIMM(ctx->opcode, 0, 12));
3c824109
NF
11144 break;
11145 case SC:
11146 gen_st_cond(ctx, OPC_SC, rt, rs, SIMM(ctx->opcode, 0, 12));
11147 break;
11148#if defined(TARGET_MIPS64)
11149 case SCD:
11150 gen_st_cond(ctx, OPC_SCD, rt, rs, SIMM(ctx->opcode, 0, 12));
11151 break;
11152#endif
11153 case PREF:
11154 /* Treat as no-op */
11155 break;
11156 default:
11157 MIPS_INVAL("pool32c");
11158 generate_exception(ctx, EXCP_RI);
11159 break;
11160 }
11161 break;
11162 case ADDI32:
11163 mips32_op = OPC_ADDI;
11164 goto do_addi;
11165 case ADDIU32:
11166 mips32_op = OPC_ADDIU;
11167 do_addi:
11168 gen_arith_imm(env, ctx, mips32_op, rt, rs, imm);
11169 break;
11170
11171 /* Logical operations */
11172 case ORI32:
11173 mips32_op = OPC_ORI;
11174 goto do_logici;
11175 case XORI32:
11176 mips32_op = OPC_XORI;
11177 goto do_logici;
11178 case ANDI32:
11179 mips32_op = OPC_ANDI;
11180 do_logici:
11181 gen_logic_imm(env, mips32_op, rt, rs, imm);
11182 break;
11183
11184 /* Set less than immediate */
11185 case SLTI32:
11186 mips32_op = OPC_SLTI;
11187 goto do_slti;
11188 case SLTIU32:
11189 mips32_op = OPC_SLTIU;
11190 do_slti:
11191 gen_slt_imm(env, mips32_op, rt, rs, imm);
11192 break;
11193 case JALX32:
11194 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2;
11195 gen_compute_branch(ctx, OPC_JALX, 4, rt, rs, offset);
11196 *is_branch = 1;
11197 break;
11198 case JALS32:
11199 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 1;
11200 gen_compute_branch(ctx, OPC_JALS, 4, rt, rs, offset);
11201 *is_branch = 1;
11202 break;
11203 case BEQ32:
11204 gen_compute_branch(ctx, OPC_BEQ, 4, rt, rs, imm << 1);
11205 *is_branch = 1;
11206 break;
11207 case BNE32:
11208 gen_compute_branch(ctx, OPC_BNE, 4, rt, rs, imm << 1);
11209 *is_branch = 1;
11210 break;
11211 case J32:
11212 gen_compute_branch(ctx, OPC_J, 4, rt, rs,
11213 (int32_t)(ctx->opcode & 0x3FFFFFF) << 1);
11214 *is_branch = 1;
11215 break;
11216 case JAL32:
11217 gen_compute_branch(ctx, OPC_JAL, 4, rt, rs,
11218 (int32_t)(ctx->opcode & 0x3FFFFFF) << 1);
11219 *is_branch = 1;
11220 break;
11221 /* Floating point (COP1) */
11222 case LWC132:
11223 mips32_op = OPC_LWC1;
11224 goto do_cop1;
11225 case LDC132:
11226 mips32_op = OPC_LDC1;
11227 goto do_cop1;
11228 case SWC132:
11229 mips32_op = OPC_SWC1;
11230 goto do_cop1;
11231 case SDC132:
11232 mips32_op = OPC_SDC1;
11233 do_cop1:
11234 gen_cop1_ldst(env, ctx, mips32_op, rt, rs, imm);
11235 break;
11236 case ADDIUPC:
11237 {
11238 int reg = mmreg(ZIMM(ctx->opcode, 23, 3));
11239 int offset = SIMM(ctx->opcode, 0, 23) << 2;
11240
11241 gen_addiupc(ctx, reg, offset, 0, 0);
11242 }
11243 break;
11244 /* Loads and stores */
11245 case LB32:
11246 mips32_op = OPC_LB;
5c13fdfd 11247 goto do_ld;
3c824109
NF
11248 case LBU32:
11249 mips32_op = OPC_LBU;
5c13fdfd 11250 goto do_ld;
3c824109
NF
11251 case LH32:
11252 mips32_op = OPC_LH;
5c13fdfd 11253 goto do_ld;
3c824109
NF
11254 case LHU32:
11255 mips32_op = OPC_LHU;
5c13fdfd 11256 goto do_ld;
3c824109
NF
11257 case LW32:
11258 mips32_op = OPC_LW;
5c13fdfd 11259 goto do_ld;
3c824109
NF
11260#ifdef TARGET_MIPS64
11261 case LD32:
11262 mips32_op = OPC_LD;
5c13fdfd 11263 goto do_ld;
3c824109
NF
11264 case SD32:
11265 mips32_op = OPC_SD;
5c13fdfd 11266 goto do_st;
3c824109
NF
11267#endif
11268 case SB32:
11269 mips32_op = OPC_SB;
5c13fdfd 11270 goto do_st;
3c824109
NF
11271 case SH32:
11272 mips32_op = OPC_SH;
5c13fdfd 11273 goto do_st;
3c824109
NF
11274 case SW32:
11275 mips32_op = OPC_SW;
5c13fdfd
AJ
11276 goto do_st;
11277 do_ld:
afa88c3a 11278 gen_ld(env, ctx, mips32_op, rt, rs, imm);
5c13fdfd
AJ
11279 break;
11280 do_st:
11281 gen_st(ctx, mips32_op, rt, rs, imm);
3c824109
NF
11282 break;
11283 default:
11284 generate_exception(ctx, EXCP_RI);
11285 break;
11286 }
11287}
11288
11289static int decode_micromips_opc (CPUState *env, DisasContext *ctx, int *is_branch)
11290{
11291 uint32_t op;
11292
11293 /* make sure instructions are on a halfword boundary */
11294 if (ctx->pc & 0x1) {
11295 env->CP0_BadVAddr = ctx->pc;
11296 generate_exception(ctx, EXCP_AdEL);
11297 ctx->bstate = BS_STOP;
11298 return 2;
11299 }
11300
11301 op = (ctx->opcode >> 10) & 0x3f;
11302 /* Enforce properly-sized instructions in a delay slot */
11303 if (ctx->hflags & MIPS_HFLAG_BMASK) {
11304 int bits = ctx->hflags & MIPS_HFLAG_BMASK_EXT;
11305
11306 switch (op) {
11307 case POOL32A:
11308 case POOL32B:
11309 case POOL32I:
11310 case POOL32C:
11311 case ADDI32:
11312 case ADDIU32:
11313 case ORI32:
11314 case XORI32:
11315 case SLTI32:
11316 case SLTIU32:
11317 case ANDI32:
11318 case JALX32:
11319 case LBU32:
11320 case LHU32:
11321 case POOL32F:
11322 case JALS32:
11323 case BEQ32:
11324 case BNE32:
11325 case J32:
11326 case JAL32:
11327 case SB32:
11328 case SH32:
11329 case POOL32S:
11330 case ADDIUPC:
11331 case SWC132:
11332 case SDC132:
11333 case SD32:
11334 case SW32:
11335 case LB32:
11336 case LH32:
11337 case DADDIU32:
11338 case POOL48A: /* ??? */
11339 case LWC132:
11340 case LDC132:
11341 case LD32:
11342 case LW32:
11343 if (bits & MIPS_HFLAG_BDS16) {
11344 generate_exception(ctx, EXCP_RI);
11345 /* Just stop translation; the user is confused. */
11346 ctx->bstate = BS_STOP;
11347 return 2;
11348 }
11349 break;
11350 case POOL16A:
11351 case POOL16B:
11352 case POOL16C:
11353 case LWGP16:
11354 case POOL16F:
11355 case LBU16:
11356 case LHU16:
11357 case LWSP16:
11358 case LW16:
11359 case SB16:
11360 case SH16:
11361 case SWSP16:
11362 case SW16:
11363 case MOVE16:
11364 case ANDI16:
11365 case POOL16D:
11366 case POOL16E:
11367 case BEQZ16:
11368 case BNEZ16:
11369 case B16:
11370 case LI16:
11371 if (bits & MIPS_HFLAG_BDS32) {
11372 generate_exception(ctx, EXCP_RI);
11373 /* Just stop translation; the user is confused. */
11374 ctx->bstate = BS_STOP;
11375 return 2;
11376 }
11377 break;
11378 default:
11379 break;
11380 }
11381 }
11382 switch (op) {
11383 case POOL16A:
11384 {
11385 int rd = mmreg(uMIPS_RD(ctx->opcode));
11386 int rs1 = mmreg(uMIPS_RS1(ctx->opcode));
11387 int rs2 = mmreg(uMIPS_RS2(ctx->opcode));
11388 uint32_t opc = 0;
11389
11390 switch (ctx->opcode & 0x1) {
11391 case ADDU16:
11392 opc = OPC_ADDU;
11393 break;
11394 case SUBU16:
11395 opc = OPC_SUBU;
11396 break;
11397 }
11398
11399 gen_arith(env, ctx, opc, rd, rs1, rs2);
11400 }
11401 break;
11402 case POOL16B:
11403 {
11404 int rd = mmreg(uMIPS_RD(ctx->opcode));
11405 int rs = mmreg(uMIPS_RS(ctx->opcode));
11406 int amount = (ctx->opcode >> 1) & 0x7;
11407 uint32_t opc = 0;
11408 amount = amount == 0 ? 8 : amount;
11409
11410 switch (ctx->opcode & 0x1) {
11411 case SLL16:
11412 opc = OPC_SLL;
11413 break;
11414 case SRL16:
11415 opc = OPC_SRL;
11416 break;
11417 }
11418
11419 gen_shift_imm(env, ctx, opc, rd, rs, amount);
11420 }
11421 break;
11422 case POOL16C:
11423 gen_pool16c_insn(env, ctx, is_branch);
11424 break;
11425 case LWGP16:
11426 {
11427 int rd = mmreg(uMIPS_RD(ctx->opcode));
11428 int rb = 28; /* GP */
11429 int16_t offset = SIMM(ctx->opcode, 0, 7) << 2;
11430
afa88c3a 11431 gen_ld(env, ctx, OPC_LW, rd, rb, offset);
3c824109
NF
11432 }
11433 break;
11434 case POOL16F:
11435 if (ctx->opcode & 1) {
11436 generate_exception(ctx, EXCP_RI);
11437 } else {
11438 /* MOVEP */
11439 int enc_dest = uMIPS_RD(ctx->opcode);
11440 int enc_rt = uMIPS_RS2(ctx->opcode);
11441 int enc_rs = uMIPS_RS1(ctx->opcode);
11442 int rd, rs, re, rt;
11443 static const int rd_enc[] = { 5, 5, 6, 4, 4, 4, 4, 4 };
11444 static const int re_enc[] = { 6, 7, 7, 21, 22, 5, 6, 7 };
11445 static const int rs_rt_enc[] = { 0, 17, 2, 3, 16, 18, 19, 20 };
11446
11447 rd = rd_enc[enc_dest];
11448 re = re_enc[enc_dest];
11449 rs = rs_rt_enc[enc_rs];
11450 rt = rs_rt_enc[enc_rt];
11451
11452 gen_arith_imm(env, ctx, OPC_ADDIU, rd, rs, 0);
11453 gen_arith_imm(env, ctx, OPC_ADDIU, re, rt, 0);
11454 }
11455 break;
11456 case LBU16:
11457 {
11458 int rd = mmreg(uMIPS_RD(ctx->opcode));
11459 int rb = mmreg(uMIPS_RS(ctx->opcode));
11460 int16_t offset = ZIMM(ctx->opcode, 0, 4);
11461 offset = (offset == 0xf ? -1 : offset);
11462
afa88c3a 11463 gen_ld(env, ctx, OPC_LBU, rd, rb, offset);
3c824109
NF
11464 }
11465 break;
11466 case LHU16:
11467 {
11468 int rd = mmreg(uMIPS_RD(ctx->opcode));
11469 int rb = mmreg(uMIPS_RS(ctx->opcode));
11470 int16_t offset = ZIMM(ctx->opcode, 0, 4) << 1;
11471
afa88c3a 11472 gen_ld(env, ctx, OPC_LHU, rd, rb, offset);
3c824109
NF
11473 }
11474 break;
11475 case LWSP16:
11476 {
11477 int rd = (ctx->opcode >> 5) & 0x1f;
11478 int rb = 29; /* SP */
11479 int16_t offset = ZIMM(ctx->opcode, 0, 5) << 2;
11480
afa88c3a 11481 gen_ld(env, ctx, OPC_LW, rd, rb, offset);
3c824109
NF
11482 }
11483 break;
11484 case LW16:
11485 {
11486 int rd = mmreg(uMIPS_RD(ctx->opcode));
11487 int rb = mmreg(uMIPS_RS(ctx->opcode));
11488 int16_t offset = ZIMM(ctx->opcode, 0, 4) << 2;
11489
afa88c3a 11490 gen_ld(env, ctx, OPC_LW, rd, rb, offset);
3c824109
NF
11491 }
11492 break;
11493 case SB16:
11494 {
11495 int rd = mmreg2(uMIPS_RD(ctx->opcode));
11496 int rb = mmreg(uMIPS_RS(ctx->opcode));
11497 int16_t offset = ZIMM(ctx->opcode, 0, 4);
11498
5c13fdfd 11499 gen_st(ctx, OPC_SB, rd, rb, offset);
3c824109
NF
11500 }
11501 break;
11502 case SH16:
11503 {
11504 int rd = mmreg2(uMIPS_RD(ctx->opcode));
11505 int rb = mmreg(uMIPS_RS(ctx->opcode));
11506 int16_t offset = ZIMM(ctx->opcode, 0, 4) << 1;
11507
5c13fdfd 11508 gen_st(ctx, OPC_SH, rd, rb, offset);
3c824109
NF
11509 }
11510 break;
11511 case SWSP16:
11512 {
11513 int rd = (ctx->opcode >> 5) & 0x1f;
11514 int rb = 29; /* SP */
11515 int16_t offset = ZIMM(ctx->opcode, 0, 5) << 2;
11516
5c13fdfd 11517 gen_st(ctx, OPC_SW, rd, rb, offset);
3c824109
NF
11518 }
11519 break;
11520 case SW16:
11521 {
11522 int rd = mmreg2(uMIPS_RD(ctx->opcode));
11523 int rb = mmreg(uMIPS_RS(ctx->opcode));
11524 int16_t offset = ZIMM(ctx->opcode, 0, 4) << 2;
11525
5c13fdfd 11526 gen_st(ctx, OPC_SW, rd, rb, offset);
3c824109
NF
11527 }
11528 break;
11529 case MOVE16:
11530 {
11531 int rd = uMIPS_RD5(ctx->opcode);
11532 int rs = uMIPS_RS5(ctx->opcode);
11533
11534 gen_arith_imm(env, ctx, OPC_ADDIU, rd, rs, 0);
11535 }
11536 break;
11537 case ANDI16:
11538 gen_andi16(env, ctx);
11539 break;
11540 case POOL16D:
11541 switch (ctx->opcode & 0x1) {
11542 case ADDIUS5:
11543 gen_addius5(env, ctx);
11544 break;
11545 case ADDIUSP:
11546 gen_addiusp(env, ctx);
11547 break;
11548 }
11549 break;
11550 case POOL16E:
11551 switch (ctx->opcode & 0x1) {
11552 case ADDIUR2:
11553 gen_addiur2(env, ctx);
11554 break;
11555 case ADDIUR1SP:
11556 gen_addiur1sp(env, ctx);
11557 break;
11558 }
11559 break;
11560 case B16:
11561 gen_compute_branch(ctx, OPC_BEQ, 2, 0, 0,
11562 SIMM(ctx->opcode, 0, 10) << 1);
11563 *is_branch = 1;
11564 break;
11565 case BNEZ16:
11566 case BEQZ16:
11567 gen_compute_branch(ctx, op == BNEZ16 ? OPC_BNE : OPC_BEQ, 2,
11568 mmreg(uMIPS_RD(ctx->opcode)),
11569 0, SIMM(ctx->opcode, 0, 7) << 1);
11570 *is_branch = 1;
11571 break;
11572 case LI16:
11573 {
11574 int reg = mmreg(uMIPS_RD(ctx->opcode));
11575 int imm = ZIMM(ctx->opcode, 0, 7);
11576
11577 imm = (imm == 0x7f ? -1 : imm);
11578 tcg_gen_movi_tl(cpu_gpr[reg], imm);
11579 }
11580 break;
11581 case RES_20:
11582 case RES_28:
11583 case RES_29:
11584 case RES_30:
11585 case RES_31:
11586 case RES_38:
11587 case RES_39:
11588 generate_exception(ctx, EXCP_RI);
11589 break;
11590 default:
11591 decode_micromips32_opc (env, ctx, op, is_branch);
11592 return 4;
11593 }
11594
11595 return 2;
11596}
11597
11598/* SmartMIPS extension to MIPS32 */
11599
11600#if defined(TARGET_MIPS64)
11601
11602/* MDMX extension to MIPS64 */
11603
11604#endif
11605
11606static void decode_opc (CPUState *env, DisasContext *ctx, int *is_branch)
11607{
11608 int32_t offset;
11609 int rs, rt, rd, sa;
11610 uint32_t op, op1, op2;
11611 int16_t imm;
11612
11613 /* make sure instructions are on a word boundary */
11614 if (ctx->pc & 0x3) {
11615 env->CP0_BadVAddr = ctx->pc;
11616 generate_exception(ctx, EXCP_AdEL);
11617 return;
11618 }
11619
11620 /* Handle blikely not taken case */
11621 if ((ctx->hflags & MIPS_HFLAG_BMASK_BASE) == MIPS_HFLAG_BL) {
11622 int l1 = gen_new_label();
11623
11624 MIPS_DEBUG("blikely condition (" TARGET_FMT_lx ")", ctx->pc + 4);
11625 tcg_gen_brcondi_tl(TCG_COND_NE, bcond, 0, l1);
11626 tcg_gen_movi_i32(hflags, ctx->hflags & ~MIPS_HFLAG_BMASK);
11627 gen_goto_tb(ctx, 1, ctx->pc + 4);
11628 gen_set_label(l1);
11629 }
11630
11631 if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP)))
11632 tcg_gen_debug_insn_start(ctx->pc);
11633
11634 op = MASK_OP_MAJOR(ctx->opcode);
11635 rs = (ctx->opcode >> 21) & 0x1f;
11636 rt = (ctx->opcode >> 16) & 0x1f;
11637 rd = (ctx->opcode >> 11) & 0x1f;
11638 sa = (ctx->opcode >> 6) & 0x1f;
11639 imm = (int16_t)ctx->opcode;
11640 switch (op) {
7a387fff
TS
11641 case OPC_SPECIAL:
11642 op1 = MASK_SPECIAL(ctx->opcode);
6af0bf9c 11643 switch (op1) {
324d9e32
AJ
11644 case OPC_SLL: /* Shift with immediate */
11645 case OPC_SRA:
324d9e32 11646 gen_shift_imm(env, ctx, op1, rd, rt, sa);
7a387fff 11647 break;
ea63e2c3
NF
11648 case OPC_SRL:
11649 switch ((ctx->opcode >> 21) & 0x1f) {
11650 case 1:
11651 /* rotr is decoded as srl on non-R2 CPUs */
11652 if (env->insn_flags & ISA_MIPS32R2) {
11653 op1 = OPC_ROTR;
11654 }
11655 /* Fallthrough */
11656 case 0:
11657 gen_shift_imm(env, ctx, op1, rd, rt, sa);
11658 break;
11659 default:
11660 generate_exception(ctx, EXCP_RI);
11661 break;
11662 }
11663 break;
460f00c4
AJ
11664 case OPC_MOVN: /* Conditional move */
11665 case OPC_MOVZ:
aa8f4009
AJ
11666 check_insn(env, ctx, ISA_MIPS4 | ISA_MIPS32 |
11667 INSN_LOONGSON2E | INSN_LOONGSON2F);
460f00c4
AJ
11668 gen_cond_move(env, op1, rd, rs, rt);
11669 break;
11670 case OPC_ADD ... OPC_SUBU:
e189e748 11671 gen_arith(env, ctx, op1, rd, rs, rt);
7a387fff 11672 break;
460f00c4 11673 case OPC_SLLV: /* Shifts */
460f00c4
AJ
11674 case OPC_SRAV:
11675 gen_shift(env, ctx, op1, rd, rs, rt);
11676 break;
ea63e2c3
NF
11677 case OPC_SRLV:
11678 switch ((ctx->opcode >> 6) & 0x1f) {
11679 case 1:
11680 /* rotrv is decoded as srlv on non-R2 CPUs */
11681 if (env->insn_flags & ISA_MIPS32R2) {
11682 op1 = OPC_ROTRV;
11683 }
11684 /* Fallthrough */
11685 case 0:
11686 gen_shift(env, ctx, op1, rd, rs, rt);
11687 break;
11688 default:
11689 generate_exception(ctx, EXCP_RI);
11690 break;
11691 }
11692 break;
460f00c4
AJ
11693 case OPC_SLT: /* Set on less than */
11694 case OPC_SLTU:
11695 gen_slt(env, op1, rd, rs, rt);
11696 break;
11697 case OPC_AND: /* Logic*/
11698 case OPC_OR:
11699 case OPC_NOR:
11700 case OPC_XOR:
11701 gen_logic(env, op1, rd, rs, rt);
11702 break;
7a387fff 11703 case OPC_MULT ... OPC_DIVU:
e9c71dd1
TS
11704 if (sa) {
11705 check_insn(env, ctx, INSN_VR54XX);
11706 op1 = MASK_MUL_VR54XX(ctx->opcode);
11707 gen_mul_vr54xx(ctx, op1, rd, rs, rt);
11708 } else
11709 gen_muldiv(ctx, op1, rs, rt);
7a387fff
TS
11710 break;
11711 case OPC_JR ... OPC_JALR:
7dca4ad0 11712 gen_compute_branch(ctx, op1, 4, rs, rd, sa);
c9602061
NF
11713 *is_branch = 1;
11714 break;
7a387fff
TS
11715 case OPC_TGE ... OPC_TEQ: /* Traps */
11716 case OPC_TNE:
11717 gen_trap(ctx, op1, rs, rt, -1);
6af0bf9c 11718 break;
7a387fff
TS
11719 case OPC_MFHI: /* Move from HI/LO */
11720 case OPC_MFLO:
11721 gen_HILO(ctx, op1, rd);
6af0bf9c 11722 break;
7a387fff
TS
11723 case OPC_MTHI:
11724 case OPC_MTLO: /* Move to HI/LO */
11725 gen_HILO(ctx, op1, rs);
6af0bf9c 11726 break;
b48cfdff
TS
11727 case OPC_PMON: /* Pmon entry point, also R4010 selsl */
11728#ifdef MIPS_STRICT_STANDARD
11729 MIPS_INVAL("PMON / selsl");
11730 generate_exception(ctx, EXCP_RI);
11731#else
a7812ae4 11732 gen_helper_0i(pmon, sa);
b48cfdff 11733#endif
7a387fff
TS
11734 break;
11735 case OPC_SYSCALL:
6af0bf9c 11736 generate_exception(ctx, EXCP_SYSCALL);
8e0f950d 11737 ctx->bstate = BS_STOP;
6af0bf9c 11738 break;
7a387fff 11739 case OPC_BREAK:
6af0bf9c
FB
11740 generate_exception(ctx, EXCP_BREAK);
11741 break;
b48cfdff
TS
11742 case OPC_SPIM:
11743#ifdef MIPS_STRICT_STANDARD
11744 MIPS_INVAL("SPIM");
11745 generate_exception(ctx, EXCP_RI);
11746#else
7a387fff
TS
11747 /* Implemented as RI exception for now. */
11748 MIPS_INVAL("spim (unofficial)");
11749 generate_exception(ctx, EXCP_RI);
b48cfdff 11750#endif
6af0bf9c 11751 break;
7a387fff 11752 case OPC_SYNC:
ead9360e 11753 /* Treat as NOP. */
6af0bf9c 11754 break;
4ad40f36 11755
7a387fff 11756 case OPC_MOVCI:
e189e748 11757 check_insn(env, ctx, ISA_MIPS4 | ISA_MIPS32);
36d23958 11758 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
5e755519 11759 check_cp1_enabled(ctx);
36d23958
TS
11760 gen_movci(ctx, rd, rs, (ctx->opcode >> 18) & 0x7,
11761 (ctx->opcode >> 16) & 1);
11762 } else {
e397ee33 11763 generate_exception_err(ctx, EXCP_CpU, 1);
36d23958 11764 }
4ad40f36
FB
11765 break;
11766
d26bc211 11767#if defined(TARGET_MIPS64)
7a387fff
TS
11768 /* MIPS64 specific opcodes */
11769 case OPC_DSLL:
324d9e32 11770 case OPC_DSRA:
7a387fff 11771 case OPC_DSLL32:
324d9e32 11772 case OPC_DSRA32:
e189e748
TS
11773 check_insn(env, ctx, ISA_MIPS3);
11774 check_mips_64(ctx);
324d9e32 11775 gen_shift_imm(env, ctx, op1, rd, rt, sa);
7a387fff 11776 break;
ea63e2c3
NF
11777 case OPC_DSRL:
11778 switch ((ctx->opcode >> 21) & 0x1f) {
11779 case 1:
11780 /* drotr is decoded as dsrl on non-R2 CPUs */
11781 if (env->insn_flags & ISA_MIPS32R2) {
11782 op1 = OPC_DROTR;
11783 }
11784 /* Fallthrough */
11785 case 0:
11786 check_insn(env, ctx, ISA_MIPS3);
11787 check_mips_64(ctx);
11788 gen_shift_imm(env, ctx, op1, rd, rt, sa);
11789 break;
11790 default:
11791 generate_exception(ctx, EXCP_RI);
11792 break;
11793 }
11794 break;
11795 case OPC_DSRL32:
11796 switch ((ctx->opcode >> 21) & 0x1f) {
11797 case 1:
11798 /* drotr32 is decoded as dsrl32 on non-R2 CPUs */
11799 if (env->insn_flags & ISA_MIPS32R2) {
11800 op1 = OPC_DROTR32;
11801 }
11802 /* Fallthrough */
11803 case 0:
11804 check_insn(env, ctx, ISA_MIPS3);
11805 check_mips_64(ctx);
11806 gen_shift_imm(env, ctx, op1, rd, rt, sa);
11807 break;
11808 default:
11809 generate_exception(ctx, EXCP_RI);
11810 break;
11811 }
11812 break;
7a387fff 11813 case OPC_DADD ... OPC_DSUBU:
e189e748
TS
11814 check_insn(env, ctx, ISA_MIPS3);
11815 check_mips_64(ctx);
11816 gen_arith(env, ctx, op1, rd, rs, rt);
7a387fff 11817 break;
460f00c4
AJ
11818 case OPC_DSLLV:
11819 case OPC_DSRAV:
460f00c4
AJ
11820 check_insn(env, ctx, ISA_MIPS3);
11821 check_mips_64(ctx);
11822 gen_shift(env, ctx, op1, rd, rs, rt);
11823 break;
ea63e2c3
NF
11824 case OPC_DSRLV:
11825 switch ((ctx->opcode >> 6) & 0x1f) {
11826 case 1:
11827 /* drotrv is decoded as dsrlv on non-R2 CPUs */
11828 if (env->insn_flags & ISA_MIPS32R2) {
11829 op1 = OPC_DROTRV;
11830 }
11831 /* Fallthrough */
11832 case 0:
11833 check_insn(env, ctx, ISA_MIPS3);
11834 check_mips_64(ctx);
11835 gen_shift(env, ctx, op1, rd, rs, rt);
11836 break;
11837 default:
11838 generate_exception(ctx, EXCP_RI);
11839 break;
11840 }
11841 break;
7a387fff 11842 case OPC_DMULT ... OPC_DDIVU:
e189e748
TS
11843 check_insn(env, ctx, ISA_MIPS3);
11844 check_mips_64(ctx);
7a387fff
TS
11845 gen_muldiv(ctx, op1, rs, rt);
11846 break;
6af0bf9c
FB
11847#endif
11848 default: /* Invalid */
11849 MIPS_INVAL("special");
11850 generate_exception(ctx, EXCP_RI);
11851 break;
11852 }
11853 break;
7a387fff
TS
11854 case OPC_SPECIAL2:
11855 op1 = MASK_SPECIAL2(ctx->opcode);
6af0bf9c 11856 switch (op1) {
7a387fff
TS
11857 case OPC_MADD ... OPC_MADDU: /* Multiply and add/sub */
11858 case OPC_MSUB ... OPC_MSUBU:
e189e748 11859 check_insn(env, ctx, ISA_MIPS32);
7a387fff 11860 gen_muldiv(ctx, op1, rs, rt);
6af0bf9c 11861 break;
7a387fff 11862 case OPC_MUL:
e189e748 11863 gen_arith(env, ctx, op1, rd, rs, rt);
6af0bf9c 11864 break;
20e1fb52
AJ
11865 case OPC_CLO:
11866 case OPC_CLZ:
e189e748 11867 check_insn(env, ctx, ISA_MIPS32);
7a387fff 11868 gen_cl(ctx, op1, rd, rs);
6af0bf9c 11869 break;
7a387fff 11870 case OPC_SDBBP:
6af0bf9c
FB
11871 /* XXX: not clear which exception should be raised
11872 * when in debug mode...
11873 */
e189e748 11874 check_insn(env, ctx, ISA_MIPS32);
6af0bf9c
FB
11875 if (!(ctx->hflags & MIPS_HFLAG_DM)) {
11876 generate_exception(ctx, EXCP_DBp);
11877 } else {
11878 generate_exception(ctx, EXCP_DBp);
11879 }
ead9360e 11880 /* Treat as NOP. */
6af0bf9c 11881 break;
161f85e6
AJ
11882 case OPC_DIV_G_2F:
11883 case OPC_DIVU_G_2F:
11884 case OPC_MULT_G_2F:
11885 case OPC_MULTU_G_2F:
11886 case OPC_MOD_G_2F:
11887 case OPC_MODU_G_2F:
11888 check_insn(env, ctx, INSN_LOONGSON2F);
11889 gen_loongson_integer(ctx, op1, rd, rs, rt);
11890 break;
d26bc211 11891#if defined(TARGET_MIPS64)
20e1fb52
AJ
11892 case OPC_DCLO:
11893 case OPC_DCLZ:
e189e748
TS
11894 check_insn(env, ctx, ISA_MIPS64);
11895 check_mips_64(ctx);
7a387fff
TS
11896 gen_cl(ctx, op1, rd, rs);
11897 break;
161f85e6
AJ
11898 case OPC_DMULT_G_2F:
11899 case OPC_DMULTU_G_2F:
11900 case OPC_DDIV_G_2F:
11901 case OPC_DDIVU_G_2F:
11902 case OPC_DMOD_G_2F:
11903 case OPC_DMODU_G_2F:
11904 check_insn(env, ctx, INSN_LOONGSON2F);
11905 gen_loongson_integer(ctx, op1, rd, rs, rt);
11906 break;
7a387fff 11907#endif
6af0bf9c
FB
11908 default: /* Invalid */
11909 MIPS_INVAL("special2");
11910 generate_exception(ctx, EXCP_RI);
11911 break;
11912 }
11913 break;
7a387fff 11914 case OPC_SPECIAL3:
2b0233ab
TS
11915 op1 = MASK_SPECIAL3(ctx->opcode);
11916 switch (op1) {
11917 case OPC_EXT:
11918 case OPC_INS:
11919 check_insn(env, ctx, ISA_MIPS32R2);
11920 gen_bitops(ctx, op1, rt, rs, sa, rd);
11921 break;
11922 case OPC_BSHFL:
11923 check_insn(env, ctx, ISA_MIPS32R2);
11924 op2 = MASK_BSHFL(ctx->opcode);
49bcf33c 11925 gen_bshfl(ctx, op2, rt, rd);
7a387fff 11926 break;
1579a72e 11927 case OPC_RDHWR:
26ebe468 11928 gen_rdhwr(env, ctx, rt, rd);
1579a72e 11929 break;
ead9360e 11930 case OPC_FORK:
7385ac0b 11931 check_insn(env, ctx, ASE_MT);
6c5c1e20 11932 {
35fbce2c
AJ
11933 TCGv t0 = tcg_temp_new();
11934 TCGv t1 = tcg_temp_new();
6c5c1e20
TS
11935
11936 gen_load_gpr(t0, rt);
11937 gen_load_gpr(t1, rs);
a7812ae4 11938 gen_helper_fork(t0, t1);
6c5c1e20
TS
11939 tcg_temp_free(t0);
11940 tcg_temp_free(t1);
11941 }
ead9360e
TS
11942 break;
11943 case OPC_YIELD:
7385ac0b 11944 check_insn(env, ctx, ASE_MT);
6c5c1e20 11945 {
35fbce2c 11946 TCGv t0 = tcg_temp_new();
6c5c1e20 11947
35fbce2c 11948 save_cpu_state(ctx, 1);
6c5c1e20 11949 gen_load_gpr(t0, rs);
a7812ae4 11950 gen_helper_yield(t0, t0);
6c5c1e20
TS
11951 gen_store_gpr(t0, rd);
11952 tcg_temp_free(t0);
11953 }
ead9360e 11954 break;
161f85e6
AJ
11955 case OPC_DIV_G_2E ... OPC_DIVU_G_2E:
11956 case OPC_MULT_G_2E ... OPC_MULTU_G_2E:
11957 case OPC_MOD_G_2E ... OPC_MODU_G_2E:
11958 check_insn(env, ctx, INSN_LOONGSON2E);
11959 gen_loongson_integer(ctx, op1, rd, rs, rt);
11960 break;
d26bc211 11961#if defined(TARGET_MIPS64)
1579a72e
TS
11962 case OPC_DEXTM ... OPC_DEXT:
11963 case OPC_DINSM ... OPC_DINS:
e189e748
TS
11964 check_insn(env, ctx, ISA_MIPS64R2);
11965 check_mips_64(ctx);
1579a72e 11966 gen_bitops(ctx, op1, rt, rs, sa, rd);
7a387fff 11967 break;
1579a72e 11968 case OPC_DBSHFL:
e189e748
TS
11969 check_insn(env, ctx, ISA_MIPS64R2);
11970 check_mips_64(ctx);
1579a72e 11971 op2 = MASK_DBSHFL(ctx->opcode);
49bcf33c 11972 gen_bshfl(ctx, op2, rt, rd);
c6d6dd7c 11973 break;
161f85e6
AJ
11974 case OPC_DDIV_G_2E ... OPC_DDIVU_G_2E:
11975 case OPC_DMULT_G_2E ... OPC_DMULTU_G_2E:
11976 case OPC_DMOD_G_2E ... OPC_DMODU_G_2E:
11977 check_insn(env, ctx, INSN_LOONGSON2E);
11978 gen_loongson_integer(ctx, op1, rd, rs, rt);
11979 break;
7a387fff
TS
11980#endif
11981 default: /* Invalid */
11982 MIPS_INVAL("special3");
11983 generate_exception(ctx, EXCP_RI);
11984 break;
11985 }
11986 break;
11987 case OPC_REGIMM:
11988 op1 = MASK_REGIMM(ctx->opcode);
11989 switch (op1) {
11990 case OPC_BLTZ ... OPC_BGEZL: /* REGIMM branches */
11991 case OPC_BLTZAL ... OPC_BGEZALL:
7dca4ad0 11992 gen_compute_branch(ctx, op1, 4, rs, -1, imm << 2);
c9602061
NF
11993 *is_branch = 1;
11994 break;
7a387fff
TS
11995 case OPC_TGEI ... OPC_TEQI: /* REGIMM traps */
11996 case OPC_TNEI:
11997 gen_trap(ctx, op1, rs, -1, imm);
11998 break;
11999 case OPC_SYNCI:
e189e748 12000 check_insn(env, ctx, ISA_MIPS32R2);
ead9360e 12001 /* Treat as NOP. */
6af0bf9c
FB
12002 break;
12003 default: /* Invalid */
923617a3 12004 MIPS_INVAL("regimm");
6af0bf9c
FB
12005 generate_exception(ctx, EXCP_RI);
12006 break;
12007 }
12008 break;
7a387fff 12009 case OPC_CP0:
387a8fe5 12010 check_cp0_enabled(ctx);
7a387fff 12011 op1 = MASK_CP0(ctx->opcode);
6af0bf9c 12012 switch (op1) {
7a387fff
TS
12013 case OPC_MFC0:
12014 case OPC_MTC0:
ead9360e
TS
12015 case OPC_MFTR:
12016 case OPC_MTTR:
d26bc211 12017#if defined(TARGET_MIPS64)
7a387fff
TS
12018 case OPC_DMFC0:
12019 case OPC_DMTC0:
12020#endif
f1aa6320 12021#ifndef CONFIG_USER_ONLY
932e71cd 12022 gen_cp0(env, ctx, op1, rt, rd);
0eaef5aa 12023#endif /* !CONFIG_USER_ONLY */
7a387fff
TS
12024 break;
12025 case OPC_C0_FIRST ... OPC_C0_LAST:
f1aa6320 12026#ifndef CONFIG_USER_ONLY
932e71cd 12027 gen_cp0(env, ctx, MASK_C0(ctx->opcode), rt, rd);
0eaef5aa 12028#endif /* !CONFIG_USER_ONLY */
7a387fff
TS
12029 break;
12030 case OPC_MFMC0:
8706c382 12031#ifndef CONFIG_USER_ONLY
932e71cd 12032 {
35fbce2c 12033 TCGv t0 = tcg_temp_new();
6c5c1e20 12034
0eaef5aa 12035 op2 = MASK_MFMC0(ctx->opcode);
6c5c1e20
TS
12036 switch (op2) {
12037 case OPC_DMT:
12038 check_insn(env, ctx, ASE_MT);
9ed5726c 12039 gen_helper_dmt(t0);
35fbce2c 12040 gen_store_gpr(t0, rt);
6c5c1e20
TS
12041 break;
12042 case OPC_EMT:
12043 check_insn(env, ctx, ASE_MT);
9ed5726c 12044 gen_helper_emt(t0);
35fbce2c 12045 gen_store_gpr(t0, rt);
da80682b 12046 break;
6c5c1e20
TS
12047 case OPC_DVPE:
12048 check_insn(env, ctx, ASE_MT);
9ed5726c 12049 gen_helper_dvpe(t0);
35fbce2c 12050 gen_store_gpr(t0, rt);
6c5c1e20
TS
12051 break;
12052 case OPC_EVPE:
12053 check_insn(env, ctx, ASE_MT);
9ed5726c 12054 gen_helper_evpe(t0);
35fbce2c 12055 gen_store_gpr(t0, rt);
6c5c1e20
TS
12056 break;
12057 case OPC_DI:
12058 check_insn(env, ctx, ISA_MIPS32R2);
867abc7e 12059 save_cpu_state(ctx, 1);
a7812ae4 12060 gen_helper_di(t0);
35fbce2c 12061 gen_store_gpr(t0, rt);
6c5c1e20
TS
12062 /* Stop translation as we may have switched the execution mode */
12063 ctx->bstate = BS_STOP;
12064 break;
12065 case OPC_EI:
12066 check_insn(env, ctx, ISA_MIPS32R2);
867abc7e 12067 save_cpu_state(ctx, 1);
a7812ae4 12068 gen_helper_ei(t0);
35fbce2c 12069 gen_store_gpr(t0, rt);
6c5c1e20
TS
12070 /* Stop translation as we may have switched the execution mode */
12071 ctx->bstate = BS_STOP;
12072 break;
12073 default: /* Invalid */
12074 MIPS_INVAL("mfmc0");
12075 generate_exception(ctx, EXCP_RI);
12076 break;
12077 }
6c5c1e20 12078 tcg_temp_free(t0);
7a387fff 12079 }
0eaef5aa 12080#endif /* !CONFIG_USER_ONLY */
6af0bf9c 12081 break;
7a387fff 12082 case OPC_RDPGPR:
e189e748 12083 check_insn(env, ctx, ISA_MIPS32R2);
be24bb4f 12084 gen_load_srsgpr(rt, rd);
ead9360e 12085 break;
7a387fff 12086 case OPC_WRPGPR:
e189e748 12087 check_insn(env, ctx, ISA_MIPS32R2);
be24bb4f 12088 gen_store_srsgpr(rt, rd);
38121543 12089 break;
6af0bf9c 12090 default:
923617a3 12091 MIPS_INVAL("cp0");
7a387fff 12092 generate_exception(ctx, EXCP_RI);
6af0bf9c
FB
12093 break;
12094 }
12095 break;
324d9e32
AJ
12096 case OPC_ADDI: /* Arithmetic with immediate opcode */
12097 case OPC_ADDIU:
e189e748 12098 gen_arith_imm(env, ctx, op, rt, rs, imm);
7a387fff 12099 break;
324d9e32
AJ
12100 case OPC_SLTI: /* Set on less than with immediate opcode */
12101 case OPC_SLTIU:
12102 gen_slt_imm(env, op, rt, rs, imm);
12103 break;
12104 case OPC_ANDI: /* Arithmetic with immediate opcode */
12105 case OPC_LUI:
12106 case OPC_ORI:
12107 case OPC_XORI:
12108 gen_logic_imm(env, op, rt, rs, imm);
12109 break;
7a387fff
TS
12110 case OPC_J ... OPC_JAL: /* Jump */
12111 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2;
7dca4ad0 12112 gen_compute_branch(ctx, op, 4, rs, rt, offset);
c9602061
NF
12113 *is_branch = 1;
12114 break;
7a387fff
TS
12115 case OPC_BEQ ... OPC_BGTZ: /* Branch */
12116 case OPC_BEQL ... OPC_BGTZL:
7dca4ad0 12117 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2);
c9602061
NF
12118 *is_branch = 1;
12119 break;
7a387fff 12120 case OPC_LB ... OPC_LWR: /* Load and stores */
5c13fdfd 12121 case OPC_LL:
afa88c3a 12122 gen_ld(env, ctx, op, rt, rs, imm);
5c13fdfd 12123 break;
7a387fff
TS
12124 case OPC_SB ... OPC_SW:
12125 case OPC_SWR:
5c13fdfd 12126 gen_st(ctx, op, rt, rs, imm);
7a387fff 12127 break;
d66c7132
AJ
12128 case OPC_SC:
12129 gen_st_cond(ctx, op, rt, rs, imm);
12130 break;
7a387fff 12131 case OPC_CACHE:
e189e748 12132 check_insn(env, ctx, ISA_MIPS3 | ISA_MIPS32);
ead9360e 12133 /* Treat as NOP. */
34ae7b51 12134 break;
7a387fff 12135 case OPC_PREF:
e189e748 12136 check_insn(env, ctx, ISA_MIPS4 | ISA_MIPS32);
ead9360e 12137 /* Treat as NOP. */
6af0bf9c 12138 break;
4ad40f36 12139
923617a3 12140 /* Floating point (COP1). */
7a387fff
TS
12141 case OPC_LWC1:
12142 case OPC_LDC1:
12143 case OPC_SWC1:
12144 case OPC_SDC1:
26ebe468 12145 gen_cop1_ldst(env, ctx, op, rt, rs, imm);
6ea83fed
FB
12146 break;
12147
7a387fff 12148 case OPC_CP1:
36d23958 12149 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
5e755519 12150 check_cp1_enabled(ctx);
36d23958
TS
12151 op1 = MASK_CP1(ctx->opcode);
12152 switch (op1) {
3a95e3a7
TS
12153 case OPC_MFHC1:
12154 case OPC_MTHC1:
e189e748 12155 check_insn(env, ctx, ISA_MIPS32R2);
36d23958
TS
12156 case OPC_MFC1:
12157 case OPC_CFC1:
12158 case OPC_MTC1:
12159 case OPC_CTC1:
e189e748
TS
12160 gen_cp1(ctx, op1, rt, rd);
12161 break;
d26bc211 12162#if defined(TARGET_MIPS64)
36d23958
TS
12163 case OPC_DMFC1:
12164 case OPC_DMTC1:
e189e748 12165 check_insn(env, ctx, ISA_MIPS3);
36d23958
TS
12166 gen_cp1(ctx, op1, rt, rd);
12167 break;
e189e748 12168#endif
fbcc6828
TS
12169 case OPC_BC1ANY2:
12170 case OPC_BC1ANY4:
b8aa4598 12171 check_cop1x(ctx);
7385ac0b 12172 check_insn(env, ctx, ASE_MIPS3D);
d8a5950a
TS
12173 /* fall through */
12174 case OPC_BC1:
e189e748 12175 gen_compute_branch1(env, ctx, MASK_BC1(ctx->opcode),
5a5012ec 12176 (rt >> 2) & 0x7, imm << 2);
c9602061
NF
12177 *is_branch = 1;
12178 break;
36d23958
TS
12179 case OPC_S_FMT:
12180 case OPC_D_FMT:
12181 case OPC_W_FMT:
12182 case OPC_L_FMT:
5a5012ec 12183 case OPC_PS_FMT:
bf4120ad 12184 gen_farith(ctx, ctx->opcode & FOP(0x3f, 0x1f), rt, rd, sa,
5a5012ec 12185 (imm >> 8) & 0x7);
36d23958
TS
12186 break;
12187 default:
923617a3 12188 MIPS_INVAL("cp1");
e397ee33 12189 generate_exception (ctx, EXCP_RI);
36d23958
TS
12190 break;
12191 }
12192 } else {
12193 generate_exception_err(ctx, EXCP_CpU, 1);
6ea83fed 12194 }
4ad40f36
FB
12195 break;
12196
12197 /* COP2. */
7a387fff
TS
12198 case OPC_LWC2:
12199 case OPC_LDC2:
12200 case OPC_SWC2:
12201 case OPC_SDC2:
12202 case OPC_CP2:
12203 /* COP2: Not implemented. */
4ad40f36
FB
12204 generate_exception_err(ctx, EXCP_CpU, 2);
12205 break;
12206
7a387fff 12207 case OPC_CP3:
36d23958 12208 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
5e755519 12209 check_cp1_enabled(ctx);
36d23958
TS
12210 op1 = MASK_CP3(ctx->opcode);
12211 switch (op1) {
5a5012ec
TS
12212 case OPC_LWXC1:
12213 case OPC_LDXC1:
12214 case OPC_LUXC1:
12215 case OPC_SWXC1:
12216 case OPC_SDXC1:
12217 case OPC_SUXC1:
93b12ccc 12218 gen_flt3_ldst(ctx, op1, sa, rd, rs, rt);
5a5012ec 12219 break;
e0c84da7 12220 case OPC_PREFX:
ead9360e 12221 /* Treat as NOP. */
e0c84da7 12222 break;
5a5012ec
TS
12223 case OPC_ALNV_PS:
12224 case OPC_MADD_S:
12225 case OPC_MADD_D:
12226 case OPC_MADD_PS:
12227 case OPC_MSUB_S:
12228 case OPC_MSUB_D:
12229 case OPC_MSUB_PS:
12230 case OPC_NMADD_S:
12231 case OPC_NMADD_D:
12232 case OPC_NMADD_PS:
12233 case OPC_NMSUB_S:
12234 case OPC_NMSUB_D:
12235 case OPC_NMSUB_PS:
12236 gen_flt3_arith(ctx, op1, sa, rs, rd, rt);
12237 break;
36d23958 12238 default:
923617a3 12239 MIPS_INVAL("cp3");
e397ee33 12240 generate_exception (ctx, EXCP_RI);
36d23958
TS
12241 break;
12242 }
12243 } else {
e397ee33 12244 generate_exception_err(ctx, EXCP_CpU, 1);
7a387fff 12245 }
4ad40f36
FB
12246 break;
12247
d26bc211 12248#if defined(TARGET_MIPS64)
7a387fff
TS
12249 /* MIPS64 opcodes */
12250 case OPC_LWU:
12251 case OPC_LDL ... OPC_LDR:
7a387fff
TS
12252 case OPC_LLD:
12253 case OPC_LD:
5c13fdfd
AJ
12254 check_insn(env, ctx, ISA_MIPS3);
12255 check_mips_64(ctx);
afa88c3a 12256 gen_ld(env, ctx, op, rt, rs, imm);
5c13fdfd
AJ
12257 break;
12258 case OPC_SDL ... OPC_SDR:
7a387fff 12259 case OPC_SD:
e189e748
TS
12260 check_insn(env, ctx, ISA_MIPS3);
12261 check_mips_64(ctx);
5c13fdfd 12262 gen_st(ctx, op, rt, rs, imm);
7a387fff 12263 break;
d66c7132
AJ
12264 case OPC_SCD:
12265 check_insn(env, ctx, ISA_MIPS3);
12266 check_mips_64(ctx);
12267 gen_st_cond(ctx, op, rt, rs, imm);
12268 break;
324d9e32
AJ
12269 case OPC_DADDI:
12270 case OPC_DADDIU:
e189e748
TS
12271 check_insn(env, ctx, ISA_MIPS3);
12272 check_mips_64(ctx);
12273 gen_arith_imm(env, ctx, op, rt, rs, imm);
7a387fff 12274 break;
6af0bf9c 12275#endif
7a387fff 12276 case OPC_JALX:
3c824109 12277 check_insn(env, ctx, ASE_MIPS16 | ASE_MICROMIPS);
364d4831
NF
12278 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2;
12279 gen_compute_branch(ctx, op, 4, rs, rt, offset);
12280 *is_branch = 1;
12281 break;
7a387fff 12282 case OPC_MDMX:
e189e748 12283 check_insn(env, ctx, ASE_MDMX);
7a387fff 12284 /* MDMX: Not implemented. */
6af0bf9c 12285 default: /* Invalid */
923617a3 12286 MIPS_INVAL("major opcode");
6af0bf9c
FB
12287 generate_exception(ctx, EXCP_RI);
12288 break;
12289 }
6af0bf9c
FB
12290}
12291
2cfc5f17 12292static inline void
820e00f2
TS
12293gen_intermediate_code_internal (CPUState *env, TranslationBlock *tb,
12294 int search_pc)
6af0bf9c 12295{
278d0702 12296 DisasContext ctx;
6af0bf9c
FB
12297 target_ulong pc_start;
12298 uint16_t *gen_opc_end;
a1d1bb31 12299 CPUBreakpoint *bp;
6af0bf9c 12300 int j, lj = -1;
2e70f6ef
PB
12301 int num_insns;
12302 int max_insns;
c9602061
NF
12303 int insn_bytes;
12304 int is_branch;
6af0bf9c 12305
93fcfe39
AL
12306 if (search_pc)
12307 qemu_log("search pc %d\n", search_pc);
4ad40f36 12308
6af0bf9c 12309 pc_start = tb->pc;
d42320c2 12310 gen_opc_end = gen_opc_buf + OPC_MAX_SIZE;
6af0bf9c 12311 ctx.pc = pc_start;
4ad40f36 12312 ctx.saved_pc = -1;
7b270ef2 12313 ctx.singlestep_enabled = env->singlestep_enabled;
6af0bf9c
FB
12314 ctx.tb = tb;
12315 ctx.bstate = BS_NONE;
4ad40f36 12316 /* Restore delay slot state from the tb context. */
c068688b 12317 ctx.hflags = (uint32_t)tb->flags; /* FIXME: maybe use 64 bits here? */
fd4a04eb 12318 restore_cpu_state(env, &ctx);
932e71cd 12319#ifdef CONFIG_USER_ONLY
0eaef5aa 12320 ctx.mem_idx = MIPS_HFLAG_UM;
932e71cd 12321#else
0eaef5aa 12322 ctx.mem_idx = ctx.hflags & MIPS_HFLAG_KSU;
932e71cd 12323#endif
2e70f6ef
PB
12324 num_insns = 0;
12325 max_insns = tb->cflags & CF_COUNT_MASK;
12326 if (max_insns == 0)
12327 max_insns = CF_COUNT_MASK;
d12d51d5 12328 LOG_DISAS("\ntb %p idx %d hflags %04x\n", tb, ctx.mem_idx, ctx.hflags);
2e70f6ef 12329 gen_icount_start();
faf7aaa9 12330 while (ctx.bstate == BS_NONE) {
72cf2d4f
BS
12331 if (unlikely(!QTAILQ_EMPTY(&env->breakpoints))) {
12332 QTAILQ_FOREACH(bp, &env->breakpoints, entry) {
a1d1bb31 12333 if (bp->pc == ctx.pc) {
278d0702 12334 save_cpu_state(&ctx, 1);
4ad40f36 12335 ctx.bstate = BS_BRANCH;
a7812ae4 12336 gen_helper_0i(raise_exception, EXCP_DEBUG);
ce62e5ba
TS
12337 /* Include the breakpoint location or the tb won't
12338 * be flushed when it must be. */
12339 ctx.pc += 4;
4ad40f36
FB
12340 goto done_generating;
12341 }
12342 }
12343 }
12344
6af0bf9c
FB
12345 if (search_pc) {
12346 j = gen_opc_ptr - gen_opc_buf;
6af0bf9c
FB
12347 if (lj < j) {
12348 lj++;
12349 while (lj < j)
12350 gen_opc_instr_start[lj++] = 0;
6af0bf9c 12351 }
4ad40f36
FB
12352 gen_opc_pc[lj] = ctx.pc;
12353 gen_opc_hflags[lj] = ctx.hflags & MIPS_HFLAG_BMASK;
12354 gen_opc_instr_start[lj] = 1;
2e70f6ef 12355 gen_opc_icount[lj] = num_insns;
6af0bf9c 12356 }
2e70f6ef
PB
12357 if (num_insns + 1 == max_insns && (tb->cflags & CF_LAST_IO))
12358 gen_io_start();
c9602061
NF
12359
12360 is_branch = 0;
364d4831 12361 if (!(ctx.hflags & MIPS_HFLAG_M16)) {
c9602061
NF
12362 ctx.opcode = ldl_code(ctx.pc);
12363 insn_bytes = 4;
12364 decode_opc(env, &ctx, &is_branch);
3c824109
NF
12365 } else if (env->insn_flags & ASE_MICROMIPS) {
12366 ctx.opcode = lduw_code(ctx.pc);
12367 insn_bytes = decode_micromips_opc(env, &ctx, &is_branch);
364d4831
NF
12368 } else if (env->insn_flags & ASE_MIPS16) {
12369 ctx.opcode = lduw_code(ctx.pc);
12370 insn_bytes = decode_mips16_opc(env, &ctx, &is_branch);
c9602061
NF
12371 } else {
12372 generate_exception(&ctx, EXCP_RI);
3c824109 12373 ctx.bstate = BS_STOP;
c9602061
NF
12374 break;
12375 }
12376 if (!is_branch) {
12377 handle_delay_slot(env, &ctx, insn_bytes);
12378 }
12379 ctx.pc += insn_bytes;
12380
2e70f6ef 12381 num_insns++;
4ad40f36 12382
7b270ef2
NF
12383 /* Execute a branch and its delay slot as a single instruction.
12384 This is what GDB expects and is consistent with what the
12385 hardware does (e.g. if a delay slot instruction faults, the
12386 reported PC is the PC of the branch). */
12387 if (env->singlestep_enabled && (ctx.hflags & MIPS_HFLAG_BMASK) == 0)
4ad40f36
FB
12388 break;
12389
6af0bf9c
FB
12390 if ((ctx.pc & (TARGET_PAGE_SIZE - 1)) == 0)
12391 break;
4ad40f36 12392
faf7aaa9
TS
12393 if (gen_opc_ptr >= gen_opc_end)
12394 break;
12395
2e70f6ef
PB
12396 if (num_insns >= max_insns)
12397 break;
1b530a6d
AJ
12398
12399 if (singlestep)
12400 break;
6af0bf9c 12401 }
2e70f6ef
PB
12402 if (tb->cflags & CF_LAST_IO)
12403 gen_io_end();
7b270ef2 12404 if (env->singlestep_enabled && ctx.bstate != BS_BRANCH) {
278d0702 12405 save_cpu_state(&ctx, ctx.bstate == BS_NONE);
a7812ae4 12406 gen_helper_0i(raise_exception, EXCP_DEBUG);
16c00cb2 12407 } else {
6958549d 12408 switch (ctx.bstate) {
16c00cb2 12409 case BS_STOP:
df1561e2
TS
12410 gen_goto_tb(&ctx, 0, ctx.pc);
12411 break;
16c00cb2 12412 case BS_NONE:
278d0702 12413 save_cpu_state(&ctx, 0);
16c00cb2
TS
12414 gen_goto_tb(&ctx, 0, ctx.pc);
12415 break;
5a5012ec 12416 case BS_EXCP:
57fec1fe 12417 tcg_gen_exit_tb(0);
16c00cb2 12418 break;
5a5012ec
TS
12419 case BS_BRANCH:
12420 default:
12421 break;
6958549d 12422 }
6af0bf9c 12423 }
4ad40f36 12424done_generating:
2e70f6ef 12425 gen_icount_end(tb, num_insns);
6af0bf9c
FB
12426 *gen_opc_ptr = INDEX_op_end;
12427 if (search_pc) {
12428 j = gen_opc_ptr - gen_opc_buf;
12429 lj++;
12430 while (lj <= j)
12431 gen_opc_instr_start[lj++] = 0;
6af0bf9c
FB
12432 } else {
12433 tb->size = ctx.pc - pc_start;
2e70f6ef 12434 tb->icount = num_insns;
6af0bf9c
FB
12435 }
12436#ifdef DEBUG_DISAS
d12d51d5 12437 LOG_DISAS("\n");
8fec2b8c 12438 if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) {
93fcfe39
AL
12439 qemu_log("IN: %s\n", lookup_symbol(pc_start));
12440 log_target_disas(pc_start, ctx.pc - pc_start, 0);
12441 qemu_log("\n");
6af0bf9c
FB
12442 }
12443#endif
6af0bf9c
FB
12444}
12445
2cfc5f17 12446void gen_intermediate_code (CPUState *env, struct TranslationBlock *tb)
6af0bf9c 12447{
2cfc5f17 12448 gen_intermediate_code_internal(env, tb, 0);
6af0bf9c
FB
12449}
12450
2cfc5f17 12451void gen_intermediate_code_pc (CPUState *env, struct TranslationBlock *tb)
6af0bf9c 12452{
2cfc5f17 12453 gen_intermediate_code_internal(env, tb, 1);
6af0bf9c
FB
12454}
12455
9a78eead 12456static void fpu_dump_state(CPUState *env, FILE *f, fprintf_function fpu_fprintf,
8706c382 12457 int flags)
6ea83fed
FB
12458{
12459 int i;
5e755519 12460 int is_fpu64 = !!(env->hflags & MIPS_HFLAG_F64);
5a5012ec 12461
2a5612e6
SW
12462#define printfpr(fp) \
12463 do { \
12464 if (is_fpu64) \
12465 fpu_fprintf(f, "w:%08x d:%016" PRIx64 \
12466 " fd:%13g fs:%13g psu: %13g\n", \
12467 (fp)->w[FP_ENDIAN_IDX], (fp)->d, \
12468 (double)(fp)->fd, \
12469 (double)(fp)->fs[FP_ENDIAN_IDX], \
12470 (double)(fp)->fs[!FP_ENDIAN_IDX]); \
12471 else { \
12472 fpr_t tmp; \
12473 tmp.w[FP_ENDIAN_IDX] = (fp)->w[FP_ENDIAN_IDX]; \
12474 tmp.w[!FP_ENDIAN_IDX] = ((fp) + 1)->w[FP_ENDIAN_IDX]; \
12475 fpu_fprintf(f, "w:%08x d:%016" PRIx64 \
12476 " fd:%13g fs:%13g psu:%13g\n", \
12477 tmp.w[FP_ENDIAN_IDX], tmp.d, \
12478 (double)tmp.fd, \
12479 (double)tmp.fs[FP_ENDIAN_IDX], \
12480 (double)tmp.fs[!FP_ENDIAN_IDX]); \
12481 } \
6ea83fed
FB
12482 } while(0)
12483
5a5012ec 12484
9a78eead
SW
12485 fpu_fprintf(f, "CP1 FCR0 0x%08x FCR31 0x%08x SR.FR %d fp_status 0x%02x\n",
12486 env->active_fpu.fcr0, env->active_fpu.fcr31, is_fpu64,
f01be154 12487 get_float_exception_flags(&env->active_fpu.fp_status));
5a5012ec
TS
12488 for (i = 0; i < 32; (is_fpu64) ? i++ : (i += 2)) {
12489 fpu_fprintf(f, "%3s: ", fregnames[i]);
f01be154 12490 printfpr(&env->active_fpu.fpr[i]);
6ea83fed
FB
12491 }
12492
12493#undef printfpr
12494}
12495
d26bc211 12496#if defined(TARGET_MIPS64) && defined(MIPS_DEBUG_SIGN_EXTENSIONS)
c570fd16 12497/* Debug help: The architecture requires 32bit code to maintain proper
c7e8a937 12498 sign-extended values on 64bit machines. */
c570fd16
TS
12499
12500#define SIGN_EXT_P(val) ((((val) & ~0x7fffffff) == 0) || (((val) & ~0x7fffffff) == ~0x7fffffff))
12501
8706c382
TS
12502static void
12503cpu_mips_check_sign_extensions (CPUState *env, FILE *f,
9a78eead 12504 fprintf_function cpu_fprintf,
8706c382 12505 int flags)
c570fd16
TS
12506{
12507 int i;
12508
b5dc7732
TS
12509 if (!SIGN_EXT_P(env->active_tc.PC))
12510 cpu_fprintf(f, "BROKEN: pc=0x" TARGET_FMT_lx "\n", env->active_tc.PC);
12511 if (!SIGN_EXT_P(env->active_tc.HI[0]))
12512 cpu_fprintf(f, "BROKEN: HI=0x" TARGET_FMT_lx "\n", env->active_tc.HI[0]);
12513 if (!SIGN_EXT_P(env->active_tc.LO[0]))
12514 cpu_fprintf(f, "BROKEN: LO=0x" TARGET_FMT_lx "\n", env->active_tc.LO[0]);
c570fd16 12515 if (!SIGN_EXT_P(env->btarget))
3594c774 12516 cpu_fprintf(f, "BROKEN: btarget=0x" TARGET_FMT_lx "\n", env->btarget);
c570fd16
TS
12517
12518 for (i = 0; i < 32; i++) {
b5dc7732
TS
12519 if (!SIGN_EXT_P(env->active_tc.gpr[i]))
12520 cpu_fprintf(f, "BROKEN: %s=0x" TARGET_FMT_lx "\n", regnames[i], env->active_tc.gpr[i]);
c570fd16
TS
12521 }
12522
12523 if (!SIGN_EXT_P(env->CP0_EPC))
3594c774 12524 cpu_fprintf(f, "BROKEN: EPC=0x" TARGET_FMT_lx "\n", env->CP0_EPC);
5499b6ff
AJ
12525 if (!SIGN_EXT_P(env->lladdr))
12526 cpu_fprintf(f, "BROKEN: LLAddr=0x" TARGET_FMT_lx "\n", env->lladdr);
c570fd16
TS
12527}
12528#endif
12529
9a78eead 12530void cpu_dump_state (CPUState *env, FILE *f, fprintf_function cpu_fprintf,
6af0bf9c
FB
12531 int flags)
12532{
12533 int i;
3b46e624 12534
a7200c9f
SW
12535 cpu_fprintf(f, "pc=0x" TARGET_FMT_lx " HI=0x" TARGET_FMT_lx
12536 " LO=0x" TARGET_FMT_lx " ds %04x "
12537 TARGET_FMT_lx " " TARGET_FMT_ld "\n",
3d5be870
TS
12538 env->active_tc.PC, env->active_tc.HI[0], env->active_tc.LO[0],
12539 env->hflags, env->btarget, env->bcond);
6af0bf9c
FB
12540 for (i = 0; i < 32; i++) {
12541 if ((i & 3) == 0)
12542 cpu_fprintf(f, "GPR%02d:", i);
b5dc7732 12543 cpu_fprintf(f, " %s " TARGET_FMT_lx, regnames[i], env->active_tc.gpr[i]);
6af0bf9c
FB
12544 if ((i & 3) == 3)
12545 cpu_fprintf(f, "\n");
12546 }
568b600d 12547
3594c774 12548 cpu_fprintf(f, "CP0 Status 0x%08x Cause 0x%08x EPC 0x" TARGET_FMT_lx "\n",
5e755519 12549 env->CP0_Status, env->CP0_Cause, env->CP0_EPC);
3594c774 12550 cpu_fprintf(f, " Config0 0x%08x Config1 0x%08x LLAddr 0x" TARGET_FMT_lx "\n",
5499b6ff 12551 env->CP0_Config0, env->CP0_Config1, env->lladdr);
5e755519 12552 if (env->hflags & MIPS_HFLAG_FPU)
7a387fff 12553 fpu_dump_state(env, f, cpu_fprintf, flags);
d26bc211 12554#if defined(TARGET_MIPS64) && defined(MIPS_DEBUG_SIGN_EXTENSIONS)
c570fd16
TS
12555 cpu_mips_check_sign_extensions(env, f, cpu_fprintf, flags);
12556#endif
6af0bf9c
FB
12557}
12558
39454628
TS
12559static void mips_tcg_init(void)
12560{
f01be154 12561 int i;
39454628
TS
12562 static int inited;
12563
12564 /* Initialize various static tables. */
12565 if (inited)
6958549d 12566 return;
39454628 12567
a7812ae4 12568 cpu_env = tcg_global_reg_new_ptr(TCG_AREG0, "env");
f2c94b92 12569 TCGV_UNUSED(cpu_gpr[0]);
bb928dbe 12570 for (i = 1; i < 32; i++)
a7812ae4 12571 cpu_gpr[i] = tcg_global_mem_new(TCG_AREG0,
4b2eb8d2
TS
12572 offsetof(CPUState, active_tc.gpr[i]),
12573 regnames[i]);
a7812ae4 12574 cpu_PC = tcg_global_mem_new(TCG_AREG0,
4b2eb8d2
TS
12575 offsetof(CPUState, active_tc.PC), "PC");
12576 for (i = 0; i < MIPS_DSP_ACC; i++) {
a7812ae4 12577 cpu_HI[i] = tcg_global_mem_new(TCG_AREG0,
4b2eb8d2
TS
12578 offsetof(CPUState, active_tc.HI[i]),
12579 regnames_HI[i]);
a7812ae4 12580 cpu_LO[i] = tcg_global_mem_new(TCG_AREG0,
4b2eb8d2
TS
12581 offsetof(CPUState, active_tc.LO[i]),
12582 regnames_LO[i]);
a7812ae4 12583 cpu_ACX[i] = tcg_global_mem_new(TCG_AREG0,
4b2eb8d2
TS
12584 offsetof(CPUState, active_tc.ACX[i]),
12585 regnames_ACX[i]);
12586 }
a7812ae4 12587 cpu_dspctrl = tcg_global_mem_new(TCG_AREG0,
4b2eb8d2
TS
12588 offsetof(CPUState, active_tc.DSPControl),
12589 "DSPControl");
1ba74fb8
AJ
12590 bcond = tcg_global_mem_new(TCG_AREG0,
12591 offsetof(CPUState, bcond), "bcond");
a7812ae4 12592 btarget = tcg_global_mem_new(TCG_AREG0,
d077b6f7 12593 offsetof(CPUState, btarget), "btarget");
41db4607
AJ
12594 hflags = tcg_global_mem_new_i32(TCG_AREG0,
12595 offsetof(CPUState, hflags), "hflags");
12596
a7812ae4
PB
12597 fpu_fcr0 = tcg_global_mem_new_i32(TCG_AREG0,
12598 offsetof(CPUState, active_fpu.fcr0),
12599 "fcr0");
12600 fpu_fcr31 = tcg_global_mem_new_i32(TCG_AREG0,
12601 offsetof(CPUState, active_fpu.fcr31),
12602 "fcr31");
39454628 12603
7dd9e556 12604 /* register helpers */
a7812ae4 12605#define GEN_HELPER 2
7dd9e556
TS
12606#include "helper.h"
12607
39454628
TS
12608 inited = 1;
12609}
12610
aaed909a
FB
12611#include "translate_init.c"
12612
12613CPUMIPSState *cpu_mips_init (const char *cpu_model)
6af0bf9c
FB
12614{
12615 CPUMIPSState *env;
c227f099 12616 const mips_def_t *def;
6af0bf9c 12617
aaed909a
FB
12618 def = cpu_mips_find_by_name(cpu_model);
12619 if (!def)
12620 return NULL;
7267c094 12621 env = g_malloc0(sizeof(CPUMIPSState));
aaed909a 12622 env->cpu_model = def;
51cc2e78 12623 env->cpu_model_str = cpu_model;
aaed909a 12624
173d6cfe 12625 cpu_exec_init(env);
51cc2e78
BS
12626#ifndef CONFIG_USER_ONLY
12627 mmu_init(env, def);
12628#endif
12629 fpu_init(env, def);
12630 mvp_init(env, def);
39454628 12631 mips_tcg_init();
6ae81775 12632 cpu_reset(env);
0bf46a40 12633 qemu_init_vcpu(env);
6ae81775
TS
12634 return env;
12635}
12636
12637void cpu_reset (CPUMIPSState *env)
12638{
eca1bdf4
AL
12639 if (qemu_loglevel_mask(CPU_LOG_RESET)) {
12640 qemu_log("CPU Reset (CPU %d)\n", env->cpu_index);
12641 log_cpu_state(env, 0);
12642 }
12643
6ae81775 12644 memset(env, 0, offsetof(CPUMIPSState, breakpoints));
6af0bf9c 12645 tlb_flush(env, 1);
6ae81775 12646
51cc2e78
BS
12647 /* Reset registers to their default values */
12648 env->CP0_PRid = env->cpu_model->CP0_PRid;
12649 env->CP0_Config0 = env->cpu_model->CP0_Config0;
12650#ifdef TARGET_WORDS_BIGENDIAN
12651 env->CP0_Config0 |= (1 << CP0C0_BE);
12652#endif
12653 env->CP0_Config1 = env->cpu_model->CP0_Config1;
12654 env->CP0_Config2 = env->cpu_model->CP0_Config2;
12655 env->CP0_Config3 = env->cpu_model->CP0_Config3;
12656 env->CP0_Config6 = env->cpu_model->CP0_Config6;
12657 env->CP0_Config7 = env->cpu_model->CP0_Config7;
2a6e32dd
AJ
12658 env->CP0_LLAddr_rw_bitmask = env->cpu_model->CP0_LLAddr_rw_bitmask
12659 << env->cpu_model->CP0_LLAddr_shift;
12660 env->CP0_LLAddr_shift = env->cpu_model->CP0_LLAddr_shift;
51cc2e78
BS
12661 env->SYNCI_Step = env->cpu_model->SYNCI_Step;
12662 env->CCRes = env->cpu_model->CCRes;
12663 env->CP0_Status_rw_bitmask = env->cpu_model->CP0_Status_rw_bitmask;
12664 env->CP0_TCStatus_rw_bitmask = env->cpu_model->CP0_TCStatus_rw_bitmask;
12665 env->CP0_SRSCtl = env->cpu_model->CP0_SRSCtl;
12666 env->current_tc = 0;
12667 env->SEGBITS = env->cpu_model->SEGBITS;
12668 env->SEGMask = (target_ulong)((1ULL << env->cpu_model->SEGBITS) - 1);
12669#if defined(TARGET_MIPS64)
12670 if (env->cpu_model->insn_flags & ISA_MIPS3) {
12671 env->SEGMask |= 3ULL << 62;
12672 }
12673#endif
12674 env->PABITS = env->cpu_model->PABITS;
12675 env->PAMask = (target_ulong)((1ULL << env->cpu_model->PABITS) - 1);
12676 env->CP0_SRSConf0_rw_bitmask = env->cpu_model->CP0_SRSConf0_rw_bitmask;
12677 env->CP0_SRSConf0 = env->cpu_model->CP0_SRSConf0;
12678 env->CP0_SRSConf1_rw_bitmask = env->cpu_model->CP0_SRSConf1_rw_bitmask;
12679 env->CP0_SRSConf1 = env->cpu_model->CP0_SRSConf1;
12680 env->CP0_SRSConf2_rw_bitmask = env->cpu_model->CP0_SRSConf2_rw_bitmask;
12681 env->CP0_SRSConf2 = env->cpu_model->CP0_SRSConf2;
12682 env->CP0_SRSConf3_rw_bitmask = env->cpu_model->CP0_SRSConf3_rw_bitmask;
12683 env->CP0_SRSConf3 = env->cpu_model->CP0_SRSConf3;
12684 env->CP0_SRSConf4_rw_bitmask = env->cpu_model->CP0_SRSConf4_rw_bitmask;
12685 env->CP0_SRSConf4 = env->cpu_model->CP0_SRSConf4;
12686 env->insn_flags = env->cpu_model->insn_flags;
12687
0eaef5aa 12688#if defined(CONFIG_USER_ONLY)
932e71cd 12689 env->hflags = MIPS_HFLAG_UM;
df357f0e
PB
12690 /* Enable access to the SYNCI_Step register. */
12691 env->CP0_HWREna |= (1 << 1);
91a75935
NF
12692 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
12693 env->hflags |= MIPS_HFLAG_FPU;
12694 }
12695#ifdef TARGET_MIPS64
12696 if (env->active_fpu.fcr0 & (1 << FCR0_F64)) {
12697 env->hflags |= MIPS_HFLAG_F64;
12698 }
12699#endif
932e71cd
AJ
12700#else
12701 if (env->hflags & MIPS_HFLAG_BMASK) {
12702 /* If the exception was raised from a delay slot,
12703 come back to the jump. */
12704 env->CP0_ErrorEPC = env->active_tc.PC - 4;
aa328add 12705 } else {
932e71cd
AJ
12706 env->CP0_ErrorEPC = env->active_tc.PC;
12707 }
12708 env->active_tc.PC = (int32_t)0xBFC00000;
51cc2e78
BS
12709 env->CP0_Random = env->tlb->nb_tlb - 1;
12710 env->tlb->tlb_in_use = env->tlb->nb_tlb;
932e71cd 12711 env->CP0_Wired = 0;
671b0f36 12712 env->CP0_EBase = 0x80000000 | (env->cpu_index & 0x3FF);
932e71cd
AJ
12713 env->CP0_Status = (1 << CP0St_BEV) | (1 << CP0St_ERL);
12714 /* vectored interrupts not implemented, timer on int 7,
12715 no performance counters. */
12716 env->CP0_IntCtl = 0xe0000000;
12717 {
12718 int i;
12719
12720 for (i = 0; i < 7; i++) {
12721 env->CP0_WatchLo[i] = 0;
12722 env->CP0_WatchHi[i] = 0x80000000;
fd88b6ab 12723 }
932e71cd
AJ
12724 env->CP0_WatchLo[7] = 0;
12725 env->CP0_WatchHi[7] = 0;
fd88b6ab 12726 }
932e71cd
AJ
12727 /* Count register increments in debug mode, EJTAG version 1 */
12728 env->CP0_Debug = (1 << CP0DB_CNT) | (0x1 << CP0DB_VER);
12729 env->hflags = MIPS_HFLAG_CP0;
51cc2e78
BS
12730#endif
12731#if defined(TARGET_MIPS64)
12732 if (env->cpu_model->insn_flags & ISA_MIPS3) {
12733 env->hflags |= MIPS_HFLAG_64;
12734 }
932e71cd 12735#endif
6af0bf9c 12736 env->exception_index = EXCP_NONE;
6af0bf9c 12737}
d2856f1a 12738
e87b7cb0 12739void restore_state_to_opc(CPUState *env, TranslationBlock *tb, int pc_pos)
d2856f1a 12740{
b5dc7732 12741 env->active_tc.PC = gen_opc_pc[pc_pos];
d2856f1a
AJ
12742 env->hflags &= ~MIPS_HFLAG_BMASK;
12743 env->hflags |= gen_opc_hflags[pc_pos];
12744}