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