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