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