]> git.proxmox.com Git - qemu.git/blame - target-mips/translate.c
target-mips: add loongson 2E & 2F integer instructions
[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);
d9bea114 5193 gen_helper_mtc0_cause(arg);
2423f660
TS
5194 rn = "Cause";
5195 break;
9c2149c8
TS
5196 default:
5197 goto die;
876d4b07 5198 }
9c2149c8
TS
5199 break;
5200 case 14:
5201 switch (sel) {
5202 case 0:
d9bea114 5203 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUState, CP0_EPC));
2423f660
TS
5204 rn = "EPC";
5205 break;
9c2149c8
TS
5206 default:
5207 goto die;
876d4b07 5208 }
9c2149c8
TS
5209 break;
5210 case 15:
5211 switch (sel) {
5212 case 0:
2423f660
TS
5213 /* ignored */
5214 rn = "PRid";
5215 break;
9c2149c8 5216 case 1:
e189e748 5217 check_insn(env, ctx, ISA_MIPS32R2);
d9bea114 5218 gen_helper_mtc0_ebase(arg);
2423f660
TS
5219 rn = "EBase";
5220 break;
9c2149c8
TS
5221 default:
5222 goto die;
876d4b07 5223 }
9c2149c8
TS
5224 break;
5225 case 16:
5226 switch (sel) {
5227 case 0:
d9bea114 5228 gen_helper_mtc0_config0(arg);
9c2149c8 5229 rn = "Config";
2423f660
TS
5230 /* Stop translation as we may have switched the execution mode */
5231 ctx->bstate = BS_STOP;
9c2149c8
TS
5232 break;
5233 case 1:
1fc7bf6e 5234 /* ignored, read only */
9c2149c8
TS
5235 rn = "Config1";
5236 break;
5237 case 2:
d9bea114 5238 gen_helper_mtc0_config2(arg);
9c2149c8 5239 rn = "Config2";
2423f660
TS
5240 /* Stop translation as we may have switched the execution mode */
5241 ctx->bstate = BS_STOP;
9c2149c8
TS
5242 break;
5243 case 3:
2423f660 5244 /* ignored */
9c2149c8
TS
5245 rn = "Config3";
5246 break;
5247 /* 6,7 are implementation dependent */
5248 default:
5249 rn = "Invalid config selector";
5250 goto die;
5251 }
9c2149c8
TS
5252 break;
5253 case 17:
5254 switch (sel) {
5255 case 0:
2a6e32dd 5256 gen_helper_mtc0_lladdr(arg);
2423f660
TS
5257 rn = "LLAddr";
5258 break;
9c2149c8
TS
5259 default:
5260 goto die;
5261 }
5262 break;
5263 case 18:
5264 switch (sel) {
fd88b6ab 5265 case 0 ... 7:
d9bea114 5266 gen_helper_1i(mtc0_watchlo, arg, sel);
2423f660
TS
5267 rn = "WatchLo";
5268 break;
9c2149c8
TS
5269 default:
5270 goto die;
5271 }
5272 break;
5273 case 19:
5274 switch (sel) {
fd88b6ab 5275 case 0 ... 7:
d9bea114 5276 gen_helper_1i(mtc0_watchhi, arg, sel);
2423f660
TS
5277 rn = "WatchHi";
5278 break;
9c2149c8
TS
5279 default:
5280 goto die;
5281 }
5282 break;
5283 case 20:
5284 switch (sel) {
5285 case 0:
e189e748 5286 check_insn(env, ctx, ISA_MIPS3);
d9bea114 5287 gen_helper_mtc0_xcontext(arg);
2423f660
TS
5288 rn = "XContext";
5289 break;
9c2149c8
TS
5290 default:
5291 goto die;
5292 }
5293 break;
5294 case 21:
5295 /* Officially reserved, but sel 0 is used for R1x000 framemask */
5296 switch (sel) {
5297 case 0:
d9bea114 5298 gen_helper_mtc0_framemask(arg);
2423f660
TS
5299 rn = "Framemask";
5300 break;
9c2149c8
TS
5301 default:
5302 goto die;
5303 }
5304 break;
5305 case 22:
5306 /* ignored */
5307 rn = "Diagnostic"; /* implementation dependent */
876d4b07 5308 break;
9c2149c8
TS
5309 case 23:
5310 switch (sel) {
5311 case 0:
d9bea114 5312 gen_helper_mtc0_debug(arg); /* EJTAG support */
8487327a
TS
5313 /* BS_STOP isn't good enough here, hflags may have changed. */
5314 gen_save_pc(ctx->pc + 4);
5315 ctx->bstate = BS_EXCP;
2423f660
TS
5316 rn = "Debug";
5317 break;
9c2149c8 5318 case 1:
d9bea114 5319// gen_helper_mtc0_tracecontrol(arg); /* PDtrace support */
8487327a
TS
5320 /* Stop translation as we may have switched the execution mode */
5321 ctx->bstate = BS_STOP;
2423f660
TS
5322 rn = "TraceControl";
5323// break;
9c2149c8 5324 case 2:
d9bea114 5325// gen_helper_mtc0_tracecontrol2(arg); /* PDtrace support */
8487327a
TS
5326 /* Stop translation as we may have switched the execution mode */
5327 ctx->bstate = BS_STOP;
2423f660
TS
5328 rn = "TraceControl2";
5329// break;
9c2149c8 5330 case 3:
d9bea114 5331// gen_helper_mtc0_usertracedata(arg); /* PDtrace support */
8487327a
TS
5332 /* Stop translation as we may have switched the execution mode */
5333 ctx->bstate = BS_STOP;
2423f660
TS
5334 rn = "UserTraceData";
5335// break;
9c2149c8 5336 case 4:
d9bea114 5337// gen_helper_mtc0_tracebpc(arg); /* PDtrace support */
8487327a
TS
5338 /* Stop translation as we may have switched the execution mode */
5339 ctx->bstate = BS_STOP;
2423f660
TS
5340 rn = "TraceBPC";
5341// break;
9c2149c8
TS
5342 default:
5343 goto die;
5344 }
9c2149c8
TS
5345 break;
5346 case 24:
5347 switch (sel) {
5348 case 0:
f1aa6320 5349 /* EJTAG support */
d9bea114 5350 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUState, CP0_DEPC));
2423f660
TS
5351 rn = "DEPC";
5352 break;
9c2149c8
TS
5353 default:
5354 goto die;
5355 }
5356 break;
5357 case 25:
5358 switch (sel) {
5359 case 0:
d9bea114 5360 gen_helper_mtc0_performance0(arg);
2423f660
TS
5361 rn = "Performance0";
5362 break;
9c2149c8 5363 case 1:
d9bea114 5364// gen_helper_mtc0_performance1(arg);
2423f660
TS
5365 rn = "Performance1";
5366// break;
9c2149c8 5367 case 2:
d9bea114 5368// gen_helper_mtc0_performance2(arg);
2423f660
TS
5369 rn = "Performance2";
5370// break;
9c2149c8 5371 case 3:
d9bea114 5372// gen_helper_mtc0_performance3(arg);
2423f660
TS
5373 rn = "Performance3";
5374// break;
9c2149c8 5375 case 4:
d9bea114 5376// gen_helper_mtc0_performance4(arg);
2423f660
TS
5377 rn = "Performance4";
5378// break;
9c2149c8 5379 case 5:
d9bea114 5380// gen_helper_mtc0_performance5(arg);
2423f660
TS
5381 rn = "Performance5";
5382// break;
9c2149c8 5383 case 6:
d9bea114 5384// gen_helper_mtc0_performance6(arg);
2423f660
TS
5385 rn = "Performance6";
5386// break;
9c2149c8 5387 case 7:
d9bea114 5388// gen_helper_mtc0_performance7(arg);
2423f660
TS
5389 rn = "Performance7";
5390// break;
9c2149c8
TS
5391 default:
5392 goto die;
5393 }
876d4b07 5394 break;
9c2149c8 5395 case 26:
876d4b07 5396 /* ignored */
9c2149c8 5397 rn = "ECC";
876d4b07 5398 break;
9c2149c8
TS
5399 case 27:
5400 switch (sel) {
5401 case 0 ... 3:
2423f660
TS
5402 /* ignored */
5403 rn = "CacheErr";
5404 break;
9c2149c8
TS
5405 default:
5406 goto die;
5407 }
876d4b07 5408 break;
9c2149c8
TS
5409 case 28:
5410 switch (sel) {
5411 case 0:
5412 case 2:
5413 case 4:
5414 case 6:
d9bea114 5415 gen_helper_mtc0_taglo(arg);
9c2149c8
TS
5416 rn = "TagLo";
5417 break;
5418 case 1:
5419 case 3:
5420 case 5:
5421 case 7:
d9bea114 5422 gen_helper_mtc0_datalo(arg);
9c2149c8
TS
5423 rn = "DataLo";
5424 break;
5425 default:
5426 goto die;
5427 }
5428 break;
5429 case 29:
5430 switch (sel) {
5431 case 0:
5432 case 2:
5433 case 4:
5434 case 6:
d9bea114 5435 gen_helper_mtc0_taghi(arg);
9c2149c8
TS
5436 rn = "TagHi";
5437 break;
5438 case 1:
5439 case 3:
5440 case 5:
5441 case 7:
d9bea114 5442 gen_helper_mtc0_datahi(arg);
9c2149c8
TS
5443 rn = "DataHi";
5444 break;
5445 default:
5446 rn = "invalid sel";
5447 goto die;
5448 }
876d4b07 5449 break;
9c2149c8
TS
5450 case 30:
5451 switch (sel) {
5452 case 0:
d9bea114 5453 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUState, CP0_ErrorEPC));
2423f660
TS
5454 rn = "ErrorEPC";
5455 break;
9c2149c8
TS
5456 default:
5457 goto die;
5458 }
5459 break;
5460 case 31:
5461 switch (sel) {
5462 case 0:
f1aa6320 5463 /* EJTAG support */
d9bea114 5464 gen_mtc0_store32(arg, offsetof(CPUState, CP0_DESAVE));
2423f660
TS
5465 rn = "DESAVE";
5466 break;
9c2149c8
TS
5467 default:
5468 goto die;
5469 }
876d4b07
TS
5470 /* Stop translation as we may have switched the execution mode */
5471 ctx->bstate = BS_STOP;
9c2149c8
TS
5472 break;
5473 default:
876d4b07 5474 goto die;
9c2149c8 5475 }
d12d51d5 5476 LOG_DISAS("dmtc0 %s (reg %d sel %d)\n", rn, reg, sel);
bf20dc07 5477 /* For simplicity assume that all writes can cause interrupts. */
2e70f6ef
PB
5478 if (use_icount) {
5479 gen_io_end();
5480 ctx->bstate = BS_STOP;
5481 }
9c2149c8
TS
5482 return;
5483
5484die:
d12d51d5 5485 LOG_DISAS("dmtc0 %s (reg %d sel %d)\n", rn, reg, sel);
9c2149c8
TS
5486 generate_exception(ctx, EXCP_RI);
5487}
d26bc211 5488#endif /* TARGET_MIPS64 */
9c2149c8 5489
6c5c1e20 5490static void gen_mftr(CPUState *env, DisasContext *ctx, int rt, int rd,
ead9360e
TS
5491 int u, int sel, int h)
5492{
5493 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
a7812ae4 5494 TCGv t0 = tcg_temp_local_new();
ead9360e
TS
5495
5496 if ((env->CP0_VPEConf0 & (1 << CP0VPEC0_MVP)) == 0 &&
b5dc7732
TS
5497 ((env->tcs[other_tc].CP0_TCBind & (0xf << CP0TCBd_CurVPE)) !=
5498 (env->active_tc.CP0_TCBind & (0xf << CP0TCBd_CurVPE))))
1a3fd9c3 5499 tcg_gen_movi_tl(t0, -1);
ead9360e
TS
5500 else if ((env->CP0_VPEControl & (0xff << CP0VPECo_TargTC)) >
5501 (env->mvp->CP0_MVPConf0 & (0xff << CP0MVPC0_PTC)))
1a3fd9c3 5502 tcg_gen_movi_tl(t0, -1);
ead9360e
TS
5503 else if (u == 0) {
5504 switch (rt) {
5505 case 2:
5506 switch (sel) {
5507 case 1:
a7812ae4 5508 gen_helper_mftc0_tcstatus(t0);
ead9360e
TS
5509 break;
5510 case 2:
a7812ae4 5511 gen_helper_mftc0_tcbind(t0);
ead9360e
TS
5512 break;
5513 case 3:
a7812ae4 5514 gen_helper_mftc0_tcrestart(t0);
ead9360e
TS
5515 break;
5516 case 4:
a7812ae4 5517 gen_helper_mftc0_tchalt(t0);
ead9360e
TS
5518 break;
5519 case 5:
a7812ae4 5520 gen_helper_mftc0_tccontext(t0);
ead9360e
TS
5521 break;
5522 case 6:
a7812ae4 5523 gen_helper_mftc0_tcschedule(t0);
ead9360e
TS
5524 break;
5525 case 7:
a7812ae4 5526 gen_helper_mftc0_tcschefback(t0);
ead9360e
TS
5527 break;
5528 default:
1a3fd9c3 5529 gen_mfc0(env, ctx, t0, rt, sel);
ead9360e
TS
5530 break;
5531 }
5532 break;
5533 case 10:
5534 switch (sel) {
5535 case 0:
a7812ae4 5536 gen_helper_mftc0_entryhi(t0);
ead9360e
TS
5537 break;
5538 default:
1a3fd9c3 5539 gen_mfc0(env, ctx, t0, rt, sel);
ead9360e
TS
5540 break;
5541 }
5542 case 12:
5543 switch (sel) {
5544 case 0:
a7812ae4 5545 gen_helper_mftc0_status(t0);
ead9360e
TS
5546 break;
5547 default:
1a3fd9c3 5548 gen_mfc0(env, ctx, t0, rt, sel);
ead9360e
TS
5549 break;
5550 }
5551 case 23:
5552 switch (sel) {
5553 case 0:
a7812ae4 5554 gen_helper_mftc0_debug(t0);
ead9360e
TS
5555 break;
5556 default:
1a3fd9c3 5557 gen_mfc0(env, ctx, t0, rt, sel);
ead9360e
TS
5558 break;
5559 }
5560 break;
5561 default:
1a3fd9c3 5562 gen_mfc0(env, ctx, t0, rt, sel);
ead9360e
TS
5563 }
5564 } else switch (sel) {
5565 /* GPR registers. */
5566 case 0:
a7812ae4 5567 gen_helper_1i(mftgpr, t0, rt);
ead9360e
TS
5568 break;
5569 /* Auxiliary CPU registers */
5570 case 1:
5571 switch (rt) {
5572 case 0:
a7812ae4 5573 gen_helper_1i(mftlo, t0, 0);
ead9360e
TS
5574 break;
5575 case 1:
a7812ae4 5576 gen_helper_1i(mfthi, t0, 0);
ead9360e
TS
5577 break;
5578 case 2:
a7812ae4 5579 gen_helper_1i(mftacx, t0, 0);
ead9360e
TS
5580 break;
5581 case 4:
a7812ae4 5582 gen_helper_1i(mftlo, t0, 1);
ead9360e
TS
5583 break;
5584 case 5:
a7812ae4 5585 gen_helper_1i(mfthi, t0, 1);
ead9360e
TS
5586 break;
5587 case 6:
a7812ae4 5588 gen_helper_1i(mftacx, t0, 1);
ead9360e
TS
5589 break;
5590 case 8:
a7812ae4 5591 gen_helper_1i(mftlo, t0, 2);
ead9360e
TS
5592 break;
5593 case 9:
a7812ae4 5594 gen_helper_1i(mfthi, t0, 2);
ead9360e
TS
5595 break;
5596 case 10:
a7812ae4 5597 gen_helper_1i(mftacx, t0, 2);
ead9360e
TS
5598 break;
5599 case 12:
a7812ae4 5600 gen_helper_1i(mftlo, t0, 3);
ead9360e
TS
5601 break;
5602 case 13:
a7812ae4 5603 gen_helper_1i(mfthi, t0, 3);
ead9360e
TS
5604 break;
5605 case 14:
a7812ae4 5606 gen_helper_1i(mftacx, t0, 3);
ead9360e
TS
5607 break;
5608 case 16:
a7812ae4 5609 gen_helper_mftdsp(t0);
ead9360e
TS
5610 break;
5611 default:
5612 goto die;
5613 }
5614 break;
5615 /* Floating point (COP1). */
5616 case 2:
5617 /* XXX: For now we support only a single FPU context. */
5618 if (h == 0) {
a7812ae4 5619 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed
TS
5620
5621 gen_load_fpr32(fp0, rt);
5622 tcg_gen_ext_i32_tl(t0, fp0);
a7812ae4 5623 tcg_temp_free_i32(fp0);
ead9360e 5624 } else {
a7812ae4 5625 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed
TS
5626
5627 gen_load_fpr32h(fp0, rt);
5628 tcg_gen_ext_i32_tl(t0, fp0);
a7812ae4 5629 tcg_temp_free_i32(fp0);
ead9360e
TS
5630 }
5631 break;
5632 case 3:
5633 /* XXX: For now we support only a single FPU context. */
a7812ae4 5634 gen_helper_1i(cfc1, t0, rt);
ead9360e
TS
5635 break;
5636 /* COP2: Not implemented. */
5637 case 4:
5638 case 5:
5639 /* fall through */
5640 default:
5641 goto die;
5642 }
d12d51d5 5643 LOG_DISAS("mftr (reg %d u %d sel %d h %d)\n", rt, u, sel, h);
1a3fd9c3
TS
5644 gen_store_gpr(t0, rd);
5645 tcg_temp_free(t0);
ead9360e
TS
5646 return;
5647
5648die:
1a3fd9c3 5649 tcg_temp_free(t0);
d12d51d5 5650 LOG_DISAS("mftr (reg %d u %d sel %d h %d)\n", rt, u, sel, h);
ead9360e
TS
5651 generate_exception(ctx, EXCP_RI);
5652}
5653
6c5c1e20 5654static void gen_mttr(CPUState *env, DisasContext *ctx, int rd, int rt,
ead9360e
TS
5655 int u, int sel, int h)
5656{
5657 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
a7812ae4 5658 TCGv t0 = tcg_temp_local_new();
ead9360e 5659
1a3fd9c3 5660 gen_load_gpr(t0, rt);
ead9360e 5661 if ((env->CP0_VPEConf0 & (1 << CP0VPEC0_MVP)) == 0 &&
b5dc7732
TS
5662 ((env->tcs[other_tc].CP0_TCBind & (0xf << CP0TCBd_CurVPE)) !=
5663 (env->active_tc.CP0_TCBind & (0xf << CP0TCBd_CurVPE))))
ead9360e
TS
5664 /* NOP */ ;
5665 else if ((env->CP0_VPEControl & (0xff << CP0VPECo_TargTC)) >
5666 (env->mvp->CP0_MVPConf0 & (0xff << CP0MVPC0_PTC)))
5667 /* NOP */ ;
5668 else if (u == 0) {
5669 switch (rd) {
5670 case 2:
5671 switch (sel) {
5672 case 1:
a7812ae4 5673 gen_helper_mttc0_tcstatus(t0);
ead9360e
TS
5674 break;
5675 case 2:
a7812ae4 5676 gen_helper_mttc0_tcbind(t0);
ead9360e
TS
5677 break;
5678 case 3:
a7812ae4 5679 gen_helper_mttc0_tcrestart(t0);
ead9360e
TS
5680 break;
5681 case 4:
a7812ae4 5682 gen_helper_mttc0_tchalt(t0);
ead9360e
TS
5683 break;
5684 case 5:
a7812ae4 5685 gen_helper_mttc0_tccontext(t0);
ead9360e
TS
5686 break;
5687 case 6:
a7812ae4 5688 gen_helper_mttc0_tcschedule(t0);
ead9360e
TS
5689 break;
5690 case 7:
a7812ae4 5691 gen_helper_mttc0_tcschefback(t0);
ead9360e
TS
5692 break;
5693 default:
1a3fd9c3 5694 gen_mtc0(env, ctx, t0, rd, sel);
ead9360e
TS
5695 break;
5696 }
5697 break;
5698 case 10:
5699 switch (sel) {
5700 case 0:
a7812ae4 5701 gen_helper_mttc0_entryhi(t0);
ead9360e
TS
5702 break;
5703 default:
1a3fd9c3 5704 gen_mtc0(env, ctx, t0, rd, sel);
ead9360e
TS
5705 break;
5706 }
5707 case 12:
5708 switch (sel) {
5709 case 0:
a7812ae4 5710 gen_helper_mttc0_status(t0);
ead9360e
TS
5711 break;
5712 default:
1a3fd9c3 5713 gen_mtc0(env, ctx, t0, rd, sel);
ead9360e
TS
5714 break;
5715 }
5716 case 23:
5717 switch (sel) {
5718 case 0:
a7812ae4 5719 gen_helper_mttc0_debug(t0);
ead9360e
TS
5720 break;
5721 default:
1a3fd9c3 5722 gen_mtc0(env, ctx, t0, rd, sel);
ead9360e
TS
5723 break;
5724 }
5725 break;
5726 default:
1a3fd9c3 5727 gen_mtc0(env, ctx, t0, rd, sel);
ead9360e
TS
5728 }
5729 } else switch (sel) {
5730 /* GPR registers. */
5731 case 0:
a7812ae4 5732 gen_helper_1i(mttgpr, t0, rd);
ead9360e
TS
5733 break;
5734 /* Auxiliary CPU registers */
5735 case 1:
5736 switch (rd) {
5737 case 0:
a7812ae4 5738 gen_helper_1i(mttlo, t0, 0);
ead9360e
TS
5739 break;
5740 case 1:
a7812ae4 5741 gen_helper_1i(mtthi, t0, 0);
ead9360e
TS
5742 break;
5743 case 2:
a7812ae4 5744 gen_helper_1i(mttacx, t0, 0);
ead9360e
TS
5745 break;
5746 case 4:
a7812ae4 5747 gen_helper_1i(mttlo, t0, 1);
ead9360e
TS
5748 break;
5749 case 5:
a7812ae4 5750 gen_helper_1i(mtthi, t0, 1);
ead9360e
TS
5751 break;
5752 case 6:
a7812ae4 5753 gen_helper_1i(mttacx, t0, 1);
ead9360e
TS
5754 break;
5755 case 8:
a7812ae4 5756 gen_helper_1i(mttlo, t0, 2);
ead9360e
TS
5757 break;
5758 case 9:
a7812ae4 5759 gen_helper_1i(mtthi, t0, 2);
ead9360e
TS
5760 break;
5761 case 10:
a7812ae4 5762 gen_helper_1i(mttacx, t0, 2);
ead9360e
TS
5763 break;
5764 case 12:
a7812ae4 5765 gen_helper_1i(mttlo, t0, 3);
ead9360e
TS
5766 break;
5767 case 13:
a7812ae4 5768 gen_helper_1i(mtthi, t0, 3);
ead9360e
TS
5769 break;
5770 case 14:
a7812ae4 5771 gen_helper_1i(mttacx, t0, 3);
ead9360e
TS
5772 break;
5773 case 16:
a7812ae4 5774 gen_helper_mttdsp(t0);
ead9360e
TS
5775 break;
5776 default:
5777 goto die;
5778 }
5779 break;
5780 /* Floating point (COP1). */
5781 case 2:
5782 /* XXX: For now we support only a single FPU context. */
5783 if (h == 0) {
a7812ae4 5784 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed
TS
5785
5786 tcg_gen_trunc_tl_i32(fp0, t0);
5787 gen_store_fpr32(fp0, rd);
a7812ae4 5788 tcg_temp_free_i32(fp0);
ead9360e 5789 } else {
a7812ae4 5790 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed
TS
5791
5792 tcg_gen_trunc_tl_i32(fp0, t0);
5793 gen_store_fpr32h(fp0, rd);
a7812ae4 5794 tcg_temp_free_i32(fp0);
ead9360e
TS
5795 }
5796 break;
5797 case 3:
5798 /* XXX: For now we support only a single FPU context. */
a7812ae4 5799 gen_helper_1i(ctc1, t0, rd);
ead9360e
TS
5800 break;
5801 /* COP2: Not implemented. */
5802 case 4:
5803 case 5:
5804 /* fall through */
5805 default:
5806 goto die;
5807 }
d12d51d5 5808 LOG_DISAS("mttr (reg %d u %d sel %d h %d)\n", rd, u, sel, h);
1a3fd9c3 5809 tcg_temp_free(t0);
ead9360e
TS
5810 return;
5811
5812die:
1a3fd9c3 5813 tcg_temp_free(t0);
d12d51d5 5814 LOG_DISAS("mttr (reg %d u %d sel %d h %d)\n", rd, u, sel, h);
ead9360e
TS
5815 generate_exception(ctx, EXCP_RI);
5816}
5817
29929e34 5818static void gen_cp0 (CPUState *env, DisasContext *ctx, uint32_t opc, int rt, int rd)
6af0bf9c 5819{
287c4b84 5820 const char *opn = "ldst";
6af0bf9c 5821
6af0bf9c
FB
5822 switch (opc) {
5823 case OPC_MFC0:
5824 if (rt == 0) {
ead9360e 5825 /* Treat as NOP. */
6af0bf9c
FB
5826 return;
5827 }
1fc7bf6e 5828 gen_mfc0(env, ctx, cpu_gpr[rt], rd, ctx->opcode & 0x7);
6af0bf9c
FB
5829 opn = "mfc0";
5830 break;
5831 case OPC_MTC0:
1a3fd9c3 5832 {
1fc7bf6e 5833 TCGv t0 = tcg_temp_new();
1a3fd9c3
TS
5834
5835 gen_load_gpr(t0, rt);
1a3fd9c3
TS
5836 gen_mtc0(env, ctx, t0, rd, ctx->opcode & 0x7);
5837 tcg_temp_free(t0);
5838 }
6af0bf9c
FB
5839 opn = "mtc0";
5840 break;
d26bc211 5841#if defined(TARGET_MIPS64)
9c2149c8 5842 case OPC_DMFC0:
e189e748 5843 check_insn(env, ctx, ISA_MIPS3);
9c2149c8 5844 if (rt == 0) {
ead9360e 5845 /* Treat as NOP. */
9c2149c8
TS
5846 return;
5847 }
1fc7bf6e 5848 gen_dmfc0(env, ctx, cpu_gpr[rt], rd, ctx->opcode & 0x7);
9c2149c8
TS
5849 opn = "dmfc0";
5850 break;
5851 case OPC_DMTC0:
e189e748 5852 check_insn(env, ctx, ISA_MIPS3);
1a3fd9c3 5853 {
1fc7bf6e 5854 TCGv t0 = tcg_temp_new();
1a3fd9c3
TS
5855
5856 gen_load_gpr(t0, rt);
1a3fd9c3
TS
5857 gen_dmtc0(env, ctx, t0, rd, ctx->opcode & 0x7);
5858 tcg_temp_free(t0);
5859 }
9c2149c8
TS
5860 opn = "dmtc0";
5861 break;
534ce69f 5862#endif
ead9360e 5863 case OPC_MFTR:
7385ac0b 5864 check_insn(env, ctx, ASE_MT);
ead9360e
TS
5865 if (rd == 0) {
5866 /* Treat as NOP. */
5867 return;
5868 }
6c5c1e20 5869 gen_mftr(env, ctx, rt, rd, (ctx->opcode >> 5) & 1,
ead9360e 5870 ctx->opcode & 0x7, (ctx->opcode >> 4) & 1);
ead9360e
TS
5871 opn = "mftr";
5872 break;
5873 case OPC_MTTR:
7385ac0b 5874 check_insn(env, ctx, ASE_MT);
6c5c1e20 5875 gen_mttr(env, ctx, rd, rt, (ctx->opcode >> 5) & 1,
ead9360e
TS
5876 ctx->opcode & 0x7, (ctx->opcode >> 4) & 1);
5877 opn = "mttr";
5878 break;
6af0bf9c 5879 case OPC_TLBWI:
6af0bf9c 5880 opn = "tlbwi";
c01fccd2 5881 if (!env->tlb->helper_tlbwi)
29929e34 5882 goto die;
a7812ae4 5883 gen_helper_tlbwi();
6af0bf9c
FB
5884 break;
5885 case OPC_TLBWR:
6af0bf9c 5886 opn = "tlbwr";
c01fccd2 5887 if (!env->tlb->helper_tlbwr)
29929e34 5888 goto die;
a7812ae4 5889 gen_helper_tlbwr();
6af0bf9c
FB
5890 break;
5891 case OPC_TLBP:
6af0bf9c 5892 opn = "tlbp";
c01fccd2 5893 if (!env->tlb->helper_tlbp)
29929e34 5894 goto die;
a7812ae4 5895 gen_helper_tlbp();
6af0bf9c
FB
5896 break;
5897 case OPC_TLBR:
6af0bf9c 5898 opn = "tlbr";
c01fccd2 5899 if (!env->tlb->helper_tlbr)
29929e34 5900 goto die;
a7812ae4 5901 gen_helper_tlbr();
6af0bf9c 5902 break;
6af0bf9c
FB
5903 case OPC_ERET:
5904 opn = "eret";
e189e748 5905 check_insn(env, ctx, ISA_MIPS2);
a7812ae4 5906 gen_helper_eret();
6af0bf9c
FB
5907 ctx->bstate = BS_EXCP;
5908 break;
5909 case OPC_DERET:
5910 opn = "deret";
e189e748 5911 check_insn(env, ctx, ISA_MIPS32);
6af0bf9c 5912 if (!(ctx->hflags & MIPS_HFLAG_DM)) {
923617a3 5913 MIPS_INVAL(opn);
6af0bf9c
FB
5914 generate_exception(ctx, EXCP_RI);
5915 } else {
a7812ae4 5916 gen_helper_deret();
6af0bf9c
FB
5917 ctx->bstate = BS_EXCP;
5918 }
5919 break;
4ad40f36
FB
5920 case OPC_WAIT:
5921 opn = "wait";
e189e748 5922 check_insn(env, ctx, ISA_MIPS3 | ISA_MIPS32);
4ad40f36
FB
5923 /* If we get an exception, we want to restart at next instruction */
5924 ctx->pc += 4;
5925 save_cpu_state(ctx, 1);
5926 ctx->pc -= 4;
a7812ae4 5927 gen_helper_wait();
4ad40f36
FB
5928 ctx->bstate = BS_EXCP;
5929 break;
6af0bf9c 5930 default:
29929e34 5931 die:
923617a3 5932 MIPS_INVAL(opn);
6af0bf9c
FB
5933 generate_exception(ctx, EXCP_RI);
5934 return;
5935 }
5936 MIPS_DEBUG("%s %s %d", opn, regnames[rt], rd);
5937}
f1aa6320 5938#endif /* !CONFIG_USER_ONLY */
6af0bf9c 5939
6ea83fed 5940/* CP1 Branches (before delay slot) */
e189e748 5941static void gen_compute_branch1 (CPUState *env, DisasContext *ctx, uint32_t op,
5a5012ec 5942 int32_t cc, int32_t offset)
6ea83fed
FB
5943{
5944 target_ulong btarget;
923617a3 5945 const char *opn = "cp1 cond branch";
a7812ae4 5946 TCGv_i32 t0 = tcg_temp_new_i32();
6ea83fed 5947
e189e748
TS
5948 if (cc != 0)
5949 check_insn(env, ctx, ISA_MIPS4 | ISA_MIPS32);
5950
6ea83fed
FB
5951 btarget = ctx->pc + 4 + offset;
5952
7a387fff
TS
5953 switch (op) {
5954 case OPC_BC1F:
d94536f4
AJ
5955 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
5956 tcg_gen_not_i32(t0, t0);
5957 tcg_gen_andi_i32(t0, t0, 1);
5958 tcg_gen_extu_i32_tl(bcond, t0);
923617a3 5959 opn = "bc1f";
6ea83fed 5960 goto not_likely;
7a387fff 5961 case OPC_BC1FL:
d94536f4
AJ
5962 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
5963 tcg_gen_not_i32(t0, t0);
5964 tcg_gen_andi_i32(t0, t0, 1);
5965 tcg_gen_extu_i32_tl(bcond, t0);
923617a3 5966 opn = "bc1fl";
6ea83fed 5967 goto likely;
7a387fff 5968 case OPC_BC1T:
d94536f4
AJ
5969 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
5970 tcg_gen_andi_i32(t0, t0, 1);
5971 tcg_gen_extu_i32_tl(bcond, t0);
923617a3 5972 opn = "bc1t";
5a5012ec 5973 goto not_likely;
7a387fff 5974 case OPC_BC1TL:
d94536f4
AJ
5975 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
5976 tcg_gen_andi_i32(t0, t0, 1);
5977 tcg_gen_extu_i32_tl(bcond, t0);
923617a3 5978 opn = "bc1tl";
6ea83fed
FB
5979 likely:
5980 ctx->hflags |= MIPS_HFLAG_BL;
5981 break;
5a5012ec 5982 case OPC_BC1FANY2:
a16336e4 5983 {
d94536f4
AJ
5984 TCGv_i32 t1 = tcg_temp_new_i32();
5985 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
5986 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+1));
deb4203d 5987 tcg_gen_nor_i32(t0, t0, t1);
d94536f4 5988 tcg_temp_free_i32(t1);
d94536f4
AJ
5989 tcg_gen_andi_i32(t0, t0, 1);
5990 tcg_gen_extu_i32_tl(bcond, t0);
a16336e4 5991 }
fd4a04eb 5992 opn = "bc1any2f";
5a5012ec
TS
5993 goto not_likely;
5994 case OPC_BC1TANY2:
a16336e4 5995 {
d94536f4
AJ
5996 TCGv_i32 t1 = tcg_temp_new_i32();
5997 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
5998 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+1));
5999 tcg_gen_or_i32(t0, t0, t1);
6000 tcg_temp_free_i32(t1);
6001 tcg_gen_andi_i32(t0, t0, 1);
6002 tcg_gen_extu_i32_tl(bcond, t0);
a16336e4 6003 }
fd4a04eb 6004 opn = "bc1any2t";
5a5012ec
TS
6005 goto not_likely;
6006 case OPC_BC1FANY4:
a16336e4 6007 {
d94536f4
AJ
6008 TCGv_i32 t1 = tcg_temp_new_i32();
6009 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
6010 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+1));
6011 tcg_gen_or_i32(t0, t0, t1);
6012 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+2));
6013 tcg_gen_or_i32(t0, t0, t1);
6014 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+3));
deb4203d 6015 tcg_gen_nor_i32(t0, t0, t1);
d94536f4 6016 tcg_temp_free_i32(t1);
d94536f4
AJ
6017 tcg_gen_andi_i32(t0, t0, 1);
6018 tcg_gen_extu_i32_tl(bcond, t0);
a16336e4 6019 }
fd4a04eb 6020 opn = "bc1any4f";
5a5012ec
TS
6021 goto not_likely;
6022 case OPC_BC1TANY4:
a16336e4 6023 {
d94536f4
AJ
6024 TCGv_i32 t1 = tcg_temp_new_i32();
6025 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
6026 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+1));
6027 tcg_gen_or_i32(t0, t0, t1);
6028 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+2));
6029 tcg_gen_or_i32(t0, t0, t1);
6030 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+3));
6031 tcg_gen_or_i32(t0, t0, t1);
6032 tcg_temp_free_i32(t1);
6033 tcg_gen_andi_i32(t0, t0, 1);
6034 tcg_gen_extu_i32_tl(bcond, t0);
a16336e4 6035 }
fd4a04eb 6036 opn = "bc1any4t";
5a5012ec
TS
6037 not_likely:
6038 ctx->hflags |= MIPS_HFLAG_BC;
5a5012ec
TS
6039 break;
6040 default:
923617a3 6041 MIPS_INVAL(opn);
e397ee33 6042 generate_exception (ctx, EXCP_RI);
6c5c1e20 6043 goto out;
6ea83fed 6044 }
923617a3 6045 MIPS_DEBUG("%s: cond %02x target " TARGET_FMT_lx, opn,
6ea83fed
FB
6046 ctx->hflags, btarget);
6047 ctx->btarget = btarget;
6c5c1e20
TS
6048
6049 out:
a7812ae4 6050 tcg_temp_free_i32(t0);
6ea83fed
FB
6051}
6052
6af0bf9c 6053/* Coprocessor 1 (FPU) */
5a5012ec 6054
5a5012ec
TS
6055#define FOP(func, fmt) (((fmt) << 21) | (func))
6056
bf4120ad
NF
6057enum fopcode {
6058 OPC_ADD_S = FOP(0, FMT_S),
6059 OPC_SUB_S = FOP(1, FMT_S),
6060 OPC_MUL_S = FOP(2, FMT_S),
6061 OPC_DIV_S = FOP(3, FMT_S),
6062 OPC_SQRT_S = FOP(4, FMT_S),
6063 OPC_ABS_S = FOP(5, FMT_S),
6064 OPC_MOV_S = FOP(6, FMT_S),
6065 OPC_NEG_S = FOP(7, FMT_S),
6066 OPC_ROUND_L_S = FOP(8, FMT_S),
6067 OPC_TRUNC_L_S = FOP(9, FMT_S),
6068 OPC_CEIL_L_S = FOP(10, FMT_S),
6069 OPC_FLOOR_L_S = FOP(11, FMT_S),
6070 OPC_ROUND_W_S = FOP(12, FMT_S),
6071 OPC_TRUNC_W_S = FOP(13, FMT_S),
6072 OPC_CEIL_W_S = FOP(14, FMT_S),
6073 OPC_FLOOR_W_S = FOP(15, FMT_S),
6074 OPC_MOVCF_S = FOP(17, FMT_S),
6075 OPC_MOVZ_S = FOP(18, FMT_S),
6076 OPC_MOVN_S = FOP(19, FMT_S),
6077 OPC_RECIP_S = FOP(21, FMT_S),
6078 OPC_RSQRT_S = FOP(22, FMT_S),
6079 OPC_RECIP2_S = FOP(28, FMT_S),
6080 OPC_RECIP1_S = FOP(29, FMT_S),
6081 OPC_RSQRT1_S = FOP(30, FMT_S),
6082 OPC_RSQRT2_S = FOP(31, FMT_S),
6083 OPC_CVT_D_S = FOP(33, FMT_S),
6084 OPC_CVT_W_S = FOP(36, FMT_S),
6085 OPC_CVT_L_S = FOP(37, FMT_S),
6086 OPC_CVT_PS_S = FOP(38, FMT_S),
6087 OPC_CMP_F_S = FOP (48, FMT_S),
6088 OPC_CMP_UN_S = FOP (49, FMT_S),
6089 OPC_CMP_EQ_S = FOP (50, FMT_S),
6090 OPC_CMP_UEQ_S = FOP (51, FMT_S),
6091 OPC_CMP_OLT_S = FOP (52, FMT_S),
6092 OPC_CMP_ULT_S = FOP (53, FMT_S),
6093 OPC_CMP_OLE_S = FOP (54, FMT_S),
6094 OPC_CMP_ULE_S = FOP (55, FMT_S),
6095 OPC_CMP_SF_S = FOP (56, FMT_S),
6096 OPC_CMP_NGLE_S = FOP (57, FMT_S),
6097 OPC_CMP_SEQ_S = FOP (58, FMT_S),
6098 OPC_CMP_NGL_S = FOP (59, FMT_S),
6099 OPC_CMP_LT_S = FOP (60, FMT_S),
6100 OPC_CMP_NGE_S = FOP (61, FMT_S),
6101 OPC_CMP_LE_S = FOP (62, FMT_S),
6102 OPC_CMP_NGT_S = FOP (63, FMT_S),
6103
6104 OPC_ADD_D = FOP(0, FMT_D),
6105 OPC_SUB_D = FOP(1, FMT_D),
6106 OPC_MUL_D = FOP(2, FMT_D),
6107 OPC_DIV_D = FOP(3, FMT_D),
6108 OPC_SQRT_D = FOP(4, FMT_D),
6109 OPC_ABS_D = FOP(5, FMT_D),
6110 OPC_MOV_D = FOP(6, FMT_D),
6111 OPC_NEG_D = FOP(7, FMT_D),
6112 OPC_ROUND_L_D = FOP(8, FMT_D),
6113 OPC_TRUNC_L_D = FOP(9, FMT_D),
6114 OPC_CEIL_L_D = FOP(10, FMT_D),
6115 OPC_FLOOR_L_D = FOP(11, FMT_D),
6116 OPC_ROUND_W_D = FOP(12, FMT_D),
6117 OPC_TRUNC_W_D = FOP(13, FMT_D),
6118 OPC_CEIL_W_D = FOP(14, FMT_D),
6119 OPC_FLOOR_W_D = FOP(15, FMT_D),
6120 OPC_MOVCF_D = FOP(17, FMT_D),
6121 OPC_MOVZ_D = FOP(18, FMT_D),
6122 OPC_MOVN_D = FOP(19, FMT_D),
6123 OPC_RECIP_D = FOP(21, FMT_D),
6124 OPC_RSQRT_D = FOP(22, FMT_D),
6125 OPC_RECIP2_D = FOP(28, FMT_D),
6126 OPC_RECIP1_D = FOP(29, FMT_D),
6127 OPC_RSQRT1_D = FOP(30, FMT_D),
6128 OPC_RSQRT2_D = FOP(31, FMT_D),
6129 OPC_CVT_S_D = FOP(32, FMT_D),
6130 OPC_CVT_W_D = FOP(36, FMT_D),
6131 OPC_CVT_L_D = FOP(37, FMT_D),
6132 OPC_CMP_F_D = FOP (48, FMT_D),
6133 OPC_CMP_UN_D = FOP (49, FMT_D),
6134 OPC_CMP_EQ_D = FOP (50, FMT_D),
6135 OPC_CMP_UEQ_D = FOP (51, FMT_D),
6136 OPC_CMP_OLT_D = FOP (52, FMT_D),
6137 OPC_CMP_ULT_D = FOP (53, FMT_D),
6138 OPC_CMP_OLE_D = FOP (54, FMT_D),
6139 OPC_CMP_ULE_D = FOP (55, FMT_D),
6140 OPC_CMP_SF_D = FOP (56, FMT_D),
6141 OPC_CMP_NGLE_D = FOP (57, FMT_D),
6142 OPC_CMP_SEQ_D = FOP (58, FMT_D),
6143 OPC_CMP_NGL_D = FOP (59, FMT_D),
6144 OPC_CMP_LT_D = FOP (60, FMT_D),
6145 OPC_CMP_NGE_D = FOP (61, FMT_D),
6146 OPC_CMP_LE_D = FOP (62, FMT_D),
6147 OPC_CMP_NGT_D = FOP (63, FMT_D),
6148
6149 OPC_CVT_S_W = FOP(32, FMT_W),
6150 OPC_CVT_D_W = FOP(33, FMT_W),
6151 OPC_CVT_S_L = FOP(32, FMT_L),
6152 OPC_CVT_D_L = FOP(33, FMT_L),
6153 OPC_CVT_PS_PW = FOP(38, FMT_W),
6154
6155 OPC_ADD_PS = FOP(0, FMT_PS),
6156 OPC_SUB_PS = FOP(1, FMT_PS),
6157 OPC_MUL_PS = FOP(2, FMT_PS),
6158 OPC_DIV_PS = FOP(3, FMT_PS),
6159 OPC_ABS_PS = FOP(5, FMT_PS),
6160 OPC_MOV_PS = FOP(6, FMT_PS),
6161 OPC_NEG_PS = FOP(7, FMT_PS),
6162 OPC_MOVCF_PS = FOP(17, FMT_PS),
6163 OPC_MOVZ_PS = FOP(18, FMT_PS),
6164 OPC_MOVN_PS = FOP(19, FMT_PS),
6165 OPC_ADDR_PS = FOP(24, FMT_PS),
6166 OPC_MULR_PS = FOP(26, FMT_PS),
6167 OPC_RECIP2_PS = FOP(28, FMT_PS),
6168 OPC_RECIP1_PS = FOP(29, FMT_PS),
6169 OPC_RSQRT1_PS = FOP(30, FMT_PS),
6170 OPC_RSQRT2_PS = FOP(31, FMT_PS),
6171
6172 OPC_CVT_S_PU = FOP(32, FMT_PS),
6173 OPC_CVT_PW_PS = FOP(36, FMT_PS),
6174 OPC_CVT_S_PL = FOP(40, FMT_PS),
6175 OPC_PLL_PS = FOP(44, FMT_PS),
6176 OPC_PLU_PS = FOP(45, FMT_PS),
6177 OPC_PUL_PS = FOP(46, FMT_PS),
6178 OPC_PUU_PS = FOP(47, FMT_PS),
6179 OPC_CMP_F_PS = FOP (48, FMT_PS),
6180 OPC_CMP_UN_PS = FOP (49, FMT_PS),
6181 OPC_CMP_EQ_PS = FOP (50, FMT_PS),
6182 OPC_CMP_UEQ_PS = FOP (51, FMT_PS),
6183 OPC_CMP_OLT_PS = FOP (52, FMT_PS),
6184 OPC_CMP_ULT_PS = FOP (53, FMT_PS),
6185 OPC_CMP_OLE_PS = FOP (54, FMT_PS),
6186 OPC_CMP_ULE_PS = FOP (55, FMT_PS),
6187 OPC_CMP_SF_PS = FOP (56, FMT_PS),
6188 OPC_CMP_NGLE_PS = FOP (57, FMT_PS),
6189 OPC_CMP_SEQ_PS = FOP (58, FMT_PS),
6190 OPC_CMP_NGL_PS = FOP (59, FMT_PS),
6191 OPC_CMP_LT_PS = FOP (60, FMT_PS),
6192 OPC_CMP_NGE_PS = FOP (61, FMT_PS),
6193 OPC_CMP_LE_PS = FOP (62, FMT_PS),
6194 OPC_CMP_NGT_PS = FOP (63, FMT_PS),
6195};
6196
7a387fff 6197static void gen_cp1 (DisasContext *ctx, uint32_t opc, int rt, int fs)
6ea83fed 6198{
923617a3 6199 const char *opn = "cp1 move";
72c3a3ee 6200 TCGv t0 = tcg_temp_new();
6ea83fed
FB
6201
6202 switch (opc) {
6203 case OPC_MFC1:
b6d96bed 6204 {
a7812ae4 6205 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed
TS
6206
6207 gen_load_fpr32(fp0, fs);
6208 tcg_gen_ext_i32_tl(t0, fp0);
a7812ae4 6209 tcg_temp_free_i32(fp0);
6958549d 6210 }
6c5c1e20 6211 gen_store_gpr(t0, rt);
6ea83fed
FB
6212 opn = "mfc1";
6213 break;
6214 case OPC_MTC1:
6c5c1e20 6215 gen_load_gpr(t0, rt);
b6d96bed 6216 {
a7812ae4 6217 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed
TS
6218
6219 tcg_gen_trunc_tl_i32(fp0, t0);
6220 gen_store_fpr32(fp0, fs);
a7812ae4 6221 tcg_temp_free_i32(fp0);
6958549d 6222 }
6ea83fed
FB
6223 opn = "mtc1";
6224 break;
6225 case OPC_CFC1:
a7812ae4 6226 gen_helper_1i(cfc1, t0, fs);
6c5c1e20 6227 gen_store_gpr(t0, rt);
6ea83fed
FB
6228 opn = "cfc1";
6229 break;
6230 case OPC_CTC1:
6c5c1e20 6231 gen_load_gpr(t0, rt);
a7812ae4 6232 gen_helper_1i(ctc1, t0, fs);
6ea83fed
FB
6233 opn = "ctc1";
6234 break;
72c3a3ee 6235#if defined(TARGET_MIPS64)
9c2149c8 6236 case OPC_DMFC1:
72c3a3ee 6237 gen_load_fpr64(ctx, t0, fs);
6c5c1e20 6238 gen_store_gpr(t0, rt);
5a5012ec
TS
6239 opn = "dmfc1";
6240 break;
9c2149c8 6241 case OPC_DMTC1:
6c5c1e20 6242 gen_load_gpr(t0, rt);
72c3a3ee 6243 gen_store_fpr64(ctx, t0, fs);
5a5012ec
TS
6244 opn = "dmtc1";
6245 break;
72c3a3ee 6246#endif
5a5012ec 6247 case OPC_MFHC1:
b6d96bed 6248 {
a7812ae4 6249 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed
TS
6250
6251 gen_load_fpr32h(fp0, fs);
6252 tcg_gen_ext_i32_tl(t0, fp0);
a7812ae4 6253 tcg_temp_free_i32(fp0);
6958549d 6254 }
6c5c1e20 6255 gen_store_gpr(t0, rt);
5a5012ec
TS
6256 opn = "mfhc1";
6257 break;
6258 case OPC_MTHC1:
6c5c1e20 6259 gen_load_gpr(t0, rt);
b6d96bed 6260 {
a7812ae4 6261 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed
TS
6262
6263 tcg_gen_trunc_tl_i32(fp0, t0);
6264 gen_store_fpr32h(fp0, fs);
a7812ae4 6265 tcg_temp_free_i32(fp0);
6958549d 6266 }
5a5012ec
TS
6267 opn = "mthc1";
6268 break;
6ea83fed 6269 default:
923617a3 6270 MIPS_INVAL(opn);
e397ee33 6271 generate_exception (ctx, EXCP_RI);
6c5c1e20 6272 goto out;
6ea83fed
FB
6273 }
6274 MIPS_DEBUG("%s %s %s", opn, regnames[rt], fregnames[fs]);
6c5c1e20
TS
6275
6276 out:
6277 tcg_temp_free(t0);
6ea83fed
FB
6278}
6279
5a5012ec
TS
6280static void gen_movci (DisasContext *ctx, int rd, int rs, int cc, int tf)
6281{
af58f9ca 6282 int l1;
e214b9bb 6283 TCGCond cond;
af58f9ca
AJ
6284 TCGv_i32 t0;
6285
6286 if (rd == 0) {
6287 /* Treat as NOP. */
6288 return;
6289 }
6ea83fed 6290
e214b9bb 6291 if (tf)
e214b9bb 6292 cond = TCG_COND_EQ;
27848470
TS
6293 else
6294 cond = TCG_COND_NE;
6295
af58f9ca
AJ
6296 l1 = gen_new_label();
6297 t0 = tcg_temp_new_i32();
fa31af0e 6298 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
af58f9ca 6299 tcg_gen_brcondi_i32(cond, t0, 0, l1);
a4e8338d 6300 tcg_temp_free_i32(t0);
af58f9ca
AJ
6301 if (rs == 0) {
6302 tcg_gen_movi_tl(cpu_gpr[rd], 0);
6303 } else {
6304 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
6305 }
e214b9bb 6306 gen_set_label(l1);
5a5012ec
TS
6307}
6308
b6d96bed 6309static inline void gen_movcf_s (int fs, int fd, int cc, int tf)
a16336e4 6310{
a16336e4 6311 int cond;
cbc37b28 6312 TCGv_i32 t0 = tcg_temp_new_i32();
a16336e4
TS
6313 int l1 = gen_new_label();
6314
a16336e4
TS
6315 if (tf)
6316 cond = TCG_COND_EQ;
6317 else
6318 cond = TCG_COND_NE;
6319
fa31af0e 6320 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
cbc37b28
AJ
6321 tcg_gen_brcondi_i32(cond, t0, 0, l1);
6322 gen_load_fpr32(t0, fs);
6323 gen_store_fpr32(t0, fd);
a16336e4 6324 gen_set_label(l1);
cbc37b28 6325 tcg_temp_free_i32(t0);
5a5012ec 6326}
a16336e4 6327
b6d96bed 6328static inline void gen_movcf_d (DisasContext *ctx, int fs, int fd, int cc, int tf)
a16336e4 6329{
a16336e4 6330 int cond;
cbc37b28
AJ
6331 TCGv_i32 t0 = tcg_temp_new_i32();
6332 TCGv_i64 fp0;
a16336e4
TS
6333 int l1 = gen_new_label();
6334
a16336e4
TS
6335 if (tf)
6336 cond = TCG_COND_EQ;
6337 else
6338 cond = TCG_COND_NE;
6339
fa31af0e 6340 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
cbc37b28 6341 tcg_gen_brcondi_i32(cond, t0, 0, l1);
a4e8338d 6342 tcg_temp_free_i32(t0);
11f94258 6343 fp0 = tcg_temp_new_i64();
9bf3eb2c 6344 gen_load_fpr64(ctx, fp0, fs);
9bf3eb2c 6345 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 6346 tcg_temp_free_i64(fp0);
cbc37b28 6347 gen_set_label(l1);
a16336e4
TS
6348}
6349
b6d96bed 6350static inline void gen_movcf_ps (int fs, int fd, int cc, int tf)
a16336e4
TS
6351{
6352 int cond;
cbc37b28 6353 TCGv_i32 t0 = tcg_temp_new_i32();
a16336e4
TS
6354 int l1 = gen_new_label();
6355 int l2 = gen_new_label();
6356
6357 if (tf)
6358 cond = TCG_COND_EQ;
6359 else
6360 cond = TCG_COND_NE;
6361
fa31af0e 6362 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
cbc37b28
AJ
6363 tcg_gen_brcondi_i32(cond, t0, 0, l1);
6364 gen_load_fpr32(t0, fs);
6365 gen_store_fpr32(t0, fd);
a16336e4 6366 gen_set_label(l1);
9bf3eb2c 6367
fa31af0e 6368 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc+1));
cbc37b28
AJ
6369 tcg_gen_brcondi_i32(cond, t0, 0, l2);
6370 gen_load_fpr32h(t0, fs);
6371 gen_store_fpr32h(t0, fd);
52a0e9eb 6372 tcg_temp_free_i32(t0);
a16336e4 6373 gen_set_label(l2);
a16336e4
TS
6374}
6375
6ea83fed 6376
bf4120ad 6377static void gen_farith (DisasContext *ctx, enum fopcode op1,
5e755519 6378 int ft, int fs, int fd, int cc)
6ea83fed 6379{
923617a3 6380 const char *opn = "farith";
6ea83fed
FB
6381 const char *condnames[] = {
6382 "c.f",
6383 "c.un",
6384 "c.eq",
6385 "c.ueq",
6386 "c.olt",
6387 "c.ult",
6388 "c.ole",
6389 "c.ule",
6390 "c.sf",
6391 "c.ngle",
6392 "c.seq",
6393 "c.ngl",
6394 "c.lt",
6395 "c.nge",
6396 "c.le",
6397 "c.ngt",
6398 };
5a1e8ffb
TS
6399 const char *condnames_abs[] = {
6400 "cabs.f",
6401 "cabs.un",
6402 "cabs.eq",
6403 "cabs.ueq",
6404 "cabs.olt",
6405 "cabs.ult",
6406 "cabs.ole",
6407 "cabs.ule",
6408 "cabs.sf",
6409 "cabs.ngle",
6410 "cabs.seq",
6411 "cabs.ngl",
6412 "cabs.lt",
6413 "cabs.nge",
6414 "cabs.le",
6415 "cabs.ngt",
6416 };
6417 enum { BINOP, CMPOP, OTHEROP } optype = OTHEROP;
7a387fff
TS
6418 uint32_t func = ctx->opcode & 0x3f;
6419
bf4120ad
NF
6420 switch (op1) {
6421 case OPC_ADD_S:
b6d96bed 6422 {
a7812ae4
PB
6423 TCGv_i32 fp0 = tcg_temp_new_i32();
6424 TCGv_i32 fp1 = tcg_temp_new_i32();
b6d96bed
TS
6425
6426 gen_load_fpr32(fp0, fs);
6427 gen_load_fpr32(fp1, ft);
a7812ae4
PB
6428 gen_helper_float_add_s(fp0, fp0, fp1);
6429 tcg_temp_free_i32(fp1);
b6d96bed 6430 gen_store_fpr32(fp0, fd);
a7812ae4 6431 tcg_temp_free_i32(fp0);
b6d96bed 6432 }
5a5012ec 6433 opn = "add.s";
5a1e8ffb 6434 optype = BINOP;
5a5012ec 6435 break;
bf4120ad 6436 case OPC_SUB_S:
b6d96bed 6437 {
a7812ae4
PB
6438 TCGv_i32 fp0 = tcg_temp_new_i32();
6439 TCGv_i32 fp1 = tcg_temp_new_i32();
b6d96bed
TS
6440
6441 gen_load_fpr32(fp0, fs);
6442 gen_load_fpr32(fp1, ft);
a7812ae4
PB
6443 gen_helper_float_sub_s(fp0, fp0, fp1);
6444 tcg_temp_free_i32(fp1);
b6d96bed 6445 gen_store_fpr32(fp0, fd);
a7812ae4 6446 tcg_temp_free_i32(fp0);
b6d96bed 6447 }
5a5012ec 6448 opn = "sub.s";
5a1e8ffb 6449 optype = BINOP;
5a5012ec 6450 break;
bf4120ad 6451 case OPC_MUL_S:
b6d96bed 6452 {
a7812ae4
PB
6453 TCGv_i32 fp0 = tcg_temp_new_i32();
6454 TCGv_i32 fp1 = tcg_temp_new_i32();
b6d96bed
TS
6455
6456 gen_load_fpr32(fp0, fs);
6457 gen_load_fpr32(fp1, ft);
a7812ae4
PB
6458 gen_helper_float_mul_s(fp0, fp0, fp1);
6459 tcg_temp_free_i32(fp1);
b6d96bed 6460 gen_store_fpr32(fp0, fd);
a7812ae4 6461 tcg_temp_free_i32(fp0);
b6d96bed 6462 }
5a5012ec 6463 opn = "mul.s";
5a1e8ffb 6464 optype = BINOP;
5a5012ec 6465 break;
bf4120ad 6466 case OPC_DIV_S:
b6d96bed 6467 {
a7812ae4
PB
6468 TCGv_i32 fp0 = tcg_temp_new_i32();
6469 TCGv_i32 fp1 = tcg_temp_new_i32();
b6d96bed
TS
6470
6471 gen_load_fpr32(fp0, fs);
6472 gen_load_fpr32(fp1, ft);
a7812ae4
PB
6473 gen_helper_float_div_s(fp0, fp0, fp1);
6474 tcg_temp_free_i32(fp1);
b6d96bed 6475 gen_store_fpr32(fp0, fd);
a7812ae4 6476 tcg_temp_free_i32(fp0);
b6d96bed 6477 }
5a5012ec 6478 opn = "div.s";
5a1e8ffb 6479 optype = BINOP;
5a5012ec 6480 break;
bf4120ad 6481 case OPC_SQRT_S:
b6d96bed 6482 {
a7812ae4 6483 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed
TS
6484
6485 gen_load_fpr32(fp0, fs);
a7812ae4 6486 gen_helper_float_sqrt_s(fp0, fp0);
b6d96bed 6487 gen_store_fpr32(fp0, fd);
a7812ae4 6488 tcg_temp_free_i32(fp0);
b6d96bed 6489 }
5a5012ec
TS
6490 opn = "sqrt.s";
6491 break;
bf4120ad 6492 case OPC_ABS_S:
b6d96bed 6493 {
a7812ae4 6494 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed
TS
6495
6496 gen_load_fpr32(fp0, fs);
a7812ae4 6497 gen_helper_float_abs_s(fp0, fp0);
b6d96bed 6498 gen_store_fpr32(fp0, fd);
a7812ae4 6499 tcg_temp_free_i32(fp0);
b6d96bed 6500 }
5a5012ec
TS
6501 opn = "abs.s";
6502 break;
bf4120ad 6503 case OPC_MOV_S:
b6d96bed 6504 {
a7812ae4 6505 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed
TS
6506
6507 gen_load_fpr32(fp0, fs);
6508 gen_store_fpr32(fp0, fd);
a7812ae4 6509 tcg_temp_free_i32(fp0);
b6d96bed 6510 }
5a5012ec
TS
6511 opn = "mov.s";
6512 break;
bf4120ad 6513 case OPC_NEG_S:
b6d96bed 6514 {
a7812ae4 6515 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed
TS
6516
6517 gen_load_fpr32(fp0, fs);
a7812ae4 6518 gen_helper_float_chs_s(fp0, fp0);
b6d96bed 6519 gen_store_fpr32(fp0, fd);
a7812ae4 6520 tcg_temp_free_i32(fp0);
b6d96bed 6521 }
5a5012ec
TS
6522 opn = "neg.s";
6523 break;
bf4120ad 6524 case OPC_ROUND_L_S:
5e755519 6525 check_cp1_64bitmode(ctx);
b6d96bed 6526 {
a7812ae4
PB
6527 TCGv_i32 fp32 = tcg_temp_new_i32();
6528 TCGv_i64 fp64 = tcg_temp_new_i64();
b6d96bed
TS
6529
6530 gen_load_fpr32(fp32, fs);
a7812ae4
PB
6531 gen_helper_float_roundl_s(fp64, fp32);
6532 tcg_temp_free_i32(fp32);
b6d96bed 6533 gen_store_fpr64(ctx, fp64, fd);
a7812ae4 6534 tcg_temp_free_i64(fp64);
b6d96bed 6535 }
5a5012ec
TS
6536 opn = "round.l.s";
6537 break;
bf4120ad 6538 case OPC_TRUNC_L_S:
5e755519 6539 check_cp1_64bitmode(ctx);
b6d96bed 6540 {
a7812ae4
PB
6541 TCGv_i32 fp32 = tcg_temp_new_i32();
6542 TCGv_i64 fp64 = tcg_temp_new_i64();
b6d96bed
TS
6543
6544 gen_load_fpr32(fp32, fs);
a7812ae4
PB
6545 gen_helper_float_truncl_s(fp64, fp32);
6546 tcg_temp_free_i32(fp32);
b6d96bed 6547 gen_store_fpr64(ctx, fp64, fd);
a7812ae4 6548 tcg_temp_free_i64(fp64);
b6d96bed 6549 }
5a5012ec
TS
6550 opn = "trunc.l.s";
6551 break;
bf4120ad 6552 case OPC_CEIL_L_S:
5e755519 6553 check_cp1_64bitmode(ctx);
b6d96bed 6554 {
a7812ae4
PB
6555 TCGv_i32 fp32 = tcg_temp_new_i32();
6556 TCGv_i64 fp64 = tcg_temp_new_i64();
b6d96bed
TS
6557
6558 gen_load_fpr32(fp32, fs);
a7812ae4
PB
6559 gen_helper_float_ceill_s(fp64, fp32);
6560 tcg_temp_free_i32(fp32);
b6d96bed 6561 gen_store_fpr64(ctx, fp64, fd);
a7812ae4 6562 tcg_temp_free_i64(fp64);
b6d96bed 6563 }
5a5012ec
TS
6564 opn = "ceil.l.s";
6565 break;
bf4120ad 6566 case OPC_FLOOR_L_S:
5e755519 6567 check_cp1_64bitmode(ctx);
b6d96bed 6568 {
a7812ae4
PB
6569 TCGv_i32 fp32 = tcg_temp_new_i32();
6570 TCGv_i64 fp64 = tcg_temp_new_i64();
b6d96bed
TS
6571
6572 gen_load_fpr32(fp32, fs);
a7812ae4
PB
6573 gen_helper_float_floorl_s(fp64, fp32);
6574 tcg_temp_free_i32(fp32);
b6d96bed 6575 gen_store_fpr64(ctx, fp64, fd);
a7812ae4 6576 tcg_temp_free_i64(fp64);
b6d96bed 6577 }
5a5012ec
TS
6578 opn = "floor.l.s";
6579 break;
bf4120ad 6580 case OPC_ROUND_W_S:
b6d96bed 6581 {
a7812ae4 6582 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed
TS
6583
6584 gen_load_fpr32(fp0, fs);
a7812ae4 6585 gen_helper_float_roundw_s(fp0, fp0);
b6d96bed 6586 gen_store_fpr32(fp0, fd);
a7812ae4 6587 tcg_temp_free_i32(fp0);
b6d96bed 6588 }
5a5012ec
TS
6589 opn = "round.w.s";
6590 break;
bf4120ad 6591 case OPC_TRUNC_W_S:
b6d96bed 6592 {
a7812ae4 6593 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed
TS
6594
6595 gen_load_fpr32(fp0, fs);
a7812ae4 6596 gen_helper_float_truncw_s(fp0, fp0);
b6d96bed 6597 gen_store_fpr32(fp0, fd);
a7812ae4 6598 tcg_temp_free_i32(fp0);
b6d96bed 6599 }
5a5012ec
TS
6600 opn = "trunc.w.s";
6601 break;
bf4120ad 6602 case OPC_CEIL_W_S:
b6d96bed 6603 {
a7812ae4 6604 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed
TS
6605
6606 gen_load_fpr32(fp0, fs);
a7812ae4 6607 gen_helper_float_ceilw_s(fp0, fp0);
b6d96bed 6608 gen_store_fpr32(fp0, fd);
a7812ae4 6609 tcg_temp_free_i32(fp0);
b6d96bed 6610 }
5a5012ec
TS
6611 opn = "ceil.w.s";
6612 break;
bf4120ad 6613 case OPC_FLOOR_W_S:
b6d96bed 6614 {
a7812ae4 6615 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed
TS
6616
6617 gen_load_fpr32(fp0, fs);
a7812ae4 6618 gen_helper_float_floorw_s(fp0, fp0);
b6d96bed 6619 gen_store_fpr32(fp0, fd);
a7812ae4 6620 tcg_temp_free_i32(fp0);
b6d96bed 6621 }
5a5012ec
TS
6622 opn = "floor.w.s";
6623 break;
bf4120ad 6624 case OPC_MOVCF_S:
b6d96bed 6625 gen_movcf_s(fs, fd, (ft >> 2) & 0x7, ft & 0x1);
5a5012ec
TS
6626 opn = "movcf.s";
6627 break;
bf4120ad 6628 case OPC_MOVZ_S:
a16336e4
TS
6629 {
6630 int l1 = gen_new_label();
c9297f4d 6631 TCGv_i32 fp0;
a16336e4 6632
c9297f4d
AJ
6633 if (ft != 0) {
6634 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[ft], 0, l1);
6635 }
6636 fp0 = tcg_temp_new_i32();
b6d96bed
TS
6637 gen_load_fpr32(fp0, fs);
6638 gen_store_fpr32(fp0, fd);
a7812ae4 6639 tcg_temp_free_i32(fp0);
a16336e4
TS
6640 gen_set_label(l1);
6641 }
5a5012ec
TS
6642 opn = "movz.s";
6643 break;
bf4120ad 6644 case OPC_MOVN_S:
a16336e4
TS
6645 {
6646 int l1 = gen_new_label();
c9297f4d
AJ
6647 TCGv_i32 fp0;
6648
6649 if (ft != 0) {
6650 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[ft], 0, l1);
6651 fp0 = tcg_temp_new_i32();
6652 gen_load_fpr32(fp0, fs);
6653 gen_store_fpr32(fp0, fd);
6654 tcg_temp_free_i32(fp0);
6655 gen_set_label(l1);
6656 }
a16336e4 6657 }
5a5012ec
TS
6658 opn = "movn.s";
6659 break;
bf4120ad 6660 case OPC_RECIP_S:
b8aa4598 6661 check_cop1x(ctx);
b6d96bed 6662 {
a7812ae4 6663 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed
TS
6664
6665 gen_load_fpr32(fp0, fs);
a7812ae4 6666 gen_helper_float_recip_s(fp0, fp0);
b6d96bed 6667 gen_store_fpr32(fp0, fd);
a7812ae4 6668 tcg_temp_free_i32(fp0);
b6d96bed 6669 }
57fa1fb3
TS
6670 opn = "recip.s";
6671 break;
bf4120ad 6672 case OPC_RSQRT_S:
b8aa4598 6673 check_cop1x(ctx);
b6d96bed 6674 {
a7812ae4 6675 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed
TS
6676
6677 gen_load_fpr32(fp0, fs);
a7812ae4 6678 gen_helper_float_rsqrt_s(fp0, fp0);
b6d96bed 6679 gen_store_fpr32(fp0, fd);
a7812ae4 6680 tcg_temp_free_i32(fp0);
b6d96bed 6681 }
57fa1fb3
TS
6682 opn = "rsqrt.s";
6683 break;
bf4120ad 6684 case OPC_RECIP2_S:
5e755519 6685 check_cp1_64bitmode(ctx);
b6d96bed 6686 {
a7812ae4
PB
6687 TCGv_i32 fp0 = tcg_temp_new_i32();
6688 TCGv_i32 fp1 = tcg_temp_new_i32();
b6d96bed
TS
6689
6690 gen_load_fpr32(fp0, fs);
6691 gen_load_fpr32(fp1, fd);
a7812ae4
PB
6692 gen_helper_float_recip2_s(fp0, fp0, fp1);
6693 tcg_temp_free_i32(fp1);
b6d96bed 6694 gen_store_fpr32(fp0, fd);
a7812ae4 6695 tcg_temp_free_i32(fp0);
b6d96bed 6696 }
57fa1fb3
TS
6697 opn = "recip2.s";
6698 break;
bf4120ad 6699 case OPC_RECIP1_S:
5e755519 6700 check_cp1_64bitmode(ctx);
b6d96bed 6701 {
a7812ae4 6702 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed
TS
6703
6704 gen_load_fpr32(fp0, fs);
a7812ae4 6705 gen_helper_float_recip1_s(fp0, fp0);
b6d96bed 6706 gen_store_fpr32(fp0, fd);
a7812ae4 6707 tcg_temp_free_i32(fp0);
b6d96bed 6708 }
57fa1fb3
TS
6709 opn = "recip1.s";
6710 break;
bf4120ad 6711 case OPC_RSQRT1_S:
5e755519 6712 check_cp1_64bitmode(ctx);
b6d96bed 6713 {
a7812ae4 6714 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed
TS
6715
6716 gen_load_fpr32(fp0, fs);
a7812ae4 6717 gen_helper_float_rsqrt1_s(fp0, fp0);
b6d96bed 6718 gen_store_fpr32(fp0, fd);
a7812ae4 6719 tcg_temp_free_i32(fp0);
b6d96bed 6720 }
57fa1fb3
TS
6721 opn = "rsqrt1.s";
6722 break;
bf4120ad 6723 case OPC_RSQRT2_S:
5e755519 6724 check_cp1_64bitmode(ctx);
b6d96bed 6725 {
a7812ae4
PB
6726 TCGv_i32 fp0 = tcg_temp_new_i32();
6727 TCGv_i32 fp1 = tcg_temp_new_i32();
b6d96bed
TS
6728
6729 gen_load_fpr32(fp0, fs);
6730 gen_load_fpr32(fp1, ft);
a7812ae4
PB
6731 gen_helper_float_rsqrt2_s(fp0, fp0, fp1);
6732 tcg_temp_free_i32(fp1);
b6d96bed 6733 gen_store_fpr32(fp0, fd);
a7812ae4 6734 tcg_temp_free_i32(fp0);
b6d96bed 6735 }
57fa1fb3
TS
6736 opn = "rsqrt2.s";
6737 break;
bf4120ad 6738 case OPC_CVT_D_S:
5e755519 6739 check_cp1_registers(ctx, fd);
b6d96bed 6740 {
a7812ae4
PB
6741 TCGv_i32 fp32 = tcg_temp_new_i32();
6742 TCGv_i64 fp64 = tcg_temp_new_i64();
b6d96bed
TS
6743
6744 gen_load_fpr32(fp32, fs);
a7812ae4
PB
6745 gen_helper_float_cvtd_s(fp64, fp32);
6746 tcg_temp_free_i32(fp32);
b6d96bed 6747 gen_store_fpr64(ctx, fp64, fd);
a7812ae4 6748 tcg_temp_free_i64(fp64);
b6d96bed 6749 }
5a5012ec
TS
6750 opn = "cvt.d.s";
6751 break;
bf4120ad 6752 case OPC_CVT_W_S:
b6d96bed 6753 {
a7812ae4 6754 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed
TS
6755
6756 gen_load_fpr32(fp0, fs);
a7812ae4 6757 gen_helper_float_cvtw_s(fp0, fp0);
b6d96bed 6758 gen_store_fpr32(fp0, fd);
a7812ae4 6759 tcg_temp_free_i32(fp0);
b6d96bed 6760 }
5a5012ec
TS
6761 opn = "cvt.w.s";
6762 break;
bf4120ad 6763 case OPC_CVT_L_S:
5e755519 6764 check_cp1_64bitmode(ctx);
b6d96bed 6765 {
a7812ae4
PB
6766 TCGv_i32 fp32 = tcg_temp_new_i32();
6767 TCGv_i64 fp64 = tcg_temp_new_i64();
b6d96bed
TS
6768
6769 gen_load_fpr32(fp32, fs);
a7812ae4
PB
6770 gen_helper_float_cvtl_s(fp64, fp32);
6771 tcg_temp_free_i32(fp32);
b6d96bed 6772 gen_store_fpr64(ctx, fp64, fd);
a7812ae4 6773 tcg_temp_free_i64(fp64);
b6d96bed 6774 }
5a5012ec
TS
6775 opn = "cvt.l.s";
6776 break;
bf4120ad 6777 case OPC_CVT_PS_S:
5e755519 6778 check_cp1_64bitmode(ctx);
b6d96bed 6779 {
a7812ae4
PB
6780 TCGv_i64 fp64 = tcg_temp_new_i64();
6781 TCGv_i32 fp32_0 = tcg_temp_new_i32();
6782 TCGv_i32 fp32_1 = tcg_temp_new_i32();
b6d96bed
TS
6783
6784 gen_load_fpr32(fp32_0, fs);
6785 gen_load_fpr32(fp32_1, ft);
36aa55dc 6786 tcg_gen_concat_i32_i64(fp64, fp32_0, fp32_1);
a7812ae4
PB
6787 tcg_temp_free_i32(fp32_1);
6788 tcg_temp_free_i32(fp32_0);
36aa55dc 6789 gen_store_fpr64(ctx, fp64, fd);
a7812ae4 6790 tcg_temp_free_i64(fp64);
b6d96bed 6791 }
5a5012ec
TS
6792 opn = "cvt.ps.s";
6793 break;
bf4120ad
NF
6794 case OPC_CMP_F_S:
6795 case OPC_CMP_UN_S:
6796 case OPC_CMP_EQ_S:
6797 case OPC_CMP_UEQ_S:
6798 case OPC_CMP_OLT_S:
6799 case OPC_CMP_ULT_S:
6800 case OPC_CMP_OLE_S:
6801 case OPC_CMP_ULE_S:
6802 case OPC_CMP_SF_S:
6803 case OPC_CMP_NGLE_S:
6804 case OPC_CMP_SEQ_S:
6805 case OPC_CMP_NGL_S:
6806 case OPC_CMP_LT_S:
6807 case OPC_CMP_NGE_S:
6808 case OPC_CMP_LE_S:
6809 case OPC_CMP_NGT_S:
8153667c
NF
6810 if (ctx->opcode & (1 << 6)) {
6811 gen_cmpabs_s(ctx, func-48, ft, fs, cc);
6812 opn = condnames_abs[func-48];
6813 } else {
6814 gen_cmp_s(ctx, func-48, ft, fs, cc);
6815 opn = condnames[func-48];
5a1e8ffb 6816 }
5a5012ec 6817 break;
bf4120ad 6818 case OPC_ADD_D:
5e755519 6819 check_cp1_registers(ctx, fs | ft | fd);
b6d96bed 6820 {
a7812ae4
PB
6821 TCGv_i64 fp0 = tcg_temp_new_i64();
6822 TCGv_i64 fp1 = tcg_temp_new_i64();
b6d96bed
TS
6823
6824 gen_load_fpr64(ctx, fp0, fs);
6825 gen_load_fpr64(ctx, fp1, ft);
a7812ae4
PB
6826 gen_helper_float_add_d(fp0, fp0, fp1);
6827 tcg_temp_free_i64(fp1);
b6d96bed 6828 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 6829 tcg_temp_free_i64(fp0);
b6d96bed 6830 }
6ea83fed 6831 opn = "add.d";
5a1e8ffb 6832 optype = BINOP;
6ea83fed 6833 break;
bf4120ad 6834 case OPC_SUB_D:
5e755519 6835 check_cp1_registers(ctx, fs | ft | fd);
b6d96bed 6836 {
a7812ae4
PB
6837 TCGv_i64 fp0 = tcg_temp_new_i64();
6838 TCGv_i64 fp1 = tcg_temp_new_i64();
b6d96bed
TS
6839
6840 gen_load_fpr64(ctx, fp0, fs);
6841 gen_load_fpr64(ctx, fp1, ft);
a7812ae4
PB
6842 gen_helper_float_sub_d(fp0, fp0, fp1);
6843 tcg_temp_free_i64(fp1);
b6d96bed 6844 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 6845 tcg_temp_free_i64(fp0);
b6d96bed 6846 }
6ea83fed 6847 opn = "sub.d";
5a1e8ffb 6848 optype = BINOP;
6ea83fed 6849 break;
bf4120ad 6850 case OPC_MUL_D:
5e755519 6851 check_cp1_registers(ctx, fs | ft | fd);
b6d96bed 6852 {
a7812ae4
PB
6853 TCGv_i64 fp0 = tcg_temp_new_i64();
6854 TCGv_i64 fp1 = tcg_temp_new_i64();
b6d96bed
TS
6855
6856 gen_load_fpr64(ctx, fp0, fs);
6857 gen_load_fpr64(ctx, fp1, ft);
a7812ae4
PB
6858 gen_helper_float_mul_d(fp0, fp0, fp1);
6859 tcg_temp_free_i64(fp1);
b6d96bed 6860 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 6861 tcg_temp_free_i64(fp0);
b6d96bed 6862 }
6ea83fed 6863 opn = "mul.d";
5a1e8ffb 6864 optype = BINOP;
6ea83fed 6865 break;
bf4120ad 6866 case OPC_DIV_D:
5e755519 6867 check_cp1_registers(ctx, fs | ft | fd);
b6d96bed 6868 {
a7812ae4
PB
6869 TCGv_i64 fp0 = tcg_temp_new_i64();
6870 TCGv_i64 fp1 = tcg_temp_new_i64();
b6d96bed
TS
6871
6872 gen_load_fpr64(ctx, fp0, fs);
6873 gen_load_fpr64(ctx, fp1, ft);
a7812ae4
PB
6874 gen_helper_float_div_d(fp0, fp0, fp1);
6875 tcg_temp_free_i64(fp1);
b6d96bed 6876 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 6877 tcg_temp_free_i64(fp0);
b6d96bed 6878 }
6ea83fed 6879 opn = "div.d";
5a1e8ffb 6880 optype = BINOP;
6ea83fed 6881 break;
bf4120ad 6882 case OPC_SQRT_D:
5e755519 6883 check_cp1_registers(ctx, fs | fd);
b6d96bed 6884 {
a7812ae4 6885 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
6886
6887 gen_load_fpr64(ctx, fp0, fs);
a7812ae4 6888 gen_helper_float_sqrt_d(fp0, fp0);
b6d96bed 6889 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 6890 tcg_temp_free_i64(fp0);
b6d96bed 6891 }
6ea83fed
FB
6892 opn = "sqrt.d";
6893 break;
bf4120ad 6894 case OPC_ABS_D:
5e755519 6895 check_cp1_registers(ctx, fs | fd);
b6d96bed 6896 {
a7812ae4 6897 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
6898
6899 gen_load_fpr64(ctx, fp0, fs);
a7812ae4 6900 gen_helper_float_abs_d(fp0, fp0);
b6d96bed 6901 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 6902 tcg_temp_free_i64(fp0);
b6d96bed 6903 }
6ea83fed
FB
6904 opn = "abs.d";
6905 break;
bf4120ad 6906 case OPC_MOV_D:
5e755519 6907 check_cp1_registers(ctx, fs | fd);
b6d96bed 6908 {
a7812ae4 6909 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
6910
6911 gen_load_fpr64(ctx, fp0, fs);
6912 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 6913 tcg_temp_free_i64(fp0);
b6d96bed 6914 }
6ea83fed
FB
6915 opn = "mov.d";
6916 break;
bf4120ad 6917 case OPC_NEG_D:
5e755519 6918 check_cp1_registers(ctx, fs | fd);
b6d96bed 6919 {
a7812ae4 6920 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
6921
6922 gen_load_fpr64(ctx, fp0, fs);
a7812ae4 6923 gen_helper_float_chs_d(fp0, fp0);
b6d96bed 6924 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 6925 tcg_temp_free_i64(fp0);
b6d96bed 6926 }
6ea83fed
FB
6927 opn = "neg.d";
6928 break;
bf4120ad 6929 case OPC_ROUND_L_D:
5e755519 6930 check_cp1_64bitmode(ctx);
b6d96bed 6931 {
a7812ae4 6932 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
6933
6934 gen_load_fpr64(ctx, fp0, fs);
a7812ae4 6935 gen_helper_float_roundl_d(fp0, fp0);
b6d96bed 6936 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 6937 tcg_temp_free_i64(fp0);
b6d96bed 6938 }
5a5012ec
TS
6939 opn = "round.l.d";
6940 break;
bf4120ad 6941 case OPC_TRUNC_L_D:
5e755519 6942 check_cp1_64bitmode(ctx);
b6d96bed 6943 {
a7812ae4 6944 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
6945
6946 gen_load_fpr64(ctx, fp0, fs);
a7812ae4 6947 gen_helper_float_truncl_d(fp0, fp0);
b6d96bed 6948 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 6949 tcg_temp_free_i64(fp0);
b6d96bed 6950 }
5a5012ec
TS
6951 opn = "trunc.l.d";
6952 break;
bf4120ad 6953 case OPC_CEIL_L_D:
5e755519 6954 check_cp1_64bitmode(ctx);
b6d96bed 6955 {
a7812ae4 6956 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
6957
6958 gen_load_fpr64(ctx, fp0, fs);
a7812ae4 6959 gen_helper_float_ceill_d(fp0, fp0);
b6d96bed 6960 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 6961 tcg_temp_free_i64(fp0);
b6d96bed 6962 }
5a5012ec
TS
6963 opn = "ceil.l.d";
6964 break;
bf4120ad 6965 case OPC_FLOOR_L_D:
5e755519 6966 check_cp1_64bitmode(ctx);
b6d96bed 6967 {
a7812ae4 6968 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
6969
6970 gen_load_fpr64(ctx, fp0, fs);
a7812ae4 6971 gen_helper_float_floorl_d(fp0, fp0);
b6d96bed 6972 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 6973 tcg_temp_free_i64(fp0);
b6d96bed 6974 }
5a5012ec
TS
6975 opn = "floor.l.d";
6976 break;
bf4120ad 6977 case OPC_ROUND_W_D:
5e755519 6978 check_cp1_registers(ctx, fs);
b6d96bed 6979 {
a7812ae4
PB
6980 TCGv_i32 fp32 = tcg_temp_new_i32();
6981 TCGv_i64 fp64 = tcg_temp_new_i64();
b6d96bed
TS
6982
6983 gen_load_fpr64(ctx, fp64, fs);
a7812ae4
PB
6984 gen_helper_float_roundw_d(fp32, fp64);
6985 tcg_temp_free_i64(fp64);
b6d96bed 6986 gen_store_fpr32(fp32, fd);
a7812ae4 6987 tcg_temp_free_i32(fp32);
b6d96bed 6988 }
6ea83fed
FB
6989 opn = "round.w.d";
6990 break;
bf4120ad 6991 case OPC_TRUNC_W_D:
5e755519 6992 check_cp1_registers(ctx, fs);
b6d96bed 6993 {
a7812ae4
PB
6994 TCGv_i32 fp32 = tcg_temp_new_i32();
6995 TCGv_i64 fp64 = tcg_temp_new_i64();
b6d96bed
TS
6996
6997 gen_load_fpr64(ctx, fp64, fs);
a7812ae4
PB
6998 gen_helper_float_truncw_d(fp32, fp64);
6999 tcg_temp_free_i64(fp64);
b6d96bed 7000 gen_store_fpr32(fp32, fd);
a7812ae4 7001 tcg_temp_free_i32(fp32);
b6d96bed 7002 }
6ea83fed
FB
7003 opn = "trunc.w.d";
7004 break;
bf4120ad 7005 case OPC_CEIL_W_D:
5e755519 7006 check_cp1_registers(ctx, fs);
b6d96bed 7007 {
a7812ae4
PB
7008 TCGv_i32 fp32 = tcg_temp_new_i32();
7009 TCGv_i64 fp64 = tcg_temp_new_i64();
b6d96bed
TS
7010
7011 gen_load_fpr64(ctx, fp64, fs);
a7812ae4
PB
7012 gen_helper_float_ceilw_d(fp32, fp64);
7013 tcg_temp_free_i64(fp64);
b6d96bed 7014 gen_store_fpr32(fp32, fd);
a7812ae4 7015 tcg_temp_free_i32(fp32);
b6d96bed 7016 }
6ea83fed
FB
7017 opn = "ceil.w.d";
7018 break;
bf4120ad 7019 case OPC_FLOOR_W_D:
5e755519 7020 check_cp1_registers(ctx, fs);
b6d96bed 7021 {
a7812ae4
PB
7022 TCGv_i32 fp32 = tcg_temp_new_i32();
7023 TCGv_i64 fp64 = tcg_temp_new_i64();
b6d96bed
TS
7024
7025 gen_load_fpr64(ctx, fp64, fs);
a7812ae4
PB
7026 gen_helper_float_floorw_d(fp32, fp64);
7027 tcg_temp_free_i64(fp64);
b6d96bed 7028 gen_store_fpr32(fp32, fd);
a7812ae4 7029 tcg_temp_free_i32(fp32);
b6d96bed 7030 }
7a387fff 7031 opn = "floor.w.d";
6ea83fed 7032 break;
bf4120ad 7033 case OPC_MOVCF_D:
b6d96bed 7034 gen_movcf_d(ctx, fs, fd, (ft >> 2) & 0x7, ft & 0x1);
5a5012ec 7035 opn = "movcf.d";
dd016883 7036 break;
bf4120ad 7037 case OPC_MOVZ_D:
a16336e4
TS
7038 {
7039 int l1 = gen_new_label();
c9297f4d 7040 TCGv_i64 fp0;
a16336e4 7041
c9297f4d
AJ
7042 if (ft != 0) {
7043 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[ft], 0, l1);
7044 }
7045 fp0 = tcg_temp_new_i64();
b6d96bed
TS
7046 gen_load_fpr64(ctx, fp0, fs);
7047 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 7048 tcg_temp_free_i64(fp0);
a16336e4
TS
7049 gen_set_label(l1);
7050 }
5a5012ec
TS
7051 opn = "movz.d";
7052 break;
bf4120ad 7053 case OPC_MOVN_D:
a16336e4
TS
7054 {
7055 int l1 = gen_new_label();
c9297f4d
AJ
7056 TCGv_i64 fp0;
7057
7058 if (ft != 0) {
7059 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[ft], 0, l1);
7060 fp0 = tcg_temp_new_i64();
7061 gen_load_fpr64(ctx, fp0, fs);
7062 gen_store_fpr64(ctx, fp0, fd);
7063 tcg_temp_free_i64(fp0);
7064 gen_set_label(l1);
7065 }
a16336e4 7066 }
5a5012ec 7067 opn = "movn.d";
6ea83fed 7068 break;
bf4120ad 7069 case OPC_RECIP_D:
b8aa4598 7070 check_cp1_64bitmode(ctx);
b6d96bed 7071 {
a7812ae4 7072 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
7073
7074 gen_load_fpr64(ctx, fp0, fs);
a7812ae4 7075 gen_helper_float_recip_d(fp0, fp0);
b6d96bed 7076 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 7077 tcg_temp_free_i64(fp0);
b6d96bed 7078 }
57fa1fb3
TS
7079 opn = "recip.d";
7080 break;
bf4120ad 7081 case OPC_RSQRT_D:
b8aa4598 7082 check_cp1_64bitmode(ctx);
b6d96bed 7083 {
a7812ae4 7084 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
7085
7086 gen_load_fpr64(ctx, fp0, fs);
a7812ae4 7087 gen_helper_float_rsqrt_d(fp0, fp0);
b6d96bed 7088 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 7089 tcg_temp_free_i64(fp0);
b6d96bed 7090 }
57fa1fb3
TS
7091 opn = "rsqrt.d";
7092 break;
bf4120ad 7093 case OPC_RECIP2_D:
5e755519 7094 check_cp1_64bitmode(ctx);
b6d96bed 7095 {
a7812ae4
PB
7096 TCGv_i64 fp0 = tcg_temp_new_i64();
7097 TCGv_i64 fp1 = tcg_temp_new_i64();
b6d96bed
TS
7098
7099 gen_load_fpr64(ctx, fp0, fs);
7100 gen_load_fpr64(ctx, fp1, ft);
a7812ae4
PB
7101 gen_helper_float_recip2_d(fp0, fp0, fp1);
7102 tcg_temp_free_i64(fp1);
b6d96bed 7103 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 7104 tcg_temp_free_i64(fp0);
b6d96bed 7105 }
57fa1fb3
TS
7106 opn = "recip2.d";
7107 break;
bf4120ad 7108 case OPC_RECIP1_D:
5e755519 7109 check_cp1_64bitmode(ctx);
b6d96bed 7110 {
a7812ae4 7111 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
7112
7113 gen_load_fpr64(ctx, fp0, fs);
a7812ae4 7114 gen_helper_float_recip1_d(fp0, fp0);
b6d96bed 7115 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 7116 tcg_temp_free_i64(fp0);
b6d96bed 7117 }
57fa1fb3
TS
7118 opn = "recip1.d";
7119 break;
bf4120ad 7120 case OPC_RSQRT1_D:
5e755519 7121 check_cp1_64bitmode(ctx);
b6d96bed 7122 {
a7812ae4 7123 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
7124
7125 gen_load_fpr64(ctx, fp0, fs);
a7812ae4 7126 gen_helper_float_rsqrt1_d(fp0, fp0);
b6d96bed 7127 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 7128 tcg_temp_free_i64(fp0);
b6d96bed 7129 }
57fa1fb3
TS
7130 opn = "rsqrt1.d";
7131 break;
bf4120ad 7132 case OPC_RSQRT2_D:
5e755519 7133 check_cp1_64bitmode(ctx);
b6d96bed 7134 {
a7812ae4
PB
7135 TCGv_i64 fp0 = tcg_temp_new_i64();
7136 TCGv_i64 fp1 = tcg_temp_new_i64();
b6d96bed
TS
7137
7138 gen_load_fpr64(ctx, fp0, fs);
7139 gen_load_fpr64(ctx, fp1, ft);
a7812ae4
PB
7140 gen_helper_float_rsqrt2_d(fp0, fp0, fp1);
7141 tcg_temp_free_i64(fp1);
b6d96bed 7142 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 7143 tcg_temp_free_i64(fp0);
b6d96bed 7144 }
57fa1fb3
TS
7145 opn = "rsqrt2.d";
7146 break;
bf4120ad
NF
7147 case OPC_CMP_F_D:
7148 case OPC_CMP_UN_D:
7149 case OPC_CMP_EQ_D:
7150 case OPC_CMP_UEQ_D:
7151 case OPC_CMP_OLT_D:
7152 case OPC_CMP_ULT_D:
7153 case OPC_CMP_OLE_D:
7154 case OPC_CMP_ULE_D:
7155 case OPC_CMP_SF_D:
7156 case OPC_CMP_NGLE_D:
7157 case OPC_CMP_SEQ_D:
7158 case OPC_CMP_NGL_D:
7159 case OPC_CMP_LT_D:
7160 case OPC_CMP_NGE_D:
7161 case OPC_CMP_LE_D:
7162 case OPC_CMP_NGT_D:
8153667c
NF
7163 if (ctx->opcode & (1 << 6)) {
7164 gen_cmpabs_d(ctx, func-48, ft, fs, cc);
7165 opn = condnames_abs[func-48];
7166 } else {
7167 gen_cmp_d(ctx, func-48, ft, fs, cc);
7168 opn = condnames[func-48];
5a1e8ffb 7169 }
6ea83fed 7170 break;
bf4120ad 7171 case OPC_CVT_S_D:
5e755519 7172 check_cp1_registers(ctx, fs);
b6d96bed 7173 {
a7812ae4
PB
7174 TCGv_i32 fp32 = tcg_temp_new_i32();
7175 TCGv_i64 fp64 = tcg_temp_new_i64();
b6d96bed
TS
7176
7177 gen_load_fpr64(ctx, fp64, fs);
a7812ae4
PB
7178 gen_helper_float_cvts_d(fp32, fp64);
7179 tcg_temp_free_i64(fp64);
b6d96bed 7180 gen_store_fpr32(fp32, fd);
a7812ae4 7181 tcg_temp_free_i32(fp32);
b6d96bed 7182 }
5a5012ec
TS
7183 opn = "cvt.s.d";
7184 break;
bf4120ad 7185 case OPC_CVT_W_D:
5e755519 7186 check_cp1_registers(ctx, fs);
b6d96bed 7187 {
a7812ae4
PB
7188 TCGv_i32 fp32 = tcg_temp_new_i32();
7189 TCGv_i64 fp64 = tcg_temp_new_i64();
b6d96bed
TS
7190
7191 gen_load_fpr64(ctx, fp64, fs);
a7812ae4
PB
7192 gen_helper_float_cvtw_d(fp32, fp64);
7193 tcg_temp_free_i64(fp64);
b6d96bed 7194 gen_store_fpr32(fp32, fd);
a7812ae4 7195 tcg_temp_free_i32(fp32);
b6d96bed 7196 }
5a5012ec
TS
7197 opn = "cvt.w.d";
7198 break;
bf4120ad 7199 case OPC_CVT_L_D:
5e755519 7200 check_cp1_64bitmode(ctx);
b6d96bed 7201 {
a7812ae4 7202 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
7203
7204 gen_load_fpr64(ctx, fp0, fs);
a7812ae4 7205 gen_helper_float_cvtl_d(fp0, fp0);
b6d96bed 7206 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 7207 tcg_temp_free_i64(fp0);
b6d96bed 7208 }
5a5012ec
TS
7209 opn = "cvt.l.d";
7210 break;
bf4120ad 7211 case OPC_CVT_S_W:
b6d96bed 7212 {
a7812ae4 7213 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed
TS
7214
7215 gen_load_fpr32(fp0, fs);
a7812ae4 7216 gen_helper_float_cvts_w(fp0, fp0);
b6d96bed 7217 gen_store_fpr32(fp0, fd);
a7812ae4 7218 tcg_temp_free_i32(fp0);
b6d96bed 7219 }
5a5012ec 7220 opn = "cvt.s.w";
6ea83fed 7221 break;
bf4120ad 7222 case OPC_CVT_D_W:
5e755519 7223 check_cp1_registers(ctx, fd);
b6d96bed 7224 {
a7812ae4
PB
7225 TCGv_i32 fp32 = tcg_temp_new_i32();
7226 TCGv_i64 fp64 = tcg_temp_new_i64();
b6d96bed
TS
7227
7228 gen_load_fpr32(fp32, fs);
a7812ae4
PB
7229 gen_helper_float_cvtd_w(fp64, fp32);
7230 tcg_temp_free_i32(fp32);
b6d96bed 7231 gen_store_fpr64(ctx, fp64, fd);
a7812ae4 7232 tcg_temp_free_i64(fp64);
b6d96bed 7233 }
5a5012ec
TS
7234 opn = "cvt.d.w";
7235 break;
bf4120ad 7236 case OPC_CVT_S_L:
5e755519 7237 check_cp1_64bitmode(ctx);
b6d96bed 7238 {
a7812ae4
PB
7239 TCGv_i32 fp32 = tcg_temp_new_i32();
7240 TCGv_i64 fp64 = tcg_temp_new_i64();
b6d96bed
TS
7241
7242 gen_load_fpr64(ctx, fp64, fs);
a7812ae4
PB
7243 gen_helper_float_cvts_l(fp32, fp64);
7244 tcg_temp_free_i64(fp64);
b6d96bed 7245 gen_store_fpr32(fp32, fd);
a7812ae4 7246 tcg_temp_free_i32(fp32);
b6d96bed 7247 }
5a5012ec
TS
7248 opn = "cvt.s.l";
7249 break;
bf4120ad 7250 case OPC_CVT_D_L:
5e755519 7251 check_cp1_64bitmode(ctx);
b6d96bed 7252 {
a7812ae4 7253 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
7254
7255 gen_load_fpr64(ctx, fp0, fs);
a7812ae4 7256 gen_helper_float_cvtd_l(fp0, fp0);
b6d96bed 7257 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 7258 tcg_temp_free_i64(fp0);
b6d96bed 7259 }
5a5012ec
TS
7260 opn = "cvt.d.l";
7261 break;
bf4120ad 7262 case OPC_CVT_PS_PW:
5e755519 7263 check_cp1_64bitmode(ctx);
b6d96bed 7264 {
a7812ae4 7265 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
7266
7267 gen_load_fpr64(ctx, fp0, fs);
a7812ae4 7268 gen_helper_float_cvtps_pw(fp0, fp0);
b6d96bed 7269 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 7270 tcg_temp_free_i64(fp0);
b6d96bed 7271 }
5a5012ec
TS
7272 opn = "cvt.ps.pw";
7273 break;
bf4120ad 7274 case OPC_ADD_PS:
5e755519 7275 check_cp1_64bitmode(ctx);
b6d96bed 7276 {
a7812ae4
PB
7277 TCGv_i64 fp0 = tcg_temp_new_i64();
7278 TCGv_i64 fp1 = tcg_temp_new_i64();
b6d96bed
TS
7279
7280 gen_load_fpr64(ctx, fp0, fs);
7281 gen_load_fpr64(ctx, fp1, ft);
a7812ae4
PB
7282 gen_helper_float_add_ps(fp0, fp0, fp1);
7283 tcg_temp_free_i64(fp1);
b6d96bed 7284 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 7285 tcg_temp_free_i64(fp0);
b6d96bed 7286 }
5a5012ec 7287 opn = "add.ps";
6ea83fed 7288 break;
bf4120ad 7289 case OPC_SUB_PS:
5e755519 7290 check_cp1_64bitmode(ctx);
b6d96bed 7291 {
a7812ae4
PB
7292 TCGv_i64 fp0 = tcg_temp_new_i64();
7293 TCGv_i64 fp1 = tcg_temp_new_i64();
b6d96bed
TS
7294
7295 gen_load_fpr64(ctx, fp0, fs);
7296 gen_load_fpr64(ctx, fp1, ft);
a7812ae4
PB
7297 gen_helper_float_sub_ps(fp0, fp0, fp1);
7298 tcg_temp_free_i64(fp1);
b6d96bed 7299 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 7300 tcg_temp_free_i64(fp0);
b6d96bed 7301 }
5a5012ec 7302 opn = "sub.ps";
6ea83fed 7303 break;
bf4120ad 7304 case OPC_MUL_PS:
5e755519 7305 check_cp1_64bitmode(ctx);
b6d96bed 7306 {
a7812ae4
PB
7307 TCGv_i64 fp0 = tcg_temp_new_i64();
7308 TCGv_i64 fp1 = tcg_temp_new_i64();
b6d96bed
TS
7309
7310 gen_load_fpr64(ctx, fp0, fs);
7311 gen_load_fpr64(ctx, fp1, ft);
a7812ae4
PB
7312 gen_helper_float_mul_ps(fp0, fp0, fp1);
7313 tcg_temp_free_i64(fp1);
b6d96bed 7314 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 7315 tcg_temp_free_i64(fp0);
b6d96bed 7316 }
5a5012ec 7317 opn = "mul.ps";
6ea83fed 7318 break;
bf4120ad 7319 case OPC_ABS_PS:
5e755519 7320 check_cp1_64bitmode(ctx);
b6d96bed 7321 {
a7812ae4 7322 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
7323
7324 gen_load_fpr64(ctx, fp0, fs);
a7812ae4 7325 gen_helper_float_abs_ps(fp0, fp0);
b6d96bed 7326 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 7327 tcg_temp_free_i64(fp0);
b6d96bed 7328 }
5a5012ec 7329 opn = "abs.ps";
6ea83fed 7330 break;
bf4120ad 7331 case OPC_MOV_PS:
5e755519 7332 check_cp1_64bitmode(ctx);
b6d96bed 7333 {
a7812ae4 7334 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
7335
7336 gen_load_fpr64(ctx, fp0, fs);
7337 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 7338 tcg_temp_free_i64(fp0);
b6d96bed 7339 }
5a5012ec 7340 opn = "mov.ps";
6ea83fed 7341 break;
bf4120ad 7342 case OPC_NEG_PS:
5e755519 7343 check_cp1_64bitmode(ctx);
b6d96bed 7344 {
a7812ae4 7345 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
7346
7347 gen_load_fpr64(ctx, fp0, fs);
a7812ae4 7348 gen_helper_float_chs_ps(fp0, fp0);
b6d96bed 7349 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 7350 tcg_temp_free_i64(fp0);
b6d96bed 7351 }
5a5012ec 7352 opn = "neg.ps";
6ea83fed 7353 break;
bf4120ad 7354 case OPC_MOVCF_PS:
5e755519 7355 check_cp1_64bitmode(ctx);
b6d96bed 7356 gen_movcf_ps(fs, fd, (ft >> 2) & 0x7, ft & 0x1);
5a5012ec 7357 opn = "movcf.ps";
6ea83fed 7358 break;
bf4120ad 7359 case OPC_MOVZ_PS:
5e755519 7360 check_cp1_64bitmode(ctx);
a16336e4
TS
7361 {
7362 int l1 = gen_new_label();
30a3848b 7363 TCGv_i64 fp0;
a16336e4 7364
c9297f4d
AJ
7365 if (ft != 0)
7366 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[ft], 0, l1);
7367 fp0 = tcg_temp_new_i64();
7368 gen_load_fpr64(ctx, fp0, fs);
7369 gen_store_fpr64(ctx, fp0, fd);
7370 tcg_temp_free_i64(fp0);
a16336e4
TS
7371 gen_set_label(l1);
7372 }
5a5012ec 7373 opn = "movz.ps";
6ea83fed 7374 break;
bf4120ad 7375 case OPC_MOVN_PS:
5e755519 7376 check_cp1_64bitmode(ctx);
a16336e4
TS
7377 {
7378 int l1 = gen_new_label();
30a3848b 7379 TCGv_i64 fp0;
c9297f4d
AJ
7380
7381 if (ft != 0) {
7382 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[ft], 0, l1);
7383 fp0 = tcg_temp_new_i64();
7384 gen_load_fpr64(ctx, fp0, fs);
7385 gen_store_fpr64(ctx, fp0, fd);
7386 tcg_temp_free_i64(fp0);
7387 gen_set_label(l1);
7388 }
a16336e4 7389 }
5a5012ec 7390 opn = "movn.ps";
6ea83fed 7391 break;
bf4120ad 7392 case OPC_ADDR_PS:
5e755519 7393 check_cp1_64bitmode(ctx);
b6d96bed 7394 {
a7812ae4
PB
7395 TCGv_i64 fp0 = tcg_temp_new_i64();
7396 TCGv_i64 fp1 = tcg_temp_new_i64();
b6d96bed
TS
7397
7398 gen_load_fpr64(ctx, fp0, ft);
7399 gen_load_fpr64(ctx, fp1, fs);
a7812ae4
PB
7400 gen_helper_float_addr_ps(fp0, fp0, fp1);
7401 tcg_temp_free_i64(fp1);
b6d96bed 7402 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 7403 tcg_temp_free_i64(fp0);
b6d96bed 7404 }
fbcc6828
TS
7405 opn = "addr.ps";
7406 break;
bf4120ad 7407 case OPC_MULR_PS:
5e755519 7408 check_cp1_64bitmode(ctx);
b6d96bed 7409 {
a7812ae4
PB
7410 TCGv_i64 fp0 = tcg_temp_new_i64();
7411 TCGv_i64 fp1 = tcg_temp_new_i64();
b6d96bed
TS
7412
7413 gen_load_fpr64(ctx, fp0, ft);
7414 gen_load_fpr64(ctx, fp1, fs);
a7812ae4
PB
7415 gen_helper_float_mulr_ps(fp0, fp0, fp1);
7416 tcg_temp_free_i64(fp1);
b6d96bed 7417 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 7418 tcg_temp_free_i64(fp0);
b6d96bed 7419 }
57fa1fb3
TS
7420 opn = "mulr.ps";
7421 break;
bf4120ad 7422 case OPC_RECIP2_PS:
5e755519 7423 check_cp1_64bitmode(ctx);
b6d96bed 7424 {
a7812ae4
PB
7425 TCGv_i64 fp0 = tcg_temp_new_i64();
7426 TCGv_i64 fp1 = tcg_temp_new_i64();
b6d96bed
TS
7427
7428 gen_load_fpr64(ctx, fp0, fs);
7429 gen_load_fpr64(ctx, fp1, fd);
a7812ae4
PB
7430 gen_helper_float_recip2_ps(fp0, fp0, fp1);
7431 tcg_temp_free_i64(fp1);
b6d96bed 7432 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 7433 tcg_temp_free_i64(fp0);
b6d96bed 7434 }
57fa1fb3
TS
7435 opn = "recip2.ps";
7436 break;
bf4120ad 7437 case OPC_RECIP1_PS:
5e755519 7438 check_cp1_64bitmode(ctx);
b6d96bed 7439 {
a7812ae4 7440 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
7441
7442 gen_load_fpr64(ctx, fp0, fs);
a7812ae4 7443 gen_helper_float_recip1_ps(fp0, fp0);
b6d96bed 7444 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 7445 tcg_temp_free_i64(fp0);
b6d96bed 7446 }
57fa1fb3
TS
7447 opn = "recip1.ps";
7448 break;
bf4120ad 7449 case OPC_RSQRT1_PS:
5e755519 7450 check_cp1_64bitmode(ctx);
b6d96bed 7451 {
a7812ae4 7452 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
7453
7454 gen_load_fpr64(ctx, fp0, fs);
a7812ae4 7455 gen_helper_float_rsqrt1_ps(fp0, fp0);
b6d96bed 7456 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 7457 tcg_temp_free_i64(fp0);
b6d96bed 7458 }
57fa1fb3
TS
7459 opn = "rsqrt1.ps";
7460 break;
bf4120ad 7461 case OPC_RSQRT2_PS:
5e755519 7462 check_cp1_64bitmode(ctx);
b6d96bed 7463 {
a7812ae4
PB
7464 TCGv_i64 fp0 = tcg_temp_new_i64();
7465 TCGv_i64 fp1 = tcg_temp_new_i64();
b6d96bed
TS
7466
7467 gen_load_fpr64(ctx, fp0, fs);
7468 gen_load_fpr64(ctx, fp1, ft);
a7812ae4
PB
7469 gen_helper_float_rsqrt2_ps(fp0, fp0, fp1);
7470 tcg_temp_free_i64(fp1);
b6d96bed 7471 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 7472 tcg_temp_free_i64(fp0);
b6d96bed 7473 }
57fa1fb3
TS
7474 opn = "rsqrt2.ps";
7475 break;
bf4120ad 7476 case OPC_CVT_S_PU:
5e755519 7477 check_cp1_64bitmode(ctx);
b6d96bed 7478 {
a7812ae4 7479 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed
TS
7480
7481 gen_load_fpr32h(fp0, fs);
a7812ae4 7482 gen_helper_float_cvts_pu(fp0, fp0);
b6d96bed 7483 gen_store_fpr32(fp0, fd);
a7812ae4 7484 tcg_temp_free_i32(fp0);
b6d96bed 7485 }
5a5012ec 7486 opn = "cvt.s.pu";
dd016883 7487 break;
bf4120ad 7488 case OPC_CVT_PW_PS:
5e755519 7489 check_cp1_64bitmode(ctx);
b6d96bed 7490 {
a7812ae4 7491 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
7492
7493 gen_load_fpr64(ctx, fp0, fs);
a7812ae4 7494 gen_helper_float_cvtpw_ps(fp0, fp0);
b6d96bed 7495 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 7496 tcg_temp_free_i64(fp0);
b6d96bed 7497 }
5a5012ec 7498 opn = "cvt.pw.ps";
6ea83fed 7499 break;
bf4120ad 7500 case OPC_CVT_S_PL:
5e755519 7501 check_cp1_64bitmode(ctx);
b6d96bed 7502 {
a7812ae4 7503 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed
TS
7504
7505 gen_load_fpr32(fp0, fs);
a7812ae4 7506 gen_helper_float_cvts_pl(fp0, fp0);
b6d96bed 7507 gen_store_fpr32(fp0, fd);
a7812ae4 7508 tcg_temp_free_i32(fp0);
b6d96bed 7509 }
5a5012ec 7510 opn = "cvt.s.pl";
6ea83fed 7511 break;
bf4120ad 7512 case OPC_PLL_PS:
5e755519 7513 check_cp1_64bitmode(ctx);
b6d96bed 7514 {
a7812ae4
PB
7515 TCGv_i32 fp0 = tcg_temp_new_i32();
7516 TCGv_i32 fp1 = tcg_temp_new_i32();
b6d96bed
TS
7517
7518 gen_load_fpr32(fp0, fs);
7519 gen_load_fpr32(fp1, ft);
7520 gen_store_fpr32h(fp0, fd);
7521 gen_store_fpr32(fp1, fd);
a7812ae4
PB
7522 tcg_temp_free_i32(fp0);
7523 tcg_temp_free_i32(fp1);
b6d96bed 7524 }
5a5012ec 7525 opn = "pll.ps";
6ea83fed 7526 break;
bf4120ad 7527 case OPC_PLU_PS:
5e755519 7528 check_cp1_64bitmode(ctx);
b6d96bed 7529 {
a7812ae4
PB
7530 TCGv_i32 fp0 = tcg_temp_new_i32();
7531 TCGv_i32 fp1 = tcg_temp_new_i32();
b6d96bed
TS
7532
7533 gen_load_fpr32(fp0, fs);
7534 gen_load_fpr32h(fp1, ft);
7535 gen_store_fpr32(fp1, fd);
7536 gen_store_fpr32h(fp0, fd);
a7812ae4
PB
7537 tcg_temp_free_i32(fp0);
7538 tcg_temp_free_i32(fp1);
b6d96bed 7539 }
5a5012ec
TS
7540 opn = "plu.ps";
7541 break;
bf4120ad 7542 case OPC_PUL_PS:
5e755519 7543 check_cp1_64bitmode(ctx);
b6d96bed 7544 {
a7812ae4
PB
7545 TCGv_i32 fp0 = tcg_temp_new_i32();
7546 TCGv_i32 fp1 = tcg_temp_new_i32();
b6d96bed
TS
7547
7548 gen_load_fpr32h(fp0, fs);
7549 gen_load_fpr32(fp1, ft);
7550 gen_store_fpr32(fp1, fd);
7551 gen_store_fpr32h(fp0, fd);
a7812ae4
PB
7552 tcg_temp_free_i32(fp0);
7553 tcg_temp_free_i32(fp1);
b6d96bed 7554 }
5a5012ec
TS
7555 opn = "pul.ps";
7556 break;
bf4120ad 7557 case OPC_PUU_PS:
5e755519 7558 check_cp1_64bitmode(ctx);
b6d96bed 7559 {
a7812ae4
PB
7560 TCGv_i32 fp0 = tcg_temp_new_i32();
7561 TCGv_i32 fp1 = tcg_temp_new_i32();
b6d96bed
TS
7562
7563 gen_load_fpr32h(fp0, fs);
7564 gen_load_fpr32h(fp1, ft);
7565 gen_store_fpr32(fp1, fd);
7566 gen_store_fpr32h(fp0, fd);
a7812ae4
PB
7567 tcg_temp_free_i32(fp0);
7568 tcg_temp_free_i32(fp1);
b6d96bed 7569 }
5a5012ec
TS
7570 opn = "puu.ps";
7571 break;
bf4120ad
NF
7572 case OPC_CMP_F_PS:
7573 case OPC_CMP_UN_PS:
7574 case OPC_CMP_EQ_PS:
7575 case OPC_CMP_UEQ_PS:
7576 case OPC_CMP_OLT_PS:
7577 case OPC_CMP_ULT_PS:
7578 case OPC_CMP_OLE_PS:
7579 case OPC_CMP_ULE_PS:
7580 case OPC_CMP_SF_PS:
7581 case OPC_CMP_NGLE_PS:
7582 case OPC_CMP_SEQ_PS:
7583 case OPC_CMP_NGL_PS:
7584 case OPC_CMP_LT_PS:
7585 case OPC_CMP_NGE_PS:
7586 case OPC_CMP_LE_PS:
7587 case OPC_CMP_NGT_PS:
8153667c
NF
7588 if (ctx->opcode & (1 << 6)) {
7589 gen_cmpabs_ps(ctx, func-48, ft, fs, cc);
7590 opn = condnames_abs[func-48];
7591 } else {
7592 gen_cmp_ps(ctx, func-48, ft, fs, cc);
7593 opn = condnames[func-48];
5a1e8ffb 7594 }
6ea83fed 7595 break;
5a5012ec 7596 default:
923617a3 7597 MIPS_INVAL(opn);
e397ee33 7598 generate_exception (ctx, EXCP_RI);
6ea83fed
FB
7599 return;
7600 }
5a1e8ffb
TS
7601 switch (optype) {
7602 case BINOP:
6ea83fed 7603 MIPS_DEBUG("%s %s, %s, %s", opn, fregnames[fd], fregnames[fs], fregnames[ft]);
5a1e8ffb
TS
7604 break;
7605 case CMPOP:
7606 MIPS_DEBUG("%s %s,%s", opn, fregnames[fs], fregnames[ft]);
7607 break;
7608 default:
6ea83fed 7609 MIPS_DEBUG("%s %s,%s", opn, fregnames[fd], fregnames[fs]);
5a1e8ffb
TS
7610 break;
7611 }
6ea83fed 7612}
6af0bf9c 7613
5a5012ec 7614/* Coprocessor 3 (FPU) */
5e755519
TS
7615static void gen_flt3_ldst (DisasContext *ctx, uint32_t opc,
7616 int fd, int fs, int base, int index)
7a387fff 7617{
923617a3 7618 const char *opn = "extended float load/store";
93b12ccc 7619 int store = 0;
4e2474d6 7620 TCGv t0 = tcg_temp_new();
7a387fff 7621
93b12ccc 7622 if (base == 0) {
6c5c1e20 7623 gen_load_gpr(t0, index);
93b12ccc 7624 } else if (index == 0) {
6c5c1e20 7625 gen_load_gpr(t0, base);
93b12ccc 7626 } else {
e9203484 7627 gen_load_gpr(t0, index);
941694d0 7628 gen_op_addr_add(ctx, t0, cpu_gpr[base], t0);
93b12ccc 7629 }
5a5012ec 7630 /* Don't do NOP if destination is zero: we must perform the actual
ead9360e 7631 memory access. */
4e2474d6 7632 save_cpu_state(ctx, 0);
5a5012ec
TS
7633 switch (opc) {
7634 case OPC_LWXC1:
8c0ab41f 7635 check_cop1x(ctx);
b6d96bed 7636 {
a7812ae4 7637 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed 7638
585c88d5
AJ
7639 tcg_gen_qemu_ld32s(t0, t0, ctx->mem_idx);
7640 tcg_gen_trunc_tl_i32(fp0, t0);
b6d96bed 7641 gen_store_fpr32(fp0, fd);
a7812ae4 7642 tcg_temp_free_i32(fp0);
b6d96bed 7643 }
5a5012ec
TS
7644 opn = "lwxc1";
7645 break;
7646 case OPC_LDXC1:
8c0ab41f
AJ
7647 check_cop1x(ctx);
7648 check_cp1_registers(ctx, fd);
b6d96bed 7649 {
a7812ae4 7650 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
7651
7652 tcg_gen_qemu_ld64(fp0, t0, ctx->mem_idx);
7653 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 7654 tcg_temp_free_i64(fp0);
b6d96bed 7655 }
5a5012ec
TS
7656 opn = "ldxc1";
7657 break;
7658 case OPC_LUXC1:
8c0ab41f 7659 check_cp1_64bitmode(ctx);
6c5c1e20 7660 tcg_gen_andi_tl(t0, t0, ~0x7);
b6d96bed 7661 {
a7812ae4 7662 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
7663
7664 tcg_gen_qemu_ld64(fp0, t0, ctx->mem_idx);
7665 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 7666 tcg_temp_free_i64(fp0);
b6d96bed 7667 }
5a5012ec
TS
7668 opn = "luxc1";
7669 break;
7670 case OPC_SWXC1:
8c0ab41f 7671 check_cop1x(ctx);
b6d96bed 7672 {
a7812ae4 7673 TCGv_i32 fp0 = tcg_temp_new_i32();
585c88d5 7674 TCGv t1 = tcg_temp_new();
b6d96bed
TS
7675
7676 gen_load_fpr32(fp0, fs);
a7812ae4
PB
7677 tcg_gen_extu_i32_tl(t1, fp0);
7678 tcg_gen_qemu_st32(t1, t0, ctx->mem_idx);
7679 tcg_temp_free_i32(fp0);
a6035857 7680 tcg_temp_free(t1);
b6d96bed 7681 }
5a5012ec 7682 opn = "swxc1";
93b12ccc 7683 store = 1;
5a5012ec
TS
7684 break;
7685 case OPC_SDXC1:
8c0ab41f
AJ
7686 check_cop1x(ctx);
7687 check_cp1_registers(ctx, fs);
b6d96bed 7688 {
a7812ae4 7689 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
7690
7691 gen_load_fpr64(ctx, fp0, fs);
7692 tcg_gen_qemu_st64(fp0, t0, ctx->mem_idx);
a7812ae4 7693 tcg_temp_free_i64(fp0);
b6d96bed 7694 }
5a5012ec 7695 opn = "sdxc1";
93b12ccc 7696 store = 1;
5a5012ec
TS
7697 break;
7698 case OPC_SUXC1:
8c0ab41f 7699 check_cp1_64bitmode(ctx);
6c5c1e20 7700 tcg_gen_andi_tl(t0, t0, ~0x7);
b6d96bed 7701 {
a7812ae4 7702 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
7703
7704 gen_load_fpr64(ctx, fp0, fs);
7705 tcg_gen_qemu_st64(fp0, t0, ctx->mem_idx);
a7812ae4 7706 tcg_temp_free_i64(fp0);
b6d96bed 7707 }
5a5012ec 7708 opn = "suxc1";
93b12ccc 7709 store = 1;
5a5012ec 7710 break;
5a5012ec 7711 }
6c5c1e20 7712 tcg_temp_free(t0);
93b12ccc
TS
7713 MIPS_DEBUG("%s %s, %s(%s)", opn, fregnames[store ? fs : fd],
7714 regnames[index], regnames[base]);
5a5012ec
TS
7715}
7716
5e755519
TS
7717static void gen_flt3_arith (DisasContext *ctx, uint32_t opc,
7718 int fd, int fr, int fs, int ft)
5a5012ec 7719{
923617a3 7720 const char *opn = "flt3_arith";
5a5012ec 7721
5a5012ec
TS
7722 switch (opc) {
7723 case OPC_ALNV_PS:
b8aa4598 7724 check_cp1_64bitmode(ctx);
a16336e4 7725 {
a7812ae4 7726 TCGv t0 = tcg_temp_local_new();
c905fdac
AJ
7727 TCGv_i32 fp = tcg_temp_new_i32();
7728 TCGv_i32 fph = tcg_temp_new_i32();
a16336e4
TS
7729 int l1 = gen_new_label();
7730 int l2 = gen_new_label();
7731
6c5c1e20
TS
7732 gen_load_gpr(t0, fr);
7733 tcg_gen_andi_tl(t0, t0, 0x7);
6c5c1e20
TS
7734
7735 tcg_gen_brcondi_tl(TCG_COND_NE, t0, 0, l1);
c905fdac
AJ
7736 gen_load_fpr32(fp, fs);
7737 gen_load_fpr32h(fph, fs);
7738 gen_store_fpr32(fp, fd);
7739 gen_store_fpr32h(fph, fd);
a16336e4
TS
7740 tcg_gen_br(l2);
7741 gen_set_label(l1);
6c5c1e20
TS
7742 tcg_gen_brcondi_tl(TCG_COND_NE, t0, 4, l2);
7743 tcg_temp_free(t0);
a16336e4 7744#ifdef TARGET_WORDS_BIGENDIAN
c905fdac
AJ
7745 gen_load_fpr32(fp, fs);
7746 gen_load_fpr32h(fph, ft);
7747 gen_store_fpr32h(fp, fd);
7748 gen_store_fpr32(fph, fd);
a16336e4 7749#else
c905fdac
AJ
7750 gen_load_fpr32h(fph, fs);
7751 gen_load_fpr32(fp, ft);
7752 gen_store_fpr32(fph, fd);
7753 gen_store_fpr32h(fp, fd);
a16336e4
TS
7754#endif
7755 gen_set_label(l2);
c905fdac
AJ
7756 tcg_temp_free_i32(fp);
7757 tcg_temp_free_i32(fph);
a16336e4 7758 }
5a5012ec
TS
7759 opn = "alnv.ps";
7760 break;
7761 case OPC_MADD_S:
b8aa4598 7762 check_cop1x(ctx);
b6d96bed 7763 {
a7812ae4
PB
7764 TCGv_i32 fp0 = tcg_temp_new_i32();
7765 TCGv_i32 fp1 = tcg_temp_new_i32();
7766 TCGv_i32 fp2 = tcg_temp_new_i32();
b6d96bed
TS
7767
7768 gen_load_fpr32(fp0, fs);
7769 gen_load_fpr32(fp1, ft);
7770 gen_load_fpr32(fp2, fr);
a7812ae4
PB
7771 gen_helper_float_muladd_s(fp2, fp0, fp1, fp2);
7772 tcg_temp_free_i32(fp0);
7773 tcg_temp_free_i32(fp1);
b6d96bed 7774 gen_store_fpr32(fp2, fd);
a7812ae4 7775 tcg_temp_free_i32(fp2);
b6d96bed 7776 }
5a5012ec
TS
7777 opn = "madd.s";
7778 break;
7779 case OPC_MADD_D:
b8aa4598
TS
7780 check_cop1x(ctx);
7781 check_cp1_registers(ctx, fd | fs | ft | fr);
b6d96bed 7782 {
a7812ae4
PB
7783 TCGv_i64 fp0 = tcg_temp_new_i64();
7784 TCGv_i64 fp1 = tcg_temp_new_i64();
7785 TCGv_i64 fp2 = tcg_temp_new_i64();
b6d96bed
TS
7786
7787 gen_load_fpr64(ctx, fp0, fs);
7788 gen_load_fpr64(ctx, fp1, ft);
7789 gen_load_fpr64(ctx, fp2, fr);
a7812ae4
PB
7790 gen_helper_float_muladd_d(fp2, fp0, fp1, fp2);
7791 tcg_temp_free_i64(fp0);
7792 tcg_temp_free_i64(fp1);
b6d96bed 7793 gen_store_fpr64(ctx, fp2, fd);
a7812ae4 7794 tcg_temp_free_i64(fp2);
b6d96bed 7795 }
5a5012ec
TS
7796 opn = "madd.d";
7797 break;
7798 case OPC_MADD_PS:
b8aa4598 7799 check_cp1_64bitmode(ctx);
b6d96bed 7800 {
a7812ae4
PB
7801 TCGv_i64 fp0 = tcg_temp_new_i64();
7802 TCGv_i64 fp1 = tcg_temp_new_i64();
7803 TCGv_i64 fp2 = tcg_temp_new_i64();
b6d96bed
TS
7804
7805 gen_load_fpr64(ctx, fp0, fs);
7806 gen_load_fpr64(ctx, fp1, ft);
7807 gen_load_fpr64(ctx, fp2, fr);
a7812ae4
PB
7808 gen_helper_float_muladd_ps(fp2, fp0, fp1, fp2);
7809 tcg_temp_free_i64(fp0);
7810 tcg_temp_free_i64(fp1);
b6d96bed 7811 gen_store_fpr64(ctx, fp2, fd);
a7812ae4 7812 tcg_temp_free_i64(fp2);
b6d96bed 7813 }
5a5012ec
TS
7814 opn = "madd.ps";
7815 break;
7816 case OPC_MSUB_S:
b8aa4598 7817 check_cop1x(ctx);
b6d96bed 7818 {
a7812ae4
PB
7819 TCGv_i32 fp0 = tcg_temp_new_i32();
7820 TCGv_i32 fp1 = tcg_temp_new_i32();
7821 TCGv_i32 fp2 = tcg_temp_new_i32();
b6d96bed
TS
7822
7823 gen_load_fpr32(fp0, fs);
7824 gen_load_fpr32(fp1, ft);
7825 gen_load_fpr32(fp2, fr);
a7812ae4
PB
7826 gen_helper_float_mulsub_s(fp2, fp0, fp1, fp2);
7827 tcg_temp_free_i32(fp0);
7828 tcg_temp_free_i32(fp1);
b6d96bed 7829 gen_store_fpr32(fp2, fd);
a7812ae4 7830 tcg_temp_free_i32(fp2);
b6d96bed 7831 }
5a5012ec
TS
7832 opn = "msub.s";
7833 break;
7834 case OPC_MSUB_D:
b8aa4598
TS
7835 check_cop1x(ctx);
7836 check_cp1_registers(ctx, fd | fs | ft | fr);
b6d96bed 7837 {
a7812ae4
PB
7838 TCGv_i64 fp0 = tcg_temp_new_i64();
7839 TCGv_i64 fp1 = tcg_temp_new_i64();
7840 TCGv_i64 fp2 = tcg_temp_new_i64();
b6d96bed
TS
7841
7842 gen_load_fpr64(ctx, fp0, fs);
7843 gen_load_fpr64(ctx, fp1, ft);
7844 gen_load_fpr64(ctx, fp2, fr);
a7812ae4
PB
7845 gen_helper_float_mulsub_d(fp2, fp0, fp1, fp2);
7846 tcg_temp_free_i64(fp0);
7847 tcg_temp_free_i64(fp1);
b6d96bed 7848 gen_store_fpr64(ctx, fp2, fd);
a7812ae4 7849 tcg_temp_free_i64(fp2);
b6d96bed 7850 }
5a5012ec
TS
7851 opn = "msub.d";
7852 break;
7853 case OPC_MSUB_PS:
b8aa4598 7854 check_cp1_64bitmode(ctx);
b6d96bed 7855 {
a7812ae4
PB
7856 TCGv_i64 fp0 = tcg_temp_new_i64();
7857 TCGv_i64 fp1 = tcg_temp_new_i64();
7858 TCGv_i64 fp2 = tcg_temp_new_i64();
b6d96bed
TS
7859
7860 gen_load_fpr64(ctx, fp0, fs);
7861 gen_load_fpr64(ctx, fp1, ft);
7862 gen_load_fpr64(ctx, fp2, fr);
a7812ae4
PB
7863 gen_helper_float_mulsub_ps(fp2, fp0, fp1, fp2);
7864 tcg_temp_free_i64(fp0);
7865 tcg_temp_free_i64(fp1);
b6d96bed 7866 gen_store_fpr64(ctx, fp2, fd);
a7812ae4 7867 tcg_temp_free_i64(fp2);
b6d96bed 7868 }
5a5012ec
TS
7869 opn = "msub.ps";
7870 break;
7871 case OPC_NMADD_S:
b8aa4598 7872 check_cop1x(ctx);
b6d96bed 7873 {
a7812ae4
PB
7874 TCGv_i32 fp0 = tcg_temp_new_i32();
7875 TCGv_i32 fp1 = tcg_temp_new_i32();
7876 TCGv_i32 fp2 = tcg_temp_new_i32();
b6d96bed
TS
7877
7878 gen_load_fpr32(fp0, fs);
7879 gen_load_fpr32(fp1, ft);
7880 gen_load_fpr32(fp2, fr);
a7812ae4
PB
7881 gen_helper_float_nmuladd_s(fp2, fp0, fp1, fp2);
7882 tcg_temp_free_i32(fp0);
7883 tcg_temp_free_i32(fp1);
b6d96bed 7884 gen_store_fpr32(fp2, fd);
a7812ae4 7885 tcg_temp_free_i32(fp2);
b6d96bed 7886 }
5a5012ec
TS
7887 opn = "nmadd.s";
7888 break;
7889 case OPC_NMADD_D:
b8aa4598
TS
7890 check_cop1x(ctx);
7891 check_cp1_registers(ctx, fd | fs | ft | fr);
b6d96bed 7892 {
a7812ae4
PB
7893 TCGv_i64 fp0 = tcg_temp_new_i64();
7894 TCGv_i64 fp1 = tcg_temp_new_i64();
7895 TCGv_i64 fp2 = tcg_temp_new_i64();
b6d96bed
TS
7896
7897 gen_load_fpr64(ctx, fp0, fs);
7898 gen_load_fpr64(ctx, fp1, ft);
7899 gen_load_fpr64(ctx, fp2, fr);
a7812ae4
PB
7900 gen_helper_float_nmuladd_d(fp2, fp0, fp1, fp2);
7901 tcg_temp_free_i64(fp0);
7902 tcg_temp_free_i64(fp1);
b6d96bed 7903 gen_store_fpr64(ctx, fp2, fd);
a7812ae4 7904 tcg_temp_free_i64(fp2);
b6d96bed 7905 }
5a5012ec
TS
7906 opn = "nmadd.d";
7907 break;
7908 case OPC_NMADD_PS:
b8aa4598 7909 check_cp1_64bitmode(ctx);
b6d96bed 7910 {
a7812ae4
PB
7911 TCGv_i64 fp0 = tcg_temp_new_i64();
7912 TCGv_i64 fp1 = tcg_temp_new_i64();
7913 TCGv_i64 fp2 = tcg_temp_new_i64();
b6d96bed
TS
7914
7915 gen_load_fpr64(ctx, fp0, fs);
7916 gen_load_fpr64(ctx, fp1, ft);
7917 gen_load_fpr64(ctx, fp2, fr);
a7812ae4
PB
7918 gen_helper_float_nmuladd_ps(fp2, fp0, fp1, fp2);
7919 tcg_temp_free_i64(fp0);
7920 tcg_temp_free_i64(fp1);
b6d96bed 7921 gen_store_fpr64(ctx, fp2, fd);
a7812ae4 7922 tcg_temp_free_i64(fp2);
b6d96bed 7923 }
5a5012ec
TS
7924 opn = "nmadd.ps";
7925 break;
7926 case OPC_NMSUB_S:
b8aa4598 7927 check_cop1x(ctx);
b6d96bed 7928 {
a7812ae4
PB
7929 TCGv_i32 fp0 = tcg_temp_new_i32();
7930 TCGv_i32 fp1 = tcg_temp_new_i32();
7931 TCGv_i32 fp2 = tcg_temp_new_i32();
b6d96bed
TS
7932
7933 gen_load_fpr32(fp0, fs);
7934 gen_load_fpr32(fp1, ft);
7935 gen_load_fpr32(fp2, fr);
a7812ae4
PB
7936 gen_helper_float_nmulsub_s(fp2, fp0, fp1, fp2);
7937 tcg_temp_free_i32(fp0);
7938 tcg_temp_free_i32(fp1);
b6d96bed 7939 gen_store_fpr32(fp2, fd);
a7812ae4 7940 tcg_temp_free_i32(fp2);
b6d96bed 7941 }
5a5012ec
TS
7942 opn = "nmsub.s";
7943 break;
7944 case OPC_NMSUB_D:
b8aa4598
TS
7945 check_cop1x(ctx);
7946 check_cp1_registers(ctx, fd | fs | ft | fr);
b6d96bed 7947 {
a7812ae4
PB
7948 TCGv_i64 fp0 = tcg_temp_new_i64();
7949 TCGv_i64 fp1 = tcg_temp_new_i64();
7950 TCGv_i64 fp2 = tcg_temp_new_i64();
b6d96bed
TS
7951
7952 gen_load_fpr64(ctx, fp0, fs);
7953 gen_load_fpr64(ctx, fp1, ft);
7954 gen_load_fpr64(ctx, fp2, fr);
a7812ae4
PB
7955 gen_helper_float_nmulsub_d(fp2, fp0, fp1, fp2);
7956 tcg_temp_free_i64(fp0);
7957 tcg_temp_free_i64(fp1);
b6d96bed 7958 gen_store_fpr64(ctx, fp2, fd);
a7812ae4 7959 tcg_temp_free_i64(fp2);
b6d96bed 7960 }
5a5012ec
TS
7961 opn = "nmsub.d";
7962 break;
7963 case OPC_NMSUB_PS:
b8aa4598 7964 check_cp1_64bitmode(ctx);
b6d96bed 7965 {
a7812ae4
PB
7966 TCGv_i64 fp0 = tcg_temp_new_i64();
7967 TCGv_i64 fp1 = tcg_temp_new_i64();
7968 TCGv_i64 fp2 = tcg_temp_new_i64();
b6d96bed
TS
7969
7970 gen_load_fpr64(ctx, fp0, fs);
7971 gen_load_fpr64(ctx, fp1, ft);
7972 gen_load_fpr64(ctx, fp2, fr);
a7812ae4
PB
7973 gen_helper_float_nmulsub_ps(fp2, fp0, fp1, fp2);
7974 tcg_temp_free_i64(fp0);
7975 tcg_temp_free_i64(fp1);
b6d96bed 7976 gen_store_fpr64(ctx, fp2, fd);
a7812ae4 7977 tcg_temp_free_i64(fp2);
b6d96bed 7978 }
5a5012ec
TS
7979 opn = "nmsub.ps";
7980 break;
923617a3
TS
7981 default:
7982 MIPS_INVAL(opn);
5a5012ec
TS
7983 generate_exception (ctx, EXCP_RI);
7984 return;
7985 }
7986 MIPS_DEBUG("%s %s, %s, %s, %s", opn, fregnames[fd], fregnames[fr],
7987 fregnames[fs], fregnames[ft]);
7a387fff
TS
7988}
7989
26ebe468
NF
7990static void
7991gen_rdhwr (CPUState *env, DisasContext *ctx, int rt, int rd)
7992{
7993 TCGv t0;
7994
7995 check_insn(env, ctx, ISA_MIPS32R2);
7996 t0 = tcg_temp_new();
7997
7998 switch (rd) {
7999 case 0:
8000 save_cpu_state(ctx, 1);
8001 gen_helper_rdhwr_cpunum(t0);
8002 gen_store_gpr(t0, rt);
8003 break;
8004 case 1:
8005 save_cpu_state(ctx, 1);
8006 gen_helper_rdhwr_synci_step(t0);
8007 gen_store_gpr(t0, rt);
8008 break;
8009 case 2:
8010 save_cpu_state(ctx, 1);
8011 gen_helper_rdhwr_cc(t0);
8012 gen_store_gpr(t0, rt);
8013 break;
8014 case 3:
8015 save_cpu_state(ctx, 1);
8016 gen_helper_rdhwr_ccres(t0);
8017 gen_store_gpr(t0, rt);
8018 break;
8019 case 29:
8020#if defined(CONFIG_USER_ONLY)
8021 tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUState, tls_value));
8022 gen_store_gpr(t0, rt);
8023 break;
8024#else
8025 /* XXX: Some CPUs implement this in hardware.
8026 Not supported yet. */
8027#endif
8028 default: /* Invalid */
8029 MIPS_INVAL("rdhwr");
8030 generate_exception(ctx, EXCP_RI);
8031 break;
8032 }
8033 tcg_temp_free(t0);
8034}
8035
c9602061
NF
8036static void handle_delay_slot (CPUState *env, DisasContext *ctx,
8037 int insn_bytes)
8038{
8039 if (ctx->hflags & MIPS_HFLAG_BMASK) {
364d4831 8040 int proc_hflags = ctx->hflags & MIPS_HFLAG_BMASK;
c9602061
NF
8041 /* Branches completion */
8042 ctx->hflags &= ~MIPS_HFLAG_BMASK;
8043 ctx->bstate = BS_BRANCH;
8044 save_cpu_state(ctx, 0);
8045 /* FIXME: Need to clear can_do_io. */
364d4831 8046 switch (proc_hflags & MIPS_HFLAG_BMASK_BASE) {
c9602061
NF
8047 case MIPS_HFLAG_B:
8048 /* unconditional branch */
8049 MIPS_DEBUG("unconditional branch");
364d4831
NF
8050 if (proc_hflags & MIPS_HFLAG_BX) {
8051 tcg_gen_xori_i32(hflags, hflags, MIPS_HFLAG_M16);
8052 }
c9602061
NF
8053 gen_goto_tb(ctx, 0, ctx->btarget);
8054 break;
8055 case MIPS_HFLAG_BL:
8056 /* blikely taken case */
8057 MIPS_DEBUG("blikely branch taken");
8058 gen_goto_tb(ctx, 0, ctx->btarget);
8059 break;
8060 case MIPS_HFLAG_BC:
8061 /* Conditional branch */
8062 MIPS_DEBUG("conditional branch");
8063 {
8064 int l1 = gen_new_label();
8065
8066 tcg_gen_brcondi_tl(TCG_COND_NE, bcond, 0, l1);
8067 gen_goto_tb(ctx, 1, ctx->pc + insn_bytes);
8068 gen_set_label(l1);
8069 gen_goto_tb(ctx, 0, ctx->btarget);
8070 }
8071 break;
8072 case MIPS_HFLAG_BR:
8073 /* unconditional branch to register */
8074 MIPS_DEBUG("branch to register");
3c824109 8075 if (env->insn_flags & (ASE_MIPS16 | ASE_MICROMIPS)) {
364d4831
NF
8076 TCGv t0 = tcg_temp_new();
8077 TCGv_i32 t1 = tcg_temp_new_i32();
8078
8079 tcg_gen_andi_tl(t0, btarget, 0x1);
8080 tcg_gen_trunc_tl_i32(t1, t0);
8081 tcg_temp_free(t0);
8082 tcg_gen_andi_i32(hflags, hflags, ~(uint32_t)MIPS_HFLAG_M16);
8083 tcg_gen_shli_i32(t1, t1, MIPS_HFLAG_M16_SHIFT);
8084 tcg_gen_or_i32(hflags, hflags, t1);
8085 tcg_temp_free_i32(t1);
8086
8087 tcg_gen_andi_tl(cpu_PC, btarget, ~(target_ulong)0x1);
8088 } else {
8089 tcg_gen_mov_tl(cpu_PC, btarget);
8090 }
c9602061
NF
8091 if (ctx->singlestep_enabled) {
8092 save_cpu_state(ctx, 0);
8093 gen_helper_0i(raise_exception, EXCP_DEBUG);
8094 }
8095 tcg_gen_exit_tb(0);
8096 break;
8097 default:
8098 MIPS_DEBUG("unknown branch");
8099 break;
8100 }
8101 }
8102}
8103
7a387fff 8104/* ISA extensions (ASEs) */
6af0bf9c 8105/* MIPS16 extension to MIPS32 */
6ea219d0
NF
8106
8107/* MIPS16 major opcodes */
8108enum {
8109 M16_OPC_ADDIUSP = 0x00,
8110 M16_OPC_ADDIUPC = 0x01,
8111 M16_OPC_B = 0x02,
8112 M16_OPC_JAL = 0x03,
8113 M16_OPC_BEQZ = 0x04,
8114 M16_OPC_BNEQZ = 0x05,
8115 M16_OPC_SHIFT = 0x06,
8116 M16_OPC_LD = 0x07,
8117 M16_OPC_RRIA = 0x08,
8118 M16_OPC_ADDIU8 = 0x09,
8119 M16_OPC_SLTI = 0x0a,
8120 M16_OPC_SLTIU = 0x0b,
8121 M16_OPC_I8 = 0x0c,
8122 M16_OPC_LI = 0x0d,
8123 M16_OPC_CMPI = 0x0e,
8124 M16_OPC_SD = 0x0f,
8125 M16_OPC_LB = 0x10,
8126 M16_OPC_LH = 0x11,
8127 M16_OPC_LWSP = 0x12,
8128 M16_OPC_LW = 0x13,
8129 M16_OPC_LBU = 0x14,
8130 M16_OPC_LHU = 0x15,
8131 M16_OPC_LWPC = 0x16,
8132 M16_OPC_LWU = 0x17,
8133 M16_OPC_SB = 0x18,
8134 M16_OPC_SH = 0x19,
8135 M16_OPC_SWSP = 0x1a,
8136 M16_OPC_SW = 0x1b,
8137 M16_OPC_RRR = 0x1c,
8138 M16_OPC_RR = 0x1d,
8139 M16_OPC_EXTEND = 0x1e,
8140 M16_OPC_I64 = 0x1f
8141};
8142
8143/* I8 funct field */
8144enum {
8145 I8_BTEQZ = 0x0,
8146 I8_BTNEZ = 0x1,
8147 I8_SWRASP = 0x2,
8148 I8_ADJSP = 0x3,
8149 I8_SVRS = 0x4,
8150 I8_MOV32R = 0x5,
8151 I8_MOVR32 = 0x7
8152};
8153
8154/* RRR f field */
8155enum {
8156 RRR_DADDU = 0x0,
8157 RRR_ADDU = 0x1,
8158 RRR_DSUBU = 0x2,
8159 RRR_SUBU = 0x3
8160};
8161
8162/* RR funct field */
8163enum {
8164 RR_JR = 0x00,
8165 RR_SDBBP = 0x01,
8166 RR_SLT = 0x02,
8167 RR_SLTU = 0x03,
8168 RR_SLLV = 0x04,
8169 RR_BREAK = 0x05,
8170 RR_SRLV = 0x06,
8171 RR_SRAV = 0x07,
8172 RR_DSRL = 0x08,
8173 RR_CMP = 0x0a,
8174 RR_NEG = 0x0b,
8175 RR_AND = 0x0c,
8176 RR_OR = 0x0d,
8177 RR_XOR = 0x0e,
8178 RR_NOT = 0x0f,
8179 RR_MFHI = 0x10,
8180 RR_CNVT = 0x11,
8181 RR_MFLO = 0x12,
8182 RR_DSRA = 0x13,
8183 RR_DSLLV = 0x14,
8184 RR_DSRLV = 0x16,
8185 RR_DSRAV = 0x17,
8186 RR_MULT = 0x18,
8187 RR_MULTU = 0x19,
8188 RR_DIV = 0x1a,
8189 RR_DIVU = 0x1b,
8190 RR_DMULT = 0x1c,
8191 RR_DMULTU = 0x1d,
8192 RR_DDIV = 0x1e,
8193 RR_DDIVU = 0x1f
8194};
8195
8196/* I64 funct field */
8197enum {
8198 I64_LDSP = 0x0,
8199 I64_SDSP = 0x1,
8200 I64_SDRASP = 0x2,
8201 I64_DADJSP = 0x3,
8202 I64_LDPC = 0x4,
364d4831 8203 I64_DADDIU5 = 0x5,
6ea219d0
NF
8204 I64_DADDIUPC = 0x6,
8205 I64_DADDIUSP = 0x7
8206};
8207
8208/* RR ry field for CNVT */
8209enum {
8210 RR_RY_CNVT_ZEB = 0x0,
8211 RR_RY_CNVT_ZEH = 0x1,
8212 RR_RY_CNVT_ZEW = 0x2,
8213 RR_RY_CNVT_SEB = 0x4,
8214 RR_RY_CNVT_SEH = 0x5,
8215 RR_RY_CNVT_SEW = 0x6,
8216};
8217
364d4831
NF
8218static int xlat (int r)
8219{
8220 static int map[] = { 16, 17, 2, 3, 4, 5, 6, 7 };
8221
8222 return map[r];
8223}
8224
8225static void gen_mips16_save (DisasContext *ctx,
8226 int xsregs, int aregs,
8227 int do_ra, int do_s0, int do_s1,
8228 int framesize)
8229{
8230 TCGv t0 = tcg_temp_new();
8231 TCGv t1 = tcg_temp_new();
8232 int args, astatic;
8233
8234 switch (aregs) {
8235 case 0:
8236 case 1:
8237 case 2:
8238 case 3:
8239 case 11:
8240 args = 0;
8241 break;
8242 case 4:
8243 case 5:
8244 case 6:
8245 case 7:
8246 args = 1;
8247 break;
8248 case 8:
8249 case 9:
8250 case 10:
8251 args = 2;
8252 break;
8253 case 12:
8254 case 13:
8255 args = 3;
8256 break;
8257 case 14:
8258 args = 4;
8259 break;
8260 default:
8261 generate_exception(ctx, EXCP_RI);
8262 return;
8263 }
8264
8265 switch (args) {
8266 case 4:
8267 gen_base_offset_addr(ctx, t0, 29, 12);
8268 gen_load_gpr(t1, 7);
5c13fdfd 8269 op_st_sw(t1, t0, ctx);
364d4831
NF
8270 /* Fall through */
8271 case 3:
8272 gen_base_offset_addr(ctx, t0, 29, 8);
8273 gen_load_gpr(t1, 6);
5c13fdfd 8274 op_st_sw(t1, t0, ctx);
364d4831
NF
8275 /* Fall through */
8276 case 2:
8277 gen_base_offset_addr(ctx, t0, 29, 4);
8278 gen_load_gpr(t1, 5);
5c13fdfd 8279 op_st_sw(t1, t0, ctx);
364d4831
NF
8280 /* Fall through */
8281 case 1:
8282 gen_base_offset_addr(ctx, t0, 29, 0);
8283 gen_load_gpr(t1, 4);
5c13fdfd 8284 op_st_sw(t1, t0, ctx);
364d4831
NF
8285 }
8286
8287 gen_load_gpr(t0, 29);
8288
8289#define DECR_AND_STORE(reg) do { \
8290 tcg_gen_subi_tl(t0, t0, 4); \
8291 gen_load_gpr(t1, reg); \
5c13fdfd 8292 op_st_sw(t1, t0, ctx); \
364d4831
NF
8293 } while (0)
8294
8295 if (do_ra) {
8296 DECR_AND_STORE(31);
8297 }
8298
8299 switch (xsregs) {
8300 case 7:
8301 DECR_AND_STORE(30);
8302 /* Fall through */
8303 case 6:
8304 DECR_AND_STORE(23);
8305 /* Fall through */
8306 case 5:
8307 DECR_AND_STORE(22);
8308 /* Fall through */
8309 case 4:
8310 DECR_AND_STORE(21);
8311 /* Fall through */
8312 case 3:
8313 DECR_AND_STORE(20);
8314 /* Fall through */
8315 case 2:
8316 DECR_AND_STORE(19);
8317 /* Fall through */
8318 case 1:
8319 DECR_AND_STORE(18);
8320 }
8321
8322 if (do_s1) {
8323 DECR_AND_STORE(17);
8324 }
8325 if (do_s0) {
8326 DECR_AND_STORE(16);
8327 }
8328
8329 switch (aregs) {
8330 case 0:
8331 case 4:
8332 case 8:
8333 case 12:
8334 case 14:
8335 astatic = 0;
8336 break;
8337 case 1:
8338 case 5:
8339 case 9:
8340 case 13:
8341 astatic = 1;
8342 break;
8343 case 2:
8344 case 6:
8345 case 10:
8346 astatic = 2;
8347 break;
8348 case 3:
8349 case 7:
8350 astatic = 3;
8351 break;
8352 case 11:
8353 astatic = 4;
8354 break;
8355 default:
8356 generate_exception(ctx, EXCP_RI);
8357 return;
8358 }
8359
8360 if (astatic > 0) {
8361 DECR_AND_STORE(7);
8362 if (astatic > 1) {
8363 DECR_AND_STORE(6);
8364 if (astatic > 2) {
8365 DECR_AND_STORE(5);
8366 if (astatic > 3) {
8367 DECR_AND_STORE(4);
8368 }
8369 }
8370 }
8371 }
8372#undef DECR_AND_STORE
8373
8374 tcg_gen_subi_tl(cpu_gpr[29], cpu_gpr[29], framesize);
8375 tcg_temp_free(t0);
8376 tcg_temp_free(t1);
8377}
8378
8379static void gen_mips16_restore (DisasContext *ctx,
8380 int xsregs, int aregs,
8381 int do_ra, int do_s0, int do_s1,
8382 int framesize)
8383{
8384 int astatic;
8385 TCGv t0 = tcg_temp_new();
8386 TCGv t1 = tcg_temp_new();
8387
8388 tcg_gen_addi_tl(t0, cpu_gpr[29], framesize);
8389
8390#define DECR_AND_LOAD(reg) do { \
8391 tcg_gen_subi_tl(t0, t0, 4); \
5c13fdfd 8392 op_ld_lw(t1, t0, ctx); \
364d4831
NF
8393 gen_store_gpr(t1, reg); \
8394 } while (0)
8395
8396 if (do_ra) {
8397 DECR_AND_LOAD(31);
8398 }
8399
8400 switch (xsregs) {
8401 case 7:
8402 DECR_AND_LOAD(30);
8403 /* Fall through */
8404 case 6:
8405 DECR_AND_LOAD(23);
8406 /* Fall through */
8407 case 5:
8408 DECR_AND_LOAD(22);
8409 /* Fall through */
8410 case 4:
8411 DECR_AND_LOAD(21);
8412 /* Fall through */
8413 case 3:
8414 DECR_AND_LOAD(20);
8415 /* Fall through */
8416 case 2:
8417 DECR_AND_LOAD(19);
8418 /* Fall through */
8419 case 1:
8420 DECR_AND_LOAD(18);
8421 }
8422
8423 if (do_s1) {
8424 DECR_AND_LOAD(17);
8425 }
8426 if (do_s0) {
8427 DECR_AND_LOAD(16);
8428 }
8429
8430 switch (aregs) {
8431 case 0:
8432 case 4:
8433 case 8:
8434 case 12:
8435 case 14:
8436 astatic = 0;
8437 break;
8438 case 1:
8439 case 5:
8440 case 9:
8441 case 13:
8442 astatic = 1;
8443 break;
8444 case 2:
8445 case 6:
8446 case 10:
8447 astatic = 2;
8448 break;
8449 case 3:
8450 case 7:
8451 astatic = 3;
8452 break;
8453 case 11:
8454 astatic = 4;
8455 break;
8456 default:
8457 generate_exception(ctx, EXCP_RI);
8458 return;
8459 }
8460
8461 if (astatic > 0) {
8462 DECR_AND_LOAD(7);
8463 if (astatic > 1) {
8464 DECR_AND_LOAD(6);
8465 if (astatic > 2) {
8466 DECR_AND_LOAD(5);
8467 if (astatic > 3) {
8468 DECR_AND_LOAD(4);
8469 }
8470 }
8471 }
8472 }
8473#undef DECR_AND_LOAD
8474
8475 tcg_gen_addi_tl(cpu_gpr[29], cpu_gpr[29], framesize);
8476 tcg_temp_free(t0);
8477 tcg_temp_free(t1);
8478}
8479
8480static void gen_addiupc (DisasContext *ctx, int rx, int imm,
8481 int is_64_bit, int extended)
8482{
8483 TCGv t0;
8484
8485 if (extended && (ctx->hflags & MIPS_HFLAG_BMASK)) {
8486 generate_exception(ctx, EXCP_RI);
8487 return;
8488 }
8489
8490 t0 = tcg_temp_new();
8491
8492 tcg_gen_movi_tl(t0, pc_relative_pc(ctx));
8493 tcg_gen_addi_tl(cpu_gpr[rx], t0, imm);
8494 if (!is_64_bit) {
8495 tcg_gen_ext32s_tl(cpu_gpr[rx], cpu_gpr[rx]);
8496 }
8497
8498 tcg_temp_free(t0);
8499}
8500
8501#if defined(TARGET_MIPS64)
8502static void decode_i64_mips16 (CPUState *env, DisasContext *ctx,
8503 int ry, int funct, int16_t offset,
8504 int extended)
8505{
8506 switch (funct) {
8507 case I64_LDSP:
8508 check_mips_64(ctx);
8509 offset = extended ? offset : offset << 3;
afa88c3a 8510 gen_ld(env, ctx, OPC_LD, ry, 29, offset);
364d4831
NF
8511 break;
8512 case I64_SDSP:
8513 check_mips_64(ctx);
8514 offset = extended ? offset : offset << 3;
5c13fdfd 8515 gen_st(ctx, OPC_SD, ry, 29, offset);
364d4831
NF
8516 break;
8517 case I64_SDRASP:
8518 check_mips_64(ctx);
8519 offset = extended ? offset : (ctx->opcode & 0xff) << 3;
5c13fdfd 8520 gen_st(ctx, OPC_SD, 31, 29, offset);
364d4831
NF
8521 break;
8522 case I64_DADJSP:
8523 check_mips_64(ctx);
8524 offset = extended ? offset : ((int8_t)ctx->opcode) << 3;
8525 gen_arith_imm(env, ctx, OPC_DADDIU, 29, 29, offset);
8526 break;
8527 case I64_LDPC:
8528 if (extended && (ctx->hflags & MIPS_HFLAG_BMASK)) {
8529 generate_exception(ctx, EXCP_RI);
8530 } else {
8531 offset = extended ? offset : offset << 3;
afa88c3a 8532 gen_ld(env, ctx, OPC_LDPC, ry, 0, offset);
364d4831
NF
8533 }
8534 break;
8535 case I64_DADDIU5:
8536 check_mips_64(ctx);
8537 offset = extended ? offset : ((int8_t)(offset << 3)) >> 3;
8538 gen_arith_imm(env, ctx, OPC_DADDIU, ry, ry, offset);
8539 break;
8540 case I64_DADDIUPC:
8541 check_mips_64(ctx);
8542 offset = extended ? offset : offset << 2;
8543 gen_addiupc(ctx, ry, offset, 1, extended);
8544 break;
8545 case I64_DADDIUSP:
8546 check_mips_64(ctx);
8547 offset = extended ? offset : offset << 2;
8548 gen_arith_imm(env, ctx, OPC_DADDIU, ry, 29, offset);
8549 break;
8550 }
8551}
8552#endif
8553
8554static int decode_extended_mips16_opc (CPUState *env, DisasContext *ctx,
8555 int *is_branch)
8556{
8557 int extend = lduw_code(ctx->pc + 2);
8558 int op, rx, ry, funct, sa;
8559 int16_t imm, offset;
8560
8561 ctx->opcode = (ctx->opcode << 16) | extend;
8562 op = (ctx->opcode >> 11) & 0x1f;
8563 sa = (ctx->opcode >> 22) & 0x1f;
8564 funct = (ctx->opcode >> 8) & 0x7;
8565 rx = xlat((ctx->opcode >> 8) & 0x7);
8566 ry = xlat((ctx->opcode >> 5) & 0x7);
8567 offset = imm = (int16_t) (((ctx->opcode >> 16) & 0x1f) << 11
8568 | ((ctx->opcode >> 21) & 0x3f) << 5
8569 | (ctx->opcode & 0x1f));
8570
8571 /* The extended opcodes cleverly reuse the opcodes from their 16-bit
8572 counterparts. */
8573 switch (op) {
8574 case M16_OPC_ADDIUSP:
8575 gen_arith_imm(env, ctx, OPC_ADDIU, rx, 29, imm);
8576 break;
8577 case M16_OPC_ADDIUPC:
8578 gen_addiupc(ctx, rx, imm, 0, 1);
8579 break;
8580 case M16_OPC_B:
8581 gen_compute_branch(ctx, OPC_BEQ, 4, 0, 0, offset << 1);
8582 /* No delay slot, so just process as a normal instruction */
8583 break;
8584 case M16_OPC_BEQZ:
8585 gen_compute_branch(ctx, OPC_BEQ, 4, rx, 0, offset << 1);
8586 /* No delay slot, so just process as a normal instruction */
8587 break;
8588 case M16_OPC_BNEQZ:
8589 gen_compute_branch(ctx, OPC_BNE, 4, rx, 0, offset << 1);
8590 /* No delay slot, so just process as a normal instruction */
8591 break;
8592 case M16_OPC_SHIFT:
8593 switch (ctx->opcode & 0x3) {
8594 case 0x0:
8595 gen_shift_imm(env, ctx, OPC_SLL, rx, ry, sa);
8596 break;
8597 case 0x1:
8598#if defined(TARGET_MIPS64)
8599 check_mips_64(ctx);
8600 gen_shift_imm(env, ctx, OPC_DSLL, rx, ry, sa);
8601#else
8602 generate_exception(ctx, EXCP_RI);
8603#endif
8604 break;
8605 case 0x2:
8606 gen_shift_imm(env, ctx, OPC_SRL, rx, ry, sa);
8607 break;
8608 case 0x3:
8609 gen_shift_imm(env, ctx, OPC_SRA, rx, ry, sa);
8610 break;
8611 }
8612 break;
8613#if defined(TARGET_MIPS64)
8614 case M16_OPC_LD:
8615 check_mips_64(ctx);
afa88c3a 8616 gen_ld(env, ctx, OPC_LD, ry, rx, offset);
364d4831
NF
8617 break;
8618#endif
8619 case M16_OPC_RRIA:
8620 imm = ctx->opcode & 0xf;
8621 imm = imm | ((ctx->opcode >> 20) & 0x7f) << 4;
8622 imm = imm | ((ctx->opcode >> 16) & 0xf) << 11;
8623 imm = (int16_t) (imm << 1) >> 1;
8624 if ((ctx->opcode >> 4) & 0x1) {
8625#if defined(TARGET_MIPS64)
8626 check_mips_64(ctx);
8627 gen_arith_imm(env, ctx, OPC_DADDIU, ry, rx, imm);
8628#else
8629 generate_exception(ctx, EXCP_RI);
8630#endif
8631 } else {
8632 gen_arith_imm(env, ctx, OPC_ADDIU, ry, rx, imm);
8633 }
8634 break;
8635 case M16_OPC_ADDIU8:
8636 gen_arith_imm(env, ctx, OPC_ADDIU, rx, rx, imm);
8637 break;
8638 case M16_OPC_SLTI:
8639 gen_slt_imm(env, OPC_SLTI, 24, rx, imm);
8640 break;
8641 case M16_OPC_SLTIU:
8642 gen_slt_imm(env, OPC_SLTIU, 24, rx, imm);
8643 break;
8644 case M16_OPC_I8:
8645 switch (funct) {
8646 case I8_BTEQZ:
8647 gen_compute_branch(ctx, OPC_BEQ, 4, 24, 0, offset << 1);
8648 break;
8649 case I8_BTNEZ:
8650 gen_compute_branch(ctx, OPC_BNE, 4, 24, 0, offset << 1);
8651 break;
8652 case I8_SWRASP:
5c13fdfd 8653 gen_st(ctx, OPC_SW, 31, 29, imm);
364d4831
NF
8654 break;
8655 case I8_ADJSP:
8656 gen_arith_imm(env, ctx, OPC_ADDIU, 29, 29, imm);
8657 break;
8658 case I8_SVRS:
8659 {
8660 int xsregs = (ctx->opcode >> 24) & 0x7;
8661 int aregs = (ctx->opcode >> 16) & 0xf;
8662 int do_ra = (ctx->opcode >> 6) & 0x1;
8663 int do_s0 = (ctx->opcode >> 5) & 0x1;
8664 int do_s1 = (ctx->opcode >> 4) & 0x1;
8665 int framesize = (((ctx->opcode >> 20) & 0xf) << 4
8666 | (ctx->opcode & 0xf)) << 3;
8667
8668 if (ctx->opcode & (1 << 7)) {
8669 gen_mips16_save(ctx, xsregs, aregs,
8670 do_ra, do_s0, do_s1,
8671 framesize);
8672 } else {
8673 gen_mips16_restore(ctx, xsregs, aregs,
8674 do_ra, do_s0, do_s1,
8675 framesize);
8676 }
8677 }
8678 break;
8679 default:
8680 generate_exception(ctx, EXCP_RI);
8681 break;
8682 }
8683 break;
8684 case M16_OPC_LI:
8685 tcg_gen_movi_tl(cpu_gpr[rx], (uint16_t) imm);
8686 break;
8687 case M16_OPC_CMPI:
8688 tcg_gen_xori_tl(cpu_gpr[24], cpu_gpr[rx], (uint16_t) imm);
8689 break;
8690#if defined(TARGET_MIPS64)
8691 case M16_OPC_SD:
5c13fdfd 8692 gen_st(ctx, OPC_SD, ry, rx, offset);
364d4831
NF
8693 break;
8694#endif
8695 case M16_OPC_LB:
afa88c3a 8696 gen_ld(env, ctx, OPC_LB, ry, rx, offset);
364d4831
NF
8697 break;
8698 case M16_OPC_LH:
afa88c3a 8699 gen_ld(env, ctx, OPC_LH, ry, rx, offset);
364d4831
NF
8700 break;
8701 case M16_OPC_LWSP:
afa88c3a 8702 gen_ld(env, ctx, OPC_LW, rx, 29, offset);
364d4831
NF
8703 break;
8704 case M16_OPC_LW:
afa88c3a 8705 gen_ld(env, ctx, OPC_LW, ry, rx, offset);
364d4831
NF
8706 break;
8707 case M16_OPC_LBU:
afa88c3a 8708 gen_ld(env, ctx, OPC_LBU, ry, rx, offset);
364d4831
NF
8709 break;
8710 case M16_OPC_LHU:
afa88c3a 8711 gen_ld(env, ctx, OPC_LHU, ry, rx, offset);
364d4831
NF
8712 break;
8713 case M16_OPC_LWPC:
afa88c3a 8714 gen_ld(env, ctx, OPC_LWPC, rx, 0, offset);
364d4831
NF
8715 break;
8716#if defined(TARGET_MIPS64)
8717 case M16_OPC_LWU:
afa88c3a 8718 gen_ld(env, ctx, OPC_LWU, ry, rx, offset);
364d4831
NF
8719 break;
8720#endif
8721 case M16_OPC_SB:
5c13fdfd 8722 gen_st(ctx, OPC_SB, ry, rx, offset);
364d4831
NF
8723 break;
8724 case M16_OPC_SH:
5c13fdfd 8725 gen_st(ctx, OPC_SH, ry, rx, offset);
364d4831
NF
8726 break;
8727 case M16_OPC_SWSP:
5c13fdfd 8728 gen_st(ctx, OPC_SW, rx, 29, offset);
364d4831
NF
8729 break;
8730 case M16_OPC_SW:
5c13fdfd 8731 gen_st(ctx, OPC_SW, ry, rx, offset);
364d4831
NF
8732 break;
8733#if defined(TARGET_MIPS64)
8734 case M16_OPC_I64:
8735 decode_i64_mips16(env, ctx, ry, funct, offset, 1);
8736 break;
8737#endif
8738 default:
8739 generate_exception(ctx, EXCP_RI);
8740 break;
8741 }
8742
8743 return 4;
8744}
8745
8746static int decode_mips16_opc (CPUState *env, DisasContext *ctx,
8747 int *is_branch)
8748{
8749 int rx, ry;
8750 int sa;
8751 int op, cnvt_op, op1, offset;
8752 int funct;
8753 int n_bytes;
8754
8755 op = (ctx->opcode >> 11) & 0x1f;
8756 sa = (ctx->opcode >> 2) & 0x7;
8757 sa = sa == 0 ? 8 : sa;
8758 rx = xlat((ctx->opcode >> 8) & 0x7);
8759 cnvt_op = (ctx->opcode >> 5) & 0x7;
8760 ry = xlat((ctx->opcode >> 5) & 0x7);
8761 op1 = offset = ctx->opcode & 0x1f;
8762
8763 n_bytes = 2;
8764
8765 switch (op) {
8766 case M16_OPC_ADDIUSP:
8767 {
8768 int16_t imm = ((uint8_t) ctx->opcode) << 2;
8769
8770 gen_arith_imm(env, ctx, OPC_ADDIU, rx, 29, imm);
8771 }
8772 break;
8773 case M16_OPC_ADDIUPC:
8774 gen_addiupc(ctx, rx, ((uint8_t) ctx->opcode) << 2, 0, 0);
8775 break;
8776 case M16_OPC_B:
8777 offset = (ctx->opcode & 0x7ff) << 1;
8778 offset = (int16_t)(offset << 4) >> 4;
8779 gen_compute_branch(ctx, OPC_BEQ, 2, 0, 0, offset);
8780 /* No delay slot, so just process as a normal instruction */
8781 break;
8782 case M16_OPC_JAL:
8783 offset = lduw_code(ctx->pc + 2);
8784 offset = (((ctx->opcode & 0x1f) << 21)
8785 | ((ctx->opcode >> 5) & 0x1f) << 16
8786 | offset) << 2;
620e48f6 8787 op = ((ctx->opcode >> 10) & 0x1) ? OPC_JALXS : OPC_JALS;
364d4831
NF
8788 gen_compute_branch(ctx, op, 4, rx, ry, offset);
8789 n_bytes = 4;
8790 *is_branch = 1;
8791 break;
8792 case M16_OPC_BEQZ:
8793 gen_compute_branch(ctx, OPC_BEQ, 2, rx, 0, ((int8_t)ctx->opcode) << 1);
8794 /* No delay slot, so just process as a normal instruction */
8795 break;
8796 case M16_OPC_BNEQZ:
8797 gen_compute_branch(ctx, OPC_BNE, 2, rx, 0, ((int8_t)ctx->opcode) << 1);
8798 /* No delay slot, so just process as a normal instruction */
8799 break;
8800 case M16_OPC_SHIFT:
8801 switch (ctx->opcode & 0x3) {
8802 case 0x0:
8803 gen_shift_imm(env, ctx, OPC_SLL, rx, ry, sa);
8804 break;
8805 case 0x1:
8806#if defined(TARGET_MIPS64)
8807 check_mips_64(ctx);
8808 gen_shift_imm(env, ctx, OPC_DSLL, rx, ry, sa);
8809#else
8810 generate_exception(ctx, EXCP_RI);
8811#endif
8812 break;
8813 case 0x2:
8814 gen_shift_imm(env, ctx, OPC_SRL, rx, ry, sa);
8815 break;
8816 case 0x3:
8817 gen_shift_imm(env, ctx, OPC_SRA, rx, ry, sa);
8818 break;
8819 }
8820 break;
8821#if defined(TARGET_MIPS64)
8822 case M16_OPC_LD:
8823 check_mips_64(ctx);
afa88c3a 8824 gen_ld(env, ctx, OPC_LD, ry, rx, offset << 3);
364d4831
NF
8825 break;
8826#endif
8827 case M16_OPC_RRIA:
8828 {
8829 int16_t imm = (int8_t)((ctx->opcode & 0xf) << 4) >> 4;
8830
8831 if ((ctx->opcode >> 4) & 1) {
8832#if defined(TARGET_MIPS64)
8833 check_mips_64(ctx);
8834 gen_arith_imm(env, ctx, OPC_DADDIU, ry, rx, imm);
8835#else
8836 generate_exception(ctx, EXCP_RI);
8837#endif
8838 } else {
8839 gen_arith_imm(env, ctx, OPC_ADDIU, ry, rx, imm);
8840 }
8841 }
8842 break;
8843 case M16_OPC_ADDIU8:
8844 {
8845 int16_t imm = (int8_t) ctx->opcode;
8846
8847 gen_arith_imm(env, ctx, OPC_ADDIU, rx, rx, imm);
8848 }
8849 break;
8850 case M16_OPC_SLTI:
8851 {
8852 int16_t imm = (uint8_t) ctx->opcode;
8853
8854 gen_slt_imm(env, OPC_SLTI, 24, rx, imm);
8855 }
8856 break;
8857 case M16_OPC_SLTIU:
8858 {
8859 int16_t imm = (uint8_t) ctx->opcode;
8860
8861 gen_slt_imm(env, OPC_SLTIU, 24, rx, imm);
8862 }
8863 break;
8864 case M16_OPC_I8:
8865 {
8866 int reg32;
8867
8868 funct = (ctx->opcode >> 8) & 0x7;
8869 switch (funct) {
8870 case I8_BTEQZ:
8871 gen_compute_branch(ctx, OPC_BEQ, 2, 24, 0,
8872 ((int8_t)ctx->opcode) << 1);
8873 break;
8874 case I8_BTNEZ:
8875 gen_compute_branch(ctx, OPC_BNE, 2, 24, 0,
8876 ((int8_t)ctx->opcode) << 1);
8877 break;
8878 case I8_SWRASP:
5c13fdfd 8879 gen_st(ctx, OPC_SW, 31, 29, (ctx->opcode & 0xff) << 2);
364d4831
NF
8880 break;
8881 case I8_ADJSP:
8882 gen_arith_imm(env, ctx, OPC_ADDIU, 29, 29,
8883 ((int8_t)ctx->opcode) << 3);
8884 break;
8885 case I8_SVRS:
8886 {
8887 int do_ra = ctx->opcode & (1 << 6);
8888 int do_s0 = ctx->opcode & (1 << 5);
8889 int do_s1 = ctx->opcode & (1 << 4);
8890 int framesize = ctx->opcode & 0xf;
8891
8892 if (framesize == 0) {
8893 framesize = 128;
8894 } else {
8895 framesize = framesize << 3;
8896 }
8897
8898 if (ctx->opcode & (1 << 7)) {
8899 gen_mips16_save(ctx, 0, 0,
8900 do_ra, do_s0, do_s1, framesize);
8901 } else {
8902 gen_mips16_restore(ctx, 0, 0,
8903 do_ra, do_s0, do_s1, framesize);
8904 }
8905 }
8906 break;
8907 case I8_MOV32R:
8908 {
8909 int rz = xlat(ctx->opcode & 0x7);
8910
8911 reg32 = (((ctx->opcode >> 3) & 0x3) << 3) |
8912 ((ctx->opcode >> 5) & 0x7);
8913 gen_arith(env, ctx, OPC_ADDU, reg32, rz, 0);
8914 }
8915 break;
8916 case I8_MOVR32:
8917 reg32 = ctx->opcode & 0x1f;
8918 gen_arith(env, ctx, OPC_ADDU, ry, reg32, 0);
8919 break;
8920 default:
8921 generate_exception(ctx, EXCP_RI);
8922 break;
8923 }
8924 }
8925 break;
8926 case M16_OPC_LI:
8927 {
8928 int16_t imm = (uint8_t) ctx->opcode;
8929
8930 gen_arith_imm(env, ctx, OPC_ADDIU, rx, 0, imm);
8931 }
8932 break;
8933 case M16_OPC_CMPI:
8934 {
8935 int16_t imm = (uint8_t) ctx->opcode;
8936
8937 gen_logic_imm(env, OPC_XORI, 24, rx, imm);
8938 }
8939 break;
8940#if defined(TARGET_MIPS64)
8941 case M16_OPC_SD:
8942 check_mips_64(ctx);
5c13fdfd 8943 gen_st(ctx, OPC_SD, ry, rx, offset << 3);
364d4831
NF
8944 break;
8945#endif
8946 case M16_OPC_LB:
afa88c3a 8947 gen_ld(env, ctx, OPC_LB, ry, rx, offset);
364d4831
NF
8948 break;
8949 case M16_OPC_LH:
afa88c3a 8950 gen_ld(env, ctx, OPC_LH, ry, rx, offset << 1);
364d4831
NF
8951 break;
8952 case M16_OPC_LWSP:
afa88c3a 8953 gen_ld(env, ctx, OPC_LW, rx, 29, ((uint8_t)ctx->opcode) << 2);
364d4831
NF
8954 break;
8955 case M16_OPC_LW:
afa88c3a 8956 gen_ld(env, ctx, OPC_LW, ry, rx, offset << 2);
364d4831
NF
8957 break;
8958 case M16_OPC_LBU:
afa88c3a 8959 gen_ld(env, ctx, OPC_LBU, ry, rx, offset);
364d4831
NF
8960 break;
8961 case M16_OPC_LHU:
afa88c3a 8962 gen_ld(env, ctx, OPC_LHU, ry, rx, offset << 1);
364d4831
NF
8963 break;
8964 case M16_OPC_LWPC:
afa88c3a 8965 gen_ld(env, ctx, OPC_LWPC, rx, 0, ((uint8_t)ctx->opcode) << 2);
364d4831
NF
8966 break;
8967#if defined (TARGET_MIPS64)
8968 case M16_OPC_LWU:
8969 check_mips_64(ctx);
afa88c3a 8970 gen_ld(env, ctx, OPC_LWU, ry, rx, offset << 2);
364d4831
NF
8971 break;
8972#endif
8973 case M16_OPC_SB:
5c13fdfd 8974 gen_st(ctx, OPC_SB, ry, rx, offset);
364d4831
NF
8975 break;
8976 case M16_OPC_SH:
5c13fdfd 8977 gen_st(ctx, OPC_SH, ry, rx, offset << 1);
364d4831
NF
8978 break;
8979 case M16_OPC_SWSP:
5c13fdfd 8980 gen_st(ctx, OPC_SW, rx, 29, ((uint8_t)ctx->opcode) << 2);
364d4831
NF
8981 break;
8982 case M16_OPC_SW:
5c13fdfd 8983 gen_st(ctx, OPC_SW, ry, rx, offset << 2);
364d4831
NF
8984 break;
8985 case M16_OPC_RRR:
8986 {
8987 int rz = xlat((ctx->opcode >> 2) & 0x7);
8988 int mips32_op;
8989
8990 switch (ctx->opcode & 0x3) {
8991 case RRR_ADDU:
8992 mips32_op = OPC_ADDU;
8993 break;
8994 case RRR_SUBU:
8995 mips32_op = OPC_SUBU;
8996 break;
8997#if defined(TARGET_MIPS64)
8998 case RRR_DADDU:
8999 mips32_op = OPC_DADDU;
9000 check_mips_64(ctx);
9001 break;
9002 case RRR_DSUBU:
9003 mips32_op = OPC_DSUBU;
9004 check_mips_64(ctx);
9005 break;
9006#endif
9007 default:
9008 generate_exception(ctx, EXCP_RI);
9009 goto done;
9010 }
9011
9012 gen_arith(env, ctx, mips32_op, rz, rx, ry);
9013 done:
9014 ;
9015 }
9016 break;
9017 case M16_OPC_RR:
9018 switch (op1) {
9019 case RR_JR:
9020 {
9021 int nd = (ctx->opcode >> 7) & 0x1;
9022 int link = (ctx->opcode >> 6) & 0x1;
9023 int ra = (ctx->opcode >> 5) & 0x1;
9024
9025 if (link) {
620e48f6 9026 op = nd ? OPC_JALRC : OPC_JALRS;
364d4831
NF
9027 } else {
9028 op = OPC_JR;
9029 }
9030
9031 gen_compute_branch(ctx, op, 2, ra ? 31 : rx, 31, 0);
9032 if (!nd) {
9033 *is_branch = 1;
9034 }
9035 }
9036 break;
9037 case RR_SDBBP:
9038 /* XXX: not clear which exception should be raised
9039 * when in debug mode...
9040 */
9041 check_insn(env, ctx, ISA_MIPS32);
9042 if (!(ctx->hflags & MIPS_HFLAG_DM)) {
9043 generate_exception(ctx, EXCP_DBp);
9044 } else {
9045 generate_exception(ctx, EXCP_DBp);
9046 }
9047 break;
9048 case RR_SLT:
9049 gen_slt(env, OPC_SLT, 24, rx, ry);
9050 break;
9051 case RR_SLTU:
9052 gen_slt(env, OPC_SLTU, 24, rx, ry);
9053 break;
9054 case RR_BREAK:
9055 generate_exception(ctx, EXCP_BREAK);
9056 break;
9057 case RR_SLLV:
9058 gen_shift(env, ctx, OPC_SLLV, ry, rx, ry);
9059 break;
9060 case RR_SRLV:
9061 gen_shift(env, ctx, OPC_SRLV, ry, rx, ry);
9062 break;
9063 case RR_SRAV:
9064 gen_shift(env, ctx, OPC_SRAV, ry, rx, ry);
9065 break;
9066#if defined (TARGET_MIPS64)
9067 case RR_DSRL:
9068 check_mips_64(ctx);
9069 gen_shift_imm(env, ctx, OPC_DSRL, ry, ry, sa);
9070 break;
9071#endif
9072 case RR_CMP:
9073 gen_logic(env, OPC_XOR, 24, rx, ry);
9074 break;
9075 case RR_NEG:
9076 gen_arith(env, ctx, OPC_SUBU, rx, 0, ry);
9077 break;
9078 case RR_AND:
9079 gen_logic(env, OPC_AND, rx, rx, ry);
9080 break;
9081 case RR_OR:
9082 gen_logic(env, OPC_OR, rx, rx, ry);
9083 break;
9084 case RR_XOR:
9085 gen_logic(env, OPC_XOR, rx, rx, ry);
9086 break;
9087 case RR_NOT:
9088 gen_logic(env, OPC_NOR, rx, ry, 0);
9089 break;
9090 case RR_MFHI:
9091 gen_HILO(ctx, OPC_MFHI, rx);
9092 break;
9093 case RR_CNVT:
9094 switch (cnvt_op) {
9095 case RR_RY_CNVT_ZEB:
9096 tcg_gen_ext8u_tl(cpu_gpr[rx], cpu_gpr[rx]);
9097 break;
9098 case RR_RY_CNVT_ZEH:
9099 tcg_gen_ext16u_tl(cpu_gpr[rx], cpu_gpr[rx]);
9100 break;
9101 case RR_RY_CNVT_SEB:
9102 tcg_gen_ext8s_tl(cpu_gpr[rx], cpu_gpr[rx]);
9103 break;
9104 case RR_RY_CNVT_SEH:
9105 tcg_gen_ext16s_tl(cpu_gpr[rx], cpu_gpr[rx]);
9106 break;
9107#if defined (TARGET_MIPS64)
9108 case RR_RY_CNVT_ZEW:
9109 check_mips_64(ctx);
9110 tcg_gen_ext32u_tl(cpu_gpr[rx], cpu_gpr[rx]);
9111 break;
9112 case RR_RY_CNVT_SEW:
9113 check_mips_64(ctx);
9114 tcg_gen_ext32s_tl(cpu_gpr[rx], cpu_gpr[rx]);
9115 break;
9116#endif
9117 default:
9118 generate_exception(ctx, EXCP_RI);
9119 break;
9120 }
9121 break;
9122 case RR_MFLO:
9123 gen_HILO(ctx, OPC_MFLO, rx);
9124 break;
9125#if defined (TARGET_MIPS64)
9126 case RR_DSRA:
9127 check_mips_64(ctx);
9128 gen_shift_imm(env, ctx, OPC_DSRA, ry, ry, sa);
9129 break;
9130 case RR_DSLLV:
9131 check_mips_64(ctx);
9132 gen_shift(env, ctx, OPC_DSLLV, ry, rx, ry);
9133 break;
9134 case RR_DSRLV:
9135 check_mips_64(ctx);
9136 gen_shift(env, ctx, OPC_DSRLV, ry, rx, ry);
9137 break;
9138 case RR_DSRAV:
9139 check_mips_64(ctx);
9140 gen_shift(env, ctx, OPC_DSRAV, ry, rx, ry);
9141 break;
9142#endif
9143 case RR_MULT:
9144 gen_muldiv(ctx, OPC_MULT, rx, ry);
9145 break;
9146 case RR_MULTU:
9147 gen_muldiv(ctx, OPC_MULTU, rx, ry);
9148 break;
9149 case RR_DIV:
9150 gen_muldiv(ctx, OPC_DIV, rx, ry);
9151 break;
9152 case RR_DIVU:
9153 gen_muldiv(ctx, OPC_DIVU, rx, ry);
9154 break;
9155#if defined (TARGET_MIPS64)
9156 case RR_DMULT:
9157 check_mips_64(ctx);
9158 gen_muldiv(ctx, OPC_DMULT, rx, ry);
9159 break;
9160 case RR_DMULTU:
9161 check_mips_64(ctx);
9162 gen_muldiv(ctx, OPC_DMULTU, rx, ry);
9163 break;
9164 case RR_DDIV:
9165 check_mips_64(ctx);
9166 gen_muldiv(ctx, OPC_DDIV, rx, ry);
9167 break;
9168 case RR_DDIVU:
9169 check_mips_64(ctx);
9170 gen_muldiv(ctx, OPC_DDIVU, rx, ry);
9171 break;
9172#endif
9173 default:
9174 generate_exception(ctx, EXCP_RI);
9175 break;
9176 }
9177 break;
9178 case M16_OPC_EXTEND:
9179 decode_extended_mips16_opc(env, ctx, is_branch);
9180 n_bytes = 4;
9181 break;
9182#if defined(TARGET_MIPS64)
9183 case M16_OPC_I64:
9184 funct = (ctx->opcode >> 8) & 0x7;
9185 decode_i64_mips16(env, ctx, ry, funct, offset, 0);
9186 break;
9187#endif
9188 default:
9189 generate_exception(ctx, EXCP_RI);
9190 break;
9191 }
9192
9193 return n_bytes;
9194}
9195
3c824109 9196/* microMIPS extension to MIPS32 */
6af0bf9c 9197
3c824109 9198/* microMIPS32 major opcodes */
6af0bf9c 9199
3c824109
NF
9200enum {
9201 POOL32A = 0x00,
9202 POOL16A = 0x01,
9203 LBU16 = 0x02,
9204 MOVE16 = 0x03,
9205 ADDI32 = 0x04,
9206 LBU32 = 0x05,
9207 SB32 = 0x06,
9208 LB32 = 0x07,
9209
9210 POOL32B = 0x08,
9211 POOL16B = 0x09,
9212 LHU16 = 0x0a,
9213 ANDI16 = 0x0b,
9214 ADDIU32 = 0x0c,
9215 LHU32 = 0x0d,
9216 SH32 = 0x0e,
9217 LH32 = 0x0f,
9218
9219 POOL32I = 0x10,
9220 POOL16C = 0x11,
9221 LWSP16 = 0x12,
9222 POOL16D = 0x13,
9223 ORI32 = 0x14,
9224 POOL32F = 0x15,
9225 POOL32S = 0x16,
9226 DADDIU32 = 0x17,
9227
9228 POOL32C = 0x18,
9229 LWGP16 = 0x19,
9230 LW16 = 0x1a,
9231 POOL16E = 0x1b,
9232 XORI32 = 0x1c,
9233 JALS32 = 0x1d,
9234 ADDIUPC = 0x1e,
9235 POOL48A = 0x1f,
9236
9237 /* 0x20 is reserved */
9238 RES_20 = 0x20,
9239 POOL16F = 0x21,
9240 SB16 = 0x22,
9241 BEQZ16 = 0x23,
9242 SLTI32 = 0x24,
9243 BEQ32 = 0x25,
9244 SWC132 = 0x26,
9245 LWC132 = 0x27,
9246
9247 /* 0x28 and 0x29 are reserved */
9248 RES_28 = 0x28,
9249 RES_29 = 0x29,
9250 SH16 = 0x2a,
9251 BNEZ16 = 0x2b,
9252 SLTIU32 = 0x2c,
9253 BNE32 = 0x2d,
9254 SDC132 = 0x2e,
9255 LDC132 = 0x2f,
9256
9257 /* 0x30 and 0x31 are reserved */
9258 RES_30 = 0x30,
9259 RES_31 = 0x31,
9260 SWSP16 = 0x32,
9261 B16 = 0x33,
9262 ANDI32 = 0x34,
9263 J32 = 0x35,
9264 SD32 = 0x36,
9265 LD32 = 0x37,
9266
9267 /* 0x38 and 0x39 are reserved */
9268 RES_38 = 0x38,
9269 RES_39 = 0x39,
9270 SW16 = 0x3a,
9271 LI16 = 0x3b,
9272 JALX32 = 0x3c,
9273 JAL32 = 0x3d,
9274 SW32 = 0x3e,
9275 LW32 = 0x3f
9276};
9277
9278/* POOL32A encoding of minor opcode field */
9279
9280enum {
9281 /* These opcodes are distinguished only by bits 9..6; those bits are
9282 * what are recorded below. */
9283 SLL32 = 0x0,
9284 SRL32 = 0x1,
9285 SRA = 0x2,
9286 ROTR = 0x3,
9287
9288 SLLV = 0x0,
9289 SRLV = 0x1,
9290 SRAV = 0x2,
9291 ROTRV = 0x3,
9292 ADD = 0x4,
9293 ADDU32 = 0x5,
9294 SUB = 0x6,
9295 SUBU32 = 0x7,
9296 MUL = 0x8,
9297 AND = 0x9,
9298 OR32 = 0xa,
9299 NOR = 0xb,
9300 XOR32 = 0xc,
9301 SLT = 0xd,
9302 SLTU = 0xe,
9303
9304 MOVN = 0x0,
9305 MOVZ = 0x1,
9306 LWXS = 0x4,
9307
9308 /* The following can be distinguished by their lower 6 bits. */
9309 INS = 0x0c,
9310 EXT = 0x2c,
9311 POOL32AXF = 0x3c
9312};
9313
9314/* POOL32AXF encoding of minor opcode field extension */
9315
9316enum {
9317 /* bits 11..6 */
9318 TEQ = 0x00,
9319 TGE = 0x08,
9320 TGEU = 0x10,
9321 TLT = 0x20,
9322 TLTU = 0x28,
9323 TNE = 0x30,
9324
9325 MFC0 = 0x03,
9326 MTC0 = 0x0b,
9327
9328 /* bits 13..12 for 0x01 */
9329 MFHI_ACC = 0x0,
9330 MFLO_ACC = 0x1,
9331 MTHI_ACC = 0x2,
9332 MTLO_ACC = 0x3,
9333
9334 /* bits 13..12 for 0x2a */
9335 MADD_ACC = 0x0,
9336 MADDU_ACC = 0x1,
9337 MSUB_ACC = 0x2,
9338 MSUBU_ACC = 0x3,
9339
9340 /* bits 13..12 for 0x32 */
9341 MULT_ACC = 0x0,
9342 MULTU_ACC = 0x0,
9343
9344 /* bits 15..12 for 0x2c */
9345 SEB = 0x2,
9346 SEH = 0x3,
9347 CLO = 0x4,
9348 CLZ = 0x5,
9349 RDHWR = 0x6,
9350 WSBH = 0x7,
9351 MULT = 0x8,
9352 MULTU = 0x9,
9353 DIV = 0xa,
9354 DIVU = 0xb,
9355 MADD = 0xc,
9356 MADDU = 0xd,
9357 MSUB = 0xe,
9358 MSUBU = 0xf,
9359
9360 /* bits 15..12 for 0x34 */
9361 MFC2 = 0x4,
9362 MTC2 = 0x5,
9363 MFHC2 = 0x8,
9364 MTHC2 = 0x9,
9365 CFC2 = 0xc,
9366 CTC2 = 0xd,
9367
9368 /* bits 15..12 for 0x3c */
9369 JALR = 0x0,
9370 JR = 0x0, /* alias */
9371 JALR_HB = 0x1,
9372 JALRS = 0x4,
9373 JALRS_HB = 0x5,
9374
9375 /* bits 15..12 for 0x05 */
9376 RDPGPR = 0xe,
9377 WRPGPR = 0xf,
9378
9379 /* bits 15..12 for 0x0d */
9380 TLBP = 0x0,
9381 TLBR = 0x1,
9382 TLBWI = 0x2,
9383 TLBWR = 0x3,
9384 WAIT = 0x9,
9385 IRET = 0xd,
9386 DERET = 0xe,
9387 ERET = 0xf,
9388
9389 /* bits 15..12 for 0x15 */
9390 DMT = 0x0,
9391 DVPE = 0x1,
9392 EMT = 0x2,
9393 EVPE = 0x3,
9394
9395 /* bits 15..12 for 0x1d */
9396 DI = 0x4,
9397 EI = 0x5,
9398
9399 /* bits 15..12 for 0x2d */
9400 SYNC = 0x6,
9401 SYSCALL = 0x8,
9402 SDBBP = 0xd,
9403
9404 /* bits 15..12 for 0x35 */
9405 MFHI32 = 0x0,
9406 MFLO32 = 0x1,
9407 MTHI32 = 0x2,
9408 MTLO32 = 0x3,
9409};
9410
9411/* POOL32B encoding of minor opcode field (bits 15..12) */
9412
9413enum {
9414 LWC2 = 0x0,
9415 LWP = 0x1,
9416 LDP = 0x4,
9417 LWM32 = 0x5,
9418 CACHE = 0x6,
9419 LDM = 0x7,
9420 SWC2 = 0x8,
9421 SWP = 0x9,
9422 SDP = 0xc,
9423 SWM32 = 0xd,
9424 SDM = 0xf
9425};
9426
9427/* POOL32C encoding of minor opcode field (bits 15..12) */
9428
9429enum {
9430 LWL = 0x0,
9431 SWL = 0x8,
9432 LWR = 0x1,
9433 SWR = 0x9,
9434 PREF = 0x2,
9435 /* 0xa is reserved */
9436 LL = 0x3,
9437 SC = 0xb,
9438 LDL = 0x4,
9439 SDL = 0xc,
9440 LDR = 0x5,
9441 SDR = 0xd,
9442 /* 0x6 is reserved */
9443 LWU = 0xe,
9444 LLD = 0x7,
9445 SCD = 0xf
9446};
9447
9448/* POOL32F encoding of minor opcode field (bits 5..0) */
9449
9450enum {
9451 /* These are the bit 7..6 values */
9452 ADD_FMT = 0x0,
9453 MOVN_FMT = 0x0,
9454
9455 SUB_FMT = 0x1,
9456 MOVZ_FMT = 0x1,
9457
9458 MUL_FMT = 0x2,
9459
9460 DIV_FMT = 0x3,
9461
9462 /* These are the bit 8..6 values */
9463 RSQRT2_FMT = 0x0,
9464 MOVF_FMT = 0x0,
9465
9466 LWXC1 = 0x1,
9467 MOVT_FMT = 0x1,
9468
9469 PLL_PS = 0x2,
9470 SWXC1 = 0x2,
9471
9472 PLU_PS = 0x3,
9473 LDXC1 = 0x3,
9474
9475 PUL_PS = 0x4,
9476 SDXC1 = 0x4,
9477 RECIP2_FMT = 0x4,
9478
9479 PUU_PS = 0x5,
9480 LUXC1 = 0x5,
9481
9482 CVT_PS_S = 0x6,
9483 SUXC1 = 0x6,
9484 ADDR_PS = 0x6,
9485 PREFX = 0x6,
9486
9487 MULR_PS = 0x7,
9488
9489 MADD_S = 0x01,
9490 MADD_D = 0x09,
9491 MADD_PS = 0x11,
9492 ALNV_PS = 0x19,
9493 MSUB_S = 0x21,
9494 MSUB_D = 0x29,
9495 MSUB_PS = 0x31,
9496
9497 NMADD_S = 0x02,
9498 NMADD_D = 0x0a,
9499 NMADD_PS = 0x12,
9500 NMSUB_S = 0x22,
9501 NMSUB_D = 0x2a,
9502 NMSUB_PS = 0x32,
9503
9504 POOL32FXF = 0x3b,
9505
9506 CABS_COND_FMT = 0x1c, /* MIPS3D */
9507 C_COND_FMT = 0x3c
9508};
9509
9510/* POOL32Fxf encoding of minor opcode extension field */
9511
9512enum {
9513 CVT_L = 0x04,
9514 RSQRT_FMT = 0x08,
9515 FLOOR_L = 0x0c,
9516 CVT_PW_PS = 0x1c,
9517 CVT_W = 0x24,
9518 SQRT_FMT = 0x28,
9519 FLOOR_W = 0x2c,
9520 CVT_PS_PW = 0x3c,
9521 CFC1 = 0x40,
9522 RECIP_FMT = 0x48,
9523 CEIL_L = 0x4c,
9524 CTC1 = 0x60,
9525 CEIL_W = 0x6c,
9526 MFC1 = 0x80,
9527 CVT_S_PL = 0x84,
9528 TRUNC_L = 0x8c,
9529 MTC1 = 0xa0,
9530 CVT_S_PU = 0xa4,
9531 TRUNC_W = 0xac,
9532 MFHC1 = 0xc0,
9533 ROUND_L = 0xcc,
9534 MTHC1 = 0xe0,
9535 ROUND_W = 0xec,
9536
9537 MOV_FMT = 0x01,
9538 MOVF = 0x05,
9539 ABS_FMT = 0x0d,
9540 RSQRT1_FMT = 0x1d,
9541 MOVT = 0x25,
9542 NEG_FMT = 0x2d,
9543 CVT_D = 0x4d,
9544 RECIP1_FMT = 0x5d,
9545 CVT_S = 0x6d
9546};
9547
9548/* POOL32I encoding of minor opcode field (bits 25..21) */
9549
9550enum {
9551 BLTZ = 0x00,
9552 BLTZAL = 0x01,
9553 BGEZ = 0x02,
9554 BGEZAL = 0x03,
9555 BLEZ = 0x04,
9556 BNEZC = 0x05,
9557 BGTZ = 0x06,
9558 BEQZC = 0x07,
9559 TLTI = 0x08,
9560 TGEI = 0x09,
9561 TLTIU = 0x0a,
9562 TGEIU = 0x0b,
9563 TNEI = 0x0c,
9564 LUI = 0x0d,
9565 TEQI = 0x0e,
9566 SYNCI = 0x10,
9567 BLTZALS = 0x11,
9568 BGEZALS = 0x13,
9569 BC2F = 0x14,
9570 BC2T = 0x15,
9571 BPOSGE64 = 0x1a,
9572 BPOSGE32 = 0x1b,
9573 /* These overlap and are distinguished by bit16 of the instruction */
9574 BC1F = 0x1c,
9575 BC1T = 0x1d,
9576 BC1ANY2F = 0x1c,
9577 BC1ANY2T = 0x1d,
9578 BC1ANY4F = 0x1e,
9579 BC1ANY4T = 0x1f
9580};
9581
9582/* POOL16A encoding of minor opcode field */
9583
9584enum {
9585 ADDU16 = 0x0,
9586 SUBU16 = 0x1
9587};
9588
9589/* POOL16B encoding of minor opcode field */
9590
9591enum {
9592 SLL16 = 0x0,
9593 SRL16 = 0x1
9594};
9595
9596/* POOL16C encoding of minor opcode field */
9597
9598enum {
9599 NOT16 = 0x00,
9600 XOR16 = 0x04,
9601 AND16 = 0x08,
9602 OR16 = 0x0c,
9603 LWM16 = 0x10,
9604 SWM16 = 0x14,
9605 JR16 = 0x18,
9606 JRC16 = 0x1a,
9607 JALR16 = 0x1c,
9608 JALR16S = 0x1e,
9609 MFHI16 = 0x20,
9610 MFLO16 = 0x24,
9611 BREAK16 = 0x28,
9612 SDBBP16 = 0x2c,
9613 JRADDIUSP = 0x30
9614};
9615
9616/* POOL16D encoding of minor opcode field */
9617
9618enum {
9619 ADDIUS5 = 0x0,
9620 ADDIUSP = 0x1
9621};
9622
9623/* POOL16E encoding of minor opcode field */
9624
9625enum {
9626 ADDIUR2 = 0x0,
9627 ADDIUR1SP = 0x1
9628};
9629
9630static int mmreg (int r)
9631{
9632 static const int map[] = { 16, 17, 2, 3, 4, 5, 6, 7 };
9633
9634 return map[r];
9635}
9636
9637/* Used for 16-bit store instructions. */
9638static int mmreg2 (int r)
9639{
9640 static const int map[] = { 0, 17, 2, 3, 4, 5, 6, 7 };
9641
9642 return map[r];
9643}
9644
9645#define uMIPS_RD(op) ((op >> 7) & 0x7)
9646#define uMIPS_RS(op) ((op >> 4) & 0x7)
9647#define uMIPS_RS2(op) uMIPS_RS(op)
9648#define uMIPS_RS1(op) ((op >> 1) & 0x7)
9649#define uMIPS_RD5(op) ((op >> 5) & 0x1f)
9650#define uMIPS_RS5(op) (op & 0x1f)
9651
9652/* Signed immediate */
9653#define SIMM(op, start, width) \
9654 ((int32_t)(((op >> start) & ((~0U) >> (32-width))) \
9655 << (32-width)) \
9656 >> (32-width))
9657/* Zero-extended immediate */
9658#define ZIMM(op, start, width) ((op >> start) & ((~0U) >> (32-width)))
9659
9660static void gen_addiur1sp (CPUState *env, DisasContext *ctx)
9661{
9662 int rd = mmreg(uMIPS_RD(ctx->opcode));
9663
9664 gen_arith_imm(env, ctx, OPC_ADDIU, rd, 29, ((ctx->opcode >> 1) & 0x3f) << 2);
9665}
9666
9667static void gen_addiur2 (CPUState *env, DisasContext *ctx)
9668{
9669 static const int decoded_imm[] = { 1, 4, 8, 12, 16, 20, 24, -1 };
9670 int rd = mmreg(uMIPS_RD(ctx->opcode));
9671 int rs = mmreg(uMIPS_RS(ctx->opcode));
9672
9673 gen_arith_imm(env, ctx, OPC_ADDIU, rd, rs, decoded_imm[ZIMM(ctx->opcode, 1, 3)]);
9674}
9675
9676static void gen_addiusp (CPUState *env, DisasContext *ctx)
9677{
9678 int encoded = ZIMM(ctx->opcode, 1, 9);
9679 int decoded;
9680
9681 if (encoded <= 1) {
9682 decoded = 256 + encoded;
9683 } else if (encoded <= 255) {
9684 decoded = encoded;
9685 } else if (encoded <= 509) {
9686 decoded = encoded - 512;
9687 } else {
9688 decoded = encoded - 768;
9689 }
9690
9691 gen_arith_imm(env, ctx, OPC_ADDIU, 29, 29, decoded << 2);
9692}
9693
9694static void gen_addius5 (CPUState *env, DisasContext *ctx)
9695{
9696 int imm = SIMM(ctx->opcode, 1, 4);
9697 int rd = (ctx->opcode >> 5) & 0x1f;
9698
9699 gen_arith_imm(env, ctx, OPC_ADDIU, rd, rd, imm);
9700}
9701
9702static void gen_andi16 (CPUState *env, DisasContext *ctx)
9703{
9704 static const int decoded_imm[] = { 128, 1, 2, 3, 4, 7, 8, 15, 16,
9705 31, 32, 63, 64, 255, 32768, 65535 };
9706 int rd = mmreg(uMIPS_RD(ctx->opcode));
9707 int rs = mmreg(uMIPS_RS(ctx->opcode));
9708 int encoded = ZIMM(ctx->opcode, 0, 4);
9709
9710 gen_logic_imm(env, OPC_ANDI, rd, rs, decoded_imm[encoded]);
9711}
9712
9713static void gen_ldst_multiple (DisasContext *ctx, uint32_t opc, int reglist,
9714 int base, int16_t offset)
9715{
9716 TCGv t0, t1;
9717 TCGv_i32 t2;
9718
9719 if (ctx->hflags & MIPS_HFLAG_BMASK) {
9720 generate_exception(ctx, EXCP_RI);
9721 return;
9722 }
9723
9724 t0 = tcg_temp_new();
9725
9726 gen_base_offset_addr(ctx, t0, base, offset);
9727
9728 t1 = tcg_const_tl(reglist);
9729 t2 = tcg_const_i32(ctx->mem_idx);
6af0bf9c 9730
3c824109
NF
9731 save_cpu_state(ctx, 1);
9732 switch (opc) {
9733 case LWM32:
9734 gen_helper_lwm(t0, t1, t2);
9735 break;
9736 case SWM32:
9737 gen_helper_swm(t0, t1, t2);
9738 break;
9739#ifdef TARGET_MIPS64
9740 case LDM:
9741 gen_helper_ldm(t0, t1, t2);
9742 break;
9743 case SDM:
9744 gen_helper_sdm(t0, t1, t2);
9745 break;
6af0bf9c 9746#endif
3c824109
NF
9747 }
9748 MIPS_DEBUG("%s, %x, %d(%s)", opn, reglist, offset, regnames[base]);
9749 tcg_temp_free(t0);
33087598 9750 tcg_temp_free(t1);
3c824109
NF
9751 tcg_temp_free_i32(t2);
9752}
6af0bf9c 9753
3c824109
NF
9754
9755static void gen_pool16c_insn (CPUState *env, DisasContext *ctx, int *is_branch)
6af0bf9c 9756{
3c824109
NF
9757 int rd = mmreg((ctx->opcode >> 3) & 0x7);
9758 int rs = mmreg(ctx->opcode & 0x7);
9759 int opc;
6af0bf9c 9760
3c824109
NF
9761 switch (((ctx->opcode) >> 4) & 0x3f) {
9762 case NOT16 + 0:
9763 case NOT16 + 1:
9764 case NOT16 + 2:
9765 case NOT16 + 3:
9766 gen_logic(env, OPC_NOR, rd, rs, 0);
9767 break;
9768 case XOR16 + 0:
9769 case XOR16 + 1:
9770 case XOR16 + 2:
9771 case XOR16 + 3:
9772 gen_logic(env, OPC_XOR, rd, rd, rs);
9773 break;
9774 case AND16 + 0:
9775 case AND16 + 1:
9776 case AND16 + 2:
9777 case AND16 + 3:
9778 gen_logic(env, OPC_AND, rd, rd, rs);
9779 break;
9780 case OR16 + 0:
9781 case OR16 + 1:
9782 case OR16 + 2:
9783 case OR16 + 3:
9784 gen_logic(env, OPC_OR, rd, rd, rs);
9785 break;
9786 case LWM16 + 0:
9787 case LWM16 + 1:
9788 case LWM16 + 2:
9789 case LWM16 + 3:
9790 {
9791 static const int lwm_convert[] = { 0x11, 0x12, 0x13, 0x14 };
9792 int offset = ZIMM(ctx->opcode, 0, 4);
9793
9794 gen_ldst_multiple(ctx, LWM32, lwm_convert[(ctx->opcode >> 4) & 0x3],
9795 29, offset << 2);
9796 }
9797 break;
9798 case SWM16 + 0:
9799 case SWM16 + 1:
9800 case SWM16 + 2:
9801 case SWM16 + 3:
9802 {
9803 static const int swm_convert[] = { 0x11, 0x12, 0x13, 0x14 };
9804 int offset = ZIMM(ctx->opcode, 0, 4);
9805
9806 gen_ldst_multiple(ctx, SWM32, swm_convert[(ctx->opcode >> 4) & 0x3],
9807 29, offset << 2);
9808 }
9809 break;
9810 case JR16 + 0:
9811 case JR16 + 1:
9812 {
9813 int reg = ctx->opcode & 0x1f;
9814
9815 gen_compute_branch(ctx, OPC_JR, 2, reg, 0, 0);
9816 }
9817 *is_branch = 1;
9818 break;
9819 case JRC16 + 0:
9820 case JRC16 + 1:
9821 {
9822 int reg = ctx->opcode & 0x1f;
9823
9824 gen_compute_branch(ctx, OPC_JR, 2, reg, 0, 0);
9825 /* Let normal delay slot handling in our caller take us
9826 to the branch target. */
9827 }
9828 break;
9829 case JALR16 + 0:
9830 case JALR16 + 1:
9831 opc = OPC_JALR;
9832 goto do_jalr;
9833 case JALR16S + 0:
9834 case JALR16S + 1:
9835 opc = OPC_JALRS;
9836 do_jalr:
9837 {
9838 int reg = ctx->opcode & 0x1f;
9839
9840 gen_compute_branch(ctx, opc, 2, reg, 31, 0);
9841 }
9842 *is_branch = 1;
9843 break;
9844 case MFHI16 + 0:
9845 case MFHI16 + 1:
9846 gen_HILO(ctx, OPC_MFHI, uMIPS_RS5(ctx->opcode));
9847 break;
9848 case MFLO16 + 0:
9849 case MFLO16 + 1:
9850 gen_HILO(ctx, OPC_MFLO, uMIPS_RS5(ctx->opcode));
9851 break;
9852 case BREAK16:
9853 generate_exception(ctx, EXCP_BREAK);
9854 break;
9855 case SDBBP16:
9856 /* XXX: not clear which exception should be raised
9857 * when in debug mode...
9858 */
9859 check_insn(env, ctx, ISA_MIPS32);
9860 if (!(ctx->hflags & MIPS_HFLAG_DM)) {
9861 generate_exception(ctx, EXCP_DBp);
9862 } else {
9863 generate_exception(ctx, EXCP_DBp);
9864 }
9865 break;
9866 case JRADDIUSP + 0:
9867 case JRADDIUSP + 1:
9868 {
9869 int imm = ZIMM(ctx->opcode, 0, 5);
9870
9871 gen_compute_branch(ctx, OPC_JR, 2, 31, 0, 0);
9872 gen_arith_imm(env, ctx, OPC_ADDIU, 29, 29, imm << 2);
9873 /* Let normal delay slot handling in our caller take us
9874 to the branch target. */
9875 }
9876 break;
9877 default:
9878 generate_exception(ctx, EXCP_RI);
9879 break;
9880 }
9881}
9882
9883static void gen_ldxs (DisasContext *ctx, int base, int index, int rd)
9884{
9885 TCGv t0 = tcg_temp_new();
9886 TCGv t1 = tcg_temp_new();
9887
9888 gen_load_gpr(t0, base);
9889
9890 if (index != 0) {
9891 gen_load_gpr(t1, index);
9892 tcg_gen_shli_tl(t1, t1, 2);
9893 gen_op_addr_add(ctx, t0, t1, t0);
9894 }
9895
9896 save_cpu_state(ctx, 0);
5c13fdfd 9897 op_ld_lw(t1, t0, ctx);
3c824109
NF
9898 gen_store_gpr(t1, rd);
9899
9900 tcg_temp_free(t0);
9901 tcg_temp_free(t1);
9902}
9903
9904static void gen_ldst_pair (DisasContext *ctx, uint32_t opc, int rd,
9905 int base, int16_t offset)
9906{
9907 const char *opn = "ldst_pair";
9908 TCGv t0, t1;
9909
9910 if (ctx->hflags & MIPS_HFLAG_BMASK || rd == 31 || rd == base) {
9911 generate_exception(ctx, EXCP_RI);
d796321b
FB
9912 return;
9913 }
9914
3c824109
NF
9915 t0 = tcg_temp_new();
9916 t1 = tcg_temp_new();
8e9ade68 9917
3c824109
NF
9918 gen_base_offset_addr(ctx, t0, base, offset);
9919
9920 switch (opc) {
9921 case LWP:
9922 save_cpu_state(ctx, 0);
5c13fdfd 9923 op_ld_lw(t1, t0, ctx);
3c824109
NF
9924 gen_store_gpr(t1, rd);
9925 tcg_gen_movi_tl(t1, 4);
9926 gen_op_addr_add(ctx, t0, t0, t1);
5c13fdfd 9927 op_ld_lw(t1, t0, ctx);
3c824109
NF
9928 gen_store_gpr(t1, rd+1);
9929 opn = "lwp";
9930 break;
9931 case SWP:
9932 save_cpu_state(ctx, 1);
9933 gen_load_gpr(t1, rd);
5c13fdfd 9934 op_st_sw(t1, t0, ctx);
3c824109
NF
9935 tcg_gen_movi_tl(t1, 4);
9936 gen_op_addr_add(ctx, t0, t0, t1);
9937 gen_load_gpr(t1, rd+1);
5c13fdfd 9938 op_st_sw(t1, t0, ctx);
3c824109
NF
9939 opn = "swp";
9940 break;
9941#ifdef TARGET_MIPS64
9942 case LDP:
9943 save_cpu_state(ctx, 0);
5c13fdfd 9944 op_ld_ld(t1, t0, ctx);
3c824109
NF
9945 gen_store_gpr(t1, rd);
9946 tcg_gen_movi_tl(t1, 8);
9947 gen_op_addr_add(ctx, t0, t0, t1);
5c13fdfd 9948 op_ld_ld(t1, t0, ctx);
3c824109
NF
9949 gen_store_gpr(t1, rd+1);
9950 opn = "ldp";
9951 break;
9952 case SDP:
9953 save_cpu_state(ctx, 1);
9954 gen_load_gpr(t1, rd);
5c13fdfd 9955 op_st_sd(t1, t0, ctx);
3c824109
NF
9956 tcg_gen_movi_tl(t1, 8);
9957 gen_op_addr_add(ctx, t0, t0, t1);
9958 gen_load_gpr(t1, rd+1);
5c13fdfd 9959 op_st_sd(t1, t0, ctx);
3c824109
NF
9960 opn = "sdp";
9961 break;
9962#endif
6af0bf9c 9963 }
3c824109
NF
9964 MIPS_DEBUG("%s, %s, %d(%s)", opn, regnames[rd], offset, regnames[base]);
9965 tcg_temp_free(t0);
9966 tcg_temp_free(t1);
9967}
618b0fe9 9968
3c824109
NF
9969static void gen_pool32axf (CPUState *env, DisasContext *ctx, int rt, int rs,
9970 int *is_branch)
9971{
9972 int extension = (ctx->opcode >> 6) & 0x3f;
9973 int minor = (ctx->opcode >> 12) & 0xf;
9974 uint32_t mips32_op;
9975
9976 switch (extension) {
9977 case TEQ:
9978 mips32_op = OPC_TEQ;
9979 goto do_trap;
9980 case TGE:
9981 mips32_op = OPC_TGE;
9982 goto do_trap;
9983 case TGEU:
9984 mips32_op = OPC_TGEU;
9985 goto do_trap;
9986 case TLT:
9987 mips32_op = OPC_TLT;
9988 goto do_trap;
9989 case TLTU:
9990 mips32_op = OPC_TLTU;
9991 goto do_trap;
9992 case TNE:
9993 mips32_op = OPC_TNE;
9994 do_trap:
9995 gen_trap(ctx, mips32_op, rs, rt, -1);
9996 break;
9997#ifndef CONFIG_USER_ONLY
9998 case MFC0:
9999 case MFC0 + 32:
10000 if (rt == 0) {
10001 /* Treat as NOP. */
10002 break;
10003 }
10004 gen_mfc0(env, ctx, cpu_gpr[rt], rs, (ctx->opcode >> 11) & 0x7);
10005 break;
10006 case MTC0:
10007 case MTC0 + 32:
10008 {
10009 TCGv t0 = tcg_temp_new();
618b0fe9 10010
3c824109
NF
10011 gen_load_gpr(t0, rt);
10012 gen_mtc0(env, ctx, t0, rs, (ctx->opcode >> 11) & 0x7);
10013 tcg_temp_free(t0);
10014 }
10015 break;
10016#endif
10017 case 0x2c:
10018 switch (minor) {
10019 case SEB:
10020 gen_bshfl(ctx, OPC_SEB, rs, rt);
10021 break;
10022 case SEH:
10023 gen_bshfl(ctx, OPC_SEH, rs, rt);
10024 break;
10025 case CLO:
10026 mips32_op = OPC_CLO;
10027 goto do_cl;
10028 case CLZ:
10029 mips32_op = OPC_CLZ;
10030 do_cl:
10031 check_insn(env, ctx, ISA_MIPS32);
10032 gen_cl(ctx, mips32_op, rt, rs);
10033 break;
10034 case RDHWR:
10035 gen_rdhwr(env, ctx, rt, rs);
10036 break;
10037 case WSBH:
10038 gen_bshfl(ctx, OPC_WSBH, rs, rt);
10039 break;
10040 case MULT:
10041 mips32_op = OPC_MULT;
10042 goto do_muldiv;
10043 case MULTU:
10044 mips32_op = OPC_MULTU;
10045 goto do_muldiv;
10046 case DIV:
10047 mips32_op = OPC_DIV;
10048 goto do_muldiv;
10049 case DIVU:
10050 mips32_op = OPC_DIVU;
10051 goto do_muldiv;
10052 case MADD:
10053 mips32_op = OPC_MADD;
10054 goto do_muldiv;
10055 case MADDU:
10056 mips32_op = OPC_MADDU;
10057 goto do_muldiv;
10058 case MSUB:
10059 mips32_op = OPC_MSUB;
10060 goto do_muldiv;
10061 case MSUBU:
10062 mips32_op = OPC_MSUBU;
10063 do_muldiv:
10064 check_insn(env, ctx, ISA_MIPS32);
10065 gen_muldiv(ctx, mips32_op, rs, rt);
10066 break;
10067 default:
10068 goto pool32axf_invalid;
10069 }
10070 break;
10071 case 0x34:
10072 switch (minor) {
10073 case MFC2:
10074 case MTC2:
10075 case MFHC2:
10076 case MTHC2:
10077 case CFC2:
10078 case CTC2:
10079 generate_exception_err(ctx, EXCP_CpU, 2);
10080 break;
10081 default:
10082 goto pool32axf_invalid;
10083 }
10084 break;
10085 case 0x3c:
10086 switch (minor) {
10087 case JALR:
10088 case JALR_HB:
10089 gen_compute_branch (ctx, OPC_JALR, 4, rs, rt, 0);
10090 *is_branch = 1;
10091 break;
10092 case JALRS:
10093 case JALRS_HB:
10094 gen_compute_branch (ctx, OPC_JALRS, 4, rs, rt, 0);
10095 *is_branch = 1;
10096 break;
10097 default:
10098 goto pool32axf_invalid;
10099 }
10100 break;
10101 case 0x05:
10102 switch (minor) {
10103 case RDPGPR:
10104 check_insn(env, ctx, ISA_MIPS32R2);
10105 gen_load_srsgpr(rt, rs);
10106 break;
10107 case WRPGPR:
10108 check_insn(env, ctx, ISA_MIPS32R2);
10109 gen_store_srsgpr(rt, rs);
10110 break;
10111 default:
10112 goto pool32axf_invalid;
10113 }
10114 break;
10115#ifndef CONFIG_USER_ONLY
10116 case 0x0d:
10117 switch (minor) {
10118 case TLBP:
10119 mips32_op = OPC_TLBP;
10120 goto do_cp0;
10121 case TLBR:
10122 mips32_op = OPC_TLBR;
10123 goto do_cp0;
10124 case TLBWI:
10125 mips32_op = OPC_TLBWI;
10126 goto do_cp0;
10127 case TLBWR:
10128 mips32_op = OPC_TLBWR;
10129 goto do_cp0;
10130 case WAIT:
10131 mips32_op = OPC_WAIT;
10132 goto do_cp0;
10133 case DERET:
10134 mips32_op = OPC_DERET;
10135 goto do_cp0;
10136 case ERET:
10137 mips32_op = OPC_ERET;
10138 do_cp0:
10139 gen_cp0(env, ctx, mips32_op, rt, rs);
10140 break;
10141 default:
10142 goto pool32axf_invalid;
10143 }
10144 break;
10145 case 0x1d:
10146 switch (minor) {
10147 case DI:
10148 {
10149 TCGv t0 = tcg_temp_new();
10150
10151 save_cpu_state(ctx, 1);
10152 gen_helper_di(t0);
10153 gen_store_gpr(t0, rs);
10154 /* Stop translation as we may have switched the execution mode */
10155 ctx->bstate = BS_STOP;
10156 tcg_temp_free(t0);
10157 }
10158 break;
10159 case EI:
10160 {
10161 TCGv t0 = tcg_temp_new();
10162
10163 save_cpu_state(ctx, 1);
10164 gen_helper_ei(t0);
10165 gen_store_gpr(t0, rs);
10166 /* Stop translation as we may have switched the execution mode */
10167 ctx->bstate = BS_STOP;
10168 tcg_temp_free(t0);
10169 }
10170 break;
10171 default:
10172 goto pool32axf_invalid;
10173 }
10174 break;
10175#endif
10176 case 0x2d:
10177 switch (minor) {
10178 case SYNC:
10179 /* NOP */
10180 break;
10181 case SYSCALL:
10182 generate_exception(ctx, EXCP_SYSCALL);
10183 ctx->bstate = BS_STOP;
10184 break;
10185 case SDBBP:
10186 check_insn(env, ctx, ISA_MIPS32);
10187 if (!(ctx->hflags & MIPS_HFLAG_DM)) {
10188 generate_exception(ctx, EXCP_DBp);
10189 } else {
10190 generate_exception(ctx, EXCP_DBp);
10191 }
10192 break;
10193 default:
10194 goto pool32axf_invalid;
10195 }
10196 break;
10197 case 0x35:
10198 switch (minor) {
10199 case MFHI32:
10200 gen_HILO(ctx, OPC_MFHI, rs);
10201 break;
10202 case MFLO32:
10203 gen_HILO(ctx, OPC_MFLO, rs);
10204 break;
10205 case MTHI32:
10206 gen_HILO(ctx, OPC_MTHI, rs);
10207 break;
10208 case MTLO32:
10209 gen_HILO(ctx, OPC_MTLO, rs);
10210 break;
10211 default:
10212 goto pool32axf_invalid;
10213 }
10214 break;
10215 default:
10216 pool32axf_invalid:
10217 MIPS_INVAL("pool32axf");
10218 generate_exception(ctx, EXCP_RI);
10219 break;
10220 }
10221}
10222
10223/* Values for microMIPS fmt field. Variable-width, depending on which
10224 formats the instruction supports. */
10225
10226enum {
10227 FMT_SD_S = 0,
10228 FMT_SD_D = 1,
10229
10230 FMT_SDPS_S = 0,
10231 FMT_SDPS_D = 1,
10232 FMT_SDPS_PS = 2,
10233
10234 FMT_SWL_S = 0,
10235 FMT_SWL_W = 1,
10236 FMT_SWL_L = 2,
10237
10238 FMT_DWL_D = 0,
10239 FMT_DWL_W = 1,
10240 FMT_DWL_L = 2
10241};
10242
10243static void gen_pool32fxf (CPUState *env, DisasContext *ctx, int rt, int rs)
10244{
10245 int extension = (ctx->opcode >> 6) & 0x3ff;
10246 uint32_t mips32_op;
10247
10248#define FLOAT_1BIT_FMT(opc, fmt) (fmt << 8) | opc
10249#define FLOAT_2BIT_FMT(opc, fmt) (fmt << 7) | opc
10250#define COND_FLOAT_MOV(opc, cond) (cond << 7) | opc
10251
10252 switch (extension) {
10253 case FLOAT_1BIT_FMT(CFC1, 0):
10254 mips32_op = OPC_CFC1;
10255 goto do_cp1;
10256 case FLOAT_1BIT_FMT(CTC1, 0):
10257 mips32_op = OPC_CTC1;
10258 goto do_cp1;
10259 case FLOAT_1BIT_FMT(MFC1, 0):
10260 mips32_op = OPC_MFC1;
10261 goto do_cp1;
10262 case FLOAT_1BIT_FMT(MTC1, 0):
10263 mips32_op = OPC_MTC1;
10264 goto do_cp1;
10265 case FLOAT_1BIT_FMT(MFHC1, 0):
10266 mips32_op = OPC_MFHC1;
10267 goto do_cp1;
10268 case FLOAT_1BIT_FMT(MTHC1, 0):
10269 mips32_op = OPC_MTHC1;
10270 do_cp1:
10271 gen_cp1(ctx, mips32_op, rt, rs);
10272 break;
10273
10274 /* Reciprocal square root */
10275 case FLOAT_1BIT_FMT(RSQRT_FMT, FMT_SD_S):
10276 mips32_op = OPC_RSQRT_S;
10277 goto do_unaryfp;
10278 case FLOAT_1BIT_FMT(RSQRT_FMT, FMT_SD_D):
10279 mips32_op = OPC_RSQRT_D;
10280 goto do_unaryfp;
10281
10282 /* Square root */
10283 case FLOAT_1BIT_FMT(SQRT_FMT, FMT_SD_S):
10284 mips32_op = OPC_SQRT_S;
10285 goto do_unaryfp;
10286 case FLOAT_1BIT_FMT(SQRT_FMT, FMT_SD_D):
10287 mips32_op = OPC_SQRT_D;
10288 goto do_unaryfp;
10289
10290 /* Reciprocal */
10291 case FLOAT_1BIT_FMT(RECIP_FMT, FMT_SD_S):
10292 mips32_op = OPC_RECIP_S;
10293 goto do_unaryfp;
10294 case FLOAT_1BIT_FMT(RECIP_FMT, FMT_SD_D):
10295 mips32_op = OPC_RECIP_D;
10296 goto do_unaryfp;
10297
10298 /* Floor */
10299 case FLOAT_1BIT_FMT(FLOOR_L, FMT_SD_S):
10300 mips32_op = OPC_FLOOR_L_S;
10301 goto do_unaryfp;
10302 case FLOAT_1BIT_FMT(FLOOR_L, FMT_SD_D):
10303 mips32_op = OPC_FLOOR_L_D;
10304 goto do_unaryfp;
10305 case FLOAT_1BIT_FMT(FLOOR_W, FMT_SD_S):
10306 mips32_op = OPC_FLOOR_W_S;
10307 goto do_unaryfp;
10308 case FLOAT_1BIT_FMT(FLOOR_W, FMT_SD_D):
10309 mips32_op = OPC_FLOOR_W_D;
10310 goto do_unaryfp;
10311
10312 /* Ceiling */
10313 case FLOAT_1BIT_FMT(CEIL_L, FMT_SD_S):
10314 mips32_op = OPC_CEIL_L_S;
10315 goto do_unaryfp;
10316 case FLOAT_1BIT_FMT(CEIL_L, FMT_SD_D):
10317 mips32_op = OPC_CEIL_L_D;
10318 goto do_unaryfp;
10319 case FLOAT_1BIT_FMT(CEIL_W, FMT_SD_S):
10320 mips32_op = OPC_CEIL_W_S;
10321 goto do_unaryfp;
10322 case FLOAT_1BIT_FMT(CEIL_W, FMT_SD_D):
10323 mips32_op = OPC_CEIL_W_D;
10324 goto do_unaryfp;
10325
10326 /* Truncation */
10327 case FLOAT_1BIT_FMT(TRUNC_L, FMT_SD_S):
10328 mips32_op = OPC_TRUNC_L_S;
10329 goto do_unaryfp;
10330 case FLOAT_1BIT_FMT(TRUNC_L, FMT_SD_D):
10331 mips32_op = OPC_TRUNC_L_D;
10332 goto do_unaryfp;
10333 case FLOAT_1BIT_FMT(TRUNC_W, FMT_SD_S):
10334 mips32_op = OPC_TRUNC_W_S;
10335 goto do_unaryfp;
10336 case FLOAT_1BIT_FMT(TRUNC_W, FMT_SD_D):
10337 mips32_op = OPC_TRUNC_W_D;
10338 goto do_unaryfp;
10339
10340 /* Round */
10341 case FLOAT_1BIT_FMT(ROUND_L, FMT_SD_S):
10342 mips32_op = OPC_ROUND_L_S;
10343 goto do_unaryfp;
10344 case FLOAT_1BIT_FMT(ROUND_L, FMT_SD_D):
10345 mips32_op = OPC_ROUND_L_D;
10346 goto do_unaryfp;
10347 case FLOAT_1BIT_FMT(ROUND_W, FMT_SD_S):
10348 mips32_op = OPC_ROUND_W_S;
10349 goto do_unaryfp;
10350 case FLOAT_1BIT_FMT(ROUND_W, FMT_SD_D):
10351 mips32_op = OPC_ROUND_W_D;
10352 goto do_unaryfp;
10353
10354 /* Integer to floating-point conversion */
10355 case FLOAT_1BIT_FMT(CVT_L, FMT_SD_S):
10356 mips32_op = OPC_CVT_L_S;
10357 goto do_unaryfp;
10358 case FLOAT_1BIT_FMT(CVT_L, FMT_SD_D):
10359 mips32_op = OPC_CVT_L_D;
10360 goto do_unaryfp;
10361 case FLOAT_1BIT_FMT(CVT_W, FMT_SD_S):
10362 mips32_op = OPC_CVT_W_S;
10363 goto do_unaryfp;
10364 case FLOAT_1BIT_FMT(CVT_W, FMT_SD_D):
10365 mips32_op = OPC_CVT_W_D;
10366 goto do_unaryfp;
10367
10368 /* Paired-foo conversions */
10369 case FLOAT_1BIT_FMT(CVT_S_PL, 0):
10370 mips32_op = OPC_CVT_S_PL;
10371 goto do_unaryfp;
10372 case FLOAT_1BIT_FMT(CVT_S_PU, 0):
10373 mips32_op = OPC_CVT_S_PU;
10374 goto do_unaryfp;
10375 case FLOAT_1BIT_FMT(CVT_PW_PS, 0):
10376 mips32_op = OPC_CVT_PW_PS;
10377 goto do_unaryfp;
10378 case FLOAT_1BIT_FMT(CVT_PS_PW, 0):
10379 mips32_op = OPC_CVT_PS_PW;
10380 goto do_unaryfp;
10381
10382 /* Floating-point moves */
10383 case FLOAT_2BIT_FMT(MOV_FMT, FMT_SDPS_S):
10384 mips32_op = OPC_MOV_S;
10385 goto do_unaryfp;
10386 case FLOAT_2BIT_FMT(MOV_FMT, FMT_SDPS_D):
10387 mips32_op = OPC_MOV_D;
10388 goto do_unaryfp;
10389 case FLOAT_2BIT_FMT(MOV_FMT, FMT_SDPS_PS):
10390 mips32_op = OPC_MOV_PS;
10391 goto do_unaryfp;
10392
10393 /* Absolute value */
10394 case FLOAT_2BIT_FMT(ABS_FMT, FMT_SDPS_S):
10395 mips32_op = OPC_ABS_S;
10396 goto do_unaryfp;
10397 case FLOAT_2BIT_FMT(ABS_FMT, FMT_SDPS_D):
10398 mips32_op = OPC_ABS_D;
10399 goto do_unaryfp;
10400 case FLOAT_2BIT_FMT(ABS_FMT, FMT_SDPS_PS):
10401 mips32_op = OPC_ABS_PS;
10402 goto do_unaryfp;
10403
10404 /* Negation */
10405 case FLOAT_2BIT_FMT(NEG_FMT, FMT_SDPS_S):
10406 mips32_op = OPC_NEG_S;
10407 goto do_unaryfp;
10408 case FLOAT_2BIT_FMT(NEG_FMT, FMT_SDPS_D):
10409 mips32_op = OPC_NEG_D;
10410 goto do_unaryfp;
10411 case FLOAT_2BIT_FMT(NEG_FMT, FMT_SDPS_PS):
10412 mips32_op = OPC_NEG_PS;
10413 goto do_unaryfp;
10414
10415 /* Reciprocal square root step */
10416 case FLOAT_2BIT_FMT(RSQRT1_FMT, FMT_SDPS_S):
10417 mips32_op = OPC_RSQRT1_S;
10418 goto do_unaryfp;
10419 case FLOAT_2BIT_FMT(RSQRT1_FMT, FMT_SDPS_D):
10420 mips32_op = OPC_RSQRT1_D;
10421 goto do_unaryfp;
10422 case FLOAT_2BIT_FMT(RSQRT1_FMT, FMT_SDPS_PS):
10423 mips32_op = OPC_RSQRT1_PS;
10424 goto do_unaryfp;
10425
10426 /* Reciprocal step */
10427 case FLOAT_2BIT_FMT(RECIP1_FMT, FMT_SDPS_S):
10428 mips32_op = OPC_RECIP1_S;
10429 goto do_unaryfp;
10430 case FLOAT_2BIT_FMT(RECIP1_FMT, FMT_SDPS_D):
10431 mips32_op = OPC_RECIP1_S;
10432 goto do_unaryfp;
10433 case FLOAT_2BIT_FMT(RECIP1_FMT, FMT_SDPS_PS):
10434 mips32_op = OPC_RECIP1_PS;
10435 goto do_unaryfp;
10436
10437 /* Conversions from double */
10438 case FLOAT_2BIT_FMT(CVT_D, FMT_SWL_S):
10439 mips32_op = OPC_CVT_D_S;
10440 goto do_unaryfp;
10441 case FLOAT_2BIT_FMT(CVT_D, FMT_SWL_W):
10442 mips32_op = OPC_CVT_D_W;
10443 goto do_unaryfp;
10444 case FLOAT_2BIT_FMT(CVT_D, FMT_SWL_L):
10445 mips32_op = OPC_CVT_D_L;
10446 goto do_unaryfp;
10447
10448 /* Conversions from single */
10449 case FLOAT_2BIT_FMT(CVT_S, FMT_DWL_D):
10450 mips32_op = OPC_CVT_S_D;
10451 goto do_unaryfp;
10452 case FLOAT_2BIT_FMT(CVT_S, FMT_DWL_W):
10453 mips32_op = OPC_CVT_S_W;
10454 goto do_unaryfp;
10455 case FLOAT_2BIT_FMT(CVT_S, FMT_DWL_L):
10456 mips32_op = OPC_CVT_S_L;
10457 do_unaryfp:
10458 gen_farith(ctx, mips32_op, -1, rs, rt, 0);
10459 break;
10460
10461 /* Conditional moves on floating-point codes */
10462 case COND_FLOAT_MOV(MOVT, 0):
10463 case COND_FLOAT_MOV(MOVT, 1):
10464 case COND_FLOAT_MOV(MOVT, 2):
10465 case COND_FLOAT_MOV(MOVT, 3):
10466 case COND_FLOAT_MOV(MOVT, 4):
10467 case COND_FLOAT_MOV(MOVT, 5):
10468 case COND_FLOAT_MOV(MOVT, 6):
10469 case COND_FLOAT_MOV(MOVT, 7):
10470 gen_movci(ctx, rt, rs, (ctx->opcode >> 13) & 0x7, 1);
10471 break;
10472 case COND_FLOAT_MOV(MOVF, 0):
10473 case COND_FLOAT_MOV(MOVF, 1):
10474 case COND_FLOAT_MOV(MOVF, 2):
10475 case COND_FLOAT_MOV(MOVF, 3):
10476 case COND_FLOAT_MOV(MOVF, 4):
10477 case COND_FLOAT_MOV(MOVF, 5):
10478 case COND_FLOAT_MOV(MOVF, 6):
10479 case COND_FLOAT_MOV(MOVF, 7):
10480 gen_movci(ctx, rt, rs, (ctx->opcode >> 13) & 0x7, 0);
10481 break;
10482 default:
10483 MIPS_INVAL("pool32fxf");
10484 generate_exception(ctx, EXCP_RI);
10485 break;
10486 }
10487}
10488
10489static void decode_micromips32_opc (CPUState *env, DisasContext *ctx,
10490 uint16_t insn_hw1, int *is_branch)
10491{
10492 int32_t offset;
10493 uint16_t insn;
10494 int rt, rs, rd, rr;
10495 int16_t imm;
10496 uint32_t op, minor, mips32_op;
10497 uint32_t cond, fmt, cc;
10498
10499 insn = lduw_code(ctx->pc + 2);
10500 ctx->opcode = (ctx->opcode << 16) | insn;
10501
10502 rt = (ctx->opcode >> 21) & 0x1f;
10503 rs = (ctx->opcode >> 16) & 0x1f;
10504 rd = (ctx->opcode >> 11) & 0x1f;
10505 rr = (ctx->opcode >> 6) & 0x1f;
10506 imm = (int16_t) ctx->opcode;
10507
10508 op = (ctx->opcode >> 26) & 0x3f;
10509 switch (op) {
10510 case POOL32A:
10511 minor = ctx->opcode & 0x3f;
10512 switch (minor) {
10513 case 0x00:
10514 minor = (ctx->opcode >> 6) & 0xf;
10515 switch (minor) {
10516 case SLL32:
10517 mips32_op = OPC_SLL;
10518 goto do_shifti;
10519 case SRA:
10520 mips32_op = OPC_SRA;
10521 goto do_shifti;
10522 case SRL32:
10523 mips32_op = OPC_SRL;
10524 goto do_shifti;
10525 case ROTR:
10526 mips32_op = OPC_ROTR;
10527 do_shifti:
10528 gen_shift_imm(env, ctx, mips32_op, rt, rs, rd);
10529 break;
10530 default:
10531 goto pool32a_invalid;
10532 }
10533 break;
10534 case 0x10:
10535 minor = (ctx->opcode >> 6) & 0xf;
10536 switch (minor) {
10537 /* Arithmetic */
10538 case ADD:
10539 mips32_op = OPC_ADD;
10540 goto do_arith;
10541 case ADDU32:
10542 mips32_op = OPC_ADDU;
10543 goto do_arith;
10544 case SUB:
10545 mips32_op = OPC_SUB;
10546 goto do_arith;
10547 case SUBU32:
10548 mips32_op = OPC_SUBU;
10549 goto do_arith;
10550 case MUL:
10551 mips32_op = OPC_MUL;
10552 do_arith:
10553 gen_arith(env, ctx, mips32_op, rd, rs, rt);
10554 break;
10555 /* Shifts */
10556 case SLLV:
10557 mips32_op = OPC_SLLV;
10558 goto do_shift;
10559 case SRLV:
10560 mips32_op = OPC_SRLV;
10561 goto do_shift;
10562 case SRAV:
10563 mips32_op = OPC_SRAV;
10564 goto do_shift;
10565 case ROTRV:
10566 mips32_op = OPC_ROTRV;
10567 do_shift:
10568 gen_shift(env, ctx, mips32_op, rd, rs, rt);
10569 break;
10570 /* Logical operations */
10571 case AND:
10572 mips32_op = OPC_AND;
10573 goto do_logic;
10574 case OR32:
10575 mips32_op = OPC_OR;
10576 goto do_logic;
10577 case NOR:
10578 mips32_op = OPC_NOR;
10579 goto do_logic;
10580 case XOR32:
10581 mips32_op = OPC_XOR;
10582 do_logic:
10583 gen_logic(env, mips32_op, rd, rs, rt);
10584 break;
10585 /* Set less than */
10586 case SLT:
10587 mips32_op = OPC_SLT;
10588 goto do_slt;
10589 case SLTU:
10590 mips32_op = OPC_SLTU;
10591 do_slt:
10592 gen_slt(env, mips32_op, rd, rs, rt);
10593 break;
10594 default:
10595 goto pool32a_invalid;
10596 }
10597 break;
10598 case 0x18:
10599 minor = (ctx->opcode >> 6) & 0xf;
10600 switch (minor) {
10601 /* Conditional moves */
10602 case MOVN:
10603 mips32_op = OPC_MOVN;
10604 goto do_cmov;
10605 case MOVZ:
10606 mips32_op = OPC_MOVZ;
10607 do_cmov:
10608 gen_cond_move(env, mips32_op, rd, rs, rt);
10609 break;
10610 case LWXS:
10611 gen_ldxs(ctx, rs, rt, rd);
10612 break;
10613 default:
10614 goto pool32a_invalid;
10615 }
10616 break;
10617 case INS:
10618 gen_bitops(ctx, OPC_INS, rt, rs, rr, rd);
10619 return;
10620 case EXT:
10621 gen_bitops(ctx, OPC_EXT, rt, rs, rr, rd);
10622 return;
10623 case POOL32AXF:
10624 gen_pool32axf(env, ctx, rt, rs, is_branch);
10625 break;
10626 case 0x07:
10627 generate_exception(ctx, EXCP_BREAK);
10628 break;
10629 default:
10630 pool32a_invalid:
10631 MIPS_INVAL("pool32a");
10632 generate_exception(ctx, EXCP_RI);
10633 break;
10634 }
10635 break;
10636 case POOL32B:
10637 minor = (ctx->opcode >> 12) & 0xf;
10638 switch (minor) {
10639 case CACHE:
10640 /* Treat as no-op. */
10641 break;
10642 case LWC2:
10643 case SWC2:
10644 /* COP2: Not implemented. */
10645 generate_exception_err(ctx, EXCP_CpU, 2);
10646 break;
10647 case LWP:
10648 case SWP:
10649#ifdef TARGET_MIPS64
10650 case LDP:
10651 case SDP:
10652#endif
10653 gen_ldst_pair(ctx, minor, rt, rs, SIMM(ctx->opcode, 0, 12));
10654 break;
10655 case LWM32:
10656 case SWM32:
10657#ifdef TARGET_MIPS64
10658 case LDM:
10659 case SDM:
10660#endif
10661 gen_ldst_multiple(ctx, minor, rt, rs, SIMM(ctx->opcode, 0, 12));
10662 break;
10663 default:
10664 MIPS_INVAL("pool32b");
10665 generate_exception(ctx, EXCP_RI);
10666 break;
10667 }
10668 break;
10669 case POOL32F:
10670 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
10671 minor = ctx->opcode & 0x3f;
10672 check_cp1_enabled(ctx);
10673 switch (minor) {
10674 case ALNV_PS:
10675 mips32_op = OPC_ALNV_PS;
10676 goto do_madd;
10677 case MADD_S:
10678 mips32_op = OPC_MADD_S;
10679 goto do_madd;
10680 case MADD_D:
10681 mips32_op = OPC_MADD_D;
10682 goto do_madd;
10683 case MADD_PS:
10684 mips32_op = OPC_MADD_PS;
10685 goto do_madd;
10686 case MSUB_S:
10687 mips32_op = OPC_MSUB_S;
10688 goto do_madd;
10689 case MSUB_D:
10690 mips32_op = OPC_MSUB_D;
10691 goto do_madd;
10692 case MSUB_PS:
10693 mips32_op = OPC_MSUB_PS;
10694 goto do_madd;
10695 case NMADD_S:
10696 mips32_op = OPC_NMADD_S;
10697 goto do_madd;
10698 case NMADD_D:
10699 mips32_op = OPC_NMADD_D;
10700 goto do_madd;
10701 case NMADD_PS:
10702 mips32_op = OPC_NMADD_PS;
10703 goto do_madd;
10704 case NMSUB_S:
10705 mips32_op = OPC_NMSUB_S;
10706 goto do_madd;
10707 case NMSUB_D:
10708 mips32_op = OPC_NMSUB_D;
10709 goto do_madd;
10710 case NMSUB_PS:
10711 mips32_op = OPC_NMSUB_PS;
10712 do_madd:
10713 gen_flt3_arith(ctx, mips32_op, rd, rr, rs, rt);
10714 break;
10715 case CABS_COND_FMT:
10716 cond = (ctx->opcode >> 6) & 0xf;
10717 cc = (ctx->opcode >> 13) & 0x7;
10718 fmt = (ctx->opcode >> 10) & 0x3;
10719 switch (fmt) {
10720 case 0x0:
10721 gen_cmpabs_s(ctx, cond, rt, rs, cc);
10722 break;
10723 case 0x1:
10724 gen_cmpabs_d(ctx, cond, rt, rs, cc);
10725 break;
10726 case 0x2:
10727 gen_cmpabs_ps(ctx, cond, rt, rs, cc);
10728 break;
10729 default:
10730 goto pool32f_invalid;
10731 }
10732 break;
10733 case C_COND_FMT:
10734 cond = (ctx->opcode >> 6) & 0xf;
10735 cc = (ctx->opcode >> 13) & 0x7;
10736 fmt = (ctx->opcode >> 10) & 0x3;
10737 switch (fmt) {
10738 case 0x0:
10739 gen_cmp_s(ctx, cond, rt, rs, cc);
10740 break;
10741 case 0x1:
10742 gen_cmp_d(ctx, cond, rt, rs, cc);
10743 break;
10744 case 0x2:
10745 gen_cmp_ps(ctx, cond, rt, rs, cc);
10746 break;
10747 default:
10748 goto pool32f_invalid;
10749 }
10750 break;
10751 case POOL32FXF:
10752 gen_pool32fxf(env, ctx, rt, rs);
10753 break;
10754 case 0x00:
10755 /* PLL foo */
10756 switch ((ctx->opcode >> 6) & 0x7) {
10757 case PLL_PS:
10758 mips32_op = OPC_PLL_PS;
10759 goto do_ps;
10760 case PLU_PS:
10761 mips32_op = OPC_PLU_PS;
10762 goto do_ps;
10763 case PUL_PS:
10764 mips32_op = OPC_PUL_PS;
10765 goto do_ps;
10766 case PUU_PS:
10767 mips32_op = OPC_PUU_PS;
10768 goto do_ps;
10769 case CVT_PS_S:
10770 mips32_op = OPC_CVT_PS_S;
10771 do_ps:
10772 gen_farith(ctx, mips32_op, rt, rs, rd, 0);
10773 break;
10774 default:
10775 goto pool32f_invalid;
10776 }
10777 break;
10778 case 0x08:
10779 /* [LS][WDU]XC1 */
10780 switch ((ctx->opcode >> 6) & 0x7) {
10781 case LWXC1:
10782 mips32_op = OPC_LWXC1;
10783 goto do_ldst_cp1;
10784 case SWXC1:
10785 mips32_op = OPC_SWXC1;
10786 goto do_ldst_cp1;
10787 case LDXC1:
10788 mips32_op = OPC_LDXC1;
10789 goto do_ldst_cp1;
10790 case SDXC1:
10791 mips32_op = OPC_SDXC1;
10792 goto do_ldst_cp1;
10793 case LUXC1:
10794 mips32_op = OPC_LUXC1;
10795 goto do_ldst_cp1;
10796 case SUXC1:
10797 mips32_op = OPC_SUXC1;
10798 do_ldst_cp1:
10799 gen_flt3_ldst(ctx, mips32_op, rd, rd, rt, rs);
10800 break;
10801 default:
10802 goto pool32f_invalid;
10803 }
10804 break;
10805 case 0x18:
10806 /* 3D insns */
10807 fmt = (ctx->opcode >> 9) & 0x3;
10808 switch ((ctx->opcode >> 6) & 0x7) {
10809 case RSQRT2_FMT:
10810 switch (fmt) {
10811 case FMT_SDPS_S:
10812 mips32_op = OPC_RSQRT2_S;
10813 goto do_3d;
10814 case FMT_SDPS_D:
10815 mips32_op = OPC_RSQRT2_D;
10816 goto do_3d;
10817 case FMT_SDPS_PS:
10818 mips32_op = OPC_RSQRT2_PS;
10819 goto do_3d;
10820 default:
10821 goto pool32f_invalid;
10822 }
10823 break;
10824 case RECIP2_FMT:
10825 switch (fmt) {
10826 case FMT_SDPS_S:
10827 mips32_op = OPC_RECIP2_S;
10828 goto do_3d;
10829 case FMT_SDPS_D:
10830 mips32_op = OPC_RECIP2_D;
10831 goto do_3d;
10832 case FMT_SDPS_PS:
10833 mips32_op = OPC_RECIP2_PS;
10834 goto do_3d;
10835 default:
10836 goto pool32f_invalid;
10837 }
10838 break;
10839 case ADDR_PS:
10840 mips32_op = OPC_ADDR_PS;
10841 goto do_3d;
10842 case MULR_PS:
10843 mips32_op = OPC_MULR_PS;
10844 do_3d:
10845 gen_farith(ctx, mips32_op, rt, rs, rd, 0);
10846 break;
10847 default:
10848 goto pool32f_invalid;
10849 }
10850 break;
10851 case 0x20:
10852 /* MOV[FT].fmt and PREFX */
10853 cc = (ctx->opcode >> 13) & 0x7;
10854 fmt = (ctx->opcode >> 9) & 0x3;
10855 switch ((ctx->opcode >> 6) & 0x7) {
10856 case MOVF_FMT:
10857 switch (fmt) {
10858 case FMT_SDPS_S:
10859 gen_movcf_s(rs, rt, cc, 0);
10860 break;
10861 case FMT_SDPS_D:
10862 gen_movcf_d(ctx, rs, rt, cc, 0);
10863 break;
10864 case FMT_SDPS_PS:
10865 gen_movcf_ps(rs, rt, cc, 0);
10866 break;
10867 default:
10868 goto pool32f_invalid;
10869 }
10870 break;
10871 case MOVT_FMT:
10872 switch (fmt) {
10873 case FMT_SDPS_S:
10874 gen_movcf_s(rs, rt, cc, 1);
10875 break;
10876 case FMT_SDPS_D:
10877 gen_movcf_d(ctx, rs, rt, cc, 1);
10878 break;
10879 case FMT_SDPS_PS:
10880 gen_movcf_ps(rs, rt, cc, 1);
10881 break;
10882 default:
10883 goto pool32f_invalid;
10884 }
10885 break;
10886 case PREFX:
10887 break;
10888 default:
10889 goto pool32f_invalid;
10890 }
10891 break;
10892#define FINSN_3ARG_SDPS(prfx) \
10893 switch ((ctx->opcode >> 8) & 0x3) { \
10894 case FMT_SDPS_S: \
10895 mips32_op = OPC_##prfx##_S; \
10896 goto do_fpop; \
10897 case FMT_SDPS_D: \
10898 mips32_op = OPC_##prfx##_D; \
10899 goto do_fpop; \
10900 case FMT_SDPS_PS: \
10901 mips32_op = OPC_##prfx##_PS; \
10902 goto do_fpop; \
10903 default: \
10904 goto pool32f_invalid; \
10905 }
10906 case 0x30:
10907 /* regular FP ops */
10908 switch ((ctx->opcode >> 6) & 0x3) {
10909 case ADD_FMT:
10910 FINSN_3ARG_SDPS(ADD);
10911 break;
10912 case SUB_FMT:
10913 FINSN_3ARG_SDPS(SUB);
10914 break;
10915 case MUL_FMT:
10916 FINSN_3ARG_SDPS(MUL);
10917 break;
10918 case DIV_FMT:
10919 fmt = (ctx->opcode >> 8) & 0x3;
10920 if (fmt == 1) {
10921 mips32_op = OPC_DIV_D;
10922 } else if (fmt == 0) {
10923 mips32_op = OPC_DIV_S;
10924 } else {
10925 goto pool32f_invalid;
10926 }
10927 goto do_fpop;
10928 default:
10929 goto pool32f_invalid;
10930 }
10931 break;
10932 case 0x38:
10933 /* cmovs */
10934 switch ((ctx->opcode >> 6) & 0x3) {
10935 case MOVN_FMT:
10936 FINSN_3ARG_SDPS(MOVN);
10937 break;
10938 case MOVZ_FMT:
10939 FINSN_3ARG_SDPS(MOVZ);
10940 break;
10941 default:
10942 goto pool32f_invalid;
10943 }
10944 break;
10945 do_fpop:
10946 gen_farith(ctx, mips32_op, rt, rs, rd, 0);
10947 break;
10948 default:
10949 pool32f_invalid:
10950 MIPS_INVAL("pool32f");
10951 generate_exception(ctx, EXCP_RI);
10952 break;
10953 }
10954 } else {
10955 generate_exception_err(ctx, EXCP_CpU, 1);
10956 }
10957 break;
10958 case POOL32I:
10959 minor = (ctx->opcode >> 21) & 0x1f;
10960 switch (minor) {
10961 case BLTZ:
10962 mips32_op = OPC_BLTZ;
10963 goto do_branch;
10964 case BLTZAL:
10965 mips32_op = OPC_BLTZAL;
10966 goto do_branch;
10967 case BLTZALS:
10968 mips32_op = OPC_BLTZALS;
10969 goto do_branch;
10970 case BGEZ:
10971 mips32_op = OPC_BGEZ;
10972 goto do_branch;
10973 case BGEZAL:
10974 mips32_op = OPC_BGEZAL;
10975 goto do_branch;
10976 case BGEZALS:
10977 mips32_op = OPC_BGEZALS;
10978 goto do_branch;
10979 case BLEZ:
10980 mips32_op = OPC_BLEZ;
10981 goto do_branch;
10982 case BGTZ:
10983 mips32_op = OPC_BGTZ;
10984 do_branch:
10985 gen_compute_branch(ctx, mips32_op, 4, rs, -1, imm << 1);
10986 *is_branch = 1;
10987 break;
10988
10989 /* Traps */
10990 case TLTI:
10991 mips32_op = OPC_TLTI;
10992 goto do_trapi;
10993 case TGEI:
10994 mips32_op = OPC_TGEI;
10995 goto do_trapi;
10996 case TLTIU:
10997 mips32_op = OPC_TLTIU;
10998 goto do_trapi;
10999 case TGEIU:
11000 mips32_op = OPC_TGEIU;
11001 goto do_trapi;
11002 case TNEI:
11003 mips32_op = OPC_TNEI;
11004 goto do_trapi;
11005 case TEQI:
11006 mips32_op = OPC_TEQI;
11007 do_trapi:
11008 gen_trap(ctx, mips32_op, rs, -1, imm);
11009 break;
11010
11011 case BNEZC:
11012 case BEQZC:
11013 gen_compute_branch(ctx, minor == BNEZC ? OPC_BNE : OPC_BEQ,
11014 4, rs, 0, imm << 1);
11015 /* Compact branches don't have a delay slot, so just let
11016 the normal delay slot handling take us to the branch
11017 target. */
11018 break;
11019 case LUI:
11020 gen_logic_imm(env, OPC_LUI, rs, -1, imm);
11021 break;
11022 case SYNCI:
11023 break;
11024 case BC2F:
11025 case BC2T:
11026 /* COP2: Not implemented. */
11027 generate_exception_err(ctx, EXCP_CpU, 2);
11028 break;
11029 case BC1F:
11030 mips32_op = (ctx->opcode & (1 << 16)) ? OPC_BC1FANY2 : OPC_BC1F;
11031 goto do_cp1branch;
11032 case BC1T:
11033 mips32_op = (ctx->opcode & (1 << 16)) ? OPC_BC1TANY2 : OPC_BC1T;
11034 goto do_cp1branch;
11035 case BC1ANY4F:
11036 mips32_op = OPC_BC1FANY4;
11037 goto do_cp1mips3d;
11038 case BC1ANY4T:
11039 mips32_op = OPC_BC1TANY4;
11040 do_cp1mips3d:
11041 check_cop1x(ctx);
11042 check_insn(env, ctx, ASE_MIPS3D);
11043 /* Fall through */
11044 do_cp1branch:
11045 gen_compute_branch1(env, ctx, mips32_op,
11046 (ctx->opcode >> 18) & 0x7, imm << 1);
11047 *is_branch = 1;
11048 break;
11049 case BPOSGE64:
11050 case BPOSGE32:
11051 /* MIPS DSP: not implemented */
11052 /* Fall through */
11053 default:
11054 MIPS_INVAL("pool32i");
11055 generate_exception(ctx, EXCP_RI);
11056 break;
11057 }
11058 break;
11059 case POOL32C:
11060 minor = (ctx->opcode >> 12) & 0xf;
11061 switch (minor) {
11062 case LWL:
11063 mips32_op = OPC_LWL;
5c13fdfd 11064 goto do_ld_lr;
3c824109
NF
11065 case SWL:
11066 mips32_op = OPC_SWL;
5c13fdfd 11067 goto do_st_lr;
3c824109
NF
11068 case LWR:
11069 mips32_op = OPC_LWR;
5c13fdfd 11070 goto do_ld_lr;
3c824109
NF
11071 case SWR:
11072 mips32_op = OPC_SWR;
5c13fdfd 11073 goto do_st_lr;
3c824109
NF
11074#if defined(TARGET_MIPS64)
11075 case LDL:
11076 mips32_op = OPC_LDL;
5c13fdfd 11077 goto do_ld_lr;
3c824109
NF
11078 case SDL:
11079 mips32_op = OPC_SDL;
5c13fdfd 11080 goto do_st_lr;
3c824109
NF
11081 case LDR:
11082 mips32_op = OPC_LDR;
5c13fdfd 11083 goto do_ld_lr;
3c824109
NF
11084 case SDR:
11085 mips32_op = OPC_SDR;
5c13fdfd 11086 goto do_st_lr;
3c824109
NF
11087 case LWU:
11088 mips32_op = OPC_LWU;
5c13fdfd 11089 goto do_ld_lr;
3c824109
NF
11090 case LLD:
11091 mips32_op = OPC_LLD;
5c13fdfd 11092 goto do_ld_lr;
3c824109
NF
11093#endif
11094 case LL:
11095 mips32_op = OPC_LL;
5c13fdfd
AJ
11096 goto do_ld_lr;
11097 do_ld_lr:
afa88c3a 11098 gen_ld(env, ctx, mips32_op, rt, rs, SIMM(ctx->opcode, 0, 12));
5c13fdfd
AJ
11099 break;
11100 do_st_lr:
11101 gen_st(ctx, mips32_op, rt, rs, SIMM(ctx->opcode, 0, 12));
3c824109
NF
11102 break;
11103 case SC:
11104 gen_st_cond(ctx, OPC_SC, rt, rs, SIMM(ctx->opcode, 0, 12));
11105 break;
11106#if defined(TARGET_MIPS64)
11107 case SCD:
11108 gen_st_cond(ctx, OPC_SCD, rt, rs, SIMM(ctx->opcode, 0, 12));
11109 break;
11110#endif
11111 case PREF:
11112 /* Treat as no-op */
11113 break;
11114 default:
11115 MIPS_INVAL("pool32c");
11116 generate_exception(ctx, EXCP_RI);
11117 break;
11118 }
11119 break;
11120 case ADDI32:
11121 mips32_op = OPC_ADDI;
11122 goto do_addi;
11123 case ADDIU32:
11124 mips32_op = OPC_ADDIU;
11125 do_addi:
11126 gen_arith_imm(env, ctx, mips32_op, rt, rs, imm);
11127 break;
11128
11129 /* Logical operations */
11130 case ORI32:
11131 mips32_op = OPC_ORI;
11132 goto do_logici;
11133 case XORI32:
11134 mips32_op = OPC_XORI;
11135 goto do_logici;
11136 case ANDI32:
11137 mips32_op = OPC_ANDI;
11138 do_logici:
11139 gen_logic_imm(env, mips32_op, rt, rs, imm);
11140 break;
11141
11142 /* Set less than immediate */
11143 case SLTI32:
11144 mips32_op = OPC_SLTI;
11145 goto do_slti;
11146 case SLTIU32:
11147 mips32_op = OPC_SLTIU;
11148 do_slti:
11149 gen_slt_imm(env, mips32_op, rt, rs, imm);
11150 break;
11151 case JALX32:
11152 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2;
11153 gen_compute_branch(ctx, OPC_JALX, 4, rt, rs, offset);
11154 *is_branch = 1;
11155 break;
11156 case JALS32:
11157 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 1;
11158 gen_compute_branch(ctx, OPC_JALS, 4, rt, rs, offset);
11159 *is_branch = 1;
11160 break;
11161 case BEQ32:
11162 gen_compute_branch(ctx, OPC_BEQ, 4, rt, rs, imm << 1);
11163 *is_branch = 1;
11164 break;
11165 case BNE32:
11166 gen_compute_branch(ctx, OPC_BNE, 4, rt, rs, imm << 1);
11167 *is_branch = 1;
11168 break;
11169 case J32:
11170 gen_compute_branch(ctx, OPC_J, 4, rt, rs,
11171 (int32_t)(ctx->opcode & 0x3FFFFFF) << 1);
11172 *is_branch = 1;
11173 break;
11174 case JAL32:
11175 gen_compute_branch(ctx, OPC_JAL, 4, rt, rs,
11176 (int32_t)(ctx->opcode & 0x3FFFFFF) << 1);
11177 *is_branch = 1;
11178 break;
11179 /* Floating point (COP1) */
11180 case LWC132:
11181 mips32_op = OPC_LWC1;
11182 goto do_cop1;
11183 case LDC132:
11184 mips32_op = OPC_LDC1;
11185 goto do_cop1;
11186 case SWC132:
11187 mips32_op = OPC_SWC1;
11188 goto do_cop1;
11189 case SDC132:
11190 mips32_op = OPC_SDC1;
11191 do_cop1:
11192 gen_cop1_ldst(env, ctx, mips32_op, rt, rs, imm);
11193 break;
11194 case ADDIUPC:
11195 {
11196 int reg = mmreg(ZIMM(ctx->opcode, 23, 3));
11197 int offset = SIMM(ctx->opcode, 0, 23) << 2;
11198
11199 gen_addiupc(ctx, reg, offset, 0, 0);
11200 }
11201 break;
11202 /* Loads and stores */
11203 case LB32:
11204 mips32_op = OPC_LB;
5c13fdfd 11205 goto do_ld;
3c824109
NF
11206 case LBU32:
11207 mips32_op = OPC_LBU;
5c13fdfd 11208 goto do_ld;
3c824109
NF
11209 case LH32:
11210 mips32_op = OPC_LH;
5c13fdfd 11211 goto do_ld;
3c824109
NF
11212 case LHU32:
11213 mips32_op = OPC_LHU;
5c13fdfd 11214 goto do_ld;
3c824109
NF
11215 case LW32:
11216 mips32_op = OPC_LW;
5c13fdfd 11217 goto do_ld;
3c824109
NF
11218#ifdef TARGET_MIPS64
11219 case LD32:
11220 mips32_op = OPC_LD;
5c13fdfd 11221 goto do_ld;
3c824109
NF
11222 case SD32:
11223 mips32_op = OPC_SD;
5c13fdfd 11224 goto do_st;
3c824109
NF
11225#endif
11226 case SB32:
11227 mips32_op = OPC_SB;
5c13fdfd 11228 goto do_st;
3c824109
NF
11229 case SH32:
11230 mips32_op = OPC_SH;
5c13fdfd 11231 goto do_st;
3c824109
NF
11232 case SW32:
11233 mips32_op = OPC_SW;
5c13fdfd
AJ
11234 goto do_st;
11235 do_ld:
afa88c3a 11236 gen_ld(env, ctx, mips32_op, rt, rs, imm);
5c13fdfd
AJ
11237 break;
11238 do_st:
11239 gen_st(ctx, mips32_op, rt, rs, imm);
3c824109
NF
11240 break;
11241 default:
11242 generate_exception(ctx, EXCP_RI);
11243 break;
11244 }
11245}
11246
11247static int decode_micromips_opc (CPUState *env, DisasContext *ctx, int *is_branch)
11248{
11249 uint32_t op;
11250
11251 /* make sure instructions are on a halfword boundary */
11252 if (ctx->pc & 0x1) {
11253 env->CP0_BadVAddr = ctx->pc;
11254 generate_exception(ctx, EXCP_AdEL);
11255 ctx->bstate = BS_STOP;
11256 return 2;
11257 }
11258
11259 op = (ctx->opcode >> 10) & 0x3f;
11260 /* Enforce properly-sized instructions in a delay slot */
11261 if (ctx->hflags & MIPS_HFLAG_BMASK) {
11262 int bits = ctx->hflags & MIPS_HFLAG_BMASK_EXT;
11263
11264 switch (op) {
11265 case POOL32A:
11266 case POOL32B:
11267 case POOL32I:
11268 case POOL32C:
11269 case ADDI32:
11270 case ADDIU32:
11271 case ORI32:
11272 case XORI32:
11273 case SLTI32:
11274 case SLTIU32:
11275 case ANDI32:
11276 case JALX32:
11277 case LBU32:
11278 case LHU32:
11279 case POOL32F:
11280 case JALS32:
11281 case BEQ32:
11282 case BNE32:
11283 case J32:
11284 case JAL32:
11285 case SB32:
11286 case SH32:
11287 case POOL32S:
11288 case ADDIUPC:
11289 case SWC132:
11290 case SDC132:
11291 case SD32:
11292 case SW32:
11293 case LB32:
11294 case LH32:
11295 case DADDIU32:
11296 case POOL48A: /* ??? */
11297 case LWC132:
11298 case LDC132:
11299 case LD32:
11300 case LW32:
11301 if (bits & MIPS_HFLAG_BDS16) {
11302 generate_exception(ctx, EXCP_RI);
11303 /* Just stop translation; the user is confused. */
11304 ctx->bstate = BS_STOP;
11305 return 2;
11306 }
11307 break;
11308 case POOL16A:
11309 case POOL16B:
11310 case POOL16C:
11311 case LWGP16:
11312 case POOL16F:
11313 case LBU16:
11314 case LHU16:
11315 case LWSP16:
11316 case LW16:
11317 case SB16:
11318 case SH16:
11319 case SWSP16:
11320 case SW16:
11321 case MOVE16:
11322 case ANDI16:
11323 case POOL16D:
11324 case POOL16E:
11325 case BEQZ16:
11326 case BNEZ16:
11327 case B16:
11328 case LI16:
11329 if (bits & MIPS_HFLAG_BDS32) {
11330 generate_exception(ctx, EXCP_RI);
11331 /* Just stop translation; the user is confused. */
11332 ctx->bstate = BS_STOP;
11333 return 2;
11334 }
11335 break;
11336 default:
11337 break;
11338 }
11339 }
11340 switch (op) {
11341 case POOL16A:
11342 {
11343 int rd = mmreg(uMIPS_RD(ctx->opcode));
11344 int rs1 = mmreg(uMIPS_RS1(ctx->opcode));
11345 int rs2 = mmreg(uMIPS_RS2(ctx->opcode));
11346 uint32_t opc = 0;
11347
11348 switch (ctx->opcode & 0x1) {
11349 case ADDU16:
11350 opc = OPC_ADDU;
11351 break;
11352 case SUBU16:
11353 opc = OPC_SUBU;
11354 break;
11355 }
11356
11357 gen_arith(env, ctx, opc, rd, rs1, rs2);
11358 }
11359 break;
11360 case POOL16B:
11361 {
11362 int rd = mmreg(uMIPS_RD(ctx->opcode));
11363 int rs = mmreg(uMIPS_RS(ctx->opcode));
11364 int amount = (ctx->opcode >> 1) & 0x7;
11365 uint32_t opc = 0;
11366 amount = amount == 0 ? 8 : amount;
11367
11368 switch (ctx->opcode & 0x1) {
11369 case SLL16:
11370 opc = OPC_SLL;
11371 break;
11372 case SRL16:
11373 opc = OPC_SRL;
11374 break;
11375 }
11376
11377 gen_shift_imm(env, ctx, opc, rd, rs, amount);
11378 }
11379 break;
11380 case POOL16C:
11381 gen_pool16c_insn(env, ctx, is_branch);
11382 break;
11383 case LWGP16:
11384 {
11385 int rd = mmreg(uMIPS_RD(ctx->opcode));
11386 int rb = 28; /* GP */
11387 int16_t offset = SIMM(ctx->opcode, 0, 7) << 2;
11388
afa88c3a 11389 gen_ld(env, ctx, OPC_LW, rd, rb, offset);
3c824109
NF
11390 }
11391 break;
11392 case POOL16F:
11393 if (ctx->opcode & 1) {
11394 generate_exception(ctx, EXCP_RI);
11395 } else {
11396 /* MOVEP */
11397 int enc_dest = uMIPS_RD(ctx->opcode);
11398 int enc_rt = uMIPS_RS2(ctx->opcode);
11399 int enc_rs = uMIPS_RS1(ctx->opcode);
11400 int rd, rs, re, rt;
11401 static const int rd_enc[] = { 5, 5, 6, 4, 4, 4, 4, 4 };
11402 static const int re_enc[] = { 6, 7, 7, 21, 22, 5, 6, 7 };
11403 static const int rs_rt_enc[] = { 0, 17, 2, 3, 16, 18, 19, 20 };
11404
11405 rd = rd_enc[enc_dest];
11406 re = re_enc[enc_dest];
11407 rs = rs_rt_enc[enc_rs];
11408 rt = rs_rt_enc[enc_rt];
11409
11410 gen_arith_imm(env, ctx, OPC_ADDIU, rd, rs, 0);
11411 gen_arith_imm(env, ctx, OPC_ADDIU, re, rt, 0);
11412 }
11413 break;
11414 case LBU16:
11415 {
11416 int rd = mmreg(uMIPS_RD(ctx->opcode));
11417 int rb = mmreg(uMIPS_RS(ctx->opcode));
11418 int16_t offset = ZIMM(ctx->opcode, 0, 4);
11419 offset = (offset == 0xf ? -1 : offset);
11420
afa88c3a 11421 gen_ld(env, ctx, OPC_LBU, rd, rb, offset);
3c824109
NF
11422 }
11423 break;
11424 case LHU16:
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) << 1;
11429
afa88c3a 11430 gen_ld(env, ctx, OPC_LHU, rd, rb, offset);
3c824109
NF
11431 }
11432 break;
11433 case LWSP16:
11434 {
11435 int rd = (ctx->opcode >> 5) & 0x1f;
11436 int rb = 29; /* SP */
11437 int16_t offset = ZIMM(ctx->opcode, 0, 5) << 2;
11438
afa88c3a 11439 gen_ld(env, ctx, OPC_LW, rd, rb, offset);
3c824109
NF
11440 }
11441 break;
11442 case LW16:
11443 {
11444 int rd = mmreg(uMIPS_RD(ctx->opcode));
11445 int rb = mmreg(uMIPS_RS(ctx->opcode));
11446 int16_t offset = ZIMM(ctx->opcode, 0, 4) << 2;
11447
afa88c3a 11448 gen_ld(env, ctx, OPC_LW, rd, rb, offset);
3c824109
NF
11449 }
11450 break;
11451 case SB16:
11452 {
11453 int rd = mmreg2(uMIPS_RD(ctx->opcode));
11454 int rb = mmreg(uMIPS_RS(ctx->opcode));
11455 int16_t offset = ZIMM(ctx->opcode, 0, 4);
11456
5c13fdfd 11457 gen_st(ctx, OPC_SB, rd, rb, offset);
3c824109
NF
11458 }
11459 break;
11460 case SH16:
11461 {
11462 int rd = mmreg2(uMIPS_RD(ctx->opcode));
11463 int rb = mmreg(uMIPS_RS(ctx->opcode));
11464 int16_t offset = ZIMM(ctx->opcode, 0, 4) << 1;
11465
5c13fdfd 11466 gen_st(ctx, OPC_SH, rd, rb, offset);
3c824109
NF
11467 }
11468 break;
11469 case SWSP16:
11470 {
11471 int rd = (ctx->opcode >> 5) & 0x1f;
11472 int rb = 29; /* SP */
11473 int16_t offset = ZIMM(ctx->opcode, 0, 5) << 2;
11474
5c13fdfd 11475 gen_st(ctx, OPC_SW, rd, rb, offset);
3c824109
NF
11476 }
11477 break;
11478 case SW16:
11479 {
11480 int rd = mmreg2(uMIPS_RD(ctx->opcode));
11481 int rb = mmreg(uMIPS_RS(ctx->opcode));
11482 int16_t offset = ZIMM(ctx->opcode, 0, 4) << 2;
11483
5c13fdfd 11484 gen_st(ctx, OPC_SW, rd, rb, offset);
3c824109
NF
11485 }
11486 break;
11487 case MOVE16:
11488 {
11489 int rd = uMIPS_RD5(ctx->opcode);
11490 int rs = uMIPS_RS5(ctx->opcode);
11491
11492 gen_arith_imm(env, ctx, OPC_ADDIU, rd, rs, 0);
11493 }
11494 break;
11495 case ANDI16:
11496 gen_andi16(env, ctx);
11497 break;
11498 case POOL16D:
11499 switch (ctx->opcode & 0x1) {
11500 case ADDIUS5:
11501 gen_addius5(env, ctx);
11502 break;
11503 case ADDIUSP:
11504 gen_addiusp(env, ctx);
11505 break;
11506 }
11507 break;
11508 case POOL16E:
11509 switch (ctx->opcode & 0x1) {
11510 case ADDIUR2:
11511 gen_addiur2(env, ctx);
11512 break;
11513 case ADDIUR1SP:
11514 gen_addiur1sp(env, ctx);
11515 break;
11516 }
11517 break;
11518 case B16:
11519 gen_compute_branch(ctx, OPC_BEQ, 2, 0, 0,
11520 SIMM(ctx->opcode, 0, 10) << 1);
11521 *is_branch = 1;
11522 break;
11523 case BNEZ16:
11524 case BEQZ16:
11525 gen_compute_branch(ctx, op == BNEZ16 ? OPC_BNE : OPC_BEQ, 2,
11526 mmreg(uMIPS_RD(ctx->opcode)),
11527 0, SIMM(ctx->opcode, 0, 7) << 1);
11528 *is_branch = 1;
11529 break;
11530 case LI16:
11531 {
11532 int reg = mmreg(uMIPS_RD(ctx->opcode));
11533 int imm = ZIMM(ctx->opcode, 0, 7);
11534
11535 imm = (imm == 0x7f ? -1 : imm);
11536 tcg_gen_movi_tl(cpu_gpr[reg], imm);
11537 }
11538 break;
11539 case RES_20:
11540 case RES_28:
11541 case RES_29:
11542 case RES_30:
11543 case RES_31:
11544 case RES_38:
11545 case RES_39:
11546 generate_exception(ctx, EXCP_RI);
11547 break;
11548 default:
11549 decode_micromips32_opc (env, ctx, op, is_branch);
11550 return 4;
11551 }
11552
11553 return 2;
11554}
11555
11556/* SmartMIPS extension to MIPS32 */
11557
11558#if defined(TARGET_MIPS64)
11559
11560/* MDMX extension to MIPS64 */
11561
11562#endif
11563
11564static void decode_opc (CPUState *env, DisasContext *ctx, int *is_branch)
11565{
11566 int32_t offset;
11567 int rs, rt, rd, sa;
11568 uint32_t op, op1, op2;
11569 int16_t imm;
11570
11571 /* make sure instructions are on a word boundary */
11572 if (ctx->pc & 0x3) {
11573 env->CP0_BadVAddr = ctx->pc;
11574 generate_exception(ctx, EXCP_AdEL);
11575 return;
11576 }
11577
11578 /* Handle blikely not taken case */
11579 if ((ctx->hflags & MIPS_HFLAG_BMASK_BASE) == MIPS_HFLAG_BL) {
11580 int l1 = gen_new_label();
11581
11582 MIPS_DEBUG("blikely condition (" TARGET_FMT_lx ")", ctx->pc + 4);
11583 tcg_gen_brcondi_tl(TCG_COND_NE, bcond, 0, l1);
11584 tcg_gen_movi_i32(hflags, ctx->hflags & ~MIPS_HFLAG_BMASK);
11585 gen_goto_tb(ctx, 1, ctx->pc + 4);
11586 gen_set_label(l1);
11587 }
11588
11589 if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP)))
11590 tcg_gen_debug_insn_start(ctx->pc);
11591
11592 op = MASK_OP_MAJOR(ctx->opcode);
11593 rs = (ctx->opcode >> 21) & 0x1f;
11594 rt = (ctx->opcode >> 16) & 0x1f;
11595 rd = (ctx->opcode >> 11) & 0x1f;
11596 sa = (ctx->opcode >> 6) & 0x1f;
11597 imm = (int16_t)ctx->opcode;
11598 switch (op) {
7a387fff
TS
11599 case OPC_SPECIAL:
11600 op1 = MASK_SPECIAL(ctx->opcode);
6af0bf9c 11601 switch (op1) {
324d9e32
AJ
11602 case OPC_SLL: /* Shift with immediate */
11603 case OPC_SRA:
324d9e32 11604 gen_shift_imm(env, ctx, op1, rd, rt, sa);
7a387fff 11605 break;
ea63e2c3
NF
11606 case OPC_SRL:
11607 switch ((ctx->opcode >> 21) & 0x1f) {
11608 case 1:
11609 /* rotr is decoded as srl on non-R2 CPUs */
11610 if (env->insn_flags & ISA_MIPS32R2) {
11611 op1 = OPC_ROTR;
11612 }
11613 /* Fallthrough */
11614 case 0:
11615 gen_shift_imm(env, ctx, op1, rd, rt, sa);
11616 break;
11617 default:
11618 generate_exception(ctx, EXCP_RI);
11619 break;
11620 }
11621 break;
460f00c4
AJ
11622 case OPC_MOVN: /* Conditional move */
11623 case OPC_MOVZ:
aa8f4009
AJ
11624 check_insn(env, ctx, ISA_MIPS4 | ISA_MIPS32 |
11625 INSN_LOONGSON2E | INSN_LOONGSON2F);
460f00c4
AJ
11626 gen_cond_move(env, op1, rd, rs, rt);
11627 break;
11628 case OPC_ADD ... OPC_SUBU:
e189e748 11629 gen_arith(env, ctx, op1, rd, rs, rt);
7a387fff 11630 break;
460f00c4 11631 case OPC_SLLV: /* Shifts */
460f00c4
AJ
11632 case OPC_SRAV:
11633 gen_shift(env, ctx, op1, rd, rs, rt);
11634 break;
ea63e2c3
NF
11635 case OPC_SRLV:
11636 switch ((ctx->opcode >> 6) & 0x1f) {
11637 case 1:
11638 /* rotrv is decoded as srlv on non-R2 CPUs */
11639 if (env->insn_flags & ISA_MIPS32R2) {
11640 op1 = OPC_ROTRV;
11641 }
11642 /* Fallthrough */
11643 case 0:
11644 gen_shift(env, ctx, op1, rd, rs, rt);
11645 break;
11646 default:
11647 generate_exception(ctx, EXCP_RI);
11648 break;
11649 }
11650 break;
460f00c4
AJ
11651 case OPC_SLT: /* Set on less than */
11652 case OPC_SLTU:
11653 gen_slt(env, op1, rd, rs, rt);
11654 break;
11655 case OPC_AND: /* Logic*/
11656 case OPC_OR:
11657 case OPC_NOR:
11658 case OPC_XOR:
11659 gen_logic(env, op1, rd, rs, rt);
11660 break;
7a387fff 11661 case OPC_MULT ... OPC_DIVU:
e9c71dd1
TS
11662 if (sa) {
11663 check_insn(env, ctx, INSN_VR54XX);
11664 op1 = MASK_MUL_VR54XX(ctx->opcode);
11665 gen_mul_vr54xx(ctx, op1, rd, rs, rt);
11666 } else
11667 gen_muldiv(ctx, op1, rs, rt);
7a387fff
TS
11668 break;
11669 case OPC_JR ... OPC_JALR:
7dca4ad0 11670 gen_compute_branch(ctx, op1, 4, rs, rd, sa);
c9602061
NF
11671 *is_branch = 1;
11672 break;
7a387fff
TS
11673 case OPC_TGE ... OPC_TEQ: /* Traps */
11674 case OPC_TNE:
11675 gen_trap(ctx, op1, rs, rt, -1);
6af0bf9c 11676 break;
7a387fff
TS
11677 case OPC_MFHI: /* Move from HI/LO */
11678 case OPC_MFLO:
11679 gen_HILO(ctx, op1, rd);
6af0bf9c 11680 break;
7a387fff
TS
11681 case OPC_MTHI:
11682 case OPC_MTLO: /* Move to HI/LO */
11683 gen_HILO(ctx, op1, rs);
6af0bf9c 11684 break;
b48cfdff
TS
11685 case OPC_PMON: /* Pmon entry point, also R4010 selsl */
11686#ifdef MIPS_STRICT_STANDARD
11687 MIPS_INVAL("PMON / selsl");
11688 generate_exception(ctx, EXCP_RI);
11689#else
a7812ae4 11690 gen_helper_0i(pmon, sa);
b48cfdff 11691#endif
7a387fff
TS
11692 break;
11693 case OPC_SYSCALL:
6af0bf9c 11694 generate_exception(ctx, EXCP_SYSCALL);
8e0f950d 11695 ctx->bstate = BS_STOP;
6af0bf9c 11696 break;
7a387fff 11697 case OPC_BREAK:
6af0bf9c
FB
11698 generate_exception(ctx, EXCP_BREAK);
11699 break;
b48cfdff
TS
11700 case OPC_SPIM:
11701#ifdef MIPS_STRICT_STANDARD
11702 MIPS_INVAL("SPIM");
11703 generate_exception(ctx, EXCP_RI);
11704#else
7a387fff
TS
11705 /* Implemented as RI exception for now. */
11706 MIPS_INVAL("spim (unofficial)");
11707 generate_exception(ctx, EXCP_RI);
b48cfdff 11708#endif
6af0bf9c 11709 break;
7a387fff 11710 case OPC_SYNC:
ead9360e 11711 /* Treat as NOP. */
6af0bf9c 11712 break;
4ad40f36 11713
7a387fff 11714 case OPC_MOVCI:
e189e748 11715 check_insn(env, ctx, ISA_MIPS4 | ISA_MIPS32);
36d23958 11716 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
5e755519 11717 check_cp1_enabled(ctx);
36d23958
TS
11718 gen_movci(ctx, rd, rs, (ctx->opcode >> 18) & 0x7,
11719 (ctx->opcode >> 16) & 1);
11720 } else {
e397ee33 11721 generate_exception_err(ctx, EXCP_CpU, 1);
36d23958 11722 }
4ad40f36
FB
11723 break;
11724
d26bc211 11725#if defined(TARGET_MIPS64)
7a387fff
TS
11726 /* MIPS64 specific opcodes */
11727 case OPC_DSLL:
324d9e32 11728 case OPC_DSRA:
7a387fff 11729 case OPC_DSLL32:
324d9e32 11730 case OPC_DSRA32:
e189e748
TS
11731 check_insn(env, ctx, ISA_MIPS3);
11732 check_mips_64(ctx);
324d9e32 11733 gen_shift_imm(env, ctx, op1, rd, rt, sa);
7a387fff 11734 break;
ea63e2c3
NF
11735 case OPC_DSRL:
11736 switch ((ctx->opcode >> 21) & 0x1f) {
11737 case 1:
11738 /* drotr is decoded as dsrl on non-R2 CPUs */
11739 if (env->insn_flags & ISA_MIPS32R2) {
11740 op1 = OPC_DROTR;
11741 }
11742 /* Fallthrough */
11743 case 0:
11744 check_insn(env, ctx, ISA_MIPS3);
11745 check_mips_64(ctx);
11746 gen_shift_imm(env, ctx, op1, rd, rt, sa);
11747 break;
11748 default:
11749 generate_exception(ctx, EXCP_RI);
11750 break;
11751 }
11752 break;
11753 case OPC_DSRL32:
11754 switch ((ctx->opcode >> 21) & 0x1f) {
11755 case 1:
11756 /* drotr32 is decoded as dsrl32 on non-R2 CPUs */
11757 if (env->insn_flags & ISA_MIPS32R2) {
11758 op1 = OPC_DROTR32;
11759 }
11760 /* Fallthrough */
11761 case 0:
11762 check_insn(env, ctx, ISA_MIPS3);
11763 check_mips_64(ctx);
11764 gen_shift_imm(env, ctx, op1, rd, rt, sa);
11765 break;
11766 default:
11767 generate_exception(ctx, EXCP_RI);
11768 break;
11769 }
11770 break;
7a387fff 11771 case OPC_DADD ... OPC_DSUBU:
e189e748
TS
11772 check_insn(env, ctx, ISA_MIPS3);
11773 check_mips_64(ctx);
11774 gen_arith(env, ctx, op1, rd, rs, rt);
7a387fff 11775 break;
460f00c4
AJ
11776 case OPC_DSLLV:
11777 case OPC_DSRAV:
460f00c4
AJ
11778 check_insn(env, ctx, ISA_MIPS3);
11779 check_mips_64(ctx);
11780 gen_shift(env, ctx, op1, rd, rs, rt);
11781 break;
ea63e2c3
NF
11782 case OPC_DSRLV:
11783 switch ((ctx->opcode >> 6) & 0x1f) {
11784 case 1:
11785 /* drotrv is decoded as dsrlv on non-R2 CPUs */
11786 if (env->insn_flags & ISA_MIPS32R2) {
11787 op1 = OPC_DROTRV;
11788 }
11789 /* Fallthrough */
11790 case 0:
11791 check_insn(env, ctx, ISA_MIPS3);
11792 check_mips_64(ctx);
11793 gen_shift(env, ctx, op1, rd, rs, rt);
11794 break;
11795 default:
11796 generate_exception(ctx, EXCP_RI);
11797 break;
11798 }
11799 break;
7a387fff 11800 case OPC_DMULT ... OPC_DDIVU:
e189e748
TS
11801 check_insn(env, ctx, ISA_MIPS3);
11802 check_mips_64(ctx);
7a387fff
TS
11803 gen_muldiv(ctx, op1, rs, rt);
11804 break;
6af0bf9c
FB
11805#endif
11806 default: /* Invalid */
11807 MIPS_INVAL("special");
11808 generate_exception(ctx, EXCP_RI);
11809 break;
11810 }
11811 break;
7a387fff
TS
11812 case OPC_SPECIAL2:
11813 op1 = MASK_SPECIAL2(ctx->opcode);
6af0bf9c 11814 switch (op1) {
7a387fff
TS
11815 case OPC_MADD ... OPC_MADDU: /* Multiply and add/sub */
11816 case OPC_MSUB ... OPC_MSUBU:
e189e748 11817 check_insn(env, ctx, ISA_MIPS32);
7a387fff 11818 gen_muldiv(ctx, op1, rs, rt);
6af0bf9c 11819 break;
7a387fff 11820 case OPC_MUL:
e189e748 11821 gen_arith(env, ctx, op1, rd, rs, rt);
6af0bf9c 11822 break;
20e1fb52
AJ
11823 case OPC_CLO:
11824 case OPC_CLZ:
e189e748 11825 check_insn(env, ctx, ISA_MIPS32);
7a387fff 11826 gen_cl(ctx, op1, rd, rs);
6af0bf9c 11827 break;
7a387fff 11828 case OPC_SDBBP:
6af0bf9c
FB
11829 /* XXX: not clear which exception should be raised
11830 * when in debug mode...
11831 */
e189e748 11832 check_insn(env, ctx, ISA_MIPS32);
6af0bf9c
FB
11833 if (!(ctx->hflags & MIPS_HFLAG_DM)) {
11834 generate_exception(ctx, EXCP_DBp);
11835 } else {
11836 generate_exception(ctx, EXCP_DBp);
11837 }
ead9360e 11838 /* Treat as NOP. */
6af0bf9c 11839 break;
161f85e6
AJ
11840 case OPC_DIV_G_2F:
11841 case OPC_DIVU_G_2F:
11842 case OPC_MULT_G_2F:
11843 case OPC_MULTU_G_2F:
11844 case OPC_MOD_G_2F:
11845 case OPC_MODU_G_2F:
11846 check_insn(env, ctx, INSN_LOONGSON2F);
11847 gen_loongson_integer(ctx, op1, rd, rs, rt);
11848 break;
d26bc211 11849#if defined(TARGET_MIPS64)
20e1fb52
AJ
11850 case OPC_DCLO:
11851 case OPC_DCLZ:
e189e748
TS
11852 check_insn(env, ctx, ISA_MIPS64);
11853 check_mips_64(ctx);
7a387fff
TS
11854 gen_cl(ctx, op1, rd, rs);
11855 break;
161f85e6
AJ
11856 case OPC_DMULT_G_2F:
11857 case OPC_DMULTU_G_2F:
11858 case OPC_DDIV_G_2F:
11859 case OPC_DDIVU_G_2F:
11860 case OPC_DMOD_G_2F:
11861 case OPC_DMODU_G_2F:
11862 check_insn(env, ctx, INSN_LOONGSON2F);
11863 gen_loongson_integer(ctx, op1, rd, rs, rt);
11864 break;
7a387fff 11865#endif
6af0bf9c
FB
11866 default: /* Invalid */
11867 MIPS_INVAL("special2");
11868 generate_exception(ctx, EXCP_RI);
11869 break;
11870 }
11871 break;
7a387fff 11872 case OPC_SPECIAL3:
2b0233ab
TS
11873 op1 = MASK_SPECIAL3(ctx->opcode);
11874 switch (op1) {
11875 case OPC_EXT:
11876 case OPC_INS:
11877 check_insn(env, ctx, ISA_MIPS32R2);
11878 gen_bitops(ctx, op1, rt, rs, sa, rd);
11879 break;
11880 case OPC_BSHFL:
11881 check_insn(env, ctx, ISA_MIPS32R2);
11882 op2 = MASK_BSHFL(ctx->opcode);
49bcf33c 11883 gen_bshfl(ctx, op2, rt, rd);
7a387fff 11884 break;
1579a72e 11885 case OPC_RDHWR:
26ebe468 11886 gen_rdhwr(env, ctx, rt, rd);
1579a72e 11887 break;
ead9360e 11888 case OPC_FORK:
7385ac0b 11889 check_insn(env, ctx, ASE_MT);
6c5c1e20 11890 {
35fbce2c
AJ
11891 TCGv t0 = tcg_temp_new();
11892 TCGv t1 = tcg_temp_new();
6c5c1e20
TS
11893
11894 gen_load_gpr(t0, rt);
11895 gen_load_gpr(t1, rs);
a7812ae4 11896 gen_helper_fork(t0, t1);
6c5c1e20
TS
11897 tcg_temp_free(t0);
11898 tcg_temp_free(t1);
11899 }
ead9360e
TS
11900 break;
11901 case OPC_YIELD:
7385ac0b 11902 check_insn(env, ctx, ASE_MT);
6c5c1e20 11903 {
35fbce2c 11904 TCGv t0 = tcg_temp_new();
6c5c1e20 11905
35fbce2c 11906 save_cpu_state(ctx, 1);
6c5c1e20 11907 gen_load_gpr(t0, rs);
a7812ae4 11908 gen_helper_yield(t0, t0);
6c5c1e20
TS
11909 gen_store_gpr(t0, rd);
11910 tcg_temp_free(t0);
11911 }
ead9360e 11912 break;
161f85e6
AJ
11913 case OPC_DIV_G_2E ... OPC_DIVU_G_2E:
11914 case OPC_MULT_G_2E ... OPC_MULTU_G_2E:
11915 case OPC_MOD_G_2E ... OPC_MODU_G_2E:
11916 check_insn(env, ctx, INSN_LOONGSON2E);
11917 gen_loongson_integer(ctx, op1, rd, rs, rt);
11918 break;
d26bc211 11919#if defined(TARGET_MIPS64)
1579a72e
TS
11920 case OPC_DEXTM ... OPC_DEXT:
11921 case OPC_DINSM ... OPC_DINS:
e189e748
TS
11922 check_insn(env, ctx, ISA_MIPS64R2);
11923 check_mips_64(ctx);
1579a72e 11924 gen_bitops(ctx, op1, rt, rs, sa, rd);
7a387fff 11925 break;
1579a72e 11926 case OPC_DBSHFL:
e189e748
TS
11927 check_insn(env, ctx, ISA_MIPS64R2);
11928 check_mips_64(ctx);
1579a72e 11929 op2 = MASK_DBSHFL(ctx->opcode);
49bcf33c 11930 gen_bshfl(ctx, op2, rt, rd);
c6d6dd7c 11931 break;
161f85e6
AJ
11932 case OPC_DDIV_G_2E ... OPC_DDIVU_G_2E:
11933 case OPC_DMULT_G_2E ... OPC_DMULTU_G_2E:
11934 case OPC_DMOD_G_2E ... OPC_DMODU_G_2E:
11935 check_insn(env, ctx, INSN_LOONGSON2E);
11936 gen_loongson_integer(ctx, op1, rd, rs, rt);
11937 break;
7a387fff
TS
11938#endif
11939 default: /* Invalid */
11940 MIPS_INVAL("special3");
11941 generate_exception(ctx, EXCP_RI);
11942 break;
11943 }
11944 break;
11945 case OPC_REGIMM:
11946 op1 = MASK_REGIMM(ctx->opcode);
11947 switch (op1) {
11948 case OPC_BLTZ ... OPC_BGEZL: /* REGIMM branches */
11949 case OPC_BLTZAL ... OPC_BGEZALL:
7dca4ad0 11950 gen_compute_branch(ctx, op1, 4, rs, -1, imm << 2);
c9602061
NF
11951 *is_branch = 1;
11952 break;
7a387fff
TS
11953 case OPC_TGEI ... OPC_TEQI: /* REGIMM traps */
11954 case OPC_TNEI:
11955 gen_trap(ctx, op1, rs, -1, imm);
11956 break;
11957 case OPC_SYNCI:
e189e748 11958 check_insn(env, ctx, ISA_MIPS32R2);
ead9360e 11959 /* Treat as NOP. */
6af0bf9c
FB
11960 break;
11961 default: /* Invalid */
923617a3 11962 MIPS_INVAL("regimm");
6af0bf9c
FB
11963 generate_exception(ctx, EXCP_RI);
11964 break;
11965 }
11966 break;
7a387fff 11967 case OPC_CP0:
387a8fe5 11968 check_cp0_enabled(ctx);
7a387fff 11969 op1 = MASK_CP0(ctx->opcode);
6af0bf9c 11970 switch (op1) {
7a387fff
TS
11971 case OPC_MFC0:
11972 case OPC_MTC0:
ead9360e
TS
11973 case OPC_MFTR:
11974 case OPC_MTTR:
d26bc211 11975#if defined(TARGET_MIPS64)
7a387fff
TS
11976 case OPC_DMFC0:
11977 case OPC_DMTC0:
11978#endif
f1aa6320 11979#ifndef CONFIG_USER_ONLY
932e71cd 11980 gen_cp0(env, ctx, op1, rt, rd);
0eaef5aa 11981#endif /* !CONFIG_USER_ONLY */
7a387fff
TS
11982 break;
11983 case OPC_C0_FIRST ... OPC_C0_LAST:
f1aa6320 11984#ifndef CONFIG_USER_ONLY
932e71cd 11985 gen_cp0(env, ctx, MASK_C0(ctx->opcode), rt, rd);
0eaef5aa 11986#endif /* !CONFIG_USER_ONLY */
7a387fff
TS
11987 break;
11988 case OPC_MFMC0:
8706c382 11989#ifndef CONFIG_USER_ONLY
932e71cd 11990 {
35fbce2c 11991 TCGv t0 = tcg_temp_new();
6c5c1e20 11992
0eaef5aa 11993 op2 = MASK_MFMC0(ctx->opcode);
6c5c1e20
TS
11994 switch (op2) {
11995 case OPC_DMT:
11996 check_insn(env, ctx, ASE_MT);
a7812ae4 11997 gen_helper_dmt(t0, t0);
35fbce2c 11998 gen_store_gpr(t0, rt);
6c5c1e20
TS
11999 break;
12000 case OPC_EMT:
12001 check_insn(env, ctx, ASE_MT);
a7812ae4 12002 gen_helper_emt(t0, t0);
35fbce2c 12003 gen_store_gpr(t0, rt);
da80682b 12004 break;
6c5c1e20
TS
12005 case OPC_DVPE:
12006 check_insn(env, ctx, ASE_MT);
a7812ae4 12007 gen_helper_dvpe(t0, t0);
35fbce2c 12008 gen_store_gpr(t0, rt);
6c5c1e20
TS
12009 break;
12010 case OPC_EVPE:
12011 check_insn(env, ctx, ASE_MT);
a7812ae4 12012 gen_helper_evpe(t0, t0);
35fbce2c 12013 gen_store_gpr(t0, rt);
6c5c1e20
TS
12014 break;
12015 case OPC_DI:
12016 check_insn(env, ctx, ISA_MIPS32R2);
867abc7e 12017 save_cpu_state(ctx, 1);
a7812ae4 12018 gen_helper_di(t0);
35fbce2c 12019 gen_store_gpr(t0, rt);
6c5c1e20
TS
12020 /* Stop translation as we may have switched the execution mode */
12021 ctx->bstate = BS_STOP;
12022 break;
12023 case OPC_EI:
12024 check_insn(env, ctx, ISA_MIPS32R2);
867abc7e 12025 save_cpu_state(ctx, 1);
a7812ae4 12026 gen_helper_ei(t0);
35fbce2c 12027 gen_store_gpr(t0, rt);
6c5c1e20
TS
12028 /* Stop translation as we may have switched the execution mode */
12029 ctx->bstate = BS_STOP;
12030 break;
12031 default: /* Invalid */
12032 MIPS_INVAL("mfmc0");
12033 generate_exception(ctx, EXCP_RI);
12034 break;
12035 }
6c5c1e20 12036 tcg_temp_free(t0);
7a387fff 12037 }
0eaef5aa 12038#endif /* !CONFIG_USER_ONLY */
6af0bf9c 12039 break;
7a387fff 12040 case OPC_RDPGPR:
e189e748 12041 check_insn(env, ctx, ISA_MIPS32R2);
be24bb4f 12042 gen_load_srsgpr(rt, rd);
ead9360e 12043 break;
7a387fff 12044 case OPC_WRPGPR:
e189e748 12045 check_insn(env, ctx, ISA_MIPS32R2);
be24bb4f 12046 gen_store_srsgpr(rt, rd);
38121543 12047 break;
6af0bf9c 12048 default:
923617a3 12049 MIPS_INVAL("cp0");
7a387fff 12050 generate_exception(ctx, EXCP_RI);
6af0bf9c
FB
12051 break;
12052 }
12053 break;
324d9e32
AJ
12054 case OPC_ADDI: /* Arithmetic with immediate opcode */
12055 case OPC_ADDIU:
e189e748 12056 gen_arith_imm(env, ctx, op, rt, rs, imm);
7a387fff 12057 break;
324d9e32
AJ
12058 case OPC_SLTI: /* Set on less than with immediate opcode */
12059 case OPC_SLTIU:
12060 gen_slt_imm(env, op, rt, rs, imm);
12061 break;
12062 case OPC_ANDI: /* Arithmetic with immediate opcode */
12063 case OPC_LUI:
12064 case OPC_ORI:
12065 case OPC_XORI:
12066 gen_logic_imm(env, op, rt, rs, imm);
12067 break;
7a387fff
TS
12068 case OPC_J ... OPC_JAL: /* Jump */
12069 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2;
7dca4ad0 12070 gen_compute_branch(ctx, op, 4, rs, rt, offset);
c9602061
NF
12071 *is_branch = 1;
12072 break;
7a387fff
TS
12073 case OPC_BEQ ... OPC_BGTZ: /* Branch */
12074 case OPC_BEQL ... OPC_BGTZL:
7dca4ad0 12075 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2);
c9602061
NF
12076 *is_branch = 1;
12077 break;
7a387fff 12078 case OPC_LB ... OPC_LWR: /* Load and stores */
5c13fdfd 12079 case OPC_LL:
afa88c3a 12080 gen_ld(env, ctx, op, rt, rs, imm);
5c13fdfd 12081 break;
7a387fff
TS
12082 case OPC_SB ... OPC_SW:
12083 case OPC_SWR:
5c13fdfd 12084 gen_st(ctx, op, rt, rs, imm);
7a387fff 12085 break;
d66c7132
AJ
12086 case OPC_SC:
12087 gen_st_cond(ctx, op, rt, rs, imm);
12088 break;
7a387fff 12089 case OPC_CACHE:
e189e748 12090 check_insn(env, ctx, ISA_MIPS3 | ISA_MIPS32);
ead9360e 12091 /* Treat as NOP. */
34ae7b51 12092 break;
7a387fff 12093 case OPC_PREF:
e189e748 12094 check_insn(env, ctx, ISA_MIPS4 | ISA_MIPS32);
ead9360e 12095 /* Treat as NOP. */
6af0bf9c 12096 break;
4ad40f36 12097
923617a3 12098 /* Floating point (COP1). */
7a387fff
TS
12099 case OPC_LWC1:
12100 case OPC_LDC1:
12101 case OPC_SWC1:
12102 case OPC_SDC1:
26ebe468 12103 gen_cop1_ldst(env, ctx, op, rt, rs, imm);
6ea83fed
FB
12104 break;
12105
7a387fff 12106 case OPC_CP1:
36d23958 12107 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
5e755519 12108 check_cp1_enabled(ctx);
36d23958
TS
12109 op1 = MASK_CP1(ctx->opcode);
12110 switch (op1) {
3a95e3a7
TS
12111 case OPC_MFHC1:
12112 case OPC_MTHC1:
e189e748 12113 check_insn(env, ctx, ISA_MIPS32R2);
36d23958
TS
12114 case OPC_MFC1:
12115 case OPC_CFC1:
12116 case OPC_MTC1:
12117 case OPC_CTC1:
e189e748
TS
12118 gen_cp1(ctx, op1, rt, rd);
12119 break;
d26bc211 12120#if defined(TARGET_MIPS64)
36d23958
TS
12121 case OPC_DMFC1:
12122 case OPC_DMTC1:
e189e748 12123 check_insn(env, ctx, ISA_MIPS3);
36d23958
TS
12124 gen_cp1(ctx, op1, rt, rd);
12125 break;
e189e748 12126#endif
fbcc6828
TS
12127 case OPC_BC1ANY2:
12128 case OPC_BC1ANY4:
b8aa4598 12129 check_cop1x(ctx);
7385ac0b 12130 check_insn(env, ctx, ASE_MIPS3D);
d8a5950a
TS
12131 /* fall through */
12132 case OPC_BC1:
e189e748 12133 gen_compute_branch1(env, ctx, MASK_BC1(ctx->opcode),
5a5012ec 12134 (rt >> 2) & 0x7, imm << 2);
c9602061
NF
12135 *is_branch = 1;
12136 break;
36d23958
TS
12137 case OPC_S_FMT:
12138 case OPC_D_FMT:
12139 case OPC_W_FMT:
12140 case OPC_L_FMT:
5a5012ec 12141 case OPC_PS_FMT:
bf4120ad 12142 gen_farith(ctx, ctx->opcode & FOP(0x3f, 0x1f), rt, rd, sa,
5a5012ec 12143 (imm >> 8) & 0x7);
36d23958
TS
12144 break;
12145 default:
923617a3 12146 MIPS_INVAL("cp1");
e397ee33 12147 generate_exception (ctx, EXCP_RI);
36d23958
TS
12148 break;
12149 }
12150 } else {
12151 generate_exception_err(ctx, EXCP_CpU, 1);
6ea83fed 12152 }
4ad40f36
FB
12153 break;
12154
12155 /* COP2. */
7a387fff
TS
12156 case OPC_LWC2:
12157 case OPC_LDC2:
12158 case OPC_SWC2:
12159 case OPC_SDC2:
12160 case OPC_CP2:
12161 /* COP2: Not implemented. */
4ad40f36
FB
12162 generate_exception_err(ctx, EXCP_CpU, 2);
12163 break;
12164
7a387fff 12165 case OPC_CP3:
36d23958 12166 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
5e755519 12167 check_cp1_enabled(ctx);
36d23958
TS
12168 op1 = MASK_CP3(ctx->opcode);
12169 switch (op1) {
5a5012ec
TS
12170 case OPC_LWXC1:
12171 case OPC_LDXC1:
12172 case OPC_LUXC1:
12173 case OPC_SWXC1:
12174 case OPC_SDXC1:
12175 case OPC_SUXC1:
93b12ccc 12176 gen_flt3_ldst(ctx, op1, sa, rd, rs, rt);
5a5012ec 12177 break;
e0c84da7 12178 case OPC_PREFX:
ead9360e 12179 /* Treat as NOP. */
e0c84da7 12180 break;
5a5012ec
TS
12181 case OPC_ALNV_PS:
12182 case OPC_MADD_S:
12183 case OPC_MADD_D:
12184 case OPC_MADD_PS:
12185 case OPC_MSUB_S:
12186 case OPC_MSUB_D:
12187 case OPC_MSUB_PS:
12188 case OPC_NMADD_S:
12189 case OPC_NMADD_D:
12190 case OPC_NMADD_PS:
12191 case OPC_NMSUB_S:
12192 case OPC_NMSUB_D:
12193 case OPC_NMSUB_PS:
12194 gen_flt3_arith(ctx, op1, sa, rs, rd, rt);
12195 break;
36d23958 12196 default:
923617a3 12197 MIPS_INVAL("cp3");
e397ee33 12198 generate_exception (ctx, EXCP_RI);
36d23958
TS
12199 break;
12200 }
12201 } else {
e397ee33 12202 generate_exception_err(ctx, EXCP_CpU, 1);
7a387fff 12203 }
4ad40f36
FB
12204 break;
12205
d26bc211 12206#if defined(TARGET_MIPS64)
7a387fff
TS
12207 /* MIPS64 opcodes */
12208 case OPC_LWU:
12209 case OPC_LDL ... OPC_LDR:
7a387fff
TS
12210 case OPC_LLD:
12211 case OPC_LD:
5c13fdfd
AJ
12212 check_insn(env, ctx, ISA_MIPS3);
12213 check_mips_64(ctx);
afa88c3a 12214 gen_ld(env, ctx, op, rt, rs, imm);
5c13fdfd
AJ
12215 break;
12216 case OPC_SDL ... OPC_SDR:
7a387fff 12217 case OPC_SD:
e189e748
TS
12218 check_insn(env, ctx, ISA_MIPS3);
12219 check_mips_64(ctx);
5c13fdfd 12220 gen_st(ctx, op, rt, rs, imm);
7a387fff 12221 break;
d66c7132
AJ
12222 case OPC_SCD:
12223 check_insn(env, ctx, ISA_MIPS3);
12224 check_mips_64(ctx);
12225 gen_st_cond(ctx, op, rt, rs, imm);
12226 break;
324d9e32
AJ
12227 case OPC_DADDI:
12228 case OPC_DADDIU:
e189e748
TS
12229 check_insn(env, ctx, ISA_MIPS3);
12230 check_mips_64(ctx);
12231 gen_arith_imm(env, ctx, op, rt, rs, imm);
7a387fff 12232 break;
6af0bf9c 12233#endif
7a387fff 12234 case OPC_JALX:
3c824109 12235 check_insn(env, ctx, ASE_MIPS16 | ASE_MICROMIPS);
364d4831
NF
12236 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2;
12237 gen_compute_branch(ctx, op, 4, rs, rt, offset);
12238 *is_branch = 1;
12239 break;
7a387fff 12240 case OPC_MDMX:
e189e748 12241 check_insn(env, ctx, ASE_MDMX);
7a387fff 12242 /* MDMX: Not implemented. */
6af0bf9c 12243 default: /* Invalid */
923617a3 12244 MIPS_INVAL("major opcode");
6af0bf9c
FB
12245 generate_exception(ctx, EXCP_RI);
12246 break;
12247 }
6af0bf9c
FB
12248}
12249
2cfc5f17 12250static inline void
820e00f2
TS
12251gen_intermediate_code_internal (CPUState *env, TranslationBlock *tb,
12252 int search_pc)
6af0bf9c 12253{
278d0702 12254 DisasContext ctx;
6af0bf9c
FB
12255 target_ulong pc_start;
12256 uint16_t *gen_opc_end;
a1d1bb31 12257 CPUBreakpoint *bp;
6af0bf9c 12258 int j, lj = -1;
2e70f6ef
PB
12259 int num_insns;
12260 int max_insns;
c9602061
NF
12261 int insn_bytes;
12262 int is_branch;
6af0bf9c 12263
93fcfe39
AL
12264 if (search_pc)
12265 qemu_log("search pc %d\n", search_pc);
4ad40f36 12266
6af0bf9c 12267 pc_start = tb->pc;
d42320c2 12268 gen_opc_end = gen_opc_buf + OPC_MAX_SIZE;
6af0bf9c 12269 ctx.pc = pc_start;
4ad40f36 12270 ctx.saved_pc = -1;
7b270ef2 12271 ctx.singlestep_enabled = env->singlestep_enabled;
6af0bf9c
FB
12272 ctx.tb = tb;
12273 ctx.bstate = BS_NONE;
4ad40f36 12274 /* Restore delay slot state from the tb context. */
c068688b 12275 ctx.hflags = (uint32_t)tb->flags; /* FIXME: maybe use 64 bits here? */
fd4a04eb 12276 restore_cpu_state(env, &ctx);
932e71cd 12277#ifdef CONFIG_USER_ONLY
0eaef5aa 12278 ctx.mem_idx = MIPS_HFLAG_UM;
932e71cd 12279#else
0eaef5aa 12280 ctx.mem_idx = ctx.hflags & MIPS_HFLAG_KSU;
932e71cd 12281#endif
2e70f6ef
PB
12282 num_insns = 0;
12283 max_insns = tb->cflags & CF_COUNT_MASK;
12284 if (max_insns == 0)
12285 max_insns = CF_COUNT_MASK;
d12d51d5 12286 LOG_DISAS("\ntb %p idx %d hflags %04x\n", tb, ctx.mem_idx, ctx.hflags);
2e70f6ef 12287 gen_icount_start();
faf7aaa9 12288 while (ctx.bstate == BS_NONE) {
72cf2d4f
BS
12289 if (unlikely(!QTAILQ_EMPTY(&env->breakpoints))) {
12290 QTAILQ_FOREACH(bp, &env->breakpoints, entry) {
a1d1bb31 12291 if (bp->pc == ctx.pc) {
278d0702 12292 save_cpu_state(&ctx, 1);
4ad40f36 12293 ctx.bstate = BS_BRANCH;
a7812ae4 12294 gen_helper_0i(raise_exception, EXCP_DEBUG);
ce62e5ba
TS
12295 /* Include the breakpoint location or the tb won't
12296 * be flushed when it must be. */
12297 ctx.pc += 4;
4ad40f36
FB
12298 goto done_generating;
12299 }
12300 }
12301 }
12302
6af0bf9c
FB
12303 if (search_pc) {
12304 j = gen_opc_ptr - gen_opc_buf;
6af0bf9c
FB
12305 if (lj < j) {
12306 lj++;
12307 while (lj < j)
12308 gen_opc_instr_start[lj++] = 0;
6af0bf9c 12309 }
4ad40f36
FB
12310 gen_opc_pc[lj] = ctx.pc;
12311 gen_opc_hflags[lj] = ctx.hflags & MIPS_HFLAG_BMASK;
12312 gen_opc_instr_start[lj] = 1;
2e70f6ef 12313 gen_opc_icount[lj] = num_insns;
6af0bf9c 12314 }
2e70f6ef
PB
12315 if (num_insns + 1 == max_insns && (tb->cflags & CF_LAST_IO))
12316 gen_io_start();
c9602061
NF
12317
12318 is_branch = 0;
364d4831 12319 if (!(ctx.hflags & MIPS_HFLAG_M16)) {
c9602061
NF
12320 ctx.opcode = ldl_code(ctx.pc);
12321 insn_bytes = 4;
12322 decode_opc(env, &ctx, &is_branch);
3c824109
NF
12323 } else if (env->insn_flags & ASE_MICROMIPS) {
12324 ctx.opcode = lduw_code(ctx.pc);
12325 insn_bytes = decode_micromips_opc(env, &ctx, &is_branch);
364d4831
NF
12326 } else if (env->insn_flags & ASE_MIPS16) {
12327 ctx.opcode = lduw_code(ctx.pc);
12328 insn_bytes = decode_mips16_opc(env, &ctx, &is_branch);
c9602061
NF
12329 } else {
12330 generate_exception(&ctx, EXCP_RI);
3c824109 12331 ctx.bstate = BS_STOP;
c9602061
NF
12332 break;
12333 }
12334 if (!is_branch) {
12335 handle_delay_slot(env, &ctx, insn_bytes);
12336 }
12337 ctx.pc += insn_bytes;
12338
2e70f6ef 12339 num_insns++;
4ad40f36 12340
7b270ef2
NF
12341 /* Execute a branch and its delay slot as a single instruction.
12342 This is what GDB expects and is consistent with what the
12343 hardware does (e.g. if a delay slot instruction faults, the
12344 reported PC is the PC of the branch). */
12345 if (env->singlestep_enabled && (ctx.hflags & MIPS_HFLAG_BMASK) == 0)
4ad40f36
FB
12346 break;
12347
6af0bf9c
FB
12348 if ((ctx.pc & (TARGET_PAGE_SIZE - 1)) == 0)
12349 break;
4ad40f36 12350
faf7aaa9
TS
12351 if (gen_opc_ptr >= gen_opc_end)
12352 break;
12353
2e70f6ef
PB
12354 if (num_insns >= max_insns)
12355 break;
1b530a6d
AJ
12356
12357 if (singlestep)
12358 break;
6af0bf9c 12359 }
2e70f6ef
PB
12360 if (tb->cflags & CF_LAST_IO)
12361 gen_io_end();
7b270ef2 12362 if (env->singlestep_enabled && ctx.bstate != BS_BRANCH) {
278d0702 12363 save_cpu_state(&ctx, ctx.bstate == BS_NONE);
a7812ae4 12364 gen_helper_0i(raise_exception, EXCP_DEBUG);
16c00cb2 12365 } else {
6958549d 12366 switch (ctx.bstate) {
16c00cb2 12367 case BS_STOP:
a7812ae4 12368 gen_helper_interrupt_restart();
df1561e2
TS
12369 gen_goto_tb(&ctx, 0, ctx.pc);
12370 break;
16c00cb2 12371 case BS_NONE:
278d0702 12372 save_cpu_state(&ctx, 0);
16c00cb2
TS
12373 gen_goto_tb(&ctx, 0, ctx.pc);
12374 break;
5a5012ec 12375 case BS_EXCP:
a7812ae4 12376 gen_helper_interrupt_restart();
57fec1fe 12377 tcg_gen_exit_tb(0);
16c00cb2 12378 break;
5a5012ec
TS
12379 case BS_BRANCH:
12380 default:
12381 break;
6958549d 12382 }
6af0bf9c 12383 }
4ad40f36 12384done_generating:
2e70f6ef 12385 gen_icount_end(tb, num_insns);
6af0bf9c
FB
12386 *gen_opc_ptr = INDEX_op_end;
12387 if (search_pc) {
12388 j = gen_opc_ptr - gen_opc_buf;
12389 lj++;
12390 while (lj <= j)
12391 gen_opc_instr_start[lj++] = 0;
6af0bf9c
FB
12392 } else {
12393 tb->size = ctx.pc - pc_start;
2e70f6ef 12394 tb->icount = num_insns;
6af0bf9c
FB
12395 }
12396#ifdef DEBUG_DISAS
d12d51d5 12397 LOG_DISAS("\n");
8fec2b8c 12398 if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) {
93fcfe39
AL
12399 qemu_log("IN: %s\n", lookup_symbol(pc_start));
12400 log_target_disas(pc_start, ctx.pc - pc_start, 0);
12401 qemu_log("\n");
6af0bf9c
FB
12402 }
12403#endif
6af0bf9c
FB
12404}
12405
2cfc5f17 12406void gen_intermediate_code (CPUState *env, struct TranslationBlock *tb)
6af0bf9c 12407{
2cfc5f17 12408 gen_intermediate_code_internal(env, tb, 0);
6af0bf9c
FB
12409}
12410
2cfc5f17 12411void gen_intermediate_code_pc (CPUState *env, struct TranslationBlock *tb)
6af0bf9c 12412{
2cfc5f17 12413 gen_intermediate_code_internal(env, tb, 1);
6af0bf9c
FB
12414}
12415
8706c382
TS
12416static void fpu_dump_state(CPUState *env, FILE *f,
12417 int (*fpu_fprintf)(FILE *f, const char *fmt, ...),
12418 int flags)
6ea83fed
FB
12419{
12420 int i;
5e755519 12421 int is_fpu64 = !!(env->hflags & MIPS_HFLAG_F64);
5a5012ec 12422
2a5612e6
SW
12423#define printfpr(fp) \
12424 do { \
12425 if (is_fpu64) \
12426 fpu_fprintf(f, "w:%08x d:%016" PRIx64 \
12427 " fd:%13g fs:%13g psu: %13g\n", \
12428 (fp)->w[FP_ENDIAN_IDX], (fp)->d, \
12429 (double)(fp)->fd, \
12430 (double)(fp)->fs[FP_ENDIAN_IDX], \
12431 (double)(fp)->fs[!FP_ENDIAN_IDX]); \
12432 else { \
12433 fpr_t tmp; \
12434 tmp.w[FP_ENDIAN_IDX] = (fp)->w[FP_ENDIAN_IDX]; \
12435 tmp.w[!FP_ENDIAN_IDX] = ((fp) + 1)->w[FP_ENDIAN_IDX]; \
12436 fpu_fprintf(f, "w:%08x d:%016" PRIx64 \
12437 " fd:%13g fs:%13g psu:%13g\n", \
12438 tmp.w[FP_ENDIAN_IDX], tmp.d, \
12439 (double)tmp.fd, \
12440 (double)tmp.fs[FP_ENDIAN_IDX], \
12441 (double)tmp.fs[!FP_ENDIAN_IDX]); \
12442 } \
6ea83fed
FB
12443 } while(0)
12444
5a5012ec
TS
12445
12446 fpu_fprintf(f, "CP1 FCR0 0x%08x FCR31 0x%08x SR.FR %d fp_status 0x%08x(0x%02x)\n",
f01be154
TS
12447 env->active_fpu.fcr0, env->active_fpu.fcr31, is_fpu64, env->active_fpu.fp_status,
12448 get_float_exception_flags(&env->active_fpu.fp_status));
5a5012ec
TS
12449 for (i = 0; i < 32; (is_fpu64) ? i++ : (i += 2)) {
12450 fpu_fprintf(f, "%3s: ", fregnames[i]);
f01be154 12451 printfpr(&env->active_fpu.fpr[i]);
6ea83fed
FB
12452 }
12453
12454#undef printfpr
12455}
12456
d26bc211 12457#if defined(TARGET_MIPS64) && defined(MIPS_DEBUG_SIGN_EXTENSIONS)
c570fd16 12458/* Debug help: The architecture requires 32bit code to maintain proper
c7e8a937 12459 sign-extended values on 64bit machines. */
c570fd16
TS
12460
12461#define SIGN_EXT_P(val) ((((val) & ~0x7fffffff) == 0) || (((val) & ~0x7fffffff) == ~0x7fffffff))
12462
8706c382
TS
12463static void
12464cpu_mips_check_sign_extensions (CPUState *env, FILE *f,
12465 int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
12466 int flags)
c570fd16
TS
12467{
12468 int i;
12469
b5dc7732
TS
12470 if (!SIGN_EXT_P(env->active_tc.PC))
12471 cpu_fprintf(f, "BROKEN: pc=0x" TARGET_FMT_lx "\n", env->active_tc.PC);
12472 if (!SIGN_EXT_P(env->active_tc.HI[0]))
12473 cpu_fprintf(f, "BROKEN: HI=0x" TARGET_FMT_lx "\n", env->active_tc.HI[0]);
12474 if (!SIGN_EXT_P(env->active_tc.LO[0]))
12475 cpu_fprintf(f, "BROKEN: LO=0x" TARGET_FMT_lx "\n", env->active_tc.LO[0]);
c570fd16 12476 if (!SIGN_EXT_P(env->btarget))
3594c774 12477 cpu_fprintf(f, "BROKEN: btarget=0x" TARGET_FMT_lx "\n", env->btarget);
c570fd16
TS
12478
12479 for (i = 0; i < 32; i++) {
b5dc7732
TS
12480 if (!SIGN_EXT_P(env->active_tc.gpr[i]))
12481 cpu_fprintf(f, "BROKEN: %s=0x" TARGET_FMT_lx "\n", regnames[i], env->active_tc.gpr[i]);
c570fd16
TS
12482 }
12483
12484 if (!SIGN_EXT_P(env->CP0_EPC))
3594c774 12485 cpu_fprintf(f, "BROKEN: EPC=0x" TARGET_FMT_lx "\n", env->CP0_EPC);
5499b6ff
AJ
12486 if (!SIGN_EXT_P(env->lladdr))
12487 cpu_fprintf(f, "BROKEN: LLAddr=0x" TARGET_FMT_lx "\n", env->lladdr);
c570fd16
TS
12488}
12489#endif
12490
5fafdf24 12491void cpu_dump_state (CPUState *env, FILE *f,
6af0bf9c
FB
12492 int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
12493 int flags)
12494{
12495 int i;
3b46e624 12496
a7200c9f
SW
12497 cpu_fprintf(f, "pc=0x" TARGET_FMT_lx " HI=0x" TARGET_FMT_lx
12498 " LO=0x" TARGET_FMT_lx " ds %04x "
12499 TARGET_FMT_lx " " TARGET_FMT_ld "\n",
3d5be870
TS
12500 env->active_tc.PC, env->active_tc.HI[0], env->active_tc.LO[0],
12501 env->hflags, env->btarget, env->bcond);
6af0bf9c
FB
12502 for (i = 0; i < 32; i++) {
12503 if ((i & 3) == 0)
12504 cpu_fprintf(f, "GPR%02d:", i);
b5dc7732 12505 cpu_fprintf(f, " %s " TARGET_FMT_lx, regnames[i], env->active_tc.gpr[i]);
6af0bf9c
FB
12506 if ((i & 3) == 3)
12507 cpu_fprintf(f, "\n");
12508 }
568b600d 12509
3594c774 12510 cpu_fprintf(f, "CP0 Status 0x%08x Cause 0x%08x EPC 0x" TARGET_FMT_lx "\n",
5e755519 12511 env->CP0_Status, env->CP0_Cause, env->CP0_EPC);
3594c774 12512 cpu_fprintf(f, " Config0 0x%08x Config1 0x%08x LLAddr 0x" TARGET_FMT_lx "\n",
5499b6ff 12513 env->CP0_Config0, env->CP0_Config1, env->lladdr);
5e755519 12514 if (env->hflags & MIPS_HFLAG_FPU)
7a387fff 12515 fpu_dump_state(env, f, cpu_fprintf, flags);
d26bc211 12516#if defined(TARGET_MIPS64) && defined(MIPS_DEBUG_SIGN_EXTENSIONS)
c570fd16
TS
12517 cpu_mips_check_sign_extensions(env, f, cpu_fprintf, flags);
12518#endif
6af0bf9c
FB
12519}
12520
39454628
TS
12521static void mips_tcg_init(void)
12522{
f01be154 12523 int i;
39454628
TS
12524 static int inited;
12525
12526 /* Initialize various static tables. */
12527 if (inited)
6958549d 12528 return;
39454628 12529
a7812ae4 12530 cpu_env = tcg_global_reg_new_ptr(TCG_AREG0, "env");
f2c94b92 12531 TCGV_UNUSED(cpu_gpr[0]);
bb928dbe 12532 for (i = 1; i < 32; i++)
a7812ae4 12533 cpu_gpr[i] = tcg_global_mem_new(TCG_AREG0,
4b2eb8d2
TS
12534 offsetof(CPUState, active_tc.gpr[i]),
12535 regnames[i]);
a7812ae4 12536 cpu_PC = tcg_global_mem_new(TCG_AREG0,
4b2eb8d2
TS
12537 offsetof(CPUState, active_tc.PC), "PC");
12538 for (i = 0; i < MIPS_DSP_ACC; i++) {
a7812ae4 12539 cpu_HI[i] = tcg_global_mem_new(TCG_AREG0,
4b2eb8d2
TS
12540 offsetof(CPUState, active_tc.HI[i]),
12541 regnames_HI[i]);
a7812ae4 12542 cpu_LO[i] = tcg_global_mem_new(TCG_AREG0,
4b2eb8d2
TS
12543 offsetof(CPUState, active_tc.LO[i]),
12544 regnames_LO[i]);
a7812ae4 12545 cpu_ACX[i] = tcg_global_mem_new(TCG_AREG0,
4b2eb8d2
TS
12546 offsetof(CPUState, active_tc.ACX[i]),
12547 regnames_ACX[i]);
12548 }
a7812ae4 12549 cpu_dspctrl = tcg_global_mem_new(TCG_AREG0,
4b2eb8d2
TS
12550 offsetof(CPUState, active_tc.DSPControl),
12551 "DSPControl");
1ba74fb8
AJ
12552 bcond = tcg_global_mem_new(TCG_AREG0,
12553 offsetof(CPUState, bcond), "bcond");
a7812ae4 12554 btarget = tcg_global_mem_new(TCG_AREG0,
d077b6f7 12555 offsetof(CPUState, btarget), "btarget");
41db4607
AJ
12556 hflags = tcg_global_mem_new_i32(TCG_AREG0,
12557 offsetof(CPUState, hflags), "hflags");
12558
a7812ae4
PB
12559 fpu_fcr0 = tcg_global_mem_new_i32(TCG_AREG0,
12560 offsetof(CPUState, active_fpu.fcr0),
12561 "fcr0");
12562 fpu_fcr31 = tcg_global_mem_new_i32(TCG_AREG0,
12563 offsetof(CPUState, active_fpu.fcr31),
12564 "fcr31");
39454628 12565
7dd9e556 12566 /* register helpers */
a7812ae4 12567#define GEN_HELPER 2
7dd9e556
TS
12568#include "helper.h"
12569
39454628
TS
12570 inited = 1;
12571}
12572
aaed909a
FB
12573#include "translate_init.c"
12574
12575CPUMIPSState *cpu_mips_init (const char *cpu_model)
6af0bf9c
FB
12576{
12577 CPUMIPSState *env;
c227f099 12578 const mips_def_t *def;
6af0bf9c 12579
aaed909a
FB
12580 def = cpu_mips_find_by_name(cpu_model);
12581 if (!def)
12582 return NULL;
6af0bf9c 12583 env = qemu_mallocz(sizeof(CPUMIPSState));
aaed909a 12584 env->cpu_model = def;
51cc2e78 12585 env->cpu_model_str = cpu_model;
aaed909a 12586
173d6cfe 12587 cpu_exec_init(env);
51cc2e78
BS
12588#ifndef CONFIG_USER_ONLY
12589 mmu_init(env, def);
12590#endif
12591 fpu_init(env, def);
12592 mvp_init(env, def);
39454628 12593 mips_tcg_init();
6ae81775 12594 cpu_reset(env);
0bf46a40 12595 qemu_init_vcpu(env);
6ae81775
TS
12596 return env;
12597}
12598
12599void cpu_reset (CPUMIPSState *env)
12600{
eca1bdf4
AL
12601 if (qemu_loglevel_mask(CPU_LOG_RESET)) {
12602 qemu_log("CPU Reset (CPU %d)\n", env->cpu_index);
12603 log_cpu_state(env, 0);
12604 }
12605
6ae81775 12606 memset(env, 0, offsetof(CPUMIPSState, breakpoints));
6af0bf9c 12607 tlb_flush(env, 1);
6ae81775 12608
51cc2e78
BS
12609 /* Reset registers to their default values */
12610 env->CP0_PRid = env->cpu_model->CP0_PRid;
12611 env->CP0_Config0 = env->cpu_model->CP0_Config0;
12612#ifdef TARGET_WORDS_BIGENDIAN
12613 env->CP0_Config0 |= (1 << CP0C0_BE);
12614#endif
12615 env->CP0_Config1 = env->cpu_model->CP0_Config1;
12616 env->CP0_Config2 = env->cpu_model->CP0_Config2;
12617 env->CP0_Config3 = env->cpu_model->CP0_Config3;
12618 env->CP0_Config6 = env->cpu_model->CP0_Config6;
12619 env->CP0_Config7 = env->cpu_model->CP0_Config7;
2a6e32dd
AJ
12620 env->CP0_LLAddr_rw_bitmask = env->cpu_model->CP0_LLAddr_rw_bitmask
12621 << env->cpu_model->CP0_LLAddr_shift;
12622 env->CP0_LLAddr_shift = env->cpu_model->CP0_LLAddr_shift;
51cc2e78
BS
12623 env->SYNCI_Step = env->cpu_model->SYNCI_Step;
12624 env->CCRes = env->cpu_model->CCRes;
12625 env->CP0_Status_rw_bitmask = env->cpu_model->CP0_Status_rw_bitmask;
12626 env->CP0_TCStatus_rw_bitmask = env->cpu_model->CP0_TCStatus_rw_bitmask;
12627 env->CP0_SRSCtl = env->cpu_model->CP0_SRSCtl;
12628 env->current_tc = 0;
12629 env->SEGBITS = env->cpu_model->SEGBITS;
12630 env->SEGMask = (target_ulong)((1ULL << env->cpu_model->SEGBITS) - 1);
12631#if defined(TARGET_MIPS64)
12632 if (env->cpu_model->insn_flags & ISA_MIPS3) {
12633 env->SEGMask |= 3ULL << 62;
12634 }
12635#endif
12636 env->PABITS = env->cpu_model->PABITS;
12637 env->PAMask = (target_ulong)((1ULL << env->cpu_model->PABITS) - 1);
12638 env->CP0_SRSConf0_rw_bitmask = env->cpu_model->CP0_SRSConf0_rw_bitmask;
12639 env->CP0_SRSConf0 = env->cpu_model->CP0_SRSConf0;
12640 env->CP0_SRSConf1_rw_bitmask = env->cpu_model->CP0_SRSConf1_rw_bitmask;
12641 env->CP0_SRSConf1 = env->cpu_model->CP0_SRSConf1;
12642 env->CP0_SRSConf2_rw_bitmask = env->cpu_model->CP0_SRSConf2_rw_bitmask;
12643 env->CP0_SRSConf2 = env->cpu_model->CP0_SRSConf2;
12644 env->CP0_SRSConf3_rw_bitmask = env->cpu_model->CP0_SRSConf3_rw_bitmask;
12645 env->CP0_SRSConf3 = env->cpu_model->CP0_SRSConf3;
12646 env->CP0_SRSConf4_rw_bitmask = env->cpu_model->CP0_SRSConf4_rw_bitmask;
12647 env->CP0_SRSConf4 = env->cpu_model->CP0_SRSConf4;
12648 env->insn_flags = env->cpu_model->insn_flags;
12649
0eaef5aa 12650#if defined(CONFIG_USER_ONLY)
932e71cd 12651 env->hflags = MIPS_HFLAG_UM;
df357f0e
PB
12652 /* Enable access to the SYNCI_Step register. */
12653 env->CP0_HWREna |= (1 << 1);
91a75935
NF
12654 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
12655 env->hflags |= MIPS_HFLAG_FPU;
12656 }
12657#ifdef TARGET_MIPS64
12658 if (env->active_fpu.fcr0 & (1 << FCR0_F64)) {
12659 env->hflags |= MIPS_HFLAG_F64;
12660 }
12661#endif
932e71cd
AJ
12662#else
12663 if (env->hflags & MIPS_HFLAG_BMASK) {
12664 /* If the exception was raised from a delay slot,
12665 come back to the jump. */
12666 env->CP0_ErrorEPC = env->active_tc.PC - 4;
aa328add 12667 } else {
932e71cd
AJ
12668 env->CP0_ErrorEPC = env->active_tc.PC;
12669 }
12670 env->active_tc.PC = (int32_t)0xBFC00000;
51cc2e78
BS
12671 env->CP0_Random = env->tlb->nb_tlb - 1;
12672 env->tlb->tlb_in_use = env->tlb->nb_tlb;
932e71cd
AJ
12673 env->CP0_Wired = 0;
12674 /* SMP not implemented */
12675 env->CP0_EBase = 0x80000000;
12676 env->CP0_Status = (1 << CP0St_BEV) | (1 << CP0St_ERL);
12677 /* vectored interrupts not implemented, timer on int 7,
12678 no performance counters. */
12679 env->CP0_IntCtl = 0xe0000000;
12680 {
12681 int i;
12682
12683 for (i = 0; i < 7; i++) {
12684 env->CP0_WatchLo[i] = 0;
12685 env->CP0_WatchHi[i] = 0x80000000;
fd88b6ab 12686 }
932e71cd
AJ
12687 env->CP0_WatchLo[7] = 0;
12688 env->CP0_WatchHi[7] = 0;
fd88b6ab 12689 }
932e71cd
AJ
12690 /* Count register increments in debug mode, EJTAG version 1 */
12691 env->CP0_Debug = (1 << CP0DB_CNT) | (0x1 << CP0DB_VER);
12692 env->hflags = MIPS_HFLAG_CP0;
51cc2e78
BS
12693#endif
12694#if defined(TARGET_MIPS64)
12695 if (env->cpu_model->insn_flags & ISA_MIPS3) {
12696 env->hflags |= MIPS_HFLAG_64;
12697 }
932e71cd 12698#endif
6af0bf9c 12699 env->exception_index = EXCP_NONE;
6af0bf9c 12700}
d2856f1a
AJ
12701
12702void gen_pc_load(CPUState *env, TranslationBlock *tb,
12703 unsigned long searched_pc, int pc_pos, void *puc)
12704{
b5dc7732 12705 env->active_tc.PC = gen_opc_pc[pc_pos];
d2856f1a
AJ
12706 env->hflags &= ~MIPS_HFLAG_BMASK;
12707 env->hflags |= gen_opc_hflags[pc_pos];
12708}