]> git.proxmox.com Git - qemu.git/blame - target-mips/translate.c
Add new command line option -singlestep for tcg single stepping.
[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)
6af0bf9c
FB
7 *
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2 of the License, or (at your option) any later version.
12 *
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
17 *
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the Free Software
fad6cb1a 20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA
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),
60 OPC_ANDI = (0x0C << 26),
61 OPC_ORI = (0x0D << 26),
62 OPC_XORI = (0x0E << 26),
63 OPC_LUI = (0x0F << 26),
64 OPC_DADDI = (0x18 << 26),
65 OPC_DADDIU = (0x19 << 26),
e37e863f 66 /* Jump and branches */
7a387fff
TS
67 OPC_J = (0x02 << 26),
68 OPC_JAL = (0x03 << 26),
69 OPC_BEQ = (0x04 << 26), /* Unconditional if rs = rt = 0 (B) */
70 OPC_BEQL = (0x14 << 26),
71 OPC_BNE = (0x05 << 26),
72 OPC_BNEL = (0x15 << 26),
73 OPC_BLEZ = (0x06 << 26),
74 OPC_BLEZL = (0x16 << 26),
75 OPC_BGTZ = (0x07 << 26),
76 OPC_BGTZL = (0x17 << 26),
77 OPC_JALX = (0x1D << 26), /* MIPS 16 only */
e37e863f 78 /* Load and stores */
7a387fff
TS
79 OPC_LDL = (0x1A << 26),
80 OPC_LDR = (0x1B << 26),
81 OPC_LB = (0x20 << 26),
82 OPC_LH = (0x21 << 26),
83 OPC_LWL = (0x22 << 26),
84 OPC_LW = (0x23 << 26),
85 OPC_LBU = (0x24 << 26),
86 OPC_LHU = (0x25 << 26),
87 OPC_LWR = (0x26 << 26),
88 OPC_LWU = (0x27 << 26),
89 OPC_SB = (0x28 << 26),
90 OPC_SH = (0x29 << 26),
91 OPC_SWL = (0x2A << 26),
92 OPC_SW = (0x2B << 26),
93 OPC_SDL = (0x2C << 26),
94 OPC_SDR = (0x2D << 26),
95 OPC_SWR = (0x2E << 26),
96 OPC_LL = (0x30 << 26),
97 OPC_LLD = (0x34 << 26),
98 OPC_LD = (0x37 << 26),
99 OPC_SC = (0x38 << 26),
100 OPC_SCD = (0x3C << 26),
101 OPC_SD = (0x3F << 26),
e37e863f 102 /* Floating point load/store */
7a387fff
TS
103 OPC_LWC1 = (0x31 << 26),
104 OPC_LWC2 = (0x32 << 26),
105 OPC_LDC1 = (0x35 << 26),
106 OPC_LDC2 = (0x36 << 26),
107 OPC_SWC1 = (0x39 << 26),
108 OPC_SWC2 = (0x3A << 26),
109 OPC_SDC1 = (0x3D << 26),
110 OPC_SDC2 = (0x3E << 26),
111 /* MDMX ASE specific */
112 OPC_MDMX = (0x1E << 26),
e37e863f 113 /* Cache and prefetch */
7a387fff
TS
114 OPC_CACHE = (0x2F << 26),
115 OPC_PREF = (0x33 << 26),
116 /* Reserved major opcode */
117 OPC_MAJOR3B_RESERVED = (0x3B << 26),
e37e863f
FB
118};
119
120/* MIPS special opcodes */
7a387fff
TS
121#define MASK_SPECIAL(op) MASK_OP_MAJOR(op) | (op & 0x3F)
122
e37e863f
FB
123enum {
124 /* Shifts */
7a387fff 125 OPC_SLL = 0x00 | OPC_SPECIAL,
e37e863f
FB
126 /* NOP is SLL r0, r0, 0 */
127 /* SSNOP is SLL r0, r0, 1 */
7a387fff
TS
128 /* EHB is SLL r0, r0, 3 */
129 OPC_SRL = 0x02 | OPC_SPECIAL, /* also ROTR */
130 OPC_SRA = 0x03 | OPC_SPECIAL,
131 OPC_SLLV = 0x04 | OPC_SPECIAL,
e189e748 132 OPC_SRLV = 0x06 | OPC_SPECIAL, /* also ROTRV */
7a387fff
TS
133 OPC_SRAV = 0x07 | OPC_SPECIAL,
134 OPC_DSLLV = 0x14 | OPC_SPECIAL,
135 OPC_DSRLV = 0x16 | OPC_SPECIAL, /* also DROTRV */
136 OPC_DSRAV = 0x17 | OPC_SPECIAL,
137 OPC_DSLL = 0x38 | OPC_SPECIAL,
138 OPC_DSRL = 0x3A | OPC_SPECIAL, /* also DROTR */
139 OPC_DSRA = 0x3B | OPC_SPECIAL,
140 OPC_DSLL32 = 0x3C | OPC_SPECIAL,
141 OPC_DSRL32 = 0x3E | OPC_SPECIAL, /* also DROTR32 */
142 OPC_DSRA32 = 0x3F | OPC_SPECIAL,
e37e863f 143 /* Multiplication / division */
7a387fff
TS
144 OPC_MULT = 0x18 | OPC_SPECIAL,
145 OPC_MULTU = 0x19 | OPC_SPECIAL,
146 OPC_DIV = 0x1A | OPC_SPECIAL,
147 OPC_DIVU = 0x1B | OPC_SPECIAL,
148 OPC_DMULT = 0x1C | OPC_SPECIAL,
149 OPC_DMULTU = 0x1D | OPC_SPECIAL,
150 OPC_DDIV = 0x1E | OPC_SPECIAL,
151 OPC_DDIVU = 0x1F | OPC_SPECIAL,
e37e863f 152 /* 2 registers arithmetic / logic */
7a387fff
TS
153 OPC_ADD = 0x20 | OPC_SPECIAL,
154 OPC_ADDU = 0x21 | OPC_SPECIAL,
155 OPC_SUB = 0x22 | OPC_SPECIAL,
156 OPC_SUBU = 0x23 | OPC_SPECIAL,
157 OPC_AND = 0x24 | OPC_SPECIAL,
158 OPC_OR = 0x25 | OPC_SPECIAL,
159 OPC_XOR = 0x26 | OPC_SPECIAL,
160 OPC_NOR = 0x27 | OPC_SPECIAL,
161 OPC_SLT = 0x2A | OPC_SPECIAL,
162 OPC_SLTU = 0x2B | OPC_SPECIAL,
163 OPC_DADD = 0x2C | OPC_SPECIAL,
164 OPC_DADDU = 0x2D | OPC_SPECIAL,
165 OPC_DSUB = 0x2E | OPC_SPECIAL,
166 OPC_DSUBU = 0x2F | OPC_SPECIAL,
e37e863f 167 /* Jumps */
7a387fff
TS
168 OPC_JR = 0x08 | OPC_SPECIAL, /* Also JR.HB */
169 OPC_JALR = 0x09 | OPC_SPECIAL, /* Also JALR.HB */
e37e863f 170 /* Traps */
7a387fff
TS
171 OPC_TGE = 0x30 | OPC_SPECIAL,
172 OPC_TGEU = 0x31 | OPC_SPECIAL,
173 OPC_TLT = 0x32 | OPC_SPECIAL,
174 OPC_TLTU = 0x33 | OPC_SPECIAL,
175 OPC_TEQ = 0x34 | OPC_SPECIAL,
176 OPC_TNE = 0x36 | OPC_SPECIAL,
e37e863f 177 /* HI / LO registers load & stores */
7a387fff
TS
178 OPC_MFHI = 0x10 | OPC_SPECIAL,
179 OPC_MTHI = 0x11 | OPC_SPECIAL,
180 OPC_MFLO = 0x12 | OPC_SPECIAL,
181 OPC_MTLO = 0x13 | OPC_SPECIAL,
e37e863f 182 /* Conditional moves */
7a387fff
TS
183 OPC_MOVZ = 0x0A | OPC_SPECIAL,
184 OPC_MOVN = 0x0B | OPC_SPECIAL,
e37e863f 185
7a387fff 186 OPC_MOVCI = 0x01 | OPC_SPECIAL,
e37e863f
FB
187
188 /* Special */
7a387fff
TS
189 OPC_PMON = 0x05 | OPC_SPECIAL, /* inofficial */
190 OPC_SYSCALL = 0x0C | OPC_SPECIAL,
191 OPC_BREAK = 0x0D | OPC_SPECIAL,
192 OPC_SPIM = 0x0E | OPC_SPECIAL, /* inofficial */
193 OPC_SYNC = 0x0F | OPC_SPECIAL,
194
195 OPC_SPECIAL15_RESERVED = 0x15 | OPC_SPECIAL,
196 OPC_SPECIAL28_RESERVED = 0x28 | OPC_SPECIAL,
197 OPC_SPECIAL29_RESERVED = 0x29 | OPC_SPECIAL,
198 OPC_SPECIAL35_RESERVED = 0x35 | OPC_SPECIAL,
199 OPC_SPECIAL37_RESERVED = 0x37 | OPC_SPECIAL,
200 OPC_SPECIAL39_RESERVED = 0x39 | OPC_SPECIAL,
201 OPC_SPECIAL3D_RESERVED = 0x3D | OPC_SPECIAL,
202};
203
e9c71dd1
TS
204/* Multiplication variants of the vr54xx. */
205#define MASK_MUL_VR54XX(op) MASK_SPECIAL(op) | (op & (0x1F << 6))
206
207enum {
208 OPC_VR54XX_MULS = (0x03 << 6) | OPC_MULT,
209 OPC_VR54XX_MULSU = (0x03 << 6) | OPC_MULTU,
210 OPC_VR54XX_MACC = (0x05 << 6) | OPC_MULT,
211 OPC_VR54XX_MACCU = (0x05 << 6) | OPC_MULTU,
212 OPC_VR54XX_MSAC = (0x07 << 6) | OPC_MULT,
213 OPC_VR54XX_MSACU = (0x07 << 6) | OPC_MULTU,
214 OPC_VR54XX_MULHI = (0x09 << 6) | OPC_MULT,
215 OPC_VR54XX_MULHIU = (0x09 << 6) | OPC_MULTU,
216 OPC_VR54XX_MULSHI = (0x0B << 6) | OPC_MULT,
217 OPC_VR54XX_MULSHIU = (0x0B << 6) | OPC_MULTU,
218 OPC_VR54XX_MACCHI = (0x0D << 6) | OPC_MULT,
219 OPC_VR54XX_MACCHIU = (0x0D << 6) | OPC_MULTU,
220 OPC_VR54XX_MSACHI = (0x0F << 6) | OPC_MULT,
221 OPC_VR54XX_MSACHIU = (0x0F << 6) | OPC_MULTU,
222};
223
7a387fff
TS
224/* REGIMM (rt field) opcodes */
225#define MASK_REGIMM(op) MASK_OP_MAJOR(op) | (op & (0x1F << 16))
226
227enum {
228 OPC_BLTZ = (0x00 << 16) | OPC_REGIMM,
229 OPC_BLTZL = (0x02 << 16) | OPC_REGIMM,
230 OPC_BGEZ = (0x01 << 16) | OPC_REGIMM,
231 OPC_BGEZL = (0x03 << 16) | OPC_REGIMM,
232 OPC_BLTZAL = (0x10 << 16) | OPC_REGIMM,
233 OPC_BLTZALL = (0x12 << 16) | OPC_REGIMM,
234 OPC_BGEZAL = (0x11 << 16) | OPC_REGIMM,
235 OPC_BGEZALL = (0x13 << 16) | OPC_REGIMM,
236 OPC_TGEI = (0x08 << 16) | OPC_REGIMM,
237 OPC_TGEIU = (0x09 << 16) | OPC_REGIMM,
238 OPC_TLTI = (0x0A << 16) | OPC_REGIMM,
239 OPC_TLTIU = (0x0B << 16) | OPC_REGIMM,
240 OPC_TEQI = (0x0C << 16) | OPC_REGIMM,
241 OPC_TNEI = (0x0E << 16) | OPC_REGIMM,
242 OPC_SYNCI = (0x1F << 16) | OPC_REGIMM,
e37e863f
FB
243};
244
7a387fff
TS
245/* Special2 opcodes */
246#define MASK_SPECIAL2(op) MASK_OP_MAJOR(op) | (op & 0x3F)
247
e37e863f 248enum {
7a387fff
TS
249 /* Multiply & xxx operations */
250 OPC_MADD = 0x00 | OPC_SPECIAL2,
251 OPC_MADDU = 0x01 | OPC_SPECIAL2,
252 OPC_MUL = 0x02 | OPC_SPECIAL2,
253 OPC_MSUB = 0x04 | OPC_SPECIAL2,
254 OPC_MSUBU = 0x05 | OPC_SPECIAL2,
e37e863f 255 /* Misc */
7a387fff
TS
256 OPC_CLZ = 0x20 | OPC_SPECIAL2,
257 OPC_CLO = 0x21 | OPC_SPECIAL2,
258 OPC_DCLZ = 0x24 | OPC_SPECIAL2,
259 OPC_DCLO = 0x25 | OPC_SPECIAL2,
e37e863f 260 /* Special */
7a387fff
TS
261 OPC_SDBBP = 0x3F | OPC_SPECIAL2,
262};
263
264/* Special3 opcodes */
265#define MASK_SPECIAL3(op) MASK_OP_MAJOR(op) | (op & 0x3F)
266
267enum {
268 OPC_EXT = 0x00 | OPC_SPECIAL3,
269 OPC_DEXTM = 0x01 | OPC_SPECIAL3,
270 OPC_DEXTU = 0x02 | OPC_SPECIAL3,
271 OPC_DEXT = 0x03 | OPC_SPECIAL3,
272 OPC_INS = 0x04 | OPC_SPECIAL3,
273 OPC_DINSM = 0x05 | OPC_SPECIAL3,
274 OPC_DINSU = 0x06 | OPC_SPECIAL3,
275 OPC_DINS = 0x07 | OPC_SPECIAL3,
ead9360e
TS
276 OPC_FORK = 0x08 | OPC_SPECIAL3,
277 OPC_YIELD = 0x09 | OPC_SPECIAL3,
7a387fff
TS
278 OPC_BSHFL = 0x20 | OPC_SPECIAL3,
279 OPC_DBSHFL = 0x24 | OPC_SPECIAL3,
280 OPC_RDHWR = 0x3B | OPC_SPECIAL3,
e37e863f
FB
281};
282
7a387fff
TS
283/* BSHFL opcodes */
284#define MASK_BSHFL(op) MASK_SPECIAL3(op) | (op & (0x1F << 6))
285
e37e863f 286enum {
7a387fff
TS
287 OPC_WSBH = (0x02 << 6) | OPC_BSHFL,
288 OPC_SEB = (0x10 << 6) | OPC_BSHFL,
289 OPC_SEH = (0x18 << 6) | OPC_BSHFL,
e37e863f
FB
290};
291
7a387fff
TS
292/* DBSHFL opcodes */
293#define MASK_DBSHFL(op) MASK_SPECIAL3(op) | (op & (0x1F << 6))
294
e37e863f 295enum {
7a387fff
TS
296 OPC_DSBH = (0x02 << 6) | OPC_DBSHFL,
297 OPC_DSHD = (0x05 << 6) | OPC_DBSHFL,
e37e863f
FB
298};
299
7a387fff
TS
300/* Coprocessor 0 (rs field) */
301#define MASK_CP0(op) MASK_OP_MAJOR(op) | (op & (0x1F << 21))
302
6ea83fed 303enum {
7a387fff
TS
304 OPC_MFC0 = (0x00 << 21) | OPC_CP0,
305 OPC_DMFC0 = (0x01 << 21) | OPC_CP0,
306 OPC_MTC0 = (0x04 << 21) | OPC_CP0,
307 OPC_DMTC0 = (0x05 << 21) | OPC_CP0,
ead9360e 308 OPC_MFTR = (0x08 << 21) | OPC_CP0,
7a387fff
TS
309 OPC_RDPGPR = (0x0A << 21) | OPC_CP0,
310 OPC_MFMC0 = (0x0B << 21) | OPC_CP0,
ead9360e 311 OPC_MTTR = (0x0C << 21) | OPC_CP0,
7a387fff
TS
312 OPC_WRPGPR = (0x0E << 21) | OPC_CP0,
313 OPC_C0 = (0x10 << 21) | OPC_CP0,
314 OPC_C0_FIRST = (0x10 << 21) | OPC_CP0,
315 OPC_C0_LAST = (0x1F << 21) | OPC_CP0,
6ea83fed 316};
7a387fff
TS
317
318/* MFMC0 opcodes */
b48cfdff 319#define MASK_MFMC0(op) MASK_CP0(op) | (op & 0xFFFF)
7a387fff
TS
320
321enum {
ead9360e
TS
322 OPC_DMT = 0x01 | (0 << 5) | (0x0F << 6) | (0x01 << 11) | OPC_MFMC0,
323 OPC_EMT = 0x01 | (1 << 5) | (0x0F << 6) | (0x01 << 11) | OPC_MFMC0,
324 OPC_DVPE = 0x01 | (0 << 5) | OPC_MFMC0,
325 OPC_EVPE = 0x01 | (1 << 5) | OPC_MFMC0,
7a387fff
TS
326 OPC_DI = (0 << 5) | (0x0C << 11) | OPC_MFMC0,
327 OPC_EI = (1 << 5) | (0x0C << 11) | OPC_MFMC0,
328};
329
330/* Coprocessor 0 (with rs == C0) */
331#define MASK_C0(op) MASK_CP0(op) | (op & 0x3F)
332
333enum {
334 OPC_TLBR = 0x01 | OPC_C0,
335 OPC_TLBWI = 0x02 | OPC_C0,
336 OPC_TLBWR = 0x06 | OPC_C0,
337 OPC_TLBP = 0x08 | OPC_C0,
338 OPC_RFE = 0x10 | OPC_C0,
339 OPC_ERET = 0x18 | OPC_C0,
340 OPC_DERET = 0x1F | OPC_C0,
341 OPC_WAIT = 0x20 | OPC_C0,
342};
343
344/* Coprocessor 1 (rs field) */
345#define MASK_CP1(op) MASK_OP_MAJOR(op) | (op & (0x1F << 21))
346
347enum {
348 OPC_MFC1 = (0x00 << 21) | OPC_CP1,
349 OPC_DMFC1 = (0x01 << 21) | OPC_CP1,
350 OPC_CFC1 = (0x02 << 21) | OPC_CP1,
5a5012ec 351 OPC_MFHC1 = (0x03 << 21) | OPC_CP1,
7a387fff
TS
352 OPC_MTC1 = (0x04 << 21) | OPC_CP1,
353 OPC_DMTC1 = (0x05 << 21) | OPC_CP1,
354 OPC_CTC1 = (0x06 << 21) | OPC_CP1,
5a5012ec 355 OPC_MTHC1 = (0x07 << 21) | OPC_CP1,
7a387fff 356 OPC_BC1 = (0x08 << 21) | OPC_CP1, /* bc */
5a5012ec
TS
357 OPC_BC1ANY2 = (0x09 << 21) | OPC_CP1,
358 OPC_BC1ANY4 = (0x0A << 21) | OPC_CP1,
7a387fff
TS
359 OPC_S_FMT = (0x10 << 21) | OPC_CP1, /* 16: fmt=single fp */
360 OPC_D_FMT = (0x11 << 21) | OPC_CP1, /* 17: fmt=double fp */
361 OPC_E_FMT = (0x12 << 21) | OPC_CP1, /* 18: fmt=extended fp */
362 OPC_Q_FMT = (0x13 << 21) | OPC_CP1, /* 19: fmt=quad fp */
363 OPC_W_FMT = (0x14 << 21) | OPC_CP1, /* 20: fmt=32bit fixed */
364 OPC_L_FMT = (0x15 << 21) | OPC_CP1, /* 21: fmt=64bit fixed */
5a5012ec 365 OPC_PS_FMT = (0x16 << 21) | OPC_CP1, /* 22: fmt=paired single fp */
7a387fff
TS
366};
367
5a5012ec
TS
368#define MASK_CP1_FUNC(op) MASK_CP1(op) | (op & 0x3F)
369#define MASK_BC1(op) MASK_CP1(op) | (op & (0x3 << 16))
370
7a387fff
TS
371enum {
372 OPC_BC1F = (0x00 << 16) | OPC_BC1,
373 OPC_BC1T = (0x01 << 16) | OPC_BC1,
374 OPC_BC1FL = (0x02 << 16) | OPC_BC1,
375 OPC_BC1TL = (0x03 << 16) | OPC_BC1,
376};
377
5a5012ec
TS
378enum {
379 OPC_BC1FANY2 = (0x00 << 16) | OPC_BC1ANY2,
380 OPC_BC1TANY2 = (0x01 << 16) | OPC_BC1ANY2,
381};
382
383enum {
384 OPC_BC1FANY4 = (0x00 << 16) | OPC_BC1ANY4,
385 OPC_BC1TANY4 = (0x01 << 16) | OPC_BC1ANY4,
386};
7a387fff
TS
387
388#define MASK_CP2(op) MASK_OP_MAJOR(op) | (op & (0x1F << 21))
e0c84da7
TS
389
390enum {
391 OPC_MFC2 = (0x00 << 21) | OPC_CP2,
392 OPC_DMFC2 = (0x01 << 21) | OPC_CP2,
393 OPC_CFC2 = (0x02 << 21) | OPC_CP2,
394 OPC_MFHC2 = (0x03 << 21) | OPC_CP2,
395 OPC_MTC2 = (0x04 << 21) | OPC_CP2,
396 OPC_DMTC2 = (0x05 << 21) | OPC_CP2,
397 OPC_CTC2 = (0x06 << 21) | OPC_CP2,
398 OPC_MTHC2 = (0x07 << 21) | OPC_CP2,
399 OPC_BC2 = (0x08 << 21) | OPC_CP2,
400};
401
402#define MASK_CP3(op) MASK_OP_MAJOR(op) | (op & 0x3F)
403
404enum {
405 OPC_LWXC1 = 0x00 | OPC_CP3,
406 OPC_LDXC1 = 0x01 | OPC_CP3,
407 OPC_LUXC1 = 0x05 | OPC_CP3,
408 OPC_SWXC1 = 0x08 | OPC_CP3,
409 OPC_SDXC1 = 0x09 | OPC_CP3,
410 OPC_SUXC1 = 0x0D | OPC_CP3,
411 OPC_PREFX = 0x0F | OPC_CP3,
412 OPC_ALNV_PS = 0x1E | OPC_CP3,
413 OPC_MADD_S = 0x20 | OPC_CP3,
414 OPC_MADD_D = 0x21 | OPC_CP3,
415 OPC_MADD_PS = 0x26 | OPC_CP3,
416 OPC_MSUB_S = 0x28 | OPC_CP3,
417 OPC_MSUB_D = 0x29 | OPC_CP3,
418 OPC_MSUB_PS = 0x2E | OPC_CP3,
419 OPC_NMADD_S = 0x30 | OPC_CP3,
fbcc6828 420 OPC_NMADD_D = 0x31 | OPC_CP3,
e0c84da7
TS
421 OPC_NMADD_PS= 0x36 | OPC_CP3,
422 OPC_NMSUB_S = 0x38 | OPC_CP3,
423 OPC_NMSUB_D = 0x39 | OPC_CP3,
424 OPC_NMSUB_PS= 0x3E | OPC_CP3,
425};
426
39454628 427/* global register indices */
a7812ae4
PB
428static TCGv_ptr cpu_env;
429static TCGv cpu_gpr[32], cpu_PC;
4b2eb8d2 430static TCGv cpu_HI[MIPS_DSP_ACC], cpu_LO[MIPS_DSP_ACC], cpu_ACX[MIPS_DSP_ACC];
41db4607
AJ
431static TCGv cpu_dspctrl, btarget, bcond;
432static TCGv_i32 hflags;
a7812ae4 433static TCGv_i32 fpu_fcr0, fpu_fcr31;
aa0bf00b 434
2e70f6ef
PB
435#include "gen-icount.h"
436
a7812ae4
PB
437#define gen_helper_0i(name, arg) do { \
438 TCGv_i32 helper_tmp = tcg_const_i32(arg); \
439 gen_helper_##name(helper_tmp); \
440 tcg_temp_free_i32(helper_tmp); \
441 } while(0)
be24bb4f 442
a7812ae4
PB
443#define gen_helper_1i(name, arg1, arg2) do { \
444 TCGv_i32 helper_tmp = tcg_const_i32(arg2); \
445 gen_helper_##name(arg1, helper_tmp); \
446 tcg_temp_free_i32(helper_tmp); \
447 } while(0)
be24bb4f 448
a7812ae4
PB
449#define gen_helper_2i(name, arg1, arg2, arg3) do { \
450 TCGv_i32 helper_tmp = tcg_const_i32(arg3); \
451 gen_helper_##name(arg1, arg2, helper_tmp); \
452 tcg_temp_free_i32(helper_tmp); \
453 } while(0)
be24bb4f 454
a7812ae4
PB
455#define gen_helper_3i(name, arg1, arg2, arg3, arg4) do { \
456 TCGv_i32 helper_tmp = tcg_const_i32(arg4); \
457 gen_helper_##name(arg1, arg2, arg3, helper_tmp); \
458 tcg_temp_free_i32(helper_tmp); \
459 } while(0)
c239529e 460
8e9ade68
TS
461typedef struct DisasContext {
462 struct TranslationBlock *tb;
463 target_ulong pc, saved_pc;
464 uint32_t opcode;
8e9ade68
TS
465 /* Routine used to access memory */
466 int mem_idx;
467 uint32_t hflags, saved_hflags;
468 int bstate;
469 target_ulong btarget;
470} DisasContext;
471
472enum {
473 BS_NONE = 0, /* We go out of the TB without reaching a branch or an
d077b6f7 474 * exception condition */
8e9ade68
TS
475 BS_STOP = 1, /* We want to stop translation for any reason */
476 BS_BRANCH = 2, /* We reached a branch condition */
477 BS_EXCP = 3, /* We reached an exception condition */
478};
479
480static const char *regnames[] =
6af0bf9c
FB
481 { "r0", "at", "v0", "v1", "a0", "a1", "a2", "a3",
482 "t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7",
483 "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7",
484 "t8", "t9", "k0", "k1", "gp", "sp", "s8", "ra", };
485
4b2eb8d2
TS
486static const char *regnames_HI[] =
487 { "HI0", "HI1", "HI2", "HI3", };
488
489static const char *regnames_LO[] =
490 { "LO0", "LO1", "LO2", "LO3", };
491
492static const char *regnames_ACX[] =
493 { "ACX0", "ACX1", "ACX2", "ACX3", };
494
8e9ade68
TS
495static const char *fregnames[] =
496 { "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7",
497 "f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15",
498 "f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23",
499 "f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31", };
958fb4a9 500
8e9ade68 501#ifdef MIPS_DEBUG_DISAS
93fcfe39
AL
502#define MIPS_DEBUG(fmt, args...) \
503 qemu_log_mask(CPU_LOG_TB_IN_ASM, \
504 TARGET_FMT_lx ": %08x " fmt "\n", \
505 ctx->pc, ctx->opcode , ##args)
506#define LOG_DISAS(...) qemu_log_mask(CPU_LOG_TB_IN_ASM, ## __VA_ARGS__)
8e9ade68
TS
507#else
508#define MIPS_DEBUG(fmt, args...) do { } while(0)
d12d51d5 509#define LOG_DISAS(...) do { } while (0)
8e9ade68 510#endif
958fb4a9 511
8e9ade68
TS
512#define MIPS_INVAL(op) \
513do { \
514 MIPS_DEBUG("Invalid %s %03x %03x %03x", op, ctx->opcode >> 26, \
515 ctx->opcode & 0x3F, ((ctx->opcode >> 16) & 0x1F)); \
516} while (0)
ead9360e 517
8e9ade68
TS
518/* General purpose registers moves. */
519static inline void gen_load_gpr (TCGv t, int reg)
aaa9128a 520{
8e9ade68
TS
521 if (reg == 0)
522 tcg_gen_movi_tl(t, 0);
523 else
4b2eb8d2 524 tcg_gen_mov_tl(t, cpu_gpr[reg]);
aaa9128a
TS
525}
526
8e9ade68 527static inline void gen_store_gpr (TCGv t, int reg)
aaa9128a 528{
8e9ade68 529 if (reg != 0)
4b2eb8d2 530 tcg_gen_mov_tl(cpu_gpr[reg], t);
aaa9128a
TS
531}
532
b10fa3c9 533/* Moves to/from ACX register. */
4b2eb8d2 534static inline void gen_load_ACX (TCGv t, int reg)
893f9865 535{
4b2eb8d2 536 tcg_gen_mov_tl(t, cpu_ACX[reg]);
893f9865
TS
537}
538
4b2eb8d2 539static inline void gen_store_ACX (TCGv t, int reg)
893f9865 540{
4b2eb8d2 541 tcg_gen_mov_tl(cpu_ACX[reg], t);
893f9865
TS
542}
543
8e9ade68 544/* Moves to/from shadow registers. */
be24bb4f 545static inline void gen_load_srsgpr (int from, int to)
aaa9128a 546{
a7812ae4 547 TCGv r_tmp1 = tcg_temp_new();
be24bb4f
TS
548
549 if (from == 0)
550 tcg_gen_movi_tl(r_tmp1, 0);
8e9ade68 551 else {
a7812ae4
PB
552 TCGv_i32 r_tmp2 = tcg_temp_new_i32();
553 TCGv_ptr addr = tcg_temp_new_ptr();
aaa9128a 554
be24bb4f
TS
555 tcg_gen_ld_i32(r_tmp2, cpu_env, offsetof(CPUState, CP0_SRSCtl));
556 tcg_gen_shri_i32(r_tmp2, r_tmp2, CP0SRSCtl_PSS);
557 tcg_gen_andi_i32(r_tmp2, r_tmp2, 0xf);
558 tcg_gen_muli_i32(r_tmp2, r_tmp2, sizeof(target_ulong) * 32);
a7812ae4
PB
559 tcg_gen_ext_i32_ptr(addr, r_tmp2);
560 tcg_gen_add_ptr(addr, cpu_env, addr);
aaa9128a 561
a7812ae4
PB
562 tcg_gen_ld_tl(r_tmp1, addr, sizeof(target_ulong) * from);
563 tcg_temp_free_ptr(addr);
564 tcg_temp_free_i32(r_tmp2);
8e9ade68 565 }
be24bb4f
TS
566 gen_store_gpr(r_tmp1, to);
567 tcg_temp_free(r_tmp1);
aaa9128a
TS
568}
569
be24bb4f 570static inline void gen_store_srsgpr (int from, int to)
aaa9128a 571{
be24bb4f 572 if (to != 0) {
a7812ae4
PB
573 TCGv r_tmp1 = tcg_temp_new();
574 TCGv_i32 r_tmp2 = tcg_temp_new_i32();
575 TCGv_ptr addr = tcg_temp_new_ptr();
be24bb4f
TS
576
577 gen_load_gpr(r_tmp1, from);
578 tcg_gen_ld_i32(r_tmp2, cpu_env, offsetof(CPUState, CP0_SRSCtl));
579 tcg_gen_shri_i32(r_tmp2, r_tmp2, CP0SRSCtl_PSS);
580 tcg_gen_andi_i32(r_tmp2, r_tmp2, 0xf);
581 tcg_gen_muli_i32(r_tmp2, r_tmp2, sizeof(target_ulong) * 32);
a7812ae4
PB
582 tcg_gen_ext_i32_ptr(addr, r_tmp2);
583 tcg_gen_add_ptr(addr, cpu_env, addr);
be24bb4f 584
a7812ae4
PB
585 tcg_gen_st_tl(r_tmp1, addr, sizeof(target_ulong) * to);
586 tcg_temp_free_ptr(addr);
587 tcg_temp_free_i32(r_tmp2);
be24bb4f 588 tcg_temp_free(r_tmp1);
8e9ade68 589 }
aaa9128a
TS
590}
591
aaa9128a 592/* Floating point register moves. */
a7812ae4 593static inline void gen_load_fpr32 (TCGv_i32 t, int reg)
aa0bf00b 594{
6d066274 595 tcg_gen_ld_i32(t, cpu_env, offsetof(CPUState, active_fpu.fpr[reg].w[FP_ENDIAN_IDX]));
6ea83fed
FB
596}
597
a7812ae4 598static inline void gen_store_fpr32 (TCGv_i32 t, int reg)
aa0bf00b 599{
6d066274
AJ
600 tcg_gen_st_i32(t, cpu_env, offsetof(CPUState, active_fpu.fpr[reg].w[FP_ENDIAN_IDX]));
601}
602
603static inline void gen_load_fpr32h (TCGv_i32 t, int reg)
604{
605 tcg_gen_ld_i32(t, cpu_env, offsetof(CPUState, active_fpu.fpr[reg].w[!FP_ENDIAN_IDX]));
606}
607
608static inline void gen_store_fpr32h (TCGv_i32 t, int reg)
609{
610 tcg_gen_st_i32(t, cpu_env, offsetof(CPUState, active_fpu.fpr[reg].w[!FP_ENDIAN_IDX]));
aa0bf00b 611}
6ea83fed 612
a7812ae4 613static inline void gen_load_fpr64 (DisasContext *ctx, TCGv_i64 t, int reg)
aa0bf00b 614{
f364515c 615 if (ctx->hflags & MIPS_HFLAG_F64) {
6d066274 616 tcg_gen_ld_i64(t, cpu_env, offsetof(CPUState, active_fpu.fpr[reg].d));
f364515c 617 } else {
6d066274
AJ
618 TCGv_i32 t0 = tcg_temp_new_i32();
619 TCGv_i32 t1 = tcg_temp_new_i32();
620 gen_load_fpr32(t0, reg & ~1);
621 gen_load_fpr32(t1, reg | 1);
622 tcg_gen_concat_i32_i64(t, t0, t1);
623 tcg_temp_free_i32(t0);
624 tcg_temp_free_i32(t1);
aa0bf00b
TS
625 }
626}
6ea83fed 627
a7812ae4 628static inline void gen_store_fpr64 (DisasContext *ctx, TCGv_i64 t, int reg)
aa0bf00b 629{
f364515c 630 if (ctx->hflags & MIPS_HFLAG_F64) {
6d066274 631 tcg_gen_st_i64(t, cpu_env, offsetof(CPUState, active_fpu.fpr[reg].d));
f364515c 632 } else {
6d066274
AJ
633 TCGv_i64 t0 = tcg_temp_new_i64();
634 TCGv_i32 t1 = tcg_temp_new_i32();
635 tcg_gen_trunc_i64_i32(t1, t);
636 gen_store_fpr32(t1, reg & ~1);
637 tcg_gen_shri_i64(t0, t, 32);
638 tcg_gen_trunc_i64_i32(t1, t0);
639 gen_store_fpr32(t1, reg | 1);
640 tcg_temp_free_i32(t1);
641 tcg_temp_free_i64(t0);
aa0bf00b
TS
642 }
643}
6ea83fed 644
d94536f4 645static inline int get_fp_bit (int cc)
a16336e4 646{
d94536f4
AJ
647 if (cc)
648 return 24 + cc;
649 else
650 return 23;
a16336e4
TS
651}
652
a7812ae4
PB
653#define FOP_CONDS(type, fmt, bits) \
654static inline void gen_cmp ## type ## _ ## fmt(int n, TCGv_i##bits a, \
655 TCGv_i##bits b, int cc) \
b6d96bed 656{ \
a7812ae4
PB
657 switch (n) { \
658 case 0: gen_helper_2i(cmp ## type ## _ ## fmt ## _f, a, b, cc); break;\
659 case 1: gen_helper_2i(cmp ## type ## _ ## fmt ## _un, a, b, cc); break;\
660 case 2: gen_helper_2i(cmp ## type ## _ ## fmt ## _eq, a, b, cc); break;\
661 case 3: gen_helper_2i(cmp ## type ## _ ## fmt ## _ueq, a, b, cc); break;\
662 case 4: gen_helper_2i(cmp ## type ## _ ## fmt ## _olt, a, b, cc); break;\
663 case 5: gen_helper_2i(cmp ## type ## _ ## fmt ## _ult, a, b, cc); break;\
664 case 6: gen_helper_2i(cmp ## type ## _ ## fmt ## _ole, a, b, cc); break;\
665 case 7: gen_helper_2i(cmp ## type ## _ ## fmt ## _ule, a, b, cc); break;\
666 case 8: gen_helper_2i(cmp ## type ## _ ## fmt ## _sf, a, b, cc); break;\
667 case 9: gen_helper_2i(cmp ## type ## _ ## fmt ## _ngle, a, b, cc); break;\
668 case 10: gen_helper_2i(cmp ## type ## _ ## fmt ## _seq, a, b, cc); break;\
669 case 11: gen_helper_2i(cmp ## type ## _ ## fmt ## _ngl, a, b, cc); break;\
670 case 12: gen_helper_2i(cmp ## type ## _ ## fmt ## _lt, a, b, cc); break;\
671 case 13: gen_helper_2i(cmp ## type ## _ ## fmt ## _nge, a, b, cc); break;\
672 case 14: gen_helper_2i(cmp ## type ## _ ## fmt ## _le, a, b, cc); break;\
673 case 15: gen_helper_2i(cmp ## type ## _ ## fmt ## _ngt, a, b, cc); break;\
674 default: abort(); \
675 } \
6ea83fed
FB
676}
677
a7812ae4
PB
678FOP_CONDS(, d, 64)
679FOP_CONDS(abs, d, 64)
680FOP_CONDS(, s, 32)
681FOP_CONDS(abs, s, 32)
682FOP_CONDS(, ps, 64)
683FOP_CONDS(abs, ps, 64)
5d0fc900 684#undef FOP_CONDS
6ea83fed 685
30898801 686/* Tests */
92e90443
AJ
687#define OP_COND(name, cond) \
688static inline void glue(gen_op_, name) (TCGv ret, TCGv t0, TCGv t1) \
689{ \
690 int l1 = gen_new_label(); \
691 int l2 = gen_new_label(); \
692 \
693 tcg_gen_brcond_tl(cond, t0, t1, l1); \
694 tcg_gen_movi_tl(ret, 0); \
695 tcg_gen_br(l2); \
696 gen_set_label(l1); \
697 tcg_gen_movi_tl(ret, 1); \
698 gen_set_label(l2); \
30898801
TS
699}
700OP_COND(eq, TCG_COND_EQ);
701OP_COND(ne, TCG_COND_NE);
702OP_COND(ge, TCG_COND_GE);
703OP_COND(geu, TCG_COND_GEU);
704OP_COND(lt, TCG_COND_LT);
705OP_COND(ltu, TCG_COND_LTU);
706#undef OP_COND
707
92e90443
AJ
708#define OP_CONDI(name, cond) \
709static inline void glue(gen_op_, name) (TCGv ret, TCGv t0, target_ulong val) \
710{ \
711 int l1 = gen_new_label(); \
712 int l2 = gen_new_label(); \
713 \
714 tcg_gen_brcondi_tl(cond, t0, val, l1); \
715 tcg_gen_movi_tl(ret, 0); \
716 tcg_gen_br(l2); \
717 gen_set_label(l1); \
718 tcg_gen_movi_tl(ret, 1); \
719 gen_set_label(l2); \
30898801
TS
720}
721OP_CONDI(lti, TCG_COND_LT);
722OP_CONDI(ltiu, TCG_COND_LTU);
723#undef OP_CONDI
724
725#define OP_CONDZ(name, cond) \
92e90443 726static inline void glue(gen_op_, name) (TCGv ret, TCGv t0) \
30898801
TS
727{ \
728 int l1 = gen_new_label(); \
729 int l2 = gen_new_label(); \
730 \
92e90443
AJ
731 tcg_gen_brcondi_tl(cond, t0, 0, l1); \
732 tcg_gen_movi_tl(ret, 0); \
30898801
TS
733 tcg_gen_br(l2); \
734 gen_set_label(l1); \
92e90443 735 tcg_gen_movi_tl(ret, 1); \
30898801
TS
736 gen_set_label(l2); \
737}
738OP_CONDZ(gez, TCG_COND_GE);
739OP_CONDZ(gtz, TCG_COND_GT);
740OP_CONDZ(lez, TCG_COND_LE);
741OP_CONDZ(ltz, TCG_COND_LT);
742#undef OP_CONDZ
743
8e9ade68
TS
744static inline void gen_save_pc(target_ulong pc)
745{
1eb75d4a 746 tcg_gen_movi_tl(cpu_PC, pc);
8e9ade68 747}
30898801 748
356265ae 749static inline void save_cpu_state (DisasContext *ctx, int do_save_pc)
6af0bf9c 750{
d12d51d5 751 LOG_DISAS("hflags %08x saved %08x\n", ctx->hflags, ctx->saved_hflags);
6af0bf9c 752 if (do_save_pc && ctx->pc != ctx->saved_pc) {
9b9e4393 753 gen_save_pc(ctx->pc);
6af0bf9c
FB
754 ctx->saved_pc = ctx->pc;
755 }
756 if (ctx->hflags != ctx->saved_hflags) {
41db4607 757 tcg_gen_movi_i32(hflags, ctx->hflags);
6af0bf9c 758 ctx->saved_hflags = ctx->hflags;
5a5012ec
TS
759 switch (ctx->hflags & MIPS_HFLAG_BMASK) {
760 case MIPS_HFLAG_BR:
5a5012ec
TS
761 break;
762 case MIPS_HFLAG_BC:
5a5012ec 763 case MIPS_HFLAG_BL:
5a5012ec 764 case MIPS_HFLAG_B:
d077b6f7 765 tcg_gen_movi_tl(btarget, ctx->btarget);
5a5012ec 766 break;
6af0bf9c
FB
767 }
768 }
769}
770
356265ae 771static inline void restore_cpu_state (CPUState *env, DisasContext *ctx)
5a5012ec 772{
fd4a04eb
TS
773 ctx->saved_hflags = ctx->hflags;
774 switch (ctx->hflags & MIPS_HFLAG_BMASK) {
775 case MIPS_HFLAG_BR:
fd4a04eb
TS
776 break;
777 case MIPS_HFLAG_BC:
778 case MIPS_HFLAG_BL:
39454628 779 case MIPS_HFLAG_B:
fd4a04eb 780 ctx->btarget = env->btarget;
fd4a04eb 781 break;
5a5012ec
TS
782 }
783}
784
356265ae 785static inline void
48d38ca5 786generate_exception_err (DisasContext *ctx, int excp, int err)
aaa9128a 787{
a7812ae4
PB
788 TCGv_i32 texcp = tcg_const_i32(excp);
789 TCGv_i32 terr = tcg_const_i32(err);
aaa9128a 790 save_cpu_state(ctx, 1);
a7812ae4
PB
791 gen_helper_raise_exception_err(texcp, terr);
792 tcg_temp_free_i32(terr);
793 tcg_temp_free_i32(texcp);
794 gen_helper_interrupt_restart();
aaa9128a
TS
795 tcg_gen_exit_tb(0);
796}
797
356265ae 798static inline void
48d38ca5 799generate_exception (DisasContext *ctx, int excp)
aaa9128a 800{
6af0bf9c 801 save_cpu_state(ctx, 1);
a7812ae4
PB
802 gen_helper_0i(raise_exception, excp);
803 gen_helper_interrupt_restart();
48d38ca5 804 tcg_gen_exit_tb(0);
6af0bf9c
FB
805}
806
48d38ca5 807/* Addresses computation */
d144d1d9 808static inline void gen_op_addr_add (DisasContext *ctx, TCGv t0, TCGv t1)
4ad40f36 809{
be24bb4f 810 tcg_gen_add_tl(t0, t0, t1);
48d38ca5
TS
811
812#if defined(TARGET_MIPS64)
813 /* For compatibility with 32-bit code, data reference in user mode
814 with Status_UX = 0 should be casted to 32-bit and sign extended.
815 See the MIPS64 PRA manual, section 4.10. */
2623c1ec
AJ
816 if (((ctx->hflags & MIPS_HFLAG_KSU) == MIPS_HFLAG_UM) &&
817 !(ctx->hflags & MIPS_HFLAG_UX)) {
be24bb4f 818 tcg_gen_ext32s_i64(t0, t0);
48d38ca5
TS
819 }
820#endif
4ad40f36
FB
821}
822
356265ae 823static inline void check_cp0_enabled(DisasContext *ctx)
387a8fe5 824{
fe253235 825 if (unlikely(!(ctx->hflags & MIPS_HFLAG_CP0)))
387a8fe5
TS
826 generate_exception_err(ctx, EXCP_CpU, 1);
827}
828
356265ae 829static inline void check_cp1_enabled(DisasContext *ctx)
5e755519 830{
fe253235 831 if (unlikely(!(ctx->hflags & MIPS_HFLAG_FPU)))
5e755519
TS
832 generate_exception_err(ctx, EXCP_CpU, 1);
833}
834
b8aa4598
TS
835/* Verify that the processor is running with COP1X instructions enabled.
836 This is associated with the nabla symbol in the MIPS32 and MIPS64
837 opcode tables. */
838
356265ae 839static inline void check_cop1x(DisasContext *ctx)
b8aa4598
TS
840{
841 if (unlikely(!(ctx->hflags & MIPS_HFLAG_COP1X)))
842 generate_exception(ctx, EXCP_RI);
843}
844
845/* Verify that the processor is running with 64-bit floating-point
846 operations enabled. */
847
356265ae 848static inline void check_cp1_64bitmode(DisasContext *ctx)
5e755519 849{
b8aa4598 850 if (unlikely(~ctx->hflags & (MIPS_HFLAG_F64 | MIPS_HFLAG_COP1X)))
5e755519
TS
851 generate_exception(ctx, EXCP_RI);
852}
853
854/*
855 * Verify if floating point register is valid; an operation is not defined
856 * if bit 0 of any register specification is set and the FR bit in the
857 * Status register equals zero, since the register numbers specify an
858 * even-odd pair of adjacent coprocessor general registers. When the FR bit
859 * in the Status register equals one, both even and odd register numbers
860 * are valid. This limitation exists only for 64 bit wide (d,l,ps) registers.
861 *
862 * Multiple 64 bit wide registers can be checked by calling
863 * gen_op_cp1_registers(freg1 | freg2 | ... | fregN);
864 */
356265ae 865static inline void check_cp1_registers(DisasContext *ctx, int regs)
5e755519 866{
fe253235 867 if (unlikely(!(ctx->hflags & MIPS_HFLAG_F64) && (regs & 1)))
5e755519
TS
868 generate_exception(ctx, EXCP_RI);
869}
870
3a95e3a7 871/* This code generates a "reserved instruction" exception if the
e189e748 872 CPU does not support the instruction set corresponding to flags. */
356265ae 873static inline void check_insn(CPUState *env, DisasContext *ctx, int flags)
3a95e3a7 874{
e189e748 875 if (unlikely(!(env->insn_flags & flags)))
3a95e3a7
TS
876 generate_exception(ctx, EXCP_RI);
877}
878
e189e748
TS
879/* This code generates a "reserved instruction" exception if 64-bit
880 instructions are not enabled. */
356265ae 881static inline void check_mips_64(DisasContext *ctx)
e189e748 882{
fe253235 883 if (unlikely(!(ctx->hflags & MIPS_HFLAG_64)))
e189e748
TS
884 generate_exception(ctx, EXCP_RI);
885}
886
958fb4a9 887/* load/store instructions. */
aaa9128a 888#define OP_LD(insn,fname) \
356265ae 889static inline void op_ldst_##insn(TCGv t0, DisasContext *ctx) \
aaa9128a 890{ \
be24bb4f 891 tcg_gen_qemu_##fname(t0, t0, 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
904#define OP_ST(insn,fname) \
356265ae 905static inline void op_ldst_##insn(TCGv t0, TCGv t1, DisasContext *ctx) \
aaa9128a 906{ \
be24bb4f 907 tcg_gen_qemu_##fname(t1, t0, 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
917#define OP_LD_ATOMIC(insn,fname) \
356265ae 918static inline void op_ldst_##insn(TCGv t0, TCGv t1, DisasContext *ctx) \
aaa9128a 919{ \
be24bb4f
TS
920 tcg_gen_mov_tl(t1, t0); \
921 tcg_gen_qemu_##fname(t0, t0, ctx->mem_idx); \
922 tcg_gen_st_tl(t1, cpu_env, offsetof(CPUState, CP0_LLAddr)); \
aaa9128a
TS
923}
924OP_LD_ATOMIC(ll,ld32s);
925#if defined(TARGET_MIPS64)
926OP_LD_ATOMIC(lld,ld64);
927#endif
928#undef OP_LD_ATOMIC
929
930#define OP_ST_ATOMIC(insn,fname,almask) \
356265ae 931static inline void op_ldst_##insn(TCGv t0, TCGv t1, DisasContext *ctx) \
aaa9128a 932{ \
a7812ae4 933 TCGv r_tmp = tcg_temp_local_new(); \
aaa9128a
TS
934 int l1 = gen_new_label(); \
935 int l2 = gen_new_label(); \
936 int l3 = gen_new_label(); \
937 \
be24bb4f 938 tcg_gen_andi_tl(r_tmp, t0, almask); \
cb63669a 939 tcg_gen_brcondi_tl(TCG_COND_EQ, r_tmp, 0, l1); \
be24bb4f 940 tcg_gen_st_tl(t0, cpu_env, offsetof(CPUState, CP0_BadVAddr)); \
f0b3f3ae 941 generate_exception(ctx, EXCP_AdES); \
aaa9128a
TS
942 gen_set_label(l1); \
943 tcg_gen_ld_tl(r_tmp, cpu_env, offsetof(CPUState, CP0_LLAddr)); \
be24bb4f 944 tcg_gen_brcond_tl(TCG_COND_NE, t0, r_tmp, l2); \
be24bb4f
TS
945 tcg_gen_qemu_##fname(t1, t0, ctx->mem_idx); \
946 tcg_gen_movi_tl(t0, 1); \
aaa9128a
TS
947 tcg_gen_br(l3); \
948 gen_set_label(l2); \
be24bb4f 949 tcg_gen_movi_tl(t0, 0); \
aaa9128a 950 gen_set_label(l3); \
c24135ff 951 tcg_temp_free(r_tmp); \
aaa9128a
TS
952}
953OP_ST_ATOMIC(sc,st32,0x3);
954#if defined(TARGET_MIPS64)
955OP_ST_ATOMIC(scd,st64,0x7);
956#endif
957#undef OP_ST_ATOMIC
958
6af0bf9c 959/* Load and store */
7a387fff 960static void gen_ldst (DisasContext *ctx, uint32_t opc, int rt,
6af0bf9c
FB
961 int base, int16_t offset)
962{
923617a3 963 const char *opn = "ldst";
a7812ae4
PB
964 TCGv t0 = tcg_temp_local_new();
965 TCGv t1 = tcg_temp_local_new();
6af0bf9c
FB
966
967 if (base == 0) {
78723684 968 tcg_gen_movi_tl(t0, offset);
6af0bf9c 969 } else if (offset == 0) {
78723684 970 gen_load_gpr(t0, base);
6af0bf9c 971 } else {
e9203484
AJ
972 tcg_gen_movi_tl(t0, offset);
973 gen_op_addr_add(ctx, t0, cpu_gpr[base]);
6af0bf9c
FB
974 }
975 /* Don't do NOP if destination is zero: we must perform the actual
ead9360e 976 memory access. */
6af0bf9c 977 switch (opc) {
d26bc211 978#if defined(TARGET_MIPS64)
6e473128 979 case OPC_LWU:
78723684
TS
980 op_ldst_lwu(t0, ctx);
981 gen_store_gpr(t0, rt);
6e473128
TS
982 opn = "lwu";
983 break;
6af0bf9c 984 case OPC_LD:
78723684
TS
985 op_ldst_ld(t0, ctx);
986 gen_store_gpr(t0, rt);
6af0bf9c
FB
987 opn = "ld";
988 break;
7a387fff 989 case OPC_LLD:
78723684
TS
990 op_ldst_lld(t0, t1, ctx);
991 gen_store_gpr(t0, rt);
7a387fff
TS
992 opn = "lld";
993 break;
6af0bf9c 994 case OPC_SD:
78723684
TS
995 gen_load_gpr(t1, rt);
996 op_ldst_sd(t0, t1, ctx);
6af0bf9c
FB
997 opn = "sd";
998 break;
7a387fff 999 case OPC_SCD:
62c5609a 1000 save_cpu_state(ctx, 1);
78723684
TS
1001 gen_load_gpr(t1, rt);
1002 op_ldst_scd(t0, t1, ctx);
1003 gen_store_gpr(t0, rt);
7a387fff
TS
1004 opn = "scd";
1005 break;
6af0bf9c 1006 case OPC_LDL:
c8c2227e 1007 save_cpu_state(ctx, 1);
78723684 1008 gen_load_gpr(t1, rt);
a7812ae4 1009 gen_helper_3i(ldl, t1, t0, t1, ctx->mem_idx);
78723684 1010 gen_store_gpr(t1, rt);
6af0bf9c
FB
1011 opn = "ldl";
1012 break;
1013 case OPC_SDL:
c8c2227e 1014 save_cpu_state(ctx, 1);
78723684 1015 gen_load_gpr(t1, rt);
a7812ae4 1016 gen_helper_2i(sdl, t0, t1, ctx->mem_idx);
6af0bf9c
FB
1017 opn = "sdl";
1018 break;
1019 case OPC_LDR:
c8c2227e 1020 save_cpu_state(ctx, 1);
78723684 1021 gen_load_gpr(t1, rt);
a7812ae4 1022 gen_helper_3i(ldr, t1, t0, t1, ctx->mem_idx);
78723684 1023 gen_store_gpr(t1, rt);
6af0bf9c
FB
1024 opn = "ldr";
1025 break;
1026 case OPC_SDR:
c8c2227e 1027 save_cpu_state(ctx, 1);
78723684 1028 gen_load_gpr(t1, rt);
a7812ae4 1029 gen_helper_2i(sdr, t0, t1, ctx->mem_idx);
6af0bf9c
FB
1030 opn = "sdr";
1031 break;
1032#endif
1033 case OPC_LW:
78723684
TS
1034 op_ldst_lw(t0, ctx);
1035 gen_store_gpr(t0, rt);
6af0bf9c
FB
1036 opn = "lw";
1037 break;
1038 case OPC_SW:
78723684
TS
1039 gen_load_gpr(t1, rt);
1040 op_ldst_sw(t0, t1, ctx);
6af0bf9c
FB
1041 opn = "sw";
1042 break;
1043 case OPC_LH:
78723684
TS
1044 op_ldst_lh(t0, ctx);
1045 gen_store_gpr(t0, rt);
6af0bf9c
FB
1046 opn = "lh";
1047 break;
1048 case OPC_SH:
78723684
TS
1049 gen_load_gpr(t1, rt);
1050 op_ldst_sh(t0, t1, ctx);
6af0bf9c
FB
1051 opn = "sh";
1052 break;
1053 case OPC_LHU:
78723684
TS
1054 op_ldst_lhu(t0, ctx);
1055 gen_store_gpr(t0, rt);
6af0bf9c
FB
1056 opn = "lhu";
1057 break;
1058 case OPC_LB:
78723684
TS
1059 op_ldst_lb(t0, ctx);
1060 gen_store_gpr(t0, rt);
6af0bf9c
FB
1061 opn = "lb";
1062 break;
1063 case OPC_SB:
78723684
TS
1064 gen_load_gpr(t1, rt);
1065 op_ldst_sb(t0, t1, ctx);
6af0bf9c
FB
1066 opn = "sb";
1067 break;
1068 case OPC_LBU:
78723684
TS
1069 op_ldst_lbu(t0, ctx);
1070 gen_store_gpr(t0, rt);
6af0bf9c
FB
1071 opn = "lbu";
1072 break;
1073 case OPC_LWL:
c8c2227e 1074 save_cpu_state(ctx, 1);
6958549d 1075 gen_load_gpr(t1, rt);
a7812ae4 1076 gen_helper_3i(lwl, t1, t0, t1, ctx->mem_idx);
78723684 1077 gen_store_gpr(t1, rt);
6af0bf9c
FB
1078 opn = "lwl";
1079 break;
1080 case OPC_SWL:
c8c2227e 1081 save_cpu_state(ctx, 1);
78723684 1082 gen_load_gpr(t1, rt);
a7812ae4 1083 gen_helper_2i(swl, t0, t1, ctx->mem_idx);
6af0bf9c
FB
1084 opn = "swr";
1085 break;
1086 case OPC_LWR:
c8c2227e 1087 save_cpu_state(ctx, 1);
6958549d 1088 gen_load_gpr(t1, rt);
a7812ae4 1089 gen_helper_3i(lwr, t1, t0, t1, ctx->mem_idx);
78723684 1090 gen_store_gpr(t1, rt);
6af0bf9c
FB
1091 opn = "lwr";
1092 break;
1093 case OPC_SWR:
c8c2227e 1094 save_cpu_state(ctx, 1);
78723684 1095 gen_load_gpr(t1, rt);
a7812ae4 1096 gen_helper_2i(swr, t0, t1, ctx->mem_idx);
6af0bf9c
FB
1097 opn = "swr";
1098 break;
1099 case OPC_LL:
78723684
TS
1100 op_ldst_ll(t0, t1, ctx);
1101 gen_store_gpr(t0, rt);
6af0bf9c
FB
1102 opn = "ll";
1103 break;
1104 case OPC_SC:
62c5609a 1105 save_cpu_state(ctx, 1);
78723684
TS
1106 gen_load_gpr(t1, rt);
1107 op_ldst_sc(t0, t1, ctx);
1108 gen_store_gpr(t0, rt);
6af0bf9c
FB
1109 opn = "sc";
1110 break;
1111 default:
923617a3 1112 MIPS_INVAL(opn);
6af0bf9c 1113 generate_exception(ctx, EXCP_RI);
78723684 1114 goto out;
6af0bf9c
FB
1115 }
1116 MIPS_DEBUG("%s %s, %d(%s)", opn, regnames[rt], offset, regnames[base]);
78723684
TS
1117 out:
1118 tcg_temp_free(t0);
1119 tcg_temp_free(t1);
6af0bf9c
FB
1120}
1121
6ea83fed 1122/* Load and store */
7a387fff 1123static void gen_flt_ldst (DisasContext *ctx, uint32_t opc, int ft,
356265ae 1124 int base, int16_t offset)
6ea83fed 1125{
923617a3 1126 const char *opn = "flt_ldst";
a7812ae4 1127 TCGv t0 = tcg_temp_local_new();
6ea83fed
FB
1128
1129 if (base == 0) {
78723684 1130 tcg_gen_movi_tl(t0, offset);
6ea83fed 1131 } else if (offset == 0) {
78723684 1132 gen_load_gpr(t0, base);
6ea83fed 1133 } else {
e9203484
AJ
1134 tcg_gen_movi_tl(t0, offset);
1135 gen_op_addr_add(ctx, t0, cpu_gpr[base]);
6ea83fed
FB
1136 }
1137 /* Don't do NOP if destination is zero: we must perform the actual
ead9360e 1138 memory access. */
6ea83fed
FB
1139 switch (opc) {
1140 case OPC_LWC1:
b6d96bed 1141 {
a7812ae4
PB
1142 TCGv_i32 fp0 = tcg_temp_new_i32();
1143 TCGv t1 = tcg_temp_new();
b6d96bed 1144
a7812ae4
PB
1145 tcg_gen_qemu_ld32s(t1, t0, ctx->mem_idx);
1146 tcg_gen_trunc_tl_i32(fp0, t1);
b6d96bed 1147 gen_store_fpr32(fp0, ft);
a7812ae4
PB
1148 tcg_temp_free(t1);
1149 tcg_temp_free_i32(fp0);
b6d96bed 1150 }
6ea83fed
FB
1151 opn = "lwc1";
1152 break;
1153 case OPC_SWC1:
b6d96bed 1154 {
a7812ae4
PB
1155 TCGv_i32 fp0 = tcg_temp_new_i32();
1156 TCGv t1 = tcg_temp_new();
b6d96bed
TS
1157
1158 gen_load_fpr32(fp0, ft);
a7812ae4
PB
1159 tcg_gen_extu_i32_tl(t1, fp0);
1160 tcg_gen_qemu_st32(t1, t0, ctx->mem_idx);
1161 tcg_temp_free(t1);
1162 tcg_temp_free_i32(fp0);
b6d96bed 1163 }
6ea83fed
FB
1164 opn = "swc1";
1165 break;
1166 case OPC_LDC1:
b6d96bed 1167 {
a7812ae4 1168 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
1169
1170 tcg_gen_qemu_ld64(fp0, t0, ctx->mem_idx);
1171 gen_store_fpr64(ctx, fp0, ft);
a7812ae4 1172 tcg_temp_free_i64(fp0);
b6d96bed 1173 }
6ea83fed
FB
1174 opn = "ldc1";
1175 break;
1176 case OPC_SDC1:
b6d96bed 1177 {
a7812ae4 1178 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
1179
1180 gen_load_fpr64(ctx, fp0, ft);
1181 tcg_gen_qemu_st64(fp0, t0, ctx->mem_idx);
a7812ae4 1182 tcg_temp_free_i64(fp0);
b6d96bed 1183 }
6ea83fed
FB
1184 opn = "sdc1";
1185 break;
1186 default:
923617a3 1187 MIPS_INVAL(opn);
e397ee33 1188 generate_exception(ctx, EXCP_RI);
78723684 1189 goto out;
6ea83fed
FB
1190 }
1191 MIPS_DEBUG("%s %s, %d(%s)", opn, fregnames[ft], offset, regnames[base]);
78723684
TS
1192 out:
1193 tcg_temp_free(t0);
6ea83fed 1194}
6ea83fed 1195
6af0bf9c 1196/* Arithmetic with immediate operand */
e189e748
TS
1197static void gen_arith_imm (CPUState *env, DisasContext *ctx, uint32_t opc,
1198 int rt, int rs, int16_t imm)
6af0bf9c 1199{
f469b9db 1200 target_ulong uimm;
923617a3 1201 const char *opn = "imm arith";
a7812ae4 1202 TCGv t0 = tcg_temp_local_new();
6af0bf9c 1203
7a387fff 1204 if (rt == 0 && opc != OPC_ADDI && opc != OPC_DADDI) {
ead9360e
TS
1205 /* If no destination, treat it as a NOP.
1206 For addi, we must generate the overflow exception when needed. */
6af0bf9c 1207 MIPS_DEBUG("NOP");
78723684 1208 goto out;
6af0bf9c 1209 }
5a63bcb2
TS
1210 uimm = (uint16_t)imm;
1211 switch (opc) {
1212 case OPC_ADDI:
1213 case OPC_ADDIU:
d26bc211 1214#if defined(TARGET_MIPS64)
5a63bcb2
TS
1215 case OPC_DADDI:
1216 case OPC_DADDIU:
1217#endif
1218 case OPC_SLTI:
1219 case OPC_SLTIU:
f469b9db 1220 uimm = (target_long)imm; /* Sign extend to 32/64 bits */
5a63bcb2
TS
1221 /* Fall through. */
1222 case OPC_ANDI:
1223 case OPC_ORI:
1224 case OPC_XORI:
78723684 1225 gen_load_gpr(t0, rs);
5a63bcb2
TS
1226 break;
1227 case OPC_LUI:
78723684 1228 tcg_gen_movi_tl(t0, imm << 16);
5a63bcb2
TS
1229 break;
1230 case OPC_SLL:
1231 case OPC_SRA:
1232 case OPC_SRL:
d26bc211 1233#if defined(TARGET_MIPS64)
5a63bcb2
TS
1234 case OPC_DSLL:
1235 case OPC_DSRA:
1236 case OPC_DSRL:
1237 case OPC_DSLL32:
1238 case OPC_DSRA32:
1239 case OPC_DSRL32:
1240#endif
1241 uimm &= 0x1f;
78723684 1242 gen_load_gpr(t0, rs);
5a63bcb2 1243 break;
6af0bf9c
FB
1244 }
1245 switch (opc) {
1246 case OPC_ADDI:
48d38ca5 1247 {
a7812ae4
PB
1248 TCGv r_tmp1 = tcg_temp_new();
1249 TCGv r_tmp2 = tcg_temp_new();
48d38ca5
TS
1250 int l1 = gen_new_label();
1251
1252 save_cpu_state(ctx, 1);
78723684
TS
1253 tcg_gen_ext32s_tl(r_tmp1, t0);
1254 tcg_gen_addi_tl(t0, r_tmp1, uimm);
48d38ca5 1255
507563e8 1256 tcg_gen_xori_tl(r_tmp1, r_tmp1, ~uimm);
78723684 1257 tcg_gen_xori_tl(r_tmp2, t0, uimm);
48d38ca5 1258 tcg_gen_and_tl(r_tmp1, r_tmp1, r_tmp2);
4f57689a 1259 tcg_temp_free(r_tmp2);
507563e8 1260 tcg_gen_brcondi_tl(TCG_COND_GE, r_tmp1, 0, l1);
48d38ca5
TS
1261 /* operands of same sign, result different sign */
1262 generate_exception(ctx, EXCP_OVERFLOW);
1263 gen_set_label(l1);
507563e8 1264 tcg_temp_free(r_tmp1);
48d38ca5 1265
78723684 1266 tcg_gen_ext32s_tl(t0, t0);
48d38ca5 1267 }
6af0bf9c
FB
1268 opn = "addi";
1269 break;
1270 case OPC_ADDIU:
78723684
TS
1271 tcg_gen_addi_tl(t0, t0, uimm);
1272 tcg_gen_ext32s_tl(t0, t0);
6af0bf9c
FB
1273 opn = "addiu";
1274 break;
d26bc211 1275#if defined(TARGET_MIPS64)
7a387fff 1276 case OPC_DADDI:
48d38ca5 1277 {
a7812ae4
PB
1278 TCGv r_tmp1 = tcg_temp_new();
1279 TCGv r_tmp2 = tcg_temp_new();
48d38ca5
TS
1280 int l1 = gen_new_label();
1281
1282 save_cpu_state(ctx, 1);
78723684
TS
1283 tcg_gen_mov_tl(r_tmp1, t0);
1284 tcg_gen_addi_tl(t0, t0, uimm);
48d38ca5 1285
507563e8 1286 tcg_gen_xori_tl(r_tmp1, r_tmp1, ~uimm);
78723684 1287 tcg_gen_xori_tl(r_tmp2, t0, uimm);
48d38ca5 1288 tcg_gen_and_tl(r_tmp1, r_tmp1, r_tmp2);
4f57689a 1289 tcg_temp_free(r_tmp2);
507563e8 1290 tcg_gen_brcondi_tl(TCG_COND_GE, r_tmp1, 0, l1);
48d38ca5
TS
1291 /* operands of same sign, result different sign */
1292 generate_exception(ctx, EXCP_OVERFLOW);
1293 gen_set_label(l1);
507563e8 1294 tcg_temp_free(r_tmp1);
48d38ca5 1295 }
7a387fff
TS
1296 opn = "daddi";
1297 break;
1298 case OPC_DADDIU:
78723684 1299 tcg_gen_addi_tl(t0, t0, uimm);
7a387fff
TS
1300 opn = "daddiu";
1301 break;
1302#endif
6af0bf9c 1303 case OPC_SLTI:
92e90443 1304 gen_op_lti(t0, t0, uimm);
6af0bf9c
FB
1305 opn = "slti";
1306 break;
1307 case OPC_SLTIU:
92e90443 1308 gen_op_ltiu(t0, t0, uimm);
6af0bf9c
FB
1309 opn = "sltiu";
1310 break;
1311 case OPC_ANDI:
78723684 1312 tcg_gen_andi_tl(t0, t0, uimm);
6af0bf9c
FB
1313 opn = "andi";
1314 break;
1315 case OPC_ORI:
78723684 1316 tcg_gen_ori_tl(t0, t0, uimm);
6af0bf9c
FB
1317 opn = "ori";
1318 break;
1319 case OPC_XORI:
78723684 1320 tcg_gen_xori_tl(t0, t0, uimm);
6af0bf9c
FB
1321 opn = "xori";
1322 break;
1323 case OPC_LUI:
1324 opn = "lui";
1325 break;
1326 case OPC_SLL:
78723684
TS
1327 tcg_gen_shli_tl(t0, t0, uimm);
1328 tcg_gen_ext32s_tl(t0, t0);
6af0bf9c
FB
1329 opn = "sll";
1330 break;
1331 case OPC_SRA:
78723684
TS
1332 tcg_gen_ext32s_tl(t0, t0);
1333 tcg_gen_sari_tl(t0, t0, uimm);
6af0bf9c
FB
1334 opn = "sra";
1335 break;
1336 case OPC_SRL:
5a63bcb2
TS
1337 switch ((ctx->opcode >> 21) & 0x1f) {
1338 case 0:
507563e8
AJ
1339 if (uimm != 0) {
1340 tcg_gen_ext32u_tl(t0, t0);
1341 tcg_gen_shri_tl(t0, t0, uimm);
1342 } else {
1343 tcg_gen_ext32s_tl(t0, t0);
1344 }
7a387fff 1345 opn = "srl";
5a63bcb2
TS
1346 break;
1347 case 1:
e189e748
TS
1348 /* rotr is decoded as srl on non-R2 CPUs */
1349 if (env->insn_flags & ISA_MIPS32R2) {
48d38ca5 1350 if (uimm != 0) {
a7812ae4 1351 TCGv_i32 r_tmp1 = tcg_temp_new_i32();
48d38ca5 1352
78723684 1353 tcg_gen_trunc_tl_i32(r_tmp1, t0);
e00fcff7 1354 tcg_gen_rotri_i32(r_tmp1, r_tmp1, uimm);
78723684 1355 tcg_gen_ext_i32_tl(t0, r_tmp1);
a7812ae4 1356 tcg_temp_free_i32(r_tmp1);
48d38ca5 1357 }
e189e748
TS
1358 opn = "rotr";
1359 } else {
507563e8
AJ
1360 if (uimm != 0) {
1361 tcg_gen_ext32u_tl(t0, t0);
1362 tcg_gen_shri_tl(t0, t0, uimm);
1363 } else {
1364 tcg_gen_ext32s_tl(t0, t0);
1365 }
e189e748
TS
1366 opn = "srl";
1367 }
5a63bcb2
TS
1368 break;
1369 default:
1370 MIPS_INVAL("invalid srl flag");
1371 generate_exception(ctx, EXCP_RI);
1372 break;
1373 }
7a387fff 1374 break;
d26bc211 1375#if defined(TARGET_MIPS64)
7a387fff 1376 case OPC_DSLL:
78723684 1377 tcg_gen_shli_tl(t0, t0, uimm);
7a387fff
TS
1378 opn = "dsll";
1379 break;
1380 case OPC_DSRA:
78723684 1381 tcg_gen_sari_tl(t0, t0, uimm);
7a387fff
TS
1382 opn = "dsra";
1383 break;
1384 case OPC_DSRL:
5a63bcb2
TS
1385 switch ((ctx->opcode >> 21) & 0x1f) {
1386 case 0:
78723684 1387 tcg_gen_shri_tl(t0, t0, uimm);
7a387fff 1388 opn = "dsrl";
5a63bcb2
TS
1389 break;
1390 case 1:
e189e748
TS
1391 /* drotr is decoded as dsrl on non-R2 CPUs */
1392 if (env->insn_flags & ISA_MIPS32R2) {
48d38ca5 1393 if (uimm != 0) {
e00fcff7 1394 tcg_gen_rotri_tl(t0, t0, uimm);
48d38ca5 1395 }
e189e748
TS
1396 opn = "drotr";
1397 } else {
78723684 1398 tcg_gen_shri_tl(t0, t0, uimm);
e189e748
TS
1399 opn = "dsrl";
1400 }
5a63bcb2
TS
1401 break;
1402 default:
1403 MIPS_INVAL("invalid dsrl flag");
1404 generate_exception(ctx, EXCP_RI);
1405 break;
1406 }
7a387fff
TS
1407 break;
1408 case OPC_DSLL32:
78723684 1409 tcg_gen_shli_tl(t0, t0, uimm + 32);
7a387fff
TS
1410 opn = "dsll32";
1411 break;
1412 case OPC_DSRA32:
78723684 1413 tcg_gen_sari_tl(t0, t0, uimm + 32);
7a387fff
TS
1414 opn = "dsra32";
1415 break;
1416 case OPC_DSRL32:
5a63bcb2
TS
1417 switch ((ctx->opcode >> 21) & 0x1f) {
1418 case 0:
78723684 1419 tcg_gen_shri_tl(t0, t0, uimm + 32);
7a387fff 1420 opn = "dsrl32";
5a63bcb2
TS
1421 break;
1422 case 1:
e189e748
TS
1423 /* drotr32 is decoded as dsrl32 on non-R2 CPUs */
1424 if (env->insn_flags & ISA_MIPS32R2) {
e00fcff7 1425 tcg_gen_rotri_tl(t0, t0, uimm + 32);
e189e748
TS
1426 opn = "drotr32";
1427 } else {
78723684 1428 tcg_gen_shri_tl(t0, t0, uimm + 32);
e189e748
TS
1429 opn = "dsrl32";
1430 }
5a63bcb2
TS
1431 break;
1432 default:
1433 MIPS_INVAL("invalid dsrl32 flag");
1434 generate_exception(ctx, EXCP_RI);
1435 break;
1436 }
6af0bf9c 1437 break;
7a387fff 1438#endif
6af0bf9c 1439 default:
923617a3 1440 MIPS_INVAL(opn);
6af0bf9c 1441 generate_exception(ctx, EXCP_RI);
78723684 1442 goto out;
6af0bf9c 1443 }
78723684 1444 gen_store_gpr(t0, rt);
93b12ccc 1445 MIPS_DEBUG("%s %s, %s, " TARGET_FMT_lx, opn, regnames[rt], regnames[rs], uimm);
78723684
TS
1446 out:
1447 tcg_temp_free(t0);
6af0bf9c
FB
1448}
1449
1450/* Arithmetic */
e189e748 1451static void gen_arith (CPUState *env, DisasContext *ctx, uint32_t opc,
6af0bf9c
FB
1452 int rd, int rs, int rt)
1453{
923617a3 1454 const char *opn = "arith";
a7812ae4
PB
1455 TCGv t0 = tcg_temp_local_new();
1456 TCGv t1 = tcg_temp_local_new();
6af0bf9c 1457
7a387fff
TS
1458 if (rd == 0 && opc != OPC_ADD && opc != OPC_SUB
1459 && opc != OPC_DADD && opc != OPC_DSUB) {
ead9360e
TS
1460 /* If no destination, treat it as a NOP.
1461 For add & sub, we must generate the overflow exception when needed. */
6af0bf9c 1462 MIPS_DEBUG("NOP");
78723684 1463 goto out;
6af0bf9c 1464 }
78723684 1465 gen_load_gpr(t0, rs);
185f0762
TS
1466 /* Specialcase the conventional move operation. */
1467 if (rt == 0 && (opc == OPC_ADDU || opc == OPC_DADDU
1468 || opc == OPC_SUBU || opc == OPC_DSUBU)) {
78723684
TS
1469 gen_store_gpr(t0, rd);
1470 goto out;
185f0762 1471 }
78723684 1472 gen_load_gpr(t1, rt);
6af0bf9c
FB
1473 switch (opc) {
1474 case OPC_ADD:
48d38ca5 1475 {
a7812ae4
PB
1476 TCGv r_tmp1 = tcg_temp_new();
1477 TCGv r_tmp2 = tcg_temp_new();
48d38ca5
TS
1478 int l1 = gen_new_label();
1479
1480 save_cpu_state(ctx, 1);
78723684
TS
1481 tcg_gen_ext32s_tl(r_tmp1, t0);
1482 tcg_gen_ext32s_tl(r_tmp2, t1);
1483 tcg_gen_add_tl(t0, r_tmp1, r_tmp2);
48d38ca5 1484
78723684 1485 tcg_gen_xor_tl(r_tmp1, r_tmp1, t1);
48d38ca5 1486 tcg_gen_xori_tl(r_tmp1, r_tmp1, -1);
78723684 1487 tcg_gen_xor_tl(r_tmp2, t0, t1);
48d38ca5 1488 tcg_gen_and_tl(r_tmp1, r_tmp1, r_tmp2);
4f57689a 1489 tcg_temp_free(r_tmp2);
507563e8 1490 tcg_gen_brcondi_tl(TCG_COND_GE, r_tmp1, 0, l1);
48d38ca5
TS
1491 /* operands of same sign, result different sign */
1492 generate_exception(ctx, EXCP_OVERFLOW);
1493 gen_set_label(l1);
507563e8 1494 tcg_temp_free(r_tmp1);
48d38ca5 1495
78723684 1496 tcg_gen_ext32s_tl(t0, t0);
48d38ca5 1497 }
6af0bf9c
FB
1498 opn = "add";
1499 break;
1500 case OPC_ADDU:
78723684
TS
1501 tcg_gen_add_tl(t0, t0, t1);
1502 tcg_gen_ext32s_tl(t0, t0);
6af0bf9c
FB
1503 opn = "addu";
1504 break;
1505 case OPC_SUB:
48d38ca5 1506 {
a7812ae4
PB
1507 TCGv r_tmp1 = tcg_temp_new();
1508 TCGv r_tmp2 = tcg_temp_new();
48d38ca5
TS
1509 int l1 = gen_new_label();
1510
1511 save_cpu_state(ctx, 1);
78723684
TS
1512 tcg_gen_ext32s_tl(r_tmp1, t0);
1513 tcg_gen_ext32s_tl(r_tmp2, t1);
1514 tcg_gen_sub_tl(t0, r_tmp1, r_tmp2);
48d38ca5 1515
78723684
TS
1516 tcg_gen_xor_tl(r_tmp2, r_tmp1, t1);
1517 tcg_gen_xor_tl(r_tmp1, r_tmp1, t0);
48d38ca5 1518 tcg_gen_and_tl(r_tmp1, r_tmp1, r_tmp2);
4f57689a 1519 tcg_temp_free(r_tmp2);
507563e8 1520 tcg_gen_brcondi_tl(TCG_COND_GE, r_tmp1, 0, l1);
48d38ca5
TS
1521 /* operands of different sign, first operand and result different sign */
1522 generate_exception(ctx, EXCP_OVERFLOW);
1523 gen_set_label(l1);
507563e8 1524 tcg_temp_free(r_tmp1);
48d38ca5 1525
78723684 1526 tcg_gen_ext32s_tl(t0, t0);
48d38ca5 1527 }
6af0bf9c
FB
1528 opn = "sub";
1529 break;
1530 case OPC_SUBU:
78723684
TS
1531 tcg_gen_sub_tl(t0, t0, t1);
1532 tcg_gen_ext32s_tl(t0, t0);
6af0bf9c
FB
1533 opn = "subu";
1534 break;
d26bc211 1535#if defined(TARGET_MIPS64)
7a387fff 1536 case OPC_DADD:
48d38ca5 1537 {
a7812ae4
PB
1538 TCGv r_tmp1 = tcg_temp_new();
1539 TCGv r_tmp2 = tcg_temp_new();
48d38ca5
TS
1540 int l1 = gen_new_label();
1541
1542 save_cpu_state(ctx, 1);
78723684
TS
1543 tcg_gen_mov_tl(r_tmp1, t0);
1544 tcg_gen_add_tl(t0, t0, t1);
48d38ca5 1545
78723684 1546 tcg_gen_xor_tl(r_tmp1, r_tmp1, t1);
48d38ca5 1547 tcg_gen_xori_tl(r_tmp1, r_tmp1, -1);
78723684 1548 tcg_gen_xor_tl(r_tmp2, t0, t1);
48d38ca5 1549 tcg_gen_and_tl(r_tmp1, r_tmp1, r_tmp2);
4f57689a 1550 tcg_temp_free(r_tmp2);
507563e8 1551 tcg_gen_brcondi_tl(TCG_COND_GE, r_tmp1, 0, l1);
48d38ca5
TS
1552 /* operands of same sign, result different sign */
1553 generate_exception(ctx, EXCP_OVERFLOW);
1554 gen_set_label(l1);
507563e8 1555 tcg_temp_free(r_tmp1);
48d38ca5 1556 }
7a387fff
TS
1557 opn = "dadd";
1558 break;
1559 case OPC_DADDU:
78723684 1560 tcg_gen_add_tl(t0, t0, t1);
7a387fff
TS
1561 opn = "daddu";
1562 break;
1563 case OPC_DSUB:
48d38ca5 1564 {
a7812ae4
PB
1565 TCGv r_tmp1 = tcg_temp_new();
1566 TCGv r_tmp2 = tcg_temp_new();
48d38ca5
TS
1567 int l1 = gen_new_label();
1568
1569 save_cpu_state(ctx, 1);
78723684
TS
1570 tcg_gen_mov_tl(r_tmp1, t0);
1571 tcg_gen_sub_tl(t0, t0, t1);
48d38ca5 1572
78723684
TS
1573 tcg_gen_xor_tl(r_tmp2, r_tmp1, t1);
1574 tcg_gen_xor_tl(r_tmp1, r_tmp1, t0);
48d38ca5 1575 tcg_gen_and_tl(r_tmp1, r_tmp1, r_tmp2);
4f57689a 1576 tcg_temp_free(r_tmp2);
507563e8 1577 tcg_gen_brcondi_tl(TCG_COND_GE, r_tmp1, 0, l1);
48d38ca5
TS
1578 /* operands of different sign, first operand and result different sign */
1579 generate_exception(ctx, EXCP_OVERFLOW);
1580 gen_set_label(l1);
507563e8 1581 tcg_temp_free(r_tmp1);
48d38ca5 1582 }
7a387fff
TS
1583 opn = "dsub";
1584 break;
1585 case OPC_DSUBU:
78723684 1586 tcg_gen_sub_tl(t0, t0, t1);
7a387fff
TS
1587 opn = "dsubu";
1588 break;
1589#endif
6af0bf9c 1590 case OPC_SLT:
92e90443 1591 gen_op_lt(t0, t0, t1);
6af0bf9c
FB
1592 opn = "slt";
1593 break;
1594 case OPC_SLTU:
92e90443 1595 gen_op_ltu(t0, t0, t1);
6af0bf9c
FB
1596 opn = "sltu";
1597 break;
1598 case OPC_AND:
78723684 1599 tcg_gen_and_tl(t0, t0, t1);
6af0bf9c
FB
1600 opn = "and";
1601 break;
1602 case OPC_NOR:
a3fe9013 1603 tcg_gen_nor_tl(t0, t0, t1);
6af0bf9c
FB
1604 opn = "nor";
1605 break;
1606 case OPC_OR:
78723684 1607 tcg_gen_or_tl(t0, t0, t1);
6af0bf9c
FB
1608 opn = "or";
1609 break;
1610 case OPC_XOR:
78723684 1611 tcg_gen_xor_tl(t0, t0, t1);
6af0bf9c
FB
1612 opn = "xor";
1613 break;
1614 case OPC_MUL:
78723684
TS
1615 tcg_gen_mul_tl(t0, t0, t1);
1616 tcg_gen_ext32s_tl(t0, t0);
6af0bf9c
FB
1617 opn = "mul";
1618 break;
1619 case OPC_MOVN:
20c4c97c
TS
1620 {
1621 int l1 = gen_new_label();
1622
78723684
TS
1623 tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
1624 gen_store_gpr(t0, rd);
20c4c97c
TS
1625 gen_set_label(l1);
1626 }
6af0bf9c
FB
1627 opn = "movn";
1628 goto print;
1629 case OPC_MOVZ:
20c4c97c
TS
1630 {
1631 int l1 = gen_new_label();
1632
78723684
TS
1633 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
1634 gen_store_gpr(t0, rd);
20c4c97c
TS
1635 gen_set_label(l1);
1636 }
6af0bf9c
FB
1637 opn = "movz";
1638 goto print;
1639 case OPC_SLLV:
78723684
TS
1640 tcg_gen_andi_tl(t0, t0, 0x1f);
1641 tcg_gen_shl_tl(t0, t1, t0);
1642 tcg_gen_ext32s_tl(t0, t0);
6af0bf9c
FB
1643 opn = "sllv";
1644 break;
1645 case OPC_SRAV:
78723684
TS
1646 tcg_gen_ext32s_tl(t1, t1);
1647 tcg_gen_andi_tl(t0, t0, 0x1f);
1648 tcg_gen_sar_tl(t0, t1, t0);
6af0bf9c
FB
1649 opn = "srav";
1650 break;
1651 case OPC_SRLV:
5a63bcb2
TS
1652 switch ((ctx->opcode >> 6) & 0x1f) {
1653 case 0:
78723684
TS
1654 tcg_gen_ext32u_tl(t1, t1);
1655 tcg_gen_andi_tl(t0, t0, 0x1f);
1656 tcg_gen_shr_tl(t0, t1, t0);
1657 tcg_gen_ext32s_tl(t0, t0);
7a387fff 1658 opn = "srlv";
5a63bcb2
TS
1659 break;
1660 case 1:
e189e748
TS
1661 /* rotrv is decoded as srlv on non-R2 CPUs */
1662 if (env->insn_flags & ISA_MIPS32R2) {
48d38ca5
TS
1663 int l1 = gen_new_label();
1664 int l2 = gen_new_label();
1665
78723684
TS
1666 tcg_gen_andi_tl(t0, t0, 0x1f);
1667 tcg_gen_brcondi_tl(TCG_COND_EQ, t0, 0, l1);
48d38ca5 1668 {
a7812ae4
PB
1669 TCGv_i32 r_tmp1 = tcg_temp_new_i32();
1670 TCGv_i32 r_tmp2 = tcg_temp_new_i32();
48d38ca5 1671
78723684
TS
1672 tcg_gen_trunc_tl_i32(r_tmp1, t0);
1673 tcg_gen_trunc_tl_i32(r_tmp2, t1);
e00fcff7 1674 tcg_gen_rotr_i32(r_tmp1, r_tmp1, r_tmp2);
a7812ae4
PB
1675 tcg_temp_free_i32(r_tmp1);
1676 tcg_temp_free_i32(r_tmp2);
48d38ca5
TS
1677 tcg_gen_br(l2);
1678 }
1679 gen_set_label(l1);
78723684 1680 tcg_gen_mov_tl(t0, t1);
48d38ca5 1681 gen_set_label(l2);
e189e748
TS
1682 opn = "rotrv";
1683 } else {
78723684
TS
1684 tcg_gen_ext32u_tl(t1, t1);
1685 tcg_gen_andi_tl(t0, t0, 0x1f);
1686 tcg_gen_shr_tl(t0, t1, t0);
1687 tcg_gen_ext32s_tl(t0, t0);
e189e748
TS
1688 opn = "srlv";
1689 }
5a63bcb2
TS
1690 break;
1691 default:
1692 MIPS_INVAL("invalid srlv flag");
1693 generate_exception(ctx, EXCP_RI);
1694 break;
1695 }
7a387fff 1696 break;
d26bc211 1697#if defined(TARGET_MIPS64)
7a387fff 1698 case OPC_DSLLV:
78723684
TS
1699 tcg_gen_andi_tl(t0, t0, 0x3f);
1700 tcg_gen_shl_tl(t0, t1, t0);
7a387fff
TS
1701 opn = "dsllv";
1702 break;
1703 case OPC_DSRAV:
78723684
TS
1704 tcg_gen_andi_tl(t0, t0, 0x3f);
1705 tcg_gen_sar_tl(t0, t1, t0);
7a387fff
TS
1706 opn = "dsrav";
1707 break;
1708 case OPC_DSRLV:
5a63bcb2
TS
1709 switch ((ctx->opcode >> 6) & 0x1f) {
1710 case 0:
78723684
TS
1711 tcg_gen_andi_tl(t0, t0, 0x3f);
1712 tcg_gen_shr_tl(t0, t1, t0);
7a387fff 1713 opn = "dsrlv";
5a63bcb2
TS
1714 break;
1715 case 1:
e189e748
TS
1716 /* drotrv is decoded as dsrlv on non-R2 CPUs */
1717 if (env->insn_flags & ISA_MIPS32R2) {
48d38ca5
TS
1718 int l1 = gen_new_label();
1719 int l2 = gen_new_label();
1720
78723684
TS
1721 tcg_gen_andi_tl(t0, t0, 0x3f);
1722 tcg_gen_brcondi_tl(TCG_COND_EQ, t0, 0, l1);
48d38ca5 1723 {
e00fcff7 1724 tcg_gen_rotr_tl(t0, t1, t0);
48d38ca5
TS
1725 tcg_gen_br(l2);
1726 }
1727 gen_set_label(l1);
78723684 1728 tcg_gen_mov_tl(t0, t1);
48d38ca5 1729 gen_set_label(l2);
e189e748
TS
1730 opn = "drotrv";
1731 } else {
78723684
TS
1732 tcg_gen_andi_tl(t0, t0, 0x3f);
1733 tcg_gen_shr_tl(t0, t1, t0);
e189e748
TS
1734 opn = "dsrlv";
1735 }
5a63bcb2
TS
1736 break;
1737 default:
1738 MIPS_INVAL("invalid dsrlv flag");
1739 generate_exception(ctx, EXCP_RI);
1740 break;
1741 }
6af0bf9c 1742 break;
7a387fff 1743#endif
6af0bf9c 1744 default:
923617a3 1745 MIPS_INVAL(opn);
6af0bf9c 1746 generate_exception(ctx, EXCP_RI);
78723684 1747 goto out;
6af0bf9c 1748 }
78723684 1749 gen_store_gpr(t0, rd);
6af0bf9c
FB
1750 print:
1751 MIPS_DEBUG("%s %s, %s, %s", opn, regnames[rd], regnames[rs], regnames[rt]);
78723684
TS
1752 out:
1753 tcg_temp_free(t0);
1754 tcg_temp_free(t1);
6af0bf9c
FB
1755}
1756
1757/* Arithmetic on HI/LO registers */
7a387fff 1758static void gen_HILO (DisasContext *ctx, uint32_t opc, int reg)
6af0bf9c 1759{
923617a3 1760 const char *opn = "hilo";
6af0bf9c
FB
1761
1762 if (reg == 0 && (opc == OPC_MFHI || opc == OPC_MFLO)) {
ead9360e 1763 /* Treat as NOP. */
6af0bf9c 1764 MIPS_DEBUG("NOP");
a1f6684d 1765 return;
6af0bf9c
FB
1766 }
1767 switch (opc) {
1768 case OPC_MFHI:
a1f6684d 1769 tcg_gen_mov_tl(cpu_gpr[reg], cpu_HI[0]);
6af0bf9c
FB
1770 opn = "mfhi";
1771 break;
1772 case OPC_MFLO:
a1f6684d 1773 tcg_gen_mov_tl(cpu_gpr[reg], cpu_LO[0]);
6af0bf9c
FB
1774 opn = "mflo";
1775 break;
1776 case OPC_MTHI:
a1f6684d
AJ
1777 if (reg != 0)
1778 tcg_gen_mov_tl(cpu_HI[0], cpu_gpr[reg]);
1779 else
1780 tcg_gen_movi_tl(cpu_HI[0], 0);
6af0bf9c
FB
1781 opn = "mthi";
1782 break;
1783 case OPC_MTLO:
a1f6684d
AJ
1784 if (reg != 0)
1785 tcg_gen_mov_tl(cpu_LO[0], cpu_gpr[reg]);
1786 else
1787 tcg_gen_movi_tl(cpu_LO[0], 0);
6af0bf9c
FB
1788 opn = "mtlo";
1789 break;
6af0bf9c
FB
1790 }
1791 MIPS_DEBUG("%s %s", opn, regnames[reg]);
1792}
1793
7a387fff 1794static void gen_muldiv (DisasContext *ctx, uint32_t opc,
6af0bf9c
FB
1795 int rs, int rt)
1796{
923617a3 1797 const char *opn = "mul/div";
d45f89f4
AJ
1798 TCGv t0, t1;
1799
1800 switch (opc) {
1801 case OPC_DIV:
1802 case OPC_DIVU:
1803#if defined(TARGET_MIPS64)
1804 case OPC_DDIV:
1805 case OPC_DDIVU:
1806#endif
1807 t0 = tcg_temp_local_new();
1808 t1 = tcg_temp_local_new();
1809 break;
1810 default:
1811 t0 = tcg_temp_new();
1812 t1 = tcg_temp_new();
1813 break;
1814 }
6af0bf9c 1815
78723684
TS
1816 gen_load_gpr(t0, rs);
1817 gen_load_gpr(t1, rt);
6af0bf9c
FB
1818 switch (opc) {
1819 case OPC_DIV:
48d38ca5
TS
1820 {
1821 int l1 = gen_new_label();
d45f89f4 1822 int l2 = gen_new_label();
48d38ca5 1823
d45f89f4
AJ
1824 tcg_gen_ext32s_tl(t0, t0);
1825 tcg_gen_ext32s_tl(t1, t1);
78723684 1826 tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
d45f89f4
AJ
1827 tcg_gen_brcondi_tl(TCG_COND_NE, t0, INT_MIN, l2);
1828 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1, l2);
1829
1830 tcg_gen_mov_tl(cpu_LO[0], t0);
1831 tcg_gen_movi_tl(cpu_HI[0], 0);
1832 tcg_gen_br(l1);
1833 gen_set_label(l2);
1834 tcg_gen_div_tl(cpu_LO[0], t0, t1);
1835 tcg_gen_rem_tl(cpu_HI[0], t0, t1);
1836 tcg_gen_ext32s_tl(cpu_LO[0], cpu_LO[0]);
1837 tcg_gen_ext32s_tl(cpu_HI[0], cpu_HI[0]);
48d38ca5
TS
1838 gen_set_label(l1);
1839 }
6af0bf9c
FB
1840 opn = "div";
1841 break;
1842 case OPC_DIVU:
48d38ca5
TS
1843 {
1844 int l1 = gen_new_label();
1845
0c0ed03b
AJ
1846 tcg_gen_ext32u_tl(t0, t0);
1847 tcg_gen_ext32u_tl(t1, t1);
78723684 1848 tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
d45f89f4
AJ
1849 tcg_gen_divu_tl(cpu_LO[0], t0, t1);
1850 tcg_gen_remu_tl(cpu_HI[0], t0, t1);
1851 tcg_gen_ext32s_tl(cpu_LO[0], cpu_LO[0]);
1852 tcg_gen_ext32s_tl(cpu_HI[0], cpu_HI[0]);
48d38ca5
TS
1853 gen_set_label(l1);
1854 }
6af0bf9c
FB
1855 opn = "divu";
1856 break;
1857 case OPC_MULT:
214c465f 1858 {
d45f89f4
AJ
1859 TCGv_i64 t2 = tcg_temp_new_i64();
1860 TCGv_i64 t3 = tcg_temp_new_i64();
1861
1862 tcg_gen_ext_tl_i64(t2, t0);
1863 tcg_gen_ext_tl_i64(t3, t1);
1864 tcg_gen_mul_i64(t2, t2, t3);
1865 tcg_temp_free_i64(t3);
1866 tcg_gen_trunc_i64_tl(t0, t2);
1867 tcg_gen_shri_i64(t2, t2, 32);
1868 tcg_gen_trunc_i64_tl(t1, t2);
1869 tcg_temp_free_i64(t2);
b10fa3c9
AJ
1870 tcg_gen_ext32s_tl(cpu_LO[0], t0);
1871 tcg_gen_ext32s_tl(cpu_HI[0], t1);
214c465f 1872 }
6af0bf9c
FB
1873 opn = "mult";
1874 break;
1875 case OPC_MULTU:
214c465f 1876 {
d45f89f4
AJ
1877 TCGv_i64 t2 = tcg_temp_new_i64();
1878 TCGv_i64 t3 = tcg_temp_new_i64();
214c465f 1879
78723684
TS
1880 tcg_gen_ext32u_tl(t0, t0);
1881 tcg_gen_ext32u_tl(t1, t1);
d45f89f4
AJ
1882 tcg_gen_extu_tl_i64(t2, t0);
1883 tcg_gen_extu_tl_i64(t3, t1);
1884 tcg_gen_mul_i64(t2, t2, t3);
1885 tcg_temp_free_i64(t3);
1886 tcg_gen_trunc_i64_tl(t0, t2);
1887 tcg_gen_shri_i64(t2, t2, 32);
1888 tcg_gen_trunc_i64_tl(t1, t2);
1889 tcg_temp_free_i64(t2);
b10fa3c9
AJ
1890 tcg_gen_ext32s_tl(cpu_LO[0], t0);
1891 tcg_gen_ext32s_tl(cpu_HI[0], t1);
214c465f 1892 }
6af0bf9c
FB
1893 opn = "multu";
1894 break;
d26bc211 1895#if defined(TARGET_MIPS64)
7a387fff 1896 case OPC_DDIV:
48d38ca5
TS
1897 {
1898 int l1 = gen_new_label();
d45f89f4 1899 int l2 = gen_new_label();
48d38ca5 1900
78723684 1901 tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
d45f89f4
AJ
1902 tcg_gen_brcondi_tl(TCG_COND_NE, t0, -1LL << 63, l2);
1903 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1LL, l2);
1904 tcg_gen_mov_tl(cpu_LO[0], t0);
1905 tcg_gen_movi_tl(cpu_HI[0], 0);
1906 tcg_gen_br(l1);
1907 gen_set_label(l2);
1908 tcg_gen_div_i64(cpu_LO[0], t0, t1);
1909 tcg_gen_rem_i64(cpu_HI[0], t0, t1);
48d38ca5
TS
1910 gen_set_label(l1);
1911 }
7a387fff
TS
1912 opn = "ddiv";
1913 break;
1914 case OPC_DDIVU:
48d38ca5
TS
1915 {
1916 int l1 = gen_new_label();
1917
78723684 1918 tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
b10fa3c9
AJ
1919 tcg_gen_divu_i64(cpu_LO[0], t0, t1);
1920 tcg_gen_remu_i64(cpu_HI[0], t0, t1);
48d38ca5
TS
1921 gen_set_label(l1);
1922 }
7a387fff
TS
1923 opn = "ddivu";
1924 break;
1925 case OPC_DMULT:
a7812ae4 1926 gen_helper_dmult(t0, t1);
7a387fff
TS
1927 opn = "dmult";
1928 break;
1929 case OPC_DMULTU:
a7812ae4 1930 gen_helper_dmultu(t0, t1);
7a387fff
TS
1931 opn = "dmultu";
1932 break;
1933#endif
6af0bf9c 1934 case OPC_MADD:
214c465f 1935 {
d45f89f4
AJ
1936 TCGv_i64 t2 = tcg_temp_new_i64();
1937 TCGv_i64 t3 = tcg_temp_new_i64();
1938
1939 tcg_gen_ext_tl_i64(t2, t0);
1940 tcg_gen_ext_tl_i64(t3, t1);
1941 tcg_gen_mul_i64(t2, t2, t3);
1942 tcg_gen_concat_tl_i64(t3, cpu_LO[0], cpu_HI[0]);
1943 tcg_gen_add_i64(t2, t2, t3);
1944 tcg_temp_free_i64(t3);
1945 tcg_gen_trunc_i64_tl(t0, t2);
1946 tcg_gen_shri_i64(t2, t2, 32);
1947 tcg_gen_trunc_i64_tl(t1, t2);
1948 tcg_temp_free_i64(t2);
b10fa3c9
AJ
1949 tcg_gen_ext32s_tl(cpu_LO[0], t0);
1950 tcg_gen_ext32s_tl(cpu_LO[1], t1);
214c465f 1951 }
6af0bf9c
FB
1952 opn = "madd";
1953 break;
1954 case OPC_MADDU:
214c465f 1955 {
d45f89f4
AJ
1956 TCGv_i64 t2 = tcg_temp_new_i64();
1957 TCGv_i64 t3 = tcg_temp_new_i64();
214c465f 1958
78723684
TS
1959 tcg_gen_ext32u_tl(t0, t0);
1960 tcg_gen_ext32u_tl(t1, t1);
d45f89f4
AJ
1961 tcg_gen_extu_tl_i64(t2, t0);
1962 tcg_gen_extu_tl_i64(t3, t1);
1963 tcg_gen_mul_i64(t2, t2, t3);
1964 tcg_gen_concat_tl_i64(t3, cpu_LO[0], cpu_HI[0]);
1965 tcg_gen_add_i64(t2, t2, t3);
1966 tcg_temp_free_i64(t3);
1967 tcg_gen_trunc_i64_tl(t0, t2);
1968 tcg_gen_shri_i64(t2, t2, 32);
1969 tcg_gen_trunc_i64_tl(t1, t2);
1970 tcg_temp_free_i64(t2);
b10fa3c9
AJ
1971 tcg_gen_ext32s_tl(cpu_LO[0], t0);
1972 tcg_gen_ext32s_tl(cpu_HI[0], t1);
214c465f 1973 }
6af0bf9c
FB
1974 opn = "maddu";
1975 break;
1976 case OPC_MSUB:
214c465f 1977 {
d45f89f4
AJ
1978 TCGv_i64 t2 = tcg_temp_new_i64();
1979 TCGv_i64 t3 = tcg_temp_new_i64();
1980
1981 tcg_gen_ext_tl_i64(t2, t0);
1982 tcg_gen_ext_tl_i64(t3, t1);
1983 tcg_gen_mul_i64(t2, t2, t3);
1984 tcg_gen_concat_tl_i64(t3, cpu_LO[0], cpu_HI[0]);
1985 tcg_gen_sub_i64(t2, t2, t3);
1986 tcg_temp_free_i64(t3);
1987 tcg_gen_trunc_i64_tl(t0, t2);
1988 tcg_gen_shri_i64(t2, t2, 32);
1989 tcg_gen_trunc_i64_tl(t1, t2);
1990 tcg_temp_free_i64(t2);
b10fa3c9
AJ
1991 tcg_gen_ext32s_tl(cpu_LO[0], t0);
1992 tcg_gen_ext32s_tl(cpu_HI[0], t1);
214c465f 1993 }
6af0bf9c
FB
1994 opn = "msub";
1995 break;
1996 case OPC_MSUBU:
214c465f 1997 {
d45f89f4
AJ
1998 TCGv_i64 t2 = tcg_temp_new_i64();
1999 TCGv_i64 t3 = tcg_temp_new_i64();
214c465f 2000
78723684
TS
2001 tcg_gen_ext32u_tl(t0, t0);
2002 tcg_gen_ext32u_tl(t1, t1);
d45f89f4
AJ
2003 tcg_gen_extu_tl_i64(t2, t0);
2004 tcg_gen_extu_tl_i64(t3, t1);
2005 tcg_gen_mul_i64(t2, t2, t3);
2006 tcg_gen_concat_tl_i64(t3, cpu_LO[0], cpu_HI[0]);
2007 tcg_gen_sub_i64(t2, t2, t3);
2008 tcg_temp_free_i64(t3);
2009 tcg_gen_trunc_i64_tl(t0, t2);
2010 tcg_gen_shri_i64(t2, t2, 32);
2011 tcg_gen_trunc_i64_tl(t1, t2);
2012 tcg_temp_free_i64(t2);
b10fa3c9
AJ
2013 tcg_gen_ext32s_tl(cpu_LO[0], t0);
2014 tcg_gen_ext32s_tl(cpu_HI[0], t1);
214c465f 2015 }
6af0bf9c
FB
2016 opn = "msubu";
2017 break;
2018 default:
923617a3 2019 MIPS_INVAL(opn);
6af0bf9c 2020 generate_exception(ctx, EXCP_RI);
78723684 2021 goto out;
6af0bf9c
FB
2022 }
2023 MIPS_DEBUG("%s %s %s", opn, regnames[rs], regnames[rt]);
78723684
TS
2024 out:
2025 tcg_temp_free(t0);
2026 tcg_temp_free(t1);
6af0bf9c
FB
2027}
2028
e9c71dd1
TS
2029static void gen_mul_vr54xx (DisasContext *ctx, uint32_t opc,
2030 int rd, int rs, int rt)
2031{
2032 const char *opn = "mul vr54xx";
f157bfe1
AJ
2033 TCGv t0 = tcg_temp_new();
2034 TCGv t1 = tcg_temp_new();
e9c71dd1 2035
6c5c1e20
TS
2036 gen_load_gpr(t0, rs);
2037 gen_load_gpr(t1, rt);
e9c71dd1
TS
2038
2039 switch (opc) {
2040 case OPC_VR54XX_MULS:
a7812ae4 2041 gen_helper_muls(t0, t0, t1);
e9c71dd1 2042 opn = "muls";
6958549d 2043 break;
e9c71dd1 2044 case OPC_VR54XX_MULSU:
a7812ae4 2045 gen_helper_mulsu(t0, t0, t1);
e9c71dd1 2046 opn = "mulsu";
6958549d 2047 break;
e9c71dd1 2048 case OPC_VR54XX_MACC:
a7812ae4 2049 gen_helper_macc(t0, t0, t1);
e9c71dd1 2050 opn = "macc";
6958549d 2051 break;
e9c71dd1 2052 case OPC_VR54XX_MACCU:
a7812ae4 2053 gen_helper_maccu(t0, t0, t1);
e9c71dd1 2054 opn = "maccu";
6958549d 2055 break;
e9c71dd1 2056 case OPC_VR54XX_MSAC:
a7812ae4 2057 gen_helper_msac(t0, t0, t1);
e9c71dd1 2058 opn = "msac";
6958549d 2059 break;
e9c71dd1 2060 case OPC_VR54XX_MSACU:
a7812ae4 2061 gen_helper_msacu(t0, t0, t1);
e9c71dd1 2062 opn = "msacu";
6958549d 2063 break;
e9c71dd1 2064 case OPC_VR54XX_MULHI:
a7812ae4 2065 gen_helper_mulhi(t0, t0, t1);
e9c71dd1 2066 opn = "mulhi";
6958549d 2067 break;
e9c71dd1 2068 case OPC_VR54XX_MULHIU:
a7812ae4 2069 gen_helper_mulhiu(t0, t0, t1);
e9c71dd1 2070 opn = "mulhiu";
6958549d 2071 break;
e9c71dd1 2072 case OPC_VR54XX_MULSHI:
a7812ae4 2073 gen_helper_mulshi(t0, t0, t1);
e9c71dd1 2074 opn = "mulshi";
6958549d 2075 break;
e9c71dd1 2076 case OPC_VR54XX_MULSHIU:
a7812ae4 2077 gen_helper_mulshiu(t0, t0, t1);
e9c71dd1 2078 opn = "mulshiu";
6958549d 2079 break;
e9c71dd1 2080 case OPC_VR54XX_MACCHI:
a7812ae4 2081 gen_helper_macchi(t0, t0, t1);
e9c71dd1 2082 opn = "macchi";
6958549d 2083 break;
e9c71dd1 2084 case OPC_VR54XX_MACCHIU:
a7812ae4 2085 gen_helper_macchiu(t0, t0, t1);
e9c71dd1 2086 opn = "macchiu";
6958549d 2087 break;
e9c71dd1 2088 case OPC_VR54XX_MSACHI:
a7812ae4 2089 gen_helper_msachi(t0, t0, t1);
e9c71dd1 2090 opn = "msachi";
6958549d 2091 break;
e9c71dd1 2092 case OPC_VR54XX_MSACHIU:
a7812ae4 2093 gen_helper_msachiu(t0, t0, t1);
e9c71dd1 2094 opn = "msachiu";
6958549d 2095 break;
e9c71dd1
TS
2096 default:
2097 MIPS_INVAL("mul vr54xx");
2098 generate_exception(ctx, EXCP_RI);
6c5c1e20 2099 goto out;
e9c71dd1 2100 }
6c5c1e20 2101 gen_store_gpr(t0, rd);
e9c71dd1 2102 MIPS_DEBUG("%s %s, %s, %s", opn, regnames[rd], regnames[rs], regnames[rt]);
6c5c1e20
TS
2103
2104 out:
2105 tcg_temp_free(t0);
2106 tcg_temp_free(t1);
e9c71dd1
TS
2107}
2108
7a387fff 2109static void gen_cl (DisasContext *ctx, uint32_t opc,
6af0bf9c
FB
2110 int rd, int rs)
2111{
923617a3 2112 const char *opn = "CLx";
20e1fb52 2113 TCGv t0;
6c5c1e20 2114
6af0bf9c 2115 if (rd == 0) {
ead9360e 2116 /* Treat as NOP. */
6af0bf9c 2117 MIPS_DEBUG("NOP");
20e1fb52 2118 return;
6af0bf9c 2119 }
20e1fb52 2120 t0 = tcg_temp_new();
6c5c1e20 2121 gen_load_gpr(t0, rs);
6af0bf9c
FB
2122 switch (opc) {
2123 case OPC_CLO:
20e1fb52 2124 gen_helper_clo(cpu_gpr[rd], t0);
6af0bf9c
FB
2125 opn = "clo";
2126 break;
2127 case OPC_CLZ:
20e1fb52 2128 gen_helper_clz(cpu_gpr[rd], t0);
6af0bf9c
FB
2129 opn = "clz";
2130 break;
d26bc211 2131#if defined(TARGET_MIPS64)
7a387fff 2132 case OPC_DCLO:
20e1fb52 2133 gen_helper_dclo(cpu_gpr[rd], t0);
7a387fff
TS
2134 opn = "dclo";
2135 break;
2136 case OPC_DCLZ:
20e1fb52 2137 gen_helper_dclz(cpu_gpr[rd], t0);
7a387fff
TS
2138 opn = "dclz";
2139 break;
2140#endif
6af0bf9c 2141 }
6af0bf9c 2142 MIPS_DEBUG("%s %s, %s", opn, regnames[rd], regnames[rs]);
6c5c1e20 2143 tcg_temp_free(t0);
6af0bf9c
FB
2144}
2145
2146/* Traps */
7a387fff 2147static void gen_trap (DisasContext *ctx, uint32_t opc,
6af0bf9c
FB
2148 int rs, int rt, int16_t imm)
2149{
2150 int cond;
cdc0faa6 2151 TCGv t0 = tcg_temp_new();
1ba74fb8 2152 TCGv t1 = tcg_temp_new();
6af0bf9c
FB
2153
2154 cond = 0;
2155 /* Load needed operands */
2156 switch (opc) {
2157 case OPC_TEQ:
2158 case OPC_TGE:
2159 case OPC_TGEU:
2160 case OPC_TLT:
2161 case OPC_TLTU:
2162 case OPC_TNE:
2163 /* Compare two registers */
2164 if (rs != rt) {
be24bb4f
TS
2165 gen_load_gpr(t0, rs);
2166 gen_load_gpr(t1, rt);
6af0bf9c
FB
2167 cond = 1;
2168 }
179e32bb 2169 break;
6af0bf9c
FB
2170 case OPC_TEQI:
2171 case OPC_TGEI:
2172 case OPC_TGEIU:
2173 case OPC_TLTI:
2174 case OPC_TLTIU:
2175 case OPC_TNEI:
2176 /* Compare register to immediate */
2177 if (rs != 0 || imm != 0) {
be24bb4f
TS
2178 gen_load_gpr(t0, rs);
2179 tcg_gen_movi_tl(t1, (int32_t)imm);
6af0bf9c
FB
2180 cond = 1;
2181 }
2182 break;
2183 }
2184 if (cond == 0) {
2185 switch (opc) {
2186 case OPC_TEQ: /* rs == rs */
2187 case OPC_TEQI: /* r0 == 0 */
2188 case OPC_TGE: /* rs >= rs */
2189 case OPC_TGEI: /* r0 >= 0 */
2190 case OPC_TGEU: /* rs >= rs unsigned */
2191 case OPC_TGEIU: /* r0 >= 0 unsigned */
2192 /* Always trap */
cdc0faa6 2193 generate_exception(ctx, EXCP_TRAP);
6af0bf9c
FB
2194 break;
2195 case OPC_TLT: /* rs < rs */
2196 case OPC_TLTI: /* r0 < 0 */
2197 case OPC_TLTU: /* rs < rs unsigned */
2198 case OPC_TLTIU: /* r0 < 0 unsigned */
2199 case OPC_TNE: /* rs != rs */
2200 case OPC_TNEI: /* r0 != 0 */
ead9360e 2201 /* Never trap: treat as NOP. */
cdc0faa6 2202 break;
6af0bf9c
FB
2203 }
2204 } else {
cdc0faa6
AJ
2205 int l1 = gen_new_label();
2206
6af0bf9c
FB
2207 switch (opc) {
2208 case OPC_TEQ:
2209 case OPC_TEQI:
cdc0faa6 2210 tcg_gen_brcond_tl(TCG_COND_NE, t0, t1, l1);
6af0bf9c
FB
2211 break;
2212 case OPC_TGE:
2213 case OPC_TGEI:
cdc0faa6 2214 tcg_gen_brcond_tl(TCG_COND_LT, t0, t1, l1);
6af0bf9c
FB
2215 break;
2216 case OPC_TGEU:
2217 case OPC_TGEIU:
cdc0faa6 2218 tcg_gen_brcond_tl(TCG_COND_LTU, t0, t1, l1);
6af0bf9c
FB
2219 break;
2220 case OPC_TLT:
2221 case OPC_TLTI:
cdc0faa6 2222 tcg_gen_brcond_tl(TCG_COND_GE, t0, t1, l1);
6af0bf9c
FB
2223 break;
2224 case OPC_TLTU:
2225 case OPC_TLTIU:
cdc0faa6 2226 tcg_gen_brcond_tl(TCG_COND_GEU, t0, t1, l1);
6af0bf9c
FB
2227 break;
2228 case OPC_TNE:
2229 case OPC_TNEI:
cdc0faa6 2230 tcg_gen_brcond_tl(TCG_COND_EQ, t0, t1, l1);
6af0bf9c 2231 break;
6af0bf9c 2232 }
cdc0faa6 2233 generate_exception(ctx, EXCP_TRAP);
08ba7963
TS
2234 gen_set_label(l1);
2235 }
be24bb4f
TS
2236 tcg_temp_free(t0);
2237 tcg_temp_free(t1);
6af0bf9c
FB
2238}
2239
356265ae 2240static inline void gen_goto_tb(DisasContext *ctx, int n, target_ulong dest)
c53be334 2241{
6e256c93
FB
2242 TranslationBlock *tb;
2243 tb = ctx->tb;
2244 if ((tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK)) {
57fec1fe 2245 tcg_gen_goto_tb(n);
9b9e4393 2246 gen_save_pc(dest);
57fec1fe 2247 tcg_gen_exit_tb((long)tb + n);
6e256c93 2248 } else {
9b9e4393 2249 gen_save_pc(dest);
57fec1fe 2250 tcg_gen_exit_tb(0);
6e256c93 2251 }
c53be334
FB
2252}
2253
6af0bf9c 2254/* Branches (before delay slot) */
7a387fff 2255static void gen_compute_branch (DisasContext *ctx, uint32_t opc,
6af0bf9c
FB
2256 int rs, int rt, int32_t offset)
2257{
d077b6f7 2258 target_ulong btgt = -1;
3ad4bb2d 2259 int blink = 0;
2fdbad25 2260 int bcond_compute = 0;
1ba74fb8
AJ
2261 TCGv t0 = tcg_temp_new();
2262 TCGv t1 = tcg_temp_new();
3ad4bb2d
TS
2263
2264 if (ctx->hflags & MIPS_HFLAG_BMASK) {
923617a3 2265#ifdef MIPS_DEBUG_DISAS
d12d51d5 2266 LOG_DISAS("Branch in delay slot at PC 0x" TARGET_FMT_lx "\n", ctx->pc);
923617a3 2267#endif
3ad4bb2d 2268 generate_exception(ctx, EXCP_RI);
6c5c1e20 2269 goto out;
3ad4bb2d 2270 }
6af0bf9c 2271
6af0bf9c
FB
2272 /* Load needed operands */
2273 switch (opc) {
2274 case OPC_BEQ:
2275 case OPC_BEQL:
2276 case OPC_BNE:
2277 case OPC_BNEL:
2278 /* Compare two registers */
2279 if (rs != rt) {
6c5c1e20
TS
2280 gen_load_gpr(t0, rs);
2281 gen_load_gpr(t1, rt);
2fdbad25 2282 bcond_compute = 1;
6af0bf9c 2283 }
d077b6f7 2284 btgt = ctx->pc + 4 + offset;
6af0bf9c
FB
2285 break;
2286 case OPC_BGEZ:
2287 case OPC_BGEZAL:
2288 case OPC_BGEZALL:
2289 case OPC_BGEZL:
2290 case OPC_BGTZ:
2291 case OPC_BGTZL:
2292 case OPC_BLEZ:
2293 case OPC_BLEZL:
2294 case OPC_BLTZ:
2295 case OPC_BLTZAL:
2296 case OPC_BLTZALL:
2297 case OPC_BLTZL:
2298 /* Compare to zero */
2299 if (rs != 0) {
6c5c1e20 2300 gen_load_gpr(t0, rs);
2fdbad25 2301 bcond_compute = 1;
6af0bf9c 2302 }
d077b6f7 2303 btgt = ctx->pc + 4 + offset;
6af0bf9c
FB
2304 break;
2305 case OPC_J:
2306 case OPC_JAL:
2307 /* Jump to immediate */
d077b6f7 2308 btgt = ((ctx->pc + 4) & (int32_t)0xF0000000) | (uint32_t)offset;
6af0bf9c
FB
2309 break;
2310 case OPC_JR:
2311 case OPC_JALR:
2312 /* Jump to register */
7a387fff
TS
2313 if (offset != 0 && offset != 16) {
2314 /* Hint = 0 is JR/JALR, hint 16 is JR.HB/JALR.HB, the
cbeb0857 2315 others are reserved. */
923617a3 2316 MIPS_INVAL("jump hint");
6af0bf9c 2317 generate_exception(ctx, EXCP_RI);
6c5c1e20 2318 goto out;
6af0bf9c 2319 }
d077b6f7 2320 gen_load_gpr(btarget, rs);
6af0bf9c
FB
2321 break;
2322 default:
2323 MIPS_INVAL("branch/jump");
2324 generate_exception(ctx, EXCP_RI);
6c5c1e20 2325 goto out;
6af0bf9c 2326 }
2fdbad25 2327 if (bcond_compute == 0) {
6af0bf9c
FB
2328 /* No condition to be computed */
2329 switch (opc) {
2330 case OPC_BEQ: /* rx == rx */
2331 case OPC_BEQL: /* rx == rx likely */
2332 case OPC_BGEZ: /* 0 >= 0 */
2333 case OPC_BGEZL: /* 0 >= 0 likely */
2334 case OPC_BLEZ: /* 0 <= 0 */
2335 case OPC_BLEZL: /* 0 <= 0 likely */
2336 /* Always take */
4ad40f36 2337 ctx->hflags |= MIPS_HFLAG_B;
6af0bf9c
FB
2338 MIPS_DEBUG("balways");
2339 break;
2340 case OPC_BGEZAL: /* 0 >= 0 */
2341 case OPC_BGEZALL: /* 0 >= 0 likely */
2342 /* Always take and link */
2343 blink = 31;
4ad40f36 2344 ctx->hflags |= MIPS_HFLAG_B;
6af0bf9c
FB
2345 MIPS_DEBUG("balways and link");
2346 break;
2347 case OPC_BNE: /* rx != rx */
2348 case OPC_BGTZ: /* 0 > 0 */
2349 case OPC_BLTZ: /* 0 < 0 */
ead9360e 2350 /* Treat as NOP. */
6af0bf9c 2351 MIPS_DEBUG("bnever (NOP)");
6c5c1e20 2352 goto out;
eeef26cd 2353 case OPC_BLTZAL: /* 0 < 0 */
1ba74fb8 2354 tcg_gen_movi_tl(cpu_gpr[31], ctx->pc + 8);
9898128f 2355 MIPS_DEBUG("bnever and link");
6c5c1e20 2356 goto out;
eeef26cd 2357 case OPC_BLTZALL: /* 0 < 0 likely */
1ba74fb8 2358 tcg_gen_movi_tl(cpu_gpr[31], ctx->pc + 8);
9898128f
TS
2359 /* Skip the instruction in the delay slot */
2360 MIPS_DEBUG("bnever, link and skip");
2361 ctx->pc += 4;
6c5c1e20 2362 goto out;
6af0bf9c
FB
2363 case OPC_BNEL: /* rx != rx likely */
2364 case OPC_BGTZL: /* 0 > 0 likely */
6af0bf9c
FB
2365 case OPC_BLTZL: /* 0 < 0 likely */
2366 /* Skip the instruction in the delay slot */
2367 MIPS_DEBUG("bnever and skip");
9898128f 2368 ctx->pc += 4;
6c5c1e20 2369 goto out;
6af0bf9c 2370 case OPC_J:
4ad40f36 2371 ctx->hflags |= MIPS_HFLAG_B;
d077b6f7 2372 MIPS_DEBUG("j " TARGET_FMT_lx, btgt);
6af0bf9c
FB
2373 break;
2374 case OPC_JAL:
2375 blink = 31;
4ad40f36 2376 ctx->hflags |= MIPS_HFLAG_B;
d077b6f7 2377 MIPS_DEBUG("jal " TARGET_FMT_lx, btgt);
6af0bf9c
FB
2378 break;
2379 case OPC_JR:
4ad40f36 2380 ctx->hflags |= MIPS_HFLAG_BR;
6af0bf9c
FB
2381 MIPS_DEBUG("jr %s", regnames[rs]);
2382 break;
2383 case OPC_JALR:
2384 blink = rt;
4ad40f36 2385 ctx->hflags |= MIPS_HFLAG_BR;
6af0bf9c
FB
2386 MIPS_DEBUG("jalr %s, %s", regnames[rt], regnames[rs]);
2387 break;
2388 default:
2389 MIPS_INVAL("branch/jump");
2390 generate_exception(ctx, EXCP_RI);
6c5c1e20 2391 goto out;
6af0bf9c
FB
2392 }
2393 } else {
2394 switch (opc) {
2395 case OPC_BEQ:
1ba74fb8 2396 gen_op_eq(bcond, t0, t1);
923617a3 2397 MIPS_DEBUG("beq %s, %s, " TARGET_FMT_lx,
d077b6f7 2398 regnames[rs], regnames[rt], btgt);
6af0bf9c
FB
2399 goto not_likely;
2400 case OPC_BEQL:
1ba74fb8 2401 gen_op_eq(bcond, t0, t1);
923617a3 2402 MIPS_DEBUG("beql %s, %s, " TARGET_FMT_lx,
d077b6f7 2403 regnames[rs], regnames[rt], btgt);
6af0bf9c
FB
2404 goto likely;
2405 case OPC_BNE:
1ba74fb8 2406 gen_op_ne(bcond, t0, t1);
923617a3 2407 MIPS_DEBUG("bne %s, %s, " TARGET_FMT_lx,
d077b6f7 2408 regnames[rs], regnames[rt], btgt);
6af0bf9c
FB
2409 goto not_likely;
2410 case OPC_BNEL:
1ba74fb8 2411 gen_op_ne(bcond, t0, t1);
923617a3 2412 MIPS_DEBUG("bnel %s, %s, " TARGET_FMT_lx,
d077b6f7 2413 regnames[rs], regnames[rt], btgt);
6af0bf9c
FB
2414 goto likely;
2415 case OPC_BGEZ:
1ba74fb8 2416 gen_op_gez(bcond, t0);
d077b6f7 2417 MIPS_DEBUG("bgez %s, " TARGET_FMT_lx, regnames[rs], btgt);
6af0bf9c
FB
2418 goto not_likely;
2419 case OPC_BGEZL:
1ba74fb8 2420 gen_op_gez(bcond, t0);
d077b6f7 2421 MIPS_DEBUG("bgezl %s, " TARGET_FMT_lx, regnames[rs], btgt);
6af0bf9c
FB
2422 goto likely;
2423 case OPC_BGEZAL:
1ba74fb8 2424 gen_op_gez(bcond, t0);
d077b6f7 2425 MIPS_DEBUG("bgezal %s, " TARGET_FMT_lx, regnames[rs], btgt);
6af0bf9c
FB
2426 blink = 31;
2427 goto not_likely;
2428 case OPC_BGEZALL:
1ba74fb8 2429 gen_op_gez(bcond, t0);
6af0bf9c 2430 blink = 31;
d077b6f7 2431 MIPS_DEBUG("bgezall %s, " TARGET_FMT_lx, regnames[rs], btgt);
6af0bf9c
FB
2432 goto likely;
2433 case OPC_BGTZ:
1ba74fb8 2434 gen_op_gtz(bcond, t0);
d077b6f7 2435 MIPS_DEBUG("bgtz %s, " TARGET_FMT_lx, regnames[rs], btgt);
6af0bf9c
FB
2436 goto not_likely;
2437 case OPC_BGTZL:
1ba74fb8 2438 gen_op_gtz(bcond, t0);
d077b6f7 2439 MIPS_DEBUG("bgtzl %s, " TARGET_FMT_lx, regnames[rs], btgt);
6af0bf9c
FB
2440 goto likely;
2441 case OPC_BLEZ:
1ba74fb8 2442 gen_op_lez(bcond, t0);
d077b6f7 2443 MIPS_DEBUG("blez %s, " TARGET_FMT_lx, regnames[rs], btgt);
6af0bf9c
FB
2444 goto not_likely;
2445 case OPC_BLEZL:
1ba74fb8 2446 gen_op_lez(bcond, t0);
d077b6f7 2447 MIPS_DEBUG("blezl %s, " TARGET_FMT_lx, regnames[rs], btgt);
6af0bf9c
FB
2448 goto likely;
2449 case OPC_BLTZ:
1ba74fb8 2450 gen_op_ltz(bcond, t0);
d077b6f7 2451 MIPS_DEBUG("bltz %s, " TARGET_FMT_lx, regnames[rs], btgt);
6af0bf9c
FB
2452 goto not_likely;
2453 case OPC_BLTZL:
1ba74fb8 2454 gen_op_ltz(bcond, t0);
d077b6f7 2455 MIPS_DEBUG("bltzl %s, " TARGET_FMT_lx, regnames[rs], btgt);
6af0bf9c
FB
2456 goto likely;
2457 case OPC_BLTZAL:
1ba74fb8 2458 gen_op_ltz(bcond, t0);
6af0bf9c 2459 blink = 31;
d077b6f7 2460 MIPS_DEBUG("bltzal %s, " TARGET_FMT_lx, regnames[rs], btgt);
6af0bf9c 2461 not_likely:
4ad40f36 2462 ctx->hflags |= MIPS_HFLAG_BC;
6af0bf9c
FB
2463 break;
2464 case OPC_BLTZALL:
1ba74fb8 2465 gen_op_ltz(bcond, t0);
6af0bf9c 2466 blink = 31;
d077b6f7 2467 MIPS_DEBUG("bltzall %s, " TARGET_FMT_lx, regnames[rs], btgt);
6af0bf9c 2468 likely:
4ad40f36 2469 ctx->hflags |= MIPS_HFLAG_BL;
6af0bf9c 2470 break;
c53f4a62
TS
2471 default:
2472 MIPS_INVAL("conditional branch/jump");
2473 generate_exception(ctx, EXCP_RI);
6c5c1e20 2474 goto out;
6af0bf9c 2475 }
6af0bf9c 2476 }
923617a3 2477 MIPS_DEBUG("enter ds: link %d cond %02x target " TARGET_FMT_lx,
d077b6f7 2478 blink, ctx->hflags, btgt);
9b9e4393 2479
d077b6f7 2480 ctx->btarget = btgt;
6af0bf9c 2481 if (blink > 0) {
1ba74fb8 2482 tcg_gen_movi_tl(cpu_gpr[blink], ctx->pc + 8);
6af0bf9c 2483 }
6c5c1e20
TS
2484
2485 out:
2486 tcg_temp_free(t0);
2487 tcg_temp_free(t1);
6af0bf9c
FB
2488}
2489
7a387fff
TS
2490/* special3 bitfield operations */
2491static void gen_bitops (DisasContext *ctx, uint32_t opc, int rt,
356265ae 2492 int rs, int lsb, int msb)
7a387fff 2493{
a7812ae4
PB
2494 TCGv t0 = tcg_temp_new();
2495 TCGv t1 = tcg_temp_new();
505ad7c2 2496 target_ulong mask;
6c5c1e20
TS
2497
2498 gen_load_gpr(t1, rs);
7a387fff
TS
2499 switch (opc) {
2500 case OPC_EXT:
2501 if (lsb + msb > 31)
2502 goto fail;
505ad7c2
AJ
2503 tcg_gen_shri_tl(t0, t1, lsb);
2504 if (msb != 31) {
2505 tcg_gen_andi_tl(t0, t0, (1 << (msb + 1)) - 1);
2506 } else {
2507 tcg_gen_ext32s_tl(t0, t0);
2508 }
7a387fff 2509 break;
c6d6dd7c 2510#if defined(TARGET_MIPS64)
7a387fff 2511 case OPC_DEXTM:
505ad7c2
AJ
2512 tcg_gen_shri_tl(t0, t1, lsb);
2513 if (msb != 31) {
2514 tcg_gen_andi_tl(t0, t0, (1ULL << (msb + 1 + 32)) - 1);
2515 }
7a387fff
TS
2516 break;
2517 case OPC_DEXTU:
505ad7c2
AJ
2518 tcg_gen_shri_tl(t0, t1, lsb + 32);
2519 tcg_gen_andi_tl(t0, t0, (1ULL << (msb + 1)) - 1);
7a387fff
TS
2520 break;
2521 case OPC_DEXT:
505ad7c2
AJ
2522 tcg_gen_shri_tl(t0, t1, lsb);
2523 tcg_gen_andi_tl(t0, t0, (1ULL << (msb + 1)) - 1);
7a387fff 2524 break;
c6d6dd7c 2525#endif
7a387fff
TS
2526 case OPC_INS:
2527 if (lsb > msb)
2528 goto fail;
505ad7c2 2529 mask = ((msb - lsb + 1 < 32) ? ((1 << (msb - lsb + 1)) - 1) : ~0) << lsb;
6c5c1e20 2530 gen_load_gpr(t0, rt);
505ad7c2
AJ
2531 tcg_gen_andi_tl(t0, t0, ~mask);
2532 tcg_gen_shli_tl(t1, t1, lsb);
2533 tcg_gen_andi_tl(t1, t1, mask);
2534 tcg_gen_or_tl(t0, t0, t1);
2535 tcg_gen_ext32s_tl(t0, t0);
7a387fff 2536 break;
c6d6dd7c 2537#if defined(TARGET_MIPS64)
7a387fff
TS
2538 case OPC_DINSM:
2539 if (lsb > msb)
2540 goto fail;
505ad7c2 2541 mask = ((msb - lsb + 1 + 32 < 64) ? ((1ULL << (msb - lsb + 1 + 32)) - 1) : ~0ULL) << lsb;
6c5c1e20 2542 gen_load_gpr(t0, rt);
505ad7c2
AJ
2543 tcg_gen_andi_tl(t0, t0, ~mask);
2544 tcg_gen_shli_tl(t1, t1, lsb);
2545 tcg_gen_andi_tl(t1, t1, mask);
2546 tcg_gen_or_tl(t0, t0, t1);
7a387fff
TS
2547 break;
2548 case OPC_DINSU:
2549 if (lsb > msb)
2550 goto fail;
505ad7c2 2551 mask = ((1ULL << (msb - lsb + 1)) - 1) << lsb;
6c5c1e20 2552 gen_load_gpr(t0, rt);
505ad7c2
AJ
2553 tcg_gen_andi_tl(t0, t0, ~mask);
2554 tcg_gen_shli_tl(t1, t1, lsb + 32);
2555 tcg_gen_andi_tl(t1, t1, mask);
2556 tcg_gen_or_tl(t0, t0, t1);
7a387fff
TS
2557 break;
2558 case OPC_DINS:
2559 if (lsb > msb)
2560 goto fail;
6c5c1e20 2561 gen_load_gpr(t0, rt);
505ad7c2
AJ
2562 mask = ((1ULL << (msb - lsb + 1)) - 1) << lsb;
2563 gen_load_gpr(t0, rt);
2564 tcg_gen_andi_tl(t0, t0, ~mask);
2565 tcg_gen_shli_tl(t1, t1, lsb);
2566 tcg_gen_andi_tl(t1, t1, mask);
2567 tcg_gen_or_tl(t0, t0, t1);
7a387fff 2568 break;
c6d6dd7c 2569#endif
7a387fff
TS
2570 default:
2571fail:
2572 MIPS_INVAL("bitops");
2573 generate_exception(ctx, EXCP_RI);
6c5c1e20
TS
2574 tcg_temp_free(t0);
2575 tcg_temp_free(t1);
7a387fff
TS
2576 return;
2577 }
6c5c1e20
TS
2578 gen_store_gpr(t0, rt);
2579 tcg_temp_free(t0);
2580 tcg_temp_free(t1);
7a387fff
TS
2581}
2582
49bcf33c
AJ
2583static void gen_bshfl (DisasContext *ctx, uint32_t op2, int rt, int rd)
2584{
3a55fa47 2585 TCGv t0;
49bcf33c 2586
3a55fa47
AJ
2587 if (rd == 0) {
2588 /* If no destination, treat it as a NOP. */
2589 MIPS_DEBUG("NOP");
2590 return;
2591 }
2592
2593 t0 = tcg_temp_new();
2594 gen_load_gpr(t0, rt);
49bcf33c
AJ
2595 switch (op2) {
2596 case OPC_WSBH:
3a55fa47
AJ
2597 {
2598 TCGv t1 = tcg_temp_new();
2599
2600 tcg_gen_shri_tl(t1, t0, 8);
2601 tcg_gen_andi_tl(t1, t1, 0x00FF00FF);
2602 tcg_gen_shli_tl(t0, t0, 8);
2603 tcg_gen_andi_tl(t0, t0, ~0x00FF00FF);
2604 tcg_gen_or_tl(t0, t0, t1);
2605 tcg_temp_free(t1);
2606 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
2607 }
49bcf33c
AJ
2608 break;
2609 case OPC_SEB:
3a55fa47 2610 tcg_gen_ext8s_tl(cpu_gpr[rd], t0);
49bcf33c
AJ
2611 break;
2612 case OPC_SEH:
3a55fa47 2613 tcg_gen_ext16s_tl(cpu_gpr[rd], t0);
49bcf33c
AJ
2614 break;
2615#if defined(TARGET_MIPS64)
2616 case OPC_DSBH:
3a55fa47
AJ
2617 {
2618 TCGv t1 = tcg_temp_new();
2619
2620 tcg_gen_shri_tl(t1, t0, 8);
2621 tcg_gen_andi_tl(t1, t1, 0x00FF00FF00FF00FFULL);
2622 tcg_gen_shli_tl(t0, t0, 8);
2623 tcg_gen_andi_tl(t0, t0, ~0x00FF00FF00FF00FFULL);
2624 tcg_gen_or_tl(cpu_gpr[rd], t0, t1);
2625 tcg_temp_free(t1);
2626 }
49bcf33c
AJ
2627 break;
2628 case OPC_DSHD:
3a55fa47
AJ
2629 {
2630 TCGv t1 = tcg_temp_new();
2631
2632 tcg_gen_shri_tl(t1, t0, 16);
2633 tcg_gen_andi_tl(t1, t1, 0x0000FFFF0000FFFFULL);
2634 tcg_gen_shli_tl(t0, t0, 16);
2635 tcg_gen_andi_tl(t0, t0, ~0x0000FFFF0000FFFFULL);
2636 tcg_gen_or_tl(t0, t0, t1);
2637 tcg_gen_shri_tl(t1, t0, 32);
2638 tcg_gen_shli_tl(t0, t0, 32);
2639 tcg_gen_or_tl(cpu_gpr[rd], t0, t1);
2640 tcg_temp_free(t1);
2641 }
49bcf33c
AJ
2642 break;
2643#endif
2644 default:
2645 MIPS_INVAL("bsfhl");
2646 generate_exception(ctx, EXCP_RI);
2647 tcg_temp_free(t0);
49bcf33c
AJ
2648 return;
2649 }
49bcf33c 2650 tcg_temp_free(t0);
49bcf33c
AJ
2651}
2652
f1aa6320 2653#ifndef CONFIG_USER_ONLY
0eaef5aa 2654/* CP0 (MMU and control) */
4f57689a
TS
2655static inline void gen_mfc0_load32 (TCGv t, target_ulong off)
2656{
a7812ae4 2657 TCGv_i32 r_tmp = tcg_temp_new_i32();
4f57689a
TS
2658
2659 tcg_gen_ld_i32(r_tmp, cpu_env, off);
2660 tcg_gen_ext_i32_tl(t, r_tmp);
a7812ae4 2661 tcg_temp_free_i32(r_tmp);
4f57689a
TS
2662}
2663
2664static inline void gen_mfc0_load64 (TCGv t, target_ulong off)
2665{
2c2435bd
TS
2666 tcg_gen_ld_tl(t, cpu_env, off);
2667 tcg_gen_ext32s_tl(t, t);
4f57689a
TS
2668}
2669
f1aa6320
TS
2670static inline void gen_mtc0_store32 (TCGv t, target_ulong off)
2671{
a7812ae4 2672 TCGv_i32 r_tmp = tcg_temp_new_i32();
f1aa6320
TS
2673
2674 tcg_gen_trunc_tl_i32(r_tmp, t);
2675 tcg_gen_st_i32(r_tmp, cpu_env, off);
a7812ae4 2676 tcg_temp_free_i32(r_tmp);
f1aa6320
TS
2677}
2678
2679static inline void gen_mtc0_store64 (TCGv t, target_ulong off)
2680{
2c2435bd
TS
2681 tcg_gen_ext32s_tl(t, t);
2682 tcg_gen_st_tl(t, cpu_env, off);
f1aa6320
TS
2683}
2684
1a3fd9c3 2685static void gen_mfc0 (CPUState *env, DisasContext *ctx, TCGv t0, int reg, int sel)
873eb012 2686{
7a387fff 2687 const char *rn = "invalid";
873eb012 2688
e189e748
TS
2689 if (sel != 0)
2690 check_insn(env, ctx, ISA_MIPS32);
2691
873eb012
TS
2692 switch (reg) {
2693 case 0:
7a387fff
TS
2694 switch (sel) {
2695 case 0:
1a3fd9c3 2696 gen_mfc0_load32(t0, offsetof(CPUState, CP0_Index));
7a387fff
TS
2697 rn = "Index";
2698 break;
2699 case 1:
7385ac0b 2700 check_insn(env, ctx, ASE_MT);
a7812ae4 2701 gen_helper_mfc0_mvpcontrol(t0);
7a387fff 2702 rn = "MVPControl";
ead9360e 2703 break;
7a387fff 2704 case 2:
7385ac0b 2705 check_insn(env, ctx, ASE_MT);
a7812ae4 2706 gen_helper_mfc0_mvpconf0(t0);
7a387fff 2707 rn = "MVPConf0";
ead9360e 2708 break;
7a387fff 2709 case 3:
7385ac0b 2710 check_insn(env, ctx, ASE_MT);
a7812ae4 2711 gen_helper_mfc0_mvpconf1(t0);
7a387fff 2712 rn = "MVPConf1";
ead9360e 2713 break;
7a387fff
TS
2714 default:
2715 goto die;
2716 }
873eb012
TS
2717 break;
2718 case 1:
7a387fff
TS
2719 switch (sel) {
2720 case 0:
a7812ae4 2721 gen_helper_mfc0_random(t0);
7a387fff 2722 rn = "Random";
2423f660 2723 break;
7a387fff 2724 case 1:
7385ac0b 2725 check_insn(env, ctx, ASE_MT);
1a3fd9c3 2726 gen_mfc0_load32(t0, offsetof(CPUState, CP0_VPEControl));
7a387fff 2727 rn = "VPEControl";
ead9360e 2728 break;
7a387fff 2729 case 2:
7385ac0b 2730 check_insn(env, ctx, ASE_MT);
1a3fd9c3 2731 gen_mfc0_load32(t0, offsetof(CPUState, CP0_VPEConf0));
7a387fff 2732 rn = "VPEConf0";
ead9360e 2733 break;
7a387fff 2734 case 3:
7385ac0b 2735 check_insn(env, ctx, ASE_MT);
1a3fd9c3 2736 gen_mfc0_load32(t0, offsetof(CPUState, CP0_VPEConf1));
7a387fff 2737 rn = "VPEConf1";
ead9360e 2738 break;
7a387fff 2739 case 4:
7385ac0b 2740 check_insn(env, ctx, ASE_MT);
1a3fd9c3 2741 gen_mfc0_load64(t0, offsetof(CPUState, CP0_YQMask));
7a387fff 2742 rn = "YQMask";
ead9360e 2743 break;
7a387fff 2744 case 5:
7385ac0b 2745 check_insn(env, ctx, ASE_MT);
1a3fd9c3 2746 gen_mfc0_load64(t0, offsetof(CPUState, CP0_VPESchedule));
7a387fff 2747 rn = "VPESchedule";
ead9360e 2748 break;
7a387fff 2749 case 6:
7385ac0b 2750 check_insn(env, ctx, ASE_MT);
1a3fd9c3 2751 gen_mfc0_load64(t0, offsetof(CPUState, CP0_VPEScheFBack));
7a387fff 2752 rn = "VPEScheFBack";
ead9360e 2753 break;
7a387fff 2754 case 7:
7385ac0b 2755 check_insn(env, ctx, ASE_MT);
1a3fd9c3 2756 gen_mfc0_load32(t0, offsetof(CPUState, CP0_VPEOpt));
7a387fff 2757 rn = "VPEOpt";
ead9360e 2758 break;
7a387fff
TS
2759 default:
2760 goto die;
2761 }
873eb012
TS
2762 break;
2763 case 2:
7a387fff
TS
2764 switch (sel) {
2765 case 0:
1a3fd9c3
TS
2766 tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUState, CP0_EntryLo0));
2767 tcg_gen_ext32s_tl(t0, t0);
2423f660
TS
2768 rn = "EntryLo0";
2769 break;
7a387fff 2770 case 1:
7385ac0b 2771 check_insn(env, ctx, ASE_MT);
a7812ae4 2772 gen_helper_mfc0_tcstatus(t0);
2423f660 2773 rn = "TCStatus";
ead9360e 2774 break;
7a387fff 2775 case 2:
7385ac0b 2776 check_insn(env, ctx, ASE_MT);
a7812ae4 2777 gen_helper_mfc0_tcbind(t0);
2423f660 2778 rn = "TCBind";
ead9360e 2779 break;
7a387fff 2780 case 3:
7385ac0b 2781 check_insn(env, ctx, ASE_MT);
a7812ae4 2782 gen_helper_mfc0_tcrestart(t0);
2423f660 2783 rn = "TCRestart";
ead9360e 2784 break;
7a387fff 2785 case 4:
7385ac0b 2786 check_insn(env, ctx, ASE_MT);
a7812ae4 2787 gen_helper_mfc0_tchalt(t0);
2423f660 2788 rn = "TCHalt";
ead9360e 2789 break;
7a387fff 2790 case 5:
7385ac0b 2791 check_insn(env, ctx, ASE_MT);
a7812ae4 2792 gen_helper_mfc0_tccontext(t0);
2423f660 2793 rn = "TCContext";
ead9360e 2794 break;
7a387fff 2795 case 6:
7385ac0b 2796 check_insn(env, ctx, ASE_MT);
a7812ae4 2797 gen_helper_mfc0_tcschedule(t0);
2423f660 2798 rn = "TCSchedule";
ead9360e 2799 break;
7a387fff 2800 case 7:
7385ac0b 2801 check_insn(env, ctx, ASE_MT);
a7812ae4 2802 gen_helper_mfc0_tcschefback(t0);
2423f660 2803 rn = "TCScheFBack";
ead9360e 2804 break;
7a387fff
TS
2805 default:
2806 goto die;
2807 }
873eb012
TS
2808 break;
2809 case 3:
7a387fff
TS
2810 switch (sel) {
2811 case 0:
1a3fd9c3
TS
2812 tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUState, CP0_EntryLo1));
2813 tcg_gen_ext32s_tl(t0, t0);
2423f660
TS
2814 rn = "EntryLo1";
2815 break;
7a387fff
TS
2816 default:
2817 goto die;
1579a72e 2818 }
873eb012
TS
2819 break;
2820 case 4:
7a387fff
TS
2821 switch (sel) {
2822 case 0:
1a3fd9c3
TS
2823 tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUState, CP0_Context));
2824 tcg_gen_ext32s_tl(t0, t0);
2423f660
TS
2825 rn = "Context";
2826 break;
7a387fff 2827 case 1:
a7812ae4 2828// gen_helper_mfc0_contextconfig(t0); /* SmartMIPS ASE */
2423f660
TS
2829 rn = "ContextConfig";
2830// break;
7a387fff
TS
2831 default:
2832 goto die;
1579a72e 2833 }
873eb012
TS
2834 break;
2835 case 5:
7a387fff
TS
2836 switch (sel) {
2837 case 0:
1a3fd9c3 2838 gen_mfc0_load32(t0, offsetof(CPUState, CP0_PageMask));
2423f660
TS
2839 rn = "PageMask";
2840 break;
7a387fff 2841 case 1:
e189e748 2842 check_insn(env, ctx, ISA_MIPS32R2);
1a3fd9c3 2843 gen_mfc0_load32(t0, offsetof(CPUState, CP0_PageGrain));
2423f660
TS
2844 rn = "PageGrain";
2845 break;
7a387fff
TS
2846 default:
2847 goto die;
1579a72e 2848 }
873eb012
TS
2849 break;
2850 case 6:
7a387fff
TS
2851 switch (sel) {
2852 case 0:
1a3fd9c3 2853 gen_mfc0_load32(t0, offsetof(CPUState, CP0_Wired));
2423f660
TS
2854 rn = "Wired";
2855 break;
7a387fff 2856 case 1:
e189e748 2857 check_insn(env, ctx, ISA_MIPS32R2);
1a3fd9c3 2858 gen_mfc0_load32(t0, offsetof(CPUState, CP0_SRSConf0));
2423f660 2859 rn = "SRSConf0";
ead9360e 2860 break;
7a387fff 2861 case 2:
e189e748 2862 check_insn(env, ctx, ISA_MIPS32R2);
1a3fd9c3 2863 gen_mfc0_load32(t0, offsetof(CPUState, CP0_SRSConf1));
2423f660 2864 rn = "SRSConf1";
ead9360e 2865 break;
7a387fff 2866 case 3:
e189e748 2867 check_insn(env, ctx, ISA_MIPS32R2);
1a3fd9c3 2868 gen_mfc0_load32(t0, offsetof(CPUState, CP0_SRSConf2));
2423f660 2869 rn = "SRSConf2";
ead9360e 2870 break;
7a387fff 2871 case 4:
e189e748 2872 check_insn(env, ctx, ISA_MIPS32R2);
1a3fd9c3 2873 gen_mfc0_load32(t0, offsetof(CPUState, CP0_SRSConf3));
2423f660 2874 rn = "SRSConf3";
ead9360e 2875 break;
7a387fff 2876 case 5:
e189e748 2877 check_insn(env, ctx, ISA_MIPS32R2);
1a3fd9c3 2878 gen_mfc0_load32(t0, offsetof(CPUState, CP0_SRSConf4));
2423f660 2879 rn = "SRSConf4";
ead9360e 2880 break;
7a387fff
TS
2881 default:
2882 goto die;
1579a72e 2883 }
873eb012 2884 break;
8c0fdd85 2885 case 7:
7a387fff
TS
2886 switch (sel) {
2887 case 0:
e189e748 2888 check_insn(env, ctx, ISA_MIPS32R2);
1a3fd9c3 2889 gen_mfc0_load32(t0, offsetof(CPUState, CP0_HWREna));
2423f660
TS
2890 rn = "HWREna";
2891 break;
7a387fff
TS
2892 default:
2893 goto die;
1579a72e 2894 }
8c0fdd85 2895 break;
873eb012 2896 case 8:
7a387fff
TS
2897 switch (sel) {
2898 case 0:
1a3fd9c3
TS
2899 tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUState, CP0_BadVAddr));
2900 tcg_gen_ext32s_tl(t0, t0);
f0b3f3ae 2901 rn = "BadVAddr";
2423f660 2902 break;
7a387fff
TS
2903 default:
2904 goto die;
2905 }
873eb012
TS
2906 break;
2907 case 9:
7a387fff
TS
2908 switch (sel) {
2909 case 0:
2e70f6ef
PB
2910 /* Mark as an IO operation because we read the time. */
2911 if (use_icount)
2912 gen_io_start();
a7812ae4 2913 gen_helper_mfc0_count(t0);
2e70f6ef
PB
2914 if (use_icount) {
2915 gen_io_end();
2916 ctx->bstate = BS_STOP;
2917 }
2423f660
TS
2918 rn = "Count";
2919 break;
2920 /* 6,7 are implementation dependent */
7a387fff
TS
2921 default:
2922 goto die;
2423f660 2923 }
873eb012
TS
2924 break;
2925 case 10:
7a387fff
TS
2926 switch (sel) {
2927 case 0:
1a3fd9c3
TS
2928 tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUState, CP0_EntryHi));
2929 tcg_gen_ext32s_tl(t0, t0);
2423f660
TS
2930 rn = "EntryHi";
2931 break;
7a387fff
TS
2932 default:
2933 goto die;
1579a72e 2934 }
873eb012
TS
2935 break;
2936 case 11:
7a387fff
TS
2937 switch (sel) {
2938 case 0:
1a3fd9c3 2939 gen_mfc0_load32(t0, offsetof(CPUState, CP0_Compare));
2423f660
TS
2940 rn = "Compare";
2941 break;
2942 /* 6,7 are implementation dependent */
7a387fff
TS
2943 default:
2944 goto die;
2423f660 2945 }
873eb012
TS
2946 break;
2947 case 12:
7a387fff
TS
2948 switch (sel) {
2949 case 0:
1a3fd9c3 2950 gen_mfc0_load32(t0, offsetof(CPUState, CP0_Status));
2423f660
TS
2951 rn = "Status";
2952 break;
7a387fff 2953 case 1:
e189e748 2954 check_insn(env, ctx, ISA_MIPS32R2);
1a3fd9c3 2955 gen_mfc0_load32(t0, offsetof(CPUState, CP0_IntCtl));
2423f660
TS
2956 rn = "IntCtl";
2957 break;
7a387fff 2958 case 2:
e189e748 2959 check_insn(env, ctx, ISA_MIPS32R2);
1a3fd9c3 2960 gen_mfc0_load32(t0, offsetof(CPUState, CP0_SRSCtl));
2423f660
TS
2961 rn = "SRSCtl";
2962 break;
7a387fff 2963 case 3:
e189e748 2964 check_insn(env, ctx, ISA_MIPS32R2);
1a3fd9c3 2965 gen_mfc0_load32(t0, offsetof(CPUState, CP0_SRSMap));
2423f660 2966 rn = "SRSMap";
fd88b6ab 2967 break;
7a387fff
TS
2968 default:
2969 goto die;
2970 }
873eb012
TS
2971 break;
2972 case 13:
7a387fff
TS
2973 switch (sel) {
2974 case 0:
1a3fd9c3 2975 gen_mfc0_load32(t0, offsetof(CPUState, CP0_Cause));
2423f660
TS
2976 rn = "Cause";
2977 break;
7a387fff
TS
2978 default:
2979 goto die;
2980 }
873eb012
TS
2981 break;
2982 case 14:
7a387fff
TS
2983 switch (sel) {
2984 case 0:
1a3fd9c3
TS
2985 tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUState, CP0_EPC));
2986 tcg_gen_ext32s_tl(t0, t0);
2423f660
TS
2987 rn = "EPC";
2988 break;
7a387fff
TS
2989 default:
2990 goto die;
1579a72e 2991 }
873eb012
TS
2992 break;
2993 case 15:
7a387fff
TS
2994 switch (sel) {
2995 case 0:
1a3fd9c3 2996 gen_mfc0_load32(t0, offsetof(CPUState, CP0_PRid));
2423f660
TS
2997 rn = "PRid";
2998 break;
7a387fff 2999 case 1:
e189e748 3000 check_insn(env, ctx, ISA_MIPS32R2);
1a3fd9c3 3001 gen_mfc0_load32(t0, offsetof(CPUState, CP0_EBase));
2423f660
TS
3002 rn = "EBase";
3003 break;
7a387fff
TS
3004 default:
3005 goto die;
3006 }
873eb012
TS
3007 break;
3008 case 16:
3009 switch (sel) {
3010 case 0:
1a3fd9c3 3011 gen_mfc0_load32(t0, offsetof(CPUState, CP0_Config0));
873eb012
TS
3012 rn = "Config";
3013 break;
3014 case 1:
1a3fd9c3 3015 gen_mfc0_load32(t0, offsetof(CPUState, CP0_Config1));
873eb012
TS
3016 rn = "Config1";
3017 break;
7a387fff 3018 case 2:
1a3fd9c3 3019 gen_mfc0_load32(t0, offsetof(CPUState, CP0_Config2));
7a387fff
TS
3020 rn = "Config2";
3021 break;
3022 case 3:
1a3fd9c3 3023 gen_mfc0_load32(t0, offsetof(CPUState, CP0_Config3));
7a387fff
TS
3024 rn = "Config3";
3025 break;
e397ee33
TS
3026 /* 4,5 are reserved */
3027 /* 6,7 are implementation dependent */
3028 case 6:
1a3fd9c3 3029 gen_mfc0_load32(t0, offsetof(CPUState, CP0_Config6));
e397ee33
TS
3030 rn = "Config6";
3031 break;
3032 case 7:
1a3fd9c3 3033 gen_mfc0_load32(t0, offsetof(CPUState, CP0_Config7));
e397ee33
TS
3034 rn = "Config7";
3035 break;
873eb012 3036 default:
873eb012
TS
3037 goto die;
3038 }
3039 break;
3040 case 17:
7a387fff
TS
3041 switch (sel) {
3042 case 0:
a7812ae4 3043 gen_helper_mfc0_lladdr(t0);
2423f660
TS
3044 rn = "LLAddr";
3045 break;
7a387fff
TS
3046 default:
3047 goto die;
3048 }
873eb012
TS
3049 break;
3050 case 18:
7a387fff 3051 switch (sel) {
fd88b6ab 3052 case 0 ... 7:
a7812ae4 3053 gen_helper_1i(mfc0_watchlo, t0, sel);
2423f660
TS
3054 rn = "WatchLo";
3055 break;
7a387fff
TS
3056 default:
3057 goto die;
3058 }
873eb012
TS
3059 break;
3060 case 19:
7a387fff 3061 switch (sel) {
fd88b6ab 3062 case 0 ...7:
a7812ae4 3063 gen_helper_1i(mfc0_watchhi, t0, sel);
2423f660
TS
3064 rn = "WatchHi";
3065 break;
7a387fff
TS
3066 default:
3067 goto die;
3068 }
873eb012 3069 break;
8c0fdd85 3070 case 20:
7a387fff
TS
3071 switch (sel) {
3072 case 0:
d26bc211 3073#if defined(TARGET_MIPS64)
e189e748 3074 check_insn(env, ctx, ISA_MIPS3);
1a3fd9c3
TS
3075 tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUState, CP0_XContext));
3076 tcg_gen_ext32s_tl(t0, t0);
2423f660
TS
3077 rn = "XContext";
3078 break;
703eaf37 3079#endif
7a387fff
TS
3080 default:
3081 goto die;
3082 }
8c0fdd85
TS
3083 break;
3084 case 21:
7a387fff
TS
3085 /* Officially reserved, but sel 0 is used for R1x000 framemask */
3086 switch (sel) {
3087 case 0:
1a3fd9c3 3088 gen_mfc0_load32(t0, offsetof(CPUState, CP0_Framemask));
2423f660
TS
3089 rn = "Framemask";
3090 break;
7a387fff
TS
3091 default:
3092 goto die;
3093 }
8c0fdd85
TS
3094 break;
3095 case 22:
da80682b 3096 tcg_gen_movi_tl(t0, 0); /* unimplemented */
2423f660
TS
3097 rn = "'Diagnostic"; /* implementation dependent */
3098 break;
873eb012 3099 case 23:
7a387fff
TS
3100 switch (sel) {
3101 case 0:
a7812ae4 3102 gen_helper_mfc0_debug(t0); /* EJTAG support */
2423f660
TS
3103 rn = "Debug";
3104 break;
7a387fff 3105 case 1:
a7812ae4 3106// gen_helper_mfc0_tracecontrol(t0); /* PDtrace support */
2423f660
TS
3107 rn = "TraceControl";
3108// break;
7a387fff 3109 case 2:
a7812ae4 3110// gen_helper_mfc0_tracecontrol2(t0); /* PDtrace support */
2423f660
TS
3111 rn = "TraceControl2";
3112// break;
7a387fff 3113 case 3:
a7812ae4 3114// gen_helper_mfc0_usertracedata(t0); /* PDtrace support */
2423f660
TS
3115 rn = "UserTraceData";
3116// break;
7a387fff 3117 case 4:
a7812ae4 3118// gen_helper_mfc0_tracebpc(t0); /* PDtrace support */
2423f660
TS
3119 rn = "TraceBPC";
3120// break;
7a387fff
TS
3121 default:
3122 goto die;
3123 }
873eb012
TS
3124 break;
3125 case 24:
7a387fff
TS
3126 switch (sel) {
3127 case 0:
f0b3f3ae 3128 /* EJTAG support */
1a3fd9c3
TS
3129 tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUState, CP0_DEPC));
3130 tcg_gen_ext32s_tl(t0, t0);
2423f660
TS
3131 rn = "DEPC";
3132 break;
7a387fff
TS
3133 default:
3134 goto die;
3135 }
873eb012 3136 break;
8c0fdd85 3137 case 25:
7a387fff
TS
3138 switch (sel) {
3139 case 0:
1a3fd9c3 3140 gen_mfc0_load32(t0, offsetof(CPUState, CP0_Performance0));
2423f660 3141 rn = "Performance0";
7a387fff
TS
3142 break;
3143 case 1:
a7812ae4 3144// gen_helper_mfc0_performance1(t0);
2423f660
TS
3145 rn = "Performance1";
3146// break;
7a387fff 3147 case 2:
a7812ae4 3148// gen_helper_mfc0_performance2(t0);
2423f660
TS
3149 rn = "Performance2";
3150// break;
7a387fff 3151 case 3:
a7812ae4 3152// gen_helper_mfc0_performance3(t0);
2423f660
TS
3153 rn = "Performance3";
3154// break;
7a387fff 3155 case 4:
a7812ae4 3156// gen_helper_mfc0_performance4(t0);
2423f660
TS
3157 rn = "Performance4";
3158// break;
7a387fff 3159 case 5:
a7812ae4 3160// gen_helper_mfc0_performance5(t0);
2423f660
TS
3161 rn = "Performance5";
3162// break;
7a387fff 3163 case 6:
a7812ae4 3164// gen_helper_mfc0_performance6(t0);
2423f660
TS
3165 rn = "Performance6";
3166// break;
7a387fff 3167 case 7:
a7812ae4 3168// gen_helper_mfc0_performance7(t0);
2423f660
TS
3169 rn = "Performance7";
3170// break;
7a387fff
TS
3171 default:
3172 goto die;
3173 }
8c0fdd85
TS
3174 break;
3175 case 26:
da80682b
AJ
3176 tcg_gen_movi_tl(t0, 0); /* unimplemented */
3177 rn = "ECC";
3178 break;
8c0fdd85 3179 case 27:
7a387fff 3180 switch (sel) {
7a387fff 3181 case 0 ... 3:
da80682b 3182 tcg_gen_movi_tl(t0, 0); /* unimplemented */
2423f660
TS
3183 rn = "CacheErr";
3184 break;
7a387fff
TS
3185 default:
3186 goto die;
3187 }
8c0fdd85 3188 break;
873eb012
TS
3189 case 28:
3190 switch (sel) {
3191 case 0:
7a387fff
TS
3192 case 2:
3193 case 4:
3194 case 6:
1a3fd9c3 3195 gen_mfc0_load32(t0, offsetof(CPUState, CP0_TagLo));
873eb012
TS
3196 rn = "TagLo";
3197 break;
3198 case 1:
7a387fff
TS
3199 case 3:
3200 case 5:
3201 case 7:
1a3fd9c3 3202 gen_mfc0_load32(t0, offsetof(CPUState, CP0_DataLo));
873eb012
TS
3203 rn = "DataLo";
3204 break;
3205 default:
873eb012
TS
3206 goto die;
3207 }
3208 break;
8c0fdd85 3209 case 29:
7a387fff
TS
3210 switch (sel) {
3211 case 0:
3212 case 2:
3213 case 4:
3214 case 6:
1a3fd9c3 3215 gen_mfc0_load32(t0, offsetof(CPUState, CP0_TagHi));
7a387fff
TS
3216 rn = "TagHi";
3217 break;
3218 case 1:
3219 case 3:
3220 case 5:
3221 case 7:
1a3fd9c3 3222 gen_mfc0_load32(t0, offsetof(CPUState, CP0_DataHi));
7a387fff
TS
3223 rn = "DataHi";
3224 break;
3225 default:
3226 goto die;
3227 }
8c0fdd85 3228 break;
873eb012 3229 case 30:
7a387fff
TS
3230 switch (sel) {
3231 case 0:
1a3fd9c3
TS
3232 tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUState, CP0_ErrorEPC));
3233 tcg_gen_ext32s_tl(t0, t0);
2423f660
TS
3234 rn = "ErrorEPC";
3235 break;
7a387fff
TS
3236 default:
3237 goto die;
3238 }
873eb012
TS
3239 break;
3240 case 31:
7a387fff
TS
3241 switch (sel) {
3242 case 0:
f0b3f3ae 3243 /* EJTAG support */
1a3fd9c3 3244 gen_mfc0_load32(t0, offsetof(CPUState, CP0_DESAVE));
2423f660
TS
3245 rn = "DESAVE";
3246 break;
7a387fff
TS
3247 default:
3248 goto die;
3249 }
873eb012
TS
3250 break;
3251 default:
873eb012
TS
3252 goto die;
3253 }
d12d51d5 3254 LOG_DISAS("mfc0 %s (reg %d sel %d)\n", rn, reg, sel);
873eb012
TS
3255 return;
3256
3257die:
d12d51d5 3258 LOG_DISAS("mfc0 %s (reg %d sel %d)\n", rn, reg, sel);
873eb012
TS
3259 generate_exception(ctx, EXCP_RI);
3260}
3261
1a3fd9c3 3262static void gen_mtc0 (CPUState *env, DisasContext *ctx, TCGv t0, int reg, int sel)
8c0fdd85 3263{
7a387fff
TS
3264 const char *rn = "invalid";
3265
e189e748
TS
3266 if (sel != 0)
3267 check_insn(env, ctx, ISA_MIPS32);
3268
2e70f6ef
PB
3269 if (use_icount)
3270 gen_io_start();
3271
8c0fdd85
TS
3272 switch (reg) {
3273 case 0:
7a387fff
TS
3274 switch (sel) {
3275 case 0:
a7812ae4 3276 gen_helper_mtc0_index(t0);
7a387fff
TS
3277 rn = "Index";
3278 break;
3279 case 1:
7385ac0b 3280 check_insn(env, ctx, ASE_MT);
a7812ae4 3281 gen_helper_mtc0_mvpcontrol(t0);
7a387fff 3282 rn = "MVPControl";
ead9360e 3283 break;
7a387fff 3284 case 2:
7385ac0b 3285 check_insn(env, ctx, ASE_MT);
ead9360e 3286 /* ignored */
7a387fff 3287 rn = "MVPConf0";
ead9360e 3288 break;
7a387fff 3289 case 3:
7385ac0b 3290 check_insn(env, ctx, ASE_MT);
ead9360e 3291 /* ignored */
7a387fff 3292 rn = "MVPConf1";
ead9360e 3293 break;
7a387fff
TS
3294 default:
3295 goto die;
3296 }
8c0fdd85
TS
3297 break;
3298 case 1:
7a387fff
TS
3299 switch (sel) {
3300 case 0:
2423f660 3301 /* ignored */
7a387fff 3302 rn = "Random";
2423f660 3303 break;
7a387fff 3304 case 1:
7385ac0b 3305 check_insn(env, ctx, ASE_MT);
a7812ae4 3306 gen_helper_mtc0_vpecontrol(t0);
7a387fff 3307 rn = "VPEControl";
ead9360e 3308 break;
7a387fff 3309 case 2:
7385ac0b 3310 check_insn(env, ctx, ASE_MT);
a7812ae4 3311 gen_helper_mtc0_vpeconf0(t0);
7a387fff 3312 rn = "VPEConf0";
ead9360e 3313 break;
7a387fff 3314 case 3:
7385ac0b 3315 check_insn(env, ctx, ASE_MT);
a7812ae4 3316 gen_helper_mtc0_vpeconf1(t0);
7a387fff 3317 rn = "VPEConf1";
ead9360e 3318 break;
7a387fff 3319 case 4:
7385ac0b 3320 check_insn(env, ctx, ASE_MT);
a7812ae4 3321 gen_helper_mtc0_yqmask(t0);
7a387fff 3322 rn = "YQMask";
ead9360e 3323 break;
7a387fff 3324 case 5:
7385ac0b 3325 check_insn(env, ctx, ASE_MT);
1a3fd9c3 3326 gen_mtc0_store64(t0, offsetof(CPUState, CP0_VPESchedule));
7a387fff 3327 rn = "VPESchedule";
ead9360e 3328 break;
7a387fff 3329 case 6:
7385ac0b 3330 check_insn(env, ctx, ASE_MT);
1a3fd9c3 3331 gen_mtc0_store64(t0, offsetof(CPUState, CP0_VPEScheFBack));
7a387fff 3332 rn = "VPEScheFBack";
ead9360e 3333 break;
7a387fff 3334 case 7:
7385ac0b 3335 check_insn(env, ctx, ASE_MT);
a7812ae4 3336 gen_helper_mtc0_vpeopt(t0);
7a387fff 3337 rn = "VPEOpt";
ead9360e 3338 break;
7a387fff
TS
3339 default:
3340 goto die;
3341 }
8c0fdd85
TS
3342 break;
3343 case 2:
7a387fff
TS
3344 switch (sel) {
3345 case 0:
a7812ae4 3346 gen_helper_mtc0_entrylo0(t0);
2423f660
TS
3347 rn = "EntryLo0";
3348 break;
7a387fff 3349 case 1:
7385ac0b 3350 check_insn(env, ctx, ASE_MT);
a7812ae4 3351 gen_helper_mtc0_tcstatus(t0);
2423f660 3352 rn = "TCStatus";
ead9360e 3353 break;
7a387fff 3354 case 2:
7385ac0b 3355 check_insn(env, ctx, ASE_MT);
a7812ae4 3356 gen_helper_mtc0_tcbind(t0);
2423f660 3357 rn = "TCBind";
ead9360e 3358 break;
7a387fff 3359 case 3:
7385ac0b 3360 check_insn(env, ctx, ASE_MT);
a7812ae4 3361 gen_helper_mtc0_tcrestart(t0);
2423f660 3362 rn = "TCRestart";
ead9360e 3363 break;
7a387fff 3364 case 4:
7385ac0b 3365 check_insn(env, ctx, ASE_MT);
a7812ae4 3366 gen_helper_mtc0_tchalt(t0);
2423f660 3367 rn = "TCHalt";
ead9360e 3368 break;
7a387fff 3369 case 5:
7385ac0b 3370 check_insn(env, ctx, ASE_MT);
a7812ae4 3371 gen_helper_mtc0_tccontext(t0);
2423f660 3372 rn = "TCContext";
ead9360e 3373 break;
7a387fff 3374 case 6:
7385ac0b 3375 check_insn(env, ctx, ASE_MT);
a7812ae4 3376 gen_helper_mtc0_tcschedule(t0);
2423f660 3377 rn = "TCSchedule";
ead9360e 3378 break;
7a387fff 3379 case 7:
7385ac0b 3380 check_insn(env, ctx, ASE_MT);
a7812ae4 3381 gen_helper_mtc0_tcschefback(t0);
2423f660 3382 rn = "TCScheFBack";
ead9360e 3383 break;
7a387fff
TS
3384 default:
3385 goto die;
3386 }
8c0fdd85
TS
3387 break;
3388 case 3:
7a387fff
TS
3389 switch (sel) {
3390 case 0:
a7812ae4 3391 gen_helper_mtc0_entrylo1(t0);
2423f660
TS
3392 rn = "EntryLo1";
3393 break;
7a387fff
TS
3394 default:
3395 goto die;
876d4b07 3396 }
8c0fdd85
TS
3397 break;
3398 case 4:
7a387fff
TS
3399 switch (sel) {
3400 case 0:
a7812ae4 3401 gen_helper_mtc0_context(t0);
2423f660
TS
3402 rn = "Context";
3403 break;
7a387fff 3404 case 1:
a7812ae4 3405// gen_helper_mtc0_contextconfig(t0); /* SmartMIPS ASE */
2423f660
TS
3406 rn = "ContextConfig";
3407// break;
7a387fff
TS
3408 default:
3409 goto die;
876d4b07 3410 }
8c0fdd85
TS
3411 break;
3412 case 5:
7a387fff
TS
3413 switch (sel) {
3414 case 0:
a7812ae4 3415 gen_helper_mtc0_pagemask(t0);
2423f660
TS
3416 rn = "PageMask";
3417 break;
7a387fff 3418 case 1:
e189e748 3419 check_insn(env, ctx, ISA_MIPS32R2);
a7812ae4 3420 gen_helper_mtc0_pagegrain(t0);
2423f660
TS
3421 rn = "PageGrain";
3422 break;
7a387fff
TS
3423 default:
3424 goto die;
876d4b07 3425 }
8c0fdd85
TS
3426 break;
3427 case 6:
7a387fff
TS
3428 switch (sel) {
3429 case 0:
a7812ae4 3430 gen_helper_mtc0_wired(t0);
2423f660
TS
3431 rn = "Wired";
3432 break;
7a387fff 3433 case 1:
e189e748 3434 check_insn(env, ctx, ISA_MIPS32R2);
a7812ae4 3435 gen_helper_mtc0_srsconf0(t0);
2423f660 3436 rn = "SRSConf0";
ead9360e 3437 break;
7a387fff 3438 case 2:
e189e748 3439 check_insn(env, ctx, ISA_MIPS32R2);
a7812ae4 3440 gen_helper_mtc0_srsconf1(t0);
2423f660 3441 rn = "SRSConf1";
ead9360e 3442 break;
7a387fff 3443 case 3:
e189e748 3444 check_insn(env, ctx, ISA_MIPS32R2);
a7812ae4 3445 gen_helper_mtc0_srsconf2(t0);
2423f660 3446 rn = "SRSConf2";
ead9360e 3447 break;
7a387fff 3448 case 4:
e189e748 3449 check_insn(env, ctx, ISA_MIPS32R2);
a7812ae4 3450 gen_helper_mtc0_srsconf3(t0);
2423f660 3451 rn = "SRSConf3";
ead9360e 3452 break;
7a387fff 3453 case 5:
e189e748 3454 check_insn(env, ctx, ISA_MIPS32R2);
a7812ae4 3455 gen_helper_mtc0_srsconf4(t0);
2423f660 3456 rn = "SRSConf4";
ead9360e 3457 break;
7a387fff
TS
3458 default:
3459 goto die;
876d4b07 3460 }
8c0fdd85
TS
3461 break;
3462 case 7:
7a387fff
TS
3463 switch (sel) {
3464 case 0:
e189e748 3465 check_insn(env, ctx, ISA_MIPS32R2);
a7812ae4 3466 gen_helper_mtc0_hwrena(t0);
2423f660
TS
3467 rn = "HWREna";
3468 break;
7a387fff
TS
3469 default:
3470 goto die;
876d4b07 3471 }
8c0fdd85
TS
3472 break;
3473 case 8:
7a387fff 3474 /* ignored */
f0b3f3ae 3475 rn = "BadVAddr";
8c0fdd85
TS
3476 break;
3477 case 9:
7a387fff
TS
3478 switch (sel) {
3479 case 0:
a7812ae4 3480 gen_helper_mtc0_count(t0);
2423f660
TS
3481 rn = "Count";
3482 break;
876d4b07 3483 /* 6,7 are implementation dependent */
7a387fff
TS
3484 default:
3485 goto die;
876d4b07
TS
3486 }
3487 /* Stop translation as we may have switched the execution mode */
3488 ctx->bstate = BS_STOP;
8c0fdd85
TS
3489 break;
3490 case 10:
7a387fff
TS
3491 switch (sel) {
3492 case 0:
a7812ae4 3493 gen_helper_mtc0_entryhi(t0);
2423f660
TS
3494 rn = "EntryHi";
3495 break;
7a387fff
TS
3496 default:
3497 goto die;
876d4b07 3498 }
8c0fdd85
TS
3499 break;
3500 case 11:
7a387fff
TS
3501 switch (sel) {
3502 case 0:
a7812ae4 3503 gen_helper_mtc0_compare(t0);
2423f660
TS
3504 rn = "Compare";
3505 break;
3506 /* 6,7 are implementation dependent */
7a387fff
TS
3507 default:
3508 goto die;
876d4b07 3509 }
de9a95f0
AJ
3510 /* Stop translation as we may have switched the execution mode */
3511 ctx->bstate = BS_STOP;
8c0fdd85
TS
3512 break;
3513 case 12:
7a387fff
TS
3514 switch (sel) {
3515 case 0:
a7812ae4 3516 gen_helper_mtc0_status(t0);
8487327a
TS
3517 /* BS_STOP isn't good enough here, hflags may have changed. */
3518 gen_save_pc(ctx->pc + 4);
3519 ctx->bstate = BS_EXCP;
2423f660
TS
3520 rn = "Status";
3521 break;
7a387fff 3522 case 1:
e189e748 3523 check_insn(env, ctx, ISA_MIPS32R2);
a7812ae4 3524 gen_helper_mtc0_intctl(t0);
8487327a
TS
3525 /* Stop translation as we may have switched the execution mode */
3526 ctx->bstate = BS_STOP;
2423f660
TS
3527 rn = "IntCtl";
3528 break;
7a387fff 3529 case 2:
e189e748 3530 check_insn(env, ctx, ISA_MIPS32R2);
a7812ae4 3531 gen_helper_mtc0_srsctl(t0);
8487327a
TS
3532 /* Stop translation as we may have switched the execution mode */
3533 ctx->bstate = BS_STOP;
2423f660
TS
3534 rn = "SRSCtl";
3535 break;
7a387fff 3536 case 3:
e189e748 3537 check_insn(env, ctx, ISA_MIPS32R2);
1a3fd9c3 3538 gen_mtc0_store32(t0, offsetof(CPUState, CP0_SRSMap));
8487327a
TS
3539 /* Stop translation as we may have switched the execution mode */
3540 ctx->bstate = BS_STOP;
2423f660 3541 rn = "SRSMap";
fd88b6ab 3542 break;
7a387fff
TS
3543 default:
3544 goto die;
876d4b07 3545 }
8c0fdd85
TS
3546 break;
3547 case 13:
7a387fff
TS
3548 switch (sel) {
3549 case 0:
a7812ae4 3550 gen_helper_mtc0_cause(t0);
2423f660
TS
3551 rn = "Cause";
3552 break;
7a387fff
TS
3553 default:
3554 goto die;
876d4b07
TS
3555 }
3556 /* Stop translation as we may have switched the execution mode */
3557 ctx->bstate = BS_STOP;
8c0fdd85
TS
3558 break;
3559 case 14:
7a387fff
TS
3560 switch (sel) {
3561 case 0:
1a3fd9c3 3562 gen_mtc0_store64(t0, offsetof(CPUState, CP0_EPC));
2423f660
TS
3563 rn = "EPC";
3564 break;
7a387fff
TS
3565 default:
3566 goto die;
876d4b07 3567 }
8c0fdd85
TS
3568 break;
3569 case 15:
7a387fff
TS
3570 switch (sel) {
3571 case 0:
2423f660
TS
3572 /* ignored */
3573 rn = "PRid";
3574 break;
7a387fff 3575 case 1:
e189e748 3576 check_insn(env, ctx, ISA_MIPS32R2);
a7812ae4 3577 gen_helper_mtc0_ebase(t0);
2423f660
TS
3578 rn = "EBase";
3579 break;
7a387fff
TS
3580 default:
3581 goto die;
1579a72e 3582 }
8c0fdd85
TS
3583 break;
3584 case 16:
3585 switch (sel) {
3586 case 0:
a7812ae4 3587 gen_helper_mtc0_config0(t0);
7a387fff 3588 rn = "Config";
2423f660
TS
3589 /* Stop translation as we may have switched the execution mode */
3590 ctx->bstate = BS_STOP;
7a387fff
TS
3591 break;
3592 case 1:
e397ee33 3593 /* ignored, read only */
7a387fff
TS
3594 rn = "Config1";
3595 break;
3596 case 2:
a7812ae4 3597 gen_helper_mtc0_config2(t0);
7a387fff 3598 rn = "Config2";
2423f660
TS
3599 /* Stop translation as we may have switched the execution mode */
3600 ctx->bstate = BS_STOP;
8c0fdd85 3601 break;
7a387fff 3602 case 3:
e397ee33 3603 /* ignored, read only */
7a387fff
TS
3604 rn = "Config3";
3605 break;
e397ee33
TS
3606 /* 4,5 are reserved */
3607 /* 6,7 are implementation dependent */
3608 case 6:
3609 /* ignored */
3610 rn = "Config6";
3611 break;
3612 case 7:
3613 /* ignored */
3614 rn = "Config7";
3615 break;
8c0fdd85
TS
3616 default:
3617 rn = "Invalid config selector";
3618 goto die;
3619 }
3620 break;
3621 case 17:
7a387fff
TS
3622 switch (sel) {
3623 case 0:
2423f660
TS
3624 /* ignored */
3625 rn = "LLAddr";
3626 break;
7a387fff
TS
3627 default:
3628 goto die;
3629 }
8c0fdd85
TS
3630 break;
3631 case 18:
7a387fff 3632 switch (sel) {
fd88b6ab 3633 case 0 ... 7:
a7812ae4 3634 gen_helper_1i(mtc0_watchlo, t0, sel);
2423f660
TS
3635 rn = "WatchLo";
3636 break;
7a387fff
TS
3637 default:
3638 goto die;
3639 }
8c0fdd85
TS
3640 break;
3641 case 19:
7a387fff 3642 switch (sel) {
fd88b6ab 3643 case 0 ... 7:
a7812ae4 3644 gen_helper_1i(mtc0_watchhi, t0, sel);
2423f660
TS
3645 rn = "WatchHi";
3646 break;
7a387fff
TS
3647 default:
3648 goto die;
3649 }
8c0fdd85
TS
3650 break;
3651 case 20:
7a387fff
TS
3652 switch (sel) {
3653 case 0:
d26bc211 3654#if defined(TARGET_MIPS64)
e189e748 3655 check_insn(env, ctx, ISA_MIPS3);
a7812ae4 3656 gen_helper_mtc0_xcontext(t0);
2423f660
TS
3657 rn = "XContext";
3658 break;
703eaf37 3659#endif
7a387fff
TS
3660 default:
3661 goto die;
3662 }
8c0fdd85
TS
3663 break;
3664 case 21:
7a387fff
TS
3665 /* Officially reserved, but sel 0 is used for R1x000 framemask */
3666 switch (sel) {
3667 case 0:
a7812ae4 3668 gen_helper_mtc0_framemask(t0);
2423f660
TS
3669 rn = "Framemask";
3670 break;
7a387fff
TS
3671 default:
3672 goto die;
3673 }
3674 break;
8c0fdd85 3675 case 22:
7a387fff
TS
3676 /* ignored */
3677 rn = "Diagnostic"; /* implementation dependent */
2423f660 3678 break;
8c0fdd85 3679 case 23:
7a387fff
TS
3680 switch (sel) {
3681 case 0:
a7812ae4 3682 gen_helper_mtc0_debug(t0); /* EJTAG support */
8487327a
TS
3683 /* BS_STOP isn't good enough here, hflags may have changed. */
3684 gen_save_pc(ctx->pc + 4);
3685 ctx->bstate = BS_EXCP;
2423f660
TS
3686 rn = "Debug";
3687 break;
7a387fff 3688 case 1:
a7812ae4 3689// gen_helper_mtc0_tracecontrol(t0); /* PDtrace support */
2423f660 3690 rn = "TraceControl";
8487327a
TS
3691 /* Stop translation as we may have switched the execution mode */
3692 ctx->bstate = BS_STOP;
2423f660 3693// break;
7a387fff 3694 case 2:
a7812ae4 3695// gen_helper_mtc0_tracecontrol2(t0); /* PDtrace support */
2423f660 3696 rn = "TraceControl2";
8487327a
TS
3697 /* Stop translation as we may have switched the execution mode */
3698 ctx->bstate = BS_STOP;
2423f660 3699// break;
7a387fff 3700 case 3:
8487327a
TS
3701 /* Stop translation as we may have switched the execution mode */
3702 ctx->bstate = BS_STOP;
a7812ae4 3703// gen_helper_mtc0_usertracedata(t0); /* PDtrace support */
2423f660 3704 rn = "UserTraceData";
8487327a
TS
3705 /* Stop translation as we may have switched the execution mode */
3706 ctx->bstate = BS_STOP;
2423f660 3707// break;
7a387fff 3708 case 4:
a7812ae4 3709// gen_helper_mtc0_tracebpc(t0); /* PDtrace support */
8487327a
TS
3710 /* Stop translation as we may have switched the execution mode */
3711 ctx->bstate = BS_STOP;
2423f660
TS
3712 rn = "TraceBPC";
3713// break;
7a387fff
TS
3714 default:
3715 goto die;
3716 }
8c0fdd85
TS
3717 break;
3718 case 24:
7a387fff
TS
3719 switch (sel) {
3720 case 0:
f1aa6320 3721 /* EJTAG support */
1a3fd9c3 3722 gen_mtc0_store64(t0, offsetof(CPUState, CP0_DEPC));
2423f660
TS
3723 rn = "DEPC";
3724 break;
7a387fff
TS
3725 default:
3726 goto die;
3727 }
8c0fdd85
TS
3728 break;
3729 case 25:
7a387fff
TS
3730 switch (sel) {
3731 case 0:
a7812ae4 3732 gen_helper_mtc0_performance0(t0);
2423f660
TS
3733 rn = "Performance0";
3734 break;
7a387fff 3735 case 1:
a7812ae4 3736// gen_helper_mtc0_performance1(t0);
2423f660
TS
3737 rn = "Performance1";
3738// break;
7a387fff 3739 case 2:
a7812ae4 3740// gen_helper_mtc0_performance2(t0);
2423f660
TS
3741 rn = "Performance2";
3742// break;
7a387fff 3743 case 3:
a7812ae4 3744// gen_helper_mtc0_performance3(t0);
2423f660
TS
3745 rn = "Performance3";
3746// break;
7a387fff 3747 case 4:
a7812ae4 3748// gen_helper_mtc0_performance4(t0);
2423f660
TS
3749 rn = "Performance4";
3750// break;
7a387fff 3751 case 5:
a7812ae4 3752// gen_helper_mtc0_performance5(t0);
2423f660
TS
3753 rn = "Performance5";
3754// break;
7a387fff 3755 case 6:
a7812ae4 3756// gen_helper_mtc0_performance6(t0);
2423f660
TS
3757 rn = "Performance6";
3758// break;
7a387fff 3759 case 7:
a7812ae4 3760// gen_helper_mtc0_performance7(t0);
2423f660
TS
3761 rn = "Performance7";
3762// break;
7a387fff
TS
3763 default:
3764 goto die;
3765 }
8c0fdd85
TS
3766 break;
3767 case 26:
2423f660 3768 /* ignored */
8c0fdd85 3769 rn = "ECC";
2423f660 3770 break;
8c0fdd85 3771 case 27:
7a387fff
TS
3772 switch (sel) {
3773 case 0 ... 3:
2423f660
TS
3774 /* ignored */
3775 rn = "CacheErr";
3776 break;
7a387fff
TS
3777 default:
3778 goto die;
3779 }
8c0fdd85
TS
3780 break;
3781 case 28:
3782 switch (sel) {
3783 case 0:
7a387fff
TS
3784 case 2:
3785 case 4:
3786 case 6:
a7812ae4 3787 gen_helper_mtc0_taglo(t0);
8c0fdd85
TS
3788 rn = "TagLo";
3789 break;
7a387fff
TS
3790 case 1:
3791 case 3:
3792 case 5:
3793 case 7:
a7812ae4 3794 gen_helper_mtc0_datalo(t0);
7a387fff
TS
3795 rn = "DataLo";
3796 break;
8c0fdd85 3797 default:
8c0fdd85
TS
3798 goto die;
3799 }
3800 break;
3801 case 29:
7a387fff
TS
3802 switch (sel) {
3803 case 0:
3804 case 2:
3805 case 4:
3806 case 6:
a7812ae4 3807 gen_helper_mtc0_taghi(t0);
7a387fff
TS
3808 rn = "TagHi";
3809 break;
3810 case 1:
3811 case 3:
3812 case 5:
3813 case 7:
a7812ae4 3814 gen_helper_mtc0_datahi(t0);
7a387fff
TS
3815 rn = "DataHi";
3816 break;
3817 default:
3818 rn = "invalid sel";
3819 goto die;
3820 }
8c0fdd85
TS
3821 break;
3822 case 30:
7a387fff
TS
3823 switch (sel) {
3824 case 0:
1a3fd9c3 3825 gen_mtc0_store64(t0, offsetof(CPUState, CP0_ErrorEPC));
2423f660
TS
3826 rn = "ErrorEPC";
3827 break;
7a387fff
TS
3828 default:
3829 goto die;
3830 }
8c0fdd85
TS
3831 break;
3832 case 31:
7a387fff
TS
3833 switch (sel) {
3834 case 0:
f1aa6320 3835 /* EJTAG support */
1a3fd9c3 3836 gen_mtc0_store32(t0, offsetof(CPUState, CP0_DESAVE));
2423f660
TS
3837 rn = "DESAVE";
3838 break;
7a387fff
TS
3839 default:
3840 goto die;
3841 }
2423f660
TS
3842 /* Stop translation as we may have switched the execution mode */
3843 ctx->bstate = BS_STOP;
8c0fdd85
TS
3844 break;
3845 default:
8c0fdd85
TS
3846 goto die;
3847 }
d12d51d5 3848 LOG_DISAS("mtc0 %s (reg %d sel %d)\n", rn, reg, sel);
bf20dc07 3849 /* For simplicity assume that all writes can cause interrupts. */
2e70f6ef
PB
3850 if (use_icount) {
3851 gen_io_end();
3852 ctx->bstate = BS_STOP;
3853 }
8c0fdd85
TS
3854 return;
3855
3856die:
d12d51d5 3857 LOG_DISAS("mtc0 %s (reg %d sel %d)\n", rn, reg, sel);
8c0fdd85
TS
3858 generate_exception(ctx, EXCP_RI);
3859}
3860
d26bc211 3861#if defined(TARGET_MIPS64)
1a3fd9c3 3862static void gen_dmfc0 (CPUState *env, DisasContext *ctx, TCGv t0, int reg, int sel)
9c2149c8
TS
3863{
3864 const char *rn = "invalid";
3865
e189e748
TS
3866 if (sel != 0)
3867 check_insn(env, ctx, ISA_MIPS64);
3868
9c2149c8
TS
3869 switch (reg) {
3870 case 0:
3871 switch (sel) {
3872 case 0:
1a3fd9c3 3873 gen_mfc0_load32(t0, offsetof(CPUState, CP0_Index));
9c2149c8
TS
3874 rn = "Index";
3875 break;
3876 case 1:
7385ac0b 3877 check_insn(env, ctx, ASE_MT);
a7812ae4 3878 gen_helper_mfc0_mvpcontrol(t0);
9c2149c8 3879 rn = "MVPControl";
ead9360e 3880 break;
9c2149c8 3881 case 2:
7385ac0b 3882 check_insn(env, ctx, ASE_MT);
a7812ae4 3883 gen_helper_mfc0_mvpconf0(t0);
9c2149c8 3884 rn = "MVPConf0";
ead9360e 3885 break;
9c2149c8 3886 case 3:
7385ac0b 3887 check_insn(env, ctx, ASE_MT);
a7812ae4 3888 gen_helper_mfc0_mvpconf1(t0);
9c2149c8 3889 rn = "MVPConf1";
ead9360e 3890 break;
9c2149c8
TS
3891 default:
3892 goto die;
3893 }
3894 break;
3895 case 1:
3896 switch (sel) {
3897 case 0:
a7812ae4 3898 gen_helper_mfc0_random(t0);
9c2149c8 3899 rn = "Random";
2423f660 3900 break;
9c2149c8 3901 case 1:
7385ac0b 3902 check_insn(env, ctx, ASE_MT);
1a3fd9c3 3903 gen_mfc0_load32(t0, offsetof(CPUState, CP0_VPEControl));
9c2149c8 3904 rn = "VPEControl";
ead9360e 3905 break;
9c2149c8 3906 case 2:
7385ac0b 3907 check_insn(env, ctx, ASE_MT);
1a3fd9c3 3908 gen_mfc0_load32(t0, offsetof(CPUState, CP0_VPEConf0));
9c2149c8 3909 rn = "VPEConf0";
ead9360e 3910 break;
9c2149c8 3911 case 3:
7385ac0b 3912 check_insn(env, ctx, ASE_MT);
1a3fd9c3 3913 gen_mfc0_load32(t0, offsetof(CPUState, CP0_VPEConf1));
9c2149c8 3914 rn = "VPEConf1";
ead9360e 3915 break;
9c2149c8 3916 case 4:
7385ac0b 3917 check_insn(env, ctx, ASE_MT);
1a3fd9c3 3918 tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUState, CP0_YQMask));
9c2149c8 3919 rn = "YQMask";
ead9360e 3920 break;
9c2149c8 3921 case 5:
7385ac0b 3922 check_insn(env, ctx, ASE_MT);
1a3fd9c3 3923 tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUState, CP0_VPESchedule));
9c2149c8 3924 rn = "VPESchedule";
ead9360e 3925 break;
9c2149c8 3926 case 6:
7385ac0b 3927 check_insn(env, ctx, ASE_MT);
1a3fd9c3 3928 tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUState, CP0_VPEScheFBack));
9c2149c8 3929 rn = "VPEScheFBack";
ead9360e 3930 break;
9c2149c8 3931 case 7:
7385ac0b 3932 check_insn(env, ctx, ASE_MT);
1a3fd9c3 3933 gen_mfc0_load32(t0, offsetof(CPUState, CP0_VPEOpt));
9c2149c8 3934 rn = "VPEOpt";
ead9360e 3935 break;
9c2149c8
TS
3936 default:
3937 goto die;
3938 }
3939 break;
3940 case 2:
3941 switch (sel) {
3942 case 0:
1a3fd9c3 3943 tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUState, CP0_EntryLo0));
2423f660
TS
3944 rn = "EntryLo0";
3945 break;
9c2149c8 3946 case 1:
7385ac0b 3947 check_insn(env, ctx, ASE_MT);
a7812ae4 3948 gen_helper_mfc0_tcstatus(t0);
2423f660 3949 rn = "TCStatus";
ead9360e 3950 break;
9c2149c8 3951 case 2:
7385ac0b 3952 check_insn(env, ctx, ASE_MT);
a7812ae4 3953 gen_helper_mfc0_tcbind(t0);
2423f660 3954 rn = "TCBind";
ead9360e 3955 break;
9c2149c8 3956 case 3:
7385ac0b 3957 check_insn(env, ctx, ASE_MT);
a7812ae4 3958 gen_helper_dmfc0_tcrestart(t0);
2423f660 3959 rn = "TCRestart";
ead9360e 3960 break;
9c2149c8 3961 case 4:
7385ac0b 3962 check_insn(env, ctx, ASE_MT);
a7812ae4 3963 gen_helper_dmfc0_tchalt(t0);
2423f660 3964 rn = "TCHalt";
ead9360e 3965 break;
9c2149c8 3966 case 5:
7385ac0b 3967 check_insn(env, ctx, ASE_MT);
a7812ae4 3968 gen_helper_dmfc0_tccontext(t0);
2423f660 3969 rn = "TCContext";
ead9360e 3970 break;
9c2149c8 3971 case 6:
7385ac0b 3972 check_insn(env, ctx, ASE_MT);
a7812ae4 3973 gen_helper_dmfc0_tcschedule(t0);
2423f660 3974 rn = "TCSchedule";
ead9360e 3975 break;
9c2149c8 3976 case 7:
7385ac0b 3977 check_insn(env, ctx, ASE_MT);
a7812ae4 3978 gen_helper_dmfc0_tcschefback(t0);
2423f660 3979 rn = "TCScheFBack";
ead9360e 3980 break;
9c2149c8
TS
3981 default:
3982 goto die;
3983 }
3984 break;
3985 case 3:
3986 switch (sel) {
3987 case 0:
1a3fd9c3 3988 tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUState, CP0_EntryLo1));
2423f660
TS
3989 rn = "EntryLo1";
3990 break;
9c2149c8
TS
3991 default:
3992 goto die;
1579a72e 3993 }
9c2149c8
TS
3994 break;
3995 case 4:
3996 switch (sel) {
3997 case 0:
1a3fd9c3 3998 tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUState, CP0_Context));
2423f660
TS
3999 rn = "Context";
4000 break;
9c2149c8 4001 case 1:
a7812ae4 4002// gen_helper_dmfc0_contextconfig(t0); /* SmartMIPS ASE */
2423f660
TS
4003 rn = "ContextConfig";
4004// break;
9c2149c8
TS
4005 default:
4006 goto die;
876d4b07 4007 }
9c2149c8
TS
4008 break;
4009 case 5:
4010 switch (sel) {
4011 case 0:
1a3fd9c3 4012 gen_mfc0_load32(t0, offsetof(CPUState, CP0_PageMask));
2423f660
TS
4013 rn = "PageMask";
4014 break;
9c2149c8 4015 case 1:
e189e748 4016 check_insn(env, ctx, ISA_MIPS32R2);
1a3fd9c3 4017 gen_mfc0_load32(t0, offsetof(CPUState, CP0_PageGrain));
2423f660
TS
4018 rn = "PageGrain";
4019 break;
9c2149c8
TS
4020 default:
4021 goto die;
876d4b07 4022 }
9c2149c8
TS
4023 break;
4024 case 6:
4025 switch (sel) {
4026 case 0:
1a3fd9c3 4027 gen_mfc0_load32(t0, offsetof(CPUState, CP0_Wired));
2423f660
TS
4028 rn = "Wired";
4029 break;
9c2149c8 4030 case 1:
e189e748 4031 check_insn(env, ctx, ISA_MIPS32R2);
1a3fd9c3 4032 gen_mfc0_load32(t0, offsetof(CPUState, CP0_SRSConf0));
2423f660 4033 rn = "SRSConf0";
ead9360e 4034 break;
9c2149c8 4035 case 2:
e189e748 4036 check_insn(env, ctx, ISA_MIPS32R2);
1a3fd9c3 4037 gen_mfc0_load32(t0, offsetof(CPUState, CP0_SRSConf1));
2423f660 4038 rn = "SRSConf1";
ead9360e 4039 break;
9c2149c8 4040 case 3:
e189e748 4041 check_insn(env, ctx, ISA_MIPS32R2);
1a3fd9c3 4042 gen_mfc0_load32(t0, offsetof(CPUState, CP0_SRSConf2));
2423f660 4043 rn = "SRSConf2";
ead9360e 4044 break;
9c2149c8 4045 case 4:
e189e748 4046 check_insn(env, ctx, ISA_MIPS32R2);
1a3fd9c3 4047 gen_mfc0_load32(t0, offsetof(CPUState, CP0_SRSConf3));
2423f660 4048 rn = "SRSConf3";
ead9360e 4049 break;
9c2149c8 4050 case 5:
e189e748 4051 check_insn(env, ctx, ISA_MIPS32R2);
1a3fd9c3 4052 gen_mfc0_load32(t0, offsetof(CPUState, CP0_SRSConf4));
2423f660 4053 rn = "SRSConf4";
ead9360e 4054 break;
9c2149c8
TS
4055 default:
4056 goto die;
876d4b07 4057 }
9c2149c8
TS
4058 break;
4059 case 7:
4060 switch (sel) {
4061 case 0:
e189e748 4062 check_insn(env, ctx, ISA_MIPS32R2);
1a3fd9c3 4063 gen_mfc0_load32(t0, offsetof(CPUState, CP0_HWREna));
2423f660
TS
4064 rn = "HWREna";
4065 break;
9c2149c8
TS
4066 default:
4067 goto die;
876d4b07 4068 }
9c2149c8
TS
4069 break;
4070 case 8:
4071 switch (sel) {
4072 case 0:
1a3fd9c3 4073 tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUState, CP0_BadVAddr));
f0b3f3ae 4074 rn = "BadVAddr";
2423f660 4075 break;
9c2149c8
TS
4076 default:
4077 goto die;
876d4b07 4078 }
9c2149c8
TS
4079 break;
4080 case 9:
4081 switch (sel) {
4082 case 0:
2e70f6ef
PB
4083 /* Mark as an IO operation because we read the time. */
4084 if (use_icount)
4085 gen_io_start();
a7812ae4 4086 gen_helper_mfc0_count(t0);
2e70f6ef
PB
4087 if (use_icount) {
4088 gen_io_end();
4089 ctx->bstate = BS_STOP;
4090 }
2423f660
TS
4091 rn = "Count";
4092 break;
4093 /* 6,7 are implementation dependent */
9c2149c8
TS
4094 default:
4095 goto die;
876d4b07 4096 }
9c2149c8
TS
4097 break;
4098 case 10:
4099 switch (sel) {
4100 case 0:
1a3fd9c3 4101 tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUState, CP0_EntryHi));
2423f660
TS
4102 rn = "EntryHi";
4103 break;
9c2149c8
TS
4104 default:
4105 goto die;
876d4b07 4106 }
9c2149c8
TS
4107 break;
4108 case 11:
4109 switch (sel) {
4110 case 0:
1a3fd9c3 4111 gen_mfc0_load32(t0, offsetof(CPUState, CP0_Compare));
2423f660
TS
4112 rn = "Compare";
4113 break;
876d4b07 4114 /* 6,7 are implementation dependent */
9c2149c8
TS
4115 default:
4116 goto die;
876d4b07 4117 }
9c2149c8
TS
4118 break;
4119 case 12:
4120 switch (sel) {
4121 case 0:
1a3fd9c3 4122 gen_mfc0_load32(t0, offsetof(CPUState, CP0_Status));
2423f660
TS
4123 rn = "Status";
4124 break;
9c2149c8 4125 case 1:
e189e748 4126 check_insn(env, ctx, ISA_MIPS32R2);
1a3fd9c3 4127 gen_mfc0_load32(t0, offsetof(CPUState, CP0_IntCtl));
2423f660
TS
4128 rn = "IntCtl";
4129 break;
9c2149c8 4130 case 2:
e189e748 4131 check_insn(env, ctx, ISA_MIPS32R2);
1a3fd9c3 4132 gen_mfc0_load32(t0, offsetof(CPUState, CP0_SRSCtl));
2423f660
TS
4133 rn = "SRSCtl";
4134 break;
9c2149c8 4135 case 3:
e189e748 4136 check_insn(env, ctx, ISA_MIPS32R2);
1a3fd9c3 4137 gen_mfc0_load32(t0, offsetof(CPUState, CP0_SRSMap));
2423f660
TS
4138 rn = "SRSMap";
4139 break;
9c2149c8
TS
4140 default:
4141 goto die;
876d4b07 4142 }
9c2149c8
TS
4143 break;
4144 case 13:
4145 switch (sel) {
4146 case 0:
1a3fd9c3 4147 gen_mfc0_load32(t0, offsetof(CPUState, CP0_Cause));
2423f660
TS
4148 rn = "Cause";
4149 break;
9c2149c8
TS
4150 default:
4151 goto die;
876d4b07 4152 }
9c2149c8
TS
4153 break;
4154 case 14:
4155 switch (sel) {
4156 case 0:
1a3fd9c3 4157 tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUState, CP0_EPC));
2423f660
TS
4158 rn = "EPC";
4159 break;
9c2149c8
TS
4160 default:
4161 goto die;
876d4b07 4162 }
9c2149c8
TS
4163 break;
4164 case 15:
4165 switch (sel) {
4166 case 0:
1a3fd9c3 4167 gen_mfc0_load32(t0, offsetof(CPUState, CP0_PRid));
2423f660
TS
4168 rn = "PRid";
4169 break;
9c2149c8 4170 case 1:
e189e748 4171 check_insn(env, ctx, ISA_MIPS32R2);
1a3fd9c3 4172 gen_mfc0_load32(t0, offsetof(CPUState, CP0_EBase));
2423f660
TS
4173 rn = "EBase";
4174 break;
9c2149c8
TS
4175 default:
4176 goto die;
876d4b07 4177 }
9c2149c8
TS
4178 break;
4179 case 16:
4180 switch (sel) {
4181 case 0:
1a3fd9c3 4182 gen_mfc0_load32(t0, offsetof(CPUState, CP0_Config0));
9c2149c8
TS
4183 rn = "Config";
4184 break;
4185 case 1:
1a3fd9c3 4186 gen_mfc0_load32(t0, offsetof(CPUState, CP0_Config1));
9c2149c8
TS
4187 rn = "Config1";
4188 break;
4189 case 2:
1a3fd9c3 4190 gen_mfc0_load32(t0, offsetof(CPUState, CP0_Config2));
9c2149c8
TS
4191 rn = "Config2";
4192 break;
4193 case 3:
1a3fd9c3 4194 gen_mfc0_load32(t0, offsetof(CPUState, CP0_Config3));
9c2149c8
TS
4195 rn = "Config3";
4196 break;
4197 /* 6,7 are implementation dependent */
f0b3f3ae 4198 case 6:
1a3fd9c3 4199 gen_mfc0_load32(t0, offsetof(CPUState, CP0_Config6));
f0b3f3ae
TS
4200 rn = "Config6";
4201 break;
4202 case 7:
1a3fd9c3 4203 gen_mfc0_load32(t0, offsetof(CPUState, CP0_Config7));
f0b3f3ae
TS
4204 rn = "Config7";
4205 break;
9c2149c8
TS
4206 default:
4207 goto die;
4208 }
4209 break;
4210 case 17:
4211 switch (sel) {
4212 case 0:
a7812ae4 4213 gen_helper_dmfc0_lladdr(t0);
2423f660
TS
4214 rn = "LLAddr";
4215 break;
9c2149c8
TS
4216 default:
4217 goto die;
4218 }
4219 break;
4220 case 18:
4221 switch (sel) {
fd88b6ab 4222 case 0 ... 7:
a7812ae4 4223 gen_helper_1i(dmfc0_watchlo, t0, sel);
2423f660
TS
4224 rn = "WatchLo";
4225 break;
9c2149c8
TS
4226 default:
4227 goto die;
4228 }
4229 break;
4230 case 19:
4231 switch (sel) {
fd88b6ab 4232 case 0 ... 7:
a7812ae4 4233 gen_helper_1i(mfc0_watchhi, t0, sel);
2423f660
TS
4234 rn = "WatchHi";
4235 break;
9c2149c8
TS
4236 default:
4237 goto die;
4238 }
4239 break;
4240 case 20:
4241 switch (sel) {
4242 case 0:
e189e748 4243 check_insn(env, ctx, ISA_MIPS3);
1a3fd9c3 4244 tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUState, CP0_XContext));
2423f660
TS
4245 rn = "XContext";
4246 break;
9c2149c8
TS
4247 default:
4248 goto die;
4249 }
4250 break;
4251 case 21:
4252 /* Officially reserved, but sel 0 is used for R1x000 framemask */
4253 switch (sel) {
4254 case 0:
1a3fd9c3 4255 gen_mfc0_load32(t0, offsetof(CPUState, CP0_Framemask));
2423f660
TS
4256 rn = "Framemask";
4257 break;
9c2149c8
TS
4258 default:
4259 goto die;
4260 }
4261 break;
4262 case 22:
da80682b 4263 tcg_gen_movi_tl(t0, 0); /* unimplemented */
2423f660
TS
4264 rn = "'Diagnostic"; /* implementation dependent */
4265 break;
9c2149c8
TS
4266 case 23:
4267 switch (sel) {
4268 case 0:
a7812ae4 4269 gen_helper_mfc0_debug(t0); /* EJTAG support */
2423f660
TS
4270 rn = "Debug";
4271 break;
9c2149c8 4272 case 1:
a7812ae4 4273// gen_helper_dmfc0_tracecontrol(t0); /* PDtrace support */
2423f660
TS
4274 rn = "TraceControl";
4275// break;
9c2149c8 4276 case 2:
a7812ae4 4277// gen_helper_dmfc0_tracecontrol2(t0); /* PDtrace support */
2423f660
TS
4278 rn = "TraceControl2";
4279// break;
9c2149c8 4280 case 3:
a7812ae4 4281// gen_helper_dmfc0_usertracedata(t0); /* PDtrace support */
2423f660
TS
4282 rn = "UserTraceData";
4283// break;
9c2149c8 4284 case 4:
a7812ae4 4285// gen_helper_dmfc0_tracebpc(t0); /* PDtrace support */
2423f660
TS
4286 rn = "TraceBPC";
4287// break;
9c2149c8
TS
4288 default:
4289 goto die;
4290 }
4291 break;
4292 case 24:
4293 switch (sel) {
4294 case 0:
f0b3f3ae 4295 /* EJTAG support */
1a3fd9c3 4296 tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUState, CP0_DEPC));
2423f660
TS
4297 rn = "DEPC";
4298 break;
9c2149c8
TS
4299 default:
4300 goto die;
4301 }
4302 break;
4303 case 25:
4304 switch (sel) {
4305 case 0:
1a3fd9c3 4306 gen_mfc0_load32(t0, offsetof(CPUState, CP0_Performance0));
2423f660 4307 rn = "Performance0";
9c2149c8
TS
4308 break;
4309 case 1:
a7812ae4 4310// gen_helper_dmfc0_performance1(t0);
2423f660
TS
4311 rn = "Performance1";
4312// break;
9c2149c8 4313 case 2:
a7812ae4 4314// gen_helper_dmfc0_performance2(t0);
2423f660
TS
4315 rn = "Performance2";
4316// break;
9c2149c8 4317 case 3:
a7812ae4 4318// gen_helper_dmfc0_performance3(t0);
2423f660
TS
4319 rn = "Performance3";
4320// break;
9c2149c8 4321 case 4:
a7812ae4 4322// gen_helper_dmfc0_performance4(t0);
2423f660
TS
4323 rn = "Performance4";
4324// break;
9c2149c8 4325 case 5:
a7812ae4 4326// gen_helper_dmfc0_performance5(t0);
2423f660
TS
4327 rn = "Performance5";
4328// break;
9c2149c8 4329 case 6:
a7812ae4 4330// gen_helper_dmfc0_performance6(t0);
2423f660
TS
4331 rn = "Performance6";
4332// break;
9c2149c8 4333 case 7:
a7812ae4 4334// gen_helper_dmfc0_performance7(t0);
2423f660
TS
4335 rn = "Performance7";
4336// break;
9c2149c8
TS
4337 default:
4338 goto die;
4339 }
4340 break;
4341 case 26:
da80682b
AJ
4342 tcg_gen_movi_tl(t0, 0); /* unimplemented */
4343 rn = "ECC";
4344 break;
9c2149c8
TS
4345 case 27:
4346 switch (sel) {
4347 /* ignored */
4348 case 0 ... 3:
da80682b 4349 tcg_gen_movi_tl(t0, 0); /* unimplemented */
2423f660
TS
4350 rn = "CacheErr";
4351 break;
9c2149c8
TS
4352 default:
4353 goto die;
4354 }
4355 break;
4356 case 28:
4357 switch (sel) {
4358 case 0:
4359 case 2:
4360 case 4:
4361 case 6:
1a3fd9c3 4362 gen_mfc0_load32(t0, offsetof(CPUState, CP0_TagLo));
9c2149c8
TS
4363 rn = "TagLo";
4364 break;
4365 case 1:
4366 case 3:
4367 case 5:
4368 case 7:
1a3fd9c3 4369 gen_mfc0_load32(t0, offsetof(CPUState, CP0_DataLo));
9c2149c8
TS
4370 rn = "DataLo";
4371 break;
4372 default:
4373 goto die;
4374 }
4375 break;
4376 case 29:
4377 switch (sel) {
4378 case 0:
4379 case 2:
4380 case 4:
4381 case 6:
1a3fd9c3 4382 gen_mfc0_load32(t0, offsetof(CPUState, CP0_TagHi));
9c2149c8
TS
4383 rn = "TagHi";
4384 break;
4385 case 1:
4386 case 3:
4387 case 5:
4388 case 7:
1a3fd9c3 4389 gen_mfc0_load32(t0, offsetof(CPUState, CP0_DataHi));
9c2149c8
TS
4390 rn = "DataHi";
4391 break;
4392 default:
4393 goto die;
4394 }
4395 break;
4396 case 30:
4397 switch (sel) {
4398 case 0:
1a3fd9c3 4399 tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUState, CP0_ErrorEPC));
2423f660
TS
4400 rn = "ErrorEPC";
4401 break;
9c2149c8
TS
4402 default:
4403 goto die;
4404 }
4405 break;
4406 case 31:
4407 switch (sel) {
4408 case 0:
f0b3f3ae 4409 /* EJTAG support */
1a3fd9c3 4410 gen_mfc0_load32(t0, offsetof(CPUState, CP0_DESAVE));
2423f660
TS
4411 rn = "DESAVE";
4412 break;
9c2149c8
TS
4413 default:
4414 goto die;
4415 }
4416 break;
4417 default:
876d4b07 4418 goto die;
9c2149c8 4419 }
d12d51d5 4420 LOG_DISAS("dmfc0 %s (reg %d sel %d)\n", rn, reg, sel);
9c2149c8
TS
4421 return;
4422
4423die:
d12d51d5 4424 LOG_DISAS("dmfc0 %s (reg %d sel %d)\n", rn, reg, sel);
9c2149c8
TS
4425 generate_exception(ctx, EXCP_RI);
4426}
4427
1a3fd9c3 4428static void gen_dmtc0 (CPUState *env, DisasContext *ctx, TCGv t0, int reg, int sel)
9c2149c8
TS
4429{
4430 const char *rn = "invalid";
4431
e189e748
TS
4432 if (sel != 0)
4433 check_insn(env, ctx, ISA_MIPS64);
4434
2e70f6ef
PB
4435 if (use_icount)
4436 gen_io_start();
4437
9c2149c8
TS
4438 switch (reg) {
4439 case 0:
4440 switch (sel) {
4441 case 0:
a7812ae4 4442 gen_helper_mtc0_index(t0);
9c2149c8
TS
4443 rn = "Index";
4444 break;
4445 case 1:
7385ac0b 4446 check_insn(env, ctx, ASE_MT);
a7812ae4 4447 gen_helper_mtc0_mvpcontrol(t0);
9c2149c8 4448 rn = "MVPControl";
ead9360e 4449 break;
9c2149c8 4450 case 2:
7385ac0b 4451 check_insn(env, ctx, ASE_MT);
ead9360e 4452 /* ignored */
9c2149c8 4453 rn = "MVPConf0";
ead9360e 4454 break;
9c2149c8 4455 case 3:
7385ac0b 4456 check_insn(env, ctx, ASE_MT);
ead9360e 4457 /* ignored */
9c2149c8 4458 rn = "MVPConf1";
ead9360e 4459 break;
9c2149c8
TS
4460 default:
4461 goto die;
4462 }
4463 break;
4464 case 1:
4465 switch (sel) {
4466 case 0:
2423f660 4467 /* ignored */
9c2149c8 4468 rn = "Random";
2423f660 4469 break;
9c2149c8 4470 case 1:
7385ac0b 4471 check_insn(env, ctx, ASE_MT);
a7812ae4 4472 gen_helper_mtc0_vpecontrol(t0);
9c2149c8 4473 rn = "VPEControl";
ead9360e 4474 break;
9c2149c8 4475 case 2:
7385ac0b 4476 check_insn(env, ctx, ASE_MT);
a7812ae4 4477 gen_helper_mtc0_vpeconf0(t0);
9c2149c8 4478 rn = "VPEConf0";
ead9360e 4479 break;
9c2149c8 4480 case 3:
7385ac0b 4481 check_insn(env, ctx, ASE_MT);
a7812ae4 4482 gen_helper_mtc0_vpeconf1(t0);
9c2149c8 4483 rn = "VPEConf1";
ead9360e 4484 break;
9c2149c8 4485 case 4:
7385ac0b 4486 check_insn(env, ctx, ASE_MT);
a7812ae4 4487 gen_helper_mtc0_yqmask(t0);
9c2149c8 4488 rn = "YQMask";
ead9360e 4489 break;
9c2149c8 4490 case 5:
7385ac0b 4491 check_insn(env, ctx, ASE_MT);
1a3fd9c3 4492 tcg_gen_st_tl(t0, cpu_env, offsetof(CPUState, CP0_VPESchedule));
9c2149c8 4493 rn = "VPESchedule";
ead9360e 4494 break;
9c2149c8 4495 case 6:
7385ac0b 4496 check_insn(env, ctx, ASE_MT);
1a3fd9c3 4497 tcg_gen_st_tl(t0, cpu_env, offsetof(CPUState, CP0_VPEScheFBack));
9c2149c8 4498 rn = "VPEScheFBack";
ead9360e 4499 break;
9c2149c8 4500 case 7:
7385ac0b 4501 check_insn(env, ctx, ASE_MT);
a7812ae4 4502 gen_helper_mtc0_vpeopt(t0);
9c2149c8 4503 rn = "VPEOpt";
ead9360e 4504 break;
9c2149c8
TS
4505 default:
4506 goto die;
4507 }
4508 break;
4509 case 2:
4510 switch (sel) {
4511 case 0:
a7812ae4 4512 gen_helper_mtc0_entrylo0(t0);
2423f660
TS
4513 rn = "EntryLo0";
4514 break;
9c2149c8 4515 case 1:
7385ac0b 4516 check_insn(env, ctx, ASE_MT);
a7812ae4 4517 gen_helper_mtc0_tcstatus(t0);
2423f660 4518 rn = "TCStatus";
ead9360e 4519 break;
9c2149c8 4520 case 2:
7385ac0b 4521 check_insn(env, ctx, ASE_MT);
a7812ae4 4522 gen_helper_mtc0_tcbind(t0);
2423f660 4523 rn = "TCBind";
ead9360e 4524 break;
9c2149c8 4525 case 3:
7385ac0b 4526 check_insn(env, ctx, ASE_MT);
a7812ae4 4527 gen_helper_mtc0_tcrestart(t0);
2423f660 4528 rn = "TCRestart";
ead9360e 4529 break;
9c2149c8 4530 case 4:
7385ac0b 4531 check_insn(env, ctx, ASE_MT);
a7812ae4 4532 gen_helper_mtc0_tchalt(t0);
2423f660 4533 rn = "TCHalt";
ead9360e 4534 break;
9c2149c8 4535 case 5:
7385ac0b 4536 check_insn(env, ctx, ASE_MT);
a7812ae4 4537 gen_helper_mtc0_tccontext(t0);
2423f660 4538 rn = "TCContext";
ead9360e 4539 break;
9c2149c8 4540 case 6:
7385ac0b 4541 check_insn(env, ctx, ASE_MT);
a7812ae4 4542 gen_helper_mtc0_tcschedule(t0);
2423f660 4543 rn = "TCSchedule";
ead9360e 4544 break;
9c2149c8 4545 case 7:
7385ac0b 4546 check_insn(env, ctx, ASE_MT);
a7812ae4 4547 gen_helper_mtc0_tcschefback(t0);
2423f660 4548 rn = "TCScheFBack";
ead9360e 4549 break;
9c2149c8
TS
4550 default:
4551 goto die;
4552 }
4553 break;
4554 case 3:
4555 switch (sel) {
4556 case 0:
a7812ae4 4557 gen_helper_mtc0_entrylo1(t0);
2423f660
TS
4558 rn = "EntryLo1";
4559 break;
9c2149c8
TS
4560 default:
4561 goto die;
876d4b07 4562 }
9c2149c8
TS
4563 break;
4564 case 4:
4565 switch (sel) {
4566 case 0:
a7812ae4 4567 gen_helper_mtc0_context(t0);
2423f660
TS
4568 rn = "Context";
4569 break;
9c2149c8 4570 case 1:
a7812ae4 4571// gen_helper_mtc0_contextconfig(t0); /* SmartMIPS ASE */
2423f660
TS
4572 rn = "ContextConfig";
4573// break;
9c2149c8
TS
4574 default:
4575 goto die;
876d4b07 4576 }
9c2149c8
TS
4577 break;
4578 case 5:
4579 switch (sel) {
4580 case 0:
a7812ae4 4581 gen_helper_mtc0_pagemask(t0);
2423f660
TS
4582 rn = "PageMask";
4583 break;
9c2149c8 4584 case 1:
e189e748 4585 check_insn(env, ctx, ISA_MIPS32R2);
a7812ae4 4586 gen_helper_mtc0_pagegrain(t0);
2423f660
TS
4587 rn = "PageGrain";
4588 break;
9c2149c8
TS
4589 default:
4590 goto die;
876d4b07 4591 }
9c2149c8
TS
4592 break;
4593 case 6:
4594 switch (sel) {
4595 case 0:
a7812ae4 4596 gen_helper_mtc0_wired(t0);
2423f660
TS
4597 rn = "Wired";
4598 break;
9c2149c8 4599 case 1:
e189e748 4600 check_insn(env, ctx, ISA_MIPS32R2);
a7812ae4 4601 gen_helper_mtc0_srsconf0(t0);
2423f660 4602 rn = "SRSConf0";
ead9360e 4603 break;
9c2149c8 4604 case 2:
e189e748 4605 check_insn(env, ctx, ISA_MIPS32R2);
a7812ae4 4606 gen_helper_mtc0_srsconf1(t0);
2423f660 4607 rn = "SRSConf1";
ead9360e 4608 break;
9c2149c8 4609 case 3:
e189e748 4610 check_insn(env, ctx, ISA_MIPS32R2);
a7812ae4 4611 gen_helper_mtc0_srsconf2(t0);
2423f660 4612 rn = "SRSConf2";
ead9360e 4613 break;
9c2149c8 4614 case 4:
e189e748 4615 check_insn(env, ctx, ISA_MIPS32R2);
a7812ae4 4616 gen_helper_mtc0_srsconf3(t0);
2423f660 4617 rn = "SRSConf3";
ead9360e 4618 break;
9c2149c8 4619 case 5:
e189e748 4620 check_insn(env, ctx, ISA_MIPS32R2);
a7812ae4 4621 gen_helper_mtc0_srsconf4(t0);
2423f660 4622 rn = "SRSConf4";
ead9360e 4623 break;
9c2149c8
TS
4624 default:
4625 goto die;
876d4b07 4626 }
9c2149c8
TS
4627 break;
4628 case 7:
4629 switch (sel) {
4630 case 0:
e189e748 4631 check_insn(env, ctx, ISA_MIPS32R2);
a7812ae4 4632 gen_helper_mtc0_hwrena(t0);
2423f660
TS
4633 rn = "HWREna";
4634 break;
9c2149c8
TS
4635 default:
4636 goto die;
876d4b07 4637 }
9c2149c8
TS
4638 break;
4639 case 8:
4640 /* ignored */
f0b3f3ae 4641 rn = "BadVAddr";
9c2149c8
TS
4642 break;
4643 case 9:
4644 switch (sel) {
4645 case 0:
a7812ae4 4646 gen_helper_mtc0_count(t0);
2423f660
TS
4647 rn = "Count";
4648 break;
876d4b07 4649 /* 6,7 are implementation dependent */
9c2149c8
TS
4650 default:
4651 goto die;
876d4b07
TS
4652 }
4653 /* Stop translation as we may have switched the execution mode */
4654 ctx->bstate = BS_STOP;
9c2149c8
TS
4655 break;
4656 case 10:
4657 switch (sel) {
4658 case 0:
a7812ae4 4659 gen_helper_mtc0_entryhi(t0);
2423f660
TS
4660 rn = "EntryHi";
4661 break;
9c2149c8
TS
4662 default:
4663 goto die;
876d4b07 4664 }
9c2149c8
TS
4665 break;
4666 case 11:
4667 switch (sel) {
4668 case 0:
a7812ae4 4669 gen_helper_mtc0_compare(t0);
2423f660
TS
4670 rn = "Compare";
4671 break;
876d4b07 4672 /* 6,7 are implementation dependent */
9c2149c8
TS
4673 default:
4674 goto die;
876d4b07 4675 }
de9a95f0
AJ
4676 /* Stop translation as we may have switched the execution mode */
4677 ctx->bstate = BS_STOP;
9c2149c8
TS
4678 break;
4679 case 12:
4680 switch (sel) {
4681 case 0:
a7812ae4 4682 gen_helper_mtc0_status(t0);
8487327a
TS
4683 /* BS_STOP isn't good enough here, hflags may have changed. */
4684 gen_save_pc(ctx->pc + 4);
4685 ctx->bstate = BS_EXCP;
2423f660
TS
4686 rn = "Status";
4687 break;
9c2149c8 4688 case 1:
e189e748 4689 check_insn(env, ctx, ISA_MIPS32R2);
a7812ae4 4690 gen_helper_mtc0_intctl(t0);
8487327a
TS
4691 /* Stop translation as we may have switched the execution mode */
4692 ctx->bstate = BS_STOP;
2423f660
TS
4693 rn = "IntCtl";
4694 break;
9c2149c8 4695 case 2:
e189e748 4696 check_insn(env, ctx, ISA_MIPS32R2);
a7812ae4 4697 gen_helper_mtc0_srsctl(t0);
8487327a
TS
4698 /* Stop translation as we may have switched the execution mode */
4699 ctx->bstate = BS_STOP;
2423f660
TS
4700 rn = "SRSCtl";
4701 break;
9c2149c8 4702 case 3:
e189e748 4703 check_insn(env, ctx, ISA_MIPS32R2);
1a3fd9c3 4704 gen_mtc0_store32(t0, offsetof(CPUState, CP0_SRSMap));
8487327a
TS
4705 /* Stop translation as we may have switched the execution mode */
4706 ctx->bstate = BS_STOP;
2423f660
TS
4707 rn = "SRSMap";
4708 break;
4709 default:
9c2149c8 4710 goto die;
876d4b07 4711 }
9c2149c8
TS
4712 break;
4713 case 13:
4714 switch (sel) {
4715 case 0:
a7812ae4 4716 gen_helper_mtc0_cause(t0);
2423f660
TS
4717 rn = "Cause";
4718 break;
9c2149c8
TS
4719 default:
4720 goto die;
876d4b07
TS
4721 }
4722 /* Stop translation as we may have switched the execution mode */
4723 ctx->bstate = BS_STOP;
9c2149c8
TS
4724 break;
4725 case 14:
4726 switch (sel) {
4727 case 0:
1a3fd9c3 4728 tcg_gen_st_tl(t0, cpu_env, offsetof(CPUState, CP0_EPC));
2423f660
TS
4729 rn = "EPC";
4730 break;
9c2149c8
TS
4731 default:
4732 goto die;
876d4b07 4733 }
9c2149c8
TS
4734 break;
4735 case 15:
4736 switch (sel) {
4737 case 0:
2423f660
TS
4738 /* ignored */
4739 rn = "PRid";
4740 break;
9c2149c8 4741 case 1:
e189e748 4742 check_insn(env, ctx, ISA_MIPS32R2);
a7812ae4 4743 gen_helper_mtc0_ebase(t0);
2423f660
TS
4744 rn = "EBase";
4745 break;
9c2149c8
TS
4746 default:
4747 goto die;
876d4b07 4748 }
9c2149c8
TS
4749 break;
4750 case 16:
4751 switch (sel) {
4752 case 0:
a7812ae4 4753 gen_helper_mtc0_config0(t0);
9c2149c8 4754 rn = "Config";
2423f660
TS
4755 /* Stop translation as we may have switched the execution mode */
4756 ctx->bstate = BS_STOP;
9c2149c8
TS
4757 break;
4758 case 1:
2423f660 4759 /* ignored */
9c2149c8
TS
4760 rn = "Config1";
4761 break;
4762 case 2:
a7812ae4 4763 gen_helper_mtc0_config2(t0);
9c2149c8 4764 rn = "Config2";
2423f660
TS
4765 /* Stop translation as we may have switched the execution mode */
4766 ctx->bstate = BS_STOP;
9c2149c8
TS
4767 break;
4768 case 3:
2423f660 4769 /* ignored */
9c2149c8
TS
4770 rn = "Config3";
4771 break;
4772 /* 6,7 are implementation dependent */
4773 default:
4774 rn = "Invalid config selector";
4775 goto die;
4776 }
9c2149c8
TS
4777 break;
4778 case 17:
4779 switch (sel) {
4780 case 0:
2423f660
TS
4781 /* ignored */
4782 rn = "LLAddr";
4783 break;
9c2149c8
TS
4784 default:
4785 goto die;
4786 }
4787 break;
4788 case 18:
4789 switch (sel) {
fd88b6ab 4790 case 0 ... 7:
a7812ae4 4791 gen_helper_1i(mtc0_watchlo, t0, sel);
2423f660
TS
4792 rn = "WatchLo";
4793 break;
9c2149c8
TS
4794 default:
4795 goto die;
4796 }
4797 break;
4798 case 19:
4799 switch (sel) {
fd88b6ab 4800 case 0 ... 7:
a7812ae4 4801 gen_helper_1i(mtc0_watchhi, t0, sel);
2423f660
TS
4802 rn = "WatchHi";
4803 break;
9c2149c8
TS
4804 default:
4805 goto die;
4806 }
4807 break;
4808 case 20:
4809 switch (sel) {
4810 case 0:
e189e748 4811 check_insn(env, ctx, ISA_MIPS3);
a7812ae4 4812 gen_helper_mtc0_xcontext(t0);
2423f660
TS
4813 rn = "XContext";
4814 break;
9c2149c8
TS
4815 default:
4816 goto die;
4817 }
4818 break;
4819 case 21:
4820 /* Officially reserved, but sel 0 is used for R1x000 framemask */
4821 switch (sel) {
4822 case 0:
a7812ae4 4823 gen_helper_mtc0_framemask(t0);
2423f660
TS
4824 rn = "Framemask";
4825 break;
9c2149c8
TS
4826 default:
4827 goto die;
4828 }
4829 break;
4830 case 22:
4831 /* ignored */
4832 rn = "Diagnostic"; /* implementation dependent */
876d4b07 4833 break;
9c2149c8
TS
4834 case 23:
4835 switch (sel) {
4836 case 0:
a7812ae4 4837 gen_helper_mtc0_debug(t0); /* EJTAG support */
8487327a
TS
4838 /* BS_STOP isn't good enough here, hflags may have changed. */
4839 gen_save_pc(ctx->pc + 4);
4840 ctx->bstate = BS_EXCP;
2423f660
TS
4841 rn = "Debug";
4842 break;
9c2149c8 4843 case 1:
a7812ae4 4844// gen_helper_mtc0_tracecontrol(t0); /* PDtrace support */
8487327a
TS
4845 /* Stop translation as we may have switched the execution mode */
4846 ctx->bstate = BS_STOP;
2423f660
TS
4847 rn = "TraceControl";
4848// break;
9c2149c8 4849 case 2:
a7812ae4 4850// gen_helper_mtc0_tracecontrol2(t0); /* PDtrace support */
8487327a
TS
4851 /* Stop translation as we may have switched the execution mode */
4852 ctx->bstate = BS_STOP;
2423f660
TS
4853 rn = "TraceControl2";
4854// break;
9c2149c8 4855 case 3:
a7812ae4 4856// gen_helper_mtc0_usertracedata(t0); /* PDtrace support */
8487327a
TS
4857 /* Stop translation as we may have switched the execution mode */
4858 ctx->bstate = BS_STOP;
2423f660
TS
4859 rn = "UserTraceData";
4860// break;
9c2149c8 4861 case 4:
a7812ae4 4862// gen_helper_mtc0_tracebpc(t0); /* PDtrace support */
8487327a
TS
4863 /* Stop translation as we may have switched the execution mode */
4864 ctx->bstate = BS_STOP;
2423f660
TS
4865 rn = "TraceBPC";
4866// break;
9c2149c8
TS
4867 default:
4868 goto die;
4869 }
9c2149c8
TS
4870 break;
4871 case 24:
4872 switch (sel) {
4873 case 0:
f1aa6320 4874 /* EJTAG support */
1a3fd9c3 4875 tcg_gen_st_tl(t0, cpu_env, offsetof(CPUState, CP0_DEPC));
2423f660
TS
4876 rn = "DEPC";
4877 break;
9c2149c8
TS
4878 default:
4879 goto die;
4880 }
4881 break;
4882 case 25:
4883 switch (sel) {
4884 case 0:
a7812ae4 4885 gen_helper_mtc0_performance0(t0);
2423f660
TS
4886 rn = "Performance0";
4887 break;
9c2149c8 4888 case 1:
a7812ae4 4889// gen_helper_mtc0_performance1(t0);
2423f660
TS
4890 rn = "Performance1";
4891// break;
9c2149c8 4892 case 2:
a7812ae4 4893// gen_helper_mtc0_performance2(t0);
2423f660
TS
4894 rn = "Performance2";
4895// break;
9c2149c8 4896 case 3:
a7812ae4 4897// gen_helper_mtc0_performance3(t0);
2423f660
TS
4898 rn = "Performance3";
4899// break;
9c2149c8 4900 case 4:
a7812ae4 4901// gen_helper_mtc0_performance4(t0);
2423f660
TS
4902 rn = "Performance4";
4903// break;
9c2149c8 4904 case 5:
a7812ae4 4905// gen_helper_mtc0_performance5(t0);
2423f660
TS
4906 rn = "Performance5";
4907// break;
9c2149c8 4908 case 6:
a7812ae4 4909// gen_helper_mtc0_performance6(t0);
2423f660
TS
4910 rn = "Performance6";
4911// break;
9c2149c8 4912 case 7:
a7812ae4 4913// gen_helper_mtc0_performance7(t0);
2423f660
TS
4914 rn = "Performance7";
4915// break;
9c2149c8
TS
4916 default:
4917 goto die;
4918 }
876d4b07 4919 break;
9c2149c8 4920 case 26:
876d4b07 4921 /* ignored */
9c2149c8 4922 rn = "ECC";
876d4b07 4923 break;
9c2149c8
TS
4924 case 27:
4925 switch (sel) {
4926 case 0 ... 3:
2423f660
TS
4927 /* ignored */
4928 rn = "CacheErr";
4929 break;
9c2149c8
TS
4930 default:
4931 goto die;
4932 }
876d4b07 4933 break;
9c2149c8
TS
4934 case 28:
4935 switch (sel) {
4936 case 0:
4937 case 2:
4938 case 4:
4939 case 6:
a7812ae4 4940 gen_helper_mtc0_taglo(t0);
9c2149c8
TS
4941 rn = "TagLo";
4942 break;
4943 case 1:
4944 case 3:
4945 case 5:
4946 case 7:
a7812ae4 4947 gen_helper_mtc0_datalo(t0);
9c2149c8
TS
4948 rn = "DataLo";
4949 break;
4950 default:
4951 goto die;
4952 }
4953 break;
4954 case 29:
4955 switch (sel) {
4956 case 0:
4957 case 2:
4958 case 4:
4959 case 6:
a7812ae4 4960 gen_helper_mtc0_taghi(t0);
9c2149c8
TS
4961 rn = "TagHi";
4962 break;
4963 case 1:
4964 case 3:
4965 case 5:
4966 case 7:
a7812ae4 4967 gen_helper_mtc0_datahi(t0);
9c2149c8
TS
4968 rn = "DataHi";
4969 break;
4970 default:
4971 rn = "invalid sel";
4972 goto die;
4973 }
876d4b07 4974 break;
9c2149c8
TS
4975 case 30:
4976 switch (sel) {
4977 case 0:
1a3fd9c3 4978 tcg_gen_st_tl(t0, cpu_env, offsetof(CPUState, CP0_ErrorEPC));
2423f660
TS
4979 rn = "ErrorEPC";
4980 break;
9c2149c8
TS
4981 default:
4982 goto die;
4983 }
4984 break;
4985 case 31:
4986 switch (sel) {
4987 case 0:
f1aa6320 4988 /* EJTAG support */
1a3fd9c3 4989 gen_mtc0_store32(t0, offsetof(CPUState, CP0_DESAVE));
2423f660
TS
4990 rn = "DESAVE";
4991 break;
9c2149c8
TS
4992 default:
4993 goto die;
4994 }
876d4b07
TS
4995 /* Stop translation as we may have switched the execution mode */
4996 ctx->bstate = BS_STOP;
9c2149c8
TS
4997 break;
4998 default:
876d4b07 4999 goto die;
9c2149c8 5000 }
d12d51d5 5001 LOG_DISAS("dmtc0 %s (reg %d sel %d)\n", rn, reg, sel);
bf20dc07 5002 /* For simplicity assume that all writes can cause interrupts. */
2e70f6ef
PB
5003 if (use_icount) {
5004 gen_io_end();
5005 ctx->bstate = BS_STOP;
5006 }
9c2149c8
TS
5007 return;
5008
5009die:
d12d51d5 5010 LOG_DISAS("dmtc0 %s (reg %d sel %d)\n", rn, reg, sel);
9c2149c8
TS
5011 generate_exception(ctx, EXCP_RI);
5012}
d26bc211 5013#endif /* TARGET_MIPS64 */
9c2149c8 5014
6c5c1e20 5015static void gen_mftr(CPUState *env, DisasContext *ctx, int rt, int rd,
ead9360e
TS
5016 int u, int sel, int h)
5017{
5018 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
a7812ae4 5019 TCGv t0 = tcg_temp_local_new();
ead9360e
TS
5020
5021 if ((env->CP0_VPEConf0 & (1 << CP0VPEC0_MVP)) == 0 &&
b5dc7732
TS
5022 ((env->tcs[other_tc].CP0_TCBind & (0xf << CP0TCBd_CurVPE)) !=
5023 (env->active_tc.CP0_TCBind & (0xf << CP0TCBd_CurVPE))))
1a3fd9c3 5024 tcg_gen_movi_tl(t0, -1);
ead9360e
TS
5025 else if ((env->CP0_VPEControl & (0xff << CP0VPECo_TargTC)) >
5026 (env->mvp->CP0_MVPConf0 & (0xff << CP0MVPC0_PTC)))
1a3fd9c3 5027 tcg_gen_movi_tl(t0, -1);
ead9360e
TS
5028 else if (u == 0) {
5029 switch (rt) {
5030 case 2:
5031 switch (sel) {
5032 case 1:
a7812ae4 5033 gen_helper_mftc0_tcstatus(t0);
ead9360e
TS
5034 break;
5035 case 2:
a7812ae4 5036 gen_helper_mftc0_tcbind(t0);
ead9360e
TS
5037 break;
5038 case 3:
a7812ae4 5039 gen_helper_mftc0_tcrestart(t0);
ead9360e
TS
5040 break;
5041 case 4:
a7812ae4 5042 gen_helper_mftc0_tchalt(t0);
ead9360e
TS
5043 break;
5044 case 5:
a7812ae4 5045 gen_helper_mftc0_tccontext(t0);
ead9360e
TS
5046 break;
5047 case 6:
a7812ae4 5048 gen_helper_mftc0_tcschedule(t0);
ead9360e
TS
5049 break;
5050 case 7:
a7812ae4 5051 gen_helper_mftc0_tcschefback(t0);
ead9360e
TS
5052 break;
5053 default:
1a3fd9c3 5054 gen_mfc0(env, ctx, t0, rt, sel);
ead9360e
TS
5055 break;
5056 }
5057 break;
5058 case 10:
5059 switch (sel) {
5060 case 0:
a7812ae4 5061 gen_helper_mftc0_entryhi(t0);
ead9360e
TS
5062 break;
5063 default:
1a3fd9c3 5064 gen_mfc0(env, ctx, t0, rt, sel);
ead9360e
TS
5065 break;
5066 }
5067 case 12:
5068 switch (sel) {
5069 case 0:
a7812ae4 5070 gen_helper_mftc0_status(t0);
ead9360e
TS
5071 break;
5072 default:
1a3fd9c3 5073 gen_mfc0(env, ctx, t0, rt, sel);
ead9360e
TS
5074 break;
5075 }
5076 case 23:
5077 switch (sel) {
5078 case 0:
a7812ae4 5079 gen_helper_mftc0_debug(t0);
ead9360e
TS
5080 break;
5081 default:
1a3fd9c3 5082 gen_mfc0(env, ctx, t0, rt, sel);
ead9360e
TS
5083 break;
5084 }
5085 break;
5086 default:
1a3fd9c3 5087 gen_mfc0(env, ctx, t0, rt, sel);
ead9360e
TS
5088 }
5089 } else switch (sel) {
5090 /* GPR registers. */
5091 case 0:
a7812ae4 5092 gen_helper_1i(mftgpr, t0, rt);
ead9360e
TS
5093 break;
5094 /* Auxiliary CPU registers */
5095 case 1:
5096 switch (rt) {
5097 case 0:
a7812ae4 5098 gen_helper_1i(mftlo, t0, 0);
ead9360e
TS
5099 break;
5100 case 1:
a7812ae4 5101 gen_helper_1i(mfthi, t0, 0);
ead9360e
TS
5102 break;
5103 case 2:
a7812ae4 5104 gen_helper_1i(mftacx, t0, 0);
ead9360e
TS
5105 break;
5106 case 4:
a7812ae4 5107 gen_helper_1i(mftlo, t0, 1);
ead9360e
TS
5108 break;
5109 case 5:
a7812ae4 5110 gen_helper_1i(mfthi, t0, 1);
ead9360e
TS
5111 break;
5112 case 6:
a7812ae4 5113 gen_helper_1i(mftacx, t0, 1);
ead9360e
TS
5114 break;
5115 case 8:
a7812ae4 5116 gen_helper_1i(mftlo, t0, 2);
ead9360e
TS
5117 break;
5118 case 9:
a7812ae4 5119 gen_helper_1i(mfthi, t0, 2);
ead9360e
TS
5120 break;
5121 case 10:
a7812ae4 5122 gen_helper_1i(mftacx, t0, 2);
ead9360e
TS
5123 break;
5124 case 12:
a7812ae4 5125 gen_helper_1i(mftlo, t0, 3);
ead9360e
TS
5126 break;
5127 case 13:
a7812ae4 5128 gen_helper_1i(mfthi, t0, 3);
ead9360e
TS
5129 break;
5130 case 14:
a7812ae4 5131 gen_helper_1i(mftacx, t0, 3);
ead9360e
TS
5132 break;
5133 case 16:
a7812ae4 5134 gen_helper_mftdsp(t0);
ead9360e
TS
5135 break;
5136 default:
5137 goto die;
5138 }
5139 break;
5140 /* Floating point (COP1). */
5141 case 2:
5142 /* XXX: For now we support only a single FPU context. */
5143 if (h == 0) {
a7812ae4 5144 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed
TS
5145
5146 gen_load_fpr32(fp0, rt);
5147 tcg_gen_ext_i32_tl(t0, fp0);
a7812ae4 5148 tcg_temp_free_i32(fp0);
ead9360e 5149 } else {
a7812ae4 5150 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed
TS
5151
5152 gen_load_fpr32h(fp0, rt);
5153 tcg_gen_ext_i32_tl(t0, fp0);
a7812ae4 5154 tcg_temp_free_i32(fp0);
ead9360e
TS
5155 }
5156 break;
5157 case 3:
5158 /* XXX: For now we support only a single FPU context. */
a7812ae4 5159 gen_helper_1i(cfc1, t0, rt);
ead9360e
TS
5160 break;
5161 /* COP2: Not implemented. */
5162 case 4:
5163 case 5:
5164 /* fall through */
5165 default:
5166 goto die;
5167 }
d12d51d5 5168 LOG_DISAS("mftr (reg %d u %d sel %d h %d)\n", rt, u, sel, h);
1a3fd9c3
TS
5169 gen_store_gpr(t0, rd);
5170 tcg_temp_free(t0);
ead9360e
TS
5171 return;
5172
5173die:
1a3fd9c3 5174 tcg_temp_free(t0);
d12d51d5 5175 LOG_DISAS("mftr (reg %d u %d sel %d h %d)\n", rt, u, sel, h);
ead9360e
TS
5176 generate_exception(ctx, EXCP_RI);
5177}
5178
6c5c1e20 5179static void gen_mttr(CPUState *env, DisasContext *ctx, int rd, int rt,
ead9360e
TS
5180 int u, int sel, int h)
5181{
5182 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
a7812ae4 5183 TCGv t0 = tcg_temp_local_new();
ead9360e 5184
1a3fd9c3 5185 gen_load_gpr(t0, rt);
ead9360e 5186 if ((env->CP0_VPEConf0 & (1 << CP0VPEC0_MVP)) == 0 &&
b5dc7732
TS
5187 ((env->tcs[other_tc].CP0_TCBind & (0xf << CP0TCBd_CurVPE)) !=
5188 (env->active_tc.CP0_TCBind & (0xf << CP0TCBd_CurVPE))))
ead9360e
TS
5189 /* NOP */ ;
5190 else if ((env->CP0_VPEControl & (0xff << CP0VPECo_TargTC)) >
5191 (env->mvp->CP0_MVPConf0 & (0xff << CP0MVPC0_PTC)))
5192 /* NOP */ ;
5193 else if (u == 0) {
5194 switch (rd) {
5195 case 2:
5196 switch (sel) {
5197 case 1:
a7812ae4 5198 gen_helper_mttc0_tcstatus(t0);
ead9360e
TS
5199 break;
5200 case 2:
a7812ae4 5201 gen_helper_mttc0_tcbind(t0);
ead9360e
TS
5202 break;
5203 case 3:
a7812ae4 5204 gen_helper_mttc0_tcrestart(t0);
ead9360e
TS
5205 break;
5206 case 4:
a7812ae4 5207 gen_helper_mttc0_tchalt(t0);
ead9360e
TS
5208 break;
5209 case 5:
a7812ae4 5210 gen_helper_mttc0_tccontext(t0);
ead9360e
TS
5211 break;
5212 case 6:
a7812ae4 5213 gen_helper_mttc0_tcschedule(t0);
ead9360e
TS
5214 break;
5215 case 7:
a7812ae4 5216 gen_helper_mttc0_tcschefback(t0);
ead9360e
TS
5217 break;
5218 default:
1a3fd9c3 5219 gen_mtc0(env, ctx, t0, rd, sel);
ead9360e
TS
5220 break;
5221 }
5222 break;
5223 case 10:
5224 switch (sel) {
5225 case 0:
a7812ae4 5226 gen_helper_mttc0_entryhi(t0);
ead9360e
TS
5227 break;
5228 default:
1a3fd9c3 5229 gen_mtc0(env, ctx, t0, rd, sel);
ead9360e
TS
5230 break;
5231 }
5232 case 12:
5233 switch (sel) {
5234 case 0:
a7812ae4 5235 gen_helper_mttc0_status(t0);
ead9360e
TS
5236 break;
5237 default:
1a3fd9c3 5238 gen_mtc0(env, ctx, t0, rd, sel);
ead9360e
TS
5239 break;
5240 }
5241 case 23:
5242 switch (sel) {
5243 case 0:
a7812ae4 5244 gen_helper_mttc0_debug(t0);
ead9360e
TS
5245 break;
5246 default:
1a3fd9c3 5247 gen_mtc0(env, ctx, t0, rd, sel);
ead9360e
TS
5248 break;
5249 }
5250 break;
5251 default:
1a3fd9c3 5252 gen_mtc0(env, ctx, t0, rd, sel);
ead9360e
TS
5253 }
5254 } else switch (sel) {
5255 /* GPR registers. */
5256 case 0:
a7812ae4 5257 gen_helper_1i(mttgpr, t0, rd);
ead9360e
TS
5258 break;
5259 /* Auxiliary CPU registers */
5260 case 1:
5261 switch (rd) {
5262 case 0:
a7812ae4 5263 gen_helper_1i(mttlo, t0, 0);
ead9360e
TS
5264 break;
5265 case 1:
a7812ae4 5266 gen_helper_1i(mtthi, t0, 0);
ead9360e
TS
5267 break;
5268 case 2:
a7812ae4 5269 gen_helper_1i(mttacx, t0, 0);
ead9360e
TS
5270 break;
5271 case 4:
a7812ae4 5272 gen_helper_1i(mttlo, t0, 1);
ead9360e
TS
5273 break;
5274 case 5:
a7812ae4 5275 gen_helper_1i(mtthi, t0, 1);
ead9360e
TS
5276 break;
5277 case 6:
a7812ae4 5278 gen_helper_1i(mttacx, t0, 1);
ead9360e
TS
5279 break;
5280 case 8:
a7812ae4 5281 gen_helper_1i(mttlo, t0, 2);
ead9360e
TS
5282 break;
5283 case 9:
a7812ae4 5284 gen_helper_1i(mtthi, t0, 2);
ead9360e
TS
5285 break;
5286 case 10:
a7812ae4 5287 gen_helper_1i(mttacx, t0, 2);
ead9360e
TS
5288 break;
5289 case 12:
a7812ae4 5290 gen_helper_1i(mttlo, t0, 3);
ead9360e
TS
5291 break;
5292 case 13:
a7812ae4 5293 gen_helper_1i(mtthi, t0, 3);
ead9360e
TS
5294 break;
5295 case 14:
a7812ae4 5296 gen_helper_1i(mttacx, t0, 3);
ead9360e
TS
5297 break;
5298 case 16:
a7812ae4 5299 gen_helper_mttdsp(t0);
ead9360e
TS
5300 break;
5301 default:
5302 goto die;
5303 }
5304 break;
5305 /* Floating point (COP1). */
5306 case 2:
5307 /* XXX: For now we support only a single FPU context. */
5308 if (h == 0) {
a7812ae4 5309 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed
TS
5310
5311 tcg_gen_trunc_tl_i32(fp0, t0);
5312 gen_store_fpr32(fp0, rd);
a7812ae4 5313 tcg_temp_free_i32(fp0);
ead9360e 5314 } else {
a7812ae4 5315 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed
TS
5316
5317 tcg_gen_trunc_tl_i32(fp0, t0);
5318 gen_store_fpr32h(fp0, rd);
a7812ae4 5319 tcg_temp_free_i32(fp0);
ead9360e
TS
5320 }
5321 break;
5322 case 3:
5323 /* XXX: For now we support only a single FPU context. */
a7812ae4 5324 gen_helper_1i(ctc1, t0, rd);
ead9360e
TS
5325 break;
5326 /* COP2: Not implemented. */
5327 case 4:
5328 case 5:
5329 /* fall through */
5330 default:
5331 goto die;
5332 }
d12d51d5 5333 LOG_DISAS("mttr (reg %d u %d sel %d h %d)\n", rd, u, sel, h);
1a3fd9c3 5334 tcg_temp_free(t0);
ead9360e
TS
5335 return;
5336
5337die:
1a3fd9c3 5338 tcg_temp_free(t0);
d12d51d5 5339 LOG_DISAS("mttr (reg %d u %d sel %d h %d)\n", rd, u, sel, h);
ead9360e
TS
5340 generate_exception(ctx, EXCP_RI);
5341}
5342
29929e34 5343static void gen_cp0 (CPUState *env, DisasContext *ctx, uint32_t opc, int rt, int rd)
6af0bf9c 5344{
287c4b84 5345 const char *opn = "ldst";
6af0bf9c 5346
6af0bf9c
FB
5347 switch (opc) {
5348 case OPC_MFC0:
5349 if (rt == 0) {
ead9360e 5350 /* Treat as NOP. */
6af0bf9c
FB
5351 return;
5352 }
1a3fd9c3 5353 {
a7812ae4 5354 TCGv t0 = tcg_temp_local_new();
1a3fd9c3
TS
5355
5356 gen_mfc0(env, ctx, t0, rd, ctx->opcode & 0x7);
5357 gen_store_gpr(t0, rt);
5358 tcg_temp_free(t0);
5359 }
6af0bf9c
FB
5360 opn = "mfc0";
5361 break;
5362 case OPC_MTC0:
1a3fd9c3 5363 {
a7812ae4 5364 TCGv t0 = tcg_temp_local_new();
1a3fd9c3
TS
5365
5366 gen_load_gpr(t0, rt);
5367 save_cpu_state(ctx, 1);
5368 gen_mtc0(env, ctx, t0, rd, ctx->opcode & 0x7);
5369 tcg_temp_free(t0);
5370 }
6af0bf9c
FB
5371 opn = "mtc0";
5372 break;
d26bc211 5373#if defined(TARGET_MIPS64)
9c2149c8 5374 case OPC_DMFC0:
e189e748 5375 check_insn(env, ctx, ISA_MIPS3);
9c2149c8 5376 if (rt == 0) {
ead9360e 5377 /* Treat as NOP. */
9c2149c8
TS
5378 return;
5379 }
1a3fd9c3 5380 {
a7812ae4 5381 TCGv t0 = tcg_temp_local_new();
1a3fd9c3
TS
5382
5383 gen_dmfc0(env, ctx, t0, rd, ctx->opcode & 0x7);
5384 gen_store_gpr(t0, rt);
5385 tcg_temp_free(t0);
5386 }
9c2149c8
TS
5387 opn = "dmfc0";
5388 break;
5389 case OPC_DMTC0:
e189e748 5390 check_insn(env, ctx, ISA_MIPS3);
1a3fd9c3 5391 {
a7812ae4 5392 TCGv t0 = tcg_temp_local_new();
1a3fd9c3
TS
5393
5394 gen_load_gpr(t0, rt);
5395 save_cpu_state(ctx, 1);
5396 gen_dmtc0(env, ctx, t0, rd, ctx->opcode & 0x7);
5397 tcg_temp_free(t0);
5398 }
9c2149c8
TS
5399 opn = "dmtc0";
5400 break;
534ce69f 5401#endif
ead9360e 5402 case OPC_MFTR:
7385ac0b 5403 check_insn(env, ctx, ASE_MT);
ead9360e
TS
5404 if (rd == 0) {
5405 /* Treat as NOP. */
5406 return;
5407 }
6c5c1e20 5408 gen_mftr(env, ctx, rt, rd, (ctx->opcode >> 5) & 1,
ead9360e 5409 ctx->opcode & 0x7, (ctx->opcode >> 4) & 1);
ead9360e
TS
5410 opn = "mftr";
5411 break;
5412 case OPC_MTTR:
7385ac0b 5413 check_insn(env, ctx, ASE_MT);
6c5c1e20 5414 gen_mttr(env, ctx, rd, rt, (ctx->opcode >> 5) & 1,
ead9360e
TS
5415 ctx->opcode & 0x7, (ctx->opcode >> 4) & 1);
5416 opn = "mttr";
5417 break;
6af0bf9c 5418 case OPC_TLBWI:
6af0bf9c 5419 opn = "tlbwi";
c01fccd2 5420 if (!env->tlb->helper_tlbwi)
29929e34 5421 goto die;
a7812ae4 5422 gen_helper_tlbwi();
6af0bf9c
FB
5423 break;
5424 case OPC_TLBWR:
6af0bf9c 5425 opn = "tlbwr";
c01fccd2 5426 if (!env->tlb->helper_tlbwr)
29929e34 5427 goto die;
a7812ae4 5428 gen_helper_tlbwr();
6af0bf9c
FB
5429 break;
5430 case OPC_TLBP:
6af0bf9c 5431 opn = "tlbp";
c01fccd2 5432 if (!env->tlb->helper_tlbp)
29929e34 5433 goto die;
a7812ae4 5434 gen_helper_tlbp();
6af0bf9c
FB
5435 break;
5436 case OPC_TLBR:
6af0bf9c 5437 opn = "tlbr";
c01fccd2 5438 if (!env->tlb->helper_tlbr)
29929e34 5439 goto die;
a7812ae4 5440 gen_helper_tlbr();
6af0bf9c 5441 break;
6af0bf9c
FB
5442 case OPC_ERET:
5443 opn = "eret";
e189e748 5444 check_insn(env, ctx, ISA_MIPS2);
387a8fe5 5445 save_cpu_state(ctx, 1);
a7812ae4 5446 gen_helper_eret();
6af0bf9c
FB
5447 ctx->bstate = BS_EXCP;
5448 break;
5449 case OPC_DERET:
5450 opn = "deret";
e189e748 5451 check_insn(env, ctx, ISA_MIPS32);
6af0bf9c 5452 if (!(ctx->hflags & MIPS_HFLAG_DM)) {
923617a3 5453 MIPS_INVAL(opn);
6af0bf9c
FB
5454 generate_exception(ctx, EXCP_RI);
5455 } else {
387a8fe5 5456 save_cpu_state(ctx, 1);
a7812ae4 5457 gen_helper_deret();
6af0bf9c
FB
5458 ctx->bstate = BS_EXCP;
5459 }
5460 break;
4ad40f36
FB
5461 case OPC_WAIT:
5462 opn = "wait";
e189e748 5463 check_insn(env, ctx, ISA_MIPS3 | ISA_MIPS32);
4ad40f36
FB
5464 /* If we get an exception, we want to restart at next instruction */
5465 ctx->pc += 4;
5466 save_cpu_state(ctx, 1);
5467 ctx->pc -= 4;
a7812ae4 5468 gen_helper_wait();
4ad40f36
FB
5469 ctx->bstate = BS_EXCP;
5470 break;
6af0bf9c 5471 default:
29929e34 5472 die:
923617a3 5473 MIPS_INVAL(opn);
6af0bf9c
FB
5474 generate_exception(ctx, EXCP_RI);
5475 return;
5476 }
5477 MIPS_DEBUG("%s %s %d", opn, regnames[rt], rd);
5478}
f1aa6320 5479#endif /* !CONFIG_USER_ONLY */
6af0bf9c 5480
6ea83fed 5481/* CP1 Branches (before delay slot) */
e189e748 5482static void gen_compute_branch1 (CPUState *env, DisasContext *ctx, uint32_t op,
5a5012ec 5483 int32_t cc, int32_t offset)
6ea83fed
FB
5484{
5485 target_ulong btarget;
923617a3 5486 const char *opn = "cp1 cond branch";
a7812ae4 5487 TCGv_i32 t0 = tcg_temp_new_i32();
6ea83fed 5488
e189e748
TS
5489 if (cc != 0)
5490 check_insn(env, ctx, ISA_MIPS4 | ISA_MIPS32);
5491
6ea83fed
FB
5492 btarget = ctx->pc + 4 + offset;
5493
7a387fff
TS
5494 switch (op) {
5495 case OPC_BC1F:
d94536f4
AJ
5496 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
5497 tcg_gen_not_i32(t0, t0);
5498 tcg_gen_andi_i32(t0, t0, 1);
5499 tcg_gen_extu_i32_tl(bcond, t0);
923617a3 5500 opn = "bc1f";
6ea83fed 5501 goto not_likely;
7a387fff 5502 case OPC_BC1FL:
d94536f4
AJ
5503 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
5504 tcg_gen_not_i32(t0, t0);
5505 tcg_gen_andi_i32(t0, t0, 1);
5506 tcg_gen_extu_i32_tl(bcond, t0);
923617a3 5507 opn = "bc1fl";
6ea83fed 5508 goto likely;
7a387fff 5509 case OPC_BC1T:
d94536f4
AJ
5510 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
5511 tcg_gen_andi_i32(t0, t0, 1);
5512 tcg_gen_extu_i32_tl(bcond, t0);
923617a3 5513 opn = "bc1t";
5a5012ec 5514 goto not_likely;
7a387fff 5515 case OPC_BC1TL:
d94536f4
AJ
5516 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
5517 tcg_gen_andi_i32(t0, t0, 1);
5518 tcg_gen_extu_i32_tl(bcond, t0);
923617a3 5519 opn = "bc1tl";
6ea83fed
FB
5520 likely:
5521 ctx->hflags |= MIPS_HFLAG_BL;
5522 break;
5a5012ec 5523 case OPC_BC1FANY2:
a16336e4 5524 {
d94536f4
AJ
5525 TCGv_i32 t1 = tcg_temp_new_i32();
5526 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
5527 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+1));
5528 tcg_gen_or_i32(t0, t0, t1);
5529 tcg_temp_free_i32(t1);
5530 tcg_gen_not_i32(t0, t0);
5531 tcg_gen_andi_i32(t0, t0, 1);
5532 tcg_gen_extu_i32_tl(bcond, t0);
a16336e4 5533 }
fd4a04eb 5534 opn = "bc1any2f";
5a5012ec
TS
5535 goto not_likely;
5536 case OPC_BC1TANY2:
a16336e4 5537 {
d94536f4
AJ
5538 TCGv_i32 t1 = tcg_temp_new_i32();
5539 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
5540 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+1));
5541 tcg_gen_or_i32(t0, t0, t1);
5542 tcg_temp_free_i32(t1);
5543 tcg_gen_andi_i32(t0, t0, 1);
5544 tcg_gen_extu_i32_tl(bcond, t0);
a16336e4 5545 }
fd4a04eb 5546 opn = "bc1any2t";
5a5012ec
TS
5547 goto not_likely;
5548 case OPC_BC1FANY4:
a16336e4 5549 {
d94536f4
AJ
5550 TCGv_i32 t1 = tcg_temp_new_i32();
5551 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
5552 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+1));
5553 tcg_gen_or_i32(t0, t0, t1);
5554 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+2));
5555 tcg_gen_or_i32(t0, t0, t1);
5556 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+3));
5557 tcg_gen_or_i32(t0, t0, t1);
5558 tcg_temp_free_i32(t1);
5559 tcg_gen_not_i32(t0, t0);
5560 tcg_gen_andi_i32(t0, t0, 1);
5561 tcg_gen_extu_i32_tl(bcond, t0);
a16336e4 5562 }
fd4a04eb 5563 opn = "bc1any4f";
5a5012ec
TS
5564 goto not_likely;
5565 case OPC_BC1TANY4:
a16336e4 5566 {
d94536f4
AJ
5567 TCGv_i32 t1 = tcg_temp_new_i32();
5568 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
5569 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+1));
5570 tcg_gen_or_i32(t0, t0, t1);
5571 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+2));
5572 tcg_gen_or_i32(t0, t0, t1);
5573 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+3));
5574 tcg_gen_or_i32(t0, t0, t1);
5575 tcg_temp_free_i32(t1);
5576 tcg_gen_andi_i32(t0, t0, 1);
5577 tcg_gen_extu_i32_tl(bcond, t0);
a16336e4 5578 }
fd4a04eb 5579 opn = "bc1any4t";
5a5012ec
TS
5580 not_likely:
5581 ctx->hflags |= MIPS_HFLAG_BC;
5a5012ec
TS
5582 break;
5583 default:
923617a3 5584 MIPS_INVAL(opn);
e397ee33 5585 generate_exception (ctx, EXCP_RI);
6c5c1e20 5586 goto out;
6ea83fed 5587 }
923617a3 5588 MIPS_DEBUG("%s: cond %02x target " TARGET_FMT_lx, opn,
6ea83fed
FB
5589 ctx->hflags, btarget);
5590 ctx->btarget = btarget;
6c5c1e20
TS
5591
5592 out:
a7812ae4 5593 tcg_temp_free_i32(t0);
6ea83fed
FB
5594}
5595
6af0bf9c 5596/* Coprocessor 1 (FPU) */
5a5012ec 5597
5a5012ec
TS
5598#define FOP(func, fmt) (((fmt) << 21) | (func))
5599
7a387fff 5600static void gen_cp1 (DisasContext *ctx, uint32_t opc, int rt, int fs)
6ea83fed 5601{
923617a3 5602 const char *opn = "cp1 move";
a7812ae4 5603 TCGv t0 = tcg_temp_local_new();
6ea83fed
FB
5604
5605 switch (opc) {
5606 case OPC_MFC1:
b6d96bed 5607 {
a7812ae4 5608 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed
TS
5609
5610 gen_load_fpr32(fp0, fs);
5611 tcg_gen_ext_i32_tl(t0, fp0);
a7812ae4 5612 tcg_temp_free_i32(fp0);
6958549d 5613 }
6c5c1e20 5614 gen_store_gpr(t0, rt);
6ea83fed
FB
5615 opn = "mfc1";
5616 break;
5617 case OPC_MTC1:
6c5c1e20 5618 gen_load_gpr(t0, rt);
b6d96bed 5619 {
a7812ae4 5620 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed
TS
5621
5622 tcg_gen_trunc_tl_i32(fp0, t0);
5623 gen_store_fpr32(fp0, fs);
a7812ae4 5624 tcg_temp_free_i32(fp0);
6958549d 5625 }
6ea83fed
FB
5626 opn = "mtc1";
5627 break;
5628 case OPC_CFC1:
a7812ae4 5629 gen_helper_1i(cfc1, t0, fs);
6c5c1e20 5630 gen_store_gpr(t0, rt);
6ea83fed
FB
5631 opn = "cfc1";
5632 break;
5633 case OPC_CTC1:
6c5c1e20 5634 gen_load_gpr(t0, rt);
a7812ae4 5635 gen_helper_1i(ctc1, t0, fs);
6ea83fed
FB
5636 opn = "ctc1";
5637 break;
9c2149c8 5638 case OPC_DMFC1:
b6d96bed 5639 {
a7812ae4 5640 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
5641
5642 gen_load_fpr64(ctx, fp0, fs);
a7812ae4
PB
5643 tcg_gen_trunc_i64_tl(t0, fp0);
5644 tcg_temp_free_i64(fp0);
6958549d 5645 }
6c5c1e20 5646 gen_store_gpr(t0, rt);
5a5012ec
TS
5647 opn = "dmfc1";
5648 break;
9c2149c8 5649 case OPC_DMTC1:
6c5c1e20 5650 gen_load_gpr(t0, rt);
b6d96bed 5651 {
a7812ae4 5652 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed 5653
a7812ae4 5654 tcg_gen_extu_tl_i64(fp0, t0);
b6d96bed 5655 gen_store_fpr64(ctx, fp0, fs);
a7812ae4 5656 tcg_temp_free_i64(fp0);
6958549d 5657 }
5a5012ec
TS
5658 opn = "dmtc1";
5659 break;
5660 case OPC_MFHC1:
b6d96bed 5661 {
a7812ae4 5662 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed
TS
5663
5664 gen_load_fpr32h(fp0, fs);
5665 tcg_gen_ext_i32_tl(t0, fp0);
a7812ae4 5666 tcg_temp_free_i32(fp0);
6958549d 5667 }
6c5c1e20 5668 gen_store_gpr(t0, rt);
5a5012ec
TS
5669 opn = "mfhc1";
5670 break;
5671 case OPC_MTHC1:
6c5c1e20 5672 gen_load_gpr(t0, rt);
b6d96bed 5673 {
a7812ae4 5674 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed
TS
5675
5676 tcg_gen_trunc_tl_i32(fp0, t0);
5677 gen_store_fpr32h(fp0, fs);
a7812ae4 5678 tcg_temp_free_i32(fp0);
6958549d 5679 }
5a5012ec
TS
5680 opn = "mthc1";
5681 break;
6ea83fed 5682 default:
923617a3 5683 MIPS_INVAL(opn);
e397ee33 5684 generate_exception (ctx, EXCP_RI);
6c5c1e20 5685 goto out;
6ea83fed
FB
5686 }
5687 MIPS_DEBUG("%s %s %s", opn, regnames[rt], fregnames[fs]);
6c5c1e20
TS
5688
5689 out:
5690 tcg_temp_free(t0);
6ea83fed
FB
5691}
5692
5a5012ec
TS
5693static void gen_movci (DisasContext *ctx, int rd, int rs, int cc, int tf)
5694{
af58f9ca 5695 int l1;
e214b9bb 5696 TCGCond cond;
af58f9ca
AJ
5697 TCGv_i32 t0;
5698
5699 if (rd == 0) {
5700 /* Treat as NOP. */
5701 return;
5702 }
6ea83fed 5703
e214b9bb 5704 if (tf)
e214b9bb 5705 cond = TCG_COND_EQ;
27848470
TS
5706 else
5707 cond = TCG_COND_NE;
5708
af58f9ca
AJ
5709 l1 = gen_new_label();
5710 t0 = tcg_temp_new_i32();
5711 tcg_gen_andi_i32(t0, fpu_fcr31, get_fp_bit(cc));
5712 tcg_gen_brcondi_i32(cond, t0, 0, l1);
5713 if (rs == 0) {
5714 tcg_gen_movi_tl(cpu_gpr[rd], 0);
5715 } else {
5716 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
5717 }
e214b9bb 5718 gen_set_label(l1);
af58f9ca 5719 tcg_temp_free_i32(t0);
5a5012ec
TS
5720}
5721
b6d96bed 5722static inline void gen_movcf_s (int fs, int fd, int cc, int tf)
a16336e4 5723{
a16336e4 5724 int cond;
cbc37b28 5725 TCGv_i32 t0 = tcg_temp_new_i32();
a16336e4
TS
5726 int l1 = gen_new_label();
5727
a16336e4
TS
5728 if (tf)
5729 cond = TCG_COND_EQ;
5730 else
5731 cond = TCG_COND_NE;
5732
cbc37b28
AJ
5733 tcg_gen_andi_i32(t0, fpu_fcr31, get_fp_bit(cc));
5734 tcg_gen_brcondi_i32(cond, t0, 0, l1);
5735 gen_load_fpr32(t0, fs);
5736 gen_store_fpr32(t0, fd);
a16336e4 5737 gen_set_label(l1);
cbc37b28 5738 tcg_temp_free_i32(t0);
5a5012ec 5739}
a16336e4 5740
b6d96bed 5741static inline void gen_movcf_d (DisasContext *ctx, int fs, int fd, int cc, int tf)
a16336e4 5742{
a16336e4 5743 int cond;
cbc37b28
AJ
5744 TCGv_i32 t0 = tcg_temp_new_i32();
5745 TCGv_i64 fp0;
a16336e4
TS
5746 int l1 = gen_new_label();
5747
a16336e4
TS
5748 if (tf)
5749 cond = TCG_COND_EQ;
5750 else
5751 cond = TCG_COND_NE;
5752
cbc37b28
AJ
5753 tcg_gen_andi_i32(t0, fpu_fcr31, get_fp_bit(cc));
5754 tcg_gen_brcondi_i32(cond, t0, 0, l1);
5755 fp0 = tcg_temp_local_new_i64();
9bf3eb2c 5756 gen_load_fpr64(ctx, fp0, fs);
9bf3eb2c 5757 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 5758 tcg_temp_free_i64(fp0);
cbc37b28
AJ
5759 gen_set_label(l1);
5760 tcg_temp_free_i32(t0);
a16336e4
TS
5761}
5762
b6d96bed 5763static inline void gen_movcf_ps (int fs, int fd, int cc, int tf)
a16336e4
TS
5764{
5765 int cond;
cbc37b28 5766 TCGv_i32 t0 = tcg_temp_new_i32();
a16336e4
TS
5767 int l1 = gen_new_label();
5768 int l2 = gen_new_label();
5769
5770 if (tf)
5771 cond = TCG_COND_EQ;
5772 else
5773 cond = TCG_COND_NE;
5774
cbc37b28
AJ
5775 tcg_gen_andi_i32(t0, fpu_fcr31, get_fp_bit(cc));
5776 tcg_gen_brcondi_i32(cond, t0, 0, l1);
5777 gen_load_fpr32(t0, fs);
5778 gen_store_fpr32(t0, fd);
a16336e4 5779 gen_set_label(l1);
9bf3eb2c 5780
cbc37b28
AJ
5781 tcg_gen_andi_i32(t0, fpu_fcr31, get_fp_bit(cc+1));
5782 tcg_gen_brcondi_i32(cond, t0, 0, l2);
5783 gen_load_fpr32h(t0, fs);
5784 gen_store_fpr32h(t0, fd);
a16336e4 5785 gen_set_label(l2);
9bf3eb2c 5786
cbc37b28 5787 tcg_temp_free_i32(t0);
a16336e4
TS
5788}
5789
6ea83fed 5790
5e755519
TS
5791static void gen_farith (DisasContext *ctx, uint32_t op1,
5792 int ft, int fs, int fd, int cc)
6ea83fed 5793{
923617a3 5794 const char *opn = "farith";
6ea83fed
FB
5795 const char *condnames[] = {
5796 "c.f",
5797 "c.un",
5798 "c.eq",
5799 "c.ueq",
5800 "c.olt",
5801 "c.ult",
5802 "c.ole",
5803 "c.ule",
5804 "c.sf",
5805 "c.ngle",
5806 "c.seq",
5807 "c.ngl",
5808 "c.lt",
5809 "c.nge",
5810 "c.le",
5811 "c.ngt",
5812 };
5a1e8ffb
TS
5813 const char *condnames_abs[] = {
5814 "cabs.f",
5815 "cabs.un",
5816 "cabs.eq",
5817 "cabs.ueq",
5818 "cabs.olt",
5819 "cabs.ult",
5820 "cabs.ole",
5821 "cabs.ule",
5822 "cabs.sf",
5823 "cabs.ngle",
5824 "cabs.seq",
5825 "cabs.ngl",
5826 "cabs.lt",
5827 "cabs.nge",
5828 "cabs.le",
5829 "cabs.ngt",
5830 };
5831 enum { BINOP, CMPOP, OTHEROP } optype = OTHEROP;
7a387fff
TS
5832 uint32_t func = ctx->opcode & 0x3f;
5833
6ea83fed 5834 switch (ctx->opcode & FOP(0x3f, 0x1f)) {
5a5012ec 5835 case FOP(0, 16):
b6d96bed 5836 {
a7812ae4
PB
5837 TCGv_i32 fp0 = tcg_temp_new_i32();
5838 TCGv_i32 fp1 = tcg_temp_new_i32();
b6d96bed
TS
5839
5840 gen_load_fpr32(fp0, fs);
5841 gen_load_fpr32(fp1, ft);
a7812ae4
PB
5842 gen_helper_float_add_s(fp0, fp0, fp1);
5843 tcg_temp_free_i32(fp1);
b6d96bed 5844 gen_store_fpr32(fp0, fd);
a7812ae4 5845 tcg_temp_free_i32(fp0);
b6d96bed 5846 }
5a5012ec 5847 opn = "add.s";
5a1e8ffb 5848 optype = BINOP;
5a5012ec
TS
5849 break;
5850 case FOP(1, 16):
b6d96bed 5851 {
a7812ae4
PB
5852 TCGv_i32 fp0 = tcg_temp_new_i32();
5853 TCGv_i32 fp1 = tcg_temp_new_i32();
b6d96bed
TS
5854
5855 gen_load_fpr32(fp0, fs);
5856 gen_load_fpr32(fp1, ft);
a7812ae4
PB
5857 gen_helper_float_sub_s(fp0, fp0, fp1);
5858 tcg_temp_free_i32(fp1);
b6d96bed 5859 gen_store_fpr32(fp0, fd);
a7812ae4 5860 tcg_temp_free_i32(fp0);
b6d96bed 5861 }
5a5012ec 5862 opn = "sub.s";
5a1e8ffb 5863 optype = BINOP;
5a5012ec
TS
5864 break;
5865 case FOP(2, 16):
b6d96bed 5866 {
a7812ae4
PB
5867 TCGv_i32 fp0 = tcg_temp_new_i32();
5868 TCGv_i32 fp1 = tcg_temp_new_i32();
b6d96bed
TS
5869
5870 gen_load_fpr32(fp0, fs);
5871 gen_load_fpr32(fp1, ft);
a7812ae4
PB
5872 gen_helper_float_mul_s(fp0, fp0, fp1);
5873 tcg_temp_free_i32(fp1);
b6d96bed 5874 gen_store_fpr32(fp0, fd);
a7812ae4 5875 tcg_temp_free_i32(fp0);
b6d96bed 5876 }
5a5012ec 5877 opn = "mul.s";
5a1e8ffb 5878 optype = BINOP;
5a5012ec
TS
5879 break;
5880 case FOP(3, 16):
b6d96bed 5881 {
a7812ae4
PB
5882 TCGv_i32 fp0 = tcg_temp_new_i32();
5883 TCGv_i32 fp1 = tcg_temp_new_i32();
b6d96bed
TS
5884
5885 gen_load_fpr32(fp0, fs);
5886 gen_load_fpr32(fp1, ft);
a7812ae4
PB
5887 gen_helper_float_div_s(fp0, fp0, fp1);
5888 tcg_temp_free_i32(fp1);
b6d96bed 5889 gen_store_fpr32(fp0, fd);
a7812ae4 5890 tcg_temp_free_i32(fp0);
b6d96bed 5891 }
5a5012ec 5892 opn = "div.s";
5a1e8ffb 5893 optype = BINOP;
5a5012ec
TS
5894 break;
5895 case FOP(4, 16):
b6d96bed 5896 {
a7812ae4 5897 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed
TS
5898
5899 gen_load_fpr32(fp0, fs);
a7812ae4 5900 gen_helper_float_sqrt_s(fp0, fp0);
b6d96bed 5901 gen_store_fpr32(fp0, fd);
a7812ae4 5902 tcg_temp_free_i32(fp0);
b6d96bed 5903 }
5a5012ec
TS
5904 opn = "sqrt.s";
5905 break;
5906 case FOP(5, 16):
b6d96bed 5907 {
a7812ae4 5908 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed
TS
5909
5910 gen_load_fpr32(fp0, fs);
a7812ae4 5911 gen_helper_float_abs_s(fp0, fp0);
b6d96bed 5912 gen_store_fpr32(fp0, fd);
a7812ae4 5913 tcg_temp_free_i32(fp0);
b6d96bed 5914 }
5a5012ec
TS
5915 opn = "abs.s";
5916 break;
5917 case FOP(6, 16):
b6d96bed 5918 {
a7812ae4 5919 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed
TS
5920
5921 gen_load_fpr32(fp0, fs);
5922 gen_store_fpr32(fp0, fd);
a7812ae4 5923 tcg_temp_free_i32(fp0);
b6d96bed 5924 }
5a5012ec
TS
5925 opn = "mov.s";
5926 break;
5927 case FOP(7, 16):
b6d96bed 5928 {
a7812ae4 5929 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed
TS
5930
5931 gen_load_fpr32(fp0, fs);
a7812ae4 5932 gen_helper_float_chs_s(fp0, fp0);
b6d96bed 5933 gen_store_fpr32(fp0, fd);
a7812ae4 5934 tcg_temp_free_i32(fp0);
b6d96bed 5935 }
5a5012ec
TS
5936 opn = "neg.s";
5937 break;
5938 case FOP(8, 16):
5e755519 5939 check_cp1_64bitmode(ctx);
b6d96bed 5940 {
a7812ae4
PB
5941 TCGv_i32 fp32 = tcg_temp_new_i32();
5942 TCGv_i64 fp64 = tcg_temp_new_i64();
b6d96bed
TS
5943
5944 gen_load_fpr32(fp32, fs);
a7812ae4
PB
5945 gen_helper_float_roundl_s(fp64, fp32);
5946 tcg_temp_free_i32(fp32);
b6d96bed 5947 gen_store_fpr64(ctx, fp64, fd);
a7812ae4 5948 tcg_temp_free_i64(fp64);
b6d96bed 5949 }
5a5012ec
TS
5950 opn = "round.l.s";
5951 break;
5952 case FOP(9, 16):
5e755519 5953 check_cp1_64bitmode(ctx);
b6d96bed 5954 {
a7812ae4
PB
5955 TCGv_i32 fp32 = tcg_temp_new_i32();
5956 TCGv_i64 fp64 = tcg_temp_new_i64();
b6d96bed
TS
5957
5958 gen_load_fpr32(fp32, fs);
a7812ae4
PB
5959 gen_helper_float_truncl_s(fp64, fp32);
5960 tcg_temp_free_i32(fp32);
b6d96bed 5961 gen_store_fpr64(ctx, fp64, fd);
a7812ae4 5962 tcg_temp_free_i64(fp64);
b6d96bed 5963 }
5a5012ec
TS
5964 opn = "trunc.l.s";
5965 break;
5966 case FOP(10, 16):
5e755519 5967 check_cp1_64bitmode(ctx);
b6d96bed 5968 {
a7812ae4
PB
5969 TCGv_i32 fp32 = tcg_temp_new_i32();
5970 TCGv_i64 fp64 = tcg_temp_new_i64();
b6d96bed
TS
5971
5972 gen_load_fpr32(fp32, fs);
a7812ae4
PB
5973 gen_helper_float_ceill_s(fp64, fp32);
5974 tcg_temp_free_i32(fp32);
b6d96bed 5975 gen_store_fpr64(ctx, fp64, fd);
a7812ae4 5976 tcg_temp_free_i64(fp64);
b6d96bed 5977 }
5a5012ec
TS
5978 opn = "ceil.l.s";
5979 break;
5980 case FOP(11, 16):
5e755519 5981 check_cp1_64bitmode(ctx);
b6d96bed 5982 {
a7812ae4
PB
5983 TCGv_i32 fp32 = tcg_temp_new_i32();
5984 TCGv_i64 fp64 = tcg_temp_new_i64();
b6d96bed
TS
5985
5986 gen_load_fpr32(fp32, fs);
a7812ae4
PB
5987 gen_helper_float_floorl_s(fp64, fp32);
5988 tcg_temp_free_i32(fp32);
b6d96bed 5989 gen_store_fpr64(ctx, fp64, fd);
a7812ae4 5990 tcg_temp_free_i64(fp64);
b6d96bed 5991 }
5a5012ec
TS
5992 opn = "floor.l.s";
5993 break;
5994 case FOP(12, 16):
b6d96bed 5995 {
a7812ae4 5996 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed
TS
5997
5998 gen_load_fpr32(fp0, fs);
a7812ae4 5999 gen_helper_float_roundw_s(fp0, fp0);
b6d96bed 6000 gen_store_fpr32(fp0, fd);
a7812ae4 6001 tcg_temp_free_i32(fp0);
b6d96bed 6002 }
5a5012ec
TS
6003 opn = "round.w.s";
6004 break;
6005 case FOP(13, 16):
b6d96bed 6006 {
a7812ae4 6007 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed
TS
6008
6009 gen_load_fpr32(fp0, fs);
a7812ae4 6010 gen_helper_float_truncw_s(fp0, fp0);
b6d96bed 6011 gen_store_fpr32(fp0, fd);
a7812ae4 6012 tcg_temp_free_i32(fp0);
b6d96bed 6013 }
5a5012ec
TS
6014 opn = "trunc.w.s";
6015 break;
6016 case FOP(14, 16):
b6d96bed 6017 {
a7812ae4 6018 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed
TS
6019
6020 gen_load_fpr32(fp0, fs);
a7812ae4 6021 gen_helper_float_ceilw_s(fp0, fp0);
b6d96bed 6022 gen_store_fpr32(fp0, fd);
a7812ae4 6023 tcg_temp_free_i32(fp0);
b6d96bed 6024 }
5a5012ec
TS
6025 opn = "ceil.w.s";
6026 break;
6027 case FOP(15, 16):
b6d96bed 6028 {
a7812ae4 6029 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed
TS
6030
6031 gen_load_fpr32(fp0, fs);
a7812ae4 6032 gen_helper_float_floorw_s(fp0, fp0);
b6d96bed 6033 gen_store_fpr32(fp0, fd);
a7812ae4 6034 tcg_temp_free_i32(fp0);
b6d96bed 6035 }
5a5012ec
TS
6036 opn = "floor.w.s";
6037 break;
6038 case FOP(17, 16):
b6d96bed 6039 gen_movcf_s(fs, fd, (ft >> 2) & 0x7, ft & 0x1);
5a5012ec
TS
6040 opn = "movcf.s";
6041 break;
6042 case FOP(18, 16):
a16336e4
TS
6043 {
6044 int l1 = gen_new_label();
a7812ae4
PB
6045 TCGv t0 = tcg_temp_new();
6046 TCGv_i32 fp0 = tcg_temp_local_new_i32();
a16336e4 6047
6c5c1e20
TS
6048 gen_load_gpr(t0, ft);
6049 tcg_gen_brcondi_tl(TCG_COND_NE, t0, 0, l1);
b6d96bed
TS
6050 gen_load_fpr32(fp0, fs);
6051 gen_store_fpr32(fp0, fd);
a7812ae4 6052 tcg_temp_free_i32(fp0);
a16336e4 6053 gen_set_label(l1);
2a0ab998 6054 tcg_temp_free(t0);
a16336e4 6055 }
5a5012ec
TS
6056 opn = "movz.s";
6057 break;
6058 case FOP(19, 16):
a16336e4
TS
6059 {
6060 int l1 = gen_new_label();
a7812ae4
PB
6061 TCGv t0 = tcg_temp_new();
6062 TCGv_i32 fp0 = tcg_temp_local_new_i32();
a16336e4 6063
6c5c1e20
TS
6064 gen_load_gpr(t0, ft);
6065 tcg_gen_brcondi_tl(TCG_COND_EQ, t0, 0, l1);
b6d96bed
TS
6066 gen_load_fpr32(fp0, fs);
6067 gen_store_fpr32(fp0, fd);
a7812ae4 6068 tcg_temp_free_i32(fp0);
a16336e4 6069 gen_set_label(l1);
2a0ab998 6070 tcg_temp_free(t0);
a16336e4 6071 }
5a5012ec
TS
6072 opn = "movn.s";
6073 break;
57fa1fb3 6074 case FOP(21, 16):
b8aa4598 6075 check_cop1x(ctx);
b6d96bed 6076 {
a7812ae4 6077 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed
TS
6078
6079 gen_load_fpr32(fp0, fs);
a7812ae4 6080 gen_helper_float_recip_s(fp0, fp0);
b6d96bed 6081 gen_store_fpr32(fp0, fd);
a7812ae4 6082 tcg_temp_free_i32(fp0);
b6d96bed 6083 }
57fa1fb3
TS
6084 opn = "recip.s";
6085 break;
6086 case FOP(22, 16):
b8aa4598 6087 check_cop1x(ctx);
b6d96bed 6088 {
a7812ae4 6089 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed
TS
6090
6091 gen_load_fpr32(fp0, fs);
a7812ae4 6092 gen_helper_float_rsqrt_s(fp0, fp0);
b6d96bed 6093 gen_store_fpr32(fp0, fd);
a7812ae4 6094 tcg_temp_free_i32(fp0);
b6d96bed 6095 }
57fa1fb3
TS
6096 opn = "rsqrt.s";
6097 break;
6098 case FOP(28, 16):
5e755519 6099 check_cp1_64bitmode(ctx);
b6d96bed 6100 {
a7812ae4
PB
6101 TCGv_i32 fp0 = tcg_temp_new_i32();
6102 TCGv_i32 fp1 = tcg_temp_new_i32();
b6d96bed
TS
6103
6104 gen_load_fpr32(fp0, fs);
6105 gen_load_fpr32(fp1, fd);
a7812ae4
PB
6106 gen_helper_float_recip2_s(fp0, fp0, fp1);
6107 tcg_temp_free_i32(fp1);
b6d96bed 6108 gen_store_fpr32(fp0, fd);
a7812ae4 6109 tcg_temp_free_i32(fp0);
b6d96bed 6110 }
57fa1fb3
TS
6111 opn = "recip2.s";
6112 break;
6113 case FOP(29, 16):
5e755519 6114 check_cp1_64bitmode(ctx);
b6d96bed 6115 {
a7812ae4 6116 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed
TS
6117
6118 gen_load_fpr32(fp0, fs);
a7812ae4 6119 gen_helper_float_recip1_s(fp0, fp0);
b6d96bed 6120 gen_store_fpr32(fp0, fd);
a7812ae4 6121 tcg_temp_free_i32(fp0);
b6d96bed 6122 }
57fa1fb3
TS
6123 opn = "recip1.s";
6124 break;
6125 case FOP(30, 16):
5e755519 6126 check_cp1_64bitmode(ctx);
b6d96bed 6127 {
a7812ae4 6128 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed
TS
6129
6130 gen_load_fpr32(fp0, fs);
a7812ae4 6131 gen_helper_float_rsqrt1_s(fp0, fp0);
b6d96bed 6132 gen_store_fpr32(fp0, fd);
a7812ae4 6133 tcg_temp_free_i32(fp0);
b6d96bed 6134 }
57fa1fb3
TS
6135 opn = "rsqrt1.s";
6136 break;
6137 case FOP(31, 16):
5e755519 6138 check_cp1_64bitmode(ctx);
b6d96bed 6139 {
a7812ae4
PB
6140 TCGv_i32 fp0 = tcg_temp_new_i32();
6141 TCGv_i32 fp1 = tcg_temp_new_i32();
b6d96bed
TS
6142
6143 gen_load_fpr32(fp0, fs);
6144 gen_load_fpr32(fp1, ft);
a7812ae4
PB
6145 gen_helper_float_rsqrt2_s(fp0, fp0, fp1);
6146 tcg_temp_free_i32(fp1);
b6d96bed 6147 gen_store_fpr32(fp0, fd);
a7812ae4 6148 tcg_temp_free_i32(fp0);
b6d96bed 6149 }
57fa1fb3
TS
6150 opn = "rsqrt2.s";
6151 break;
5a5012ec 6152 case FOP(33, 16):
5e755519 6153 check_cp1_registers(ctx, fd);
b6d96bed 6154 {
a7812ae4
PB
6155 TCGv_i32 fp32 = tcg_temp_new_i32();
6156 TCGv_i64 fp64 = tcg_temp_new_i64();
b6d96bed
TS
6157
6158 gen_load_fpr32(fp32, fs);
a7812ae4
PB
6159 gen_helper_float_cvtd_s(fp64, fp32);
6160 tcg_temp_free_i32(fp32);
b6d96bed 6161 gen_store_fpr64(ctx, fp64, fd);
a7812ae4 6162 tcg_temp_free_i64(fp64);
b6d96bed 6163 }
5a5012ec
TS
6164 opn = "cvt.d.s";
6165 break;
6166 case FOP(36, 16):
b6d96bed 6167 {
a7812ae4 6168 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed
TS
6169
6170 gen_load_fpr32(fp0, fs);
a7812ae4 6171 gen_helper_float_cvtw_s(fp0, fp0);
b6d96bed 6172 gen_store_fpr32(fp0, fd);
a7812ae4 6173 tcg_temp_free_i32(fp0);
b6d96bed 6174 }
5a5012ec
TS
6175 opn = "cvt.w.s";
6176 break;
6177 case FOP(37, 16):
5e755519 6178 check_cp1_64bitmode(ctx);
b6d96bed 6179 {
a7812ae4
PB
6180 TCGv_i32 fp32 = tcg_temp_new_i32();
6181 TCGv_i64 fp64 = tcg_temp_new_i64();
b6d96bed
TS
6182
6183 gen_load_fpr32(fp32, fs);
a7812ae4
PB
6184 gen_helper_float_cvtl_s(fp64, fp32);
6185 tcg_temp_free_i32(fp32);
b6d96bed 6186 gen_store_fpr64(ctx, fp64, fd);
a7812ae4 6187 tcg_temp_free_i64(fp64);
b6d96bed 6188 }
5a5012ec
TS
6189 opn = "cvt.l.s";
6190 break;
6191 case FOP(38, 16):
5e755519 6192 check_cp1_64bitmode(ctx);
b6d96bed 6193 {
a7812ae4
PB
6194 TCGv_i64 fp64 = tcg_temp_new_i64();
6195 TCGv_i32 fp32_0 = tcg_temp_new_i32();
6196 TCGv_i32 fp32_1 = tcg_temp_new_i32();
b6d96bed
TS
6197
6198 gen_load_fpr32(fp32_0, fs);
6199 gen_load_fpr32(fp32_1, ft);
36aa55dc 6200 tcg_gen_concat_i32_i64(fp64, fp32_0, fp32_1);
a7812ae4
PB
6201 tcg_temp_free_i32(fp32_1);
6202 tcg_temp_free_i32(fp32_0);
36aa55dc 6203 gen_store_fpr64(ctx, fp64, fd);
a7812ae4 6204 tcg_temp_free_i64(fp64);
b6d96bed 6205 }
5a5012ec
TS
6206 opn = "cvt.ps.s";
6207 break;
6208 case FOP(48, 16):
6209 case FOP(49, 16):
6210 case FOP(50, 16):
6211 case FOP(51, 16):
6212 case FOP(52, 16):
6213 case FOP(53, 16):
6214 case FOP(54, 16):
6215 case FOP(55, 16):
6216 case FOP(56, 16):
6217 case FOP(57, 16):
6218 case FOP(58, 16):
6219 case FOP(59, 16):
6220 case FOP(60, 16):
6221 case FOP(61, 16):
6222 case FOP(62, 16):
6223 case FOP(63, 16):
b6d96bed 6224 {
a7812ae4
PB
6225 TCGv_i32 fp0 = tcg_temp_new_i32();
6226 TCGv_i32 fp1 = tcg_temp_new_i32();
b6d96bed
TS
6227
6228 gen_load_fpr32(fp0, fs);
6229 gen_load_fpr32(fp1, ft);
6230 if (ctx->opcode & (1 << 6)) {
6231 check_cop1x(ctx);
6232 gen_cmpabs_s(func-48, fp0, fp1, cc);
6233 opn = condnames_abs[func-48];
6234 } else {
6235 gen_cmp_s(func-48, fp0, fp1, cc);
6236 opn = condnames[func-48];
6237 }
a7812ae4
PB
6238 tcg_temp_free_i32(fp0);
6239 tcg_temp_free_i32(fp1);
5a1e8ffb 6240 }
5a5012ec 6241 break;
6ea83fed 6242 case FOP(0, 17):
5e755519 6243 check_cp1_registers(ctx, fs | ft | fd);
b6d96bed 6244 {
a7812ae4
PB
6245 TCGv_i64 fp0 = tcg_temp_new_i64();
6246 TCGv_i64 fp1 = tcg_temp_new_i64();
b6d96bed
TS
6247
6248 gen_load_fpr64(ctx, fp0, fs);
6249 gen_load_fpr64(ctx, fp1, ft);
a7812ae4
PB
6250 gen_helper_float_add_d(fp0, fp0, fp1);
6251 tcg_temp_free_i64(fp1);
b6d96bed 6252 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 6253 tcg_temp_free_i64(fp0);
b6d96bed 6254 }
6ea83fed 6255 opn = "add.d";
5a1e8ffb 6256 optype = BINOP;
6ea83fed
FB
6257 break;
6258 case FOP(1, 17):
5e755519 6259 check_cp1_registers(ctx, fs | ft | fd);
b6d96bed 6260 {
a7812ae4
PB
6261 TCGv_i64 fp0 = tcg_temp_new_i64();
6262 TCGv_i64 fp1 = tcg_temp_new_i64();
b6d96bed
TS
6263
6264 gen_load_fpr64(ctx, fp0, fs);
6265 gen_load_fpr64(ctx, fp1, ft);
a7812ae4
PB
6266 gen_helper_float_sub_d(fp0, fp0, fp1);
6267 tcg_temp_free_i64(fp1);
b6d96bed 6268 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 6269 tcg_temp_free_i64(fp0);
b6d96bed 6270 }
6ea83fed 6271 opn = "sub.d";
5a1e8ffb 6272 optype = BINOP;
6ea83fed
FB
6273 break;
6274 case FOP(2, 17):
5e755519 6275 check_cp1_registers(ctx, fs | ft | fd);
b6d96bed 6276 {
a7812ae4
PB
6277 TCGv_i64 fp0 = tcg_temp_new_i64();
6278 TCGv_i64 fp1 = tcg_temp_new_i64();
b6d96bed
TS
6279
6280 gen_load_fpr64(ctx, fp0, fs);
6281 gen_load_fpr64(ctx, fp1, ft);
a7812ae4
PB
6282 gen_helper_float_mul_d(fp0, fp0, fp1);
6283 tcg_temp_free_i64(fp1);
b6d96bed 6284 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 6285 tcg_temp_free_i64(fp0);
b6d96bed 6286 }
6ea83fed 6287 opn = "mul.d";
5a1e8ffb 6288 optype = BINOP;
6ea83fed
FB
6289 break;
6290 case FOP(3, 17):
5e755519 6291 check_cp1_registers(ctx, fs | ft | fd);
b6d96bed 6292 {
a7812ae4
PB
6293 TCGv_i64 fp0 = tcg_temp_new_i64();
6294 TCGv_i64 fp1 = tcg_temp_new_i64();
b6d96bed
TS
6295
6296 gen_load_fpr64(ctx, fp0, fs);
6297 gen_load_fpr64(ctx, fp1, ft);
a7812ae4
PB
6298 gen_helper_float_div_d(fp0, fp0, fp1);
6299 tcg_temp_free_i64(fp1);
b6d96bed 6300 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 6301 tcg_temp_free_i64(fp0);
b6d96bed 6302 }
6ea83fed 6303 opn = "div.d";
5a1e8ffb 6304 optype = BINOP;
6ea83fed
FB
6305 break;
6306 case FOP(4, 17):
5e755519 6307 check_cp1_registers(ctx, fs | fd);
b6d96bed 6308 {
a7812ae4 6309 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
6310
6311 gen_load_fpr64(ctx, fp0, fs);
a7812ae4 6312 gen_helper_float_sqrt_d(fp0, fp0);
b6d96bed 6313 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 6314 tcg_temp_free_i64(fp0);
b6d96bed 6315 }
6ea83fed
FB
6316 opn = "sqrt.d";
6317 break;
6318 case FOP(5, 17):
5e755519 6319 check_cp1_registers(ctx, fs | fd);
b6d96bed 6320 {
a7812ae4 6321 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
6322
6323 gen_load_fpr64(ctx, fp0, fs);
a7812ae4 6324 gen_helper_float_abs_d(fp0, fp0);
b6d96bed 6325 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 6326 tcg_temp_free_i64(fp0);
b6d96bed 6327 }
6ea83fed
FB
6328 opn = "abs.d";
6329 break;
6330 case FOP(6, 17):
5e755519 6331 check_cp1_registers(ctx, fs | fd);
b6d96bed 6332 {
a7812ae4 6333 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
6334
6335 gen_load_fpr64(ctx, fp0, fs);
6336 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 6337 tcg_temp_free_i64(fp0);
b6d96bed 6338 }
6ea83fed
FB
6339 opn = "mov.d";
6340 break;
6341 case FOP(7, 17):
5e755519 6342 check_cp1_registers(ctx, fs | fd);
b6d96bed 6343 {
a7812ae4 6344 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
6345
6346 gen_load_fpr64(ctx, fp0, fs);
a7812ae4 6347 gen_helper_float_chs_d(fp0, fp0);
b6d96bed 6348 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 6349 tcg_temp_free_i64(fp0);
b6d96bed 6350 }
6ea83fed
FB
6351 opn = "neg.d";
6352 break;
5a5012ec 6353 case FOP(8, 17):
5e755519 6354 check_cp1_64bitmode(ctx);
b6d96bed 6355 {
a7812ae4 6356 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
6357
6358 gen_load_fpr64(ctx, fp0, fs);
a7812ae4 6359 gen_helper_float_roundl_d(fp0, fp0);
b6d96bed 6360 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 6361 tcg_temp_free_i64(fp0);
b6d96bed 6362 }
5a5012ec
TS
6363 opn = "round.l.d";
6364 break;
6365 case FOP(9, 17):
5e755519 6366 check_cp1_64bitmode(ctx);
b6d96bed 6367 {
a7812ae4 6368 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
6369
6370 gen_load_fpr64(ctx, fp0, fs);
a7812ae4 6371 gen_helper_float_truncl_d(fp0, fp0);
b6d96bed 6372 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 6373 tcg_temp_free_i64(fp0);
b6d96bed 6374 }
5a5012ec
TS
6375 opn = "trunc.l.d";
6376 break;
6377 case FOP(10, 17):
5e755519 6378 check_cp1_64bitmode(ctx);
b6d96bed 6379 {
a7812ae4 6380 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
6381
6382 gen_load_fpr64(ctx, fp0, fs);
a7812ae4 6383 gen_helper_float_ceill_d(fp0, fp0);
b6d96bed 6384 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 6385 tcg_temp_free_i64(fp0);
b6d96bed 6386 }
5a5012ec
TS
6387 opn = "ceil.l.d";
6388 break;
6389 case FOP(11, 17):
5e755519 6390 check_cp1_64bitmode(ctx);
b6d96bed 6391 {
a7812ae4 6392 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
6393
6394 gen_load_fpr64(ctx, fp0, fs);
a7812ae4 6395 gen_helper_float_floorl_d(fp0, fp0);
b6d96bed 6396 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 6397 tcg_temp_free_i64(fp0);
b6d96bed 6398 }
5a5012ec
TS
6399 opn = "floor.l.d";
6400 break;
6ea83fed 6401 case FOP(12, 17):
5e755519 6402 check_cp1_registers(ctx, fs);
b6d96bed 6403 {
a7812ae4
PB
6404 TCGv_i32 fp32 = tcg_temp_new_i32();
6405 TCGv_i64 fp64 = tcg_temp_new_i64();
b6d96bed
TS
6406
6407 gen_load_fpr64(ctx, fp64, fs);
a7812ae4
PB
6408 gen_helper_float_roundw_d(fp32, fp64);
6409 tcg_temp_free_i64(fp64);
b6d96bed 6410 gen_store_fpr32(fp32, fd);
a7812ae4 6411 tcg_temp_free_i32(fp32);
b6d96bed 6412 }
6ea83fed
FB
6413 opn = "round.w.d";
6414 break;
6415 case FOP(13, 17):
5e755519 6416 check_cp1_registers(ctx, fs);
b6d96bed 6417 {
a7812ae4
PB
6418 TCGv_i32 fp32 = tcg_temp_new_i32();
6419 TCGv_i64 fp64 = tcg_temp_new_i64();
b6d96bed
TS
6420
6421 gen_load_fpr64(ctx, fp64, fs);
a7812ae4
PB
6422 gen_helper_float_truncw_d(fp32, fp64);
6423 tcg_temp_free_i64(fp64);
b6d96bed 6424 gen_store_fpr32(fp32, fd);
a7812ae4 6425 tcg_temp_free_i32(fp32);
b6d96bed 6426 }
6ea83fed
FB
6427 opn = "trunc.w.d";
6428 break;
6429 case FOP(14, 17):
5e755519 6430 check_cp1_registers(ctx, fs);
b6d96bed 6431 {
a7812ae4
PB
6432 TCGv_i32 fp32 = tcg_temp_new_i32();
6433 TCGv_i64 fp64 = tcg_temp_new_i64();
b6d96bed
TS
6434
6435 gen_load_fpr64(ctx, fp64, fs);
a7812ae4
PB
6436 gen_helper_float_ceilw_d(fp32, fp64);
6437 tcg_temp_free_i64(fp64);
b6d96bed 6438 gen_store_fpr32(fp32, fd);
a7812ae4 6439 tcg_temp_free_i32(fp32);
b6d96bed 6440 }
6ea83fed
FB
6441 opn = "ceil.w.d";
6442 break;
6443 case FOP(15, 17):
5e755519 6444 check_cp1_registers(ctx, fs);
b6d96bed 6445 {
a7812ae4
PB
6446 TCGv_i32 fp32 = tcg_temp_new_i32();
6447 TCGv_i64 fp64 = tcg_temp_new_i64();
b6d96bed
TS
6448
6449 gen_load_fpr64(ctx, fp64, fs);
a7812ae4
PB
6450 gen_helper_float_floorw_d(fp32, fp64);
6451 tcg_temp_free_i64(fp64);
b6d96bed 6452 gen_store_fpr32(fp32, fd);
a7812ae4 6453 tcg_temp_free_i32(fp32);
b6d96bed 6454 }
7a387fff 6455 opn = "floor.w.d";
6ea83fed 6456 break;
5a5012ec 6457 case FOP(17, 17):
b6d96bed 6458 gen_movcf_d(ctx, fs, fd, (ft >> 2) & 0x7, ft & 0x1);
5a5012ec 6459 opn = "movcf.d";
dd016883 6460 break;
5a5012ec 6461 case FOP(18, 17):
a16336e4
TS
6462 {
6463 int l1 = gen_new_label();
a7812ae4
PB
6464 TCGv t0 = tcg_temp_new();
6465 TCGv_i64 fp0 = tcg_temp_local_new_i64();
a16336e4 6466
6c5c1e20
TS
6467 gen_load_gpr(t0, ft);
6468 tcg_gen_brcondi_tl(TCG_COND_NE, t0, 0, l1);
b6d96bed
TS
6469 gen_load_fpr64(ctx, fp0, fs);
6470 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 6471 tcg_temp_free_i64(fp0);
a16336e4 6472 gen_set_label(l1);
2a0ab998 6473 tcg_temp_free(t0);
a16336e4 6474 }
5a5012ec
TS
6475 opn = "movz.d";
6476 break;
6477 case FOP(19, 17):
a16336e4
TS
6478 {
6479 int l1 = gen_new_label();
a7812ae4
PB
6480 TCGv t0 = tcg_temp_new();
6481 TCGv_i64 fp0 = tcg_temp_local_new_i64();
a16336e4 6482
6c5c1e20
TS
6483 gen_load_gpr(t0, ft);
6484 tcg_gen_brcondi_tl(TCG_COND_EQ, t0, 0, l1);
b6d96bed
TS
6485 gen_load_fpr64(ctx, fp0, fs);
6486 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 6487 tcg_temp_free_i64(fp0);
a16336e4 6488 gen_set_label(l1);
2a0ab998 6489 tcg_temp_free(t0);
a16336e4 6490 }
5a5012ec 6491 opn = "movn.d";
6ea83fed 6492 break;
57fa1fb3 6493 case FOP(21, 17):
b8aa4598 6494 check_cp1_64bitmode(ctx);
b6d96bed 6495 {
a7812ae4 6496 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
6497
6498 gen_load_fpr64(ctx, fp0, fs);
a7812ae4 6499 gen_helper_float_recip_d(fp0, fp0);
b6d96bed 6500 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 6501 tcg_temp_free_i64(fp0);
b6d96bed 6502 }
57fa1fb3
TS
6503 opn = "recip.d";
6504 break;
6505 case FOP(22, 17):
b8aa4598 6506 check_cp1_64bitmode(ctx);
b6d96bed 6507 {
a7812ae4 6508 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
6509
6510 gen_load_fpr64(ctx, fp0, fs);
a7812ae4 6511 gen_helper_float_rsqrt_d(fp0, fp0);
b6d96bed 6512 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 6513 tcg_temp_free_i64(fp0);
b6d96bed 6514 }
57fa1fb3
TS
6515 opn = "rsqrt.d";
6516 break;
6517 case FOP(28, 17):
5e755519 6518 check_cp1_64bitmode(ctx);
b6d96bed 6519 {
a7812ae4
PB
6520 TCGv_i64 fp0 = tcg_temp_new_i64();
6521 TCGv_i64 fp1 = tcg_temp_new_i64();
b6d96bed
TS
6522
6523 gen_load_fpr64(ctx, fp0, fs);
6524 gen_load_fpr64(ctx, fp1, ft);
a7812ae4
PB
6525 gen_helper_float_recip2_d(fp0, fp0, fp1);
6526 tcg_temp_free_i64(fp1);
b6d96bed 6527 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 6528 tcg_temp_free_i64(fp0);
b6d96bed 6529 }
57fa1fb3
TS
6530 opn = "recip2.d";
6531 break;
6532 case FOP(29, 17):
5e755519 6533 check_cp1_64bitmode(ctx);
b6d96bed 6534 {
a7812ae4 6535 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
6536
6537 gen_load_fpr64(ctx, fp0, fs);
a7812ae4 6538 gen_helper_float_recip1_d(fp0, fp0);
b6d96bed 6539 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 6540 tcg_temp_free_i64(fp0);
b6d96bed 6541 }
57fa1fb3
TS
6542 opn = "recip1.d";
6543 break;
6544 case FOP(30, 17):
5e755519 6545 check_cp1_64bitmode(ctx);
b6d96bed 6546 {
a7812ae4 6547 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
6548
6549 gen_load_fpr64(ctx, fp0, fs);
a7812ae4 6550 gen_helper_float_rsqrt1_d(fp0, fp0);
b6d96bed 6551 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 6552 tcg_temp_free_i64(fp0);
b6d96bed 6553 }
57fa1fb3
TS
6554 opn = "rsqrt1.d";
6555 break;
6556 case FOP(31, 17):
5e755519 6557 check_cp1_64bitmode(ctx);
b6d96bed 6558 {
a7812ae4
PB
6559 TCGv_i64 fp0 = tcg_temp_new_i64();
6560 TCGv_i64 fp1 = tcg_temp_new_i64();
b6d96bed
TS
6561
6562 gen_load_fpr64(ctx, fp0, fs);
6563 gen_load_fpr64(ctx, fp1, ft);
a7812ae4
PB
6564 gen_helper_float_rsqrt2_d(fp0, fp0, fp1);
6565 tcg_temp_free_i64(fp1);
b6d96bed 6566 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 6567 tcg_temp_free_i64(fp0);
b6d96bed 6568 }
57fa1fb3
TS
6569 opn = "rsqrt2.d";
6570 break;
6ea83fed
FB
6571 case FOP(48, 17):
6572 case FOP(49, 17):
6573 case FOP(50, 17):
6574 case FOP(51, 17):
6575 case FOP(52, 17):
6576 case FOP(53, 17):
6577 case FOP(54, 17):
6578 case FOP(55, 17):
6579 case FOP(56, 17):
6580 case FOP(57, 17):
6581 case FOP(58, 17):
6582 case FOP(59, 17):
6583 case FOP(60, 17):
6584 case FOP(61, 17):
6585 case FOP(62, 17):
6586 case FOP(63, 17):
b6d96bed 6587 {
a7812ae4
PB
6588 TCGv_i64 fp0 = tcg_temp_new_i64();
6589 TCGv_i64 fp1 = tcg_temp_new_i64();
b6d96bed
TS
6590
6591 gen_load_fpr64(ctx, fp0, fs);
6592 gen_load_fpr64(ctx, fp1, ft);
6593 if (ctx->opcode & (1 << 6)) {
6594 check_cop1x(ctx);
6595 check_cp1_registers(ctx, fs | ft);
6596 gen_cmpabs_d(func-48, fp0, fp1, cc);
6597 opn = condnames_abs[func-48];
6598 } else {
6599 check_cp1_registers(ctx, fs | ft);
6600 gen_cmp_d(func-48, fp0, fp1, cc);
6601 opn = condnames[func-48];
6602 }
a7812ae4
PB
6603 tcg_temp_free_i64(fp0);
6604 tcg_temp_free_i64(fp1);
5a1e8ffb 6605 }
6ea83fed 6606 break;
5a5012ec 6607 case FOP(32, 17):
5e755519 6608 check_cp1_registers(ctx, fs);
b6d96bed 6609 {
a7812ae4
PB
6610 TCGv_i32 fp32 = tcg_temp_new_i32();
6611 TCGv_i64 fp64 = tcg_temp_new_i64();
b6d96bed
TS
6612
6613 gen_load_fpr64(ctx, fp64, fs);
a7812ae4
PB
6614 gen_helper_float_cvts_d(fp32, fp64);
6615 tcg_temp_free_i64(fp64);
b6d96bed 6616 gen_store_fpr32(fp32, fd);
a7812ae4 6617 tcg_temp_free_i32(fp32);
b6d96bed 6618 }
5a5012ec
TS
6619 opn = "cvt.s.d";
6620 break;
6621 case FOP(36, 17):
5e755519 6622 check_cp1_registers(ctx, fs);
b6d96bed 6623 {
a7812ae4
PB
6624 TCGv_i32 fp32 = tcg_temp_new_i32();
6625 TCGv_i64 fp64 = tcg_temp_new_i64();
b6d96bed
TS
6626
6627 gen_load_fpr64(ctx, fp64, fs);
a7812ae4
PB
6628 gen_helper_float_cvtw_d(fp32, fp64);
6629 tcg_temp_free_i64(fp64);
b6d96bed 6630 gen_store_fpr32(fp32, fd);
a7812ae4 6631 tcg_temp_free_i32(fp32);
b6d96bed 6632 }
5a5012ec
TS
6633 opn = "cvt.w.d";
6634 break;
6635 case FOP(37, 17):
5e755519 6636 check_cp1_64bitmode(ctx);
b6d96bed 6637 {
a7812ae4 6638 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
6639
6640 gen_load_fpr64(ctx, fp0, fs);
a7812ae4 6641 gen_helper_float_cvtl_d(fp0, fp0);
b6d96bed 6642 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 6643 tcg_temp_free_i64(fp0);
b6d96bed 6644 }
5a5012ec
TS
6645 opn = "cvt.l.d";
6646 break;
6647 case FOP(32, 20):
b6d96bed 6648 {
a7812ae4 6649 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed
TS
6650
6651 gen_load_fpr32(fp0, fs);
a7812ae4 6652 gen_helper_float_cvts_w(fp0, fp0);
b6d96bed 6653 gen_store_fpr32(fp0, fd);
a7812ae4 6654 tcg_temp_free_i32(fp0);
b6d96bed 6655 }
5a5012ec 6656 opn = "cvt.s.w";
6ea83fed 6657 break;
5a5012ec 6658 case FOP(33, 20):
5e755519 6659 check_cp1_registers(ctx, fd);
b6d96bed 6660 {
a7812ae4
PB
6661 TCGv_i32 fp32 = tcg_temp_new_i32();
6662 TCGv_i64 fp64 = tcg_temp_new_i64();
b6d96bed
TS
6663
6664 gen_load_fpr32(fp32, fs);
a7812ae4
PB
6665 gen_helper_float_cvtd_w(fp64, fp32);
6666 tcg_temp_free_i32(fp32);
b6d96bed 6667 gen_store_fpr64(ctx, fp64, fd);
a7812ae4 6668 tcg_temp_free_i64(fp64);
b6d96bed 6669 }
5a5012ec
TS
6670 opn = "cvt.d.w";
6671 break;
6672 case FOP(32, 21):
5e755519 6673 check_cp1_64bitmode(ctx);
b6d96bed 6674 {
a7812ae4
PB
6675 TCGv_i32 fp32 = tcg_temp_new_i32();
6676 TCGv_i64 fp64 = tcg_temp_new_i64();
b6d96bed
TS
6677
6678 gen_load_fpr64(ctx, fp64, fs);
a7812ae4
PB
6679 gen_helper_float_cvts_l(fp32, fp64);
6680 tcg_temp_free_i64(fp64);
b6d96bed 6681 gen_store_fpr32(fp32, fd);
a7812ae4 6682 tcg_temp_free_i32(fp32);
b6d96bed 6683 }
5a5012ec
TS
6684 opn = "cvt.s.l";
6685 break;
6686 case FOP(33, 21):
5e755519 6687 check_cp1_64bitmode(ctx);
b6d96bed 6688 {
a7812ae4 6689 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
6690
6691 gen_load_fpr64(ctx, fp0, fs);
a7812ae4 6692 gen_helper_float_cvtd_l(fp0, fp0);
b6d96bed 6693 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 6694 tcg_temp_free_i64(fp0);
b6d96bed 6695 }
5a5012ec
TS
6696 opn = "cvt.d.l";
6697 break;
6698 case FOP(38, 20):
5e755519 6699 check_cp1_64bitmode(ctx);
b6d96bed 6700 {
a7812ae4 6701 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
6702
6703 gen_load_fpr64(ctx, fp0, fs);
a7812ae4 6704 gen_helper_float_cvtps_pw(fp0, fp0);
b6d96bed 6705 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 6706 tcg_temp_free_i64(fp0);
b6d96bed 6707 }
5a5012ec
TS
6708 opn = "cvt.ps.pw";
6709 break;
6710 case FOP(0, 22):
5e755519 6711 check_cp1_64bitmode(ctx);
b6d96bed 6712 {
a7812ae4
PB
6713 TCGv_i64 fp0 = tcg_temp_new_i64();
6714 TCGv_i64 fp1 = tcg_temp_new_i64();
b6d96bed
TS
6715
6716 gen_load_fpr64(ctx, fp0, fs);
6717 gen_load_fpr64(ctx, fp1, ft);
a7812ae4
PB
6718 gen_helper_float_add_ps(fp0, fp0, fp1);
6719 tcg_temp_free_i64(fp1);
b6d96bed 6720 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 6721 tcg_temp_free_i64(fp0);
b6d96bed 6722 }
5a5012ec 6723 opn = "add.ps";
6ea83fed 6724 break;
5a5012ec 6725 case FOP(1, 22):
5e755519 6726 check_cp1_64bitmode(ctx);
b6d96bed 6727 {
a7812ae4
PB
6728 TCGv_i64 fp0 = tcg_temp_new_i64();
6729 TCGv_i64 fp1 = tcg_temp_new_i64();
b6d96bed
TS
6730
6731 gen_load_fpr64(ctx, fp0, fs);
6732 gen_load_fpr64(ctx, fp1, ft);
a7812ae4
PB
6733 gen_helper_float_sub_ps(fp0, fp0, fp1);
6734 tcg_temp_free_i64(fp1);
b6d96bed 6735 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 6736 tcg_temp_free_i64(fp0);
b6d96bed 6737 }
5a5012ec 6738 opn = "sub.ps";
6ea83fed 6739 break;
5a5012ec 6740 case FOP(2, 22):
5e755519 6741 check_cp1_64bitmode(ctx);
b6d96bed 6742 {
a7812ae4
PB
6743 TCGv_i64 fp0 = tcg_temp_new_i64();
6744 TCGv_i64 fp1 = tcg_temp_new_i64();
b6d96bed
TS
6745
6746 gen_load_fpr64(ctx, fp0, fs);
6747 gen_load_fpr64(ctx, fp1, ft);
a7812ae4
PB
6748 gen_helper_float_mul_ps(fp0, fp0, fp1);
6749 tcg_temp_free_i64(fp1);
b6d96bed 6750 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 6751 tcg_temp_free_i64(fp0);
b6d96bed 6752 }
5a5012ec 6753 opn = "mul.ps";
6ea83fed 6754 break;
5a5012ec 6755 case FOP(5, 22):
5e755519 6756 check_cp1_64bitmode(ctx);
b6d96bed 6757 {
a7812ae4 6758 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
6759
6760 gen_load_fpr64(ctx, fp0, fs);
a7812ae4 6761 gen_helper_float_abs_ps(fp0, fp0);
b6d96bed 6762 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 6763 tcg_temp_free_i64(fp0);
b6d96bed 6764 }
5a5012ec 6765 opn = "abs.ps";
6ea83fed 6766 break;
5a5012ec 6767 case FOP(6, 22):
5e755519 6768 check_cp1_64bitmode(ctx);
b6d96bed 6769 {
a7812ae4 6770 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
6771
6772 gen_load_fpr64(ctx, fp0, fs);
6773 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 6774 tcg_temp_free_i64(fp0);
b6d96bed 6775 }
5a5012ec 6776 opn = "mov.ps";
6ea83fed 6777 break;
5a5012ec 6778 case FOP(7, 22):
5e755519 6779 check_cp1_64bitmode(ctx);
b6d96bed 6780 {
a7812ae4 6781 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
6782
6783 gen_load_fpr64(ctx, fp0, fs);
a7812ae4 6784 gen_helper_float_chs_ps(fp0, fp0);
b6d96bed 6785 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 6786 tcg_temp_free_i64(fp0);
b6d96bed 6787 }
5a5012ec 6788 opn = "neg.ps";
6ea83fed 6789 break;
5a5012ec 6790 case FOP(17, 22):
5e755519 6791 check_cp1_64bitmode(ctx);
b6d96bed 6792 gen_movcf_ps(fs, fd, (ft >> 2) & 0x7, ft & 0x1);
5a5012ec 6793 opn = "movcf.ps";
6ea83fed 6794 break;
5a5012ec 6795 case FOP(18, 22):
5e755519 6796 check_cp1_64bitmode(ctx);
a16336e4
TS
6797 {
6798 int l1 = gen_new_label();
a7812ae4
PB
6799 TCGv t0 = tcg_temp_new();
6800 TCGv_i32 fp0 = tcg_temp_local_new_i32();
6801 TCGv_i32 fph0 = tcg_temp_local_new_i32();
a16336e4 6802
6c5c1e20
TS
6803 gen_load_gpr(t0, ft);
6804 tcg_gen_brcondi_tl(TCG_COND_NE, t0, 0, l1);
b6d96bed
TS
6805 gen_load_fpr32(fp0, fs);
6806 gen_load_fpr32h(fph0, fs);
6807 gen_store_fpr32(fp0, fd);
6808 gen_store_fpr32h(fph0, fd);
a7812ae4
PB
6809 tcg_temp_free_i32(fp0);
6810 tcg_temp_free_i32(fph0);
a16336e4 6811 gen_set_label(l1);
2a0ab998 6812 tcg_temp_free(t0);
a16336e4 6813 }
5a5012ec 6814 opn = "movz.ps";
6ea83fed 6815 break;
5a5012ec 6816 case FOP(19, 22):
5e755519 6817 check_cp1_64bitmode(ctx);
a16336e4
TS
6818 {
6819 int l1 = gen_new_label();
a7812ae4
PB
6820 TCGv t0 = tcg_temp_new();
6821 TCGv_i32 fp0 = tcg_temp_local_new_i32();
6822 TCGv_i32 fph0 = tcg_temp_local_new_i32();
a16336e4 6823
6c5c1e20
TS
6824 gen_load_gpr(t0, ft);
6825 tcg_gen_brcondi_tl(TCG_COND_EQ, t0, 0, l1);
b6d96bed
TS
6826 gen_load_fpr32(fp0, fs);
6827 gen_load_fpr32h(fph0, fs);
6828 gen_store_fpr32(fp0, fd);
6829 gen_store_fpr32h(fph0, fd);
a7812ae4
PB
6830 tcg_temp_free_i32(fp0);
6831 tcg_temp_free_i32(fph0);
a16336e4 6832 gen_set_label(l1);
2a0ab998 6833 tcg_temp_free(t0);
a16336e4 6834 }
5a5012ec 6835 opn = "movn.ps";
6ea83fed 6836 break;
fbcc6828 6837 case FOP(24, 22):
5e755519 6838 check_cp1_64bitmode(ctx);
b6d96bed 6839 {
a7812ae4
PB
6840 TCGv_i64 fp0 = tcg_temp_new_i64();
6841 TCGv_i64 fp1 = tcg_temp_new_i64();
b6d96bed
TS
6842
6843 gen_load_fpr64(ctx, fp0, ft);
6844 gen_load_fpr64(ctx, fp1, fs);
a7812ae4
PB
6845 gen_helper_float_addr_ps(fp0, fp0, fp1);
6846 tcg_temp_free_i64(fp1);
b6d96bed 6847 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 6848 tcg_temp_free_i64(fp0);
b6d96bed 6849 }
fbcc6828
TS
6850 opn = "addr.ps";
6851 break;
57fa1fb3 6852 case FOP(26, 22):
5e755519 6853 check_cp1_64bitmode(ctx);
b6d96bed 6854 {
a7812ae4
PB
6855 TCGv_i64 fp0 = tcg_temp_new_i64();
6856 TCGv_i64 fp1 = tcg_temp_new_i64();
b6d96bed
TS
6857
6858 gen_load_fpr64(ctx, fp0, ft);
6859 gen_load_fpr64(ctx, fp1, fs);
a7812ae4
PB
6860 gen_helper_float_mulr_ps(fp0, fp0, fp1);
6861 tcg_temp_free_i64(fp1);
b6d96bed 6862 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 6863 tcg_temp_free_i64(fp0);
b6d96bed 6864 }
57fa1fb3
TS
6865 opn = "mulr.ps";
6866 break;
6867 case FOP(28, 22):
5e755519 6868 check_cp1_64bitmode(ctx);
b6d96bed 6869 {
a7812ae4
PB
6870 TCGv_i64 fp0 = tcg_temp_new_i64();
6871 TCGv_i64 fp1 = tcg_temp_new_i64();
b6d96bed
TS
6872
6873 gen_load_fpr64(ctx, fp0, fs);
6874 gen_load_fpr64(ctx, fp1, fd);
a7812ae4
PB
6875 gen_helper_float_recip2_ps(fp0, fp0, fp1);
6876 tcg_temp_free_i64(fp1);
b6d96bed 6877 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 6878 tcg_temp_free_i64(fp0);
b6d96bed 6879 }
57fa1fb3
TS
6880 opn = "recip2.ps";
6881 break;
6882 case FOP(29, 22):
5e755519 6883 check_cp1_64bitmode(ctx);
b6d96bed 6884 {
a7812ae4 6885 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
6886
6887 gen_load_fpr64(ctx, fp0, fs);
a7812ae4 6888 gen_helper_float_recip1_ps(fp0, fp0);
b6d96bed 6889 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 6890 tcg_temp_free_i64(fp0);
b6d96bed 6891 }
57fa1fb3
TS
6892 opn = "recip1.ps";
6893 break;
6894 case FOP(30, 22):
5e755519 6895 check_cp1_64bitmode(ctx);
b6d96bed 6896 {
a7812ae4 6897 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
6898
6899 gen_load_fpr64(ctx, fp0, fs);
a7812ae4 6900 gen_helper_float_rsqrt1_ps(fp0, fp0);
b6d96bed 6901 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 6902 tcg_temp_free_i64(fp0);
b6d96bed 6903 }
57fa1fb3
TS
6904 opn = "rsqrt1.ps";
6905 break;
6906 case FOP(31, 22):
5e755519 6907 check_cp1_64bitmode(ctx);
b6d96bed 6908 {
a7812ae4
PB
6909 TCGv_i64 fp0 = tcg_temp_new_i64();
6910 TCGv_i64 fp1 = tcg_temp_new_i64();
b6d96bed
TS
6911
6912 gen_load_fpr64(ctx, fp0, fs);
6913 gen_load_fpr64(ctx, fp1, ft);
a7812ae4
PB
6914 gen_helper_float_rsqrt2_ps(fp0, fp0, fp1);
6915 tcg_temp_free_i64(fp1);
b6d96bed 6916 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 6917 tcg_temp_free_i64(fp0);
b6d96bed 6918 }
57fa1fb3
TS
6919 opn = "rsqrt2.ps";
6920 break;
5a5012ec 6921 case FOP(32, 22):
5e755519 6922 check_cp1_64bitmode(ctx);
b6d96bed 6923 {
a7812ae4 6924 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed
TS
6925
6926 gen_load_fpr32h(fp0, fs);
a7812ae4 6927 gen_helper_float_cvts_pu(fp0, fp0);
b6d96bed 6928 gen_store_fpr32(fp0, fd);
a7812ae4 6929 tcg_temp_free_i32(fp0);
b6d96bed 6930 }
5a5012ec 6931 opn = "cvt.s.pu";
dd016883 6932 break;
5a5012ec 6933 case FOP(36, 22):
5e755519 6934 check_cp1_64bitmode(ctx);
b6d96bed 6935 {
a7812ae4 6936 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
6937
6938 gen_load_fpr64(ctx, fp0, fs);
a7812ae4 6939 gen_helper_float_cvtpw_ps(fp0, fp0);
b6d96bed 6940 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 6941 tcg_temp_free_i64(fp0);
b6d96bed 6942 }
5a5012ec 6943 opn = "cvt.pw.ps";
6ea83fed 6944 break;
5a5012ec 6945 case FOP(40, 22):
5e755519 6946 check_cp1_64bitmode(ctx);
b6d96bed 6947 {
a7812ae4 6948 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed
TS
6949
6950 gen_load_fpr32(fp0, fs);
a7812ae4 6951 gen_helper_float_cvts_pl(fp0, fp0);
b6d96bed 6952 gen_store_fpr32(fp0, fd);
a7812ae4 6953 tcg_temp_free_i32(fp0);
b6d96bed 6954 }
5a5012ec 6955 opn = "cvt.s.pl";
6ea83fed 6956 break;
5a5012ec 6957 case FOP(44, 22):
5e755519 6958 check_cp1_64bitmode(ctx);
b6d96bed 6959 {
a7812ae4
PB
6960 TCGv_i32 fp0 = tcg_temp_new_i32();
6961 TCGv_i32 fp1 = tcg_temp_new_i32();
b6d96bed
TS
6962
6963 gen_load_fpr32(fp0, fs);
6964 gen_load_fpr32(fp1, ft);
6965 gen_store_fpr32h(fp0, fd);
6966 gen_store_fpr32(fp1, fd);
a7812ae4
PB
6967 tcg_temp_free_i32(fp0);
6968 tcg_temp_free_i32(fp1);
b6d96bed 6969 }
5a5012ec 6970 opn = "pll.ps";
6ea83fed 6971 break;
5a5012ec 6972 case FOP(45, 22):
5e755519 6973 check_cp1_64bitmode(ctx);
b6d96bed 6974 {
a7812ae4
PB
6975 TCGv_i32 fp0 = tcg_temp_new_i32();
6976 TCGv_i32 fp1 = tcg_temp_new_i32();
b6d96bed
TS
6977
6978 gen_load_fpr32(fp0, fs);
6979 gen_load_fpr32h(fp1, ft);
6980 gen_store_fpr32(fp1, fd);
6981 gen_store_fpr32h(fp0, fd);
a7812ae4
PB
6982 tcg_temp_free_i32(fp0);
6983 tcg_temp_free_i32(fp1);
b6d96bed 6984 }
5a5012ec
TS
6985 opn = "plu.ps";
6986 break;
6987 case FOP(46, 22):
5e755519 6988 check_cp1_64bitmode(ctx);
b6d96bed 6989 {
a7812ae4
PB
6990 TCGv_i32 fp0 = tcg_temp_new_i32();
6991 TCGv_i32 fp1 = tcg_temp_new_i32();
b6d96bed
TS
6992
6993 gen_load_fpr32h(fp0, fs);
6994 gen_load_fpr32(fp1, ft);
6995 gen_store_fpr32(fp1, fd);
6996 gen_store_fpr32h(fp0, fd);
a7812ae4
PB
6997 tcg_temp_free_i32(fp0);
6998 tcg_temp_free_i32(fp1);
b6d96bed 6999 }
5a5012ec
TS
7000 opn = "pul.ps";
7001 break;
7002 case FOP(47, 22):
5e755519 7003 check_cp1_64bitmode(ctx);
b6d96bed 7004 {
a7812ae4
PB
7005 TCGv_i32 fp0 = tcg_temp_new_i32();
7006 TCGv_i32 fp1 = tcg_temp_new_i32();
b6d96bed
TS
7007
7008 gen_load_fpr32h(fp0, fs);
7009 gen_load_fpr32h(fp1, ft);
7010 gen_store_fpr32(fp1, fd);
7011 gen_store_fpr32h(fp0, fd);
a7812ae4
PB
7012 tcg_temp_free_i32(fp0);
7013 tcg_temp_free_i32(fp1);
b6d96bed 7014 }
5a5012ec
TS
7015 opn = "puu.ps";
7016 break;
7017 case FOP(48, 22):
7018 case FOP(49, 22):
7019 case FOP(50, 22):
7020 case FOP(51, 22):
7021 case FOP(52, 22):
7022 case FOP(53, 22):
7023 case FOP(54, 22):
7024 case FOP(55, 22):
7025 case FOP(56, 22):
7026 case FOP(57, 22):
7027 case FOP(58, 22):
7028 case FOP(59, 22):
7029 case FOP(60, 22):
7030 case FOP(61, 22):
7031 case FOP(62, 22):
7032 case FOP(63, 22):
5e755519 7033 check_cp1_64bitmode(ctx);
b6d96bed 7034 {
a7812ae4
PB
7035 TCGv_i64 fp0 = tcg_temp_new_i64();
7036 TCGv_i64 fp1 = tcg_temp_new_i64();
b6d96bed
TS
7037
7038 gen_load_fpr64(ctx, fp0, fs);
7039 gen_load_fpr64(ctx, fp1, ft);
7040 if (ctx->opcode & (1 << 6)) {
7041 gen_cmpabs_ps(func-48, fp0, fp1, cc);
7042 opn = condnames_abs[func-48];
7043 } else {
7044 gen_cmp_ps(func-48, fp0, fp1, cc);
7045 opn = condnames[func-48];
7046 }
a7812ae4
PB
7047 tcg_temp_free_i64(fp0);
7048 tcg_temp_free_i64(fp1);
5a1e8ffb 7049 }
6ea83fed 7050 break;
5a5012ec 7051 default:
923617a3 7052 MIPS_INVAL(opn);
e397ee33 7053 generate_exception (ctx, EXCP_RI);
6ea83fed
FB
7054 return;
7055 }
5a1e8ffb
TS
7056 switch (optype) {
7057 case BINOP:
6ea83fed 7058 MIPS_DEBUG("%s %s, %s, %s", opn, fregnames[fd], fregnames[fs], fregnames[ft]);
5a1e8ffb
TS
7059 break;
7060 case CMPOP:
7061 MIPS_DEBUG("%s %s,%s", opn, fregnames[fs], fregnames[ft]);
7062 break;
7063 default:
6ea83fed 7064 MIPS_DEBUG("%s %s,%s", opn, fregnames[fd], fregnames[fs]);
5a1e8ffb
TS
7065 break;
7066 }
6ea83fed 7067}
6af0bf9c 7068
5a5012ec 7069/* Coprocessor 3 (FPU) */
5e755519
TS
7070static void gen_flt3_ldst (DisasContext *ctx, uint32_t opc,
7071 int fd, int fs, int base, int index)
7a387fff 7072{
923617a3 7073 const char *opn = "extended float load/store";
93b12ccc 7074 int store = 0;
a7812ae4
PB
7075 TCGv t0 = tcg_temp_local_new();
7076 TCGv t1 = tcg_temp_local_new();
7a387fff 7077
93b12ccc 7078 if (base == 0) {
6c5c1e20 7079 gen_load_gpr(t0, index);
93b12ccc 7080 } else if (index == 0) {
6c5c1e20 7081 gen_load_gpr(t0, base);
93b12ccc 7082 } else {
e9203484
AJ
7083 gen_load_gpr(t0, index);
7084 gen_op_addr_add(ctx, t0, cpu_gpr[base]);
93b12ccc 7085 }
5a5012ec 7086 /* Don't do NOP if destination is zero: we must perform the actual
ead9360e 7087 memory access. */
5a5012ec
TS
7088 switch (opc) {
7089 case OPC_LWXC1:
b8aa4598 7090 check_cop1x(ctx);
b6d96bed 7091 {
a7812ae4 7092 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed 7093
a7812ae4
PB
7094 tcg_gen_qemu_ld32s(t1, t0, ctx->mem_idx);
7095 tcg_gen_trunc_tl_i32(fp0, t1);
b6d96bed 7096 gen_store_fpr32(fp0, fd);
a7812ae4 7097 tcg_temp_free_i32(fp0);
b6d96bed 7098 }
5a5012ec
TS
7099 opn = "lwxc1";
7100 break;
7101 case OPC_LDXC1:
b8aa4598
TS
7102 check_cop1x(ctx);
7103 check_cp1_registers(ctx, fd);
b6d96bed 7104 {
a7812ae4 7105 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
7106
7107 tcg_gen_qemu_ld64(fp0, t0, ctx->mem_idx);
7108 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 7109 tcg_temp_free_i64(fp0);
b6d96bed 7110 }
5a5012ec
TS
7111 opn = "ldxc1";
7112 break;
7113 case OPC_LUXC1:
b8aa4598 7114 check_cp1_64bitmode(ctx);
6c5c1e20 7115 tcg_gen_andi_tl(t0, t0, ~0x7);
b6d96bed 7116 {
a7812ae4 7117 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
7118
7119 tcg_gen_qemu_ld64(fp0, t0, ctx->mem_idx);
7120 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 7121 tcg_temp_free_i64(fp0);
b6d96bed 7122 }
5a5012ec
TS
7123 opn = "luxc1";
7124 break;
7125 case OPC_SWXC1:
b8aa4598 7126 check_cop1x(ctx);
b6d96bed 7127 {
a7812ae4 7128 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed
TS
7129
7130 gen_load_fpr32(fp0, fs);
a7812ae4
PB
7131 tcg_gen_extu_i32_tl(t1, fp0);
7132 tcg_gen_qemu_st32(t1, t0, ctx->mem_idx);
7133 tcg_temp_free_i32(fp0);
b6d96bed 7134 }
5a5012ec 7135 opn = "swxc1";
93b12ccc 7136 store = 1;
5a5012ec
TS
7137 break;
7138 case OPC_SDXC1:
b8aa4598
TS
7139 check_cop1x(ctx);
7140 check_cp1_registers(ctx, fs);
b6d96bed 7141 {
a7812ae4 7142 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
7143
7144 gen_load_fpr64(ctx, fp0, fs);
7145 tcg_gen_qemu_st64(fp0, t0, ctx->mem_idx);
a7812ae4 7146 tcg_temp_free_i64(fp0);
b6d96bed 7147 }
5a5012ec 7148 opn = "sdxc1";
93b12ccc 7149 store = 1;
5a5012ec
TS
7150 break;
7151 case OPC_SUXC1:
b8aa4598 7152 check_cp1_64bitmode(ctx);
6c5c1e20 7153 tcg_gen_andi_tl(t0, t0, ~0x7);
b6d96bed 7154 {
a7812ae4 7155 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
7156
7157 gen_load_fpr64(ctx, fp0, fs);
7158 tcg_gen_qemu_st64(fp0, t0, ctx->mem_idx);
a7812ae4 7159 tcg_temp_free_i64(fp0);
b6d96bed 7160 }
5a5012ec 7161 opn = "suxc1";
93b12ccc 7162 store = 1;
5a5012ec
TS
7163 break;
7164 default:
923617a3 7165 MIPS_INVAL(opn);
5a5012ec 7166 generate_exception(ctx, EXCP_RI);
6c5c1e20
TS
7167 tcg_temp_free(t0);
7168 tcg_temp_free(t1);
5a5012ec
TS
7169 return;
7170 }
6c5c1e20
TS
7171 tcg_temp_free(t0);
7172 tcg_temp_free(t1);
93b12ccc
TS
7173 MIPS_DEBUG("%s %s, %s(%s)", opn, fregnames[store ? fs : fd],
7174 regnames[index], regnames[base]);
5a5012ec
TS
7175}
7176
5e755519
TS
7177static void gen_flt3_arith (DisasContext *ctx, uint32_t opc,
7178 int fd, int fr, int fs, int ft)
5a5012ec 7179{
923617a3 7180 const char *opn = "flt3_arith";
5a5012ec 7181
5a5012ec
TS
7182 switch (opc) {
7183 case OPC_ALNV_PS:
b8aa4598 7184 check_cp1_64bitmode(ctx);
a16336e4 7185 {
a7812ae4
PB
7186 TCGv t0 = tcg_temp_local_new();
7187 TCGv_i32 fp0 = tcg_temp_local_new_i32();
7188 TCGv_i32 fph0 = tcg_temp_local_new_i32();
7189 TCGv_i32 fp1 = tcg_temp_local_new_i32();
7190 TCGv_i32 fph1 = tcg_temp_local_new_i32();
a16336e4
TS
7191 int l1 = gen_new_label();
7192 int l2 = gen_new_label();
7193
6c5c1e20
TS
7194 gen_load_gpr(t0, fr);
7195 tcg_gen_andi_tl(t0, t0, 0x7);
b6d96bed
TS
7196 gen_load_fpr32(fp0, fs);
7197 gen_load_fpr32h(fph0, fs);
7198 gen_load_fpr32(fp1, ft);
7199 gen_load_fpr32h(fph1, ft);
6c5c1e20
TS
7200
7201 tcg_gen_brcondi_tl(TCG_COND_NE, t0, 0, l1);
b6d96bed
TS
7202 gen_store_fpr32(fp0, fd);
7203 gen_store_fpr32h(fph0, fd);
a16336e4
TS
7204 tcg_gen_br(l2);
7205 gen_set_label(l1);
6c5c1e20
TS
7206 tcg_gen_brcondi_tl(TCG_COND_NE, t0, 4, l2);
7207 tcg_temp_free(t0);
a16336e4 7208#ifdef TARGET_WORDS_BIGENDIAN
b6d96bed
TS
7209 gen_store_fpr32(fph1, fd);
7210 gen_store_fpr32h(fp0, fd);
a16336e4 7211#else
b6d96bed
TS
7212 gen_store_fpr32(fph0, fd);
7213 gen_store_fpr32h(fp1, fd);
a16336e4
TS
7214#endif
7215 gen_set_label(l2);
a7812ae4
PB
7216 tcg_temp_free_i32(fp0);
7217 tcg_temp_free_i32(fph0);
7218 tcg_temp_free_i32(fp1);
7219 tcg_temp_free_i32(fph1);
a16336e4 7220 }
5a5012ec
TS
7221 opn = "alnv.ps";
7222 break;
7223 case OPC_MADD_S:
b8aa4598 7224 check_cop1x(ctx);
b6d96bed 7225 {
a7812ae4
PB
7226 TCGv_i32 fp0 = tcg_temp_new_i32();
7227 TCGv_i32 fp1 = tcg_temp_new_i32();
7228 TCGv_i32 fp2 = tcg_temp_new_i32();
b6d96bed
TS
7229
7230 gen_load_fpr32(fp0, fs);
7231 gen_load_fpr32(fp1, ft);
7232 gen_load_fpr32(fp2, fr);
a7812ae4
PB
7233 gen_helper_float_muladd_s(fp2, fp0, fp1, fp2);
7234 tcg_temp_free_i32(fp0);
7235 tcg_temp_free_i32(fp1);
b6d96bed 7236 gen_store_fpr32(fp2, fd);
a7812ae4 7237 tcg_temp_free_i32(fp2);
b6d96bed 7238 }
5a5012ec
TS
7239 opn = "madd.s";
7240 break;
7241 case OPC_MADD_D:
b8aa4598
TS
7242 check_cop1x(ctx);
7243 check_cp1_registers(ctx, fd | fs | ft | fr);
b6d96bed 7244 {
a7812ae4
PB
7245 TCGv_i64 fp0 = tcg_temp_new_i64();
7246 TCGv_i64 fp1 = tcg_temp_new_i64();
7247 TCGv_i64 fp2 = tcg_temp_new_i64();
b6d96bed
TS
7248
7249 gen_load_fpr64(ctx, fp0, fs);
7250 gen_load_fpr64(ctx, fp1, ft);
7251 gen_load_fpr64(ctx, fp2, fr);
a7812ae4
PB
7252 gen_helper_float_muladd_d(fp2, fp0, fp1, fp2);
7253 tcg_temp_free_i64(fp0);
7254 tcg_temp_free_i64(fp1);
b6d96bed 7255 gen_store_fpr64(ctx, fp2, fd);
a7812ae4 7256 tcg_temp_free_i64(fp2);
b6d96bed 7257 }
5a5012ec
TS
7258 opn = "madd.d";
7259 break;
7260 case OPC_MADD_PS:
b8aa4598 7261 check_cp1_64bitmode(ctx);
b6d96bed 7262 {
a7812ae4
PB
7263 TCGv_i64 fp0 = tcg_temp_new_i64();
7264 TCGv_i64 fp1 = tcg_temp_new_i64();
7265 TCGv_i64 fp2 = tcg_temp_new_i64();
b6d96bed
TS
7266
7267 gen_load_fpr64(ctx, fp0, fs);
7268 gen_load_fpr64(ctx, fp1, ft);
7269 gen_load_fpr64(ctx, fp2, fr);
a7812ae4
PB
7270 gen_helper_float_muladd_ps(fp2, fp0, fp1, fp2);
7271 tcg_temp_free_i64(fp0);
7272 tcg_temp_free_i64(fp1);
b6d96bed 7273 gen_store_fpr64(ctx, fp2, fd);
a7812ae4 7274 tcg_temp_free_i64(fp2);
b6d96bed 7275 }
5a5012ec
TS
7276 opn = "madd.ps";
7277 break;
7278 case OPC_MSUB_S:
b8aa4598 7279 check_cop1x(ctx);
b6d96bed 7280 {
a7812ae4
PB
7281 TCGv_i32 fp0 = tcg_temp_new_i32();
7282 TCGv_i32 fp1 = tcg_temp_new_i32();
7283 TCGv_i32 fp2 = tcg_temp_new_i32();
b6d96bed
TS
7284
7285 gen_load_fpr32(fp0, fs);
7286 gen_load_fpr32(fp1, ft);
7287 gen_load_fpr32(fp2, fr);
a7812ae4
PB
7288 gen_helper_float_mulsub_s(fp2, fp0, fp1, fp2);
7289 tcg_temp_free_i32(fp0);
7290 tcg_temp_free_i32(fp1);
b6d96bed 7291 gen_store_fpr32(fp2, fd);
a7812ae4 7292 tcg_temp_free_i32(fp2);
b6d96bed 7293 }
5a5012ec
TS
7294 opn = "msub.s";
7295 break;
7296 case OPC_MSUB_D:
b8aa4598
TS
7297 check_cop1x(ctx);
7298 check_cp1_registers(ctx, fd | fs | ft | fr);
b6d96bed 7299 {
a7812ae4
PB
7300 TCGv_i64 fp0 = tcg_temp_new_i64();
7301 TCGv_i64 fp1 = tcg_temp_new_i64();
7302 TCGv_i64 fp2 = tcg_temp_new_i64();
b6d96bed
TS
7303
7304 gen_load_fpr64(ctx, fp0, fs);
7305 gen_load_fpr64(ctx, fp1, ft);
7306 gen_load_fpr64(ctx, fp2, fr);
a7812ae4
PB
7307 gen_helper_float_mulsub_d(fp2, fp0, fp1, fp2);
7308 tcg_temp_free_i64(fp0);
7309 tcg_temp_free_i64(fp1);
b6d96bed 7310 gen_store_fpr64(ctx, fp2, fd);
a7812ae4 7311 tcg_temp_free_i64(fp2);
b6d96bed 7312 }
5a5012ec
TS
7313 opn = "msub.d";
7314 break;
7315 case OPC_MSUB_PS:
b8aa4598 7316 check_cp1_64bitmode(ctx);
b6d96bed 7317 {
a7812ae4
PB
7318 TCGv_i64 fp0 = tcg_temp_new_i64();
7319 TCGv_i64 fp1 = tcg_temp_new_i64();
7320 TCGv_i64 fp2 = tcg_temp_new_i64();
b6d96bed
TS
7321
7322 gen_load_fpr64(ctx, fp0, fs);
7323 gen_load_fpr64(ctx, fp1, ft);
7324 gen_load_fpr64(ctx, fp2, fr);
a7812ae4
PB
7325 gen_helper_float_mulsub_ps(fp2, fp0, fp1, fp2);
7326 tcg_temp_free_i64(fp0);
7327 tcg_temp_free_i64(fp1);
b6d96bed 7328 gen_store_fpr64(ctx, fp2, fd);
a7812ae4 7329 tcg_temp_free_i64(fp2);
b6d96bed 7330 }
5a5012ec
TS
7331 opn = "msub.ps";
7332 break;
7333 case OPC_NMADD_S:
b8aa4598 7334 check_cop1x(ctx);
b6d96bed 7335 {
a7812ae4
PB
7336 TCGv_i32 fp0 = tcg_temp_new_i32();
7337 TCGv_i32 fp1 = tcg_temp_new_i32();
7338 TCGv_i32 fp2 = tcg_temp_new_i32();
b6d96bed
TS
7339
7340 gen_load_fpr32(fp0, fs);
7341 gen_load_fpr32(fp1, ft);
7342 gen_load_fpr32(fp2, fr);
a7812ae4
PB
7343 gen_helper_float_nmuladd_s(fp2, fp0, fp1, fp2);
7344 tcg_temp_free_i32(fp0);
7345 tcg_temp_free_i32(fp1);
b6d96bed 7346 gen_store_fpr32(fp2, fd);
a7812ae4 7347 tcg_temp_free_i32(fp2);
b6d96bed 7348 }
5a5012ec
TS
7349 opn = "nmadd.s";
7350 break;
7351 case OPC_NMADD_D:
b8aa4598
TS
7352 check_cop1x(ctx);
7353 check_cp1_registers(ctx, fd | fs | ft | fr);
b6d96bed 7354 {
a7812ae4
PB
7355 TCGv_i64 fp0 = tcg_temp_new_i64();
7356 TCGv_i64 fp1 = tcg_temp_new_i64();
7357 TCGv_i64 fp2 = tcg_temp_new_i64();
b6d96bed
TS
7358
7359 gen_load_fpr64(ctx, fp0, fs);
7360 gen_load_fpr64(ctx, fp1, ft);
7361 gen_load_fpr64(ctx, fp2, fr);
a7812ae4
PB
7362 gen_helper_float_nmuladd_d(fp2, fp0, fp1, fp2);
7363 tcg_temp_free_i64(fp0);
7364 tcg_temp_free_i64(fp1);
b6d96bed 7365 gen_store_fpr64(ctx, fp2, fd);
a7812ae4 7366 tcg_temp_free_i64(fp2);
b6d96bed 7367 }
5a5012ec
TS
7368 opn = "nmadd.d";
7369 break;
7370 case OPC_NMADD_PS:
b8aa4598 7371 check_cp1_64bitmode(ctx);
b6d96bed 7372 {
a7812ae4
PB
7373 TCGv_i64 fp0 = tcg_temp_new_i64();
7374 TCGv_i64 fp1 = tcg_temp_new_i64();
7375 TCGv_i64 fp2 = tcg_temp_new_i64();
b6d96bed
TS
7376
7377 gen_load_fpr64(ctx, fp0, fs);
7378 gen_load_fpr64(ctx, fp1, ft);
7379 gen_load_fpr64(ctx, fp2, fr);
a7812ae4
PB
7380 gen_helper_float_nmuladd_ps(fp2, fp0, fp1, fp2);
7381 tcg_temp_free_i64(fp0);
7382 tcg_temp_free_i64(fp1);
b6d96bed 7383 gen_store_fpr64(ctx, fp2, fd);
a7812ae4 7384 tcg_temp_free_i64(fp2);
b6d96bed 7385 }
5a5012ec
TS
7386 opn = "nmadd.ps";
7387 break;
7388 case OPC_NMSUB_S:
b8aa4598 7389 check_cop1x(ctx);
b6d96bed 7390 {
a7812ae4
PB
7391 TCGv_i32 fp0 = tcg_temp_new_i32();
7392 TCGv_i32 fp1 = tcg_temp_new_i32();
7393 TCGv_i32 fp2 = tcg_temp_new_i32();
b6d96bed
TS
7394
7395 gen_load_fpr32(fp0, fs);
7396 gen_load_fpr32(fp1, ft);
7397 gen_load_fpr32(fp2, fr);
a7812ae4
PB
7398 gen_helper_float_nmulsub_s(fp2, fp0, fp1, fp2);
7399 tcg_temp_free_i32(fp0);
7400 tcg_temp_free_i32(fp1);
b6d96bed 7401 gen_store_fpr32(fp2, fd);
a7812ae4 7402 tcg_temp_free_i32(fp2);
b6d96bed 7403 }
5a5012ec
TS
7404 opn = "nmsub.s";
7405 break;
7406 case OPC_NMSUB_D:
b8aa4598
TS
7407 check_cop1x(ctx);
7408 check_cp1_registers(ctx, fd | fs | ft | fr);
b6d96bed 7409 {
a7812ae4
PB
7410 TCGv_i64 fp0 = tcg_temp_new_i64();
7411 TCGv_i64 fp1 = tcg_temp_new_i64();
7412 TCGv_i64 fp2 = tcg_temp_new_i64();
b6d96bed
TS
7413
7414 gen_load_fpr64(ctx, fp0, fs);
7415 gen_load_fpr64(ctx, fp1, ft);
7416 gen_load_fpr64(ctx, fp2, fr);
a7812ae4
PB
7417 gen_helper_float_nmulsub_d(fp2, fp0, fp1, fp2);
7418 tcg_temp_free_i64(fp0);
7419 tcg_temp_free_i64(fp1);
b6d96bed 7420 gen_store_fpr64(ctx, fp2, fd);
a7812ae4 7421 tcg_temp_free_i64(fp2);
b6d96bed 7422 }
5a5012ec
TS
7423 opn = "nmsub.d";
7424 break;
7425 case OPC_NMSUB_PS:
b8aa4598 7426 check_cp1_64bitmode(ctx);
b6d96bed 7427 {
a7812ae4
PB
7428 TCGv_i64 fp0 = tcg_temp_new_i64();
7429 TCGv_i64 fp1 = tcg_temp_new_i64();
7430 TCGv_i64 fp2 = tcg_temp_new_i64();
b6d96bed
TS
7431
7432 gen_load_fpr64(ctx, fp0, fs);
7433 gen_load_fpr64(ctx, fp1, ft);
7434 gen_load_fpr64(ctx, fp2, fr);
a7812ae4
PB
7435 gen_helper_float_nmulsub_ps(fp2, fp0, fp1, fp2);
7436 tcg_temp_free_i64(fp0);
7437 tcg_temp_free_i64(fp1);
b6d96bed 7438 gen_store_fpr64(ctx, fp2, fd);
a7812ae4 7439 tcg_temp_free_i64(fp2);
b6d96bed 7440 }
5a5012ec
TS
7441 opn = "nmsub.ps";
7442 break;
923617a3
TS
7443 default:
7444 MIPS_INVAL(opn);
5a5012ec
TS
7445 generate_exception (ctx, EXCP_RI);
7446 return;
7447 }
7448 MIPS_DEBUG("%s %s, %s, %s, %s", opn, fregnames[fd], fregnames[fr],
7449 fregnames[fs], fregnames[ft]);
7a387fff
TS
7450}
7451
7452/* ISA extensions (ASEs) */
6af0bf9c
FB
7453/* MIPS16 extension to MIPS32 */
7454/* SmartMIPS extension to MIPS32 */
7455
d26bc211 7456#if defined(TARGET_MIPS64)
6af0bf9c
FB
7457
7458/* MDMX extension to MIPS64 */
6af0bf9c
FB
7459
7460#endif
7461
36d23958 7462static void decode_opc (CPUState *env, DisasContext *ctx)
6af0bf9c
FB
7463{
7464 int32_t offset;
7465 int rs, rt, rd, sa;
7a387fff 7466 uint32_t op, op1, op2;
6af0bf9c
FB
7467 int16_t imm;
7468
d796321b
FB
7469 /* make sure instructions are on a word boundary */
7470 if (ctx->pc & 0x3) {
cbeb0857 7471 env->CP0_BadVAddr = ctx->pc;
d796321b
FB
7472 generate_exception(ctx, EXCP_AdEL);
7473 return;
7474 }
7475
8e9ade68 7476 /* Handle blikely not taken case */
4ad40f36 7477 if ((ctx->hflags & MIPS_HFLAG_BMASK) == MIPS_HFLAG_BL) {
8e9ade68
TS
7478 int l1 = gen_new_label();
7479
3594c774 7480 MIPS_DEBUG("blikely condition (" TARGET_FMT_lx ")", ctx->pc + 4);
1ba74fb8 7481 tcg_gen_brcondi_tl(TCG_COND_NE, bcond, 0, l1);
41db4607 7482 tcg_gen_movi_i32(hflags, ctx->hflags & ~MIPS_HFLAG_BMASK);
5a5012ec
TS
7483 gen_goto_tb(ctx, 1, ctx->pc + 4);
7484 gen_set_label(l1);
6af0bf9c 7485 }
7a387fff
TS
7486 op = MASK_OP_MAJOR(ctx->opcode);
7487 rs = (ctx->opcode >> 21) & 0x1f;
7488 rt = (ctx->opcode >> 16) & 0x1f;
7489 rd = (ctx->opcode >> 11) & 0x1f;
7490 sa = (ctx->opcode >> 6) & 0x1f;
6af0bf9c
FB
7491 imm = (int16_t)ctx->opcode;
7492 switch (op) {
7a387fff
TS
7493 case OPC_SPECIAL:
7494 op1 = MASK_SPECIAL(ctx->opcode);
6af0bf9c 7495 switch (op1) {
7a387fff
TS
7496 case OPC_SLL: /* Arithmetic with immediate */
7497 case OPC_SRL ... OPC_SRA:
e189e748 7498 gen_arith_imm(env, ctx, op1, rd, rt, sa);
7a387fff 7499 break;
e189e748
TS
7500 case OPC_MOVZ ... OPC_MOVN:
7501 check_insn(env, ctx, ISA_MIPS4 | ISA_MIPS32);
7a387fff
TS
7502 case OPC_SLLV: /* Arithmetic */
7503 case OPC_SRLV ... OPC_SRAV:
7a387fff
TS
7504 case OPC_ADD ... OPC_NOR:
7505 case OPC_SLT ... OPC_SLTU:
e189e748 7506 gen_arith(env, ctx, op1, rd, rs, rt);
7a387fff
TS
7507 break;
7508 case OPC_MULT ... OPC_DIVU:
e9c71dd1
TS
7509 if (sa) {
7510 check_insn(env, ctx, INSN_VR54XX);
7511 op1 = MASK_MUL_VR54XX(ctx->opcode);
7512 gen_mul_vr54xx(ctx, op1, rd, rs, rt);
7513 } else
7514 gen_muldiv(ctx, op1, rs, rt);
7a387fff
TS
7515 break;
7516 case OPC_JR ... OPC_JALR:
7517 gen_compute_branch(ctx, op1, rs, rd, sa);
6af0bf9c 7518 return;
7a387fff
TS
7519 case OPC_TGE ... OPC_TEQ: /* Traps */
7520 case OPC_TNE:
7521 gen_trap(ctx, op1, rs, rt, -1);
6af0bf9c 7522 break;
7a387fff
TS
7523 case OPC_MFHI: /* Move from HI/LO */
7524 case OPC_MFLO:
7525 gen_HILO(ctx, op1, rd);
6af0bf9c 7526 break;
7a387fff
TS
7527 case OPC_MTHI:
7528 case OPC_MTLO: /* Move to HI/LO */
7529 gen_HILO(ctx, op1, rs);
6af0bf9c 7530 break;
b48cfdff
TS
7531 case OPC_PMON: /* Pmon entry point, also R4010 selsl */
7532#ifdef MIPS_STRICT_STANDARD
7533 MIPS_INVAL("PMON / selsl");
7534 generate_exception(ctx, EXCP_RI);
7535#else
a7812ae4 7536 gen_helper_0i(pmon, sa);
b48cfdff 7537#endif
7a387fff
TS
7538 break;
7539 case OPC_SYSCALL:
6af0bf9c
FB
7540 generate_exception(ctx, EXCP_SYSCALL);
7541 break;
7a387fff 7542 case OPC_BREAK:
6af0bf9c
FB
7543 generate_exception(ctx, EXCP_BREAK);
7544 break;
b48cfdff
TS
7545 case OPC_SPIM:
7546#ifdef MIPS_STRICT_STANDARD
7547 MIPS_INVAL("SPIM");
7548 generate_exception(ctx, EXCP_RI);
7549#else
7a387fff
TS
7550 /* Implemented as RI exception for now. */
7551 MIPS_INVAL("spim (unofficial)");
7552 generate_exception(ctx, EXCP_RI);
b48cfdff 7553#endif
6af0bf9c 7554 break;
7a387fff 7555 case OPC_SYNC:
ead9360e 7556 /* Treat as NOP. */
6af0bf9c 7557 break;
4ad40f36 7558
7a387fff 7559 case OPC_MOVCI:
e189e748 7560 check_insn(env, ctx, ISA_MIPS4 | ISA_MIPS32);
36d23958 7561 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
e397ee33 7562 save_cpu_state(ctx, 1);
5e755519 7563 check_cp1_enabled(ctx);
36d23958
TS
7564 gen_movci(ctx, rd, rs, (ctx->opcode >> 18) & 0x7,
7565 (ctx->opcode >> 16) & 1);
7566 } else {
e397ee33 7567 generate_exception_err(ctx, EXCP_CpU, 1);
36d23958 7568 }
4ad40f36
FB
7569 break;
7570
d26bc211 7571#if defined(TARGET_MIPS64)
7a387fff
TS
7572 /* MIPS64 specific opcodes */
7573 case OPC_DSLL:
7574 case OPC_DSRL ... OPC_DSRA:
7575 case OPC_DSLL32:
7576 case OPC_DSRL32 ... OPC_DSRA32:
e189e748
TS
7577 check_insn(env, ctx, ISA_MIPS3);
7578 check_mips_64(ctx);
7579 gen_arith_imm(env, ctx, op1, rd, rt, sa);
7a387fff
TS
7580 break;
7581 case OPC_DSLLV:
7582 case OPC_DSRLV ... OPC_DSRAV:
7583 case OPC_DADD ... OPC_DSUBU:
e189e748
TS
7584 check_insn(env, ctx, ISA_MIPS3);
7585 check_mips_64(ctx);
7586 gen_arith(env, ctx, op1, rd, rs, rt);
7a387fff
TS
7587 break;
7588 case OPC_DMULT ... OPC_DDIVU:
e189e748
TS
7589 check_insn(env, ctx, ISA_MIPS3);
7590 check_mips_64(ctx);
7a387fff
TS
7591 gen_muldiv(ctx, op1, rs, rt);
7592 break;
6af0bf9c
FB
7593#endif
7594 default: /* Invalid */
7595 MIPS_INVAL("special");
7596 generate_exception(ctx, EXCP_RI);
7597 break;
7598 }
7599 break;
7a387fff
TS
7600 case OPC_SPECIAL2:
7601 op1 = MASK_SPECIAL2(ctx->opcode);
6af0bf9c 7602 switch (op1) {
7a387fff
TS
7603 case OPC_MADD ... OPC_MADDU: /* Multiply and add/sub */
7604 case OPC_MSUB ... OPC_MSUBU:
e189e748 7605 check_insn(env, ctx, ISA_MIPS32);
7a387fff 7606 gen_muldiv(ctx, op1, rs, rt);
6af0bf9c 7607 break;
7a387fff 7608 case OPC_MUL:
e189e748 7609 gen_arith(env, ctx, op1, rd, rs, rt);
6af0bf9c 7610 break;
20e1fb52
AJ
7611 case OPC_CLO:
7612 case OPC_CLZ:
e189e748 7613 check_insn(env, ctx, ISA_MIPS32);
7a387fff 7614 gen_cl(ctx, op1, rd, rs);
6af0bf9c 7615 break;
7a387fff 7616 case OPC_SDBBP:
6af0bf9c
FB
7617 /* XXX: not clear which exception should be raised
7618 * when in debug mode...
7619 */
e189e748 7620 check_insn(env, ctx, ISA_MIPS32);
6af0bf9c
FB
7621 if (!(ctx->hflags & MIPS_HFLAG_DM)) {
7622 generate_exception(ctx, EXCP_DBp);
7623 } else {
7624 generate_exception(ctx, EXCP_DBp);
7625 }
ead9360e 7626 /* Treat as NOP. */
6af0bf9c 7627 break;
d26bc211 7628#if defined(TARGET_MIPS64)
20e1fb52
AJ
7629 case OPC_DCLO:
7630 case OPC_DCLZ:
e189e748
TS
7631 check_insn(env, ctx, ISA_MIPS64);
7632 check_mips_64(ctx);
7a387fff
TS
7633 gen_cl(ctx, op1, rd, rs);
7634 break;
7635#endif
6af0bf9c
FB
7636 default: /* Invalid */
7637 MIPS_INVAL("special2");
7638 generate_exception(ctx, EXCP_RI);
7639 break;
7640 }
7641 break;
7a387fff 7642 case OPC_SPECIAL3:
2b0233ab
TS
7643 op1 = MASK_SPECIAL3(ctx->opcode);
7644 switch (op1) {
7645 case OPC_EXT:
7646 case OPC_INS:
7647 check_insn(env, ctx, ISA_MIPS32R2);
7648 gen_bitops(ctx, op1, rt, rs, sa, rd);
7649 break;
7650 case OPC_BSHFL:
7651 check_insn(env, ctx, ISA_MIPS32R2);
7652 op2 = MASK_BSHFL(ctx->opcode);
49bcf33c 7653 gen_bshfl(ctx, op2, rt, rd);
7a387fff 7654 break;
1579a72e 7655 case OPC_RDHWR:
e189e748 7656 check_insn(env, ctx, ISA_MIPS32R2);
6c5c1e20 7657 {
a7812ae4 7658 TCGv t0 = tcg_temp_local_new();
6c5c1e20
TS
7659
7660 switch (rd) {
7661 case 0:
7662 save_cpu_state(ctx, 1);
a7812ae4 7663 gen_helper_rdhwr_cpunum(t0);
6c5c1e20
TS
7664 break;
7665 case 1:
7666 save_cpu_state(ctx, 1);
a7812ae4 7667 gen_helper_rdhwr_synci_step(t0);
6c5c1e20
TS
7668 break;
7669 case 2:
7670 save_cpu_state(ctx, 1);
a7812ae4 7671 gen_helper_rdhwr_cc(t0);
6c5c1e20
TS
7672 break;
7673 case 3:
7674 save_cpu_state(ctx, 1);
a7812ae4 7675 gen_helper_rdhwr_ccres(t0);
6c5c1e20
TS
7676 break;
7677 case 29:
932e71cd
AJ
7678#if defined(CONFIG_USER_ONLY)
7679 tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUState, tls_value));
7680 break;
7681#else
7682 /* XXX: Some CPUs implement this in hardware.
7683 Not supported yet. */
7684#endif
6c5c1e20
TS
7685 default: /* Invalid */
7686 MIPS_INVAL("rdhwr");
7687 generate_exception(ctx, EXCP_RI);
7688 break;
7689 }
7690 gen_store_gpr(t0, rt);
7691 tcg_temp_free(t0);
1579a72e 7692 }
1579a72e 7693 break;
ead9360e 7694 case OPC_FORK:
7385ac0b 7695 check_insn(env, ctx, ASE_MT);
6c5c1e20 7696 {
a7812ae4
PB
7697 TCGv t0 = tcg_temp_local_new();
7698 TCGv t1 = tcg_temp_local_new();
6c5c1e20
TS
7699
7700 gen_load_gpr(t0, rt);
7701 gen_load_gpr(t1, rs);
a7812ae4 7702 gen_helper_fork(t0, t1);
6c5c1e20
TS
7703 tcg_temp_free(t0);
7704 tcg_temp_free(t1);
7705 }
ead9360e
TS
7706 break;
7707 case OPC_YIELD:
7385ac0b 7708 check_insn(env, ctx, ASE_MT);
6c5c1e20 7709 {
a7812ae4 7710 TCGv t0 = tcg_temp_local_new();
6c5c1e20
TS
7711
7712 gen_load_gpr(t0, rs);
a7812ae4 7713 gen_helper_yield(t0, t0);
6c5c1e20
TS
7714 gen_store_gpr(t0, rd);
7715 tcg_temp_free(t0);
7716 }
ead9360e 7717 break;
d26bc211 7718#if defined(TARGET_MIPS64)
1579a72e
TS
7719 case OPC_DEXTM ... OPC_DEXT:
7720 case OPC_DINSM ... OPC_DINS:
e189e748
TS
7721 check_insn(env, ctx, ISA_MIPS64R2);
7722 check_mips_64(ctx);
1579a72e 7723 gen_bitops(ctx, op1, rt, rs, sa, rd);
7a387fff 7724 break;
1579a72e 7725 case OPC_DBSHFL:
e189e748
TS
7726 check_insn(env, ctx, ISA_MIPS64R2);
7727 check_mips_64(ctx);
1579a72e 7728 op2 = MASK_DBSHFL(ctx->opcode);
49bcf33c 7729 gen_bshfl(ctx, op2, rt, rd);
c6d6dd7c 7730 break;
7a387fff
TS
7731#endif
7732 default: /* Invalid */
7733 MIPS_INVAL("special3");
7734 generate_exception(ctx, EXCP_RI);
7735 break;
7736 }
7737 break;
7738 case OPC_REGIMM:
7739 op1 = MASK_REGIMM(ctx->opcode);
7740 switch (op1) {
7741 case OPC_BLTZ ... OPC_BGEZL: /* REGIMM branches */
7742 case OPC_BLTZAL ... OPC_BGEZALL:
7743 gen_compute_branch(ctx, op1, rs, -1, imm << 2);
6af0bf9c 7744 return;
7a387fff
TS
7745 case OPC_TGEI ... OPC_TEQI: /* REGIMM traps */
7746 case OPC_TNEI:
7747 gen_trap(ctx, op1, rs, -1, imm);
7748 break;
7749 case OPC_SYNCI:
e189e748 7750 check_insn(env, ctx, ISA_MIPS32R2);
ead9360e 7751 /* Treat as NOP. */
6af0bf9c
FB
7752 break;
7753 default: /* Invalid */
923617a3 7754 MIPS_INVAL("regimm");
6af0bf9c
FB
7755 generate_exception(ctx, EXCP_RI);
7756 break;
7757 }
7758 break;
7a387fff 7759 case OPC_CP0:
387a8fe5 7760 check_cp0_enabled(ctx);
7a387fff 7761 op1 = MASK_CP0(ctx->opcode);
6af0bf9c 7762 switch (op1) {
7a387fff
TS
7763 case OPC_MFC0:
7764 case OPC_MTC0:
ead9360e
TS
7765 case OPC_MFTR:
7766 case OPC_MTTR:
d26bc211 7767#if defined(TARGET_MIPS64)
7a387fff
TS
7768 case OPC_DMFC0:
7769 case OPC_DMTC0:
7770#endif
f1aa6320 7771#ifndef CONFIG_USER_ONLY
932e71cd 7772 gen_cp0(env, ctx, op1, rt, rd);
0eaef5aa 7773#endif /* !CONFIG_USER_ONLY */
7a387fff
TS
7774 break;
7775 case OPC_C0_FIRST ... OPC_C0_LAST:
f1aa6320 7776#ifndef CONFIG_USER_ONLY
932e71cd 7777 gen_cp0(env, ctx, MASK_C0(ctx->opcode), rt, rd);
0eaef5aa 7778#endif /* !CONFIG_USER_ONLY */
7a387fff
TS
7779 break;
7780 case OPC_MFMC0:
8706c382 7781#ifndef CONFIG_USER_ONLY
932e71cd 7782 {
a7812ae4 7783 TCGv t0 = tcg_temp_local_new();
6c5c1e20 7784
0eaef5aa 7785 op2 = MASK_MFMC0(ctx->opcode);
6c5c1e20
TS
7786 switch (op2) {
7787 case OPC_DMT:
7788 check_insn(env, ctx, ASE_MT);
a7812ae4 7789 gen_helper_dmt(t0, t0);
6c5c1e20
TS
7790 break;
7791 case OPC_EMT:
7792 check_insn(env, ctx, ASE_MT);
a7812ae4 7793 gen_helper_emt(t0, t0);
da80682b 7794 break;
6c5c1e20
TS
7795 case OPC_DVPE:
7796 check_insn(env, ctx, ASE_MT);
a7812ae4 7797 gen_helper_dvpe(t0, t0);
6c5c1e20
TS
7798 break;
7799 case OPC_EVPE:
7800 check_insn(env, ctx, ASE_MT);
a7812ae4 7801 gen_helper_evpe(t0, t0);
6c5c1e20
TS
7802 break;
7803 case OPC_DI:
7804 check_insn(env, ctx, ISA_MIPS32R2);
7805 save_cpu_state(ctx, 1);
a7812ae4 7806 gen_helper_di(t0);
6c5c1e20
TS
7807 /* Stop translation as we may have switched the execution mode */
7808 ctx->bstate = BS_STOP;
7809 break;
7810 case OPC_EI:
7811 check_insn(env, ctx, ISA_MIPS32R2);
7812 save_cpu_state(ctx, 1);
a7812ae4 7813 gen_helper_ei(t0);
6c5c1e20
TS
7814 /* Stop translation as we may have switched the execution mode */
7815 ctx->bstate = BS_STOP;
7816 break;
7817 default: /* Invalid */
7818 MIPS_INVAL("mfmc0");
7819 generate_exception(ctx, EXCP_RI);
7820 break;
7821 }
7822 gen_store_gpr(t0, rt);
7823 tcg_temp_free(t0);
7a387fff 7824 }
0eaef5aa 7825#endif /* !CONFIG_USER_ONLY */
6af0bf9c 7826 break;
7a387fff 7827 case OPC_RDPGPR:
e189e748 7828 check_insn(env, ctx, ISA_MIPS32R2);
be24bb4f 7829 gen_load_srsgpr(rt, rd);
ead9360e 7830 break;
7a387fff 7831 case OPC_WRPGPR:
e189e748 7832 check_insn(env, ctx, ISA_MIPS32R2);
be24bb4f 7833 gen_store_srsgpr(rt, rd);
38121543 7834 break;
6af0bf9c 7835 default:
923617a3 7836 MIPS_INVAL("cp0");
7a387fff 7837 generate_exception(ctx, EXCP_RI);
6af0bf9c
FB
7838 break;
7839 }
7840 break;
7a387fff 7841 case OPC_ADDI ... OPC_LUI: /* Arithmetic with immediate opcode */
e189e748 7842 gen_arith_imm(env, ctx, op, rt, rs, imm);
7a387fff
TS
7843 break;
7844 case OPC_J ... OPC_JAL: /* Jump */
7845 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2;
7846 gen_compute_branch(ctx, op, rs, rt, offset);
7847 return;
7848 case OPC_BEQ ... OPC_BGTZ: /* Branch */
7849 case OPC_BEQL ... OPC_BGTZL:
7850 gen_compute_branch(ctx, op, rs, rt, imm << 2);
7851 return;
7852 case OPC_LB ... OPC_LWR: /* Load and stores */
7853 case OPC_SB ... OPC_SW:
7854 case OPC_SWR:
7855 case OPC_LL:
7856 case OPC_SC:
7857 gen_ldst(ctx, op, rt, rs, imm);
7858 break;
7859 case OPC_CACHE:
e189e748 7860 check_insn(env, ctx, ISA_MIPS3 | ISA_MIPS32);
ead9360e 7861 /* Treat as NOP. */
34ae7b51 7862 break;
7a387fff 7863 case OPC_PREF:
e189e748 7864 check_insn(env, ctx, ISA_MIPS4 | ISA_MIPS32);
ead9360e 7865 /* Treat as NOP. */
6af0bf9c 7866 break;
4ad40f36 7867
923617a3 7868 /* Floating point (COP1). */
7a387fff
TS
7869 case OPC_LWC1:
7870 case OPC_LDC1:
7871 case OPC_SWC1:
7872 case OPC_SDC1:
36d23958
TS
7873 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
7874 save_cpu_state(ctx, 1);
5e755519 7875 check_cp1_enabled(ctx);
36d23958
TS
7876 gen_flt_ldst(ctx, op, rt, rs, imm);
7877 } else {
7878 generate_exception_err(ctx, EXCP_CpU, 1);
7879 }
6ea83fed
FB
7880 break;
7881
7a387fff 7882 case OPC_CP1:
36d23958
TS
7883 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
7884 save_cpu_state(ctx, 1);
5e755519 7885 check_cp1_enabled(ctx);
36d23958
TS
7886 op1 = MASK_CP1(ctx->opcode);
7887 switch (op1) {
3a95e3a7
TS
7888 case OPC_MFHC1:
7889 case OPC_MTHC1:
e189e748 7890 check_insn(env, ctx, ISA_MIPS32R2);
36d23958
TS
7891 case OPC_MFC1:
7892 case OPC_CFC1:
7893 case OPC_MTC1:
7894 case OPC_CTC1:
e189e748
TS
7895 gen_cp1(ctx, op1, rt, rd);
7896 break;
d26bc211 7897#if defined(TARGET_MIPS64)
36d23958
TS
7898 case OPC_DMFC1:
7899 case OPC_DMTC1:
e189e748 7900 check_insn(env, ctx, ISA_MIPS3);
36d23958
TS
7901 gen_cp1(ctx, op1, rt, rd);
7902 break;
e189e748 7903#endif
fbcc6828
TS
7904 case OPC_BC1ANY2:
7905 case OPC_BC1ANY4:
b8aa4598 7906 check_cop1x(ctx);
7385ac0b 7907 check_insn(env, ctx, ASE_MIPS3D);
d8a5950a
TS
7908 /* fall through */
7909 case OPC_BC1:
e189e748 7910 gen_compute_branch1(env, ctx, MASK_BC1(ctx->opcode),
5a5012ec 7911 (rt >> 2) & 0x7, imm << 2);
36d23958
TS
7912 return;
7913 case OPC_S_FMT:
7914 case OPC_D_FMT:
7915 case OPC_W_FMT:
7916 case OPC_L_FMT:
5a5012ec
TS
7917 case OPC_PS_FMT:
7918 gen_farith(ctx, MASK_CP1_FUNC(ctx->opcode), rt, rd, sa,
7919 (imm >> 8) & 0x7);
36d23958
TS
7920 break;
7921 default:
923617a3 7922 MIPS_INVAL("cp1");
e397ee33 7923 generate_exception (ctx, EXCP_RI);
36d23958
TS
7924 break;
7925 }
7926 } else {
7927 generate_exception_err(ctx, EXCP_CpU, 1);
6ea83fed 7928 }
4ad40f36
FB
7929 break;
7930
7931 /* COP2. */
7a387fff
TS
7932 case OPC_LWC2:
7933 case OPC_LDC2:
7934 case OPC_SWC2:
7935 case OPC_SDC2:
7936 case OPC_CP2:
7937 /* COP2: Not implemented. */
4ad40f36
FB
7938 generate_exception_err(ctx, EXCP_CpU, 2);
7939 break;
7940
7a387fff 7941 case OPC_CP3:
36d23958 7942 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
e397ee33 7943 save_cpu_state(ctx, 1);
5e755519 7944 check_cp1_enabled(ctx);
36d23958
TS
7945 op1 = MASK_CP3(ctx->opcode);
7946 switch (op1) {
5a5012ec
TS
7947 case OPC_LWXC1:
7948 case OPC_LDXC1:
7949 case OPC_LUXC1:
7950 case OPC_SWXC1:
7951 case OPC_SDXC1:
7952 case OPC_SUXC1:
93b12ccc 7953 gen_flt3_ldst(ctx, op1, sa, rd, rs, rt);
5a5012ec 7954 break;
e0c84da7 7955 case OPC_PREFX:
ead9360e 7956 /* Treat as NOP. */
e0c84da7 7957 break;
5a5012ec
TS
7958 case OPC_ALNV_PS:
7959 case OPC_MADD_S:
7960 case OPC_MADD_D:
7961 case OPC_MADD_PS:
7962 case OPC_MSUB_S:
7963 case OPC_MSUB_D:
7964 case OPC_MSUB_PS:
7965 case OPC_NMADD_S:
7966 case OPC_NMADD_D:
7967 case OPC_NMADD_PS:
7968 case OPC_NMSUB_S:
7969 case OPC_NMSUB_D:
7970 case OPC_NMSUB_PS:
7971 gen_flt3_arith(ctx, op1, sa, rs, rd, rt);
7972 break;
36d23958 7973 default:
923617a3 7974 MIPS_INVAL("cp3");
e397ee33 7975 generate_exception (ctx, EXCP_RI);
36d23958
TS
7976 break;
7977 }
7978 } else {
e397ee33 7979 generate_exception_err(ctx, EXCP_CpU, 1);
7a387fff 7980 }
4ad40f36
FB
7981 break;
7982
d26bc211 7983#if defined(TARGET_MIPS64)
7a387fff
TS
7984 /* MIPS64 opcodes */
7985 case OPC_LWU:
7986 case OPC_LDL ... OPC_LDR:
7987 case OPC_SDL ... OPC_SDR:
7988 case OPC_LLD:
7989 case OPC_LD:
7990 case OPC_SCD:
7991 case OPC_SD:
e189e748
TS
7992 check_insn(env, ctx, ISA_MIPS3);
7993 check_mips_64(ctx);
7a387fff
TS
7994 gen_ldst(ctx, op, rt, rs, imm);
7995 break;
7996 case OPC_DADDI ... OPC_DADDIU:
e189e748
TS
7997 check_insn(env, ctx, ISA_MIPS3);
7998 check_mips_64(ctx);
7999 gen_arith_imm(env, ctx, op, rt, rs, imm);
7a387fff 8000 break;
6af0bf9c 8001#endif
7a387fff 8002 case OPC_JALX:
e189e748 8003 check_insn(env, ctx, ASE_MIPS16);
7a387fff 8004 /* MIPS16: Not implemented. */
7a387fff 8005 case OPC_MDMX:
e189e748 8006 check_insn(env, ctx, ASE_MDMX);
7a387fff 8007 /* MDMX: Not implemented. */
6af0bf9c 8008 default: /* Invalid */
923617a3 8009 MIPS_INVAL("major opcode");
6af0bf9c
FB
8010 generate_exception(ctx, EXCP_RI);
8011 break;
8012 }
4ad40f36 8013 if (ctx->hflags & MIPS_HFLAG_BMASK) {
c53f4a62 8014 int hflags = ctx->hflags & MIPS_HFLAG_BMASK;
6af0bf9c 8015 /* Branches completion */
4ad40f36 8016 ctx->hflags &= ~MIPS_HFLAG_BMASK;
6af0bf9c
FB
8017 ctx->bstate = BS_BRANCH;
8018 save_cpu_state(ctx, 0);
2e70f6ef 8019 /* FIXME: Need to clear can_do_io. */
5a5012ec 8020 switch (hflags) {
6af0bf9c
FB
8021 case MIPS_HFLAG_B:
8022 /* unconditional branch */
8023 MIPS_DEBUG("unconditional branch");
6e256c93 8024 gen_goto_tb(ctx, 0, ctx->btarget);
6af0bf9c
FB
8025 break;
8026 case MIPS_HFLAG_BL:
8027 /* blikely taken case */
8028 MIPS_DEBUG("blikely branch taken");
6e256c93 8029 gen_goto_tb(ctx, 0, ctx->btarget);
6af0bf9c
FB
8030 break;
8031 case MIPS_HFLAG_BC:
8032 /* Conditional branch */
8033 MIPS_DEBUG("conditional branch");
c53be334 8034 {
8e9ade68
TS
8035 int l1 = gen_new_label();
8036
1ba74fb8 8037 tcg_gen_brcondi_tl(TCG_COND_NE, bcond, 0, l1);
8e9ade68
TS
8038 gen_goto_tb(ctx, 1, ctx->pc + 4);
8039 gen_set_label(l1);
8040 gen_goto_tb(ctx, 0, ctx->btarget);
c53be334 8041 }
6af0bf9c
FB
8042 break;
8043 case MIPS_HFLAG_BR:
8044 /* unconditional branch to register */
8045 MIPS_DEBUG("branch to register");
4b2eb8d2 8046 tcg_gen_mov_tl(cpu_PC, btarget);
57fec1fe 8047 tcg_gen_exit_tb(0);
6af0bf9c
FB
8048 break;
8049 default:
8050 MIPS_DEBUG("unknown branch");
8051 break;
8052 }
8053 }
8054}
8055
2cfc5f17 8056static inline void
820e00f2
TS
8057gen_intermediate_code_internal (CPUState *env, TranslationBlock *tb,
8058 int search_pc)
6af0bf9c 8059{
278d0702 8060 DisasContext ctx;
6af0bf9c
FB
8061 target_ulong pc_start;
8062 uint16_t *gen_opc_end;
a1d1bb31 8063 CPUBreakpoint *bp;
6af0bf9c 8064 int j, lj = -1;
2e70f6ef
PB
8065 int num_insns;
8066 int max_insns;
6af0bf9c 8067
93fcfe39
AL
8068 if (search_pc)
8069 qemu_log("search pc %d\n", search_pc);
4ad40f36 8070
6af0bf9c 8071 pc_start = tb->pc;
faf7aaa9
TS
8072 /* Leave some spare opc slots for branch handling. */
8073 gen_opc_end = gen_opc_buf + OPC_MAX_SIZE - 16;
6af0bf9c 8074 ctx.pc = pc_start;
4ad40f36 8075 ctx.saved_pc = -1;
6af0bf9c
FB
8076 ctx.tb = tb;
8077 ctx.bstate = BS_NONE;
4ad40f36 8078 /* Restore delay slot state from the tb context. */
c068688b 8079 ctx.hflags = (uint32_t)tb->flags; /* FIXME: maybe use 64 bits here? */
fd4a04eb 8080 restore_cpu_state(env, &ctx);
932e71cd 8081#ifdef CONFIG_USER_ONLY
0eaef5aa 8082 ctx.mem_idx = MIPS_HFLAG_UM;
932e71cd 8083#else
0eaef5aa 8084 ctx.mem_idx = ctx.hflags & MIPS_HFLAG_KSU;
932e71cd 8085#endif
2e70f6ef
PB
8086 num_insns = 0;
8087 max_insns = tb->cflags & CF_COUNT_MASK;
8088 if (max_insns == 0)
8089 max_insns = CF_COUNT_MASK;
6af0bf9c 8090#ifdef DEBUG_DISAS
93fcfe39
AL
8091 qemu_log_mask(CPU_LOG_TB_CPU, "------------------------------------------------\n");
8092 /* FIXME: This may print out stale hflags from env... */
8093 log_cpu_state_mask(CPU_LOG_TB_CPU, env, 0);
6af0bf9c 8094#endif
d12d51d5 8095 LOG_DISAS("\ntb %p idx %d hflags %04x\n", tb, ctx.mem_idx, ctx.hflags);
2e70f6ef 8096 gen_icount_start();
faf7aaa9 8097 while (ctx.bstate == BS_NONE) {
c0ce998e
AL
8098 if (unlikely(!TAILQ_EMPTY(&env->breakpoints))) {
8099 TAILQ_FOREACH(bp, &env->breakpoints, entry) {
a1d1bb31 8100 if (bp->pc == ctx.pc) {
278d0702 8101 save_cpu_state(&ctx, 1);
4ad40f36 8102 ctx.bstate = BS_BRANCH;
a7812ae4 8103 gen_helper_0i(raise_exception, EXCP_DEBUG);
ce62e5ba
TS
8104 /* Include the breakpoint location or the tb won't
8105 * be flushed when it must be. */
8106 ctx.pc += 4;
4ad40f36
FB
8107 goto done_generating;
8108 }
8109 }
8110 }
8111
6af0bf9c
FB
8112 if (search_pc) {
8113 j = gen_opc_ptr - gen_opc_buf;
6af0bf9c
FB
8114 if (lj < j) {
8115 lj++;
8116 while (lj < j)
8117 gen_opc_instr_start[lj++] = 0;
6af0bf9c 8118 }
4ad40f36
FB
8119 gen_opc_pc[lj] = ctx.pc;
8120 gen_opc_hflags[lj] = ctx.hflags & MIPS_HFLAG_BMASK;
8121 gen_opc_instr_start[lj] = 1;
2e70f6ef 8122 gen_opc_icount[lj] = num_insns;
6af0bf9c 8123 }
2e70f6ef
PB
8124 if (num_insns + 1 == max_insns && (tb->cflags & CF_LAST_IO))
8125 gen_io_start();
6af0bf9c 8126 ctx.opcode = ldl_code(ctx.pc);
36d23958 8127 decode_opc(env, &ctx);
6af0bf9c 8128 ctx.pc += 4;
2e70f6ef 8129 num_insns++;
4ad40f36
FB
8130
8131 if (env->singlestep_enabled)
8132 break;
8133
6af0bf9c
FB
8134 if ((ctx.pc & (TARGET_PAGE_SIZE - 1)) == 0)
8135 break;
4ad40f36 8136
faf7aaa9
TS
8137 if (gen_opc_ptr >= gen_opc_end)
8138 break;
8139
2e70f6ef
PB
8140 if (num_insns >= max_insns)
8141 break;
1b530a6d
AJ
8142
8143 if (singlestep)
8144 break;
6af0bf9c 8145 }
2e70f6ef
PB
8146 if (tb->cflags & CF_LAST_IO)
8147 gen_io_end();
4ad40f36 8148 if (env->singlestep_enabled) {
278d0702 8149 save_cpu_state(&ctx, ctx.bstate == BS_NONE);
a7812ae4 8150 gen_helper_0i(raise_exception, EXCP_DEBUG);
16c00cb2 8151 } else {
6958549d 8152 switch (ctx.bstate) {
16c00cb2 8153 case BS_STOP:
a7812ae4 8154 gen_helper_interrupt_restart();
df1561e2
TS
8155 gen_goto_tb(&ctx, 0, ctx.pc);
8156 break;
16c00cb2 8157 case BS_NONE:
278d0702 8158 save_cpu_state(&ctx, 0);
16c00cb2
TS
8159 gen_goto_tb(&ctx, 0, ctx.pc);
8160 break;
5a5012ec 8161 case BS_EXCP:
a7812ae4 8162 gen_helper_interrupt_restart();
57fec1fe 8163 tcg_gen_exit_tb(0);
16c00cb2 8164 break;
5a5012ec
TS
8165 case BS_BRANCH:
8166 default:
8167 break;
6958549d 8168 }
6af0bf9c 8169 }
4ad40f36 8170done_generating:
2e70f6ef 8171 gen_icount_end(tb, num_insns);
6af0bf9c
FB
8172 *gen_opc_ptr = INDEX_op_end;
8173 if (search_pc) {
8174 j = gen_opc_ptr - gen_opc_buf;
8175 lj++;
8176 while (lj <= j)
8177 gen_opc_instr_start[lj++] = 0;
6af0bf9c
FB
8178 } else {
8179 tb->size = ctx.pc - pc_start;
2e70f6ef 8180 tb->icount = num_insns;
6af0bf9c
FB
8181 }
8182#ifdef DEBUG_DISAS
d12d51d5 8183 LOG_DISAS("\n");
8fec2b8c 8184 if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) {
93fcfe39
AL
8185 qemu_log("IN: %s\n", lookup_symbol(pc_start));
8186 log_target_disas(pc_start, ctx.pc - pc_start, 0);
8187 qemu_log("\n");
6af0bf9c 8188 }
93fcfe39 8189 qemu_log_mask(CPU_LOG_TB_CPU, "---------------- %d %08x\n", ctx.bstate, ctx.hflags);
6af0bf9c 8190#endif
6af0bf9c
FB
8191}
8192
2cfc5f17 8193void gen_intermediate_code (CPUState *env, struct TranslationBlock *tb)
6af0bf9c 8194{
2cfc5f17 8195 gen_intermediate_code_internal(env, tb, 0);
6af0bf9c
FB
8196}
8197
2cfc5f17 8198void gen_intermediate_code_pc (CPUState *env, struct TranslationBlock *tb)
6af0bf9c 8199{
2cfc5f17 8200 gen_intermediate_code_internal(env, tb, 1);
6af0bf9c
FB
8201}
8202
8706c382
TS
8203static void fpu_dump_state(CPUState *env, FILE *f,
8204 int (*fpu_fprintf)(FILE *f, const char *fmt, ...),
8205 int flags)
6ea83fed
FB
8206{
8207 int i;
5e755519 8208 int is_fpu64 = !!(env->hflags & MIPS_HFLAG_F64);
5a5012ec
TS
8209
8210#define printfpr(fp) \
8211 do { \
8212 if (is_fpu64) \
8213 fpu_fprintf(f, "w:%08x d:%016lx fd:%13g fs:%13g psu: %13g\n", \
8214 (fp)->w[FP_ENDIAN_IDX], (fp)->d, (fp)->fd, \
8215 (fp)->fs[FP_ENDIAN_IDX], (fp)->fs[!FP_ENDIAN_IDX]); \
8216 else { \
8217 fpr_t tmp; \
8218 tmp.w[FP_ENDIAN_IDX] = (fp)->w[FP_ENDIAN_IDX]; \
8219 tmp.w[!FP_ENDIAN_IDX] = ((fp) + 1)->w[FP_ENDIAN_IDX]; \
8220 fpu_fprintf(f, "w:%08x d:%016lx fd:%13g fs:%13g psu:%13g\n", \
8221 tmp.w[FP_ENDIAN_IDX], tmp.d, tmp.fd, \
8222 tmp.fs[FP_ENDIAN_IDX], tmp.fs[!FP_ENDIAN_IDX]); \
8223 } \
6ea83fed
FB
8224 } while(0)
8225
5a5012ec
TS
8226
8227 fpu_fprintf(f, "CP1 FCR0 0x%08x FCR31 0x%08x SR.FR %d fp_status 0x%08x(0x%02x)\n",
f01be154
TS
8228 env->active_fpu.fcr0, env->active_fpu.fcr31, is_fpu64, env->active_fpu.fp_status,
8229 get_float_exception_flags(&env->active_fpu.fp_status));
5a5012ec
TS
8230 for (i = 0; i < 32; (is_fpu64) ? i++ : (i += 2)) {
8231 fpu_fprintf(f, "%3s: ", fregnames[i]);
f01be154 8232 printfpr(&env->active_fpu.fpr[i]);
6ea83fed
FB
8233 }
8234
8235#undef printfpr
8236}
8237
d26bc211 8238#if defined(TARGET_MIPS64) && defined(MIPS_DEBUG_SIGN_EXTENSIONS)
c570fd16 8239/* Debug help: The architecture requires 32bit code to maintain proper
c7e8a937 8240 sign-extended values on 64bit machines. */
c570fd16
TS
8241
8242#define SIGN_EXT_P(val) ((((val) & ~0x7fffffff) == 0) || (((val) & ~0x7fffffff) == ~0x7fffffff))
8243
8706c382
TS
8244static void
8245cpu_mips_check_sign_extensions (CPUState *env, FILE *f,
8246 int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
8247 int flags)
c570fd16
TS
8248{
8249 int i;
8250
b5dc7732
TS
8251 if (!SIGN_EXT_P(env->active_tc.PC))
8252 cpu_fprintf(f, "BROKEN: pc=0x" TARGET_FMT_lx "\n", env->active_tc.PC);
8253 if (!SIGN_EXT_P(env->active_tc.HI[0]))
8254 cpu_fprintf(f, "BROKEN: HI=0x" TARGET_FMT_lx "\n", env->active_tc.HI[0]);
8255 if (!SIGN_EXT_P(env->active_tc.LO[0]))
8256 cpu_fprintf(f, "BROKEN: LO=0x" TARGET_FMT_lx "\n", env->active_tc.LO[0]);
c570fd16 8257 if (!SIGN_EXT_P(env->btarget))
3594c774 8258 cpu_fprintf(f, "BROKEN: btarget=0x" TARGET_FMT_lx "\n", env->btarget);
c570fd16
TS
8259
8260 for (i = 0; i < 32; i++) {
b5dc7732
TS
8261 if (!SIGN_EXT_P(env->active_tc.gpr[i]))
8262 cpu_fprintf(f, "BROKEN: %s=0x" TARGET_FMT_lx "\n", regnames[i], env->active_tc.gpr[i]);
c570fd16
TS
8263 }
8264
8265 if (!SIGN_EXT_P(env->CP0_EPC))
3594c774 8266 cpu_fprintf(f, "BROKEN: EPC=0x" TARGET_FMT_lx "\n", env->CP0_EPC);
c570fd16 8267 if (!SIGN_EXT_P(env->CP0_LLAddr))
3594c774 8268 cpu_fprintf(f, "BROKEN: LLAddr=0x" TARGET_FMT_lx "\n", env->CP0_LLAddr);
c570fd16
TS
8269}
8270#endif
8271
5fafdf24 8272void cpu_dump_state (CPUState *env, FILE *f,
6af0bf9c
FB
8273 int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
8274 int flags)
8275{
8276 int i;
3b46e624 8277
3594c774 8278 cpu_fprintf(f, "pc=0x" TARGET_FMT_lx " HI=0x" TARGET_FMT_lx " LO=0x" TARGET_FMT_lx " ds %04x " TARGET_FMT_lx " %d\n",
3d5be870
TS
8279 env->active_tc.PC, env->active_tc.HI[0], env->active_tc.LO[0],
8280 env->hflags, env->btarget, env->bcond);
6af0bf9c
FB
8281 for (i = 0; i < 32; i++) {
8282 if ((i & 3) == 0)
8283 cpu_fprintf(f, "GPR%02d:", i);
b5dc7732 8284 cpu_fprintf(f, " %s " TARGET_FMT_lx, regnames[i], env->active_tc.gpr[i]);
6af0bf9c
FB
8285 if ((i & 3) == 3)
8286 cpu_fprintf(f, "\n");
8287 }
568b600d 8288
3594c774 8289 cpu_fprintf(f, "CP0 Status 0x%08x Cause 0x%08x EPC 0x" TARGET_FMT_lx "\n",
5e755519 8290 env->CP0_Status, env->CP0_Cause, env->CP0_EPC);
3594c774 8291 cpu_fprintf(f, " Config0 0x%08x Config1 0x%08x LLAddr 0x" TARGET_FMT_lx "\n",
6af0bf9c 8292 env->CP0_Config0, env->CP0_Config1, env->CP0_LLAddr);
5e755519 8293 if (env->hflags & MIPS_HFLAG_FPU)
7a387fff 8294 fpu_dump_state(env, f, cpu_fprintf, flags);
d26bc211 8295#if defined(TARGET_MIPS64) && defined(MIPS_DEBUG_SIGN_EXTENSIONS)
c570fd16
TS
8296 cpu_mips_check_sign_extensions(env, f, cpu_fprintf, flags);
8297#endif
6af0bf9c
FB
8298}
8299
39454628
TS
8300static void mips_tcg_init(void)
8301{
f01be154 8302 int i;
39454628
TS
8303 static int inited;
8304
8305 /* Initialize various static tables. */
8306 if (inited)
6958549d 8307 return;
39454628 8308
a7812ae4 8309 cpu_env = tcg_global_reg_new_ptr(TCG_AREG0, "env");
4b2eb8d2 8310 for (i = 0; i < 32; i++)
a7812ae4 8311 cpu_gpr[i] = tcg_global_mem_new(TCG_AREG0,
4b2eb8d2
TS
8312 offsetof(CPUState, active_tc.gpr[i]),
8313 regnames[i]);
a7812ae4 8314 cpu_PC = tcg_global_mem_new(TCG_AREG0,
4b2eb8d2
TS
8315 offsetof(CPUState, active_tc.PC), "PC");
8316 for (i = 0; i < MIPS_DSP_ACC; i++) {
a7812ae4 8317 cpu_HI[i] = tcg_global_mem_new(TCG_AREG0,
4b2eb8d2
TS
8318 offsetof(CPUState, active_tc.HI[i]),
8319 regnames_HI[i]);
a7812ae4 8320 cpu_LO[i] = tcg_global_mem_new(TCG_AREG0,
4b2eb8d2
TS
8321 offsetof(CPUState, active_tc.LO[i]),
8322 regnames_LO[i]);
a7812ae4 8323 cpu_ACX[i] = tcg_global_mem_new(TCG_AREG0,
4b2eb8d2
TS
8324 offsetof(CPUState, active_tc.ACX[i]),
8325 regnames_ACX[i]);
8326 }
a7812ae4 8327 cpu_dspctrl = tcg_global_mem_new(TCG_AREG0,
4b2eb8d2
TS
8328 offsetof(CPUState, active_tc.DSPControl),
8329 "DSPControl");
1ba74fb8
AJ
8330 bcond = tcg_global_mem_new(TCG_AREG0,
8331 offsetof(CPUState, bcond), "bcond");
a7812ae4 8332 btarget = tcg_global_mem_new(TCG_AREG0,
d077b6f7 8333 offsetof(CPUState, btarget), "btarget");
41db4607
AJ
8334 hflags = tcg_global_mem_new_i32(TCG_AREG0,
8335 offsetof(CPUState, hflags), "hflags");
8336
a7812ae4
PB
8337 fpu_fcr0 = tcg_global_mem_new_i32(TCG_AREG0,
8338 offsetof(CPUState, active_fpu.fcr0),
8339 "fcr0");
8340 fpu_fcr31 = tcg_global_mem_new_i32(TCG_AREG0,
8341 offsetof(CPUState, active_fpu.fcr31),
8342 "fcr31");
39454628 8343
7dd9e556 8344 /* register helpers */
a7812ae4 8345#define GEN_HELPER 2
7dd9e556
TS
8346#include "helper.h"
8347
39454628
TS
8348 inited = 1;
8349}
8350
aaed909a
FB
8351#include "translate_init.c"
8352
8353CPUMIPSState *cpu_mips_init (const char *cpu_model)
6af0bf9c
FB
8354{
8355 CPUMIPSState *env;
aaed909a 8356 const mips_def_t *def;
6af0bf9c 8357
aaed909a
FB
8358 def = cpu_mips_find_by_name(cpu_model);
8359 if (!def)
8360 return NULL;
6af0bf9c 8361 env = qemu_mallocz(sizeof(CPUMIPSState));
aaed909a
FB
8362 env->cpu_model = def;
8363
173d6cfe 8364 cpu_exec_init(env);
01ba9816 8365 env->cpu_model_str = cpu_model;
39454628 8366 mips_tcg_init();
6ae81775
TS
8367 cpu_reset(env);
8368 return env;
8369}
8370
8371void cpu_reset (CPUMIPSState *env)
8372{
eca1bdf4
AL
8373 if (qemu_loglevel_mask(CPU_LOG_RESET)) {
8374 qemu_log("CPU Reset (CPU %d)\n", env->cpu_index);
8375 log_cpu_state(env, 0);
8376 }
8377
6ae81775
TS
8378 memset(env, 0, offsetof(CPUMIPSState, breakpoints));
8379
6af0bf9c 8380 tlb_flush(env, 1);
6ae81775 8381
6af0bf9c 8382 /* Minimal init */
0eaef5aa 8383#if defined(CONFIG_USER_ONLY)
932e71cd
AJ
8384 env->hflags = MIPS_HFLAG_UM;
8385#else
8386 if (env->hflags & MIPS_HFLAG_BMASK) {
8387 /* If the exception was raised from a delay slot,
8388 come back to the jump. */
8389 env->CP0_ErrorEPC = env->active_tc.PC - 4;
aa328add 8390 } else {
932e71cd
AJ
8391 env->CP0_ErrorEPC = env->active_tc.PC;
8392 }
8393 env->active_tc.PC = (int32_t)0xBFC00000;
8394 env->CP0_Wired = 0;
8395 /* SMP not implemented */
8396 env->CP0_EBase = 0x80000000;
8397 env->CP0_Status = (1 << CP0St_BEV) | (1 << CP0St_ERL);
8398 /* vectored interrupts not implemented, timer on int 7,
8399 no performance counters. */
8400 env->CP0_IntCtl = 0xe0000000;
8401 {
8402 int i;
8403
8404 for (i = 0; i < 7; i++) {
8405 env->CP0_WatchLo[i] = 0;
8406 env->CP0_WatchHi[i] = 0x80000000;
fd88b6ab 8407 }
932e71cd
AJ
8408 env->CP0_WatchLo[7] = 0;
8409 env->CP0_WatchHi[7] = 0;
fd88b6ab 8410 }
932e71cd
AJ
8411 /* Count register increments in debug mode, EJTAG version 1 */
8412 env->CP0_Debug = (1 << CP0DB_CNT) | (0x1 << CP0DB_VER);
8413 env->hflags = MIPS_HFLAG_CP0;
8414#endif
6af0bf9c 8415 env->exception_index = EXCP_NONE;
aaed909a 8416 cpu_mips_register(env, env->cpu_model);
6af0bf9c 8417}
d2856f1a
AJ
8418
8419void gen_pc_load(CPUState *env, TranslationBlock *tb,
8420 unsigned long searched_pc, int pc_pos, void *puc)
8421{
b5dc7732 8422 env->active_tc.PC = gen_opc_pc[pc_pos];
d2856f1a
AJ
8423 env->hflags &= ~MIPS_HFLAG_BMASK;
8424 env->hflags |= gen_opc_hflags[pc_pos];
8425}