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