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