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