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