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