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