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