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