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