]> git.proxmox.com Git - mirror_qemu.git/blame - target-mips/translate.c
Rename target_phys_addr_t to hwaddr
[mirror_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)
3c824109 7 * Copyright (c) 2009 CodeSourcery (MIPS16 and microMIPS support)
6af0bf9c
FB
8 *
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation; either
12 * version 2 of the License, or (at your option) any later version.
13 *
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
18 *
19 * You should have received a copy of the GNU Lesser General Public
8167ee88 20 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
6af0bf9c
FB
21 */
22
6af0bf9c 23#include "cpu.h"
6af0bf9c 24#include "disas.h"
57fec1fe 25#include "tcg-op.h"
6af0bf9c 26
a7812ae4
PB
27#include "helper.h"
28#define GEN_HELPER 1
29#include "helper.h"
30
fb7729e2 31#define MIPS_DEBUG_DISAS 0
c570fd16 32//#define MIPS_DEBUG_SIGN_EXTENSIONS
6af0bf9c 33
7a387fff
TS
34/* MIPS major opcodes */
35#define MASK_OP_MAJOR(op) (op & (0x3F << 26))
e37e863f
FB
36
37enum {
38 /* indirect opcode tables */
7a387fff
TS
39 OPC_SPECIAL = (0x00 << 26),
40 OPC_REGIMM = (0x01 << 26),
41 OPC_CP0 = (0x10 << 26),
42 OPC_CP1 = (0x11 << 26),
43 OPC_CP2 = (0x12 << 26),
44 OPC_CP3 = (0x13 << 26),
45 OPC_SPECIAL2 = (0x1C << 26),
46 OPC_SPECIAL3 = (0x1F << 26),
e37e863f 47 /* arithmetic with immediate */
7a387fff
TS
48 OPC_ADDI = (0x08 << 26),
49 OPC_ADDIU = (0x09 << 26),
50 OPC_SLTI = (0x0A << 26),
51 OPC_SLTIU = (0x0B << 26),
324d9e32 52 /* logic with immediate */
7a387fff
TS
53 OPC_ANDI = (0x0C << 26),
54 OPC_ORI = (0x0D << 26),
55 OPC_XORI = (0x0E << 26),
56 OPC_LUI = (0x0F << 26),
324d9e32 57 /* arithmetic with immediate */
7a387fff
TS
58 OPC_DADDI = (0x18 << 26),
59 OPC_DADDIU = (0x19 << 26),
e37e863f 60 /* Jump and branches */
7a387fff
TS
61 OPC_J = (0x02 << 26),
62 OPC_JAL = (0x03 << 26),
620e48f6 63 OPC_JALS = OPC_JAL | 0x5,
7a387fff
TS
64 OPC_BEQ = (0x04 << 26), /* Unconditional if rs = rt = 0 (B) */
65 OPC_BEQL = (0x14 << 26),
66 OPC_BNE = (0x05 << 26),
67 OPC_BNEL = (0x15 << 26),
68 OPC_BLEZ = (0x06 << 26),
69 OPC_BLEZL = (0x16 << 26),
70 OPC_BGTZ = (0x07 << 26),
71 OPC_BGTZL = (0x17 << 26),
72 OPC_JALX = (0x1D << 26), /* MIPS 16 only */
620e48f6 73 OPC_JALXS = OPC_JALX | 0x5,
e37e863f 74 /* Load and stores */
7a387fff
TS
75 OPC_LDL = (0x1A << 26),
76 OPC_LDR = (0x1B << 26),
77 OPC_LB = (0x20 << 26),
78 OPC_LH = (0x21 << 26),
79 OPC_LWL = (0x22 << 26),
80 OPC_LW = (0x23 << 26),
364d4831 81 OPC_LWPC = OPC_LW | 0x5,
7a387fff
TS
82 OPC_LBU = (0x24 << 26),
83 OPC_LHU = (0x25 << 26),
84 OPC_LWR = (0x26 << 26),
85 OPC_LWU = (0x27 << 26),
86 OPC_SB = (0x28 << 26),
87 OPC_SH = (0x29 << 26),
88 OPC_SWL = (0x2A << 26),
89 OPC_SW = (0x2B << 26),
90 OPC_SDL = (0x2C << 26),
91 OPC_SDR = (0x2D << 26),
92 OPC_SWR = (0x2E << 26),
93 OPC_LL = (0x30 << 26),
94 OPC_LLD = (0x34 << 26),
95 OPC_LD = (0x37 << 26),
364d4831 96 OPC_LDPC = OPC_LD | 0x5,
7a387fff
TS
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 */
ea63e2c3 128 OPC_ROTR = OPC_SRL | (1 << 21),
7a387fff
TS
129 OPC_SRA = 0x03 | OPC_SPECIAL,
130 OPC_SLLV = 0x04 | OPC_SPECIAL,
e189e748 131 OPC_SRLV = 0x06 | OPC_SPECIAL, /* also ROTRV */
ea63e2c3 132 OPC_ROTRV = OPC_SRLV | (1 << 6),
7a387fff
TS
133 OPC_SRAV = 0x07 | OPC_SPECIAL,
134 OPC_DSLLV = 0x14 | OPC_SPECIAL,
135 OPC_DSRLV = 0x16 | OPC_SPECIAL, /* also DROTRV */
ea63e2c3 136 OPC_DROTRV = OPC_DSRLV | (1 << 6),
7a387fff
TS
137 OPC_DSRAV = 0x17 | OPC_SPECIAL,
138 OPC_DSLL = 0x38 | OPC_SPECIAL,
139 OPC_DSRL = 0x3A | OPC_SPECIAL, /* also DROTR */
ea63e2c3 140 OPC_DROTR = OPC_DSRL | (1 << 21),
7a387fff
TS
141 OPC_DSRA = 0x3B | OPC_SPECIAL,
142 OPC_DSLL32 = 0x3C | OPC_SPECIAL,
143 OPC_DSRL32 = 0x3E | OPC_SPECIAL, /* also DROTR32 */
ea63e2c3 144 OPC_DROTR32 = OPC_DSRL32 | (1 << 21),
7a387fff 145 OPC_DSRA32 = 0x3F | OPC_SPECIAL,
e37e863f 146 /* Multiplication / division */
7a387fff
TS
147 OPC_MULT = 0x18 | OPC_SPECIAL,
148 OPC_MULTU = 0x19 | OPC_SPECIAL,
149 OPC_DIV = 0x1A | OPC_SPECIAL,
150 OPC_DIVU = 0x1B | OPC_SPECIAL,
151 OPC_DMULT = 0x1C | OPC_SPECIAL,
152 OPC_DMULTU = 0x1D | OPC_SPECIAL,
153 OPC_DDIV = 0x1E | OPC_SPECIAL,
154 OPC_DDIVU = 0x1F | OPC_SPECIAL,
e37e863f 155 /* 2 registers arithmetic / logic */
7a387fff
TS
156 OPC_ADD = 0x20 | OPC_SPECIAL,
157 OPC_ADDU = 0x21 | OPC_SPECIAL,
158 OPC_SUB = 0x22 | OPC_SPECIAL,
159 OPC_SUBU = 0x23 | OPC_SPECIAL,
160 OPC_AND = 0x24 | OPC_SPECIAL,
161 OPC_OR = 0x25 | OPC_SPECIAL,
162 OPC_XOR = 0x26 | OPC_SPECIAL,
163 OPC_NOR = 0x27 | OPC_SPECIAL,
164 OPC_SLT = 0x2A | OPC_SPECIAL,
165 OPC_SLTU = 0x2B | OPC_SPECIAL,
166 OPC_DADD = 0x2C | OPC_SPECIAL,
167 OPC_DADDU = 0x2D | OPC_SPECIAL,
168 OPC_DSUB = 0x2E | OPC_SPECIAL,
169 OPC_DSUBU = 0x2F | OPC_SPECIAL,
e37e863f 170 /* Jumps */
7a387fff
TS
171 OPC_JR = 0x08 | OPC_SPECIAL, /* Also JR.HB */
172 OPC_JALR = 0x09 | OPC_SPECIAL, /* Also JALR.HB */
364d4831 173 OPC_JALRC = OPC_JALR | (0x5 << 6),
620e48f6 174 OPC_JALRS = 0x10 | OPC_SPECIAL | (0x5 << 6),
e37e863f 175 /* Traps */
7a387fff
TS
176 OPC_TGE = 0x30 | OPC_SPECIAL,
177 OPC_TGEU = 0x31 | OPC_SPECIAL,
178 OPC_TLT = 0x32 | OPC_SPECIAL,
179 OPC_TLTU = 0x33 | OPC_SPECIAL,
180 OPC_TEQ = 0x34 | OPC_SPECIAL,
181 OPC_TNE = 0x36 | OPC_SPECIAL,
e37e863f 182 /* HI / LO registers load & stores */
7a387fff
TS
183 OPC_MFHI = 0x10 | OPC_SPECIAL,
184 OPC_MTHI = 0x11 | OPC_SPECIAL,
185 OPC_MFLO = 0x12 | OPC_SPECIAL,
186 OPC_MTLO = 0x13 | OPC_SPECIAL,
e37e863f 187 /* Conditional moves */
7a387fff
TS
188 OPC_MOVZ = 0x0A | OPC_SPECIAL,
189 OPC_MOVN = 0x0B | OPC_SPECIAL,
e37e863f 190
7a387fff 191 OPC_MOVCI = 0x01 | OPC_SPECIAL,
e37e863f
FB
192
193 /* Special */
a0d700e4 194 OPC_PMON = 0x05 | OPC_SPECIAL, /* unofficial */
7a387fff
TS
195 OPC_SYSCALL = 0x0C | OPC_SPECIAL,
196 OPC_BREAK = 0x0D | OPC_SPECIAL,
a0d700e4 197 OPC_SPIM = 0x0E | OPC_SPECIAL, /* unofficial */
7a387fff
TS
198 OPC_SYNC = 0x0F | OPC_SPECIAL,
199
200 OPC_SPECIAL15_RESERVED = 0x15 | OPC_SPECIAL,
201 OPC_SPECIAL28_RESERVED = 0x28 | OPC_SPECIAL,
202 OPC_SPECIAL29_RESERVED = 0x29 | OPC_SPECIAL,
203 OPC_SPECIAL35_RESERVED = 0x35 | OPC_SPECIAL,
204 OPC_SPECIAL37_RESERVED = 0x37 | OPC_SPECIAL,
205 OPC_SPECIAL39_RESERVED = 0x39 | OPC_SPECIAL,
206 OPC_SPECIAL3D_RESERVED = 0x3D | OPC_SPECIAL,
207};
208
e9c71dd1
TS
209/* Multiplication variants of the vr54xx. */
210#define MASK_MUL_VR54XX(op) MASK_SPECIAL(op) | (op & (0x1F << 6))
211
212enum {
213 OPC_VR54XX_MULS = (0x03 << 6) | OPC_MULT,
214 OPC_VR54XX_MULSU = (0x03 << 6) | OPC_MULTU,
215 OPC_VR54XX_MACC = (0x05 << 6) | OPC_MULT,
216 OPC_VR54XX_MACCU = (0x05 << 6) | OPC_MULTU,
217 OPC_VR54XX_MSAC = (0x07 << 6) | OPC_MULT,
218 OPC_VR54XX_MSACU = (0x07 << 6) | OPC_MULTU,
219 OPC_VR54XX_MULHI = (0x09 << 6) | OPC_MULT,
220 OPC_VR54XX_MULHIU = (0x09 << 6) | OPC_MULTU,
221 OPC_VR54XX_MULSHI = (0x0B << 6) | OPC_MULT,
222 OPC_VR54XX_MULSHIU = (0x0B << 6) | OPC_MULTU,
223 OPC_VR54XX_MACCHI = (0x0D << 6) | OPC_MULT,
224 OPC_VR54XX_MACCHIU = (0x0D << 6) | OPC_MULTU,
225 OPC_VR54XX_MSACHI = (0x0F << 6) | OPC_MULT,
226 OPC_VR54XX_MSACHIU = (0x0F << 6) | OPC_MULTU,
227};
228
7a387fff
TS
229/* REGIMM (rt field) opcodes */
230#define MASK_REGIMM(op) MASK_OP_MAJOR(op) | (op & (0x1F << 16))
231
232enum {
233 OPC_BLTZ = (0x00 << 16) | OPC_REGIMM,
234 OPC_BLTZL = (0x02 << 16) | OPC_REGIMM,
235 OPC_BGEZ = (0x01 << 16) | OPC_REGIMM,
236 OPC_BGEZL = (0x03 << 16) | OPC_REGIMM,
237 OPC_BLTZAL = (0x10 << 16) | OPC_REGIMM,
3c824109 238 OPC_BLTZALS = OPC_BLTZAL | 0x5, /* microMIPS */
7a387fff
TS
239 OPC_BLTZALL = (0x12 << 16) | OPC_REGIMM,
240 OPC_BGEZAL = (0x11 << 16) | OPC_REGIMM,
3c824109 241 OPC_BGEZALS = OPC_BGEZAL | 0x5, /* microMIPS */
7a387fff
TS
242 OPC_BGEZALL = (0x13 << 16) | OPC_REGIMM,
243 OPC_TGEI = (0x08 << 16) | OPC_REGIMM,
244 OPC_TGEIU = (0x09 << 16) | OPC_REGIMM,
245 OPC_TLTI = (0x0A << 16) | OPC_REGIMM,
246 OPC_TLTIU = (0x0B << 16) | OPC_REGIMM,
247 OPC_TEQI = (0x0C << 16) | OPC_REGIMM,
248 OPC_TNEI = (0x0E << 16) | OPC_REGIMM,
249 OPC_SYNCI = (0x1F << 16) | OPC_REGIMM,
e37e863f
FB
250};
251
7a387fff
TS
252/* Special2 opcodes */
253#define MASK_SPECIAL2(op) MASK_OP_MAJOR(op) | (op & 0x3F)
254
e37e863f 255enum {
7a387fff
TS
256 /* Multiply & xxx operations */
257 OPC_MADD = 0x00 | OPC_SPECIAL2,
258 OPC_MADDU = 0x01 | OPC_SPECIAL2,
259 OPC_MUL = 0x02 | OPC_SPECIAL2,
260 OPC_MSUB = 0x04 | OPC_SPECIAL2,
261 OPC_MSUBU = 0x05 | OPC_SPECIAL2,
161f85e6
AJ
262 /* Loongson 2F */
263 OPC_MULT_G_2F = 0x10 | OPC_SPECIAL2,
264 OPC_DMULT_G_2F = 0x11 | OPC_SPECIAL2,
265 OPC_MULTU_G_2F = 0x12 | OPC_SPECIAL2,
266 OPC_DMULTU_G_2F = 0x13 | OPC_SPECIAL2,
267 OPC_DIV_G_2F = 0x14 | OPC_SPECIAL2,
268 OPC_DDIV_G_2F = 0x15 | OPC_SPECIAL2,
269 OPC_DIVU_G_2F = 0x16 | OPC_SPECIAL2,
270 OPC_DDIVU_G_2F = 0x17 | OPC_SPECIAL2,
271 OPC_MOD_G_2F = 0x1c | OPC_SPECIAL2,
272 OPC_DMOD_G_2F = 0x1d | OPC_SPECIAL2,
273 OPC_MODU_G_2F = 0x1e | OPC_SPECIAL2,
274 OPC_DMODU_G_2F = 0x1f | OPC_SPECIAL2,
e37e863f 275 /* Misc */
7a387fff
TS
276 OPC_CLZ = 0x20 | OPC_SPECIAL2,
277 OPC_CLO = 0x21 | OPC_SPECIAL2,
278 OPC_DCLZ = 0x24 | OPC_SPECIAL2,
279 OPC_DCLO = 0x25 | OPC_SPECIAL2,
e37e863f 280 /* Special */
7a387fff
TS
281 OPC_SDBBP = 0x3F | OPC_SPECIAL2,
282};
283
284/* Special3 opcodes */
285#define MASK_SPECIAL3(op) MASK_OP_MAJOR(op) | (op & 0x3F)
286
287enum {
288 OPC_EXT = 0x00 | OPC_SPECIAL3,
289 OPC_DEXTM = 0x01 | OPC_SPECIAL3,
290 OPC_DEXTU = 0x02 | OPC_SPECIAL3,
291 OPC_DEXT = 0x03 | OPC_SPECIAL3,
292 OPC_INS = 0x04 | OPC_SPECIAL3,
293 OPC_DINSM = 0x05 | OPC_SPECIAL3,
294 OPC_DINSU = 0x06 | OPC_SPECIAL3,
295 OPC_DINS = 0x07 | OPC_SPECIAL3,
ead9360e
TS
296 OPC_FORK = 0x08 | OPC_SPECIAL3,
297 OPC_YIELD = 0x09 | OPC_SPECIAL3,
7a387fff
TS
298 OPC_BSHFL = 0x20 | OPC_SPECIAL3,
299 OPC_DBSHFL = 0x24 | OPC_SPECIAL3,
300 OPC_RDHWR = 0x3B | OPC_SPECIAL3,
161f85e6
AJ
301
302 /* Loongson 2E */
303 OPC_MULT_G_2E = 0x18 | OPC_SPECIAL3,
304 OPC_MULTU_G_2E = 0x19 | OPC_SPECIAL3,
305 OPC_DIV_G_2E = 0x1A | OPC_SPECIAL3,
306 OPC_DIVU_G_2E = 0x1B | OPC_SPECIAL3,
307 OPC_DMULT_G_2E = 0x1C | OPC_SPECIAL3,
308 OPC_DMULTU_G_2E = 0x1D | OPC_SPECIAL3,
309 OPC_DDIV_G_2E = 0x1E | OPC_SPECIAL3,
310 OPC_DDIVU_G_2E = 0x1F | OPC_SPECIAL3,
311 OPC_MOD_G_2E = 0x22 | OPC_SPECIAL3,
312 OPC_MODU_G_2E = 0x23 | OPC_SPECIAL3,
313 OPC_DMOD_G_2E = 0x26 | OPC_SPECIAL3,
314 OPC_DMODU_G_2E = 0x27 | OPC_SPECIAL3,
e37e863f
FB
315};
316
7a387fff
TS
317/* BSHFL opcodes */
318#define MASK_BSHFL(op) MASK_SPECIAL3(op) | (op & (0x1F << 6))
319
e37e863f 320enum {
7a387fff
TS
321 OPC_WSBH = (0x02 << 6) | OPC_BSHFL,
322 OPC_SEB = (0x10 << 6) | OPC_BSHFL,
323 OPC_SEH = (0x18 << 6) | OPC_BSHFL,
e37e863f
FB
324};
325
7a387fff
TS
326/* DBSHFL opcodes */
327#define MASK_DBSHFL(op) MASK_SPECIAL3(op) | (op & (0x1F << 6))
328
e37e863f 329enum {
7a387fff
TS
330 OPC_DSBH = (0x02 << 6) | OPC_DBSHFL,
331 OPC_DSHD = (0x05 << 6) | OPC_DBSHFL,
e37e863f
FB
332};
333
7a387fff
TS
334/* Coprocessor 0 (rs field) */
335#define MASK_CP0(op) MASK_OP_MAJOR(op) | (op & (0x1F << 21))
336
6ea83fed 337enum {
7a387fff
TS
338 OPC_MFC0 = (0x00 << 21) | OPC_CP0,
339 OPC_DMFC0 = (0x01 << 21) | OPC_CP0,
340 OPC_MTC0 = (0x04 << 21) | OPC_CP0,
341 OPC_DMTC0 = (0x05 << 21) | OPC_CP0,
ead9360e 342 OPC_MFTR = (0x08 << 21) | OPC_CP0,
7a387fff
TS
343 OPC_RDPGPR = (0x0A << 21) | OPC_CP0,
344 OPC_MFMC0 = (0x0B << 21) | OPC_CP0,
ead9360e 345 OPC_MTTR = (0x0C << 21) | OPC_CP0,
7a387fff
TS
346 OPC_WRPGPR = (0x0E << 21) | OPC_CP0,
347 OPC_C0 = (0x10 << 21) | OPC_CP0,
348 OPC_C0_FIRST = (0x10 << 21) | OPC_CP0,
349 OPC_C0_LAST = (0x1F << 21) | OPC_CP0,
6ea83fed 350};
7a387fff
TS
351
352/* MFMC0 opcodes */
b48cfdff 353#define MASK_MFMC0(op) MASK_CP0(op) | (op & 0xFFFF)
7a387fff
TS
354
355enum {
ead9360e
TS
356 OPC_DMT = 0x01 | (0 << 5) | (0x0F << 6) | (0x01 << 11) | OPC_MFMC0,
357 OPC_EMT = 0x01 | (1 << 5) | (0x0F << 6) | (0x01 << 11) | OPC_MFMC0,
358 OPC_DVPE = 0x01 | (0 << 5) | OPC_MFMC0,
359 OPC_EVPE = 0x01 | (1 << 5) | OPC_MFMC0,
7a387fff
TS
360 OPC_DI = (0 << 5) | (0x0C << 11) | OPC_MFMC0,
361 OPC_EI = (1 << 5) | (0x0C << 11) | OPC_MFMC0,
362};
363
364/* Coprocessor 0 (with rs == C0) */
365#define MASK_C0(op) MASK_CP0(op) | (op & 0x3F)
366
367enum {
368 OPC_TLBR = 0x01 | OPC_C0,
369 OPC_TLBWI = 0x02 | OPC_C0,
370 OPC_TLBWR = 0x06 | OPC_C0,
371 OPC_TLBP = 0x08 | OPC_C0,
372 OPC_RFE = 0x10 | OPC_C0,
373 OPC_ERET = 0x18 | OPC_C0,
374 OPC_DERET = 0x1F | OPC_C0,
375 OPC_WAIT = 0x20 | OPC_C0,
376};
377
378/* Coprocessor 1 (rs field) */
379#define MASK_CP1(op) MASK_OP_MAJOR(op) | (op & (0x1F << 21))
380
bf4120ad
NF
381/* Values for the fmt field in FP instructions */
382enum {
383 /* 0 - 15 are reserved */
e459440a
AJ
384 FMT_S = 16, /* single fp */
385 FMT_D = 17, /* double fp */
386 FMT_E = 18, /* extended fp */
387 FMT_Q = 19, /* quad fp */
388 FMT_W = 20, /* 32-bit fixed */
389 FMT_L = 21, /* 64-bit fixed */
390 FMT_PS = 22, /* paired single fp */
bf4120ad
NF
391 /* 23 - 31 are reserved */
392};
393
7a387fff
TS
394enum {
395 OPC_MFC1 = (0x00 << 21) | OPC_CP1,
396 OPC_DMFC1 = (0x01 << 21) | OPC_CP1,
397 OPC_CFC1 = (0x02 << 21) | OPC_CP1,
5a5012ec 398 OPC_MFHC1 = (0x03 << 21) | OPC_CP1,
7a387fff
TS
399 OPC_MTC1 = (0x04 << 21) | OPC_CP1,
400 OPC_DMTC1 = (0x05 << 21) | OPC_CP1,
401 OPC_CTC1 = (0x06 << 21) | OPC_CP1,
5a5012ec 402 OPC_MTHC1 = (0x07 << 21) | OPC_CP1,
7a387fff 403 OPC_BC1 = (0x08 << 21) | OPC_CP1, /* bc */
5a5012ec
TS
404 OPC_BC1ANY2 = (0x09 << 21) | OPC_CP1,
405 OPC_BC1ANY4 = (0x0A << 21) | OPC_CP1,
e459440a
AJ
406 OPC_S_FMT = (FMT_S << 21) | OPC_CP1,
407 OPC_D_FMT = (FMT_D << 21) | OPC_CP1,
408 OPC_E_FMT = (FMT_E << 21) | OPC_CP1,
409 OPC_Q_FMT = (FMT_Q << 21) | OPC_CP1,
410 OPC_W_FMT = (FMT_W << 21) | OPC_CP1,
411 OPC_L_FMT = (FMT_L << 21) | OPC_CP1,
412 OPC_PS_FMT = (FMT_PS << 21) | OPC_CP1,
7a387fff
TS
413};
414
5a5012ec
TS
415#define MASK_CP1_FUNC(op) MASK_CP1(op) | (op & 0x3F)
416#define MASK_BC1(op) MASK_CP1(op) | (op & (0x3 << 16))
417
7a387fff
TS
418enum {
419 OPC_BC1F = (0x00 << 16) | OPC_BC1,
420 OPC_BC1T = (0x01 << 16) | OPC_BC1,
421 OPC_BC1FL = (0x02 << 16) | OPC_BC1,
422 OPC_BC1TL = (0x03 << 16) | OPC_BC1,
423};
424
5a5012ec
TS
425enum {
426 OPC_BC1FANY2 = (0x00 << 16) | OPC_BC1ANY2,
427 OPC_BC1TANY2 = (0x01 << 16) | OPC_BC1ANY2,
428};
429
430enum {
431 OPC_BC1FANY4 = (0x00 << 16) | OPC_BC1ANY4,
432 OPC_BC1TANY4 = (0x01 << 16) | OPC_BC1ANY4,
433};
7a387fff
TS
434
435#define MASK_CP2(op) MASK_OP_MAJOR(op) | (op & (0x1F << 21))
e0c84da7
TS
436
437enum {
438 OPC_MFC2 = (0x00 << 21) | OPC_CP2,
439 OPC_DMFC2 = (0x01 << 21) | OPC_CP2,
440 OPC_CFC2 = (0x02 << 21) | OPC_CP2,
441 OPC_MFHC2 = (0x03 << 21) | OPC_CP2,
442 OPC_MTC2 = (0x04 << 21) | OPC_CP2,
443 OPC_DMTC2 = (0x05 << 21) | OPC_CP2,
444 OPC_CTC2 = (0x06 << 21) | OPC_CP2,
445 OPC_MTHC2 = (0x07 << 21) | OPC_CP2,
446 OPC_BC2 = (0x08 << 21) | OPC_CP2,
447};
448
bd277fa1
RH
449#define MASK_LMI(op) (MASK_OP_MAJOR(op) | (op & (0x1F << 21)) | (op & 0x1F))
450
451enum {
452 OPC_PADDSH = (24 << 21) | (0x00) | OPC_CP2,
453 OPC_PADDUSH = (25 << 21) | (0x00) | OPC_CP2,
454 OPC_PADDH = (26 << 21) | (0x00) | OPC_CP2,
455 OPC_PADDW = (27 << 21) | (0x00) | OPC_CP2,
456 OPC_PADDSB = (28 << 21) | (0x00) | OPC_CP2,
457 OPC_PADDUSB = (29 << 21) | (0x00) | OPC_CP2,
458 OPC_PADDB = (30 << 21) | (0x00) | OPC_CP2,
459 OPC_PADDD = (31 << 21) | (0x00) | OPC_CP2,
460
461 OPC_PSUBSH = (24 << 21) | (0x01) | OPC_CP2,
462 OPC_PSUBUSH = (25 << 21) | (0x01) | OPC_CP2,
463 OPC_PSUBH = (26 << 21) | (0x01) | OPC_CP2,
464 OPC_PSUBW = (27 << 21) | (0x01) | OPC_CP2,
465 OPC_PSUBSB = (28 << 21) | (0x01) | OPC_CP2,
466 OPC_PSUBUSB = (29 << 21) | (0x01) | OPC_CP2,
467 OPC_PSUBB = (30 << 21) | (0x01) | OPC_CP2,
468 OPC_PSUBD = (31 << 21) | (0x01) | OPC_CP2,
469
470 OPC_PSHUFH = (24 << 21) | (0x02) | OPC_CP2,
471 OPC_PACKSSWH = (25 << 21) | (0x02) | OPC_CP2,
472 OPC_PACKSSHB = (26 << 21) | (0x02) | OPC_CP2,
473 OPC_PACKUSHB = (27 << 21) | (0x02) | OPC_CP2,
474 OPC_XOR_CP2 = (28 << 21) | (0x02) | OPC_CP2,
475 OPC_NOR_CP2 = (29 << 21) | (0x02) | OPC_CP2,
476 OPC_AND_CP2 = (30 << 21) | (0x02) | OPC_CP2,
477 OPC_PANDN = (31 << 21) | (0x02) | OPC_CP2,
478
479 OPC_PUNPCKLHW = (24 << 21) | (0x03) | OPC_CP2,
480 OPC_PUNPCKHHW = (25 << 21) | (0x03) | OPC_CP2,
481 OPC_PUNPCKLBH = (26 << 21) | (0x03) | OPC_CP2,
482 OPC_PUNPCKHBH = (27 << 21) | (0x03) | OPC_CP2,
483 OPC_PINSRH_0 = (28 << 21) | (0x03) | OPC_CP2,
484 OPC_PINSRH_1 = (29 << 21) | (0x03) | OPC_CP2,
485 OPC_PINSRH_2 = (30 << 21) | (0x03) | OPC_CP2,
486 OPC_PINSRH_3 = (31 << 21) | (0x03) | OPC_CP2,
487
488 OPC_PAVGH = (24 << 21) | (0x08) | OPC_CP2,
489 OPC_PAVGB = (25 << 21) | (0x08) | OPC_CP2,
490 OPC_PMAXSH = (26 << 21) | (0x08) | OPC_CP2,
491 OPC_PMINSH = (27 << 21) | (0x08) | OPC_CP2,
492 OPC_PMAXUB = (28 << 21) | (0x08) | OPC_CP2,
493 OPC_PMINUB = (29 << 21) | (0x08) | OPC_CP2,
494
495 OPC_PCMPEQW = (24 << 21) | (0x09) | OPC_CP2,
496 OPC_PCMPGTW = (25 << 21) | (0x09) | OPC_CP2,
497 OPC_PCMPEQH = (26 << 21) | (0x09) | OPC_CP2,
498 OPC_PCMPGTH = (27 << 21) | (0x09) | OPC_CP2,
499 OPC_PCMPEQB = (28 << 21) | (0x09) | OPC_CP2,
500 OPC_PCMPGTB = (29 << 21) | (0x09) | OPC_CP2,
501
502 OPC_PSLLW = (24 << 21) | (0x0A) | OPC_CP2,
503 OPC_PSLLH = (25 << 21) | (0x0A) | OPC_CP2,
504 OPC_PMULLH = (26 << 21) | (0x0A) | OPC_CP2,
505 OPC_PMULHH = (27 << 21) | (0x0A) | OPC_CP2,
506 OPC_PMULUW = (28 << 21) | (0x0A) | OPC_CP2,
507 OPC_PMULHUH = (29 << 21) | (0x0A) | OPC_CP2,
508
509 OPC_PSRLW = (24 << 21) | (0x0B) | OPC_CP2,
510 OPC_PSRLH = (25 << 21) | (0x0B) | OPC_CP2,
511 OPC_PSRAW = (26 << 21) | (0x0B) | OPC_CP2,
512 OPC_PSRAH = (27 << 21) | (0x0B) | OPC_CP2,
513 OPC_PUNPCKLWD = (28 << 21) | (0x0B) | OPC_CP2,
514 OPC_PUNPCKHWD = (29 << 21) | (0x0B) | OPC_CP2,
515
516 OPC_ADDU_CP2 = (24 << 21) | (0x0C) | OPC_CP2,
517 OPC_OR_CP2 = (25 << 21) | (0x0C) | OPC_CP2,
518 OPC_ADD_CP2 = (26 << 21) | (0x0C) | OPC_CP2,
519 OPC_DADD_CP2 = (27 << 21) | (0x0C) | OPC_CP2,
520 OPC_SEQU_CP2 = (28 << 21) | (0x0C) | OPC_CP2,
521 OPC_SEQ_CP2 = (29 << 21) | (0x0C) | OPC_CP2,
522
523 OPC_SUBU_CP2 = (24 << 21) | (0x0D) | OPC_CP2,
524 OPC_PASUBUB = (25 << 21) | (0x0D) | OPC_CP2,
525 OPC_SUB_CP2 = (26 << 21) | (0x0D) | OPC_CP2,
526 OPC_DSUB_CP2 = (27 << 21) | (0x0D) | OPC_CP2,
527 OPC_SLTU_CP2 = (28 << 21) | (0x0D) | OPC_CP2,
528 OPC_SLT_CP2 = (29 << 21) | (0x0D) | OPC_CP2,
529
530 OPC_SLL_CP2 = (24 << 21) | (0x0E) | OPC_CP2,
531 OPC_DSLL_CP2 = (25 << 21) | (0x0E) | OPC_CP2,
532 OPC_PEXTRH = (26 << 21) | (0x0E) | OPC_CP2,
533 OPC_PMADDHW = (27 << 21) | (0x0E) | OPC_CP2,
534 OPC_SLEU_CP2 = (28 << 21) | (0x0E) | OPC_CP2,
535 OPC_SLE_CP2 = (29 << 21) | (0x0E) | OPC_CP2,
536
537 OPC_SRL_CP2 = (24 << 21) | (0x0F) | OPC_CP2,
538 OPC_DSRL_CP2 = (25 << 21) | (0x0F) | OPC_CP2,
539 OPC_SRA_CP2 = (26 << 21) | (0x0F) | OPC_CP2,
540 OPC_DSRA_CP2 = (27 << 21) | (0x0F) | OPC_CP2,
541 OPC_BIADD = (28 << 21) | (0x0F) | OPC_CP2,
542 OPC_PMOVMSKB = (29 << 21) | (0x0F) | OPC_CP2,
543};
544
545
e0c84da7
TS
546#define MASK_CP3(op) MASK_OP_MAJOR(op) | (op & 0x3F)
547
548enum {
549 OPC_LWXC1 = 0x00 | OPC_CP3,
550 OPC_LDXC1 = 0x01 | OPC_CP3,
551 OPC_LUXC1 = 0x05 | OPC_CP3,
552 OPC_SWXC1 = 0x08 | OPC_CP3,
553 OPC_SDXC1 = 0x09 | OPC_CP3,
554 OPC_SUXC1 = 0x0D | OPC_CP3,
555 OPC_PREFX = 0x0F | OPC_CP3,
556 OPC_ALNV_PS = 0x1E | OPC_CP3,
557 OPC_MADD_S = 0x20 | OPC_CP3,
558 OPC_MADD_D = 0x21 | OPC_CP3,
559 OPC_MADD_PS = 0x26 | OPC_CP3,
560 OPC_MSUB_S = 0x28 | OPC_CP3,
561 OPC_MSUB_D = 0x29 | OPC_CP3,
562 OPC_MSUB_PS = 0x2E | OPC_CP3,
563 OPC_NMADD_S = 0x30 | OPC_CP3,
fbcc6828 564 OPC_NMADD_D = 0x31 | OPC_CP3,
e0c84da7
TS
565 OPC_NMADD_PS= 0x36 | OPC_CP3,
566 OPC_NMSUB_S = 0x38 | OPC_CP3,
567 OPC_NMSUB_D = 0x39 | OPC_CP3,
568 OPC_NMSUB_PS= 0x3E | OPC_CP3,
569};
570
39454628 571/* global register indices */
a7812ae4
PB
572static TCGv_ptr cpu_env;
573static TCGv cpu_gpr[32], cpu_PC;
4b2eb8d2 574static TCGv cpu_HI[MIPS_DSP_ACC], cpu_LO[MIPS_DSP_ACC], cpu_ACX[MIPS_DSP_ACC];
41db4607
AJ
575static TCGv cpu_dspctrl, btarget, bcond;
576static TCGv_i32 hflags;
a7812ae4 577static TCGv_i32 fpu_fcr0, fpu_fcr31;
aa0bf00b 578
1a7ff922
PB
579static uint32_t gen_opc_hflags[OPC_BUF_SIZE];
580
2e70f6ef
PB
581#include "gen-icount.h"
582
895c2d04 583#define gen_helper_0e0i(name, arg) do { \
a7812ae4 584 TCGv_i32 helper_tmp = tcg_const_i32(arg); \
895c2d04 585 gen_helper_##name(cpu_env, helper_tmp); \
a7812ae4
PB
586 tcg_temp_free_i32(helper_tmp); \
587 } while(0)
be24bb4f 588
895c2d04 589#define gen_helper_0e1i(name, arg1, arg2) do { \
a7812ae4 590 TCGv_i32 helper_tmp = tcg_const_i32(arg2); \
895c2d04 591 gen_helper_##name(cpu_env, arg1, helper_tmp); \
a7812ae4
PB
592 tcg_temp_free_i32(helper_tmp); \
593 } while(0)
be24bb4f 594
895c2d04
BS
595#define gen_helper_1e0i(name, ret, arg1) do { \
596 TCGv_i32 helper_tmp = tcg_const_i32(arg1); \
597 gen_helper_##name(ret, cpu_env, helper_tmp); \
598 tcg_temp_free_i32(helper_tmp); \
599 } while(0)
600
601#define gen_helper_1e1i(name, ret, arg1, arg2) do { \
602 TCGv_i32 helper_tmp = tcg_const_i32(arg2); \
603 gen_helper_##name(ret, cpu_env, arg1, helper_tmp); \
604 tcg_temp_free_i32(helper_tmp); \
605 } while(0)
606
607#define gen_helper_0e2i(name, arg1, arg2, arg3) do { \
608 TCGv_i32 helper_tmp = tcg_const_i32(arg3); \
609 gen_helper_##name(cpu_env, arg1, arg2, helper_tmp); \
610 tcg_temp_free_i32(helper_tmp); \
611 } while(0)
612
613#define gen_helper_1e2i(name, ret, arg1, arg2, arg3) do { \
a7812ae4 614 TCGv_i32 helper_tmp = tcg_const_i32(arg3); \
895c2d04 615 gen_helper_##name(ret, cpu_env, arg1, arg2, helper_tmp); \
a7812ae4
PB
616 tcg_temp_free_i32(helper_tmp); \
617 } while(0)
be24bb4f 618
895c2d04 619#define gen_helper_0e3i(name, arg1, arg2, arg3, arg4) do { \
a7812ae4 620 TCGv_i32 helper_tmp = tcg_const_i32(arg4); \
895c2d04 621 gen_helper_##name(cpu_env, arg1, arg2, arg3, helper_tmp); \
a7812ae4
PB
622 tcg_temp_free_i32(helper_tmp); \
623 } while(0)
c239529e 624
8e9ade68
TS
625typedef struct DisasContext {
626 struct TranslationBlock *tb;
627 target_ulong pc, saved_pc;
628 uint32_t opcode;
7b270ef2 629 int singlestep_enabled;
8e9ade68
TS
630 /* Routine used to access memory */
631 int mem_idx;
632 uint32_t hflags, saved_hflags;
633 int bstate;
634 target_ulong btarget;
635} DisasContext;
636
637enum {
638 BS_NONE = 0, /* We go out of the TB without reaching a branch or an
d077b6f7 639 * exception condition */
8e9ade68
TS
640 BS_STOP = 1, /* We want to stop translation for any reason */
641 BS_BRANCH = 2, /* We reached a branch condition */
642 BS_EXCP = 3, /* We reached an exception condition */
643};
644
645static const char *regnames[] =
6af0bf9c
FB
646 { "r0", "at", "v0", "v1", "a0", "a1", "a2", "a3",
647 "t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7",
648 "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7",
649 "t8", "t9", "k0", "k1", "gp", "sp", "s8", "ra", };
650
4b2eb8d2
TS
651static const char *regnames_HI[] =
652 { "HI0", "HI1", "HI2", "HI3", };
653
654static const char *regnames_LO[] =
655 { "LO0", "LO1", "LO2", "LO3", };
656
657static const char *regnames_ACX[] =
658 { "ACX0", "ACX1", "ACX2", "ACX3", };
659
8e9ade68
TS
660static const char *fregnames[] =
661 { "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7",
662 "f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15",
663 "f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23",
664 "f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31", };
958fb4a9 665
fb7729e2
RH
666#define MIPS_DEBUG(fmt, ...) \
667 do { \
668 if (MIPS_DEBUG_DISAS) { \
669 qemu_log_mask(CPU_LOG_TB_IN_ASM, \
670 TARGET_FMT_lx ": %08x " fmt "\n", \
671 ctx->pc, ctx->opcode , ## __VA_ARGS__); \
672 } \
673 } while (0)
674
675#define LOG_DISAS(...) \
676 do { \
677 if (MIPS_DEBUG_DISAS) { \
678 qemu_log_mask(CPU_LOG_TB_IN_ASM, ## __VA_ARGS__); \
679 } \
680 } while (0)
958fb4a9 681
8e9ade68 682#define MIPS_INVAL(op) \
8e9ade68 683 MIPS_DEBUG("Invalid %s %03x %03x %03x", op, ctx->opcode >> 26, \
fb7729e2 684 ctx->opcode & 0x3F, ((ctx->opcode >> 16) & 0x1F))
ead9360e 685
8e9ade68
TS
686/* General purpose registers moves. */
687static inline void gen_load_gpr (TCGv t, int reg)
aaa9128a 688{
8e9ade68
TS
689 if (reg == 0)
690 tcg_gen_movi_tl(t, 0);
691 else
4b2eb8d2 692 tcg_gen_mov_tl(t, cpu_gpr[reg]);
aaa9128a
TS
693}
694
8e9ade68 695static inline void gen_store_gpr (TCGv t, int reg)
aaa9128a 696{
8e9ade68 697 if (reg != 0)
4b2eb8d2 698 tcg_gen_mov_tl(cpu_gpr[reg], t);
aaa9128a
TS
699}
700
b10fa3c9 701/* Moves to/from ACX register. */
4b2eb8d2 702static inline void gen_load_ACX (TCGv t, int reg)
893f9865 703{
4b2eb8d2 704 tcg_gen_mov_tl(t, cpu_ACX[reg]);
893f9865
TS
705}
706
4b2eb8d2 707static inline void gen_store_ACX (TCGv t, int reg)
893f9865 708{
4b2eb8d2 709 tcg_gen_mov_tl(cpu_ACX[reg], t);
893f9865
TS
710}
711
8e9ade68 712/* Moves to/from shadow registers. */
be24bb4f 713static inline void gen_load_srsgpr (int from, int to)
aaa9128a 714{
d9bea114 715 TCGv t0 = tcg_temp_new();
be24bb4f
TS
716
717 if (from == 0)
d9bea114 718 tcg_gen_movi_tl(t0, 0);
8e9ade68 719 else {
d9bea114 720 TCGv_i32 t2 = tcg_temp_new_i32();
a7812ae4 721 TCGv_ptr addr = tcg_temp_new_ptr();
aaa9128a 722
7db13fae 723 tcg_gen_ld_i32(t2, cpu_env, offsetof(CPUMIPSState, CP0_SRSCtl));
d9bea114
AJ
724 tcg_gen_shri_i32(t2, t2, CP0SRSCtl_PSS);
725 tcg_gen_andi_i32(t2, t2, 0xf);
726 tcg_gen_muli_i32(t2, t2, sizeof(target_ulong) * 32);
727 tcg_gen_ext_i32_ptr(addr, t2);
a7812ae4 728 tcg_gen_add_ptr(addr, cpu_env, addr);
aaa9128a 729
d9bea114 730 tcg_gen_ld_tl(t0, addr, sizeof(target_ulong) * from);
a7812ae4 731 tcg_temp_free_ptr(addr);
d9bea114 732 tcg_temp_free_i32(t2);
8e9ade68 733 }
d9bea114
AJ
734 gen_store_gpr(t0, to);
735 tcg_temp_free(t0);
aaa9128a
TS
736}
737
be24bb4f 738static inline void gen_store_srsgpr (int from, int to)
aaa9128a 739{
be24bb4f 740 if (to != 0) {
d9bea114
AJ
741 TCGv t0 = tcg_temp_new();
742 TCGv_i32 t2 = tcg_temp_new_i32();
a7812ae4 743 TCGv_ptr addr = tcg_temp_new_ptr();
be24bb4f 744
d9bea114 745 gen_load_gpr(t0, from);
7db13fae 746 tcg_gen_ld_i32(t2, cpu_env, offsetof(CPUMIPSState, CP0_SRSCtl));
d9bea114
AJ
747 tcg_gen_shri_i32(t2, t2, CP0SRSCtl_PSS);
748 tcg_gen_andi_i32(t2, t2, 0xf);
749 tcg_gen_muli_i32(t2, t2, sizeof(target_ulong) * 32);
750 tcg_gen_ext_i32_ptr(addr, t2);
a7812ae4 751 tcg_gen_add_ptr(addr, cpu_env, addr);
be24bb4f 752
d9bea114 753 tcg_gen_st_tl(t0, addr, sizeof(target_ulong) * to);
a7812ae4 754 tcg_temp_free_ptr(addr);
d9bea114
AJ
755 tcg_temp_free_i32(t2);
756 tcg_temp_free(t0);
8e9ade68 757 }
aaa9128a
TS
758}
759
aaa9128a 760/* Floating point register moves. */
a7812ae4 761static inline void gen_load_fpr32 (TCGv_i32 t, int reg)
aa0bf00b 762{
7db13fae 763 tcg_gen_ld_i32(t, cpu_env, offsetof(CPUMIPSState, active_fpu.fpr[reg].w[FP_ENDIAN_IDX]));
6ea83fed
FB
764}
765
a7812ae4 766static inline void gen_store_fpr32 (TCGv_i32 t, int reg)
aa0bf00b 767{
7db13fae 768 tcg_gen_st_i32(t, cpu_env, offsetof(CPUMIPSState, active_fpu.fpr[reg].w[FP_ENDIAN_IDX]));
6d066274
AJ
769}
770
771static inline void gen_load_fpr32h (TCGv_i32 t, int reg)
772{
7db13fae 773 tcg_gen_ld_i32(t, cpu_env, offsetof(CPUMIPSState, active_fpu.fpr[reg].w[!FP_ENDIAN_IDX]));
6d066274
AJ
774}
775
776static inline void gen_store_fpr32h (TCGv_i32 t, int reg)
777{
7db13fae 778 tcg_gen_st_i32(t, cpu_env, offsetof(CPUMIPSState, active_fpu.fpr[reg].w[!FP_ENDIAN_IDX]));
aa0bf00b 779}
6ea83fed 780
a7812ae4 781static inline void gen_load_fpr64 (DisasContext *ctx, TCGv_i64 t, int reg)
aa0bf00b 782{
f364515c 783 if (ctx->hflags & MIPS_HFLAG_F64) {
7db13fae 784 tcg_gen_ld_i64(t, cpu_env, offsetof(CPUMIPSState, active_fpu.fpr[reg].d));
f364515c 785 } else {
6d066274
AJ
786 TCGv_i32 t0 = tcg_temp_new_i32();
787 TCGv_i32 t1 = tcg_temp_new_i32();
788 gen_load_fpr32(t0, reg & ~1);
789 gen_load_fpr32(t1, reg | 1);
790 tcg_gen_concat_i32_i64(t, t0, t1);
791 tcg_temp_free_i32(t0);
792 tcg_temp_free_i32(t1);
aa0bf00b
TS
793 }
794}
6ea83fed 795
a7812ae4 796static inline void gen_store_fpr64 (DisasContext *ctx, TCGv_i64 t, int reg)
aa0bf00b 797{
f364515c 798 if (ctx->hflags & MIPS_HFLAG_F64) {
7db13fae 799 tcg_gen_st_i64(t, cpu_env, offsetof(CPUMIPSState, active_fpu.fpr[reg].d));
f364515c 800 } else {
6d066274
AJ
801 TCGv_i64 t0 = tcg_temp_new_i64();
802 TCGv_i32 t1 = tcg_temp_new_i32();
803 tcg_gen_trunc_i64_i32(t1, t);
804 gen_store_fpr32(t1, reg & ~1);
805 tcg_gen_shri_i64(t0, t, 32);
806 tcg_gen_trunc_i64_i32(t1, t0);
807 gen_store_fpr32(t1, reg | 1);
808 tcg_temp_free_i32(t1);
809 tcg_temp_free_i64(t0);
aa0bf00b
TS
810 }
811}
6ea83fed 812
d94536f4 813static inline int get_fp_bit (int cc)
a16336e4 814{
d94536f4
AJ
815 if (cc)
816 return 24 + cc;
817 else
818 return 23;
a16336e4
TS
819}
820
30898801 821/* Tests */
8e9ade68
TS
822static inline void gen_save_pc(target_ulong pc)
823{
1eb75d4a 824 tcg_gen_movi_tl(cpu_PC, pc);
8e9ade68 825}
30898801 826
356265ae 827static inline void save_cpu_state (DisasContext *ctx, int do_save_pc)
6af0bf9c 828{
d12d51d5 829 LOG_DISAS("hflags %08x saved %08x\n", ctx->hflags, ctx->saved_hflags);
6af0bf9c 830 if (do_save_pc && ctx->pc != ctx->saved_pc) {
9b9e4393 831 gen_save_pc(ctx->pc);
6af0bf9c
FB
832 ctx->saved_pc = ctx->pc;
833 }
834 if (ctx->hflags != ctx->saved_hflags) {
41db4607 835 tcg_gen_movi_i32(hflags, ctx->hflags);
6af0bf9c 836 ctx->saved_hflags = ctx->hflags;
364d4831 837 switch (ctx->hflags & MIPS_HFLAG_BMASK_BASE) {
5a5012ec 838 case MIPS_HFLAG_BR:
5a5012ec
TS
839 break;
840 case MIPS_HFLAG_BC:
5a5012ec 841 case MIPS_HFLAG_BL:
5a5012ec 842 case MIPS_HFLAG_B:
d077b6f7 843 tcg_gen_movi_tl(btarget, ctx->btarget);
5a5012ec 844 break;
6af0bf9c
FB
845 }
846 }
847}
848
7db13fae 849static inline void restore_cpu_state (CPUMIPSState *env, DisasContext *ctx)
5a5012ec 850{
fd4a04eb 851 ctx->saved_hflags = ctx->hflags;
364d4831 852 switch (ctx->hflags & MIPS_HFLAG_BMASK_BASE) {
fd4a04eb 853 case MIPS_HFLAG_BR:
fd4a04eb
TS
854 break;
855 case MIPS_HFLAG_BC:
856 case MIPS_HFLAG_BL:
39454628 857 case MIPS_HFLAG_B:
fd4a04eb 858 ctx->btarget = env->btarget;
fd4a04eb 859 break;
5a5012ec
TS
860 }
861}
862
356265ae 863static inline void
48d38ca5 864generate_exception_err (DisasContext *ctx, int excp, int err)
aaa9128a 865{
a7812ae4
PB
866 TCGv_i32 texcp = tcg_const_i32(excp);
867 TCGv_i32 terr = tcg_const_i32(err);
aaa9128a 868 save_cpu_state(ctx, 1);
895c2d04 869 gen_helper_raise_exception_err(cpu_env, texcp, terr);
a7812ae4
PB
870 tcg_temp_free_i32(terr);
871 tcg_temp_free_i32(texcp);
aaa9128a
TS
872}
873
356265ae 874static inline void
48d38ca5 875generate_exception (DisasContext *ctx, int excp)
aaa9128a 876{
6af0bf9c 877 save_cpu_state(ctx, 1);
895c2d04 878 gen_helper_0e0i(raise_exception, excp);
6af0bf9c
FB
879}
880
48d38ca5 881/* Addresses computation */
941694d0 882static inline void gen_op_addr_add (DisasContext *ctx, TCGv ret, TCGv arg0, TCGv arg1)
4ad40f36 883{
941694d0 884 tcg_gen_add_tl(ret, arg0, arg1);
48d38ca5
TS
885
886#if defined(TARGET_MIPS64)
887 /* For compatibility with 32-bit code, data reference in user mode
888 with Status_UX = 0 should be casted to 32-bit and sign extended.
889 See the MIPS64 PRA manual, section 4.10. */
2623c1ec
AJ
890 if (((ctx->hflags & MIPS_HFLAG_KSU) == MIPS_HFLAG_UM) &&
891 !(ctx->hflags & MIPS_HFLAG_UX)) {
941694d0 892 tcg_gen_ext32s_i64(ret, ret);
48d38ca5
TS
893 }
894#endif
4ad40f36
FB
895}
896
356265ae 897static inline void check_cp0_enabled(DisasContext *ctx)
387a8fe5 898{
fe253235 899 if (unlikely(!(ctx->hflags & MIPS_HFLAG_CP0)))
c2c65dab 900 generate_exception_err(ctx, EXCP_CpU, 0);
387a8fe5
TS
901}
902
356265ae 903static inline void check_cp1_enabled(DisasContext *ctx)
5e755519 904{
fe253235 905 if (unlikely(!(ctx->hflags & MIPS_HFLAG_FPU)))
5e755519
TS
906 generate_exception_err(ctx, EXCP_CpU, 1);
907}
908
b8aa4598
TS
909/* Verify that the processor is running with COP1X instructions enabled.
910 This is associated with the nabla symbol in the MIPS32 and MIPS64
911 opcode tables. */
912
356265ae 913static inline void check_cop1x(DisasContext *ctx)
b8aa4598
TS
914{
915 if (unlikely(!(ctx->hflags & MIPS_HFLAG_COP1X)))
916 generate_exception(ctx, EXCP_RI);
917}
918
919/* Verify that the processor is running with 64-bit floating-point
920 operations enabled. */
921
356265ae 922static inline void check_cp1_64bitmode(DisasContext *ctx)
5e755519 923{
b8aa4598 924 if (unlikely(~ctx->hflags & (MIPS_HFLAG_F64 | MIPS_HFLAG_COP1X)))
5e755519
TS
925 generate_exception(ctx, EXCP_RI);
926}
927
928/*
929 * Verify if floating point register is valid; an operation is not defined
930 * if bit 0 of any register specification is set and the FR bit in the
931 * Status register equals zero, since the register numbers specify an
932 * even-odd pair of adjacent coprocessor general registers. When the FR bit
933 * in the Status register equals one, both even and odd register numbers
934 * are valid. This limitation exists only for 64 bit wide (d,l,ps) registers.
935 *
936 * Multiple 64 bit wide registers can be checked by calling
937 * gen_op_cp1_registers(freg1 | freg2 | ... | fregN);
938 */
356265ae 939static inline void check_cp1_registers(DisasContext *ctx, int regs)
5e755519 940{
fe253235 941 if (unlikely(!(ctx->hflags & MIPS_HFLAG_F64) && (regs & 1)))
5e755519
TS
942 generate_exception(ctx, EXCP_RI);
943}
944
3a95e3a7 945/* This code generates a "reserved instruction" exception if the
e189e748 946 CPU does not support the instruction set corresponding to flags. */
7db13fae 947static inline void check_insn(CPUMIPSState *env, DisasContext *ctx, int flags)
3a95e3a7 948{
e189e748 949 if (unlikely(!(env->insn_flags & flags)))
3a95e3a7
TS
950 generate_exception(ctx, EXCP_RI);
951}
952
e189e748
TS
953/* This code generates a "reserved instruction" exception if 64-bit
954 instructions are not enabled. */
356265ae 955static inline void check_mips_64(DisasContext *ctx)
e189e748 956{
fe253235 957 if (unlikely(!(ctx->hflags & MIPS_HFLAG_64)))
e189e748
TS
958 generate_exception(ctx, EXCP_RI);
959}
960
8153667c
NF
961/* Define small wrappers for gen_load_fpr* so that we have a uniform
962 calling interface for 32 and 64-bit FPRs. No sense in changing
963 all callers for gen_load_fpr32 when we need the CTX parameter for
964 this one use. */
965#define gen_ldcmp_fpr32(ctx, x, y) gen_load_fpr32(x, y)
966#define gen_ldcmp_fpr64(ctx, x, y) gen_load_fpr64(ctx, x, y)
967#define FOP_CONDS(type, abs, fmt, ifmt, bits) \
968static inline void gen_cmp ## type ## _ ## fmt(DisasContext *ctx, int n, \
969 int ft, int fs, int cc) \
970{ \
971 TCGv_i##bits fp0 = tcg_temp_new_i##bits (); \
972 TCGv_i##bits fp1 = tcg_temp_new_i##bits (); \
973 switch (ifmt) { \
974 case FMT_PS: \
975 check_cp1_64bitmode(ctx); \
976 break; \
977 case FMT_D: \
978 if (abs) { \
979 check_cop1x(ctx); \
980 } \
981 check_cp1_registers(ctx, fs | ft); \
982 break; \
983 case FMT_S: \
984 if (abs) { \
985 check_cop1x(ctx); \
986 } \
987 break; \
988 } \
989 gen_ldcmp_fpr##bits (ctx, fp0, fs); \
990 gen_ldcmp_fpr##bits (ctx, fp1, ft); \
991 switch (n) { \
895c2d04
BS
992 case 0: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _f, fp0, fp1, cc); break;\
993 case 1: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _un, fp0, fp1, cc); break;\
994 case 2: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _eq, fp0, fp1, cc); break;\
995 case 3: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ueq, fp0, fp1, cc); break;\
996 case 4: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _olt, fp0, fp1, cc); break;\
997 case 5: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ult, fp0, fp1, cc); break;\
998 case 6: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ole, fp0, fp1, cc); break;\
999 case 7: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ule, fp0, fp1, cc); break;\
1000 case 8: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _sf, fp0, fp1, cc); break;\
1001 case 9: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ngle, fp0, fp1, cc); break;\
1002 case 10: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _seq, fp0, fp1, cc); break;\
1003 case 11: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ngl, fp0, fp1, cc); break;\
1004 case 12: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _lt, fp0, fp1, cc); break;\
1005 case 13: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _nge, fp0, fp1, cc); break;\
1006 case 14: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _le, fp0, fp1, cc); break;\
1007 case 15: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ngt, fp0, fp1, cc); break;\
8153667c
NF
1008 default: abort(); \
1009 } \
1010 tcg_temp_free_i##bits (fp0); \
1011 tcg_temp_free_i##bits (fp1); \
1012}
1013
1014FOP_CONDS(, 0, d, FMT_D, 64)
1015FOP_CONDS(abs, 1, d, FMT_D, 64)
1016FOP_CONDS(, 0, s, FMT_S, 32)
1017FOP_CONDS(abs, 1, s, FMT_S, 32)
1018FOP_CONDS(, 0, ps, FMT_PS, 64)
1019FOP_CONDS(abs, 1, ps, FMT_PS, 64)
1020#undef FOP_CONDS
1021#undef gen_ldcmp_fpr32
1022#undef gen_ldcmp_fpr64
1023
958fb4a9 1024/* load/store instructions. */
d9bea114 1025#define OP_LD(insn,fname) \
5c13fdfd 1026static inline void op_ld_##insn(TCGv ret, TCGv arg1, DisasContext *ctx) \
d9bea114
AJ
1027{ \
1028 tcg_gen_qemu_##fname(ret, arg1, ctx->mem_idx); \
aaa9128a
TS
1029}
1030OP_LD(lb,ld8s);
1031OP_LD(lbu,ld8u);
1032OP_LD(lh,ld16s);
1033OP_LD(lhu,ld16u);
1034OP_LD(lw,ld32s);
1035#if defined(TARGET_MIPS64)
1036OP_LD(lwu,ld32u);
1037OP_LD(ld,ld64);
1038#endif
1039#undef OP_LD
1040
d9bea114 1041#define OP_ST(insn,fname) \
5c13fdfd 1042static inline void op_st_##insn(TCGv arg1, TCGv arg2, DisasContext *ctx) \
d9bea114
AJ
1043{ \
1044 tcg_gen_qemu_##fname(arg1, arg2, ctx->mem_idx); \
aaa9128a
TS
1045}
1046OP_ST(sb,st8);
1047OP_ST(sh,st16);
1048OP_ST(sw,st32);
1049#if defined(TARGET_MIPS64)
1050OP_ST(sd,st64);
1051#endif
1052#undef OP_ST
1053
e7139c44 1054#ifdef CONFIG_USER_ONLY
d9bea114 1055#define OP_LD_ATOMIC(insn,fname) \
5c13fdfd 1056static inline void op_ld_##insn(TCGv ret, TCGv arg1, DisasContext *ctx) \
d9bea114
AJ
1057{ \
1058 TCGv t0 = tcg_temp_new(); \
1059 tcg_gen_mov_tl(t0, arg1); \
1060 tcg_gen_qemu_##fname(ret, arg1, ctx->mem_idx); \
7db13fae
AF
1061 tcg_gen_st_tl(t0, cpu_env, offsetof(CPUMIPSState, lladdr)); \
1062 tcg_gen_st_tl(ret, cpu_env, offsetof(CPUMIPSState, llval)); \
d9bea114 1063 tcg_temp_free(t0); \
aaa9128a 1064}
e7139c44
AJ
1065#else
1066#define OP_LD_ATOMIC(insn,fname) \
5c13fdfd 1067static inline void op_ld_##insn(TCGv ret, TCGv arg1, DisasContext *ctx) \
e7139c44 1068{ \
895c2d04 1069 gen_helper_1e1i(insn, ret, arg1, ctx->mem_idx); \
e7139c44
AJ
1070}
1071#endif
aaa9128a
TS
1072OP_LD_ATOMIC(ll,ld32s);
1073#if defined(TARGET_MIPS64)
1074OP_LD_ATOMIC(lld,ld64);
1075#endif
1076#undef OP_LD_ATOMIC
1077
590bc601
PB
1078#ifdef CONFIG_USER_ONLY
1079#define OP_ST_ATOMIC(insn,fname,ldname,almask) \
5c13fdfd 1080static inline void op_st_##insn(TCGv arg1, TCGv arg2, int rt, DisasContext *ctx) \
590bc601
PB
1081{ \
1082 TCGv t0 = tcg_temp_new(); \
1083 int l1 = gen_new_label(); \
1084 int l2 = gen_new_label(); \
1085 \
1086 tcg_gen_andi_tl(t0, arg2, almask); \
1087 tcg_gen_brcondi_tl(TCG_COND_EQ, t0, 0, l1); \
7db13fae 1088 tcg_gen_st_tl(arg2, cpu_env, offsetof(CPUMIPSState, CP0_BadVAddr)); \
590bc601
PB
1089 generate_exception(ctx, EXCP_AdES); \
1090 gen_set_label(l1); \
7db13fae 1091 tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUMIPSState, lladdr)); \
590bc601
PB
1092 tcg_gen_brcond_tl(TCG_COND_NE, arg2, t0, l2); \
1093 tcg_gen_movi_tl(t0, rt | ((almask << 3) & 0x20)); \
7db13fae
AF
1094 tcg_gen_st_tl(t0, cpu_env, offsetof(CPUMIPSState, llreg)); \
1095 tcg_gen_st_tl(arg1, cpu_env, offsetof(CPUMIPSState, llnewval)); \
895c2d04 1096 gen_helper_0e0i(raise_exception, EXCP_SC); \
590bc601
PB
1097 gen_set_label(l2); \
1098 tcg_gen_movi_tl(t0, 0); \
1099 gen_store_gpr(t0, rt); \
1100 tcg_temp_free(t0); \
1101}
1102#else
1103#define OP_ST_ATOMIC(insn,fname,ldname,almask) \
5c13fdfd 1104static inline void op_st_##insn(TCGv arg1, TCGv arg2, int rt, DisasContext *ctx) \
590bc601
PB
1105{ \
1106 TCGv t0 = tcg_temp_new(); \
895c2d04 1107 gen_helper_1e2i(insn, t0, arg1, arg2, ctx->mem_idx); \
590bc601 1108 gen_store_gpr(t0, rt); \
590bc601
PB
1109 tcg_temp_free(t0); \
1110}
1111#endif
590bc601 1112OP_ST_ATOMIC(sc,st32,ld32s,0x3);
aaa9128a 1113#if defined(TARGET_MIPS64)
590bc601 1114OP_ST_ATOMIC(scd,st64,ld64,0x7);
aaa9128a
TS
1115#endif
1116#undef OP_ST_ATOMIC
1117
662d7485
NF
1118static void gen_base_offset_addr (DisasContext *ctx, TCGv addr,
1119 int base, int16_t offset)
1120{
1121 if (base == 0) {
1122 tcg_gen_movi_tl(addr, offset);
1123 } else if (offset == 0) {
1124 gen_load_gpr(addr, base);
1125 } else {
1126 tcg_gen_movi_tl(addr, offset);
1127 gen_op_addr_add(ctx, addr, cpu_gpr[base], addr);
1128 }
1129}
1130
364d4831
NF
1131static target_ulong pc_relative_pc (DisasContext *ctx)
1132{
1133 target_ulong pc = ctx->pc;
1134
1135 if (ctx->hflags & MIPS_HFLAG_BMASK) {
1136 int branch_bytes = ctx->hflags & MIPS_HFLAG_BDS16 ? 2 : 4;
1137
1138 pc -= branch_bytes;
1139 }
1140
1141 pc &= ~(target_ulong)3;
1142 return pc;
1143}
1144
5c13fdfd 1145/* Load */
7db13fae 1146static void gen_ld (CPUMIPSState *env, DisasContext *ctx, uint32_t opc,
afa88c3a 1147 int rt, int base, int16_t offset)
6af0bf9c 1148{
5c13fdfd 1149 const char *opn = "ld";
afa88c3a
AJ
1150 TCGv t0, t1;
1151
1152 if (rt == 0 && env->insn_flags & (INSN_LOONGSON2E | INSN_LOONGSON2F)) {
1153 /* Loongson CPU uses a load to zero register for prefetch.
1154 We emulate it as a NOP. On other CPU we must perform the
1155 actual memory access. */
1156 MIPS_DEBUG("NOP");
1157 return;
1158 }
6af0bf9c 1159
afa88c3a
AJ
1160 t0 = tcg_temp_new();
1161 t1 = tcg_temp_new();
662d7485 1162 gen_base_offset_addr(ctx, t0, base, offset);
afa88c3a 1163
6af0bf9c 1164 switch (opc) {
d26bc211 1165#if defined(TARGET_MIPS64)
6e473128 1166 case OPC_LWU:
d66c7132 1167 save_cpu_state(ctx, 0);
5c13fdfd 1168 op_ld_lwu(t0, t0, ctx);
78723684 1169 gen_store_gpr(t0, rt);
6e473128
TS
1170 opn = "lwu";
1171 break;
6af0bf9c 1172 case OPC_LD:
d66c7132 1173 save_cpu_state(ctx, 0);
5c13fdfd 1174 op_ld_ld(t0, t0, ctx);
78723684 1175 gen_store_gpr(t0, rt);
6af0bf9c
FB
1176 opn = "ld";
1177 break;
7a387fff 1178 case OPC_LLD:
b835e919 1179 save_cpu_state(ctx, 1);
5c13fdfd 1180 op_ld_lld(t0, t0, ctx);
78723684 1181 gen_store_gpr(t0, rt);
7a387fff
TS
1182 opn = "lld";
1183 break;
6af0bf9c 1184 case OPC_LDL:
c8c2227e 1185 save_cpu_state(ctx, 1);
78723684 1186 gen_load_gpr(t1, rt);
895c2d04 1187 gen_helper_1e2i(ldl, t1, t1, t0, ctx->mem_idx);
78723684 1188 gen_store_gpr(t1, rt);
6af0bf9c
FB
1189 opn = "ldl";
1190 break;
6af0bf9c 1191 case OPC_LDR:
c8c2227e 1192 save_cpu_state(ctx, 1);
78723684 1193 gen_load_gpr(t1, rt);
895c2d04 1194 gen_helper_1e2i(ldr, t1, t1, t0, ctx->mem_idx);
78723684 1195 gen_store_gpr(t1, rt);
6af0bf9c
FB
1196 opn = "ldr";
1197 break;
364d4831 1198 case OPC_LDPC:
b835e919 1199 save_cpu_state(ctx, 0);
364d4831
NF
1200 tcg_gen_movi_tl(t1, pc_relative_pc(ctx));
1201 gen_op_addr_add(ctx, t0, t0, t1);
5c13fdfd 1202 op_ld_ld(t0, t0, ctx);
364d4831 1203 gen_store_gpr(t0, rt);
5c13fdfd 1204 opn = "ldpc";
364d4831 1205 break;
6af0bf9c 1206#endif
364d4831 1207 case OPC_LWPC:
b835e919 1208 save_cpu_state(ctx, 0);
364d4831
NF
1209 tcg_gen_movi_tl(t1, pc_relative_pc(ctx));
1210 gen_op_addr_add(ctx, t0, t0, t1);
5c13fdfd 1211 op_ld_lw(t0, t0, ctx);
364d4831 1212 gen_store_gpr(t0, rt);
5c13fdfd 1213 opn = "lwpc";
364d4831 1214 break;
6af0bf9c 1215 case OPC_LW:
d66c7132 1216 save_cpu_state(ctx, 0);
5c13fdfd 1217 op_ld_lw(t0, t0, ctx);
78723684 1218 gen_store_gpr(t0, rt);
6af0bf9c
FB
1219 opn = "lw";
1220 break;
6af0bf9c 1221 case OPC_LH:
d66c7132 1222 save_cpu_state(ctx, 0);
5c13fdfd 1223 op_ld_lh(t0, t0, ctx);
78723684 1224 gen_store_gpr(t0, rt);
6af0bf9c
FB
1225 opn = "lh";
1226 break;
6af0bf9c 1227 case OPC_LHU:
d66c7132 1228 save_cpu_state(ctx, 0);
5c13fdfd 1229 op_ld_lhu(t0, t0, ctx);
78723684 1230 gen_store_gpr(t0, rt);
6af0bf9c
FB
1231 opn = "lhu";
1232 break;
1233 case OPC_LB:
d66c7132 1234 save_cpu_state(ctx, 0);
5c13fdfd 1235 op_ld_lb(t0, t0, ctx);
78723684 1236 gen_store_gpr(t0, rt);
6af0bf9c
FB
1237 opn = "lb";
1238 break;
6af0bf9c 1239 case OPC_LBU:
d66c7132 1240 save_cpu_state(ctx, 0);
5c13fdfd 1241 op_ld_lbu(t0, t0, ctx);
78723684 1242 gen_store_gpr(t0, rt);
6af0bf9c
FB
1243 opn = "lbu";
1244 break;
1245 case OPC_LWL:
c8c2227e 1246 save_cpu_state(ctx, 1);
6958549d 1247 gen_load_gpr(t1, rt);
895c2d04 1248 gen_helper_1e2i(lwl, t1, t1, t0, ctx->mem_idx);
78723684 1249 gen_store_gpr(t1, rt);
6af0bf9c
FB
1250 opn = "lwl";
1251 break;
6af0bf9c 1252 case OPC_LWR:
c8c2227e 1253 save_cpu_state(ctx, 1);
6958549d 1254 gen_load_gpr(t1, rt);
895c2d04 1255 gen_helper_1e2i(lwr, t1, t1, t0, ctx->mem_idx);
78723684 1256 gen_store_gpr(t1, rt);
6af0bf9c
FB
1257 opn = "lwr";
1258 break;
6af0bf9c 1259 case OPC_LL:
e7139c44 1260 save_cpu_state(ctx, 1);
5c13fdfd 1261 op_ld_ll(t0, t0, ctx);
78723684 1262 gen_store_gpr(t0, rt);
6af0bf9c
FB
1263 opn = "ll";
1264 break;
d66c7132 1265 }
2abf314d 1266 (void)opn; /* avoid a compiler warning */
d66c7132
AJ
1267 MIPS_DEBUG("%s %s, %d(%s)", opn, regnames[rt], offset, regnames[base]);
1268 tcg_temp_free(t0);
1269 tcg_temp_free(t1);
1270}
1271
5c13fdfd
AJ
1272/* Store */
1273static void gen_st (DisasContext *ctx, uint32_t opc, int rt,
1274 int base, int16_t offset)
1275{
1276 const char *opn = "st";
1277 TCGv t0 = tcg_temp_new();
1278 TCGv t1 = tcg_temp_new();
1279
1280 gen_base_offset_addr(ctx, t0, base, offset);
1281 gen_load_gpr(t1, rt);
1282 switch (opc) {
1283#if defined(TARGET_MIPS64)
1284 case OPC_SD:
1285 save_cpu_state(ctx, 0);
1286 op_st_sd(t1, t0, ctx);
1287 opn = "sd";
1288 break;
1289 case OPC_SDL:
1290 save_cpu_state(ctx, 1);
895c2d04 1291 gen_helper_0e2i(sdl, t1, t0, ctx->mem_idx);
5c13fdfd
AJ
1292 opn = "sdl";
1293 break;
1294 case OPC_SDR:
1295 save_cpu_state(ctx, 1);
895c2d04 1296 gen_helper_0e2i(sdr, t1, t0, ctx->mem_idx);
5c13fdfd
AJ
1297 opn = "sdr";
1298 break;
1299#endif
1300 case OPC_SW:
1301 save_cpu_state(ctx, 0);
1302 op_st_sw(t1, t0, ctx);
1303 opn = "sw";
1304 break;
1305 case OPC_SH:
1306 save_cpu_state(ctx, 0);
1307 op_st_sh(t1, t0, ctx);
1308 opn = "sh";
1309 break;
1310 case OPC_SB:
1311 save_cpu_state(ctx, 0);
1312 op_st_sb(t1, t0, ctx);
1313 opn = "sb";
1314 break;
1315 case OPC_SWL:
1316 save_cpu_state(ctx, 1);
895c2d04 1317 gen_helper_0e2i(swl, t1, t0, ctx->mem_idx);
5c13fdfd
AJ
1318 opn = "swl";
1319 break;
1320 case OPC_SWR:
1321 save_cpu_state(ctx, 1);
895c2d04 1322 gen_helper_0e2i(swr, t1, t0, ctx->mem_idx);
5c13fdfd
AJ
1323 opn = "swr";
1324 break;
1325 }
2abf314d 1326 (void)opn; /* avoid a compiler warning */
5c13fdfd
AJ
1327 MIPS_DEBUG("%s %s, %d(%s)", opn, regnames[rt], offset, regnames[base]);
1328 tcg_temp_free(t0);
1329 tcg_temp_free(t1);
1330}
1331
1332
d66c7132
AJ
1333/* Store conditional */
1334static void gen_st_cond (DisasContext *ctx, uint32_t opc, int rt,
1335 int base, int16_t offset)
1336{
1337 const char *opn = "st_cond";
1338 TCGv t0, t1;
1339
1340 t0 = tcg_temp_local_new();
1341
662d7485 1342 gen_base_offset_addr(ctx, t0, base, offset);
d66c7132
AJ
1343 /* Don't do NOP if destination is zero: we must perform the actual
1344 memory access. */
1345
1346 t1 = tcg_temp_local_new();
1347 gen_load_gpr(t1, rt);
1348 switch (opc) {
1349#if defined(TARGET_MIPS64)
1350 case OPC_SCD:
b835e919 1351 save_cpu_state(ctx, 1);
5c13fdfd 1352 op_st_scd(t1, t0, rt, ctx);
d66c7132
AJ
1353 opn = "scd";
1354 break;
1355#endif
6af0bf9c 1356 case OPC_SC:
e7139c44 1357 save_cpu_state(ctx, 1);
5c13fdfd 1358 op_st_sc(t1, t0, rt, ctx);
6af0bf9c
FB
1359 opn = "sc";
1360 break;
6af0bf9c 1361 }
2abf314d 1362 (void)opn; /* avoid a compiler warning */
6af0bf9c 1363 MIPS_DEBUG("%s %s, %d(%s)", opn, regnames[rt], offset, regnames[base]);
78723684 1364 tcg_temp_free(t1);
d66c7132 1365 tcg_temp_free(t0);
6af0bf9c
FB
1366}
1367
6ea83fed 1368/* Load and store */
7a387fff 1369static void gen_flt_ldst (DisasContext *ctx, uint32_t opc, int ft,
356265ae 1370 int base, int16_t offset)
6ea83fed 1371{
923617a3 1372 const char *opn = "flt_ldst";
4e2474d6 1373 TCGv t0 = tcg_temp_new();
6ea83fed 1374
662d7485 1375 gen_base_offset_addr(ctx, t0, base, offset);
6ea83fed 1376 /* Don't do NOP if destination is zero: we must perform the actual
ead9360e 1377 memory access. */
6ea83fed
FB
1378 switch (opc) {
1379 case OPC_LWC1:
b6d96bed 1380 {
a7812ae4 1381 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed 1382
c407df81
AJ
1383 tcg_gen_qemu_ld32s(t0, t0, ctx->mem_idx);
1384 tcg_gen_trunc_tl_i32(fp0, t0);
b6d96bed 1385 gen_store_fpr32(fp0, ft);
a7812ae4 1386 tcg_temp_free_i32(fp0);
b6d96bed 1387 }
6ea83fed
FB
1388 opn = "lwc1";
1389 break;
1390 case OPC_SWC1:
b6d96bed 1391 {
a7812ae4
PB
1392 TCGv_i32 fp0 = tcg_temp_new_i32();
1393 TCGv t1 = tcg_temp_new();
b6d96bed
TS
1394
1395 gen_load_fpr32(fp0, ft);
a7812ae4
PB
1396 tcg_gen_extu_i32_tl(t1, fp0);
1397 tcg_gen_qemu_st32(t1, t0, ctx->mem_idx);
1398 tcg_temp_free(t1);
1399 tcg_temp_free_i32(fp0);
b6d96bed 1400 }
6ea83fed
FB
1401 opn = "swc1";
1402 break;
1403 case OPC_LDC1:
b6d96bed 1404 {
a7812ae4 1405 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
1406
1407 tcg_gen_qemu_ld64(fp0, t0, ctx->mem_idx);
1408 gen_store_fpr64(ctx, fp0, ft);
a7812ae4 1409 tcg_temp_free_i64(fp0);
b6d96bed 1410 }
6ea83fed
FB
1411 opn = "ldc1";
1412 break;
1413 case OPC_SDC1:
b6d96bed 1414 {
a7812ae4 1415 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
1416
1417 gen_load_fpr64(ctx, fp0, ft);
1418 tcg_gen_qemu_st64(fp0, t0, ctx->mem_idx);
a7812ae4 1419 tcg_temp_free_i64(fp0);
b6d96bed 1420 }
6ea83fed
FB
1421 opn = "sdc1";
1422 break;
1423 default:
923617a3 1424 MIPS_INVAL(opn);
e397ee33 1425 generate_exception(ctx, EXCP_RI);
78723684 1426 goto out;
6ea83fed 1427 }
2abf314d 1428 (void)opn; /* avoid a compiler warning */
6ea83fed 1429 MIPS_DEBUG("%s %s, %d(%s)", opn, fregnames[ft], offset, regnames[base]);
78723684
TS
1430 out:
1431 tcg_temp_free(t0);
6ea83fed 1432}
6ea83fed 1433
7db13fae 1434static void gen_cop1_ldst(CPUMIPSState *env, DisasContext *ctx,
26ebe468
NF
1435 uint32_t op, int rt, int rs, int16_t imm)
1436{
1437 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
1438 check_cp1_enabled(ctx);
1439 gen_flt_ldst(ctx, op, rt, rs, imm);
1440 } else {
1441 generate_exception_err(ctx, EXCP_CpU, 1);
1442 }
1443}
1444
6af0bf9c 1445/* Arithmetic with immediate operand */
7db13fae 1446static void gen_arith_imm (CPUMIPSState *env, DisasContext *ctx, uint32_t opc,
e189e748 1447 int rt, int rs, int16_t imm)
6af0bf9c 1448{
324d9e32 1449 target_ulong uimm = (target_long)imm; /* Sign extend to 32/64 bits */
923617a3 1450 const char *opn = "imm arith";
6af0bf9c 1451
7a387fff 1452 if (rt == 0 && opc != OPC_ADDI && opc != OPC_DADDI) {
ead9360e
TS
1453 /* If no destination, treat it as a NOP.
1454 For addi, we must generate the overflow exception when needed. */
6af0bf9c 1455 MIPS_DEBUG("NOP");
324d9e32 1456 return;
6af0bf9c
FB
1457 }
1458 switch (opc) {
1459 case OPC_ADDI:
48d38ca5 1460 {
324d9e32
AJ
1461 TCGv t0 = tcg_temp_local_new();
1462 TCGv t1 = tcg_temp_new();
1463 TCGv t2 = tcg_temp_new();
48d38ca5
TS
1464 int l1 = gen_new_label();
1465
324d9e32
AJ
1466 gen_load_gpr(t1, rs);
1467 tcg_gen_addi_tl(t0, t1, uimm);
1468 tcg_gen_ext32s_tl(t0, t0);
48d38ca5 1469
324d9e32
AJ
1470 tcg_gen_xori_tl(t1, t1, ~uimm);
1471 tcg_gen_xori_tl(t2, t0, uimm);
1472 tcg_gen_and_tl(t1, t1, t2);
1473 tcg_temp_free(t2);
1474 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
1475 tcg_temp_free(t1);
48d38ca5
TS
1476 /* operands of same sign, result different sign */
1477 generate_exception(ctx, EXCP_OVERFLOW);
1478 gen_set_label(l1);
78723684 1479 tcg_gen_ext32s_tl(t0, t0);
324d9e32
AJ
1480 gen_store_gpr(t0, rt);
1481 tcg_temp_free(t0);
48d38ca5 1482 }
6af0bf9c
FB
1483 opn = "addi";
1484 break;
1485 case OPC_ADDIU:
324d9e32
AJ
1486 if (rs != 0) {
1487 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
1488 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
1489 } else {
1490 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
1491 }
6af0bf9c
FB
1492 opn = "addiu";
1493 break;
d26bc211 1494#if defined(TARGET_MIPS64)
7a387fff 1495 case OPC_DADDI:
48d38ca5 1496 {
324d9e32
AJ
1497 TCGv t0 = tcg_temp_local_new();
1498 TCGv t1 = tcg_temp_new();
1499 TCGv t2 = tcg_temp_new();
48d38ca5
TS
1500 int l1 = gen_new_label();
1501
324d9e32
AJ
1502 gen_load_gpr(t1, rs);
1503 tcg_gen_addi_tl(t0, t1, uimm);
48d38ca5 1504
324d9e32
AJ
1505 tcg_gen_xori_tl(t1, t1, ~uimm);
1506 tcg_gen_xori_tl(t2, t0, uimm);
1507 tcg_gen_and_tl(t1, t1, t2);
1508 tcg_temp_free(t2);
1509 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
1510 tcg_temp_free(t1);
48d38ca5
TS
1511 /* operands of same sign, result different sign */
1512 generate_exception(ctx, EXCP_OVERFLOW);
1513 gen_set_label(l1);
324d9e32
AJ
1514 gen_store_gpr(t0, rt);
1515 tcg_temp_free(t0);
48d38ca5 1516 }
7a387fff
TS
1517 opn = "daddi";
1518 break;
1519 case OPC_DADDIU:
324d9e32
AJ
1520 if (rs != 0) {
1521 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
1522 } else {
1523 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
1524 }
7a387fff
TS
1525 opn = "daddiu";
1526 break;
1527#endif
324d9e32 1528 }
2abf314d 1529 (void)opn; /* avoid a compiler warning */
324d9e32
AJ
1530 MIPS_DEBUG("%s %s, %s, " TARGET_FMT_lx, opn, regnames[rt], regnames[rs], uimm);
1531}
1532
1533/* Logic with immediate operand */
9fa77488
RH
1534static void gen_logic_imm(CPUMIPSState *env, DisasContext *ctx, uint32_t opc,
1535 int rt, int rs, int16_t imm)
324d9e32
AJ
1536{
1537 target_ulong uimm;
1538 const char *opn = "imm logic";
1539
1540 if (rt == 0) {
1541 /* If no destination, treat it as a NOP. */
1542 MIPS_DEBUG("NOP");
1543 return;
1544 }
1545 uimm = (uint16_t)imm;
1546 switch (opc) {
6af0bf9c 1547 case OPC_ANDI:
324d9e32
AJ
1548 if (likely(rs != 0))
1549 tcg_gen_andi_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
1550 else
1551 tcg_gen_movi_tl(cpu_gpr[rt], 0);
6af0bf9c
FB
1552 opn = "andi";
1553 break;
1554 case OPC_ORI:
324d9e32
AJ
1555 if (rs != 0)
1556 tcg_gen_ori_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
1557 else
1558 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
6af0bf9c
FB
1559 opn = "ori";
1560 break;
1561 case OPC_XORI:
324d9e32
AJ
1562 if (likely(rs != 0))
1563 tcg_gen_xori_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
1564 else
1565 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
6af0bf9c
FB
1566 opn = "xori";
1567 break;
1568 case OPC_LUI:
324d9e32 1569 tcg_gen_movi_tl(cpu_gpr[rt], imm << 16);
6af0bf9c
FB
1570 opn = "lui";
1571 break;
324d9e32 1572 }
2abf314d 1573 (void)opn; /* avoid a compiler warning */
324d9e32
AJ
1574 MIPS_DEBUG("%s %s, %s, " TARGET_FMT_lx, opn, regnames[rt], regnames[rs], uimm);
1575}
1576
1577/* Set on less than with immediate operand */
9fa77488
RH
1578static void gen_slt_imm(CPUMIPSState *env, DisasContext *ctx, uint32_t opc,
1579 int rt, int rs, int16_t imm)
324d9e32
AJ
1580{
1581 target_ulong uimm = (target_long)imm; /* Sign extend to 32/64 bits */
1582 const char *opn = "imm arith";
1583 TCGv t0;
1584
1585 if (rt == 0) {
1586 /* If no destination, treat it as a NOP. */
1587 MIPS_DEBUG("NOP");
1588 return;
1589 }
1590 t0 = tcg_temp_new();
1591 gen_load_gpr(t0, rs);
1592 switch (opc) {
1593 case OPC_SLTI:
e68dd28f 1594 tcg_gen_setcondi_tl(TCG_COND_LT, cpu_gpr[rt], t0, uimm);
324d9e32
AJ
1595 opn = "slti";
1596 break;
1597 case OPC_SLTIU:
e68dd28f 1598 tcg_gen_setcondi_tl(TCG_COND_LTU, cpu_gpr[rt], t0, uimm);
324d9e32
AJ
1599 opn = "sltiu";
1600 break;
1601 }
2abf314d 1602 (void)opn; /* avoid a compiler warning */
324d9e32
AJ
1603 MIPS_DEBUG("%s %s, %s, " TARGET_FMT_lx, opn, regnames[rt], regnames[rs], uimm);
1604 tcg_temp_free(t0);
1605}
1606
1607/* Shifts with immediate operand */
7db13fae 1608static void gen_shift_imm(CPUMIPSState *env, DisasContext *ctx, uint32_t opc,
324d9e32
AJ
1609 int rt, int rs, int16_t imm)
1610{
1611 target_ulong uimm = ((uint16_t)imm) & 0x1f;
1612 const char *opn = "imm shift";
1613 TCGv t0;
1614
1615 if (rt == 0) {
1616 /* If no destination, treat it as a NOP. */
1617 MIPS_DEBUG("NOP");
1618 return;
1619 }
1620
1621 t0 = tcg_temp_new();
1622 gen_load_gpr(t0, rs);
1623 switch (opc) {
6af0bf9c 1624 case OPC_SLL:
78723684 1625 tcg_gen_shli_tl(t0, t0, uimm);
324d9e32 1626 tcg_gen_ext32s_tl(cpu_gpr[rt], t0);
6af0bf9c
FB
1627 opn = "sll";
1628 break;
1629 case OPC_SRA:
324d9e32 1630 tcg_gen_sari_tl(cpu_gpr[rt], t0, uimm);
6af0bf9c
FB
1631 opn = "sra";
1632 break;
1633 case OPC_SRL:
ea63e2c3
NF
1634 if (uimm != 0) {
1635 tcg_gen_ext32u_tl(t0, t0);
1636 tcg_gen_shri_tl(cpu_gpr[rt], t0, uimm);
1637 } else {
1638 tcg_gen_ext32s_tl(cpu_gpr[rt], t0);
5a63bcb2 1639 }
ea63e2c3
NF
1640 opn = "srl";
1641 break;
1642 case OPC_ROTR:
1643 if (uimm != 0) {
1644 TCGv_i32 t1 = tcg_temp_new_i32();
1645
1646 tcg_gen_trunc_tl_i32(t1, t0);
1647 tcg_gen_rotri_i32(t1, t1, uimm);
1648 tcg_gen_ext_i32_tl(cpu_gpr[rt], t1);
1649 tcg_temp_free_i32(t1);
3399e30f
NF
1650 } else {
1651 tcg_gen_ext32s_tl(cpu_gpr[rt], t0);
ea63e2c3
NF
1652 }
1653 opn = "rotr";
7a387fff 1654 break;
d26bc211 1655#if defined(TARGET_MIPS64)
7a387fff 1656 case OPC_DSLL:
324d9e32 1657 tcg_gen_shli_tl(cpu_gpr[rt], t0, uimm);
7a387fff
TS
1658 opn = "dsll";
1659 break;
1660 case OPC_DSRA:
324d9e32 1661 tcg_gen_sari_tl(cpu_gpr[rt], t0, uimm);
7a387fff
TS
1662 opn = "dsra";
1663 break;
1664 case OPC_DSRL:
ea63e2c3
NF
1665 tcg_gen_shri_tl(cpu_gpr[rt], t0, uimm);
1666 opn = "dsrl";
1667 break;
1668 case OPC_DROTR:
1669 if (uimm != 0) {
1670 tcg_gen_rotri_tl(cpu_gpr[rt], t0, uimm);
3399e30f
NF
1671 } else {
1672 tcg_gen_mov_tl(cpu_gpr[rt], t0);
5a63bcb2 1673 }
ea63e2c3 1674 opn = "drotr";
7a387fff
TS
1675 break;
1676 case OPC_DSLL32:
324d9e32 1677 tcg_gen_shli_tl(cpu_gpr[rt], t0, uimm + 32);
7a387fff
TS
1678 opn = "dsll32";
1679 break;
1680 case OPC_DSRA32:
324d9e32 1681 tcg_gen_sari_tl(cpu_gpr[rt], t0, uimm + 32);
7a387fff
TS
1682 opn = "dsra32";
1683 break;
1684 case OPC_DSRL32:
ea63e2c3
NF
1685 tcg_gen_shri_tl(cpu_gpr[rt], t0, uimm + 32);
1686 opn = "dsrl32";
1687 break;
1688 case OPC_DROTR32:
1689 tcg_gen_rotri_tl(cpu_gpr[rt], t0, uimm + 32);
1690 opn = "drotr32";
6af0bf9c 1691 break;
7a387fff 1692#endif
6af0bf9c 1693 }
2abf314d 1694 (void)opn; /* avoid a compiler warning */
93b12ccc 1695 MIPS_DEBUG("%s %s, %s, " TARGET_FMT_lx, opn, regnames[rt], regnames[rs], uimm);
78723684 1696 tcg_temp_free(t0);
6af0bf9c
FB
1697}
1698
1699/* Arithmetic */
7db13fae 1700static void gen_arith (CPUMIPSState *env, DisasContext *ctx, uint32_t opc,
6af0bf9c
FB
1701 int rd, int rs, int rt)
1702{
923617a3 1703 const char *opn = "arith";
6af0bf9c 1704
7a387fff
TS
1705 if (rd == 0 && opc != OPC_ADD && opc != OPC_SUB
1706 && opc != OPC_DADD && opc != OPC_DSUB) {
ead9360e
TS
1707 /* If no destination, treat it as a NOP.
1708 For add & sub, we must generate the overflow exception when needed. */
6af0bf9c 1709 MIPS_DEBUG("NOP");
460f00c4 1710 return;
185f0762 1711 }
460f00c4 1712
6af0bf9c
FB
1713 switch (opc) {
1714 case OPC_ADD:
48d38ca5 1715 {
460f00c4
AJ
1716 TCGv t0 = tcg_temp_local_new();
1717 TCGv t1 = tcg_temp_new();
1718 TCGv t2 = tcg_temp_new();
48d38ca5
TS
1719 int l1 = gen_new_label();
1720
460f00c4
AJ
1721 gen_load_gpr(t1, rs);
1722 gen_load_gpr(t2, rt);
1723 tcg_gen_add_tl(t0, t1, t2);
1724 tcg_gen_ext32s_tl(t0, t0);
1725 tcg_gen_xor_tl(t1, t1, t2);
460f00c4 1726 tcg_gen_xor_tl(t2, t0, t2);
deb4203d 1727 tcg_gen_andc_tl(t1, t2, t1);
460f00c4
AJ
1728 tcg_temp_free(t2);
1729 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
1730 tcg_temp_free(t1);
48d38ca5
TS
1731 /* operands of same sign, result different sign */
1732 generate_exception(ctx, EXCP_OVERFLOW);
1733 gen_set_label(l1);
460f00c4
AJ
1734 gen_store_gpr(t0, rd);
1735 tcg_temp_free(t0);
48d38ca5 1736 }
6af0bf9c
FB
1737 opn = "add";
1738 break;
1739 case OPC_ADDU:
460f00c4
AJ
1740 if (rs != 0 && rt != 0) {
1741 tcg_gen_add_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
1742 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
1743 } else if (rs == 0 && rt != 0) {
1744 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
1745 } else if (rs != 0 && rt == 0) {
1746 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
1747 } else {
1748 tcg_gen_movi_tl(cpu_gpr[rd], 0);
1749 }
6af0bf9c
FB
1750 opn = "addu";
1751 break;
1752 case OPC_SUB:
48d38ca5 1753 {
460f00c4
AJ
1754 TCGv t0 = tcg_temp_local_new();
1755 TCGv t1 = tcg_temp_new();
1756 TCGv t2 = tcg_temp_new();
48d38ca5
TS
1757 int l1 = gen_new_label();
1758
460f00c4
AJ
1759 gen_load_gpr(t1, rs);
1760 gen_load_gpr(t2, rt);
1761 tcg_gen_sub_tl(t0, t1, t2);
1762 tcg_gen_ext32s_tl(t0, t0);
1763 tcg_gen_xor_tl(t2, t1, t2);
1764 tcg_gen_xor_tl(t1, t0, t1);
1765 tcg_gen_and_tl(t1, t1, t2);
1766 tcg_temp_free(t2);
1767 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
1768 tcg_temp_free(t1);
31e3104f 1769 /* operands of different sign, first operand and result different sign */
48d38ca5
TS
1770 generate_exception(ctx, EXCP_OVERFLOW);
1771 gen_set_label(l1);
460f00c4
AJ
1772 gen_store_gpr(t0, rd);
1773 tcg_temp_free(t0);
48d38ca5 1774 }
6af0bf9c
FB
1775 opn = "sub";
1776 break;
1777 case OPC_SUBU:
460f00c4
AJ
1778 if (rs != 0 && rt != 0) {
1779 tcg_gen_sub_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
1780 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
1781 } else if (rs == 0 && rt != 0) {
1782 tcg_gen_neg_tl(cpu_gpr[rd], cpu_gpr[rt]);
6bb72b18 1783 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
460f00c4
AJ
1784 } else if (rs != 0 && rt == 0) {
1785 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
1786 } else {
1787 tcg_gen_movi_tl(cpu_gpr[rd], 0);
1788 }
6af0bf9c
FB
1789 opn = "subu";
1790 break;
d26bc211 1791#if defined(TARGET_MIPS64)
7a387fff 1792 case OPC_DADD:
48d38ca5 1793 {
460f00c4
AJ
1794 TCGv t0 = tcg_temp_local_new();
1795 TCGv t1 = tcg_temp_new();
1796 TCGv t2 = tcg_temp_new();
48d38ca5
TS
1797 int l1 = gen_new_label();
1798
460f00c4
AJ
1799 gen_load_gpr(t1, rs);
1800 gen_load_gpr(t2, rt);
1801 tcg_gen_add_tl(t0, t1, t2);
1802 tcg_gen_xor_tl(t1, t1, t2);
460f00c4 1803 tcg_gen_xor_tl(t2, t0, t2);
deb4203d 1804 tcg_gen_andc_tl(t1, t2, t1);
460f00c4
AJ
1805 tcg_temp_free(t2);
1806 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
1807 tcg_temp_free(t1);
48d38ca5
TS
1808 /* operands of same sign, result different sign */
1809 generate_exception(ctx, EXCP_OVERFLOW);
1810 gen_set_label(l1);
460f00c4
AJ
1811 gen_store_gpr(t0, rd);
1812 tcg_temp_free(t0);
48d38ca5 1813 }
7a387fff
TS
1814 opn = "dadd";
1815 break;
1816 case OPC_DADDU:
460f00c4
AJ
1817 if (rs != 0 && rt != 0) {
1818 tcg_gen_add_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
1819 } else if (rs == 0 && rt != 0) {
1820 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
1821 } else if (rs != 0 && rt == 0) {
1822 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
1823 } else {
1824 tcg_gen_movi_tl(cpu_gpr[rd], 0);
1825 }
7a387fff
TS
1826 opn = "daddu";
1827 break;
1828 case OPC_DSUB:
48d38ca5 1829 {
460f00c4
AJ
1830 TCGv t0 = tcg_temp_local_new();
1831 TCGv t1 = tcg_temp_new();
1832 TCGv t2 = tcg_temp_new();
48d38ca5
TS
1833 int l1 = gen_new_label();
1834
460f00c4
AJ
1835 gen_load_gpr(t1, rs);
1836 gen_load_gpr(t2, rt);
1837 tcg_gen_sub_tl(t0, t1, t2);
1838 tcg_gen_xor_tl(t2, t1, t2);
1839 tcg_gen_xor_tl(t1, t0, t1);
1840 tcg_gen_and_tl(t1, t1, t2);
1841 tcg_temp_free(t2);
1842 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
1843 tcg_temp_free(t1);
31e3104f 1844 /* operands of different sign, first operand and result different sign */
48d38ca5
TS
1845 generate_exception(ctx, EXCP_OVERFLOW);
1846 gen_set_label(l1);
460f00c4
AJ
1847 gen_store_gpr(t0, rd);
1848 tcg_temp_free(t0);
48d38ca5 1849 }
7a387fff
TS
1850 opn = "dsub";
1851 break;
1852 case OPC_DSUBU:
460f00c4
AJ
1853 if (rs != 0 && rt != 0) {
1854 tcg_gen_sub_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
1855 } else if (rs == 0 && rt != 0) {
1856 tcg_gen_neg_tl(cpu_gpr[rd], cpu_gpr[rt]);
1857 } else if (rs != 0 && rt == 0) {
1858 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
1859 } else {
1860 tcg_gen_movi_tl(cpu_gpr[rd], 0);
1861 }
7a387fff
TS
1862 opn = "dsubu";
1863 break;
1864#endif
460f00c4
AJ
1865 case OPC_MUL:
1866 if (likely(rs != 0 && rt != 0)) {
1867 tcg_gen_mul_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
1868 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
1869 } else {
1870 tcg_gen_movi_tl(cpu_gpr[rd], 0);
1871 }
1872 opn = "mul";
6af0bf9c 1873 break;
460f00c4 1874 }
2abf314d 1875 (void)opn; /* avoid a compiler warning */
460f00c4
AJ
1876 MIPS_DEBUG("%s %s, %s, %s", opn, regnames[rd], regnames[rs], regnames[rt]);
1877}
1878
1879/* Conditional move */
9fa77488
RH
1880static void gen_cond_move(CPUMIPSState *env, DisasContext *ctx, uint32_t opc,
1881 int rd, int rs, int rt)
460f00c4
AJ
1882{
1883 const char *opn = "cond move";
1884 int l1;
1885
1886 if (rd == 0) {
1887 /* If no destination, treat it as a NOP.
1888 For add & sub, we must generate the overflow exception when needed. */
1889 MIPS_DEBUG("NOP");
1890 return;
1891 }
1892
1893 l1 = gen_new_label();
1894 switch (opc) {
1895 case OPC_MOVN:
1896 if (likely(rt != 0))
1897 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[rt], 0, l1);
1898 else
1899 tcg_gen_br(l1);
1900 opn = "movn";
6af0bf9c 1901 break;
460f00c4
AJ
1902 case OPC_MOVZ:
1903 if (likely(rt != 0))
1904 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[rt], 0, l1);
1905 opn = "movz";
1906 break;
1907 }
1908 if (rs != 0)
1909 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
1910 else
1911 tcg_gen_movi_tl(cpu_gpr[rd], 0);
1912 gen_set_label(l1);
1913
2abf314d 1914 (void)opn; /* avoid a compiler warning */
460f00c4
AJ
1915 MIPS_DEBUG("%s %s, %s, %s", opn, regnames[rd], regnames[rs], regnames[rt]);
1916}
1917
1918/* Logic */
9fa77488
RH
1919static void gen_logic(CPUMIPSState *env, DisasContext *ctx, uint32_t opc,
1920 int rd, int rs, int rt)
460f00c4
AJ
1921{
1922 const char *opn = "logic";
1923
1924 if (rd == 0) {
1925 /* If no destination, treat it as a NOP. */
1926 MIPS_DEBUG("NOP");
1927 return;
1928 }
1929
1930 switch (opc) {
6af0bf9c 1931 case OPC_AND:
460f00c4
AJ
1932 if (likely(rs != 0 && rt != 0)) {
1933 tcg_gen_and_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
1934 } else {
1935 tcg_gen_movi_tl(cpu_gpr[rd], 0);
1936 }
6af0bf9c
FB
1937 opn = "and";
1938 break;
1939 case OPC_NOR:
460f00c4
AJ
1940 if (rs != 0 && rt != 0) {
1941 tcg_gen_nor_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
1942 } else if (rs == 0 && rt != 0) {
1943 tcg_gen_not_tl(cpu_gpr[rd], cpu_gpr[rt]);
1944 } else if (rs != 0 && rt == 0) {
1945 tcg_gen_not_tl(cpu_gpr[rd], cpu_gpr[rs]);
1946 } else {
1947 tcg_gen_movi_tl(cpu_gpr[rd], ~((target_ulong)0));
1948 }
6af0bf9c
FB
1949 opn = "nor";
1950 break;
1951 case OPC_OR:
460f00c4
AJ
1952 if (likely(rs != 0 && rt != 0)) {
1953 tcg_gen_or_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
1954 } else if (rs == 0 && rt != 0) {
1955 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
1956 } else if (rs != 0 && rt == 0) {
1957 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
1958 } else {
1959 tcg_gen_movi_tl(cpu_gpr[rd], 0);
1960 }
6af0bf9c
FB
1961 opn = "or";
1962 break;
1963 case OPC_XOR:
460f00c4
AJ
1964 if (likely(rs != 0 && rt != 0)) {
1965 tcg_gen_xor_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
1966 } else if (rs == 0 && rt != 0) {
1967 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
1968 } else if (rs != 0 && rt == 0) {
1969 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
1970 } else {
1971 tcg_gen_movi_tl(cpu_gpr[rd], 0);
1972 }
6af0bf9c
FB
1973 opn = "xor";
1974 break;
460f00c4 1975 }
2abf314d 1976 (void)opn; /* avoid a compiler warning */
460f00c4
AJ
1977 MIPS_DEBUG("%s %s, %s, %s", opn, regnames[rd], regnames[rs], regnames[rt]);
1978}
1979
1980/* Set on lower than */
9fa77488
RH
1981static void gen_slt(CPUMIPSState *env, DisasContext *ctx, uint32_t opc,
1982 int rd, int rs, int rt)
460f00c4
AJ
1983{
1984 const char *opn = "slt";
1985 TCGv t0, t1;
1986
1987 if (rd == 0) {
1988 /* If no destination, treat it as a NOP. */
1989 MIPS_DEBUG("NOP");
1990 return;
1991 }
1992
1993 t0 = tcg_temp_new();
1994 t1 = tcg_temp_new();
1995 gen_load_gpr(t0, rs);
1996 gen_load_gpr(t1, rt);
1997 switch (opc) {
1998 case OPC_SLT:
e68dd28f 1999 tcg_gen_setcond_tl(TCG_COND_LT, cpu_gpr[rd], t0, t1);
460f00c4 2000 opn = "slt";
6af0bf9c 2001 break;
460f00c4 2002 case OPC_SLTU:
e68dd28f 2003 tcg_gen_setcond_tl(TCG_COND_LTU, cpu_gpr[rd], t0, t1);
460f00c4
AJ
2004 opn = "sltu";
2005 break;
2006 }
2abf314d 2007 (void)opn; /* avoid a compiler warning */
460f00c4
AJ
2008 MIPS_DEBUG("%s %s, %s, %s", opn, regnames[rd], regnames[rs], regnames[rt]);
2009 tcg_temp_free(t0);
2010 tcg_temp_free(t1);
2011}
20c4c97c 2012
460f00c4 2013/* Shifts */
7db13fae 2014static void gen_shift (CPUMIPSState *env, DisasContext *ctx, uint32_t opc,
460f00c4
AJ
2015 int rd, int rs, int rt)
2016{
2017 const char *opn = "shifts";
2018 TCGv t0, t1;
20c4c97c 2019
460f00c4
AJ
2020 if (rd == 0) {
2021 /* If no destination, treat it as a NOP.
2022 For add & sub, we must generate the overflow exception when needed. */
2023 MIPS_DEBUG("NOP");
2024 return;
2025 }
2026
2027 t0 = tcg_temp_new();
2028 t1 = tcg_temp_new();
2029 gen_load_gpr(t0, rs);
2030 gen_load_gpr(t1, rt);
2031 switch (opc) {
6af0bf9c 2032 case OPC_SLLV:
78723684
TS
2033 tcg_gen_andi_tl(t0, t0, 0x1f);
2034 tcg_gen_shl_tl(t0, t1, t0);
460f00c4 2035 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
6af0bf9c
FB
2036 opn = "sllv";
2037 break;
2038 case OPC_SRAV:
78723684 2039 tcg_gen_andi_tl(t0, t0, 0x1f);
460f00c4 2040 tcg_gen_sar_tl(cpu_gpr[rd], t1, t0);
6af0bf9c
FB
2041 opn = "srav";
2042 break;
2043 case OPC_SRLV:
ea63e2c3
NF
2044 tcg_gen_ext32u_tl(t1, t1);
2045 tcg_gen_andi_tl(t0, t0, 0x1f);
2046 tcg_gen_shr_tl(t0, t1, t0);
2047 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
2048 opn = "srlv";
2049 break;
2050 case OPC_ROTRV:
2051 {
2052 TCGv_i32 t2 = tcg_temp_new_i32();
2053 TCGv_i32 t3 = tcg_temp_new_i32();
2054
2055 tcg_gen_trunc_tl_i32(t2, t0);
2056 tcg_gen_trunc_tl_i32(t3, t1);
2057 tcg_gen_andi_i32(t2, t2, 0x1f);
2058 tcg_gen_rotr_i32(t2, t3, t2);
2059 tcg_gen_ext_i32_tl(cpu_gpr[rd], t2);
2060 tcg_temp_free_i32(t2);
2061 tcg_temp_free_i32(t3);
2062 opn = "rotrv";
5a63bcb2 2063 }
7a387fff 2064 break;
d26bc211 2065#if defined(TARGET_MIPS64)
7a387fff 2066 case OPC_DSLLV:
78723684 2067 tcg_gen_andi_tl(t0, t0, 0x3f);
460f00c4 2068 tcg_gen_shl_tl(cpu_gpr[rd], t1, t0);
7a387fff
TS
2069 opn = "dsllv";
2070 break;
2071 case OPC_DSRAV:
78723684 2072 tcg_gen_andi_tl(t0, t0, 0x3f);
460f00c4 2073 tcg_gen_sar_tl(cpu_gpr[rd], t1, t0);
7a387fff
TS
2074 opn = "dsrav";
2075 break;
2076 case OPC_DSRLV:
ea63e2c3
NF
2077 tcg_gen_andi_tl(t0, t0, 0x3f);
2078 tcg_gen_shr_tl(cpu_gpr[rd], t1, t0);
2079 opn = "dsrlv";
2080 break;
2081 case OPC_DROTRV:
2082 tcg_gen_andi_tl(t0, t0, 0x3f);
2083 tcg_gen_rotr_tl(cpu_gpr[rd], t1, t0);
2084 opn = "drotrv";
6af0bf9c 2085 break;
7a387fff 2086#endif
6af0bf9c 2087 }
2abf314d 2088 (void)opn; /* avoid a compiler warning */
6af0bf9c 2089 MIPS_DEBUG("%s %s, %s, %s", opn, regnames[rd], regnames[rs], regnames[rt]);
78723684
TS
2090 tcg_temp_free(t0);
2091 tcg_temp_free(t1);
6af0bf9c
FB
2092}
2093
2094/* Arithmetic on HI/LO registers */
7a387fff 2095static void gen_HILO (DisasContext *ctx, uint32_t opc, int reg)
6af0bf9c 2096{
923617a3 2097 const char *opn = "hilo";
6af0bf9c
FB
2098
2099 if (reg == 0 && (opc == OPC_MFHI || opc == OPC_MFLO)) {
ead9360e 2100 /* Treat as NOP. */
6af0bf9c 2101 MIPS_DEBUG("NOP");
a1f6684d 2102 return;
6af0bf9c
FB
2103 }
2104 switch (opc) {
2105 case OPC_MFHI:
a1f6684d 2106 tcg_gen_mov_tl(cpu_gpr[reg], cpu_HI[0]);
6af0bf9c
FB
2107 opn = "mfhi";
2108 break;
2109 case OPC_MFLO:
a1f6684d 2110 tcg_gen_mov_tl(cpu_gpr[reg], cpu_LO[0]);
6af0bf9c
FB
2111 opn = "mflo";
2112 break;
2113 case OPC_MTHI:
a1f6684d
AJ
2114 if (reg != 0)
2115 tcg_gen_mov_tl(cpu_HI[0], cpu_gpr[reg]);
2116 else
2117 tcg_gen_movi_tl(cpu_HI[0], 0);
6af0bf9c
FB
2118 opn = "mthi";
2119 break;
2120 case OPC_MTLO:
a1f6684d
AJ
2121 if (reg != 0)
2122 tcg_gen_mov_tl(cpu_LO[0], cpu_gpr[reg]);
2123 else
2124 tcg_gen_movi_tl(cpu_LO[0], 0);
6af0bf9c
FB
2125 opn = "mtlo";
2126 break;
6af0bf9c 2127 }
2abf314d 2128 (void)opn; /* avoid a compiler warning */
6af0bf9c
FB
2129 MIPS_DEBUG("%s %s", opn, regnames[reg]);
2130}
2131
7a387fff 2132static void gen_muldiv (DisasContext *ctx, uint32_t opc,
6af0bf9c
FB
2133 int rs, int rt)
2134{
923617a3 2135 const char *opn = "mul/div";
d45f89f4
AJ
2136 TCGv t0, t1;
2137
2138 switch (opc) {
2139 case OPC_DIV:
2140 case OPC_DIVU:
2141#if defined(TARGET_MIPS64)
2142 case OPC_DDIV:
2143 case OPC_DDIVU:
2144#endif
2145 t0 = tcg_temp_local_new();
2146 t1 = tcg_temp_local_new();
2147 break;
2148 default:
2149 t0 = tcg_temp_new();
2150 t1 = tcg_temp_new();
2151 break;
2152 }
6af0bf9c 2153
78723684
TS
2154 gen_load_gpr(t0, rs);
2155 gen_load_gpr(t1, rt);
6af0bf9c
FB
2156 switch (opc) {
2157 case OPC_DIV:
48d38ca5
TS
2158 {
2159 int l1 = gen_new_label();
d45f89f4 2160 int l2 = gen_new_label();
48d38ca5 2161
d45f89f4
AJ
2162 tcg_gen_ext32s_tl(t0, t0);
2163 tcg_gen_ext32s_tl(t1, t1);
78723684 2164 tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
d45f89f4
AJ
2165 tcg_gen_brcondi_tl(TCG_COND_NE, t0, INT_MIN, l2);
2166 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1, l2);
2167
2168 tcg_gen_mov_tl(cpu_LO[0], t0);
2169 tcg_gen_movi_tl(cpu_HI[0], 0);
2170 tcg_gen_br(l1);
2171 gen_set_label(l2);
2172 tcg_gen_div_tl(cpu_LO[0], t0, t1);
2173 tcg_gen_rem_tl(cpu_HI[0], t0, t1);
2174 tcg_gen_ext32s_tl(cpu_LO[0], cpu_LO[0]);
2175 tcg_gen_ext32s_tl(cpu_HI[0], cpu_HI[0]);
48d38ca5
TS
2176 gen_set_label(l1);
2177 }
6af0bf9c
FB
2178 opn = "div";
2179 break;
2180 case OPC_DIVU:
48d38ca5
TS
2181 {
2182 int l1 = gen_new_label();
2183
0c0ed03b
AJ
2184 tcg_gen_ext32u_tl(t0, t0);
2185 tcg_gen_ext32u_tl(t1, t1);
78723684 2186 tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
d45f89f4
AJ
2187 tcg_gen_divu_tl(cpu_LO[0], t0, t1);
2188 tcg_gen_remu_tl(cpu_HI[0], t0, t1);
2189 tcg_gen_ext32s_tl(cpu_LO[0], cpu_LO[0]);
2190 tcg_gen_ext32s_tl(cpu_HI[0], cpu_HI[0]);
48d38ca5
TS
2191 gen_set_label(l1);
2192 }
6af0bf9c
FB
2193 opn = "divu";
2194 break;
2195 case OPC_MULT:
214c465f 2196 {
d45f89f4
AJ
2197 TCGv_i64 t2 = tcg_temp_new_i64();
2198 TCGv_i64 t3 = tcg_temp_new_i64();
2199
2200 tcg_gen_ext_tl_i64(t2, t0);
2201 tcg_gen_ext_tl_i64(t3, t1);
2202 tcg_gen_mul_i64(t2, t2, t3);
2203 tcg_temp_free_i64(t3);
2204 tcg_gen_trunc_i64_tl(t0, t2);
2205 tcg_gen_shri_i64(t2, t2, 32);
2206 tcg_gen_trunc_i64_tl(t1, t2);
2207 tcg_temp_free_i64(t2);
b10fa3c9
AJ
2208 tcg_gen_ext32s_tl(cpu_LO[0], t0);
2209 tcg_gen_ext32s_tl(cpu_HI[0], t1);
214c465f 2210 }
6af0bf9c
FB
2211 opn = "mult";
2212 break;
2213 case OPC_MULTU:
214c465f 2214 {
d45f89f4
AJ
2215 TCGv_i64 t2 = tcg_temp_new_i64();
2216 TCGv_i64 t3 = tcg_temp_new_i64();
214c465f 2217
78723684
TS
2218 tcg_gen_ext32u_tl(t0, t0);
2219 tcg_gen_ext32u_tl(t1, t1);
d45f89f4
AJ
2220 tcg_gen_extu_tl_i64(t2, t0);
2221 tcg_gen_extu_tl_i64(t3, t1);
2222 tcg_gen_mul_i64(t2, t2, t3);
2223 tcg_temp_free_i64(t3);
2224 tcg_gen_trunc_i64_tl(t0, t2);
2225 tcg_gen_shri_i64(t2, t2, 32);
2226 tcg_gen_trunc_i64_tl(t1, t2);
2227 tcg_temp_free_i64(t2);
b10fa3c9
AJ
2228 tcg_gen_ext32s_tl(cpu_LO[0], t0);
2229 tcg_gen_ext32s_tl(cpu_HI[0], t1);
214c465f 2230 }
6af0bf9c
FB
2231 opn = "multu";
2232 break;
d26bc211 2233#if defined(TARGET_MIPS64)
7a387fff 2234 case OPC_DDIV:
48d38ca5
TS
2235 {
2236 int l1 = gen_new_label();
d45f89f4 2237 int l2 = gen_new_label();
48d38ca5 2238
78723684 2239 tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
d45f89f4
AJ
2240 tcg_gen_brcondi_tl(TCG_COND_NE, t0, -1LL << 63, l2);
2241 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1LL, l2);
2242 tcg_gen_mov_tl(cpu_LO[0], t0);
2243 tcg_gen_movi_tl(cpu_HI[0], 0);
2244 tcg_gen_br(l1);
2245 gen_set_label(l2);
2246 tcg_gen_div_i64(cpu_LO[0], t0, t1);
2247 tcg_gen_rem_i64(cpu_HI[0], t0, t1);
48d38ca5
TS
2248 gen_set_label(l1);
2249 }
7a387fff
TS
2250 opn = "ddiv";
2251 break;
2252 case OPC_DDIVU:
48d38ca5
TS
2253 {
2254 int l1 = gen_new_label();
2255
78723684 2256 tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
b10fa3c9
AJ
2257 tcg_gen_divu_i64(cpu_LO[0], t0, t1);
2258 tcg_gen_remu_i64(cpu_HI[0], t0, t1);
48d38ca5
TS
2259 gen_set_label(l1);
2260 }
7a387fff
TS
2261 opn = "ddivu";
2262 break;
2263 case OPC_DMULT:
895c2d04 2264 gen_helper_dmult(cpu_env, t0, t1);
7a387fff
TS
2265 opn = "dmult";
2266 break;
2267 case OPC_DMULTU:
895c2d04 2268 gen_helper_dmultu(cpu_env, t0, t1);
7a387fff
TS
2269 opn = "dmultu";
2270 break;
2271#endif
6af0bf9c 2272 case OPC_MADD:
214c465f 2273 {
d45f89f4
AJ
2274 TCGv_i64 t2 = tcg_temp_new_i64();
2275 TCGv_i64 t3 = tcg_temp_new_i64();
2276
2277 tcg_gen_ext_tl_i64(t2, t0);
2278 tcg_gen_ext_tl_i64(t3, t1);
2279 tcg_gen_mul_i64(t2, t2, t3);
2280 tcg_gen_concat_tl_i64(t3, cpu_LO[0], cpu_HI[0]);
2281 tcg_gen_add_i64(t2, t2, t3);
2282 tcg_temp_free_i64(t3);
2283 tcg_gen_trunc_i64_tl(t0, t2);
2284 tcg_gen_shri_i64(t2, t2, 32);
2285 tcg_gen_trunc_i64_tl(t1, t2);
2286 tcg_temp_free_i64(t2);
b10fa3c9 2287 tcg_gen_ext32s_tl(cpu_LO[0], t0);
98070ce0 2288 tcg_gen_ext32s_tl(cpu_HI[0], t1);
214c465f 2289 }
6af0bf9c
FB
2290 opn = "madd";
2291 break;
2292 case OPC_MADDU:
214c465f 2293 {
d45f89f4
AJ
2294 TCGv_i64 t2 = tcg_temp_new_i64();
2295 TCGv_i64 t3 = tcg_temp_new_i64();
214c465f 2296
78723684
TS
2297 tcg_gen_ext32u_tl(t0, t0);
2298 tcg_gen_ext32u_tl(t1, t1);
d45f89f4
AJ
2299 tcg_gen_extu_tl_i64(t2, t0);
2300 tcg_gen_extu_tl_i64(t3, t1);
2301 tcg_gen_mul_i64(t2, t2, t3);
2302 tcg_gen_concat_tl_i64(t3, cpu_LO[0], cpu_HI[0]);
2303 tcg_gen_add_i64(t2, t2, t3);
2304 tcg_temp_free_i64(t3);
2305 tcg_gen_trunc_i64_tl(t0, t2);
2306 tcg_gen_shri_i64(t2, t2, 32);
2307 tcg_gen_trunc_i64_tl(t1, t2);
2308 tcg_temp_free_i64(t2);
b10fa3c9
AJ
2309 tcg_gen_ext32s_tl(cpu_LO[0], t0);
2310 tcg_gen_ext32s_tl(cpu_HI[0], t1);
214c465f 2311 }
6af0bf9c
FB
2312 opn = "maddu";
2313 break;
2314 case OPC_MSUB:
214c465f 2315 {
d45f89f4
AJ
2316 TCGv_i64 t2 = tcg_temp_new_i64();
2317 TCGv_i64 t3 = tcg_temp_new_i64();
2318
2319 tcg_gen_ext_tl_i64(t2, t0);
2320 tcg_gen_ext_tl_i64(t3, t1);
2321 tcg_gen_mul_i64(t2, t2, t3);
2322 tcg_gen_concat_tl_i64(t3, cpu_LO[0], cpu_HI[0]);
98070ce0 2323 tcg_gen_sub_i64(t2, t3, t2);
d45f89f4
AJ
2324 tcg_temp_free_i64(t3);
2325 tcg_gen_trunc_i64_tl(t0, t2);
2326 tcg_gen_shri_i64(t2, t2, 32);
2327 tcg_gen_trunc_i64_tl(t1, t2);
2328 tcg_temp_free_i64(t2);
b10fa3c9
AJ
2329 tcg_gen_ext32s_tl(cpu_LO[0], t0);
2330 tcg_gen_ext32s_tl(cpu_HI[0], t1);
214c465f 2331 }
6af0bf9c
FB
2332 opn = "msub";
2333 break;
2334 case OPC_MSUBU:
214c465f 2335 {
d45f89f4
AJ
2336 TCGv_i64 t2 = tcg_temp_new_i64();
2337 TCGv_i64 t3 = tcg_temp_new_i64();
214c465f 2338
78723684
TS
2339 tcg_gen_ext32u_tl(t0, t0);
2340 tcg_gen_ext32u_tl(t1, t1);
d45f89f4
AJ
2341 tcg_gen_extu_tl_i64(t2, t0);
2342 tcg_gen_extu_tl_i64(t3, t1);
2343 tcg_gen_mul_i64(t2, t2, t3);
2344 tcg_gen_concat_tl_i64(t3, cpu_LO[0], cpu_HI[0]);
98070ce0 2345 tcg_gen_sub_i64(t2, t3, t2);
d45f89f4
AJ
2346 tcg_temp_free_i64(t3);
2347 tcg_gen_trunc_i64_tl(t0, t2);
2348 tcg_gen_shri_i64(t2, t2, 32);
2349 tcg_gen_trunc_i64_tl(t1, t2);
2350 tcg_temp_free_i64(t2);
b10fa3c9
AJ
2351 tcg_gen_ext32s_tl(cpu_LO[0], t0);
2352 tcg_gen_ext32s_tl(cpu_HI[0], t1);
214c465f 2353 }
6af0bf9c
FB
2354 opn = "msubu";
2355 break;
2356 default:
923617a3 2357 MIPS_INVAL(opn);
6af0bf9c 2358 generate_exception(ctx, EXCP_RI);
78723684 2359 goto out;
6af0bf9c 2360 }
2abf314d 2361 (void)opn; /* avoid a compiler warning */
6af0bf9c 2362 MIPS_DEBUG("%s %s %s", opn, regnames[rs], regnames[rt]);
78723684
TS
2363 out:
2364 tcg_temp_free(t0);
2365 tcg_temp_free(t1);
6af0bf9c
FB
2366}
2367
e9c71dd1
TS
2368static void gen_mul_vr54xx (DisasContext *ctx, uint32_t opc,
2369 int rd, int rs, int rt)
2370{
2371 const char *opn = "mul vr54xx";
f157bfe1
AJ
2372 TCGv t0 = tcg_temp_new();
2373 TCGv t1 = tcg_temp_new();
e9c71dd1 2374
6c5c1e20
TS
2375 gen_load_gpr(t0, rs);
2376 gen_load_gpr(t1, rt);
e9c71dd1
TS
2377
2378 switch (opc) {
2379 case OPC_VR54XX_MULS:
895c2d04 2380 gen_helper_muls(t0, cpu_env, t0, t1);
e9c71dd1 2381 opn = "muls";
6958549d 2382 break;
e9c71dd1 2383 case OPC_VR54XX_MULSU:
895c2d04 2384 gen_helper_mulsu(t0, cpu_env, t0, t1);
e9c71dd1 2385 opn = "mulsu";
6958549d 2386 break;
e9c71dd1 2387 case OPC_VR54XX_MACC:
895c2d04 2388 gen_helper_macc(t0, cpu_env, t0, t1);
e9c71dd1 2389 opn = "macc";
6958549d 2390 break;
e9c71dd1 2391 case OPC_VR54XX_MACCU:
895c2d04 2392 gen_helper_maccu(t0, cpu_env, t0, t1);
e9c71dd1 2393 opn = "maccu";
6958549d 2394 break;
e9c71dd1 2395 case OPC_VR54XX_MSAC:
895c2d04 2396 gen_helper_msac(t0, cpu_env, t0, t1);
e9c71dd1 2397 opn = "msac";
6958549d 2398 break;
e9c71dd1 2399 case OPC_VR54XX_MSACU:
895c2d04 2400 gen_helper_msacu(t0, cpu_env, t0, t1);
e9c71dd1 2401 opn = "msacu";
6958549d 2402 break;
e9c71dd1 2403 case OPC_VR54XX_MULHI:
895c2d04 2404 gen_helper_mulhi(t0, cpu_env, t0, t1);
e9c71dd1 2405 opn = "mulhi";
6958549d 2406 break;
e9c71dd1 2407 case OPC_VR54XX_MULHIU:
895c2d04 2408 gen_helper_mulhiu(t0, cpu_env, t0, t1);
e9c71dd1 2409 opn = "mulhiu";
6958549d 2410 break;
e9c71dd1 2411 case OPC_VR54XX_MULSHI:
895c2d04 2412 gen_helper_mulshi(t0, cpu_env, t0, t1);
e9c71dd1 2413 opn = "mulshi";
6958549d 2414 break;
e9c71dd1 2415 case OPC_VR54XX_MULSHIU:
895c2d04 2416 gen_helper_mulshiu(t0, cpu_env, t0, t1);
e9c71dd1 2417 opn = "mulshiu";
6958549d 2418 break;
e9c71dd1 2419 case OPC_VR54XX_MACCHI:
895c2d04 2420 gen_helper_macchi(t0, cpu_env, t0, t1);
e9c71dd1 2421 opn = "macchi";
6958549d 2422 break;
e9c71dd1 2423 case OPC_VR54XX_MACCHIU:
895c2d04 2424 gen_helper_macchiu(t0, cpu_env, t0, t1);
e9c71dd1 2425 opn = "macchiu";
6958549d 2426 break;
e9c71dd1 2427 case OPC_VR54XX_MSACHI:
895c2d04 2428 gen_helper_msachi(t0, cpu_env, t0, t1);
e9c71dd1 2429 opn = "msachi";
6958549d 2430 break;
e9c71dd1 2431 case OPC_VR54XX_MSACHIU:
895c2d04 2432 gen_helper_msachiu(t0, cpu_env, t0, t1);
e9c71dd1 2433 opn = "msachiu";
6958549d 2434 break;
e9c71dd1
TS
2435 default:
2436 MIPS_INVAL("mul vr54xx");
2437 generate_exception(ctx, EXCP_RI);
6c5c1e20 2438 goto out;
e9c71dd1 2439 }
6c5c1e20 2440 gen_store_gpr(t0, rd);
2abf314d 2441 (void)opn; /* avoid a compiler warning */
e9c71dd1 2442 MIPS_DEBUG("%s %s, %s, %s", opn, regnames[rd], regnames[rs], regnames[rt]);
6c5c1e20
TS
2443
2444 out:
2445 tcg_temp_free(t0);
2446 tcg_temp_free(t1);
e9c71dd1
TS
2447}
2448
7a387fff 2449static void gen_cl (DisasContext *ctx, uint32_t opc,
6af0bf9c
FB
2450 int rd, int rs)
2451{
923617a3 2452 const char *opn = "CLx";
20e1fb52 2453 TCGv t0;
6c5c1e20 2454
6af0bf9c 2455 if (rd == 0) {
ead9360e 2456 /* Treat as NOP. */
6af0bf9c 2457 MIPS_DEBUG("NOP");
20e1fb52 2458 return;
6af0bf9c 2459 }
20e1fb52 2460 t0 = tcg_temp_new();
6c5c1e20 2461 gen_load_gpr(t0, rs);
6af0bf9c
FB
2462 switch (opc) {
2463 case OPC_CLO:
20e1fb52 2464 gen_helper_clo(cpu_gpr[rd], t0);
6af0bf9c
FB
2465 opn = "clo";
2466 break;
2467 case OPC_CLZ:
20e1fb52 2468 gen_helper_clz(cpu_gpr[rd], t0);
6af0bf9c
FB
2469 opn = "clz";
2470 break;
d26bc211 2471#if defined(TARGET_MIPS64)
7a387fff 2472 case OPC_DCLO:
20e1fb52 2473 gen_helper_dclo(cpu_gpr[rd], t0);
7a387fff
TS
2474 opn = "dclo";
2475 break;
2476 case OPC_DCLZ:
20e1fb52 2477 gen_helper_dclz(cpu_gpr[rd], t0);
7a387fff
TS
2478 opn = "dclz";
2479 break;
2480#endif
6af0bf9c 2481 }
2abf314d 2482 (void)opn; /* avoid a compiler warning */
6af0bf9c 2483 MIPS_DEBUG("%s %s, %s", opn, regnames[rd], regnames[rs]);
6c5c1e20 2484 tcg_temp_free(t0);
6af0bf9c
FB
2485}
2486
161f85e6 2487/* Godson integer instructions */
bd277fa1
RH
2488static void gen_loongson_integer(DisasContext *ctx, uint32_t opc,
2489 int rd, int rs, int rt)
161f85e6
AJ
2490{
2491 const char *opn = "loongson";
2492 TCGv t0, t1;
2493
2494 if (rd == 0) {
2495 /* Treat as NOP. */
2496 MIPS_DEBUG("NOP");
2497 return;
2498 }
2499
2500 switch (opc) {
2501 case OPC_MULT_G_2E:
2502 case OPC_MULT_G_2F:
2503 case OPC_MULTU_G_2E:
2504 case OPC_MULTU_G_2F:
2505#if defined(TARGET_MIPS64)
2506 case OPC_DMULT_G_2E:
2507 case OPC_DMULT_G_2F:
2508 case OPC_DMULTU_G_2E:
2509 case OPC_DMULTU_G_2F:
2510#endif
2511 t0 = tcg_temp_new();
2512 t1 = tcg_temp_new();
2513 break;
2514 default:
2515 t0 = tcg_temp_local_new();
2516 t1 = tcg_temp_local_new();
2517 break;
2518 }
2519
2520 gen_load_gpr(t0, rs);
2521 gen_load_gpr(t1, rt);
2522
2523 switch (opc) {
2524 case OPC_MULT_G_2E:
2525 case OPC_MULT_G_2F:
2526 tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
2527 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
2528 opn = "mult.g";
2529 break;
2530 case OPC_MULTU_G_2E:
2531 case OPC_MULTU_G_2F:
2532 tcg_gen_ext32u_tl(t0, t0);
2533 tcg_gen_ext32u_tl(t1, t1);
2534 tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
2535 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
2536 opn = "multu.g";
2537 break;
2538 case OPC_DIV_G_2E:
2539 case OPC_DIV_G_2F:
2540 {
2541 int l1 = gen_new_label();
2542 int l2 = gen_new_label();
2543 int l3 = gen_new_label();
2544 tcg_gen_ext32s_tl(t0, t0);
2545 tcg_gen_ext32s_tl(t1, t1);
2546 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
2547 tcg_gen_movi_tl(cpu_gpr[rd], 0);
2548 tcg_gen_br(l3);
2549 gen_set_label(l1);
2550 tcg_gen_brcondi_tl(TCG_COND_NE, t0, INT_MIN, l2);
2551 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1, l2);
2552 tcg_gen_mov_tl(cpu_gpr[rd], t0);
2553 tcg_gen_br(l3);
2554 gen_set_label(l2);
2555 tcg_gen_div_tl(cpu_gpr[rd], t0, t1);
2556 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
2557 gen_set_label(l3);
2558 }
2559 opn = "div.g";
2560 break;
2561 case OPC_DIVU_G_2E:
2562 case OPC_DIVU_G_2F:
2563 {
2564 int l1 = gen_new_label();
2565 int l2 = gen_new_label();
2566 tcg_gen_ext32u_tl(t0, t0);
2567 tcg_gen_ext32u_tl(t1, t1);
2568 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
2569 tcg_gen_movi_tl(cpu_gpr[rd], 0);
2570 tcg_gen_br(l2);
2571 gen_set_label(l1);
2572 tcg_gen_divu_tl(cpu_gpr[rd], t0, t1);
2573 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
2574 gen_set_label(l2);
2575 }
2576 opn = "divu.g";
2577 break;
2578 case OPC_MOD_G_2E:
2579 case OPC_MOD_G_2F:
2580 {
2581 int l1 = gen_new_label();
2582 int l2 = gen_new_label();
2583 int l3 = gen_new_label();
2584 tcg_gen_ext32u_tl(t0, t0);
2585 tcg_gen_ext32u_tl(t1, t1);
2586 tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
2587 tcg_gen_brcondi_tl(TCG_COND_NE, t0, INT_MIN, l2);
2588 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1, l2);
2589 gen_set_label(l1);
2590 tcg_gen_movi_tl(cpu_gpr[rd], 0);
2591 tcg_gen_br(l3);
2592 gen_set_label(l2);
2593 tcg_gen_rem_tl(cpu_gpr[rd], t0, t1);
2594 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
2595 gen_set_label(l3);
2596 }
2597 opn = "mod.g";
2598 break;
2599 case OPC_MODU_G_2E:
2600 case OPC_MODU_G_2F:
2601 {
2602 int l1 = gen_new_label();
2603 int l2 = gen_new_label();
2604 tcg_gen_ext32u_tl(t0, t0);
2605 tcg_gen_ext32u_tl(t1, t1);
2606 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
2607 tcg_gen_movi_tl(cpu_gpr[rd], 0);
2608 tcg_gen_br(l2);
2609 gen_set_label(l1);
2610 tcg_gen_remu_tl(cpu_gpr[rd], t0, t1);
2611 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
2612 gen_set_label(l2);
2613 }
2614 opn = "modu.g";
2615 break;
2616#if defined(TARGET_MIPS64)
2617 case OPC_DMULT_G_2E:
2618 case OPC_DMULT_G_2F:
2619 tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
2620 opn = "dmult.g";
2621 break;
2622 case OPC_DMULTU_G_2E:
2623 case OPC_DMULTU_G_2F:
2624 tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
2625 opn = "dmultu.g";
2626 break;
2627 case OPC_DDIV_G_2E:
2628 case OPC_DDIV_G_2F:
2629 {
2630 int l1 = gen_new_label();
2631 int l2 = gen_new_label();
2632 int l3 = gen_new_label();
2633 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
2634 tcg_gen_movi_tl(cpu_gpr[rd], 0);
2635 tcg_gen_br(l3);
2636 gen_set_label(l1);
2637 tcg_gen_brcondi_tl(TCG_COND_NE, t0, -1LL << 63, l2);
2638 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1LL, l2);
2639 tcg_gen_mov_tl(cpu_gpr[rd], t0);
2640 tcg_gen_br(l3);
2641 gen_set_label(l2);
2642 tcg_gen_div_tl(cpu_gpr[rd], t0, t1);
2643 gen_set_label(l3);
2644 }
2645 opn = "ddiv.g";
2646 break;
2647 case OPC_DDIVU_G_2E:
2648 case OPC_DDIVU_G_2F:
2649 {
2650 int l1 = gen_new_label();
2651 int l2 = gen_new_label();
2652 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
2653 tcg_gen_movi_tl(cpu_gpr[rd], 0);
2654 tcg_gen_br(l2);
2655 gen_set_label(l1);
2656 tcg_gen_divu_tl(cpu_gpr[rd], t0, t1);
2657 gen_set_label(l2);
2658 }
2659 opn = "ddivu.g";
2660 break;
2661 case OPC_DMOD_G_2E:
2662 case OPC_DMOD_G_2F:
2663 {
2664 int l1 = gen_new_label();
2665 int l2 = gen_new_label();
2666 int l3 = gen_new_label();
2667 tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
2668 tcg_gen_brcondi_tl(TCG_COND_NE, t0, -1LL << 63, l2);
2669 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1LL, l2);
2670 gen_set_label(l1);
2671 tcg_gen_movi_tl(cpu_gpr[rd], 0);
2672 tcg_gen_br(l3);
2673 gen_set_label(l2);
2674 tcg_gen_rem_tl(cpu_gpr[rd], t0, t1);
2675 gen_set_label(l3);
2676 }
2677 opn = "dmod.g";
2678 break;
2679 case OPC_DMODU_G_2E:
2680 case OPC_DMODU_G_2F:
2681 {
2682 int l1 = gen_new_label();
2683 int l2 = gen_new_label();
2684 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
2685 tcg_gen_movi_tl(cpu_gpr[rd], 0);
2686 tcg_gen_br(l2);
2687 gen_set_label(l1);
2688 tcg_gen_remu_tl(cpu_gpr[rd], t0, t1);
2689 gen_set_label(l2);
2690 }
2691 opn = "dmodu.g";
2692 break;
2693#endif
2694 }
2695
2abf314d 2696 (void)opn; /* avoid a compiler warning */
161f85e6
AJ
2697 MIPS_DEBUG("%s %s, %s", opn, regnames[rd], regnames[rs]);
2698 tcg_temp_free(t0);
2699 tcg_temp_free(t1);
2700}
2701
bd277fa1
RH
2702/* Loongson multimedia instructions */
2703static void gen_loongson_multimedia(DisasContext *ctx, int rd, int rs, int rt)
2704{
2705 const char *opn = "loongson_cp2";
2706 uint32_t opc, shift_max;
2707 TCGv_i64 t0, t1;
2708
2709 opc = MASK_LMI(ctx->opcode);
2710 switch (opc) {
2711 case OPC_ADD_CP2:
2712 case OPC_SUB_CP2:
2713 case OPC_DADD_CP2:
2714 case OPC_DSUB_CP2:
2715 t0 = tcg_temp_local_new_i64();
2716 t1 = tcg_temp_local_new_i64();
2717 break;
2718 default:
2719 t0 = tcg_temp_new_i64();
2720 t1 = tcg_temp_new_i64();
2721 break;
2722 }
2723
2724 gen_load_fpr64(ctx, t0, rs);
2725 gen_load_fpr64(ctx, t1, rt);
2726
2727#define LMI_HELPER(UP, LO) \
2728 case OPC_##UP: gen_helper_##LO(t0, t0, t1); opn = #LO; break
2729#define LMI_HELPER_1(UP, LO) \
2730 case OPC_##UP: gen_helper_##LO(t0, t0); opn = #LO; break
2731#define LMI_DIRECT(UP, LO, OP) \
2732 case OPC_##UP: tcg_gen_##OP##_i64(t0, t0, t1); opn = #LO; break
2733
2734 switch (opc) {
2735 LMI_HELPER(PADDSH, paddsh);
2736 LMI_HELPER(PADDUSH, paddush);
2737 LMI_HELPER(PADDH, paddh);
2738 LMI_HELPER(PADDW, paddw);
2739 LMI_HELPER(PADDSB, paddsb);
2740 LMI_HELPER(PADDUSB, paddusb);
2741 LMI_HELPER(PADDB, paddb);
2742
2743 LMI_HELPER(PSUBSH, psubsh);
2744 LMI_HELPER(PSUBUSH, psubush);
2745 LMI_HELPER(PSUBH, psubh);
2746 LMI_HELPER(PSUBW, psubw);
2747 LMI_HELPER(PSUBSB, psubsb);
2748 LMI_HELPER(PSUBUSB, psubusb);
2749 LMI_HELPER(PSUBB, psubb);
2750
2751 LMI_HELPER(PSHUFH, pshufh);
2752 LMI_HELPER(PACKSSWH, packsswh);
2753 LMI_HELPER(PACKSSHB, packsshb);
2754 LMI_HELPER(PACKUSHB, packushb);
2755
2756 LMI_HELPER(PUNPCKLHW, punpcklhw);
2757 LMI_HELPER(PUNPCKHHW, punpckhhw);
2758 LMI_HELPER(PUNPCKLBH, punpcklbh);
2759 LMI_HELPER(PUNPCKHBH, punpckhbh);
2760 LMI_HELPER(PUNPCKLWD, punpcklwd);
2761 LMI_HELPER(PUNPCKHWD, punpckhwd);
2762
2763 LMI_HELPER(PAVGH, pavgh);
2764 LMI_HELPER(PAVGB, pavgb);
2765 LMI_HELPER(PMAXSH, pmaxsh);
2766 LMI_HELPER(PMINSH, pminsh);
2767 LMI_HELPER(PMAXUB, pmaxub);
2768 LMI_HELPER(PMINUB, pminub);
2769
2770 LMI_HELPER(PCMPEQW, pcmpeqw);
2771 LMI_HELPER(PCMPGTW, pcmpgtw);
2772 LMI_HELPER(PCMPEQH, pcmpeqh);
2773 LMI_HELPER(PCMPGTH, pcmpgth);
2774 LMI_HELPER(PCMPEQB, pcmpeqb);
2775 LMI_HELPER(PCMPGTB, pcmpgtb);
2776
2777 LMI_HELPER(PSLLW, psllw);
2778 LMI_HELPER(PSLLH, psllh);
2779 LMI_HELPER(PSRLW, psrlw);
2780 LMI_HELPER(PSRLH, psrlh);
2781 LMI_HELPER(PSRAW, psraw);
2782 LMI_HELPER(PSRAH, psrah);
2783
2784 LMI_HELPER(PMULLH, pmullh);
2785 LMI_HELPER(PMULHH, pmulhh);
2786 LMI_HELPER(PMULHUH, pmulhuh);
2787 LMI_HELPER(PMADDHW, pmaddhw);
2788
2789 LMI_HELPER(PASUBUB, pasubub);
2790 LMI_HELPER_1(BIADD, biadd);
2791 LMI_HELPER_1(PMOVMSKB, pmovmskb);
2792
2793 LMI_DIRECT(PADDD, paddd, add);
2794 LMI_DIRECT(PSUBD, psubd, sub);
2795 LMI_DIRECT(XOR_CP2, xor, xor);
2796 LMI_DIRECT(NOR_CP2, nor, nor);
2797 LMI_DIRECT(AND_CP2, and, and);
2798 LMI_DIRECT(PANDN, pandn, andc);
2799 LMI_DIRECT(OR, or, or);
2800
2801 case OPC_PINSRH_0:
2802 tcg_gen_deposit_i64(t0, t0, t1, 0, 16);
2803 opn = "pinsrh_0";
2804 break;
2805 case OPC_PINSRH_1:
2806 tcg_gen_deposit_i64(t0, t0, t1, 16, 16);
2807 opn = "pinsrh_1";
2808 break;
2809 case OPC_PINSRH_2:
2810 tcg_gen_deposit_i64(t0, t0, t1, 32, 16);
2811 opn = "pinsrh_2";
2812 break;
2813 case OPC_PINSRH_3:
2814 tcg_gen_deposit_i64(t0, t0, t1, 48, 16);
2815 opn = "pinsrh_3";
2816 break;
2817
2818 case OPC_PEXTRH:
2819 tcg_gen_andi_i64(t1, t1, 3);
2820 tcg_gen_shli_i64(t1, t1, 4);
2821 tcg_gen_shr_i64(t0, t0, t1);
2822 tcg_gen_ext16u_i64(t0, t0);
2823 opn = "pextrh";
2824 break;
2825
2826 case OPC_ADDU_CP2:
2827 tcg_gen_add_i64(t0, t0, t1);
2828 tcg_gen_ext32s_i64(t0, t0);
2829 opn = "addu";
2830 break;
2831 case OPC_SUBU_CP2:
2832 tcg_gen_sub_i64(t0, t0, t1);
2833 tcg_gen_ext32s_i64(t0, t0);
2834 opn = "addu";
2835 break;
2836
2837 case OPC_SLL_CP2:
2838 opn = "sll";
2839 shift_max = 32;
2840 goto do_shift;
2841 case OPC_SRL_CP2:
2842 opn = "srl";
2843 shift_max = 32;
2844 goto do_shift;
2845 case OPC_SRA_CP2:
2846 opn = "sra";
2847 shift_max = 32;
2848 goto do_shift;
2849 case OPC_DSLL_CP2:
2850 opn = "dsll";
2851 shift_max = 64;
2852 goto do_shift;
2853 case OPC_DSRL_CP2:
2854 opn = "dsrl";
2855 shift_max = 64;
2856 goto do_shift;
2857 case OPC_DSRA_CP2:
2858 opn = "dsra";
2859 shift_max = 64;
2860 goto do_shift;
2861 do_shift:
2862 /* Make sure shift count isn't TCG undefined behaviour. */
2863 tcg_gen_andi_i64(t1, t1, shift_max - 1);
2864
2865 switch (opc) {
2866 case OPC_SLL_CP2:
2867 case OPC_DSLL_CP2:
2868 tcg_gen_shl_i64(t0, t0, t1);
2869 break;
2870 case OPC_SRA_CP2:
2871 case OPC_DSRA_CP2:
2872 /* Since SRA is UndefinedResult without sign-extended inputs,
2873 we can treat SRA and DSRA the same. */
2874 tcg_gen_sar_i64(t0, t0, t1);
2875 break;
2876 case OPC_SRL_CP2:
2877 /* We want to shift in zeros for SRL; zero-extend first. */
2878 tcg_gen_ext32u_i64(t0, t0);
2879 /* FALLTHRU */
2880 case OPC_DSRL_CP2:
2881 tcg_gen_shr_i64(t0, t0, t1);
2882 break;
2883 }
2884
2885 if (shift_max == 32) {
2886 tcg_gen_ext32s_i64(t0, t0);
2887 }
2888
2889 /* Shifts larger than MAX produce zero. */
2890 tcg_gen_setcondi_i64(TCG_COND_LTU, t1, t1, shift_max);
2891 tcg_gen_neg_i64(t1, t1);
2892 tcg_gen_and_i64(t0, t0, t1);
2893 break;
2894
2895 case OPC_ADD_CP2:
2896 case OPC_DADD_CP2:
2897 {
2898 TCGv_i64 t2 = tcg_temp_new_i64();
2899 int lab = gen_new_label();
2900
2901 tcg_gen_mov_i64(t2, t0);
2902 tcg_gen_add_i64(t0, t1, t2);
2903 if (opc == OPC_ADD_CP2) {
2904 tcg_gen_ext32s_i64(t0, t0);
2905 }
2906 tcg_gen_xor_i64(t1, t1, t2);
2907 tcg_gen_xor_i64(t2, t2, t0);
2908 tcg_gen_andc_i64(t1, t2, t1);
2909 tcg_temp_free_i64(t2);
2910 tcg_gen_brcondi_i64(TCG_COND_GE, t1, 0, lab);
2911 generate_exception(ctx, EXCP_OVERFLOW);
2912 gen_set_label(lab);
2913
2914 opn = (opc == OPC_ADD_CP2 ? "add" : "dadd");
2915 break;
2916 }
2917
2918 case OPC_SUB_CP2:
2919 case OPC_DSUB_CP2:
2920 {
2921 TCGv_i64 t2 = tcg_temp_new_i64();
2922 int lab = gen_new_label();
2923
2924 tcg_gen_mov_i64(t2, t0);
2925 tcg_gen_sub_i64(t0, t1, t2);
2926 if (opc == OPC_SUB_CP2) {
2927 tcg_gen_ext32s_i64(t0, t0);
2928 }
2929 tcg_gen_xor_i64(t1, t1, t2);
2930 tcg_gen_xor_i64(t2, t2, t0);
2931 tcg_gen_and_i64(t1, t1, t2);
2932 tcg_temp_free_i64(t2);
2933 tcg_gen_brcondi_i64(TCG_COND_GE, t1, 0, lab);
2934 generate_exception(ctx, EXCP_OVERFLOW);
2935 gen_set_label(lab);
2936
2937 opn = (opc == OPC_SUB_CP2 ? "sub" : "dsub");
2938 break;
2939 }
2940
2941 case OPC_PMULUW:
2942 tcg_gen_ext32u_i64(t0, t0);
2943 tcg_gen_ext32u_i64(t1, t1);
2944 tcg_gen_mul_i64(t0, t0, t1);
2945 opn = "pmuluw";
2946 break;
2947
2948 case OPC_SEQU_CP2:
2949 case OPC_SEQ_CP2:
2950 case OPC_SLTU_CP2:
2951 case OPC_SLT_CP2:
2952 case OPC_SLEU_CP2:
2953 case OPC_SLE_CP2:
2954 /* ??? Document is unclear: Set FCC[CC]. Does that mean the
2955 FD field is the CC field? */
2956 default:
2957 MIPS_INVAL(opn);
2958 generate_exception(ctx, EXCP_RI);
2959 return;
2960 }
2961
2962#undef LMI_HELPER
2963#undef LMI_DIRECT
2964
2965 gen_store_fpr64(ctx, t0, rd);
2966
2967 (void)opn; /* avoid a compiler warning */
2968 MIPS_DEBUG("%s %s, %s, %s", opn,
2969 fregnames[rd], fregnames[rs], fregnames[rt]);
2970 tcg_temp_free_i64(t0);
2971 tcg_temp_free_i64(t1);
2972}
2973
6af0bf9c 2974/* Traps */
7a387fff 2975static void gen_trap (DisasContext *ctx, uint32_t opc,
6af0bf9c
FB
2976 int rs, int rt, int16_t imm)
2977{
2978 int cond;
cdc0faa6 2979 TCGv t0 = tcg_temp_new();
1ba74fb8 2980 TCGv t1 = tcg_temp_new();
6af0bf9c
FB
2981
2982 cond = 0;
2983 /* Load needed operands */
2984 switch (opc) {
2985 case OPC_TEQ:
2986 case OPC_TGE:
2987 case OPC_TGEU:
2988 case OPC_TLT:
2989 case OPC_TLTU:
2990 case OPC_TNE:
2991 /* Compare two registers */
2992 if (rs != rt) {
be24bb4f
TS
2993 gen_load_gpr(t0, rs);
2994 gen_load_gpr(t1, rt);
6af0bf9c
FB
2995 cond = 1;
2996 }
179e32bb 2997 break;
6af0bf9c
FB
2998 case OPC_TEQI:
2999 case OPC_TGEI:
3000 case OPC_TGEIU:
3001 case OPC_TLTI:
3002 case OPC_TLTIU:
3003 case OPC_TNEI:
3004 /* Compare register to immediate */
3005 if (rs != 0 || imm != 0) {
be24bb4f
TS
3006 gen_load_gpr(t0, rs);
3007 tcg_gen_movi_tl(t1, (int32_t)imm);
6af0bf9c
FB
3008 cond = 1;
3009 }
3010 break;
3011 }
3012 if (cond == 0) {
3013 switch (opc) {
3014 case OPC_TEQ: /* rs == rs */
3015 case OPC_TEQI: /* r0 == 0 */
3016 case OPC_TGE: /* rs >= rs */
3017 case OPC_TGEI: /* r0 >= 0 */
3018 case OPC_TGEU: /* rs >= rs unsigned */
3019 case OPC_TGEIU: /* r0 >= 0 unsigned */
3020 /* Always trap */
cdc0faa6 3021 generate_exception(ctx, EXCP_TRAP);
6af0bf9c
FB
3022 break;
3023 case OPC_TLT: /* rs < rs */
3024 case OPC_TLTI: /* r0 < 0 */
3025 case OPC_TLTU: /* rs < rs unsigned */
3026 case OPC_TLTIU: /* r0 < 0 unsigned */
3027 case OPC_TNE: /* rs != rs */
3028 case OPC_TNEI: /* r0 != 0 */
ead9360e 3029 /* Never trap: treat as NOP. */
cdc0faa6 3030 break;
6af0bf9c
FB
3031 }
3032 } else {
cdc0faa6
AJ
3033 int l1 = gen_new_label();
3034
6af0bf9c
FB
3035 switch (opc) {
3036 case OPC_TEQ:
3037 case OPC_TEQI:
cdc0faa6 3038 tcg_gen_brcond_tl(TCG_COND_NE, t0, t1, l1);
6af0bf9c
FB
3039 break;
3040 case OPC_TGE:
3041 case OPC_TGEI:
cdc0faa6 3042 tcg_gen_brcond_tl(TCG_COND_LT, t0, t1, l1);
6af0bf9c
FB
3043 break;
3044 case OPC_TGEU:
3045 case OPC_TGEIU:
cdc0faa6 3046 tcg_gen_brcond_tl(TCG_COND_LTU, t0, t1, l1);
6af0bf9c
FB
3047 break;
3048 case OPC_TLT:
3049 case OPC_TLTI:
cdc0faa6 3050 tcg_gen_brcond_tl(TCG_COND_GE, t0, t1, l1);
6af0bf9c
FB
3051 break;
3052 case OPC_TLTU:
3053 case OPC_TLTIU:
cdc0faa6 3054 tcg_gen_brcond_tl(TCG_COND_GEU, t0, t1, l1);
6af0bf9c
FB
3055 break;
3056 case OPC_TNE:
3057 case OPC_TNEI:
cdc0faa6 3058 tcg_gen_brcond_tl(TCG_COND_EQ, t0, t1, l1);
6af0bf9c 3059 break;
6af0bf9c 3060 }
cdc0faa6 3061 generate_exception(ctx, EXCP_TRAP);
08ba7963
TS
3062 gen_set_label(l1);
3063 }
be24bb4f
TS
3064 tcg_temp_free(t0);
3065 tcg_temp_free(t1);
6af0bf9c
FB
3066}
3067
356265ae 3068static inline void gen_goto_tb(DisasContext *ctx, int n, target_ulong dest)
c53be334 3069{
6e256c93
FB
3070 TranslationBlock *tb;
3071 tb = ctx->tb;
7b270ef2
NF
3072 if ((tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK) &&
3073 likely(!ctx->singlestep_enabled)) {
57fec1fe 3074 tcg_gen_goto_tb(n);
9b9e4393 3075 gen_save_pc(dest);
4b4a72e5 3076 tcg_gen_exit_tb((tcg_target_long)tb + n);
6e256c93 3077 } else {
9b9e4393 3078 gen_save_pc(dest);
7b270ef2
NF
3079 if (ctx->singlestep_enabled) {
3080 save_cpu_state(ctx, 0);
895c2d04 3081 gen_helper_0e0i(raise_exception, EXCP_DEBUG);
7b270ef2 3082 }
57fec1fe 3083 tcg_gen_exit_tb(0);
6e256c93 3084 }
c53be334
FB
3085}
3086
6af0bf9c 3087/* Branches (before delay slot) */
7a387fff 3088static void gen_compute_branch (DisasContext *ctx, uint32_t opc,
7dca4ad0 3089 int insn_bytes,
6af0bf9c
FB
3090 int rs, int rt, int32_t offset)
3091{
d077b6f7 3092 target_ulong btgt = -1;
3ad4bb2d 3093 int blink = 0;
2fdbad25 3094 int bcond_compute = 0;
1ba74fb8
AJ
3095 TCGv t0 = tcg_temp_new();
3096 TCGv t1 = tcg_temp_new();
3ad4bb2d
TS
3097
3098 if (ctx->hflags & MIPS_HFLAG_BMASK) {
923617a3 3099#ifdef MIPS_DEBUG_DISAS
d12d51d5 3100 LOG_DISAS("Branch in delay slot at PC 0x" TARGET_FMT_lx "\n", ctx->pc);
923617a3 3101#endif
3ad4bb2d 3102 generate_exception(ctx, EXCP_RI);
6c5c1e20 3103 goto out;
3ad4bb2d 3104 }
6af0bf9c 3105
6af0bf9c
FB
3106 /* Load needed operands */
3107 switch (opc) {
3108 case OPC_BEQ:
3109 case OPC_BEQL:
3110 case OPC_BNE:
3111 case OPC_BNEL:
3112 /* Compare two registers */
3113 if (rs != rt) {
6c5c1e20
TS
3114 gen_load_gpr(t0, rs);
3115 gen_load_gpr(t1, rt);
2fdbad25 3116 bcond_compute = 1;
6af0bf9c 3117 }
7dca4ad0 3118 btgt = ctx->pc + insn_bytes + offset;
6af0bf9c
FB
3119 break;
3120 case OPC_BGEZ:
3121 case OPC_BGEZAL:
3c824109 3122 case OPC_BGEZALS:
6af0bf9c
FB
3123 case OPC_BGEZALL:
3124 case OPC_BGEZL:
3125 case OPC_BGTZ:
3126 case OPC_BGTZL:
3127 case OPC_BLEZ:
3128 case OPC_BLEZL:
3129 case OPC_BLTZ:
3130 case OPC_BLTZAL:
3c824109 3131 case OPC_BLTZALS:
6af0bf9c
FB
3132 case OPC_BLTZALL:
3133 case OPC_BLTZL:
3134 /* Compare to zero */
3135 if (rs != 0) {
6c5c1e20 3136 gen_load_gpr(t0, rs);
2fdbad25 3137 bcond_compute = 1;
6af0bf9c 3138 }
7dca4ad0 3139 btgt = ctx->pc + insn_bytes + offset;
6af0bf9c
FB
3140 break;
3141 case OPC_J:
3142 case OPC_JAL:
364d4831 3143 case OPC_JALX:
620e48f6
NF
3144 case OPC_JALS:
3145 case OPC_JALXS:
6af0bf9c 3146 /* Jump to immediate */
7dca4ad0 3147 btgt = ((ctx->pc + insn_bytes) & (int32_t)0xF0000000) | (uint32_t)offset;
6af0bf9c
FB
3148 break;
3149 case OPC_JR:
3150 case OPC_JALR:
364d4831 3151 case OPC_JALRC:
620e48f6 3152 case OPC_JALRS:
6af0bf9c 3153 /* Jump to register */
7a387fff
TS
3154 if (offset != 0 && offset != 16) {
3155 /* Hint = 0 is JR/JALR, hint 16 is JR.HB/JALR.HB, the
cbeb0857 3156 others are reserved. */
923617a3 3157 MIPS_INVAL("jump hint");
6af0bf9c 3158 generate_exception(ctx, EXCP_RI);
6c5c1e20 3159 goto out;
6af0bf9c 3160 }
d077b6f7 3161 gen_load_gpr(btarget, rs);
6af0bf9c
FB
3162 break;
3163 default:
3164 MIPS_INVAL("branch/jump");
3165 generate_exception(ctx, EXCP_RI);
6c5c1e20 3166 goto out;
6af0bf9c 3167 }
2fdbad25 3168 if (bcond_compute == 0) {
6af0bf9c
FB
3169 /* No condition to be computed */
3170 switch (opc) {
3171 case OPC_BEQ: /* rx == rx */
3172 case OPC_BEQL: /* rx == rx likely */
3173 case OPC_BGEZ: /* 0 >= 0 */
3174 case OPC_BGEZL: /* 0 >= 0 likely */
3175 case OPC_BLEZ: /* 0 <= 0 */
3176 case OPC_BLEZL: /* 0 <= 0 likely */
3177 /* Always take */
4ad40f36 3178 ctx->hflags |= MIPS_HFLAG_B;
6af0bf9c
FB
3179 MIPS_DEBUG("balways");
3180 break;
3c824109 3181 case OPC_BGEZALS:
6af0bf9c
FB
3182 case OPC_BGEZAL: /* 0 >= 0 */
3183 case OPC_BGEZALL: /* 0 >= 0 likely */
3c824109
NF
3184 ctx->hflags |= (opc == OPC_BGEZALS
3185 ? MIPS_HFLAG_BDS16
3186 : MIPS_HFLAG_BDS32);
6af0bf9c
FB
3187 /* Always take and link */
3188 blink = 31;
4ad40f36 3189 ctx->hflags |= MIPS_HFLAG_B;
6af0bf9c
FB
3190 MIPS_DEBUG("balways and link");
3191 break;
3192 case OPC_BNE: /* rx != rx */
3193 case OPC_BGTZ: /* 0 > 0 */
3194 case OPC_BLTZ: /* 0 < 0 */
ead9360e 3195 /* Treat as NOP. */
6af0bf9c 3196 MIPS_DEBUG("bnever (NOP)");
6c5c1e20 3197 goto out;
3c824109 3198 case OPC_BLTZALS:
eeef26cd 3199 case OPC_BLTZAL: /* 0 < 0 */
3c824109
NF
3200 ctx->hflags |= (opc == OPC_BLTZALS
3201 ? MIPS_HFLAG_BDS16
3202 : MIPS_HFLAG_BDS32);
3203 /* Handle as an unconditional branch to get correct delay
3204 slot checking. */
3205 blink = 31;
3206 btgt = ctx->pc + (opc == OPC_BLTZALS ? 6 : 8);
3207 ctx->hflags |= MIPS_HFLAG_B;
9898128f 3208 MIPS_DEBUG("bnever and link");
3c824109 3209 break;
eeef26cd 3210 case OPC_BLTZALL: /* 0 < 0 likely */
1ba74fb8 3211 tcg_gen_movi_tl(cpu_gpr[31], ctx->pc + 8);
9898128f
TS
3212 /* Skip the instruction in the delay slot */
3213 MIPS_DEBUG("bnever, link and skip");
3214 ctx->pc += 4;
6c5c1e20 3215 goto out;
6af0bf9c
FB
3216 case OPC_BNEL: /* rx != rx likely */
3217 case OPC_BGTZL: /* 0 > 0 likely */
6af0bf9c
FB
3218 case OPC_BLTZL: /* 0 < 0 likely */
3219 /* Skip the instruction in the delay slot */
3220 MIPS_DEBUG("bnever and skip");
9898128f 3221 ctx->pc += 4;
6c5c1e20 3222 goto out;
6af0bf9c 3223 case OPC_J:
4ad40f36 3224 ctx->hflags |= MIPS_HFLAG_B;
d077b6f7 3225 MIPS_DEBUG("j " TARGET_FMT_lx, btgt);
6af0bf9c 3226 break;
620e48f6 3227 case OPC_JALXS:
364d4831
NF
3228 case OPC_JALX:
3229 ctx->hflags |= MIPS_HFLAG_BX;
3230 /* Fallthrough */
620e48f6 3231 case OPC_JALS:
6af0bf9c
FB
3232 case OPC_JAL:
3233 blink = 31;
4ad40f36 3234 ctx->hflags |= MIPS_HFLAG_B;
620e48f6 3235 ctx->hflags |= ((opc == OPC_JALS || opc == OPC_JALXS)
364d4831
NF
3236 ? MIPS_HFLAG_BDS16
3237 : MIPS_HFLAG_BDS32);
d077b6f7 3238 MIPS_DEBUG("jal " TARGET_FMT_lx, btgt);
6af0bf9c
FB
3239 break;
3240 case OPC_JR:
4ad40f36 3241 ctx->hflags |= MIPS_HFLAG_BR;
620e48f6
NF
3242 if (insn_bytes == 4)
3243 ctx->hflags |= MIPS_HFLAG_BDS32;
6af0bf9c
FB
3244 MIPS_DEBUG("jr %s", regnames[rs]);
3245 break;
620e48f6 3246 case OPC_JALRS:
6af0bf9c 3247 case OPC_JALR:
364d4831 3248 case OPC_JALRC:
6af0bf9c 3249 blink = rt;
4ad40f36 3250 ctx->hflags |= MIPS_HFLAG_BR;
620e48f6
NF
3251 ctx->hflags |= (opc == OPC_JALRS
3252 ? MIPS_HFLAG_BDS16
3253 : MIPS_HFLAG_BDS32);
6af0bf9c
FB
3254 MIPS_DEBUG("jalr %s, %s", regnames[rt], regnames[rs]);
3255 break;
3256 default:
3257 MIPS_INVAL("branch/jump");
3258 generate_exception(ctx, EXCP_RI);
6c5c1e20 3259 goto out;
6af0bf9c
FB
3260 }
3261 } else {
3262 switch (opc) {
3263 case OPC_BEQ:
e68dd28f 3264 tcg_gen_setcond_tl(TCG_COND_EQ, bcond, t0, t1);
923617a3 3265 MIPS_DEBUG("beq %s, %s, " TARGET_FMT_lx,
d077b6f7 3266 regnames[rs], regnames[rt], btgt);
6af0bf9c
FB
3267 goto not_likely;
3268 case OPC_BEQL:
e68dd28f 3269 tcg_gen_setcond_tl(TCG_COND_EQ, bcond, t0, t1);
923617a3 3270 MIPS_DEBUG("beql %s, %s, " TARGET_FMT_lx,
d077b6f7 3271 regnames[rs], regnames[rt], btgt);
6af0bf9c
FB
3272 goto likely;
3273 case OPC_BNE:
e68dd28f 3274 tcg_gen_setcond_tl(TCG_COND_NE, bcond, t0, t1);
923617a3 3275 MIPS_DEBUG("bne %s, %s, " TARGET_FMT_lx,
d077b6f7 3276 regnames[rs], regnames[rt], btgt);
6af0bf9c
FB
3277 goto not_likely;
3278 case OPC_BNEL:
e68dd28f 3279 tcg_gen_setcond_tl(TCG_COND_NE, bcond, t0, t1);
923617a3 3280 MIPS_DEBUG("bnel %s, %s, " TARGET_FMT_lx,
d077b6f7 3281 regnames[rs], regnames[rt], btgt);
6af0bf9c
FB
3282 goto likely;
3283 case OPC_BGEZ:
e68dd28f 3284 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
d077b6f7 3285 MIPS_DEBUG("bgez %s, " TARGET_FMT_lx, regnames[rs], btgt);
6af0bf9c
FB
3286 goto not_likely;
3287 case OPC_BGEZL:
e68dd28f 3288 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
d077b6f7 3289 MIPS_DEBUG("bgezl %s, " TARGET_FMT_lx, regnames[rs], btgt);
6af0bf9c 3290 goto likely;
3c824109 3291 case OPC_BGEZALS:
6af0bf9c 3292 case OPC_BGEZAL:
3c824109
NF
3293 ctx->hflags |= (opc == OPC_BGEZALS
3294 ? MIPS_HFLAG_BDS16
3295 : MIPS_HFLAG_BDS32);
e68dd28f 3296 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
d077b6f7 3297 MIPS_DEBUG("bgezal %s, " TARGET_FMT_lx, regnames[rs], btgt);
6af0bf9c
FB
3298 blink = 31;
3299 goto not_likely;
3300 case OPC_BGEZALL:
e68dd28f 3301 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
6af0bf9c 3302 blink = 31;
d077b6f7 3303 MIPS_DEBUG("bgezall %s, " TARGET_FMT_lx, regnames[rs], btgt);
6af0bf9c
FB
3304 goto likely;
3305 case OPC_BGTZ:
e68dd28f 3306 tcg_gen_setcondi_tl(TCG_COND_GT, bcond, t0, 0);
d077b6f7 3307 MIPS_DEBUG("bgtz %s, " TARGET_FMT_lx, regnames[rs], btgt);
6af0bf9c
FB
3308 goto not_likely;
3309 case OPC_BGTZL:
e68dd28f 3310 tcg_gen_setcondi_tl(TCG_COND_GT, bcond, t0, 0);
d077b6f7 3311 MIPS_DEBUG("bgtzl %s, " TARGET_FMT_lx, regnames[rs], btgt);
6af0bf9c
FB
3312 goto likely;
3313 case OPC_BLEZ:
e68dd28f 3314 tcg_gen_setcondi_tl(TCG_COND_LE, bcond, t0, 0);
d077b6f7 3315 MIPS_DEBUG("blez %s, " TARGET_FMT_lx, regnames[rs], btgt);
6af0bf9c
FB
3316 goto not_likely;
3317 case OPC_BLEZL:
e68dd28f 3318 tcg_gen_setcondi_tl(TCG_COND_LE, bcond, t0, 0);
d077b6f7 3319 MIPS_DEBUG("blezl %s, " TARGET_FMT_lx, regnames[rs], btgt);
6af0bf9c
FB
3320 goto likely;
3321 case OPC_BLTZ:
e68dd28f 3322 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
d077b6f7 3323 MIPS_DEBUG("bltz %s, " TARGET_FMT_lx, regnames[rs], btgt);
6af0bf9c
FB
3324 goto not_likely;
3325 case OPC_BLTZL:
e68dd28f 3326 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
d077b6f7 3327 MIPS_DEBUG("bltzl %s, " TARGET_FMT_lx, regnames[rs], btgt);
6af0bf9c 3328 goto likely;
3c824109 3329 case OPC_BLTZALS:
6af0bf9c 3330 case OPC_BLTZAL:
3c824109
NF
3331 ctx->hflags |= (opc == OPC_BLTZALS
3332 ? MIPS_HFLAG_BDS16
3333 : MIPS_HFLAG_BDS32);
e68dd28f 3334 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
6af0bf9c 3335 blink = 31;
d077b6f7 3336 MIPS_DEBUG("bltzal %s, " TARGET_FMT_lx, regnames[rs], btgt);
6af0bf9c 3337 not_likely:
4ad40f36 3338 ctx->hflags |= MIPS_HFLAG_BC;
6af0bf9c
FB
3339 break;
3340 case OPC_BLTZALL:
e68dd28f 3341 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
6af0bf9c 3342 blink = 31;
d077b6f7 3343 MIPS_DEBUG("bltzall %s, " TARGET_FMT_lx, regnames[rs], btgt);
6af0bf9c 3344 likely:
4ad40f36 3345 ctx->hflags |= MIPS_HFLAG_BL;
6af0bf9c 3346 break;
c53f4a62
TS
3347 default:
3348 MIPS_INVAL("conditional branch/jump");
3349 generate_exception(ctx, EXCP_RI);
6c5c1e20 3350 goto out;
6af0bf9c 3351 }
6af0bf9c 3352 }
923617a3 3353 MIPS_DEBUG("enter ds: link %d cond %02x target " TARGET_FMT_lx,
d077b6f7 3354 blink, ctx->hflags, btgt);
9b9e4393 3355
d077b6f7 3356 ctx->btarget = btgt;
6af0bf9c 3357 if (blink > 0) {
364d4831
NF
3358 int post_delay = insn_bytes;
3359 int lowbit = !!(ctx->hflags & MIPS_HFLAG_M16);
3360
3361 if (opc != OPC_JALRC)
3362 post_delay += ((ctx->hflags & MIPS_HFLAG_BDS16) ? 2 : 4);
3363
3364 tcg_gen_movi_tl(cpu_gpr[blink], ctx->pc + post_delay + lowbit);
6af0bf9c 3365 }
6c5c1e20
TS
3366
3367 out:
364d4831
NF
3368 if (insn_bytes == 2)
3369 ctx->hflags |= MIPS_HFLAG_B16;
6c5c1e20
TS
3370 tcg_temp_free(t0);
3371 tcg_temp_free(t1);
6af0bf9c
FB
3372}
3373
7a387fff
TS
3374/* special3 bitfield operations */
3375static void gen_bitops (DisasContext *ctx, uint32_t opc, int rt,
356265ae 3376 int rs, int lsb, int msb)
7a387fff 3377{
a7812ae4
PB
3378 TCGv t0 = tcg_temp_new();
3379 TCGv t1 = tcg_temp_new();
505ad7c2 3380 target_ulong mask;
6c5c1e20
TS
3381
3382 gen_load_gpr(t1, rs);
7a387fff
TS
3383 switch (opc) {
3384 case OPC_EXT:
3385 if (lsb + msb > 31)
3386 goto fail;
505ad7c2
AJ
3387 tcg_gen_shri_tl(t0, t1, lsb);
3388 if (msb != 31) {
3389 tcg_gen_andi_tl(t0, t0, (1 << (msb + 1)) - 1);
3390 } else {
3391 tcg_gen_ext32s_tl(t0, t0);
3392 }
7a387fff 3393 break;
c6d6dd7c 3394#if defined(TARGET_MIPS64)
7a387fff 3395 case OPC_DEXTM:
505ad7c2
AJ
3396 tcg_gen_shri_tl(t0, t1, lsb);
3397 if (msb != 31) {
3398 tcg_gen_andi_tl(t0, t0, (1ULL << (msb + 1 + 32)) - 1);
3399 }
7a387fff
TS
3400 break;
3401 case OPC_DEXTU:
505ad7c2
AJ
3402 tcg_gen_shri_tl(t0, t1, lsb + 32);
3403 tcg_gen_andi_tl(t0, t0, (1ULL << (msb + 1)) - 1);
7a387fff
TS
3404 break;
3405 case OPC_DEXT:
505ad7c2
AJ
3406 tcg_gen_shri_tl(t0, t1, lsb);
3407 tcg_gen_andi_tl(t0, t0, (1ULL << (msb + 1)) - 1);
7a387fff 3408 break;
c6d6dd7c 3409#endif
7a387fff
TS
3410 case OPC_INS:
3411 if (lsb > msb)
3412 goto fail;
505ad7c2 3413 mask = ((msb - lsb + 1 < 32) ? ((1 << (msb - lsb + 1)) - 1) : ~0) << lsb;
6c5c1e20 3414 gen_load_gpr(t0, rt);
505ad7c2
AJ
3415 tcg_gen_andi_tl(t0, t0, ~mask);
3416 tcg_gen_shli_tl(t1, t1, lsb);
3417 tcg_gen_andi_tl(t1, t1, mask);
3418 tcg_gen_or_tl(t0, t0, t1);
3419 tcg_gen_ext32s_tl(t0, t0);
7a387fff 3420 break;
c6d6dd7c 3421#if defined(TARGET_MIPS64)
7a387fff
TS
3422 case OPC_DINSM:
3423 if (lsb > msb)
3424 goto fail;
505ad7c2 3425 mask = ((msb - lsb + 1 + 32 < 64) ? ((1ULL << (msb - lsb + 1 + 32)) - 1) : ~0ULL) << lsb;
6c5c1e20 3426 gen_load_gpr(t0, rt);
505ad7c2
AJ
3427 tcg_gen_andi_tl(t0, t0, ~mask);
3428 tcg_gen_shli_tl(t1, t1, lsb);
3429 tcg_gen_andi_tl(t1, t1, mask);
3430 tcg_gen_or_tl(t0, t0, t1);
7a387fff
TS
3431 break;
3432 case OPC_DINSU:
3433 if (lsb > msb)
3434 goto fail;
6fbab869 3435 mask = ((1ULL << (msb - lsb + 1)) - 1) << (lsb + 32);
6c5c1e20 3436 gen_load_gpr(t0, rt);
505ad7c2
AJ
3437 tcg_gen_andi_tl(t0, t0, ~mask);
3438 tcg_gen_shli_tl(t1, t1, lsb + 32);
3439 tcg_gen_andi_tl(t1, t1, mask);
3440 tcg_gen_or_tl(t0, t0, t1);
7a387fff
TS
3441 break;
3442 case OPC_DINS:
3443 if (lsb > msb)
3444 goto fail;
6c5c1e20 3445 gen_load_gpr(t0, rt);
505ad7c2
AJ
3446 mask = ((1ULL << (msb - lsb + 1)) - 1) << lsb;
3447 gen_load_gpr(t0, rt);
3448 tcg_gen_andi_tl(t0, t0, ~mask);
3449 tcg_gen_shli_tl(t1, t1, lsb);
3450 tcg_gen_andi_tl(t1, t1, mask);
3451 tcg_gen_or_tl(t0, t0, t1);
7a387fff 3452 break;
c6d6dd7c 3453#endif
7a387fff
TS
3454 default:
3455fail:
3456 MIPS_INVAL("bitops");
3457 generate_exception(ctx, EXCP_RI);
6c5c1e20
TS
3458 tcg_temp_free(t0);
3459 tcg_temp_free(t1);
7a387fff
TS
3460 return;
3461 }
6c5c1e20
TS
3462 gen_store_gpr(t0, rt);
3463 tcg_temp_free(t0);
3464 tcg_temp_free(t1);
7a387fff
TS
3465}
3466
49bcf33c
AJ
3467static void gen_bshfl (DisasContext *ctx, uint32_t op2, int rt, int rd)
3468{
3a55fa47 3469 TCGv t0;
49bcf33c 3470
3a55fa47
AJ
3471 if (rd == 0) {
3472 /* If no destination, treat it as a NOP. */
3473 MIPS_DEBUG("NOP");
3474 return;
3475 }
3476
3477 t0 = tcg_temp_new();
3478 gen_load_gpr(t0, rt);
49bcf33c
AJ
3479 switch (op2) {
3480 case OPC_WSBH:
3a55fa47
AJ
3481 {
3482 TCGv t1 = tcg_temp_new();
3483
3484 tcg_gen_shri_tl(t1, t0, 8);
3485 tcg_gen_andi_tl(t1, t1, 0x00FF00FF);
3486 tcg_gen_shli_tl(t0, t0, 8);
3487 tcg_gen_andi_tl(t0, t0, ~0x00FF00FF);
3488 tcg_gen_or_tl(t0, t0, t1);
3489 tcg_temp_free(t1);
3490 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
3491 }
49bcf33c
AJ
3492 break;
3493 case OPC_SEB:
3a55fa47 3494 tcg_gen_ext8s_tl(cpu_gpr[rd], t0);
49bcf33c
AJ
3495 break;
3496 case OPC_SEH:
3a55fa47 3497 tcg_gen_ext16s_tl(cpu_gpr[rd], t0);
49bcf33c
AJ
3498 break;
3499#if defined(TARGET_MIPS64)
3500 case OPC_DSBH:
3a55fa47
AJ
3501 {
3502 TCGv t1 = tcg_temp_new();
3503
3504 tcg_gen_shri_tl(t1, t0, 8);
3505 tcg_gen_andi_tl(t1, t1, 0x00FF00FF00FF00FFULL);
3506 tcg_gen_shli_tl(t0, t0, 8);
3507 tcg_gen_andi_tl(t0, t0, ~0x00FF00FF00FF00FFULL);
3508 tcg_gen_or_tl(cpu_gpr[rd], t0, t1);
3509 tcg_temp_free(t1);
3510 }
49bcf33c
AJ
3511 break;
3512 case OPC_DSHD:
3a55fa47
AJ
3513 {
3514 TCGv t1 = tcg_temp_new();
3515
3516 tcg_gen_shri_tl(t1, t0, 16);
3517 tcg_gen_andi_tl(t1, t1, 0x0000FFFF0000FFFFULL);
3518 tcg_gen_shli_tl(t0, t0, 16);
3519 tcg_gen_andi_tl(t0, t0, ~0x0000FFFF0000FFFFULL);
3520 tcg_gen_or_tl(t0, t0, t1);
3521 tcg_gen_shri_tl(t1, t0, 32);
3522 tcg_gen_shli_tl(t0, t0, 32);
3523 tcg_gen_or_tl(cpu_gpr[rd], t0, t1);
3524 tcg_temp_free(t1);
3525 }
49bcf33c
AJ
3526 break;
3527#endif
3528 default:
3529 MIPS_INVAL("bsfhl");
3530 generate_exception(ctx, EXCP_RI);
3531 tcg_temp_free(t0);
49bcf33c
AJ
3532 return;
3533 }
49bcf33c 3534 tcg_temp_free(t0);
49bcf33c
AJ
3535}
3536
f1aa6320 3537#ifndef CONFIG_USER_ONLY
0eaef5aa 3538/* CP0 (MMU and control) */
d9bea114 3539static inline void gen_mfc0_load32 (TCGv arg, target_ulong off)
4f57689a 3540{
d9bea114 3541 TCGv_i32 t0 = tcg_temp_new_i32();
4f57689a 3542
d9bea114
AJ
3543 tcg_gen_ld_i32(t0, cpu_env, off);
3544 tcg_gen_ext_i32_tl(arg, t0);
3545 tcg_temp_free_i32(t0);
4f57689a
TS
3546}
3547
d9bea114 3548static inline void gen_mfc0_load64 (TCGv arg, target_ulong off)
4f57689a 3549{
d9bea114
AJ
3550 tcg_gen_ld_tl(arg, cpu_env, off);
3551 tcg_gen_ext32s_tl(arg, arg);
4f57689a
TS
3552}
3553
d9bea114 3554static inline void gen_mtc0_store32 (TCGv arg, target_ulong off)
f1aa6320 3555{
d9bea114 3556 TCGv_i32 t0 = tcg_temp_new_i32();
f1aa6320 3557
d9bea114
AJ
3558 tcg_gen_trunc_tl_i32(t0, arg);
3559 tcg_gen_st_i32(t0, cpu_env, off);
3560 tcg_temp_free_i32(t0);
f1aa6320
TS
3561}
3562
d9bea114 3563static inline void gen_mtc0_store64 (TCGv arg, target_ulong off)
f1aa6320 3564{
d9bea114
AJ
3565 tcg_gen_ext32s_tl(arg, arg);
3566 tcg_gen_st_tl(arg, cpu_env, off);
f1aa6320
TS
3567}
3568
7db13fae 3569static void gen_mfc0 (CPUMIPSState *env, DisasContext *ctx, TCGv arg, int reg, int sel)
873eb012 3570{
7a387fff 3571 const char *rn = "invalid";
873eb012 3572
e189e748
TS
3573 if (sel != 0)
3574 check_insn(env, ctx, ISA_MIPS32);
3575
873eb012
TS
3576 switch (reg) {
3577 case 0:
7a387fff
TS
3578 switch (sel) {
3579 case 0:
7db13fae 3580 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Index));
7a387fff
TS
3581 rn = "Index";
3582 break;
3583 case 1:
7385ac0b 3584 check_insn(env, ctx, ASE_MT);
895c2d04 3585 gen_helper_mfc0_mvpcontrol(arg, cpu_env);
7a387fff 3586 rn = "MVPControl";
ead9360e 3587 break;
7a387fff 3588 case 2:
7385ac0b 3589 check_insn(env, ctx, ASE_MT);
895c2d04 3590 gen_helper_mfc0_mvpconf0(arg, cpu_env);
7a387fff 3591 rn = "MVPConf0";
ead9360e 3592 break;
7a387fff 3593 case 3:
7385ac0b 3594 check_insn(env, ctx, ASE_MT);
895c2d04 3595 gen_helper_mfc0_mvpconf1(arg, cpu_env);
7a387fff 3596 rn = "MVPConf1";
ead9360e 3597 break;
7a387fff
TS
3598 default:
3599 goto die;
3600 }
873eb012
TS
3601 break;
3602 case 1:
7a387fff
TS
3603 switch (sel) {
3604 case 0:
895c2d04 3605 gen_helper_mfc0_random(arg, cpu_env);
7a387fff 3606 rn = "Random";
2423f660 3607 break;
7a387fff 3608 case 1:
7385ac0b 3609 check_insn(env, ctx, ASE_MT);
7db13fae 3610 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEControl));
7a387fff 3611 rn = "VPEControl";
ead9360e 3612 break;
7a387fff 3613 case 2:
7385ac0b 3614 check_insn(env, ctx, ASE_MT);
7db13fae 3615 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf0));
7a387fff 3616 rn = "VPEConf0";
ead9360e 3617 break;
7a387fff 3618 case 3:
7385ac0b 3619 check_insn(env, ctx, ASE_MT);
7db13fae 3620 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf1));
7a387fff 3621 rn = "VPEConf1";
ead9360e 3622 break;
7a387fff 3623 case 4:
7385ac0b 3624 check_insn(env, ctx, ASE_MT);
7db13fae 3625 gen_mfc0_load64(arg, offsetof(CPUMIPSState, CP0_YQMask));
7a387fff 3626 rn = "YQMask";
ead9360e 3627 break;
7a387fff 3628 case 5:
7385ac0b 3629 check_insn(env, ctx, ASE_MT);
7db13fae 3630 gen_mfc0_load64(arg, offsetof(CPUMIPSState, CP0_VPESchedule));
7a387fff 3631 rn = "VPESchedule";
ead9360e 3632 break;
7a387fff 3633 case 6:
7385ac0b 3634 check_insn(env, ctx, ASE_MT);
7db13fae 3635 gen_mfc0_load64(arg, offsetof(CPUMIPSState, CP0_VPEScheFBack));
7a387fff 3636 rn = "VPEScheFBack";
ead9360e 3637 break;
7a387fff 3638 case 7:
7385ac0b 3639 check_insn(env, ctx, ASE_MT);
7db13fae 3640 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEOpt));
7a387fff 3641 rn = "VPEOpt";
ead9360e 3642 break;
7a387fff
TS
3643 default:
3644 goto die;
3645 }
873eb012
TS
3646 break;
3647 case 2:
7a387fff
TS
3648 switch (sel) {
3649 case 0:
7db13fae 3650 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryLo0));
d9bea114 3651 tcg_gen_ext32s_tl(arg, arg);
2423f660
TS
3652 rn = "EntryLo0";
3653 break;
7a387fff 3654 case 1:
7385ac0b 3655 check_insn(env, ctx, ASE_MT);
895c2d04 3656 gen_helper_mfc0_tcstatus(arg, cpu_env);
2423f660 3657 rn = "TCStatus";
ead9360e 3658 break;
7a387fff 3659 case 2:
7385ac0b 3660 check_insn(env, ctx, ASE_MT);
895c2d04 3661 gen_helper_mfc0_tcbind(arg, cpu_env);
2423f660 3662 rn = "TCBind";
ead9360e 3663 break;
7a387fff 3664 case 3:
7385ac0b 3665 check_insn(env, ctx, ASE_MT);
895c2d04 3666 gen_helper_mfc0_tcrestart(arg, cpu_env);
2423f660 3667 rn = "TCRestart";
ead9360e 3668 break;
7a387fff 3669 case 4:
7385ac0b 3670 check_insn(env, ctx, ASE_MT);
895c2d04 3671 gen_helper_mfc0_tchalt(arg, cpu_env);
2423f660 3672 rn = "TCHalt";
ead9360e 3673 break;
7a387fff 3674 case 5:
7385ac0b 3675 check_insn(env, ctx, ASE_MT);
895c2d04 3676 gen_helper_mfc0_tccontext(arg, cpu_env);
2423f660 3677 rn = "TCContext";
ead9360e 3678 break;
7a387fff 3679 case 6:
7385ac0b 3680 check_insn(env, ctx, ASE_MT);
895c2d04 3681 gen_helper_mfc0_tcschedule(arg, cpu_env);
2423f660 3682 rn = "TCSchedule";
ead9360e 3683 break;
7a387fff 3684 case 7:
7385ac0b 3685 check_insn(env, ctx, ASE_MT);
895c2d04 3686 gen_helper_mfc0_tcschefback(arg, cpu_env);
2423f660 3687 rn = "TCScheFBack";
ead9360e 3688 break;
7a387fff
TS
3689 default:
3690 goto die;
3691 }
873eb012
TS
3692 break;
3693 case 3:
7a387fff
TS
3694 switch (sel) {
3695 case 0:
7db13fae 3696 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryLo1));
d9bea114 3697 tcg_gen_ext32s_tl(arg, arg);
2423f660
TS
3698 rn = "EntryLo1";
3699 break;
7a387fff
TS
3700 default:
3701 goto die;
1579a72e 3702 }
873eb012
TS
3703 break;
3704 case 4:
7a387fff
TS
3705 switch (sel) {
3706 case 0:
7db13fae 3707 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_Context));
d9bea114 3708 tcg_gen_ext32s_tl(arg, arg);
2423f660
TS
3709 rn = "Context";
3710 break;
7a387fff 3711 case 1:
d9bea114 3712// gen_helper_mfc0_contextconfig(arg); /* SmartMIPS ASE */
2423f660
TS
3713 rn = "ContextConfig";
3714// break;
7a387fff
TS
3715 default:
3716 goto die;
1579a72e 3717 }
873eb012
TS
3718 break;
3719 case 5:
7a387fff
TS
3720 switch (sel) {
3721 case 0:
7db13fae 3722 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageMask));
2423f660
TS
3723 rn = "PageMask";
3724 break;
7a387fff 3725 case 1:
e189e748 3726 check_insn(env, ctx, ISA_MIPS32R2);
7db13fae 3727 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageGrain));
2423f660
TS
3728 rn = "PageGrain";
3729 break;
7a387fff
TS
3730 default:
3731 goto die;
1579a72e 3732 }
873eb012
TS
3733 break;
3734 case 6:
7a387fff
TS
3735 switch (sel) {
3736 case 0:
7db13fae 3737 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Wired));
2423f660
TS
3738 rn = "Wired";
3739 break;
7a387fff 3740 case 1:
e189e748 3741 check_insn(env, ctx, ISA_MIPS32R2);
7db13fae 3742 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf0));
2423f660 3743 rn = "SRSConf0";
ead9360e 3744 break;
7a387fff 3745 case 2:
e189e748 3746 check_insn(env, ctx, ISA_MIPS32R2);
7db13fae 3747 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf1));
2423f660 3748 rn = "SRSConf1";
ead9360e 3749 break;
7a387fff 3750 case 3:
e189e748 3751 check_insn(env, ctx, ISA_MIPS32R2);
7db13fae 3752 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf2));
2423f660 3753 rn = "SRSConf2";
ead9360e 3754 break;
7a387fff 3755 case 4:
e189e748 3756 check_insn(env, ctx, ISA_MIPS32R2);
7db13fae 3757 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf3));
2423f660 3758 rn = "SRSConf3";
ead9360e 3759 break;
7a387fff 3760 case 5:
e189e748 3761 check_insn(env, ctx, ISA_MIPS32R2);
7db13fae 3762 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf4));
2423f660 3763 rn = "SRSConf4";
ead9360e 3764 break;
7a387fff
TS
3765 default:
3766 goto die;
1579a72e 3767 }
873eb012 3768 break;
8c0fdd85 3769 case 7:
7a387fff
TS
3770 switch (sel) {
3771 case 0:
e189e748 3772 check_insn(env, ctx, ISA_MIPS32R2);
7db13fae 3773 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_HWREna));
2423f660
TS
3774 rn = "HWREna";
3775 break;
7a387fff
TS
3776 default:
3777 goto die;
1579a72e 3778 }
8c0fdd85 3779 break;
873eb012 3780 case 8:
7a387fff
TS
3781 switch (sel) {
3782 case 0:
7db13fae 3783 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_BadVAddr));
d9bea114 3784 tcg_gen_ext32s_tl(arg, arg);
f0b3f3ae 3785 rn = "BadVAddr";
2423f660 3786 break;
7a387fff
TS
3787 default:
3788 goto die;
3789 }
873eb012
TS
3790 break;
3791 case 9:
7a387fff
TS
3792 switch (sel) {
3793 case 0:
2e70f6ef
PB
3794 /* Mark as an IO operation because we read the time. */
3795 if (use_icount)
3796 gen_io_start();
895c2d04 3797 gen_helper_mfc0_count(arg, cpu_env);
2e70f6ef
PB
3798 if (use_icount) {
3799 gen_io_end();
2e70f6ef 3800 }
55807224
EI
3801 /* Break the TB to be able to take timer interrupts immediately
3802 after reading count. */
3803 ctx->bstate = BS_STOP;
2423f660
TS
3804 rn = "Count";
3805 break;
3806 /* 6,7 are implementation dependent */
7a387fff
TS
3807 default:
3808 goto die;
2423f660 3809 }
873eb012
TS
3810 break;
3811 case 10:
7a387fff
TS
3812 switch (sel) {
3813 case 0:
7db13fae 3814 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryHi));
d9bea114 3815 tcg_gen_ext32s_tl(arg, arg);
2423f660
TS
3816 rn = "EntryHi";
3817 break;
7a387fff
TS
3818 default:
3819 goto die;
1579a72e 3820 }
873eb012
TS
3821 break;
3822 case 11:
7a387fff
TS
3823 switch (sel) {
3824 case 0:
7db13fae 3825 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Compare));
2423f660
TS
3826 rn = "Compare";
3827 break;
3828 /* 6,7 are implementation dependent */
7a387fff
TS
3829 default:
3830 goto die;
2423f660 3831 }
873eb012
TS
3832 break;
3833 case 12:
7a387fff
TS
3834 switch (sel) {
3835 case 0:
7db13fae 3836 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Status));
2423f660
TS
3837 rn = "Status";
3838 break;
7a387fff 3839 case 1:
e189e748 3840 check_insn(env, ctx, ISA_MIPS32R2);
7db13fae 3841 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_IntCtl));
2423f660
TS
3842 rn = "IntCtl";
3843 break;
7a387fff 3844 case 2:
e189e748 3845 check_insn(env, ctx, ISA_MIPS32R2);
7db13fae 3846 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSCtl));
2423f660
TS
3847 rn = "SRSCtl";
3848 break;
7a387fff 3849 case 3:
e189e748 3850 check_insn(env, ctx, ISA_MIPS32R2);
7db13fae 3851 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
2423f660 3852 rn = "SRSMap";
fd88b6ab 3853 break;
7a387fff
TS
3854 default:
3855 goto die;
3856 }
873eb012
TS
3857 break;
3858 case 13:
7a387fff
TS
3859 switch (sel) {
3860 case 0:
7db13fae 3861 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Cause));
2423f660
TS
3862 rn = "Cause";
3863 break;
7a387fff
TS
3864 default:
3865 goto die;
3866 }
873eb012
TS
3867 break;
3868 case 14:
7a387fff
TS
3869 switch (sel) {
3870 case 0:
7db13fae 3871 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EPC));
d9bea114 3872 tcg_gen_ext32s_tl(arg, arg);
2423f660
TS
3873 rn = "EPC";
3874 break;
7a387fff
TS
3875 default:
3876 goto die;
1579a72e 3877 }
873eb012
TS
3878 break;
3879 case 15:
7a387fff
TS
3880 switch (sel) {
3881 case 0:
7db13fae 3882 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PRid));
2423f660
TS
3883 rn = "PRid";
3884 break;
7a387fff 3885 case 1:
e189e748 3886 check_insn(env, ctx, ISA_MIPS32R2);
7db13fae 3887 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_EBase));
2423f660
TS
3888 rn = "EBase";
3889 break;
7a387fff
TS
3890 default:
3891 goto die;
3892 }
873eb012
TS
3893 break;
3894 case 16:
3895 switch (sel) {
3896 case 0:
7db13fae 3897 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config0));
873eb012
TS
3898 rn = "Config";
3899 break;
3900 case 1:
7db13fae 3901 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config1));
873eb012
TS
3902 rn = "Config1";
3903 break;
7a387fff 3904 case 2:
7db13fae 3905 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config2));
7a387fff
TS
3906 rn = "Config2";
3907 break;
3908 case 3:
7db13fae 3909 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config3));
7a387fff
TS
3910 rn = "Config3";
3911 break;
e397ee33
TS
3912 /* 4,5 are reserved */
3913 /* 6,7 are implementation dependent */
3914 case 6:
7db13fae 3915 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config6));
e397ee33
TS
3916 rn = "Config6";
3917 break;
3918 case 7:
7db13fae 3919 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config7));
e397ee33
TS
3920 rn = "Config7";
3921 break;
873eb012 3922 default:
873eb012
TS
3923 goto die;
3924 }
3925 break;
3926 case 17:
7a387fff
TS
3927 switch (sel) {
3928 case 0:
895c2d04 3929 gen_helper_mfc0_lladdr(arg, cpu_env);
2423f660
TS
3930 rn = "LLAddr";
3931 break;
7a387fff
TS
3932 default:
3933 goto die;
3934 }
873eb012
TS
3935 break;
3936 case 18:
7a387fff 3937 switch (sel) {
fd88b6ab 3938 case 0 ... 7:
895c2d04 3939 gen_helper_1e0i(mfc0_watchlo, arg, sel);
2423f660
TS
3940 rn = "WatchLo";
3941 break;
7a387fff
TS
3942 default:
3943 goto die;
3944 }
873eb012
TS
3945 break;
3946 case 19:
7a387fff 3947 switch (sel) {
fd88b6ab 3948 case 0 ...7:
895c2d04 3949 gen_helper_1e0i(mfc0_watchhi, arg, sel);
2423f660
TS
3950 rn = "WatchHi";
3951 break;
7a387fff
TS
3952 default:
3953 goto die;
3954 }
873eb012 3955 break;
8c0fdd85 3956 case 20:
7a387fff
TS
3957 switch (sel) {
3958 case 0:
d26bc211 3959#if defined(TARGET_MIPS64)
e189e748 3960 check_insn(env, ctx, ISA_MIPS3);
7db13fae 3961 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_XContext));
d9bea114 3962 tcg_gen_ext32s_tl(arg, arg);
2423f660
TS
3963 rn = "XContext";
3964 break;
703eaf37 3965#endif
7a387fff
TS
3966 default:
3967 goto die;
3968 }
8c0fdd85
TS
3969 break;
3970 case 21:
7a387fff
TS
3971 /* Officially reserved, but sel 0 is used for R1x000 framemask */
3972 switch (sel) {
3973 case 0:
7db13fae 3974 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Framemask));
2423f660
TS
3975 rn = "Framemask";
3976 break;
7a387fff
TS
3977 default:
3978 goto die;
3979 }
8c0fdd85
TS
3980 break;
3981 case 22:
d9bea114 3982 tcg_gen_movi_tl(arg, 0); /* unimplemented */
2423f660
TS
3983 rn = "'Diagnostic"; /* implementation dependent */
3984 break;
873eb012 3985 case 23:
7a387fff
TS
3986 switch (sel) {
3987 case 0:
895c2d04 3988 gen_helper_mfc0_debug(arg, cpu_env); /* EJTAG support */
2423f660
TS
3989 rn = "Debug";
3990 break;
7a387fff 3991 case 1:
d9bea114 3992// gen_helper_mfc0_tracecontrol(arg); /* PDtrace support */
2423f660
TS
3993 rn = "TraceControl";
3994// break;
7a387fff 3995 case 2:
d9bea114 3996// gen_helper_mfc0_tracecontrol2(arg); /* PDtrace support */
2423f660
TS
3997 rn = "TraceControl2";
3998// break;
7a387fff 3999 case 3:
d9bea114 4000// gen_helper_mfc0_usertracedata(arg); /* PDtrace support */
2423f660
TS
4001 rn = "UserTraceData";
4002// break;
7a387fff 4003 case 4:
d9bea114 4004// gen_helper_mfc0_tracebpc(arg); /* PDtrace support */
2423f660
TS
4005 rn = "TraceBPC";
4006// break;
7a387fff
TS
4007 default:
4008 goto die;
4009 }
873eb012
TS
4010 break;
4011 case 24:
7a387fff
TS
4012 switch (sel) {
4013 case 0:
f0b3f3ae 4014 /* EJTAG support */
7db13fae 4015 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_DEPC));
d9bea114 4016 tcg_gen_ext32s_tl(arg, arg);
2423f660
TS
4017 rn = "DEPC";
4018 break;
7a387fff
TS
4019 default:
4020 goto die;
4021 }
873eb012 4022 break;
8c0fdd85 4023 case 25:
7a387fff
TS
4024 switch (sel) {
4025 case 0:
7db13fae 4026 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Performance0));
2423f660 4027 rn = "Performance0";
7a387fff
TS
4028 break;
4029 case 1:
d9bea114 4030// gen_helper_mfc0_performance1(arg);
2423f660
TS
4031 rn = "Performance1";
4032// break;
7a387fff 4033 case 2:
d9bea114 4034// gen_helper_mfc0_performance2(arg);
2423f660
TS
4035 rn = "Performance2";
4036// break;
7a387fff 4037 case 3:
d9bea114 4038// gen_helper_mfc0_performance3(arg);
2423f660
TS
4039 rn = "Performance3";
4040// break;
7a387fff 4041 case 4:
d9bea114 4042// gen_helper_mfc0_performance4(arg);
2423f660
TS
4043 rn = "Performance4";
4044// break;
7a387fff 4045 case 5:
d9bea114 4046// gen_helper_mfc0_performance5(arg);
2423f660
TS
4047 rn = "Performance5";
4048// break;
7a387fff 4049 case 6:
d9bea114 4050// gen_helper_mfc0_performance6(arg);
2423f660
TS
4051 rn = "Performance6";
4052// break;
7a387fff 4053 case 7:
d9bea114 4054// gen_helper_mfc0_performance7(arg);
2423f660
TS
4055 rn = "Performance7";
4056// break;
7a387fff
TS
4057 default:
4058 goto die;
4059 }
8c0fdd85
TS
4060 break;
4061 case 26:
d9bea114 4062 tcg_gen_movi_tl(arg, 0); /* unimplemented */
da80682b
AJ
4063 rn = "ECC";
4064 break;
8c0fdd85 4065 case 27:
7a387fff 4066 switch (sel) {
7a387fff 4067 case 0 ... 3:
d9bea114 4068 tcg_gen_movi_tl(arg, 0); /* unimplemented */
2423f660
TS
4069 rn = "CacheErr";
4070 break;
7a387fff
TS
4071 default:
4072 goto die;
4073 }
8c0fdd85 4074 break;
873eb012
TS
4075 case 28:
4076 switch (sel) {
4077 case 0:
7a387fff
TS
4078 case 2:
4079 case 4:
4080 case 6:
7db13fae 4081 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_TagLo));
873eb012
TS
4082 rn = "TagLo";
4083 break;
4084 case 1:
7a387fff
TS
4085 case 3:
4086 case 5:
4087 case 7:
7db13fae 4088 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataLo));
873eb012
TS
4089 rn = "DataLo";
4090 break;
4091 default:
873eb012
TS
4092 goto die;
4093 }
4094 break;
8c0fdd85 4095 case 29:
7a387fff
TS
4096 switch (sel) {
4097 case 0:
4098 case 2:
4099 case 4:
4100 case 6:
7db13fae 4101 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_TagHi));
7a387fff
TS
4102 rn = "TagHi";
4103 break;
4104 case 1:
4105 case 3:
4106 case 5:
4107 case 7:
7db13fae 4108 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataHi));
7a387fff
TS
4109 rn = "DataHi";
4110 break;
4111 default:
4112 goto die;
4113 }
8c0fdd85 4114 break;
873eb012 4115 case 30:
7a387fff
TS
4116 switch (sel) {
4117 case 0:
7db13fae 4118 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_ErrorEPC));
d9bea114 4119 tcg_gen_ext32s_tl(arg, arg);
2423f660
TS
4120 rn = "ErrorEPC";
4121 break;
7a387fff
TS
4122 default:
4123 goto die;
4124 }
873eb012
TS
4125 break;
4126 case 31:
7a387fff
TS
4127 switch (sel) {
4128 case 0:
f0b3f3ae 4129 /* EJTAG support */
7db13fae 4130 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
2423f660
TS
4131 rn = "DESAVE";
4132 break;
7a387fff
TS
4133 default:
4134 goto die;
4135 }
873eb012
TS
4136 break;
4137 default:
873eb012
TS
4138 goto die;
4139 }
2abf314d 4140 (void)rn; /* avoid a compiler warning */
d12d51d5 4141 LOG_DISAS("mfc0 %s (reg %d sel %d)\n", rn, reg, sel);
873eb012
TS
4142 return;
4143
4144die:
d12d51d5 4145 LOG_DISAS("mfc0 %s (reg %d sel %d)\n", rn, reg, sel);
873eb012
TS
4146 generate_exception(ctx, EXCP_RI);
4147}
4148
7db13fae 4149static void gen_mtc0 (CPUMIPSState *env, DisasContext *ctx, TCGv arg, int reg, int sel)
8c0fdd85 4150{
7a387fff
TS
4151 const char *rn = "invalid";
4152
e189e748
TS
4153 if (sel != 0)
4154 check_insn(env, ctx, ISA_MIPS32);
4155
2e70f6ef
PB
4156 if (use_icount)
4157 gen_io_start();
4158
8c0fdd85
TS
4159 switch (reg) {
4160 case 0:
7a387fff
TS
4161 switch (sel) {
4162 case 0:
895c2d04 4163 gen_helper_mtc0_index(cpu_env, arg);
7a387fff
TS
4164 rn = "Index";
4165 break;
4166 case 1:
7385ac0b 4167 check_insn(env, ctx, ASE_MT);
895c2d04 4168 gen_helper_mtc0_mvpcontrol(cpu_env, arg);
7a387fff 4169 rn = "MVPControl";
ead9360e 4170 break;
7a387fff 4171 case 2:
7385ac0b 4172 check_insn(env, ctx, ASE_MT);
ead9360e 4173 /* ignored */
7a387fff 4174 rn = "MVPConf0";
ead9360e 4175 break;
7a387fff 4176 case 3:
7385ac0b 4177 check_insn(env, ctx, ASE_MT);
ead9360e 4178 /* ignored */
7a387fff 4179 rn = "MVPConf1";
ead9360e 4180 break;
7a387fff
TS
4181 default:
4182 goto die;
4183 }
8c0fdd85
TS
4184 break;
4185 case 1:
7a387fff
TS
4186 switch (sel) {
4187 case 0:
2423f660 4188 /* ignored */
7a387fff 4189 rn = "Random";
2423f660 4190 break;
7a387fff 4191 case 1:
7385ac0b 4192 check_insn(env, ctx, ASE_MT);
895c2d04 4193 gen_helper_mtc0_vpecontrol(cpu_env, arg);
7a387fff 4194 rn = "VPEControl";
ead9360e 4195 break;
7a387fff 4196 case 2:
7385ac0b 4197 check_insn(env, ctx, ASE_MT);
895c2d04 4198 gen_helper_mtc0_vpeconf0(cpu_env, arg);
7a387fff 4199 rn = "VPEConf0";
ead9360e 4200 break;
7a387fff 4201 case 3:
7385ac0b 4202 check_insn(env, ctx, ASE_MT);
895c2d04 4203 gen_helper_mtc0_vpeconf1(cpu_env, arg);
7a387fff 4204 rn = "VPEConf1";
ead9360e 4205 break;
7a387fff 4206 case 4:
7385ac0b 4207 check_insn(env, ctx, ASE_MT);
895c2d04 4208 gen_helper_mtc0_yqmask(cpu_env, arg);
7a387fff 4209 rn = "YQMask";
ead9360e 4210 break;
7a387fff 4211 case 5:
7385ac0b 4212 check_insn(env, ctx, ASE_MT);
7db13fae 4213 gen_mtc0_store64(arg, offsetof(CPUMIPSState, CP0_VPESchedule));
7a387fff 4214 rn = "VPESchedule";
ead9360e 4215 break;
7a387fff 4216 case 6:
7385ac0b 4217 check_insn(env, ctx, ASE_MT);
7db13fae 4218 gen_mtc0_store64(arg, offsetof(CPUMIPSState, CP0_VPEScheFBack));
7a387fff 4219 rn = "VPEScheFBack";
ead9360e 4220 break;
7a387fff 4221 case 7:
7385ac0b 4222 check_insn(env, ctx, ASE_MT);
895c2d04 4223 gen_helper_mtc0_vpeopt(cpu_env, arg);
7a387fff 4224 rn = "VPEOpt";
ead9360e 4225 break;
7a387fff
TS
4226 default:
4227 goto die;
4228 }
8c0fdd85
TS
4229 break;
4230 case 2:
7a387fff
TS
4231 switch (sel) {
4232 case 0:
895c2d04 4233 gen_helper_mtc0_entrylo0(cpu_env, arg);
2423f660
TS
4234 rn = "EntryLo0";
4235 break;
7a387fff 4236 case 1:
7385ac0b 4237 check_insn(env, ctx, ASE_MT);
895c2d04 4238 gen_helper_mtc0_tcstatus(cpu_env, arg);
2423f660 4239 rn = "TCStatus";
ead9360e 4240 break;
7a387fff 4241 case 2:
7385ac0b 4242 check_insn(env, ctx, ASE_MT);
895c2d04 4243 gen_helper_mtc0_tcbind(cpu_env, arg);
2423f660 4244 rn = "TCBind";
ead9360e 4245 break;
7a387fff 4246 case 3:
7385ac0b 4247 check_insn(env, ctx, ASE_MT);
895c2d04 4248 gen_helper_mtc0_tcrestart(cpu_env, arg);
2423f660 4249 rn = "TCRestart";
ead9360e 4250 break;
7a387fff 4251 case 4:
7385ac0b 4252 check_insn(env, ctx, ASE_MT);
895c2d04 4253 gen_helper_mtc0_tchalt(cpu_env, arg);
2423f660 4254 rn = "TCHalt";
ead9360e 4255 break;
7a387fff 4256 case 5:
7385ac0b 4257 check_insn(env, ctx, ASE_MT);
895c2d04 4258 gen_helper_mtc0_tccontext(cpu_env, arg);
2423f660 4259 rn = "TCContext";
ead9360e 4260 break;
7a387fff 4261 case 6:
7385ac0b 4262 check_insn(env, ctx, ASE_MT);
895c2d04 4263 gen_helper_mtc0_tcschedule(cpu_env, arg);
2423f660 4264 rn = "TCSchedule";
ead9360e 4265 break;
7a387fff 4266 case 7:
7385ac0b 4267 check_insn(env, ctx, ASE_MT);
895c2d04 4268 gen_helper_mtc0_tcschefback(cpu_env, arg);
2423f660 4269 rn = "TCScheFBack";
ead9360e 4270 break;
7a387fff
TS
4271 default:
4272 goto die;
4273 }
8c0fdd85
TS
4274 break;
4275 case 3:
7a387fff
TS
4276 switch (sel) {
4277 case 0:
895c2d04 4278 gen_helper_mtc0_entrylo1(cpu_env, arg);
2423f660
TS
4279 rn = "EntryLo1";
4280 break;
7a387fff
TS
4281 default:
4282 goto die;
876d4b07 4283 }
8c0fdd85
TS
4284 break;
4285 case 4:
7a387fff
TS
4286 switch (sel) {
4287 case 0:
895c2d04 4288 gen_helper_mtc0_context(cpu_env, arg);
2423f660
TS
4289 rn = "Context";
4290 break;
7a387fff 4291 case 1:
895c2d04 4292// gen_helper_mtc0_contextconfig(cpu_env, arg); /* SmartMIPS ASE */
2423f660
TS
4293 rn = "ContextConfig";
4294// break;
7a387fff
TS
4295 default:
4296 goto die;
876d4b07 4297 }
8c0fdd85
TS
4298 break;
4299 case 5:
7a387fff
TS
4300 switch (sel) {
4301 case 0:
895c2d04 4302 gen_helper_mtc0_pagemask(cpu_env, arg);
2423f660
TS
4303 rn = "PageMask";
4304 break;
7a387fff 4305 case 1:
e189e748 4306 check_insn(env, ctx, ISA_MIPS32R2);
895c2d04 4307 gen_helper_mtc0_pagegrain(cpu_env, arg);
2423f660
TS
4308 rn = "PageGrain";
4309 break;
7a387fff
TS
4310 default:
4311 goto die;
876d4b07 4312 }
8c0fdd85
TS
4313 break;
4314 case 6:
7a387fff
TS
4315 switch (sel) {
4316 case 0:
895c2d04 4317 gen_helper_mtc0_wired(cpu_env, arg);
2423f660
TS
4318 rn = "Wired";
4319 break;
7a387fff 4320 case 1:
e189e748 4321 check_insn(env, ctx, ISA_MIPS32R2);
895c2d04 4322 gen_helper_mtc0_srsconf0(cpu_env, arg);
2423f660 4323 rn = "SRSConf0";
ead9360e 4324 break;
7a387fff 4325 case 2:
e189e748 4326 check_insn(env, ctx, ISA_MIPS32R2);
895c2d04 4327 gen_helper_mtc0_srsconf1(cpu_env, arg);
2423f660 4328 rn = "SRSConf1";
ead9360e 4329 break;
7a387fff 4330 case 3:
e189e748 4331 check_insn(env, ctx, ISA_MIPS32R2);
895c2d04 4332 gen_helper_mtc0_srsconf2(cpu_env, arg);
2423f660 4333 rn = "SRSConf2";
ead9360e 4334 break;
7a387fff 4335 case 4:
e189e748 4336 check_insn(env, ctx, ISA_MIPS32R2);
895c2d04 4337 gen_helper_mtc0_srsconf3(cpu_env, arg);
2423f660 4338 rn = "SRSConf3";
ead9360e 4339 break;
7a387fff 4340 case 5:
e189e748 4341 check_insn(env, ctx, ISA_MIPS32R2);
895c2d04 4342 gen_helper_mtc0_srsconf4(cpu_env, arg);
2423f660 4343 rn = "SRSConf4";
ead9360e 4344 break;
7a387fff
TS
4345 default:
4346 goto die;
876d4b07 4347 }
8c0fdd85
TS
4348 break;
4349 case 7:
7a387fff
TS
4350 switch (sel) {
4351 case 0:
e189e748 4352 check_insn(env, ctx, ISA_MIPS32R2);
895c2d04 4353 gen_helper_mtc0_hwrena(cpu_env, arg);
2423f660
TS
4354 rn = "HWREna";
4355 break;
7a387fff
TS
4356 default:
4357 goto die;
876d4b07 4358 }
8c0fdd85
TS
4359 break;
4360 case 8:
7a387fff 4361 /* ignored */
f0b3f3ae 4362 rn = "BadVAddr";
8c0fdd85
TS
4363 break;
4364 case 9:
7a387fff
TS
4365 switch (sel) {
4366 case 0:
895c2d04 4367 gen_helper_mtc0_count(cpu_env, arg);
2423f660
TS
4368 rn = "Count";
4369 break;
876d4b07 4370 /* 6,7 are implementation dependent */
7a387fff
TS
4371 default:
4372 goto die;
876d4b07 4373 }
8c0fdd85
TS
4374 break;
4375 case 10:
7a387fff
TS
4376 switch (sel) {
4377 case 0:
895c2d04 4378 gen_helper_mtc0_entryhi(cpu_env, arg);
2423f660
TS
4379 rn = "EntryHi";
4380 break;
7a387fff
TS
4381 default:
4382 goto die;
876d4b07 4383 }
8c0fdd85
TS
4384 break;
4385 case 11:
7a387fff
TS
4386 switch (sel) {
4387 case 0:
895c2d04 4388 gen_helper_mtc0_compare(cpu_env, arg);
2423f660
TS
4389 rn = "Compare";
4390 break;
4391 /* 6,7 are implementation dependent */
7a387fff
TS
4392 default:
4393 goto die;
876d4b07 4394 }
8c0fdd85
TS
4395 break;
4396 case 12:
7a387fff
TS
4397 switch (sel) {
4398 case 0:
867abc7e 4399 save_cpu_state(ctx, 1);
895c2d04 4400 gen_helper_mtc0_status(cpu_env, arg);
8487327a
TS
4401 /* BS_STOP isn't good enough here, hflags may have changed. */
4402 gen_save_pc(ctx->pc + 4);
4403 ctx->bstate = BS_EXCP;
2423f660
TS
4404 rn = "Status";
4405 break;
7a387fff 4406 case 1:
e189e748 4407 check_insn(env, ctx, ISA_MIPS32R2);
895c2d04 4408 gen_helper_mtc0_intctl(cpu_env, arg);
8487327a
TS
4409 /* Stop translation as we may have switched the execution mode */
4410 ctx->bstate = BS_STOP;
2423f660
TS
4411 rn = "IntCtl";
4412 break;
7a387fff 4413 case 2:
e189e748 4414 check_insn(env, ctx, ISA_MIPS32R2);
895c2d04 4415 gen_helper_mtc0_srsctl(cpu_env, arg);
8487327a
TS
4416 /* Stop translation as we may have switched the execution mode */
4417 ctx->bstate = BS_STOP;
2423f660
TS
4418 rn = "SRSCtl";
4419 break;
7a387fff 4420 case 3:
e189e748 4421 check_insn(env, ctx, ISA_MIPS32R2);
7db13fae 4422 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
8487327a
TS
4423 /* Stop translation as we may have switched the execution mode */
4424 ctx->bstate = BS_STOP;
2423f660 4425 rn = "SRSMap";
fd88b6ab 4426 break;
7a387fff
TS
4427 default:
4428 goto die;
876d4b07 4429 }
8c0fdd85
TS
4430 break;
4431 case 13:
7a387fff
TS
4432 switch (sel) {
4433 case 0:
867abc7e 4434 save_cpu_state(ctx, 1);
895c2d04 4435 gen_helper_mtc0_cause(cpu_env, arg);
2423f660
TS
4436 rn = "Cause";
4437 break;
7a387fff
TS
4438 default:
4439 goto die;
876d4b07 4440 }
8c0fdd85
TS
4441 break;
4442 case 14:
7a387fff
TS
4443 switch (sel) {
4444 case 0:
7db13fae 4445 gen_mtc0_store64(arg, offsetof(CPUMIPSState, CP0_EPC));
2423f660
TS
4446 rn = "EPC";
4447 break;
7a387fff
TS
4448 default:
4449 goto die;
876d4b07 4450 }
8c0fdd85
TS
4451 break;
4452 case 15:
7a387fff
TS
4453 switch (sel) {
4454 case 0:
2423f660
TS
4455 /* ignored */
4456 rn = "PRid";
4457 break;
7a387fff 4458 case 1:
e189e748 4459 check_insn(env, ctx, ISA_MIPS32R2);
895c2d04 4460 gen_helper_mtc0_ebase(cpu_env, arg);
2423f660
TS
4461 rn = "EBase";
4462 break;
7a387fff
TS
4463 default:
4464 goto die;
1579a72e 4465 }
8c0fdd85
TS
4466 break;
4467 case 16:
4468 switch (sel) {
4469 case 0:
895c2d04 4470 gen_helper_mtc0_config0(cpu_env, arg);
7a387fff 4471 rn = "Config";
2423f660
TS
4472 /* Stop translation as we may have switched the execution mode */
4473 ctx->bstate = BS_STOP;
7a387fff
TS
4474 break;
4475 case 1:
e397ee33 4476 /* ignored, read only */
7a387fff
TS
4477 rn = "Config1";
4478 break;
4479 case 2:
895c2d04 4480 gen_helper_mtc0_config2(cpu_env, arg);
7a387fff 4481 rn = "Config2";
2423f660
TS
4482 /* Stop translation as we may have switched the execution mode */
4483 ctx->bstate = BS_STOP;
8c0fdd85 4484 break;
7a387fff 4485 case 3:
e397ee33 4486 /* ignored, read only */
7a387fff
TS
4487 rn = "Config3";
4488 break;
e397ee33
TS
4489 /* 4,5 are reserved */
4490 /* 6,7 are implementation dependent */
4491 case 6:
4492 /* ignored */
4493 rn = "Config6";
4494 break;
4495 case 7:
4496 /* ignored */
4497 rn = "Config7";
4498 break;
8c0fdd85
TS
4499 default:
4500 rn = "Invalid config selector";
4501 goto die;
4502 }
4503 break;
4504 case 17:
7a387fff
TS
4505 switch (sel) {
4506 case 0:
895c2d04 4507 gen_helper_mtc0_lladdr(cpu_env, arg);
2423f660
TS
4508 rn = "LLAddr";
4509 break;
7a387fff
TS
4510 default:
4511 goto die;
4512 }
8c0fdd85
TS
4513 break;
4514 case 18:
7a387fff 4515 switch (sel) {
fd88b6ab 4516 case 0 ... 7:
895c2d04 4517 gen_helper_0e1i(mtc0_watchlo, arg, sel);
2423f660
TS
4518 rn = "WatchLo";
4519 break;
7a387fff
TS
4520 default:
4521 goto die;
4522 }
8c0fdd85
TS
4523 break;
4524 case 19:
7a387fff 4525 switch (sel) {
fd88b6ab 4526 case 0 ... 7:
895c2d04 4527 gen_helper_0e1i(mtc0_watchhi, arg, sel);
2423f660
TS
4528 rn = "WatchHi";
4529 break;
7a387fff
TS
4530 default:
4531 goto die;
4532 }
8c0fdd85
TS
4533 break;
4534 case 20:
7a387fff
TS
4535 switch (sel) {
4536 case 0:
d26bc211 4537#if defined(TARGET_MIPS64)
e189e748 4538 check_insn(env, ctx, ISA_MIPS3);
895c2d04 4539 gen_helper_mtc0_xcontext(cpu_env, arg);
2423f660
TS
4540 rn = "XContext";
4541 break;
703eaf37 4542#endif
7a387fff
TS
4543 default:
4544 goto die;
4545 }
8c0fdd85
TS
4546 break;
4547 case 21:
7a387fff
TS
4548 /* Officially reserved, but sel 0 is used for R1x000 framemask */
4549 switch (sel) {
4550 case 0:
895c2d04 4551 gen_helper_mtc0_framemask(cpu_env, arg);
2423f660
TS
4552 rn = "Framemask";
4553 break;
7a387fff
TS
4554 default:
4555 goto die;
4556 }
4557 break;
8c0fdd85 4558 case 22:
7a387fff
TS
4559 /* ignored */
4560 rn = "Diagnostic"; /* implementation dependent */
2423f660 4561 break;
8c0fdd85 4562 case 23:
7a387fff
TS
4563 switch (sel) {
4564 case 0:
895c2d04 4565 gen_helper_mtc0_debug(cpu_env, arg); /* EJTAG support */
8487327a
TS
4566 /* BS_STOP isn't good enough here, hflags may have changed. */
4567 gen_save_pc(ctx->pc + 4);
4568 ctx->bstate = BS_EXCP;
2423f660
TS
4569 rn = "Debug";
4570 break;
7a387fff 4571 case 1:
895c2d04 4572// gen_helper_mtc0_tracecontrol(cpu_env, arg); /* PDtrace support */
2423f660 4573 rn = "TraceControl";
8487327a
TS
4574 /* Stop translation as we may have switched the execution mode */
4575 ctx->bstate = BS_STOP;
2423f660 4576// break;
7a387fff 4577 case 2:
895c2d04 4578// gen_helper_mtc0_tracecontrol2(cpu_env, arg); /* PDtrace support */
2423f660 4579 rn = "TraceControl2";
8487327a
TS
4580 /* Stop translation as we may have switched the execution mode */
4581 ctx->bstate = BS_STOP;
2423f660 4582// break;
7a387fff 4583 case 3:
8487327a
TS
4584 /* Stop translation as we may have switched the execution mode */
4585 ctx->bstate = BS_STOP;
895c2d04 4586// gen_helper_mtc0_usertracedata(cpu_env, arg); /* PDtrace support */
2423f660 4587 rn = "UserTraceData";
8487327a
TS
4588 /* Stop translation as we may have switched the execution mode */
4589 ctx->bstate = BS_STOP;
2423f660 4590// break;
7a387fff 4591 case 4:
895c2d04 4592// gen_helper_mtc0_tracebpc(cpu_env, arg); /* PDtrace support */
8487327a
TS
4593 /* Stop translation as we may have switched the execution mode */
4594 ctx->bstate = BS_STOP;
2423f660
TS
4595 rn = "TraceBPC";
4596// break;
7a387fff
TS
4597 default:
4598 goto die;
4599 }
8c0fdd85
TS
4600 break;
4601 case 24:
7a387fff
TS
4602 switch (sel) {
4603 case 0:
f1aa6320 4604 /* EJTAG support */
7db13fae 4605 gen_mtc0_store64(arg, offsetof(CPUMIPSState, CP0_DEPC));
2423f660
TS
4606 rn = "DEPC";
4607 break;
7a387fff
TS
4608 default:
4609 goto die;
4610 }
8c0fdd85
TS
4611 break;
4612 case 25:
7a387fff
TS
4613 switch (sel) {
4614 case 0:
895c2d04 4615 gen_helper_mtc0_performance0(cpu_env, arg);
2423f660
TS
4616 rn = "Performance0";
4617 break;
7a387fff 4618 case 1:
d9bea114 4619// gen_helper_mtc0_performance1(arg);
2423f660
TS
4620 rn = "Performance1";
4621// break;
7a387fff 4622 case 2:
d9bea114 4623// gen_helper_mtc0_performance2(arg);
2423f660
TS
4624 rn = "Performance2";
4625// break;
7a387fff 4626 case 3:
d9bea114 4627// gen_helper_mtc0_performance3(arg);
2423f660
TS
4628 rn = "Performance3";
4629// break;
7a387fff 4630 case 4:
d9bea114 4631// gen_helper_mtc0_performance4(arg);
2423f660
TS
4632 rn = "Performance4";
4633// break;
7a387fff 4634 case 5:
d9bea114 4635// gen_helper_mtc0_performance5(arg);
2423f660
TS
4636 rn = "Performance5";
4637// break;
7a387fff 4638 case 6:
d9bea114 4639// gen_helper_mtc0_performance6(arg);
2423f660
TS
4640 rn = "Performance6";
4641// break;
7a387fff 4642 case 7:
d9bea114 4643// gen_helper_mtc0_performance7(arg);
2423f660
TS
4644 rn = "Performance7";
4645// break;
7a387fff
TS
4646 default:
4647 goto die;
4648 }
8c0fdd85
TS
4649 break;
4650 case 26:
2423f660 4651 /* ignored */
8c0fdd85 4652 rn = "ECC";
2423f660 4653 break;
8c0fdd85 4654 case 27:
7a387fff
TS
4655 switch (sel) {
4656 case 0 ... 3:
2423f660
TS
4657 /* ignored */
4658 rn = "CacheErr";
4659 break;
7a387fff
TS
4660 default:
4661 goto die;
4662 }
8c0fdd85
TS
4663 break;
4664 case 28:
4665 switch (sel) {
4666 case 0:
7a387fff
TS
4667 case 2:
4668 case 4:
4669 case 6:
895c2d04 4670 gen_helper_mtc0_taglo(cpu_env, arg);
8c0fdd85
TS
4671 rn = "TagLo";
4672 break;
7a387fff
TS
4673 case 1:
4674 case 3:
4675 case 5:
4676 case 7:
895c2d04 4677 gen_helper_mtc0_datalo(cpu_env, arg);
7a387fff
TS
4678 rn = "DataLo";
4679 break;
8c0fdd85 4680 default:
8c0fdd85
TS
4681 goto die;
4682 }
4683 break;
4684 case 29:
7a387fff
TS
4685 switch (sel) {
4686 case 0:
4687 case 2:
4688 case 4:
4689 case 6:
895c2d04 4690 gen_helper_mtc0_taghi(cpu_env, arg);
7a387fff
TS
4691 rn = "TagHi";
4692 break;
4693 case 1:
4694 case 3:
4695 case 5:
4696 case 7:
895c2d04 4697 gen_helper_mtc0_datahi(cpu_env, arg);
7a387fff
TS
4698 rn = "DataHi";
4699 break;
4700 default:
4701 rn = "invalid sel";
4702 goto die;
4703 }
8c0fdd85
TS
4704 break;
4705 case 30:
7a387fff
TS
4706 switch (sel) {
4707 case 0:
7db13fae 4708 gen_mtc0_store64(arg, offsetof(CPUMIPSState, CP0_ErrorEPC));
2423f660
TS
4709 rn = "ErrorEPC";
4710 break;
7a387fff
TS
4711 default:
4712 goto die;
4713 }
8c0fdd85
TS
4714 break;
4715 case 31:
7a387fff
TS
4716 switch (sel) {
4717 case 0:
f1aa6320 4718 /* EJTAG support */
7db13fae 4719 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
2423f660
TS
4720 rn = "DESAVE";
4721 break;
7a387fff
TS
4722 default:
4723 goto die;
4724 }
2423f660
TS
4725 /* Stop translation as we may have switched the execution mode */
4726 ctx->bstate = BS_STOP;
8c0fdd85
TS
4727 break;
4728 default:
8c0fdd85
TS
4729 goto die;
4730 }
2abf314d 4731 (void)rn; /* avoid a compiler warning */
d12d51d5 4732 LOG_DISAS("mtc0 %s (reg %d sel %d)\n", rn, reg, sel);
bf20dc07 4733 /* For simplicity assume that all writes can cause interrupts. */
2e70f6ef
PB
4734 if (use_icount) {
4735 gen_io_end();
4736 ctx->bstate = BS_STOP;
4737 }
8c0fdd85
TS
4738 return;
4739
4740die:
d12d51d5 4741 LOG_DISAS("mtc0 %s (reg %d sel %d)\n", rn, reg, sel);
8c0fdd85
TS
4742 generate_exception(ctx, EXCP_RI);
4743}
4744
d26bc211 4745#if defined(TARGET_MIPS64)
7db13fae 4746static void gen_dmfc0 (CPUMIPSState *env, DisasContext *ctx, TCGv arg, int reg, int sel)
9c2149c8
TS
4747{
4748 const char *rn = "invalid";
4749
e189e748
TS
4750 if (sel != 0)
4751 check_insn(env, ctx, ISA_MIPS64);
4752
9c2149c8
TS
4753 switch (reg) {
4754 case 0:
4755 switch (sel) {
4756 case 0:
7db13fae 4757 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Index));
9c2149c8
TS
4758 rn = "Index";
4759 break;
4760 case 1:
7385ac0b 4761 check_insn(env, ctx, ASE_MT);
895c2d04 4762 gen_helper_mfc0_mvpcontrol(arg, cpu_env);
9c2149c8 4763 rn = "MVPControl";
ead9360e 4764 break;
9c2149c8 4765 case 2:
7385ac0b 4766 check_insn(env, ctx, ASE_MT);
895c2d04 4767 gen_helper_mfc0_mvpconf0(arg, cpu_env);
9c2149c8 4768 rn = "MVPConf0";
ead9360e 4769 break;
9c2149c8 4770 case 3:
7385ac0b 4771 check_insn(env, ctx, ASE_MT);
895c2d04 4772 gen_helper_mfc0_mvpconf1(arg, cpu_env);
9c2149c8 4773 rn = "MVPConf1";
ead9360e 4774 break;
9c2149c8
TS
4775 default:
4776 goto die;
4777 }
4778 break;
4779 case 1:
4780 switch (sel) {
4781 case 0:
895c2d04 4782 gen_helper_mfc0_random(arg, cpu_env);
9c2149c8 4783 rn = "Random";
2423f660 4784 break;
9c2149c8 4785 case 1:
7385ac0b 4786 check_insn(env, ctx, ASE_MT);
7db13fae 4787 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEControl));
9c2149c8 4788 rn = "VPEControl";
ead9360e 4789 break;
9c2149c8 4790 case 2:
7385ac0b 4791 check_insn(env, ctx, ASE_MT);
7db13fae 4792 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf0));
9c2149c8 4793 rn = "VPEConf0";
ead9360e 4794 break;
9c2149c8 4795 case 3:
7385ac0b 4796 check_insn(env, ctx, ASE_MT);
7db13fae 4797 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf1));
9c2149c8 4798 rn = "VPEConf1";
ead9360e 4799 break;
9c2149c8 4800 case 4:
7385ac0b 4801 check_insn(env, ctx, ASE_MT);
7db13fae 4802 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_YQMask));
9c2149c8 4803 rn = "YQMask";
ead9360e 4804 break;
9c2149c8 4805 case 5:
7385ac0b 4806 check_insn(env, ctx, ASE_MT);
7db13fae 4807 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_VPESchedule));
9c2149c8 4808 rn = "VPESchedule";
ead9360e 4809 break;
9c2149c8 4810 case 6:
7385ac0b 4811 check_insn(env, ctx, ASE_MT);
7db13fae 4812 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_VPEScheFBack));
9c2149c8 4813 rn = "VPEScheFBack";
ead9360e 4814 break;
9c2149c8 4815 case 7:
7385ac0b 4816 check_insn(env, ctx, ASE_MT);
7db13fae 4817 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEOpt));
9c2149c8 4818 rn = "VPEOpt";
ead9360e 4819 break;
9c2149c8
TS
4820 default:
4821 goto die;
4822 }
4823 break;
4824 case 2:
4825 switch (sel) {
4826 case 0:
7db13fae 4827 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryLo0));
2423f660
TS
4828 rn = "EntryLo0";
4829 break;
9c2149c8 4830 case 1:
7385ac0b 4831 check_insn(env, ctx, ASE_MT);
895c2d04 4832 gen_helper_mfc0_tcstatus(arg, cpu_env);
2423f660 4833 rn = "TCStatus";
ead9360e 4834 break;
9c2149c8 4835 case 2:
7385ac0b 4836 check_insn(env, ctx, ASE_MT);
895c2d04 4837 gen_helper_mfc0_tcbind(arg, cpu_env);
2423f660 4838 rn = "TCBind";
ead9360e 4839 break;
9c2149c8 4840 case 3:
7385ac0b 4841 check_insn(env, ctx, ASE_MT);
895c2d04 4842 gen_helper_dmfc0_tcrestart(arg, cpu_env);
2423f660 4843 rn = "TCRestart";
ead9360e 4844 break;
9c2149c8 4845 case 4:
7385ac0b 4846 check_insn(env, ctx, ASE_MT);
895c2d04 4847 gen_helper_dmfc0_tchalt(arg, cpu_env);
2423f660 4848 rn = "TCHalt";
ead9360e 4849 break;
9c2149c8 4850 case 5:
7385ac0b 4851 check_insn(env, ctx, ASE_MT);
895c2d04 4852 gen_helper_dmfc0_tccontext(arg, cpu_env);
2423f660 4853 rn = "TCContext";
ead9360e 4854 break;
9c2149c8 4855 case 6:
7385ac0b 4856 check_insn(env, ctx, ASE_MT);
895c2d04 4857 gen_helper_dmfc0_tcschedule(arg, cpu_env);
2423f660 4858 rn = "TCSchedule";
ead9360e 4859 break;
9c2149c8 4860 case 7:
7385ac0b 4861 check_insn(env, ctx, ASE_MT);
895c2d04 4862 gen_helper_dmfc0_tcschefback(arg, cpu_env);
2423f660 4863 rn = "TCScheFBack";
ead9360e 4864 break;
9c2149c8
TS
4865 default:
4866 goto die;
4867 }
4868 break;
4869 case 3:
4870 switch (sel) {
4871 case 0:
7db13fae 4872 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryLo1));
2423f660
TS
4873 rn = "EntryLo1";
4874 break;
9c2149c8
TS
4875 default:
4876 goto die;
1579a72e 4877 }
9c2149c8
TS
4878 break;
4879 case 4:
4880 switch (sel) {
4881 case 0:
7db13fae 4882 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_Context));
2423f660
TS
4883 rn = "Context";
4884 break;
9c2149c8 4885 case 1:
d9bea114 4886// gen_helper_dmfc0_contextconfig(arg); /* SmartMIPS ASE */
2423f660
TS
4887 rn = "ContextConfig";
4888// break;
9c2149c8
TS
4889 default:
4890 goto die;
876d4b07 4891 }
9c2149c8
TS
4892 break;
4893 case 5:
4894 switch (sel) {
4895 case 0:
7db13fae 4896 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageMask));
2423f660
TS
4897 rn = "PageMask";
4898 break;
9c2149c8 4899 case 1:
e189e748 4900 check_insn(env, ctx, ISA_MIPS32R2);
7db13fae 4901 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageGrain));
2423f660
TS
4902 rn = "PageGrain";
4903 break;
9c2149c8
TS
4904 default:
4905 goto die;
876d4b07 4906 }
9c2149c8
TS
4907 break;
4908 case 6:
4909 switch (sel) {
4910 case 0:
7db13fae 4911 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Wired));
2423f660
TS
4912 rn = "Wired";
4913 break;
9c2149c8 4914 case 1:
e189e748 4915 check_insn(env, ctx, ISA_MIPS32R2);
7db13fae 4916 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf0));
2423f660 4917 rn = "SRSConf0";
ead9360e 4918 break;
9c2149c8 4919 case 2:
e189e748 4920 check_insn(env, ctx, ISA_MIPS32R2);
7db13fae 4921 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf1));
2423f660 4922 rn = "SRSConf1";
ead9360e 4923 break;
9c2149c8 4924 case 3:
e189e748 4925 check_insn(env, ctx, ISA_MIPS32R2);
7db13fae 4926 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf2));
2423f660 4927 rn = "SRSConf2";
ead9360e 4928 break;
9c2149c8 4929 case 4:
e189e748 4930 check_insn(env, ctx, ISA_MIPS32R2);
7db13fae 4931 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf3));
2423f660 4932 rn = "SRSConf3";
ead9360e 4933 break;
9c2149c8 4934 case 5:
e189e748 4935 check_insn(env, ctx, ISA_MIPS32R2);
7db13fae 4936 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf4));
2423f660 4937 rn = "SRSConf4";
ead9360e 4938 break;
9c2149c8
TS
4939 default:
4940 goto die;
876d4b07 4941 }
9c2149c8
TS
4942 break;
4943 case 7:
4944 switch (sel) {
4945 case 0:
e189e748 4946 check_insn(env, ctx, ISA_MIPS32R2);
7db13fae 4947 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_HWREna));
2423f660
TS
4948 rn = "HWREna";
4949 break;
9c2149c8
TS
4950 default:
4951 goto die;
876d4b07 4952 }
9c2149c8
TS
4953 break;
4954 case 8:
4955 switch (sel) {
4956 case 0:
7db13fae 4957 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_BadVAddr));
f0b3f3ae 4958 rn = "BadVAddr";
2423f660 4959 break;
9c2149c8
TS
4960 default:
4961 goto die;
876d4b07 4962 }
9c2149c8
TS
4963 break;
4964 case 9:
4965 switch (sel) {
4966 case 0:
2e70f6ef
PB
4967 /* Mark as an IO operation because we read the time. */
4968 if (use_icount)
4969 gen_io_start();
895c2d04 4970 gen_helper_mfc0_count(arg, cpu_env);
2e70f6ef
PB
4971 if (use_icount) {
4972 gen_io_end();
2e70f6ef 4973 }
55807224
EI
4974 /* Break the TB to be able to take timer interrupts immediately
4975 after reading count. */
4976 ctx->bstate = BS_STOP;
2423f660
TS
4977 rn = "Count";
4978 break;
4979 /* 6,7 are implementation dependent */
9c2149c8
TS
4980 default:
4981 goto die;
876d4b07 4982 }
9c2149c8
TS
4983 break;
4984 case 10:
4985 switch (sel) {
4986 case 0:
7db13fae 4987 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryHi));
2423f660
TS
4988 rn = "EntryHi";
4989 break;
9c2149c8
TS
4990 default:
4991 goto die;
876d4b07 4992 }
9c2149c8
TS
4993 break;
4994 case 11:
4995 switch (sel) {
4996 case 0:
7db13fae 4997 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Compare));
2423f660
TS
4998 rn = "Compare";
4999 break;
876d4b07 5000 /* 6,7 are implementation dependent */
9c2149c8
TS
5001 default:
5002 goto die;
876d4b07 5003 }
9c2149c8
TS
5004 break;
5005 case 12:
5006 switch (sel) {
5007 case 0:
7db13fae 5008 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Status));
2423f660
TS
5009 rn = "Status";
5010 break;
9c2149c8 5011 case 1:
e189e748 5012 check_insn(env, ctx, ISA_MIPS32R2);
7db13fae 5013 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_IntCtl));
2423f660
TS
5014 rn = "IntCtl";
5015 break;
9c2149c8 5016 case 2:
e189e748 5017 check_insn(env, ctx, ISA_MIPS32R2);
7db13fae 5018 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSCtl));
2423f660
TS
5019 rn = "SRSCtl";
5020 break;
9c2149c8 5021 case 3:
e189e748 5022 check_insn(env, ctx, ISA_MIPS32R2);
7db13fae 5023 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
2423f660
TS
5024 rn = "SRSMap";
5025 break;
9c2149c8
TS
5026 default:
5027 goto die;
876d4b07 5028 }
9c2149c8
TS
5029 break;
5030 case 13:
5031 switch (sel) {
5032 case 0:
7db13fae 5033 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Cause));
2423f660
TS
5034 rn = "Cause";
5035 break;
9c2149c8
TS
5036 default:
5037 goto die;
876d4b07 5038 }
9c2149c8
TS
5039 break;
5040 case 14:
5041 switch (sel) {
5042 case 0:
7db13fae 5043 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EPC));
2423f660
TS
5044 rn = "EPC";
5045 break;
9c2149c8
TS
5046 default:
5047 goto die;
876d4b07 5048 }
9c2149c8
TS
5049 break;
5050 case 15:
5051 switch (sel) {
5052 case 0:
7db13fae 5053 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PRid));
2423f660
TS
5054 rn = "PRid";
5055 break;
9c2149c8 5056 case 1:
e189e748 5057 check_insn(env, ctx, ISA_MIPS32R2);
7db13fae 5058 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_EBase));
2423f660
TS
5059 rn = "EBase";
5060 break;
9c2149c8
TS
5061 default:
5062 goto die;
876d4b07 5063 }
9c2149c8
TS
5064 break;
5065 case 16:
5066 switch (sel) {
5067 case 0:
7db13fae 5068 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config0));
9c2149c8
TS
5069 rn = "Config";
5070 break;
5071 case 1:
7db13fae 5072 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config1));
9c2149c8
TS
5073 rn = "Config1";
5074 break;
5075 case 2:
7db13fae 5076 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config2));
9c2149c8
TS
5077 rn = "Config2";
5078 break;
5079 case 3:
7db13fae 5080 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config3));
9c2149c8
TS
5081 rn = "Config3";
5082 break;
5083 /* 6,7 are implementation dependent */
f0b3f3ae 5084 case 6:
7db13fae 5085 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config6));
f0b3f3ae
TS
5086 rn = "Config6";
5087 break;
5088 case 7:
7db13fae 5089 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config7));
f0b3f3ae
TS
5090 rn = "Config7";
5091 break;
9c2149c8
TS
5092 default:
5093 goto die;
5094 }
5095 break;
5096 case 17:
5097 switch (sel) {
5098 case 0:
895c2d04 5099 gen_helper_dmfc0_lladdr(arg, cpu_env);
2423f660
TS
5100 rn = "LLAddr";
5101 break;
9c2149c8
TS
5102 default:
5103 goto die;
5104 }
5105 break;
5106 case 18:
5107 switch (sel) {
fd88b6ab 5108 case 0 ... 7:
895c2d04 5109 gen_helper_1e0i(dmfc0_watchlo, arg, sel);
2423f660
TS
5110 rn = "WatchLo";
5111 break;
9c2149c8
TS
5112 default:
5113 goto die;
5114 }
5115 break;
5116 case 19:
5117 switch (sel) {
fd88b6ab 5118 case 0 ... 7:
895c2d04 5119 gen_helper_1e0i(mfc0_watchhi, arg, sel);
2423f660
TS
5120 rn = "WatchHi";
5121 break;
9c2149c8
TS
5122 default:
5123 goto die;
5124 }
5125 break;
5126 case 20:
5127 switch (sel) {
5128 case 0:
e189e748 5129 check_insn(env, ctx, ISA_MIPS3);
7db13fae 5130 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_XContext));
2423f660
TS
5131 rn = "XContext";
5132 break;
9c2149c8
TS
5133 default:
5134 goto die;
5135 }
5136 break;
5137 case 21:
5138 /* Officially reserved, but sel 0 is used for R1x000 framemask */
5139 switch (sel) {
5140 case 0:
7db13fae 5141 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Framemask));
2423f660
TS
5142 rn = "Framemask";
5143 break;
9c2149c8
TS
5144 default:
5145 goto die;
5146 }
5147 break;
5148 case 22:
d9bea114 5149 tcg_gen_movi_tl(arg, 0); /* unimplemented */
2423f660
TS
5150 rn = "'Diagnostic"; /* implementation dependent */
5151 break;
9c2149c8
TS
5152 case 23:
5153 switch (sel) {
5154 case 0:
895c2d04 5155 gen_helper_mfc0_debug(arg, cpu_env); /* EJTAG support */
2423f660
TS
5156 rn = "Debug";
5157 break;
9c2149c8 5158 case 1:
895c2d04 5159// gen_helper_dmfc0_tracecontrol(arg, cpu_env); /* PDtrace support */
2423f660
TS
5160 rn = "TraceControl";
5161// break;
9c2149c8 5162 case 2:
895c2d04 5163// gen_helper_dmfc0_tracecontrol2(arg, cpu_env); /* PDtrace support */
2423f660
TS
5164 rn = "TraceControl2";
5165// break;
9c2149c8 5166 case 3:
895c2d04 5167// gen_helper_dmfc0_usertracedata(arg, cpu_env); /* PDtrace support */
2423f660
TS
5168 rn = "UserTraceData";
5169// break;
9c2149c8 5170 case 4:
895c2d04 5171// gen_helper_dmfc0_tracebpc(arg, cpu_env); /* PDtrace support */
2423f660
TS
5172 rn = "TraceBPC";
5173// break;
9c2149c8
TS
5174 default:
5175 goto die;
5176 }
5177 break;
5178 case 24:
5179 switch (sel) {
5180 case 0:
f0b3f3ae 5181 /* EJTAG support */
7db13fae 5182 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_DEPC));
2423f660
TS
5183 rn = "DEPC";
5184 break;
9c2149c8
TS
5185 default:
5186 goto die;
5187 }
5188 break;
5189 case 25:
5190 switch (sel) {
5191 case 0:
7db13fae 5192 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Performance0));
2423f660 5193 rn = "Performance0";
9c2149c8
TS
5194 break;
5195 case 1:
d9bea114 5196// gen_helper_dmfc0_performance1(arg);
2423f660
TS
5197 rn = "Performance1";
5198// break;
9c2149c8 5199 case 2:
d9bea114 5200// gen_helper_dmfc0_performance2(arg);
2423f660
TS
5201 rn = "Performance2";
5202// break;
9c2149c8 5203 case 3:
d9bea114 5204// gen_helper_dmfc0_performance3(arg);
2423f660
TS
5205 rn = "Performance3";
5206// break;
9c2149c8 5207 case 4:
d9bea114 5208// gen_helper_dmfc0_performance4(arg);
2423f660
TS
5209 rn = "Performance4";
5210// break;
9c2149c8 5211 case 5:
d9bea114 5212// gen_helper_dmfc0_performance5(arg);
2423f660
TS
5213 rn = "Performance5";
5214// break;
9c2149c8 5215 case 6:
d9bea114 5216// gen_helper_dmfc0_performance6(arg);
2423f660
TS
5217 rn = "Performance6";
5218// break;
9c2149c8 5219 case 7:
d9bea114 5220// gen_helper_dmfc0_performance7(arg);
2423f660
TS
5221 rn = "Performance7";
5222// break;
9c2149c8
TS
5223 default:
5224 goto die;
5225 }
5226 break;
5227 case 26:
d9bea114 5228 tcg_gen_movi_tl(arg, 0); /* unimplemented */
da80682b
AJ
5229 rn = "ECC";
5230 break;
9c2149c8
TS
5231 case 27:
5232 switch (sel) {
5233 /* ignored */
5234 case 0 ... 3:
d9bea114 5235 tcg_gen_movi_tl(arg, 0); /* unimplemented */
2423f660
TS
5236 rn = "CacheErr";
5237 break;
9c2149c8
TS
5238 default:
5239 goto die;
5240 }
5241 break;
5242 case 28:
5243 switch (sel) {
5244 case 0:
5245 case 2:
5246 case 4:
5247 case 6:
7db13fae 5248 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_TagLo));
9c2149c8
TS
5249 rn = "TagLo";
5250 break;
5251 case 1:
5252 case 3:
5253 case 5:
5254 case 7:
7db13fae 5255 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataLo));
9c2149c8
TS
5256 rn = "DataLo";
5257 break;
5258 default:
5259 goto die;
5260 }
5261 break;
5262 case 29:
5263 switch (sel) {
5264 case 0:
5265 case 2:
5266 case 4:
5267 case 6:
7db13fae 5268 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_TagHi));
9c2149c8
TS
5269 rn = "TagHi";
5270 break;
5271 case 1:
5272 case 3:
5273 case 5:
5274 case 7:
7db13fae 5275 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataHi));
9c2149c8
TS
5276 rn = "DataHi";
5277 break;
5278 default:
5279 goto die;
5280 }
5281 break;
5282 case 30:
5283 switch (sel) {
5284 case 0:
7db13fae 5285 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_ErrorEPC));
2423f660
TS
5286 rn = "ErrorEPC";
5287 break;
9c2149c8
TS
5288 default:
5289 goto die;
5290 }
5291 break;
5292 case 31:
5293 switch (sel) {
5294 case 0:
f0b3f3ae 5295 /* EJTAG support */
7db13fae 5296 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
2423f660
TS
5297 rn = "DESAVE";
5298 break;
9c2149c8
TS
5299 default:
5300 goto die;
5301 }
5302 break;
5303 default:
876d4b07 5304 goto die;
9c2149c8 5305 }
2abf314d 5306 (void)rn; /* avoid a compiler warning */
d12d51d5 5307 LOG_DISAS("dmfc0 %s (reg %d sel %d)\n", rn, reg, sel);
9c2149c8
TS
5308 return;
5309
5310die:
d12d51d5 5311 LOG_DISAS("dmfc0 %s (reg %d sel %d)\n", rn, reg, sel);
9c2149c8
TS
5312 generate_exception(ctx, EXCP_RI);
5313}
5314
7db13fae 5315static void gen_dmtc0 (CPUMIPSState *env, DisasContext *ctx, TCGv arg, int reg, int sel)
9c2149c8
TS
5316{
5317 const char *rn = "invalid";
5318
e189e748
TS
5319 if (sel != 0)
5320 check_insn(env, ctx, ISA_MIPS64);
5321
2e70f6ef
PB
5322 if (use_icount)
5323 gen_io_start();
5324
9c2149c8
TS
5325 switch (reg) {
5326 case 0:
5327 switch (sel) {
5328 case 0:
895c2d04 5329 gen_helper_mtc0_index(cpu_env, arg);
9c2149c8
TS
5330 rn = "Index";
5331 break;
5332 case 1:
7385ac0b 5333 check_insn(env, ctx, ASE_MT);
895c2d04 5334 gen_helper_mtc0_mvpcontrol(cpu_env, arg);
9c2149c8 5335 rn = "MVPControl";
ead9360e 5336 break;
9c2149c8 5337 case 2:
7385ac0b 5338 check_insn(env, ctx, ASE_MT);
ead9360e 5339 /* ignored */
9c2149c8 5340 rn = "MVPConf0";
ead9360e 5341 break;
9c2149c8 5342 case 3:
7385ac0b 5343 check_insn(env, ctx, ASE_MT);
ead9360e 5344 /* ignored */
9c2149c8 5345 rn = "MVPConf1";
ead9360e 5346 break;
9c2149c8
TS
5347 default:
5348 goto die;
5349 }
5350 break;
5351 case 1:
5352 switch (sel) {
5353 case 0:
2423f660 5354 /* ignored */
9c2149c8 5355 rn = "Random";
2423f660 5356 break;
9c2149c8 5357 case 1:
7385ac0b 5358 check_insn(env, ctx, ASE_MT);
895c2d04 5359 gen_helper_mtc0_vpecontrol(cpu_env, arg);
9c2149c8 5360 rn = "VPEControl";
ead9360e 5361 break;
9c2149c8 5362 case 2:
7385ac0b 5363 check_insn(env, ctx, ASE_MT);
895c2d04 5364 gen_helper_mtc0_vpeconf0(cpu_env, arg);
9c2149c8 5365 rn = "VPEConf0";
ead9360e 5366 break;
9c2149c8 5367 case 3:
7385ac0b 5368 check_insn(env, ctx, ASE_MT);
895c2d04 5369 gen_helper_mtc0_vpeconf1(cpu_env, arg);
9c2149c8 5370 rn = "VPEConf1";
ead9360e 5371 break;
9c2149c8 5372 case 4:
7385ac0b 5373 check_insn(env, ctx, ASE_MT);
895c2d04 5374 gen_helper_mtc0_yqmask(cpu_env, arg);
9c2149c8 5375 rn = "YQMask";
ead9360e 5376 break;
9c2149c8 5377 case 5:
7385ac0b 5378 check_insn(env, ctx, ASE_MT);
7db13fae 5379 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_VPESchedule));
9c2149c8 5380 rn = "VPESchedule";
ead9360e 5381 break;
9c2149c8 5382 case 6:
7385ac0b 5383 check_insn(env, ctx, ASE_MT);
7db13fae 5384 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_VPEScheFBack));
9c2149c8 5385 rn = "VPEScheFBack";
ead9360e 5386 break;
9c2149c8 5387 case 7:
7385ac0b 5388 check_insn(env, ctx, ASE_MT);
895c2d04 5389 gen_helper_mtc0_vpeopt(cpu_env, arg);
9c2149c8 5390 rn = "VPEOpt";
ead9360e 5391 break;
9c2149c8
TS
5392 default:
5393 goto die;
5394 }
5395 break;
5396 case 2:
5397 switch (sel) {
5398 case 0:
895c2d04 5399 gen_helper_mtc0_entrylo0(cpu_env, arg);
2423f660
TS
5400 rn = "EntryLo0";
5401 break;
9c2149c8 5402 case 1:
7385ac0b 5403 check_insn(env, ctx, ASE_MT);
895c2d04 5404 gen_helper_mtc0_tcstatus(cpu_env, arg);
2423f660 5405 rn = "TCStatus";
ead9360e 5406 break;
9c2149c8 5407 case 2:
7385ac0b 5408 check_insn(env, ctx, ASE_MT);
895c2d04 5409 gen_helper_mtc0_tcbind(cpu_env, arg);
2423f660 5410 rn = "TCBind";
ead9360e 5411 break;
9c2149c8 5412 case 3:
7385ac0b 5413 check_insn(env, ctx, ASE_MT);
895c2d04 5414 gen_helper_mtc0_tcrestart(cpu_env, arg);
2423f660 5415 rn = "TCRestart";
ead9360e 5416 break;
9c2149c8 5417 case 4:
7385ac0b 5418 check_insn(env, ctx, ASE_MT);
895c2d04 5419 gen_helper_mtc0_tchalt(cpu_env, arg);
2423f660 5420 rn = "TCHalt";
ead9360e 5421 break;
9c2149c8 5422 case 5:
7385ac0b 5423 check_insn(env, ctx, ASE_MT);
895c2d04 5424 gen_helper_mtc0_tccontext(cpu_env, arg);
2423f660 5425 rn = "TCContext";
ead9360e 5426 break;
9c2149c8 5427 case 6:
7385ac0b 5428 check_insn(env, ctx, ASE_MT);
895c2d04 5429 gen_helper_mtc0_tcschedule(cpu_env, arg);
2423f660 5430 rn = "TCSchedule";
ead9360e 5431 break;
9c2149c8 5432 case 7:
7385ac0b 5433 check_insn(env, ctx, ASE_MT);
895c2d04 5434 gen_helper_mtc0_tcschefback(cpu_env, arg);
2423f660 5435 rn = "TCScheFBack";
ead9360e 5436 break;
9c2149c8
TS
5437 default:
5438 goto die;
5439 }
5440 break;
5441 case 3:
5442 switch (sel) {
5443 case 0:
895c2d04 5444 gen_helper_mtc0_entrylo1(cpu_env, arg);
2423f660
TS
5445 rn = "EntryLo1";
5446 break;
9c2149c8
TS
5447 default:
5448 goto die;
876d4b07 5449 }
9c2149c8
TS
5450 break;
5451 case 4:
5452 switch (sel) {
5453 case 0:
895c2d04 5454 gen_helper_mtc0_context(cpu_env, arg);
2423f660
TS
5455 rn = "Context";
5456 break;
9c2149c8 5457 case 1:
895c2d04 5458// gen_helper_mtc0_contextconfig(cpu_env, arg); /* SmartMIPS ASE */
2423f660
TS
5459 rn = "ContextConfig";
5460// break;
9c2149c8
TS
5461 default:
5462 goto die;
876d4b07 5463 }
9c2149c8
TS
5464 break;
5465 case 5:
5466 switch (sel) {
5467 case 0:
895c2d04 5468 gen_helper_mtc0_pagemask(cpu_env, arg);
2423f660
TS
5469 rn = "PageMask";
5470 break;
9c2149c8 5471 case 1:
e189e748 5472 check_insn(env, ctx, ISA_MIPS32R2);
895c2d04 5473 gen_helper_mtc0_pagegrain(cpu_env, arg);
2423f660
TS
5474 rn = "PageGrain";
5475 break;
9c2149c8
TS
5476 default:
5477 goto die;
876d4b07 5478 }
9c2149c8
TS
5479 break;
5480 case 6:
5481 switch (sel) {
5482 case 0:
895c2d04 5483 gen_helper_mtc0_wired(cpu_env, arg);
2423f660
TS
5484 rn = "Wired";
5485 break;
9c2149c8 5486 case 1:
e189e748 5487 check_insn(env, ctx, ISA_MIPS32R2);
895c2d04 5488 gen_helper_mtc0_srsconf0(cpu_env, arg);
2423f660 5489 rn = "SRSConf0";
ead9360e 5490 break;
9c2149c8 5491 case 2:
e189e748 5492 check_insn(env, ctx, ISA_MIPS32R2);
895c2d04 5493 gen_helper_mtc0_srsconf1(cpu_env, arg);
2423f660 5494 rn = "SRSConf1";
ead9360e 5495 break;
9c2149c8 5496 case 3:
e189e748 5497 check_insn(env, ctx, ISA_MIPS32R2);
895c2d04 5498 gen_helper_mtc0_srsconf2(cpu_env, arg);
2423f660 5499 rn = "SRSConf2";
ead9360e 5500 break;
9c2149c8 5501 case 4:
e189e748 5502 check_insn(env, ctx, ISA_MIPS32R2);
895c2d04 5503 gen_helper_mtc0_srsconf3(cpu_env, arg);
2423f660 5504 rn = "SRSConf3";
ead9360e 5505 break;
9c2149c8 5506 case 5:
e189e748 5507 check_insn(env, ctx, ISA_MIPS32R2);
895c2d04 5508 gen_helper_mtc0_srsconf4(cpu_env, arg);
2423f660 5509 rn = "SRSConf4";
ead9360e 5510 break;
9c2149c8
TS
5511 default:
5512 goto die;
876d4b07 5513 }
9c2149c8
TS
5514 break;
5515 case 7:
5516 switch (sel) {
5517 case 0:
e189e748 5518 check_insn(env, ctx, ISA_MIPS32R2);
895c2d04 5519 gen_helper_mtc0_hwrena(cpu_env, arg);
2423f660
TS
5520 rn = "HWREna";
5521 break;
9c2149c8
TS
5522 default:
5523 goto die;
876d4b07 5524 }
9c2149c8
TS
5525 break;
5526 case 8:
5527 /* ignored */
f0b3f3ae 5528 rn = "BadVAddr";
9c2149c8
TS
5529 break;
5530 case 9:
5531 switch (sel) {
5532 case 0:
895c2d04 5533 gen_helper_mtc0_count(cpu_env, arg);
2423f660
TS
5534 rn = "Count";
5535 break;
876d4b07 5536 /* 6,7 are implementation dependent */
9c2149c8
TS
5537 default:
5538 goto die;
876d4b07
TS
5539 }
5540 /* Stop translation as we may have switched the execution mode */
5541 ctx->bstate = BS_STOP;
9c2149c8
TS
5542 break;
5543 case 10:
5544 switch (sel) {
5545 case 0:
895c2d04 5546 gen_helper_mtc0_entryhi(cpu_env, arg);
2423f660
TS
5547 rn = "EntryHi";
5548 break;
9c2149c8
TS
5549 default:
5550 goto die;
876d4b07 5551 }
9c2149c8
TS
5552 break;
5553 case 11:
5554 switch (sel) {
5555 case 0:
895c2d04 5556 gen_helper_mtc0_compare(cpu_env, arg);
2423f660
TS
5557 rn = "Compare";
5558 break;
876d4b07 5559 /* 6,7 are implementation dependent */
9c2149c8
TS
5560 default:
5561 goto die;
876d4b07 5562 }
de9a95f0
AJ
5563 /* Stop translation as we may have switched the execution mode */
5564 ctx->bstate = BS_STOP;
9c2149c8
TS
5565 break;
5566 case 12:
5567 switch (sel) {
5568 case 0:
867abc7e 5569 save_cpu_state(ctx, 1);
895c2d04 5570 gen_helper_mtc0_status(cpu_env, arg);
8487327a
TS
5571 /* BS_STOP isn't good enough here, hflags may have changed. */
5572 gen_save_pc(ctx->pc + 4);
5573 ctx->bstate = BS_EXCP;
2423f660
TS
5574 rn = "Status";
5575 break;
9c2149c8 5576 case 1:
e189e748 5577 check_insn(env, ctx, ISA_MIPS32R2);
895c2d04 5578 gen_helper_mtc0_intctl(cpu_env, arg);
8487327a
TS
5579 /* Stop translation as we may have switched the execution mode */
5580 ctx->bstate = BS_STOP;
2423f660
TS
5581 rn = "IntCtl";
5582 break;
9c2149c8 5583 case 2:
e189e748 5584 check_insn(env, ctx, ISA_MIPS32R2);
895c2d04 5585 gen_helper_mtc0_srsctl(cpu_env, arg);
8487327a
TS
5586 /* Stop translation as we may have switched the execution mode */
5587 ctx->bstate = BS_STOP;
2423f660
TS
5588 rn = "SRSCtl";
5589 break;
9c2149c8 5590 case 3:
e189e748 5591 check_insn(env, ctx, ISA_MIPS32R2);
7db13fae 5592 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
8487327a
TS
5593 /* Stop translation as we may have switched the execution mode */
5594 ctx->bstate = BS_STOP;
2423f660
TS
5595 rn = "SRSMap";
5596 break;
5597 default:
9c2149c8 5598 goto die;
876d4b07 5599 }
9c2149c8
TS
5600 break;
5601 case 13:
5602 switch (sel) {
5603 case 0:
867abc7e 5604 save_cpu_state(ctx, 1);
5dc5d9f0
AJ
5605 /* Mark as an IO operation because we may trigger a software
5606 interrupt. */
5607 if (use_icount) {
5608 gen_io_start();
5609 }
895c2d04 5610 gen_helper_mtc0_cause(cpu_env, arg);
5dc5d9f0
AJ
5611 if (use_icount) {
5612 gen_io_end();
5613 }
5614 /* Stop translation as we may have triggered an intetrupt */
5615 ctx->bstate = BS_STOP;
2423f660
TS
5616 rn = "Cause";
5617 break;
9c2149c8
TS
5618 default:
5619 goto die;
876d4b07 5620 }
9c2149c8
TS
5621 break;
5622 case 14:
5623 switch (sel) {
5624 case 0:
7db13fae 5625 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EPC));
2423f660
TS
5626 rn = "EPC";
5627 break;
9c2149c8
TS
5628 default:
5629 goto die;
876d4b07 5630 }
9c2149c8
TS
5631 break;
5632 case 15:
5633 switch (sel) {
5634 case 0:
2423f660
TS
5635 /* ignored */
5636 rn = "PRid";
5637 break;
9c2149c8 5638 case 1:
e189e748 5639 check_insn(env, ctx, ISA_MIPS32R2);
895c2d04 5640 gen_helper_mtc0_ebase(cpu_env, arg);
2423f660
TS
5641 rn = "EBase";
5642 break;
9c2149c8
TS
5643 default:
5644 goto die;
876d4b07 5645 }
9c2149c8
TS
5646 break;
5647 case 16:
5648 switch (sel) {
5649 case 0:
895c2d04 5650 gen_helper_mtc0_config0(cpu_env, arg);
9c2149c8 5651 rn = "Config";
2423f660
TS
5652 /* Stop translation as we may have switched the execution mode */
5653 ctx->bstate = BS_STOP;
9c2149c8
TS
5654 break;
5655 case 1:
1fc7bf6e 5656 /* ignored, read only */
9c2149c8
TS
5657 rn = "Config1";
5658 break;
5659 case 2:
895c2d04 5660 gen_helper_mtc0_config2(cpu_env, arg);
9c2149c8 5661 rn = "Config2";
2423f660
TS
5662 /* Stop translation as we may have switched the execution mode */
5663 ctx->bstate = BS_STOP;
9c2149c8
TS
5664 break;
5665 case 3:
2423f660 5666 /* ignored */
9c2149c8
TS
5667 rn = "Config3";
5668 break;
5669 /* 6,7 are implementation dependent */
5670 default:
5671 rn = "Invalid config selector";
5672 goto die;
5673 }
9c2149c8
TS
5674 break;
5675 case 17:
5676 switch (sel) {
5677 case 0:
895c2d04 5678 gen_helper_mtc0_lladdr(cpu_env, arg);
2423f660
TS
5679 rn = "LLAddr";
5680 break;
9c2149c8
TS
5681 default:
5682 goto die;
5683 }
5684 break;
5685 case 18:
5686 switch (sel) {
fd88b6ab 5687 case 0 ... 7:
895c2d04 5688 gen_helper_0e1i(mtc0_watchlo, arg, sel);
2423f660
TS
5689 rn = "WatchLo";
5690 break;
9c2149c8
TS
5691 default:
5692 goto die;
5693 }
5694 break;
5695 case 19:
5696 switch (sel) {
fd88b6ab 5697 case 0 ... 7:
895c2d04 5698 gen_helper_0e1i(mtc0_watchhi, arg, sel);
2423f660
TS
5699 rn = "WatchHi";
5700 break;
9c2149c8
TS
5701 default:
5702 goto die;
5703 }
5704 break;
5705 case 20:
5706 switch (sel) {
5707 case 0:
e189e748 5708 check_insn(env, ctx, ISA_MIPS3);
895c2d04 5709 gen_helper_mtc0_xcontext(cpu_env, arg);
2423f660
TS
5710 rn = "XContext";
5711 break;
9c2149c8
TS
5712 default:
5713 goto die;
5714 }
5715 break;
5716 case 21:
5717 /* Officially reserved, but sel 0 is used for R1x000 framemask */
5718 switch (sel) {
5719 case 0:
895c2d04 5720 gen_helper_mtc0_framemask(cpu_env, arg);
2423f660
TS
5721 rn = "Framemask";
5722 break;
9c2149c8
TS
5723 default:
5724 goto die;
5725 }
5726 break;
5727 case 22:
5728 /* ignored */
5729 rn = "Diagnostic"; /* implementation dependent */
876d4b07 5730 break;
9c2149c8
TS
5731 case 23:
5732 switch (sel) {
5733 case 0:
895c2d04 5734 gen_helper_mtc0_debug(cpu_env, arg); /* EJTAG support */
8487327a
TS
5735 /* BS_STOP isn't good enough here, hflags may have changed. */
5736 gen_save_pc(ctx->pc + 4);
5737 ctx->bstate = BS_EXCP;
2423f660
TS
5738 rn = "Debug";
5739 break;
9c2149c8 5740 case 1:
895c2d04 5741// gen_helper_mtc0_tracecontrol(cpu_env, arg); /* PDtrace support */
8487327a
TS
5742 /* Stop translation as we may have switched the execution mode */
5743 ctx->bstate = BS_STOP;
2423f660
TS
5744 rn = "TraceControl";
5745// break;
9c2149c8 5746 case 2:
895c2d04 5747// gen_helper_mtc0_tracecontrol2(cpu_env, arg); /* PDtrace support */
8487327a
TS
5748 /* Stop translation as we may have switched the execution mode */
5749 ctx->bstate = BS_STOP;
2423f660
TS
5750 rn = "TraceControl2";
5751// break;
9c2149c8 5752 case 3:
895c2d04 5753// gen_helper_mtc0_usertracedata(cpu_env, arg); /* PDtrace support */
8487327a
TS
5754 /* Stop translation as we may have switched the execution mode */
5755 ctx->bstate = BS_STOP;
2423f660
TS
5756 rn = "UserTraceData";
5757// break;
9c2149c8 5758 case 4:
895c2d04 5759// gen_helper_mtc0_tracebpc(cpu_env, arg); /* PDtrace support */
8487327a
TS
5760 /* Stop translation as we may have switched the execution mode */
5761 ctx->bstate = BS_STOP;
2423f660
TS
5762 rn = "TraceBPC";
5763// break;
9c2149c8
TS
5764 default:
5765 goto die;
5766 }
9c2149c8
TS
5767 break;
5768 case 24:
5769 switch (sel) {
5770 case 0:
f1aa6320 5771 /* EJTAG support */
7db13fae 5772 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_DEPC));
2423f660
TS
5773 rn = "DEPC";
5774 break;
9c2149c8
TS
5775 default:
5776 goto die;
5777 }
5778 break;
5779 case 25:
5780 switch (sel) {
5781 case 0:
895c2d04 5782 gen_helper_mtc0_performance0(cpu_env, arg);
2423f660
TS
5783 rn = "Performance0";
5784 break;
9c2149c8 5785 case 1:
895c2d04 5786// gen_helper_mtc0_performance1(cpu_env, arg);
2423f660
TS
5787 rn = "Performance1";
5788// break;
9c2149c8 5789 case 2:
895c2d04 5790// gen_helper_mtc0_performance2(cpu_env, arg);
2423f660
TS
5791 rn = "Performance2";
5792// break;
9c2149c8 5793 case 3:
895c2d04 5794// gen_helper_mtc0_performance3(cpu_env, arg);
2423f660
TS
5795 rn = "Performance3";
5796// break;
9c2149c8 5797 case 4:
895c2d04 5798// gen_helper_mtc0_performance4(cpu_env, arg);
2423f660
TS
5799 rn = "Performance4";
5800// break;
9c2149c8 5801 case 5:
895c2d04 5802// gen_helper_mtc0_performance5(cpu_env, arg);
2423f660
TS
5803 rn = "Performance5";
5804// break;
9c2149c8 5805 case 6:
895c2d04 5806// gen_helper_mtc0_performance6(cpu_env, arg);
2423f660
TS
5807 rn = "Performance6";
5808// break;
9c2149c8 5809 case 7:
895c2d04 5810// gen_helper_mtc0_performance7(cpu_env, arg);
2423f660
TS
5811 rn = "Performance7";
5812// break;
9c2149c8
TS
5813 default:
5814 goto die;
5815 }
876d4b07 5816 break;
9c2149c8 5817 case 26:
876d4b07 5818 /* ignored */
9c2149c8 5819 rn = "ECC";
876d4b07 5820 break;
9c2149c8
TS
5821 case 27:
5822 switch (sel) {
5823 case 0 ... 3:
2423f660
TS
5824 /* ignored */
5825 rn = "CacheErr";
5826 break;
9c2149c8
TS
5827 default:
5828 goto die;
5829 }
876d4b07 5830 break;
9c2149c8
TS
5831 case 28:
5832 switch (sel) {
5833 case 0:
5834 case 2:
5835 case 4:
5836 case 6:
895c2d04 5837 gen_helper_mtc0_taglo(cpu_env, arg);
9c2149c8
TS
5838 rn = "TagLo";
5839 break;
5840 case 1:
5841 case 3:
5842 case 5:
5843 case 7:
895c2d04 5844 gen_helper_mtc0_datalo(cpu_env, arg);
9c2149c8
TS
5845 rn = "DataLo";
5846 break;
5847 default:
5848 goto die;
5849 }
5850 break;
5851 case 29:
5852 switch (sel) {
5853 case 0:
5854 case 2:
5855 case 4:
5856 case 6:
895c2d04 5857 gen_helper_mtc0_taghi(cpu_env, arg);
9c2149c8
TS
5858 rn = "TagHi";
5859 break;
5860 case 1:
5861 case 3:
5862 case 5:
5863 case 7:
895c2d04 5864 gen_helper_mtc0_datahi(cpu_env, arg);
9c2149c8
TS
5865 rn = "DataHi";
5866 break;
5867 default:
5868 rn = "invalid sel";
5869 goto die;
5870 }
876d4b07 5871 break;
9c2149c8
TS
5872 case 30:
5873 switch (sel) {
5874 case 0:
7db13fae 5875 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_ErrorEPC));
2423f660
TS
5876 rn = "ErrorEPC";
5877 break;
9c2149c8
TS
5878 default:
5879 goto die;
5880 }
5881 break;
5882 case 31:
5883 switch (sel) {
5884 case 0:
f1aa6320 5885 /* EJTAG support */
7db13fae 5886 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
2423f660
TS
5887 rn = "DESAVE";
5888 break;
9c2149c8
TS
5889 default:
5890 goto die;
5891 }
876d4b07
TS
5892 /* Stop translation as we may have switched the execution mode */
5893 ctx->bstate = BS_STOP;
9c2149c8
TS
5894 break;
5895 default:
876d4b07 5896 goto die;
9c2149c8 5897 }
2abf314d 5898 (void)rn; /* avoid a compiler warning */
d12d51d5 5899 LOG_DISAS("dmtc0 %s (reg %d sel %d)\n", rn, reg, sel);
bf20dc07 5900 /* For simplicity assume that all writes can cause interrupts. */
2e70f6ef
PB
5901 if (use_icount) {
5902 gen_io_end();
5903 ctx->bstate = BS_STOP;
5904 }
9c2149c8
TS
5905 return;
5906
5907die:
d12d51d5 5908 LOG_DISAS("dmtc0 %s (reg %d sel %d)\n", rn, reg, sel);
9c2149c8
TS
5909 generate_exception(ctx, EXCP_RI);
5910}
d26bc211 5911#endif /* TARGET_MIPS64 */
9c2149c8 5912
7db13fae 5913static void gen_mftr(CPUMIPSState *env, DisasContext *ctx, int rt, int rd,
ead9360e
TS
5914 int u, int sel, int h)
5915{
5916 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
a7812ae4 5917 TCGv t0 = tcg_temp_local_new();
ead9360e
TS
5918
5919 if ((env->CP0_VPEConf0 & (1 << CP0VPEC0_MVP)) == 0 &&
b5dc7732
TS
5920 ((env->tcs[other_tc].CP0_TCBind & (0xf << CP0TCBd_CurVPE)) !=
5921 (env->active_tc.CP0_TCBind & (0xf << CP0TCBd_CurVPE))))
1a3fd9c3 5922 tcg_gen_movi_tl(t0, -1);
ead9360e
TS
5923 else if ((env->CP0_VPEControl & (0xff << CP0VPECo_TargTC)) >
5924 (env->mvp->CP0_MVPConf0 & (0xff << CP0MVPC0_PTC)))
1a3fd9c3 5925 tcg_gen_movi_tl(t0, -1);
ead9360e
TS
5926 else if (u == 0) {
5927 switch (rt) {
5a25ce94
EI
5928 case 1:
5929 switch (sel) {
5930 case 1:
895c2d04 5931 gen_helper_mftc0_vpecontrol(t0, cpu_env);
5a25ce94
EI
5932 break;
5933 case 2:
895c2d04 5934 gen_helper_mftc0_vpeconf0(t0, cpu_env);
5a25ce94
EI
5935 break;
5936 default:
5937 goto die;
5938 break;
5939 }
5940 break;
ead9360e
TS
5941 case 2:
5942 switch (sel) {
5943 case 1:
895c2d04 5944 gen_helper_mftc0_tcstatus(t0, cpu_env);
ead9360e
TS
5945 break;
5946 case 2:
895c2d04 5947 gen_helper_mftc0_tcbind(t0, cpu_env);
ead9360e
TS
5948 break;
5949 case 3:
895c2d04 5950 gen_helper_mftc0_tcrestart(t0, cpu_env);
ead9360e
TS
5951 break;
5952 case 4:
895c2d04 5953 gen_helper_mftc0_tchalt(t0, cpu_env);
ead9360e
TS
5954 break;
5955 case 5:
895c2d04 5956 gen_helper_mftc0_tccontext(t0, cpu_env);
ead9360e
TS
5957 break;
5958 case 6:
895c2d04 5959 gen_helper_mftc0_tcschedule(t0, cpu_env);
ead9360e
TS
5960 break;
5961 case 7:
895c2d04 5962 gen_helper_mftc0_tcschefback(t0, cpu_env);
ead9360e
TS
5963 break;
5964 default:
1a3fd9c3 5965 gen_mfc0(env, ctx, t0, rt, sel);
ead9360e
TS
5966 break;
5967 }
5968 break;
5969 case 10:
5970 switch (sel) {
5971 case 0:
895c2d04 5972 gen_helper_mftc0_entryhi(t0, cpu_env);
ead9360e
TS
5973 break;
5974 default:
1a3fd9c3 5975 gen_mfc0(env, ctx, t0, rt, sel);
ead9360e
TS
5976 break;
5977 }
5978 case 12:
5979 switch (sel) {
5980 case 0:
895c2d04 5981 gen_helper_mftc0_status(t0, cpu_env);
ead9360e
TS
5982 break;
5983 default:
1a3fd9c3 5984 gen_mfc0(env, ctx, t0, rt, sel);
ead9360e
TS
5985 break;
5986 }
5a25ce94
EI
5987 case 13:
5988 switch (sel) {
5989 case 0:
895c2d04 5990 gen_helper_mftc0_cause(t0, cpu_env);
5a25ce94
EI
5991 break;
5992 default:
5993 goto die;
5994 break;
5995 }
5996 break;
5997 case 14:
5998 switch (sel) {
5999 case 0:
895c2d04 6000 gen_helper_mftc0_epc(t0, cpu_env);
5a25ce94
EI
6001 break;
6002 default:
6003 goto die;
6004 break;
6005 }
6006 break;
6007 case 15:
6008 switch (sel) {
6009 case 1:
895c2d04 6010 gen_helper_mftc0_ebase(t0, cpu_env);
5a25ce94
EI
6011 break;
6012 default:
6013 goto die;
6014 break;
6015 }
6016 break;
6017 case 16:
6018 switch (sel) {
6019 case 0 ... 7:
895c2d04 6020 gen_helper_mftc0_configx(t0, cpu_env, tcg_const_tl(sel));
5a25ce94
EI
6021 break;
6022 default:
6023 goto die;
6024 break;
6025 }
6026 break;
ead9360e
TS
6027 case 23:
6028 switch (sel) {
6029 case 0:
895c2d04 6030 gen_helper_mftc0_debug(t0, cpu_env);
ead9360e
TS
6031 break;
6032 default:
1a3fd9c3 6033 gen_mfc0(env, ctx, t0, rt, sel);
ead9360e
TS
6034 break;
6035 }
6036 break;
6037 default:
1a3fd9c3 6038 gen_mfc0(env, ctx, t0, rt, sel);
ead9360e
TS
6039 }
6040 } else switch (sel) {
6041 /* GPR registers. */
6042 case 0:
895c2d04 6043 gen_helper_1e0i(mftgpr, t0, rt);
ead9360e
TS
6044 break;
6045 /* Auxiliary CPU registers */
6046 case 1:
6047 switch (rt) {
6048 case 0:
895c2d04 6049 gen_helper_1e0i(mftlo, t0, 0);
ead9360e
TS
6050 break;
6051 case 1:
895c2d04 6052 gen_helper_1e0i(mfthi, t0, 0);
ead9360e
TS
6053 break;
6054 case 2:
895c2d04 6055 gen_helper_1e0i(mftacx, t0, 0);
ead9360e
TS
6056 break;
6057 case 4:
895c2d04 6058 gen_helper_1e0i(mftlo, t0, 1);
ead9360e
TS
6059 break;
6060 case 5:
895c2d04 6061 gen_helper_1e0i(mfthi, t0, 1);
ead9360e
TS
6062 break;
6063 case 6:
895c2d04 6064 gen_helper_1e0i(mftacx, t0, 1);
ead9360e
TS
6065 break;
6066 case 8:
895c2d04 6067 gen_helper_1e0i(mftlo, t0, 2);
ead9360e
TS
6068 break;
6069 case 9:
895c2d04 6070 gen_helper_1e0i(mfthi, t0, 2);
ead9360e
TS
6071 break;
6072 case 10:
895c2d04 6073 gen_helper_1e0i(mftacx, t0, 2);
ead9360e
TS
6074 break;
6075 case 12:
895c2d04 6076 gen_helper_1e0i(mftlo, t0, 3);
ead9360e
TS
6077 break;
6078 case 13:
895c2d04 6079 gen_helper_1e0i(mfthi, t0, 3);
ead9360e
TS
6080 break;
6081 case 14:
895c2d04 6082 gen_helper_1e0i(mftacx, t0, 3);
ead9360e
TS
6083 break;
6084 case 16:
895c2d04 6085 gen_helper_mftdsp(t0, cpu_env);
ead9360e
TS
6086 break;
6087 default:
6088 goto die;
6089 }
6090 break;
6091 /* Floating point (COP1). */
6092 case 2:
6093 /* XXX: For now we support only a single FPU context. */
6094 if (h == 0) {
a7812ae4 6095 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed
TS
6096
6097 gen_load_fpr32(fp0, rt);
6098 tcg_gen_ext_i32_tl(t0, fp0);
a7812ae4 6099 tcg_temp_free_i32(fp0);
ead9360e 6100 } else {
a7812ae4 6101 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed
TS
6102
6103 gen_load_fpr32h(fp0, rt);
6104 tcg_gen_ext_i32_tl(t0, fp0);
a7812ae4 6105 tcg_temp_free_i32(fp0);
ead9360e
TS
6106 }
6107 break;
6108 case 3:
6109 /* XXX: For now we support only a single FPU context. */
895c2d04 6110 gen_helper_1e0i(cfc1, t0, rt);
ead9360e
TS
6111 break;
6112 /* COP2: Not implemented. */
6113 case 4:
6114 case 5:
6115 /* fall through */
6116 default:
6117 goto die;
6118 }
d12d51d5 6119 LOG_DISAS("mftr (reg %d u %d sel %d h %d)\n", rt, u, sel, h);
1a3fd9c3
TS
6120 gen_store_gpr(t0, rd);
6121 tcg_temp_free(t0);
ead9360e
TS
6122 return;
6123
6124die:
1a3fd9c3 6125 tcg_temp_free(t0);
d12d51d5 6126 LOG_DISAS("mftr (reg %d u %d sel %d h %d)\n", rt, u, sel, h);
ead9360e
TS
6127 generate_exception(ctx, EXCP_RI);
6128}
6129
7db13fae 6130static void gen_mttr(CPUMIPSState *env, DisasContext *ctx, int rd, int rt,
ead9360e
TS
6131 int u, int sel, int h)
6132{
6133 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
a7812ae4 6134 TCGv t0 = tcg_temp_local_new();
ead9360e 6135
1a3fd9c3 6136 gen_load_gpr(t0, rt);
ead9360e 6137 if ((env->CP0_VPEConf0 & (1 << CP0VPEC0_MVP)) == 0 &&
b5dc7732
TS
6138 ((env->tcs[other_tc].CP0_TCBind & (0xf << CP0TCBd_CurVPE)) !=
6139 (env->active_tc.CP0_TCBind & (0xf << CP0TCBd_CurVPE))))
ead9360e
TS
6140 /* NOP */ ;
6141 else if ((env->CP0_VPEControl & (0xff << CP0VPECo_TargTC)) >
6142 (env->mvp->CP0_MVPConf0 & (0xff << CP0MVPC0_PTC)))
6143 /* NOP */ ;
6144 else if (u == 0) {
6145 switch (rd) {
5a25ce94
EI
6146 case 1:
6147 switch (sel) {
6148 case 1:
895c2d04 6149 gen_helper_mttc0_vpecontrol(cpu_env, t0);
5a25ce94
EI
6150 break;
6151 case 2:
895c2d04 6152 gen_helper_mttc0_vpeconf0(cpu_env, t0);
5a25ce94
EI
6153 break;
6154 default:
6155 goto die;
6156 break;
6157 }
6158 break;
ead9360e
TS
6159 case 2:
6160 switch (sel) {
6161 case 1:
895c2d04 6162 gen_helper_mttc0_tcstatus(cpu_env, t0);
ead9360e
TS
6163 break;
6164 case 2:
895c2d04 6165 gen_helper_mttc0_tcbind(cpu_env, t0);
ead9360e
TS
6166 break;
6167 case 3:
895c2d04 6168 gen_helper_mttc0_tcrestart(cpu_env, t0);
ead9360e
TS
6169 break;
6170 case 4:
895c2d04 6171 gen_helper_mttc0_tchalt(cpu_env, t0);
ead9360e
TS
6172 break;
6173 case 5:
895c2d04 6174 gen_helper_mttc0_tccontext(cpu_env, t0);
ead9360e
TS
6175 break;
6176 case 6:
895c2d04 6177 gen_helper_mttc0_tcschedule(cpu_env, t0);
ead9360e
TS
6178 break;
6179 case 7:
895c2d04 6180 gen_helper_mttc0_tcschefback(cpu_env, t0);
ead9360e
TS
6181 break;
6182 default:
1a3fd9c3 6183 gen_mtc0(env, ctx, t0, rd, sel);
ead9360e
TS
6184 break;
6185 }
6186 break;
6187 case 10:
6188 switch (sel) {
6189 case 0:
895c2d04 6190 gen_helper_mttc0_entryhi(cpu_env, t0);
ead9360e
TS
6191 break;
6192 default:
1a3fd9c3 6193 gen_mtc0(env, ctx, t0, rd, sel);
ead9360e
TS
6194 break;
6195 }
6196 case 12:
6197 switch (sel) {
6198 case 0:
895c2d04 6199 gen_helper_mttc0_status(cpu_env, t0);
ead9360e
TS
6200 break;
6201 default:
1a3fd9c3 6202 gen_mtc0(env, ctx, t0, rd, sel);
ead9360e
TS
6203 break;
6204 }
5a25ce94
EI
6205 case 13:
6206 switch (sel) {
6207 case 0:
895c2d04 6208 gen_helper_mttc0_cause(cpu_env, t0);
5a25ce94
EI
6209 break;
6210 default:
6211 goto die;
6212 break;
6213 }
6214 break;
6215 case 15:
6216 switch (sel) {
6217 case 1:
895c2d04 6218 gen_helper_mttc0_ebase(cpu_env, t0);
5a25ce94
EI
6219 break;
6220 default:
6221 goto die;
6222 break;
6223 }
6224 break;
ead9360e
TS
6225 case 23:
6226 switch (sel) {
6227 case 0:
895c2d04 6228 gen_helper_mttc0_debug(cpu_env, t0);
ead9360e
TS
6229 break;
6230 default:
1a3fd9c3 6231 gen_mtc0(env, ctx, t0, rd, sel);
ead9360e
TS
6232 break;
6233 }
6234 break;
6235 default:
1a3fd9c3 6236 gen_mtc0(env, ctx, t0, rd, sel);
ead9360e
TS
6237 }
6238 } else switch (sel) {
6239 /* GPR registers. */
6240 case 0:
895c2d04 6241 gen_helper_0e1i(mttgpr, t0, rd);
ead9360e
TS
6242 break;
6243 /* Auxiliary CPU registers */
6244 case 1:
6245 switch (rd) {
6246 case 0:
895c2d04 6247 gen_helper_0e1i(mttlo, t0, 0);
ead9360e
TS
6248 break;
6249 case 1:
895c2d04 6250 gen_helper_0e1i(mtthi, t0, 0);
ead9360e
TS
6251 break;
6252 case 2:
895c2d04 6253 gen_helper_0e1i(mttacx, t0, 0);
ead9360e
TS
6254 break;
6255 case 4:
895c2d04 6256 gen_helper_0e1i(mttlo, t0, 1);
ead9360e
TS
6257 break;
6258 case 5:
895c2d04 6259 gen_helper_0e1i(mtthi, t0, 1);
ead9360e
TS
6260 break;
6261 case 6:
895c2d04 6262 gen_helper_0e1i(mttacx, t0, 1);
ead9360e
TS
6263 break;
6264 case 8:
895c2d04 6265 gen_helper_0e1i(mttlo, t0, 2);
ead9360e
TS
6266 break;
6267 case 9:
895c2d04 6268 gen_helper_0e1i(mtthi, t0, 2);
ead9360e
TS
6269 break;
6270 case 10:
895c2d04 6271 gen_helper_0e1i(mttacx, t0, 2);
ead9360e
TS
6272 break;
6273 case 12:
895c2d04 6274 gen_helper_0e1i(mttlo, t0, 3);
ead9360e
TS
6275 break;
6276 case 13:
895c2d04 6277 gen_helper_0e1i(mtthi, t0, 3);
ead9360e
TS
6278 break;
6279 case 14:
895c2d04 6280 gen_helper_0e1i(mttacx, t0, 3);
ead9360e
TS
6281 break;
6282 case 16:
895c2d04 6283 gen_helper_mttdsp(cpu_env, t0);
ead9360e
TS
6284 break;
6285 default:
6286 goto die;
6287 }
6288 break;
6289 /* Floating point (COP1). */
6290 case 2:
6291 /* XXX: For now we support only a single FPU context. */
6292 if (h == 0) {
a7812ae4 6293 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed
TS
6294
6295 tcg_gen_trunc_tl_i32(fp0, t0);
6296 gen_store_fpr32(fp0, rd);
a7812ae4 6297 tcg_temp_free_i32(fp0);
ead9360e 6298 } else {
a7812ae4 6299 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed
TS
6300
6301 tcg_gen_trunc_tl_i32(fp0, t0);
6302 gen_store_fpr32h(fp0, rd);
a7812ae4 6303 tcg_temp_free_i32(fp0);
ead9360e
TS
6304 }
6305 break;
6306 case 3:
6307 /* XXX: For now we support only a single FPU context. */
895c2d04 6308 gen_helper_0e1i(ctc1, t0, rd);
ead9360e
TS
6309 break;
6310 /* COP2: Not implemented. */
6311 case 4:
6312 case 5:
6313 /* fall through */
6314 default:
6315 goto die;
6316 }
d12d51d5 6317 LOG_DISAS("mttr (reg %d u %d sel %d h %d)\n", rd, u, sel, h);
1a3fd9c3 6318 tcg_temp_free(t0);
ead9360e
TS
6319 return;
6320
6321die:
1a3fd9c3 6322 tcg_temp_free(t0);
d12d51d5 6323 LOG_DISAS("mttr (reg %d u %d sel %d h %d)\n", rd, u, sel, h);
ead9360e
TS
6324 generate_exception(ctx, EXCP_RI);
6325}
6326
7db13fae 6327static void gen_cp0 (CPUMIPSState *env, DisasContext *ctx, uint32_t opc, int rt, int rd)
6af0bf9c 6328{
287c4b84 6329 const char *opn = "ldst";
6af0bf9c 6330
2e15497c 6331 check_cp0_enabled(ctx);
6af0bf9c
FB
6332 switch (opc) {
6333 case OPC_MFC0:
6334 if (rt == 0) {
ead9360e 6335 /* Treat as NOP. */
6af0bf9c
FB
6336 return;
6337 }
1fc7bf6e 6338 gen_mfc0(env, ctx, cpu_gpr[rt], rd, ctx->opcode & 0x7);
6af0bf9c
FB
6339 opn = "mfc0";
6340 break;
6341 case OPC_MTC0:
1a3fd9c3 6342 {
1fc7bf6e 6343 TCGv t0 = tcg_temp_new();
1a3fd9c3
TS
6344
6345 gen_load_gpr(t0, rt);
1a3fd9c3
TS
6346 gen_mtc0(env, ctx, t0, rd, ctx->opcode & 0x7);
6347 tcg_temp_free(t0);
6348 }
6af0bf9c
FB
6349 opn = "mtc0";
6350 break;
d26bc211 6351#if defined(TARGET_MIPS64)
9c2149c8 6352 case OPC_DMFC0:
e189e748 6353 check_insn(env, ctx, ISA_MIPS3);
9c2149c8 6354 if (rt == 0) {
ead9360e 6355 /* Treat as NOP. */
9c2149c8
TS
6356 return;
6357 }
1fc7bf6e 6358 gen_dmfc0(env, ctx, cpu_gpr[rt], rd, ctx->opcode & 0x7);
9c2149c8
TS
6359 opn = "dmfc0";
6360 break;
6361 case OPC_DMTC0:
e189e748 6362 check_insn(env, ctx, ISA_MIPS3);
1a3fd9c3 6363 {
1fc7bf6e 6364 TCGv t0 = tcg_temp_new();
1a3fd9c3
TS
6365
6366 gen_load_gpr(t0, rt);
1a3fd9c3
TS
6367 gen_dmtc0(env, ctx, t0, rd, ctx->opcode & 0x7);
6368 tcg_temp_free(t0);
6369 }
9c2149c8
TS
6370 opn = "dmtc0";
6371 break;
534ce69f 6372#endif
ead9360e 6373 case OPC_MFTR:
7385ac0b 6374 check_insn(env, ctx, ASE_MT);
ead9360e
TS
6375 if (rd == 0) {
6376 /* Treat as NOP. */
6377 return;
6378 }
6c5c1e20 6379 gen_mftr(env, ctx, rt, rd, (ctx->opcode >> 5) & 1,
ead9360e 6380 ctx->opcode & 0x7, (ctx->opcode >> 4) & 1);
ead9360e
TS
6381 opn = "mftr";
6382 break;
6383 case OPC_MTTR:
7385ac0b 6384 check_insn(env, ctx, ASE_MT);
6c5c1e20 6385 gen_mttr(env, ctx, rd, rt, (ctx->opcode >> 5) & 1,
ead9360e
TS
6386 ctx->opcode & 0x7, (ctx->opcode >> 4) & 1);
6387 opn = "mttr";
6388 break;
6af0bf9c 6389 case OPC_TLBWI:
6af0bf9c 6390 opn = "tlbwi";
c01fccd2 6391 if (!env->tlb->helper_tlbwi)
29929e34 6392 goto die;
895c2d04 6393 gen_helper_tlbwi(cpu_env);
6af0bf9c
FB
6394 break;
6395 case OPC_TLBWR:
6af0bf9c 6396 opn = "tlbwr";
c01fccd2 6397 if (!env->tlb->helper_tlbwr)
29929e34 6398 goto die;
895c2d04 6399 gen_helper_tlbwr(cpu_env);
6af0bf9c
FB
6400 break;
6401 case OPC_TLBP:
6af0bf9c 6402 opn = "tlbp";
c01fccd2 6403 if (!env->tlb->helper_tlbp)
29929e34 6404 goto die;
895c2d04 6405 gen_helper_tlbp(cpu_env);
6af0bf9c
FB
6406 break;
6407 case OPC_TLBR:
6af0bf9c 6408 opn = "tlbr";
c01fccd2 6409 if (!env->tlb->helper_tlbr)
29929e34 6410 goto die;
895c2d04 6411 gen_helper_tlbr(cpu_env);
6af0bf9c 6412 break;
6af0bf9c
FB
6413 case OPC_ERET:
6414 opn = "eret";
e189e748 6415 check_insn(env, ctx, ISA_MIPS2);
895c2d04 6416 gen_helper_eret(cpu_env);
6af0bf9c
FB
6417 ctx->bstate = BS_EXCP;
6418 break;
6419 case OPC_DERET:
6420 opn = "deret";
e189e748 6421 check_insn(env, ctx, ISA_MIPS32);
6af0bf9c 6422 if (!(ctx->hflags & MIPS_HFLAG_DM)) {
923617a3 6423 MIPS_INVAL(opn);
6af0bf9c
FB
6424 generate_exception(ctx, EXCP_RI);
6425 } else {
895c2d04 6426 gen_helper_deret(cpu_env);
6af0bf9c
FB
6427 ctx->bstate = BS_EXCP;
6428 }
6429 break;
4ad40f36
FB
6430 case OPC_WAIT:
6431 opn = "wait";
e189e748 6432 check_insn(env, ctx, ISA_MIPS3 | ISA_MIPS32);
4ad40f36
FB
6433 /* If we get an exception, we want to restart at next instruction */
6434 ctx->pc += 4;
6435 save_cpu_state(ctx, 1);
6436 ctx->pc -= 4;
895c2d04 6437 gen_helper_wait(cpu_env);
4ad40f36
FB
6438 ctx->bstate = BS_EXCP;
6439 break;
6af0bf9c 6440 default:
29929e34 6441 die:
923617a3 6442 MIPS_INVAL(opn);
6af0bf9c
FB
6443 generate_exception(ctx, EXCP_RI);
6444 return;
6445 }
2abf314d 6446 (void)opn; /* avoid a compiler warning */
6af0bf9c
FB
6447 MIPS_DEBUG("%s %s %d", opn, regnames[rt], rd);
6448}
f1aa6320 6449#endif /* !CONFIG_USER_ONLY */
6af0bf9c 6450
6ea83fed 6451/* CP1 Branches (before delay slot) */
7db13fae 6452static void gen_compute_branch1 (CPUMIPSState *env, DisasContext *ctx, uint32_t op,
5a5012ec 6453 int32_t cc, int32_t offset)
6ea83fed
FB
6454{
6455 target_ulong btarget;
923617a3 6456 const char *opn = "cp1 cond branch";
a7812ae4 6457 TCGv_i32 t0 = tcg_temp_new_i32();
6ea83fed 6458
e189e748
TS
6459 if (cc != 0)
6460 check_insn(env, ctx, ISA_MIPS4 | ISA_MIPS32);
6461
6ea83fed
FB
6462 btarget = ctx->pc + 4 + offset;
6463
7a387fff
TS
6464 switch (op) {
6465 case OPC_BC1F:
d94536f4
AJ
6466 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
6467 tcg_gen_not_i32(t0, t0);
6468 tcg_gen_andi_i32(t0, t0, 1);
6469 tcg_gen_extu_i32_tl(bcond, t0);
923617a3 6470 opn = "bc1f";
6ea83fed 6471 goto not_likely;
7a387fff 6472 case OPC_BC1FL:
d94536f4
AJ
6473 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
6474 tcg_gen_not_i32(t0, t0);
6475 tcg_gen_andi_i32(t0, t0, 1);
6476 tcg_gen_extu_i32_tl(bcond, t0);
923617a3 6477 opn = "bc1fl";
6ea83fed 6478 goto likely;
7a387fff 6479 case OPC_BC1T:
d94536f4
AJ
6480 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
6481 tcg_gen_andi_i32(t0, t0, 1);
6482 tcg_gen_extu_i32_tl(bcond, t0);
923617a3 6483 opn = "bc1t";
5a5012ec 6484 goto not_likely;
7a387fff 6485 case OPC_BC1TL:
d94536f4
AJ
6486 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
6487 tcg_gen_andi_i32(t0, t0, 1);
6488 tcg_gen_extu_i32_tl(bcond, t0);
923617a3 6489 opn = "bc1tl";
6ea83fed
FB
6490 likely:
6491 ctx->hflags |= MIPS_HFLAG_BL;
6492 break;
5a5012ec 6493 case OPC_BC1FANY2:
a16336e4 6494 {
d94536f4
AJ
6495 TCGv_i32 t1 = tcg_temp_new_i32();
6496 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
6497 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+1));
d7f66b52 6498 tcg_gen_nand_i32(t0, t0, t1);
d94536f4 6499 tcg_temp_free_i32(t1);
d94536f4
AJ
6500 tcg_gen_andi_i32(t0, t0, 1);
6501 tcg_gen_extu_i32_tl(bcond, t0);
a16336e4 6502 }
fd4a04eb 6503 opn = "bc1any2f";
5a5012ec
TS
6504 goto not_likely;
6505 case OPC_BC1TANY2:
a16336e4 6506 {
d94536f4
AJ
6507 TCGv_i32 t1 = tcg_temp_new_i32();
6508 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
6509 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+1));
6510 tcg_gen_or_i32(t0, t0, t1);
6511 tcg_temp_free_i32(t1);
6512 tcg_gen_andi_i32(t0, t0, 1);
6513 tcg_gen_extu_i32_tl(bcond, t0);
a16336e4 6514 }
fd4a04eb 6515 opn = "bc1any2t";
5a5012ec
TS
6516 goto not_likely;
6517 case OPC_BC1FANY4:
a16336e4 6518 {
d94536f4
AJ
6519 TCGv_i32 t1 = tcg_temp_new_i32();
6520 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
6521 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+1));
d7f66b52 6522 tcg_gen_and_i32(t0, t0, t1);
d94536f4 6523 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+2));
d7f66b52 6524 tcg_gen_and_i32(t0, t0, t1);
d94536f4 6525 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+3));
d7f66b52 6526 tcg_gen_nand_i32(t0, t0, t1);
d94536f4 6527 tcg_temp_free_i32(t1);
d94536f4
AJ
6528 tcg_gen_andi_i32(t0, t0, 1);
6529 tcg_gen_extu_i32_tl(bcond, t0);
a16336e4 6530 }
fd4a04eb 6531 opn = "bc1any4f";
5a5012ec
TS
6532 goto not_likely;
6533 case OPC_BC1TANY4:
a16336e4 6534 {
d94536f4
AJ
6535 TCGv_i32 t1 = tcg_temp_new_i32();
6536 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
6537 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+1));
6538 tcg_gen_or_i32(t0, t0, t1);
6539 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+2));
6540 tcg_gen_or_i32(t0, t0, t1);
6541 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+3));
6542 tcg_gen_or_i32(t0, t0, t1);
6543 tcg_temp_free_i32(t1);
6544 tcg_gen_andi_i32(t0, t0, 1);
6545 tcg_gen_extu_i32_tl(bcond, t0);
a16336e4 6546 }
fd4a04eb 6547 opn = "bc1any4t";
5a5012ec
TS
6548 not_likely:
6549 ctx->hflags |= MIPS_HFLAG_BC;
5a5012ec
TS
6550 break;
6551 default:
923617a3 6552 MIPS_INVAL(opn);
e397ee33 6553 generate_exception (ctx, EXCP_RI);
6c5c1e20 6554 goto out;
6ea83fed 6555 }
2abf314d 6556 (void)opn; /* avoid a compiler warning */
923617a3 6557 MIPS_DEBUG("%s: cond %02x target " TARGET_FMT_lx, opn,
6ea83fed
FB
6558 ctx->hflags, btarget);
6559 ctx->btarget = btarget;
6c5c1e20
TS
6560
6561 out:
a7812ae4 6562 tcg_temp_free_i32(t0);
6ea83fed
FB
6563}
6564
6af0bf9c 6565/* Coprocessor 1 (FPU) */
5a5012ec 6566
5a5012ec
TS
6567#define FOP(func, fmt) (((fmt) << 21) | (func))
6568
bf4120ad
NF
6569enum fopcode {
6570 OPC_ADD_S = FOP(0, FMT_S),
6571 OPC_SUB_S = FOP(1, FMT_S),
6572 OPC_MUL_S = FOP(2, FMT_S),
6573 OPC_DIV_S = FOP(3, FMT_S),
6574 OPC_SQRT_S = FOP(4, FMT_S),
6575 OPC_ABS_S = FOP(5, FMT_S),
6576 OPC_MOV_S = FOP(6, FMT_S),
6577 OPC_NEG_S = FOP(7, FMT_S),
6578 OPC_ROUND_L_S = FOP(8, FMT_S),
6579 OPC_TRUNC_L_S = FOP(9, FMT_S),
6580 OPC_CEIL_L_S = FOP(10, FMT_S),
6581 OPC_FLOOR_L_S = FOP(11, FMT_S),
6582 OPC_ROUND_W_S = FOP(12, FMT_S),
6583 OPC_TRUNC_W_S = FOP(13, FMT_S),
6584 OPC_CEIL_W_S = FOP(14, FMT_S),
6585 OPC_FLOOR_W_S = FOP(15, FMT_S),
6586 OPC_MOVCF_S = FOP(17, FMT_S),
6587 OPC_MOVZ_S = FOP(18, FMT_S),
6588 OPC_MOVN_S = FOP(19, FMT_S),
6589 OPC_RECIP_S = FOP(21, FMT_S),
6590 OPC_RSQRT_S = FOP(22, FMT_S),
6591 OPC_RECIP2_S = FOP(28, FMT_S),
6592 OPC_RECIP1_S = FOP(29, FMT_S),
6593 OPC_RSQRT1_S = FOP(30, FMT_S),
6594 OPC_RSQRT2_S = FOP(31, FMT_S),
6595 OPC_CVT_D_S = FOP(33, FMT_S),
6596 OPC_CVT_W_S = FOP(36, FMT_S),
6597 OPC_CVT_L_S = FOP(37, FMT_S),
6598 OPC_CVT_PS_S = FOP(38, FMT_S),
6599 OPC_CMP_F_S = FOP (48, FMT_S),
6600 OPC_CMP_UN_S = FOP (49, FMT_S),
6601 OPC_CMP_EQ_S = FOP (50, FMT_S),
6602 OPC_CMP_UEQ_S = FOP (51, FMT_S),
6603 OPC_CMP_OLT_S = FOP (52, FMT_S),
6604 OPC_CMP_ULT_S = FOP (53, FMT_S),
6605 OPC_CMP_OLE_S = FOP (54, FMT_S),
6606 OPC_CMP_ULE_S = FOP (55, FMT_S),
6607 OPC_CMP_SF_S = FOP (56, FMT_S),
6608 OPC_CMP_NGLE_S = FOP (57, FMT_S),
6609 OPC_CMP_SEQ_S = FOP (58, FMT_S),
6610 OPC_CMP_NGL_S = FOP (59, FMT_S),
6611 OPC_CMP_LT_S = FOP (60, FMT_S),
6612 OPC_CMP_NGE_S = FOP (61, FMT_S),
6613 OPC_CMP_LE_S = FOP (62, FMT_S),
6614 OPC_CMP_NGT_S = FOP (63, FMT_S),
6615
6616 OPC_ADD_D = FOP(0, FMT_D),
6617 OPC_SUB_D = FOP(1, FMT_D),
6618 OPC_MUL_D = FOP(2, FMT_D),
6619 OPC_DIV_D = FOP(3, FMT_D),
6620 OPC_SQRT_D = FOP(4, FMT_D),
6621 OPC_ABS_D = FOP(5, FMT_D),
6622 OPC_MOV_D = FOP(6, FMT_D),
6623 OPC_NEG_D = FOP(7, FMT_D),
6624 OPC_ROUND_L_D = FOP(8, FMT_D),
6625 OPC_TRUNC_L_D = FOP(9, FMT_D),
6626 OPC_CEIL_L_D = FOP(10, FMT_D),
6627 OPC_FLOOR_L_D = FOP(11, FMT_D),
6628 OPC_ROUND_W_D = FOP(12, FMT_D),
6629 OPC_TRUNC_W_D = FOP(13, FMT_D),
6630 OPC_CEIL_W_D = FOP(14, FMT_D),
6631 OPC_FLOOR_W_D = FOP(15, FMT_D),
6632 OPC_MOVCF_D = FOP(17, FMT_D),
6633 OPC_MOVZ_D = FOP(18, FMT_D),
6634 OPC_MOVN_D = FOP(19, FMT_D),
6635 OPC_RECIP_D = FOP(21, FMT_D),
6636 OPC_RSQRT_D = FOP(22, FMT_D),
6637 OPC_RECIP2_D = FOP(28, FMT_D),
6638 OPC_RECIP1_D = FOP(29, FMT_D),
6639 OPC_RSQRT1_D = FOP(30, FMT_D),
6640 OPC_RSQRT2_D = FOP(31, FMT_D),
6641 OPC_CVT_S_D = FOP(32, FMT_D),
6642 OPC_CVT_W_D = FOP(36, FMT_D),
6643 OPC_CVT_L_D = FOP(37, FMT_D),
6644 OPC_CMP_F_D = FOP (48, FMT_D),
6645 OPC_CMP_UN_D = FOP (49, FMT_D),
6646 OPC_CMP_EQ_D = FOP (50, FMT_D),
6647 OPC_CMP_UEQ_D = FOP (51, FMT_D),
6648 OPC_CMP_OLT_D = FOP (52, FMT_D),
6649 OPC_CMP_ULT_D = FOP (53, FMT_D),
6650 OPC_CMP_OLE_D = FOP (54, FMT_D),
6651 OPC_CMP_ULE_D = FOP (55, FMT_D),
6652 OPC_CMP_SF_D = FOP (56, FMT_D),
6653 OPC_CMP_NGLE_D = FOP (57, FMT_D),
6654 OPC_CMP_SEQ_D = FOP (58, FMT_D),
6655 OPC_CMP_NGL_D = FOP (59, FMT_D),
6656 OPC_CMP_LT_D = FOP (60, FMT_D),
6657 OPC_CMP_NGE_D = FOP (61, FMT_D),
6658 OPC_CMP_LE_D = FOP (62, FMT_D),
6659 OPC_CMP_NGT_D = FOP (63, FMT_D),
6660
6661 OPC_CVT_S_W = FOP(32, FMT_W),
6662 OPC_CVT_D_W = FOP(33, FMT_W),
6663 OPC_CVT_S_L = FOP(32, FMT_L),
6664 OPC_CVT_D_L = FOP(33, FMT_L),
6665 OPC_CVT_PS_PW = FOP(38, FMT_W),
6666
6667 OPC_ADD_PS = FOP(0, FMT_PS),
6668 OPC_SUB_PS = FOP(1, FMT_PS),
6669 OPC_MUL_PS = FOP(2, FMT_PS),
6670 OPC_DIV_PS = FOP(3, FMT_PS),
6671 OPC_ABS_PS = FOP(5, FMT_PS),
6672 OPC_MOV_PS = FOP(6, FMT_PS),
6673 OPC_NEG_PS = FOP(7, FMT_PS),
6674 OPC_MOVCF_PS = FOP(17, FMT_PS),
6675 OPC_MOVZ_PS = FOP(18, FMT_PS),
6676 OPC_MOVN_PS = FOP(19, FMT_PS),
6677 OPC_ADDR_PS = FOP(24, FMT_PS),
6678 OPC_MULR_PS = FOP(26, FMT_PS),
6679 OPC_RECIP2_PS = FOP(28, FMT_PS),
6680 OPC_RECIP1_PS = FOP(29, FMT_PS),
6681 OPC_RSQRT1_PS = FOP(30, FMT_PS),
6682 OPC_RSQRT2_PS = FOP(31, FMT_PS),
6683
6684 OPC_CVT_S_PU = FOP(32, FMT_PS),
6685 OPC_CVT_PW_PS = FOP(36, FMT_PS),
6686 OPC_CVT_S_PL = FOP(40, FMT_PS),
6687 OPC_PLL_PS = FOP(44, FMT_PS),
6688 OPC_PLU_PS = FOP(45, FMT_PS),
6689 OPC_PUL_PS = FOP(46, FMT_PS),
6690 OPC_PUU_PS = FOP(47, FMT_PS),
6691 OPC_CMP_F_PS = FOP (48, FMT_PS),
6692 OPC_CMP_UN_PS = FOP (49, FMT_PS),
6693 OPC_CMP_EQ_PS = FOP (50, FMT_PS),
6694 OPC_CMP_UEQ_PS = FOP (51, FMT_PS),
6695 OPC_CMP_OLT_PS = FOP (52, FMT_PS),
6696 OPC_CMP_ULT_PS = FOP (53, FMT_PS),
6697 OPC_CMP_OLE_PS = FOP (54, FMT_PS),
6698 OPC_CMP_ULE_PS = FOP (55, FMT_PS),
6699 OPC_CMP_SF_PS = FOP (56, FMT_PS),
6700 OPC_CMP_NGLE_PS = FOP (57, FMT_PS),
6701 OPC_CMP_SEQ_PS = FOP (58, FMT_PS),
6702 OPC_CMP_NGL_PS = FOP (59, FMT_PS),
6703 OPC_CMP_LT_PS = FOP (60, FMT_PS),
6704 OPC_CMP_NGE_PS = FOP (61, FMT_PS),
6705 OPC_CMP_LE_PS = FOP (62, FMT_PS),
6706 OPC_CMP_NGT_PS = FOP (63, FMT_PS),
6707};
6708
7a387fff 6709static void gen_cp1 (DisasContext *ctx, uint32_t opc, int rt, int fs)
6ea83fed 6710{
923617a3 6711 const char *opn = "cp1 move";
72c3a3ee 6712 TCGv t0 = tcg_temp_new();
6ea83fed
FB
6713
6714 switch (opc) {
6715 case OPC_MFC1:
b6d96bed 6716 {
a7812ae4 6717 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed
TS
6718
6719 gen_load_fpr32(fp0, fs);
6720 tcg_gen_ext_i32_tl(t0, fp0);
a7812ae4 6721 tcg_temp_free_i32(fp0);
6958549d 6722 }
6c5c1e20 6723 gen_store_gpr(t0, rt);
6ea83fed
FB
6724 opn = "mfc1";
6725 break;
6726 case OPC_MTC1:
6c5c1e20 6727 gen_load_gpr(t0, rt);
b6d96bed 6728 {
a7812ae4 6729 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed
TS
6730
6731 tcg_gen_trunc_tl_i32(fp0, t0);
6732 gen_store_fpr32(fp0, fs);
a7812ae4 6733 tcg_temp_free_i32(fp0);
6958549d 6734 }
6ea83fed
FB
6735 opn = "mtc1";
6736 break;
6737 case OPC_CFC1:
895c2d04 6738 gen_helper_1e0i(cfc1, t0, fs);
6c5c1e20 6739 gen_store_gpr(t0, rt);
6ea83fed
FB
6740 opn = "cfc1";
6741 break;
6742 case OPC_CTC1:
6c5c1e20 6743 gen_load_gpr(t0, rt);
895c2d04 6744 gen_helper_0e1i(ctc1, t0, fs);
6ea83fed
FB
6745 opn = "ctc1";
6746 break;
72c3a3ee 6747#if defined(TARGET_MIPS64)
9c2149c8 6748 case OPC_DMFC1:
72c3a3ee 6749 gen_load_fpr64(ctx, t0, fs);
6c5c1e20 6750 gen_store_gpr(t0, rt);
5a5012ec
TS
6751 opn = "dmfc1";
6752 break;
9c2149c8 6753 case OPC_DMTC1:
6c5c1e20 6754 gen_load_gpr(t0, rt);
72c3a3ee 6755 gen_store_fpr64(ctx, t0, fs);
5a5012ec
TS
6756 opn = "dmtc1";
6757 break;
72c3a3ee 6758#endif
5a5012ec 6759 case OPC_MFHC1:
b6d96bed 6760 {
a7812ae4 6761 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed
TS
6762
6763 gen_load_fpr32h(fp0, fs);
6764 tcg_gen_ext_i32_tl(t0, fp0);
a7812ae4 6765 tcg_temp_free_i32(fp0);
6958549d 6766 }
6c5c1e20 6767 gen_store_gpr(t0, rt);
5a5012ec
TS
6768 opn = "mfhc1";
6769 break;
6770 case OPC_MTHC1:
6c5c1e20 6771 gen_load_gpr(t0, rt);
b6d96bed 6772 {
a7812ae4 6773 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed
TS
6774
6775 tcg_gen_trunc_tl_i32(fp0, t0);
6776 gen_store_fpr32h(fp0, fs);
a7812ae4 6777 tcg_temp_free_i32(fp0);
6958549d 6778 }
5a5012ec
TS
6779 opn = "mthc1";
6780 break;
6ea83fed 6781 default:
923617a3 6782 MIPS_INVAL(opn);
e397ee33 6783 generate_exception (ctx, EXCP_RI);
6c5c1e20 6784 goto out;
6ea83fed 6785 }
2abf314d 6786 (void)opn; /* avoid a compiler warning */
6ea83fed 6787 MIPS_DEBUG("%s %s %s", opn, regnames[rt], fregnames[fs]);
6c5c1e20
TS
6788
6789 out:
6790 tcg_temp_free(t0);
6ea83fed
FB
6791}
6792
5a5012ec
TS
6793static void gen_movci (DisasContext *ctx, int rd, int rs, int cc, int tf)
6794{
af58f9ca 6795 int l1;
e214b9bb 6796 TCGCond cond;
af58f9ca
AJ
6797 TCGv_i32 t0;
6798
6799 if (rd == 0) {
6800 /* Treat as NOP. */
6801 return;
6802 }
6ea83fed 6803
e214b9bb 6804 if (tf)
e214b9bb 6805 cond = TCG_COND_EQ;
27848470
TS
6806 else
6807 cond = TCG_COND_NE;
6808
af58f9ca
AJ
6809 l1 = gen_new_label();
6810 t0 = tcg_temp_new_i32();
fa31af0e 6811 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
af58f9ca 6812 tcg_gen_brcondi_i32(cond, t0, 0, l1);
a4e8338d 6813 tcg_temp_free_i32(t0);
af58f9ca
AJ
6814 if (rs == 0) {
6815 tcg_gen_movi_tl(cpu_gpr[rd], 0);
6816 } else {
6817 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
6818 }
e214b9bb 6819 gen_set_label(l1);
5a5012ec
TS
6820}
6821
b6d96bed 6822static inline void gen_movcf_s (int fs, int fd, int cc, int tf)
a16336e4 6823{
a16336e4 6824 int cond;
cbc37b28 6825 TCGv_i32 t0 = tcg_temp_new_i32();
a16336e4
TS
6826 int l1 = gen_new_label();
6827
a16336e4
TS
6828 if (tf)
6829 cond = TCG_COND_EQ;
6830 else
6831 cond = TCG_COND_NE;
6832
fa31af0e 6833 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
cbc37b28
AJ
6834 tcg_gen_brcondi_i32(cond, t0, 0, l1);
6835 gen_load_fpr32(t0, fs);
6836 gen_store_fpr32(t0, fd);
a16336e4 6837 gen_set_label(l1);
cbc37b28 6838 tcg_temp_free_i32(t0);
5a5012ec 6839}
a16336e4 6840
b6d96bed 6841static inline void gen_movcf_d (DisasContext *ctx, int fs, int fd, int cc, int tf)
a16336e4 6842{
a16336e4 6843 int cond;
cbc37b28
AJ
6844 TCGv_i32 t0 = tcg_temp_new_i32();
6845 TCGv_i64 fp0;
a16336e4
TS
6846 int l1 = gen_new_label();
6847
a16336e4
TS
6848 if (tf)
6849 cond = TCG_COND_EQ;
6850 else
6851 cond = TCG_COND_NE;
6852
fa31af0e 6853 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
cbc37b28 6854 tcg_gen_brcondi_i32(cond, t0, 0, l1);
a4e8338d 6855 tcg_temp_free_i32(t0);
11f94258 6856 fp0 = tcg_temp_new_i64();
9bf3eb2c 6857 gen_load_fpr64(ctx, fp0, fs);
9bf3eb2c 6858 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 6859 tcg_temp_free_i64(fp0);
cbc37b28 6860 gen_set_label(l1);
a16336e4
TS
6861}
6862
b6d96bed 6863static inline void gen_movcf_ps (int fs, int fd, int cc, int tf)
a16336e4
TS
6864{
6865 int cond;
cbc37b28 6866 TCGv_i32 t0 = tcg_temp_new_i32();
a16336e4
TS
6867 int l1 = gen_new_label();
6868 int l2 = gen_new_label();
6869
6870 if (tf)
6871 cond = TCG_COND_EQ;
6872 else
6873 cond = TCG_COND_NE;
6874
fa31af0e 6875 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
cbc37b28
AJ
6876 tcg_gen_brcondi_i32(cond, t0, 0, l1);
6877 gen_load_fpr32(t0, fs);
6878 gen_store_fpr32(t0, fd);
a16336e4 6879 gen_set_label(l1);
9bf3eb2c 6880
fa31af0e 6881 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc+1));
cbc37b28
AJ
6882 tcg_gen_brcondi_i32(cond, t0, 0, l2);
6883 gen_load_fpr32h(t0, fs);
6884 gen_store_fpr32h(t0, fd);
52a0e9eb 6885 tcg_temp_free_i32(t0);
a16336e4 6886 gen_set_label(l2);
a16336e4
TS
6887}
6888
6ea83fed 6889
bf4120ad 6890static void gen_farith (DisasContext *ctx, enum fopcode op1,
5e755519 6891 int ft, int fs, int fd, int cc)
6ea83fed 6892{
923617a3 6893 const char *opn = "farith";
6ea83fed
FB
6894 const char *condnames[] = {
6895 "c.f",
6896 "c.un",
6897 "c.eq",
6898 "c.ueq",
6899 "c.olt",
6900 "c.ult",
6901 "c.ole",
6902 "c.ule",
6903 "c.sf",
6904 "c.ngle",
6905 "c.seq",
6906 "c.ngl",
6907 "c.lt",
6908 "c.nge",
6909 "c.le",
6910 "c.ngt",
6911 };
5a1e8ffb
TS
6912 const char *condnames_abs[] = {
6913 "cabs.f",
6914 "cabs.un",
6915 "cabs.eq",
6916 "cabs.ueq",
6917 "cabs.olt",
6918 "cabs.ult",
6919 "cabs.ole",
6920 "cabs.ule",
6921 "cabs.sf",
6922 "cabs.ngle",
6923 "cabs.seq",
6924 "cabs.ngl",
6925 "cabs.lt",
6926 "cabs.nge",
6927 "cabs.le",
6928 "cabs.ngt",
6929 };
6930 enum { BINOP, CMPOP, OTHEROP } optype = OTHEROP;
7a387fff
TS
6931 uint32_t func = ctx->opcode & 0x3f;
6932
bf4120ad
NF
6933 switch (op1) {
6934 case OPC_ADD_S:
b6d96bed 6935 {
a7812ae4
PB
6936 TCGv_i32 fp0 = tcg_temp_new_i32();
6937 TCGv_i32 fp1 = tcg_temp_new_i32();
b6d96bed
TS
6938
6939 gen_load_fpr32(fp0, fs);
6940 gen_load_fpr32(fp1, ft);
895c2d04 6941 gen_helper_float_add_s(fp0, cpu_env, fp0, fp1);
a7812ae4 6942 tcg_temp_free_i32(fp1);
b6d96bed 6943 gen_store_fpr32(fp0, fd);
a7812ae4 6944 tcg_temp_free_i32(fp0);
b6d96bed 6945 }
5a5012ec 6946 opn = "add.s";
5a1e8ffb 6947 optype = BINOP;
5a5012ec 6948 break;
bf4120ad 6949 case OPC_SUB_S:
b6d96bed 6950 {
a7812ae4
PB
6951 TCGv_i32 fp0 = tcg_temp_new_i32();
6952 TCGv_i32 fp1 = tcg_temp_new_i32();
b6d96bed
TS
6953
6954 gen_load_fpr32(fp0, fs);
6955 gen_load_fpr32(fp1, ft);
895c2d04 6956 gen_helper_float_sub_s(fp0, cpu_env, fp0, fp1);
a7812ae4 6957 tcg_temp_free_i32(fp1);
b6d96bed 6958 gen_store_fpr32(fp0, fd);
a7812ae4 6959 tcg_temp_free_i32(fp0);
b6d96bed 6960 }
5a5012ec 6961 opn = "sub.s";
5a1e8ffb 6962 optype = BINOP;
5a5012ec 6963 break;
bf4120ad 6964 case OPC_MUL_S:
b6d96bed 6965 {
a7812ae4
PB
6966 TCGv_i32 fp0 = tcg_temp_new_i32();
6967 TCGv_i32 fp1 = tcg_temp_new_i32();
b6d96bed
TS
6968
6969 gen_load_fpr32(fp0, fs);
6970 gen_load_fpr32(fp1, ft);
895c2d04 6971 gen_helper_float_mul_s(fp0, cpu_env, fp0, fp1);
a7812ae4 6972 tcg_temp_free_i32(fp1);
b6d96bed 6973 gen_store_fpr32(fp0, fd);
a7812ae4 6974 tcg_temp_free_i32(fp0);
b6d96bed 6975 }
5a5012ec 6976 opn = "mul.s";
5a1e8ffb 6977 optype = BINOP;
5a5012ec 6978 break;
bf4120ad 6979 case OPC_DIV_S:
b6d96bed 6980 {
a7812ae4
PB
6981 TCGv_i32 fp0 = tcg_temp_new_i32();
6982 TCGv_i32 fp1 = tcg_temp_new_i32();
b6d96bed
TS
6983
6984 gen_load_fpr32(fp0, fs);
6985 gen_load_fpr32(fp1, ft);
895c2d04 6986 gen_helper_float_div_s(fp0, cpu_env, fp0, fp1);
a7812ae4 6987 tcg_temp_free_i32(fp1);
b6d96bed 6988 gen_store_fpr32(fp0, fd);
a7812ae4 6989 tcg_temp_free_i32(fp0);
b6d96bed 6990 }
5a5012ec 6991 opn = "div.s";
5a1e8ffb 6992 optype = BINOP;
5a5012ec 6993 break;
bf4120ad 6994 case OPC_SQRT_S:
b6d96bed 6995 {
a7812ae4 6996 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed
TS
6997
6998 gen_load_fpr32(fp0, fs);
895c2d04 6999 gen_helper_float_sqrt_s(fp0, cpu_env, fp0);
b6d96bed 7000 gen_store_fpr32(fp0, fd);
a7812ae4 7001 tcg_temp_free_i32(fp0);
b6d96bed 7002 }
5a5012ec
TS
7003 opn = "sqrt.s";
7004 break;
bf4120ad 7005 case OPC_ABS_S:
b6d96bed 7006 {
a7812ae4 7007 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed
TS
7008
7009 gen_load_fpr32(fp0, fs);
a7812ae4 7010 gen_helper_float_abs_s(fp0, fp0);
b6d96bed 7011 gen_store_fpr32(fp0, fd);
a7812ae4 7012 tcg_temp_free_i32(fp0);
b6d96bed 7013 }
5a5012ec
TS
7014 opn = "abs.s";
7015 break;
bf4120ad 7016 case OPC_MOV_S:
b6d96bed 7017 {
a7812ae4 7018 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed
TS
7019
7020 gen_load_fpr32(fp0, fs);
7021 gen_store_fpr32(fp0, fd);
a7812ae4 7022 tcg_temp_free_i32(fp0);
b6d96bed 7023 }
5a5012ec
TS
7024 opn = "mov.s";
7025 break;
bf4120ad 7026 case OPC_NEG_S:
b6d96bed 7027 {
a7812ae4 7028 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed
TS
7029
7030 gen_load_fpr32(fp0, fs);
a7812ae4 7031 gen_helper_float_chs_s(fp0, fp0);
b6d96bed 7032 gen_store_fpr32(fp0, fd);
a7812ae4 7033 tcg_temp_free_i32(fp0);
b6d96bed 7034 }
5a5012ec
TS
7035 opn = "neg.s";
7036 break;
bf4120ad 7037 case OPC_ROUND_L_S:
5e755519 7038 check_cp1_64bitmode(ctx);
b6d96bed 7039 {
a7812ae4
PB
7040 TCGv_i32 fp32 = tcg_temp_new_i32();
7041 TCGv_i64 fp64 = tcg_temp_new_i64();
b6d96bed
TS
7042
7043 gen_load_fpr32(fp32, fs);
895c2d04 7044 gen_helper_float_roundl_s(fp64, cpu_env, fp32);
a7812ae4 7045 tcg_temp_free_i32(fp32);
b6d96bed 7046 gen_store_fpr64(ctx, fp64, fd);
a7812ae4 7047 tcg_temp_free_i64(fp64);
b6d96bed 7048 }
5a5012ec
TS
7049 opn = "round.l.s";
7050 break;
bf4120ad 7051 case OPC_TRUNC_L_S:
5e755519 7052 check_cp1_64bitmode(ctx);
b6d96bed 7053 {
a7812ae4
PB
7054 TCGv_i32 fp32 = tcg_temp_new_i32();
7055 TCGv_i64 fp64 = tcg_temp_new_i64();
b6d96bed
TS
7056
7057 gen_load_fpr32(fp32, fs);
895c2d04 7058 gen_helper_float_truncl_s(fp64, cpu_env, fp32);
a7812ae4 7059 tcg_temp_free_i32(fp32);
b6d96bed 7060 gen_store_fpr64(ctx, fp64, fd);
a7812ae4 7061 tcg_temp_free_i64(fp64);
b6d96bed 7062 }
5a5012ec
TS
7063 opn = "trunc.l.s";
7064 break;
bf4120ad 7065 case OPC_CEIL_L_S:
5e755519 7066 check_cp1_64bitmode(ctx);
b6d96bed 7067 {
a7812ae4
PB
7068 TCGv_i32 fp32 = tcg_temp_new_i32();
7069 TCGv_i64 fp64 = tcg_temp_new_i64();
b6d96bed
TS
7070
7071 gen_load_fpr32(fp32, fs);
895c2d04 7072 gen_helper_float_ceill_s(fp64, cpu_env, fp32);
a7812ae4 7073 tcg_temp_free_i32(fp32);
b6d96bed 7074 gen_store_fpr64(ctx, fp64, fd);
a7812ae4 7075 tcg_temp_free_i64(fp64);
b6d96bed 7076 }
5a5012ec
TS
7077 opn = "ceil.l.s";
7078 break;
bf4120ad 7079 case OPC_FLOOR_L_S:
5e755519 7080 check_cp1_64bitmode(ctx);
b6d96bed 7081 {
a7812ae4
PB
7082 TCGv_i32 fp32 = tcg_temp_new_i32();
7083 TCGv_i64 fp64 = tcg_temp_new_i64();
b6d96bed
TS
7084
7085 gen_load_fpr32(fp32, fs);
895c2d04 7086 gen_helper_float_floorl_s(fp64, cpu_env, fp32);
a7812ae4 7087 tcg_temp_free_i32(fp32);
b6d96bed 7088 gen_store_fpr64(ctx, fp64, fd);
a7812ae4 7089 tcg_temp_free_i64(fp64);
b6d96bed 7090 }
5a5012ec
TS
7091 opn = "floor.l.s";
7092 break;
bf4120ad 7093 case OPC_ROUND_W_S:
b6d96bed 7094 {
a7812ae4 7095 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed
TS
7096
7097 gen_load_fpr32(fp0, fs);
895c2d04 7098 gen_helper_float_roundw_s(fp0, cpu_env, fp0);
b6d96bed 7099 gen_store_fpr32(fp0, fd);
a7812ae4 7100 tcg_temp_free_i32(fp0);
b6d96bed 7101 }
5a5012ec
TS
7102 opn = "round.w.s";
7103 break;
bf4120ad 7104 case OPC_TRUNC_W_S:
b6d96bed 7105 {
a7812ae4 7106 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed
TS
7107
7108 gen_load_fpr32(fp0, fs);
895c2d04 7109 gen_helper_float_truncw_s(fp0, cpu_env, fp0);
b6d96bed 7110 gen_store_fpr32(fp0, fd);
a7812ae4 7111 tcg_temp_free_i32(fp0);
b6d96bed 7112 }
5a5012ec
TS
7113 opn = "trunc.w.s";
7114 break;
bf4120ad 7115 case OPC_CEIL_W_S:
b6d96bed 7116 {
a7812ae4 7117 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed
TS
7118
7119 gen_load_fpr32(fp0, fs);
895c2d04 7120 gen_helper_float_ceilw_s(fp0, cpu_env, fp0);
b6d96bed 7121 gen_store_fpr32(fp0, fd);
a7812ae4 7122 tcg_temp_free_i32(fp0);
b6d96bed 7123 }
5a5012ec
TS
7124 opn = "ceil.w.s";
7125 break;
bf4120ad 7126 case OPC_FLOOR_W_S:
b6d96bed 7127 {
a7812ae4 7128 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed
TS
7129
7130 gen_load_fpr32(fp0, fs);
895c2d04 7131 gen_helper_float_floorw_s(fp0, cpu_env, fp0);
b6d96bed 7132 gen_store_fpr32(fp0, fd);
a7812ae4 7133 tcg_temp_free_i32(fp0);
b6d96bed 7134 }
5a5012ec
TS
7135 opn = "floor.w.s";
7136 break;
bf4120ad 7137 case OPC_MOVCF_S:
b6d96bed 7138 gen_movcf_s(fs, fd, (ft >> 2) & 0x7, ft & 0x1);
5a5012ec
TS
7139 opn = "movcf.s";
7140 break;
bf4120ad 7141 case OPC_MOVZ_S:
a16336e4
TS
7142 {
7143 int l1 = gen_new_label();
c9297f4d 7144 TCGv_i32 fp0;
a16336e4 7145
c9297f4d
AJ
7146 if (ft != 0) {
7147 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[ft], 0, l1);
7148 }
7149 fp0 = tcg_temp_new_i32();
b6d96bed
TS
7150 gen_load_fpr32(fp0, fs);
7151 gen_store_fpr32(fp0, fd);
a7812ae4 7152 tcg_temp_free_i32(fp0);
a16336e4
TS
7153 gen_set_label(l1);
7154 }
5a5012ec
TS
7155 opn = "movz.s";
7156 break;
bf4120ad 7157 case OPC_MOVN_S:
a16336e4
TS
7158 {
7159 int l1 = gen_new_label();
c9297f4d
AJ
7160 TCGv_i32 fp0;
7161
7162 if (ft != 0) {
7163 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[ft], 0, l1);
7164 fp0 = tcg_temp_new_i32();
7165 gen_load_fpr32(fp0, fs);
7166 gen_store_fpr32(fp0, fd);
7167 tcg_temp_free_i32(fp0);
7168 gen_set_label(l1);
7169 }
a16336e4 7170 }
5a5012ec
TS
7171 opn = "movn.s";
7172 break;
bf4120ad 7173 case OPC_RECIP_S:
b8aa4598 7174 check_cop1x(ctx);
b6d96bed 7175 {
a7812ae4 7176 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed
TS
7177
7178 gen_load_fpr32(fp0, fs);
895c2d04 7179 gen_helper_float_recip_s(fp0, cpu_env, fp0);
b6d96bed 7180 gen_store_fpr32(fp0, fd);
a7812ae4 7181 tcg_temp_free_i32(fp0);
b6d96bed 7182 }
57fa1fb3
TS
7183 opn = "recip.s";
7184 break;
bf4120ad 7185 case OPC_RSQRT_S:
b8aa4598 7186 check_cop1x(ctx);
b6d96bed 7187 {
a7812ae4 7188 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed
TS
7189
7190 gen_load_fpr32(fp0, fs);
895c2d04 7191 gen_helper_float_rsqrt_s(fp0, cpu_env, fp0);
b6d96bed 7192 gen_store_fpr32(fp0, fd);
a7812ae4 7193 tcg_temp_free_i32(fp0);
b6d96bed 7194 }
57fa1fb3
TS
7195 opn = "rsqrt.s";
7196 break;
bf4120ad 7197 case OPC_RECIP2_S:
5e755519 7198 check_cp1_64bitmode(ctx);
b6d96bed 7199 {
a7812ae4
PB
7200 TCGv_i32 fp0 = tcg_temp_new_i32();
7201 TCGv_i32 fp1 = tcg_temp_new_i32();
b6d96bed
TS
7202
7203 gen_load_fpr32(fp0, fs);
d22d7289 7204 gen_load_fpr32(fp1, ft);
895c2d04 7205 gen_helper_float_recip2_s(fp0, cpu_env, fp0, fp1);
a7812ae4 7206 tcg_temp_free_i32(fp1);
b6d96bed 7207 gen_store_fpr32(fp0, fd);
a7812ae4 7208 tcg_temp_free_i32(fp0);
b6d96bed 7209 }
57fa1fb3
TS
7210 opn = "recip2.s";
7211 break;
bf4120ad 7212 case OPC_RECIP1_S:
5e755519 7213 check_cp1_64bitmode(ctx);
b6d96bed 7214 {
a7812ae4 7215 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed
TS
7216
7217 gen_load_fpr32(fp0, fs);
895c2d04 7218 gen_helper_float_recip1_s(fp0, cpu_env, fp0);
b6d96bed 7219 gen_store_fpr32(fp0, fd);
a7812ae4 7220 tcg_temp_free_i32(fp0);
b6d96bed 7221 }
57fa1fb3
TS
7222 opn = "recip1.s";
7223 break;
bf4120ad 7224 case OPC_RSQRT1_S:
5e755519 7225 check_cp1_64bitmode(ctx);
b6d96bed 7226 {
a7812ae4 7227 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed
TS
7228
7229 gen_load_fpr32(fp0, fs);
895c2d04 7230 gen_helper_float_rsqrt1_s(fp0, cpu_env, fp0);
b6d96bed 7231 gen_store_fpr32(fp0, fd);
a7812ae4 7232 tcg_temp_free_i32(fp0);
b6d96bed 7233 }
57fa1fb3
TS
7234 opn = "rsqrt1.s";
7235 break;
bf4120ad 7236 case OPC_RSQRT2_S:
5e755519 7237 check_cp1_64bitmode(ctx);
b6d96bed 7238 {
a7812ae4
PB
7239 TCGv_i32 fp0 = tcg_temp_new_i32();
7240 TCGv_i32 fp1 = tcg_temp_new_i32();
b6d96bed
TS
7241
7242 gen_load_fpr32(fp0, fs);
7243 gen_load_fpr32(fp1, ft);
895c2d04 7244 gen_helper_float_rsqrt2_s(fp0, cpu_env, fp0, fp1);
a7812ae4 7245 tcg_temp_free_i32(fp1);
b6d96bed 7246 gen_store_fpr32(fp0, fd);
a7812ae4 7247 tcg_temp_free_i32(fp0);
b6d96bed 7248 }
57fa1fb3
TS
7249 opn = "rsqrt2.s";
7250 break;
bf4120ad 7251 case OPC_CVT_D_S:
5e755519 7252 check_cp1_registers(ctx, fd);
b6d96bed 7253 {
a7812ae4
PB
7254 TCGv_i32 fp32 = tcg_temp_new_i32();
7255 TCGv_i64 fp64 = tcg_temp_new_i64();
b6d96bed
TS
7256
7257 gen_load_fpr32(fp32, fs);
895c2d04 7258 gen_helper_float_cvtd_s(fp64, cpu_env, fp32);
a7812ae4 7259 tcg_temp_free_i32(fp32);
b6d96bed 7260 gen_store_fpr64(ctx, fp64, fd);
a7812ae4 7261 tcg_temp_free_i64(fp64);
b6d96bed 7262 }
5a5012ec
TS
7263 opn = "cvt.d.s";
7264 break;
bf4120ad 7265 case OPC_CVT_W_S:
b6d96bed 7266 {
a7812ae4 7267 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed
TS
7268
7269 gen_load_fpr32(fp0, fs);
895c2d04 7270 gen_helper_float_cvtw_s(fp0, cpu_env, fp0);
b6d96bed 7271 gen_store_fpr32(fp0, fd);
a7812ae4 7272 tcg_temp_free_i32(fp0);
b6d96bed 7273 }
5a5012ec
TS
7274 opn = "cvt.w.s";
7275 break;
bf4120ad 7276 case OPC_CVT_L_S:
5e755519 7277 check_cp1_64bitmode(ctx);
b6d96bed 7278 {
a7812ae4
PB
7279 TCGv_i32 fp32 = tcg_temp_new_i32();
7280 TCGv_i64 fp64 = tcg_temp_new_i64();
b6d96bed
TS
7281
7282 gen_load_fpr32(fp32, fs);
895c2d04 7283 gen_helper_float_cvtl_s(fp64, cpu_env, fp32);
a7812ae4 7284 tcg_temp_free_i32(fp32);
b6d96bed 7285 gen_store_fpr64(ctx, fp64, fd);
a7812ae4 7286 tcg_temp_free_i64(fp64);
b6d96bed 7287 }
5a5012ec
TS
7288 opn = "cvt.l.s";
7289 break;
bf4120ad 7290 case OPC_CVT_PS_S:
5e755519 7291 check_cp1_64bitmode(ctx);
b6d96bed 7292 {
a7812ae4
PB
7293 TCGv_i64 fp64 = tcg_temp_new_i64();
7294 TCGv_i32 fp32_0 = tcg_temp_new_i32();
7295 TCGv_i32 fp32_1 = tcg_temp_new_i32();
b6d96bed
TS
7296
7297 gen_load_fpr32(fp32_0, fs);
7298 gen_load_fpr32(fp32_1, ft);
13d24f49 7299 tcg_gen_concat_i32_i64(fp64, fp32_1, fp32_0);
a7812ae4
PB
7300 tcg_temp_free_i32(fp32_1);
7301 tcg_temp_free_i32(fp32_0);
36aa55dc 7302 gen_store_fpr64(ctx, fp64, fd);
a7812ae4 7303 tcg_temp_free_i64(fp64);
b6d96bed 7304 }
5a5012ec
TS
7305 opn = "cvt.ps.s";
7306 break;
bf4120ad
NF
7307 case OPC_CMP_F_S:
7308 case OPC_CMP_UN_S:
7309 case OPC_CMP_EQ_S:
7310 case OPC_CMP_UEQ_S:
7311 case OPC_CMP_OLT_S:
7312 case OPC_CMP_ULT_S:
7313 case OPC_CMP_OLE_S:
7314 case OPC_CMP_ULE_S:
7315 case OPC_CMP_SF_S:
7316 case OPC_CMP_NGLE_S:
7317 case OPC_CMP_SEQ_S:
7318 case OPC_CMP_NGL_S:
7319 case OPC_CMP_LT_S:
7320 case OPC_CMP_NGE_S:
7321 case OPC_CMP_LE_S:
7322 case OPC_CMP_NGT_S:
8153667c
NF
7323 if (ctx->opcode & (1 << 6)) {
7324 gen_cmpabs_s(ctx, func-48, ft, fs, cc);
7325 opn = condnames_abs[func-48];
7326 } else {
7327 gen_cmp_s(ctx, func-48, ft, fs, cc);
7328 opn = condnames[func-48];
5a1e8ffb 7329 }
5a5012ec 7330 break;
bf4120ad 7331 case OPC_ADD_D:
5e755519 7332 check_cp1_registers(ctx, fs | ft | fd);
b6d96bed 7333 {
a7812ae4
PB
7334 TCGv_i64 fp0 = tcg_temp_new_i64();
7335 TCGv_i64 fp1 = tcg_temp_new_i64();
b6d96bed
TS
7336
7337 gen_load_fpr64(ctx, fp0, fs);
7338 gen_load_fpr64(ctx, fp1, ft);
895c2d04 7339 gen_helper_float_add_d(fp0, cpu_env, fp0, fp1);
a7812ae4 7340 tcg_temp_free_i64(fp1);
b6d96bed 7341 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 7342 tcg_temp_free_i64(fp0);
b6d96bed 7343 }
6ea83fed 7344 opn = "add.d";
5a1e8ffb 7345 optype = BINOP;
6ea83fed 7346 break;
bf4120ad 7347 case OPC_SUB_D:
5e755519 7348 check_cp1_registers(ctx, fs | ft | fd);
b6d96bed 7349 {
a7812ae4
PB
7350 TCGv_i64 fp0 = tcg_temp_new_i64();
7351 TCGv_i64 fp1 = tcg_temp_new_i64();
b6d96bed
TS
7352
7353 gen_load_fpr64(ctx, fp0, fs);
7354 gen_load_fpr64(ctx, fp1, ft);
895c2d04 7355 gen_helper_float_sub_d(fp0, cpu_env, fp0, fp1);
a7812ae4 7356 tcg_temp_free_i64(fp1);
b6d96bed 7357 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 7358 tcg_temp_free_i64(fp0);
b6d96bed 7359 }
6ea83fed 7360 opn = "sub.d";
5a1e8ffb 7361 optype = BINOP;
6ea83fed 7362 break;
bf4120ad 7363 case OPC_MUL_D:
5e755519 7364 check_cp1_registers(ctx, fs | ft | fd);
b6d96bed 7365 {
a7812ae4
PB
7366 TCGv_i64 fp0 = tcg_temp_new_i64();
7367 TCGv_i64 fp1 = tcg_temp_new_i64();
b6d96bed
TS
7368
7369 gen_load_fpr64(ctx, fp0, fs);
7370 gen_load_fpr64(ctx, fp1, ft);
895c2d04 7371 gen_helper_float_mul_d(fp0, cpu_env, fp0, fp1);
a7812ae4 7372 tcg_temp_free_i64(fp1);
b6d96bed 7373 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 7374 tcg_temp_free_i64(fp0);
b6d96bed 7375 }
6ea83fed 7376 opn = "mul.d";
5a1e8ffb 7377 optype = BINOP;
6ea83fed 7378 break;
bf4120ad 7379 case OPC_DIV_D:
5e755519 7380 check_cp1_registers(ctx, fs | ft | fd);
b6d96bed 7381 {
a7812ae4
PB
7382 TCGv_i64 fp0 = tcg_temp_new_i64();
7383 TCGv_i64 fp1 = tcg_temp_new_i64();
b6d96bed
TS
7384
7385 gen_load_fpr64(ctx, fp0, fs);
7386 gen_load_fpr64(ctx, fp1, ft);
895c2d04 7387 gen_helper_float_div_d(fp0, cpu_env, fp0, fp1);
a7812ae4 7388 tcg_temp_free_i64(fp1);
b6d96bed 7389 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 7390 tcg_temp_free_i64(fp0);
b6d96bed 7391 }
6ea83fed 7392 opn = "div.d";
5a1e8ffb 7393 optype = BINOP;
6ea83fed 7394 break;
bf4120ad 7395 case OPC_SQRT_D:
5e755519 7396 check_cp1_registers(ctx, fs | fd);
b6d96bed 7397 {
a7812ae4 7398 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
7399
7400 gen_load_fpr64(ctx, fp0, fs);
895c2d04 7401 gen_helper_float_sqrt_d(fp0, cpu_env, fp0);
b6d96bed 7402 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 7403 tcg_temp_free_i64(fp0);
b6d96bed 7404 }
6ea83fed
FB
7405 opn = "sqrt.d";
7406 break;
bf4120ad 7407 case OPC_ABS_D:
5e755519 7408 check_cp1_registers(ctx, fs | fd);
b6d96bed 7409 {
a7812ae4 7410 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
7411
7412 gen_load_fpr64(ctx, fp0, fs);
a7812ae4 7413 gen_helper_float_abs_d(fp0, fp0);
b6d96bed 7414 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 7415 tcg_temp_free_i64(fp0);
b6d96bed 7416 }
6ea83fed
FB
7417 opn = "abs.d";
7418 break;
bf4120ad 7419 case OPC_MOV_D:
5e755519 7420 check_cp1_registers(ctx, fs | fd);
b6d96bed 7421 {
a7812ae4 7422 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
7423
7424 gen_load_fpr64(ctx, fp0, fs);
7425 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 7426 tcg_temp_free_i64(fp0);
b6d96bed 7427 }
6ea83fed
FB
7428 opn = "mov.d";
7429 break;
bf4120ad 7430 case OPC_NEG_D:
5e755519 7431 check_cp1_registers(ctx, fs | fd);
b6d96bed 7432 {
a7812ae4 7433 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
7434
7435 gen_load_fpr64(ctx, fp0, fs);
a7812ae4 7436 gen_helper_float_chs_d(fp0, fp0);
b6d96bed 7437 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 7438 tcg_temp_free_i64(fp0);
b6d96bed 7439 }
6ea83fed
FB
7440 opn = "neg.d";
7441 break;
bf4120ad 7442 case OPC_ROUND_L_D:
5e755519 7443 check_cp1_64bitmode(ctx);
b6d96bed 7444 {
a7812ae4 7445 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
7446
7447 gen_load_fpr64(ctx, fp0, fs);
895c2d04 7448 gen_helper_float_roundl_d(fp0, cpu_env, fp0);
b6d96bed 7449 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 7450 tcg_temp_free_i64(fp0);
b6d96bed 7451 }
5a5012ec
TS
7452 opn = "round.l.d";
7453 break;
bf4120ad 7454 case OPC_TRUNC_L_D:
5e755519 7455 check_cp1_64bitmode(ctx);
b6d96bed 7456 {
a7812ae4 7457 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
7458
7459 gen_load_fpr64(ctx, fp0, fs);
895c2d04 7460 gen_helper_float_truncl_d(fp0, cpu_env, fp0);
b6d96bed 7461 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 7462 tcg_temp_free_i64(fp0);
b6d96bed 7463 }
5a5012ec
TS
7464 opn = "trunc.l.d";
7465 break;
bf4120ad 7466 case OPC_CEIL_L_D:
5e755519 7467 check_cp1_64bitmode(ctx);
b6d96bed 7468 {
a7812ae4 7469 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
7470
7471 gen_load_fpr64(ctx, fp0, fs);
895c2d04 7472 gen_helper_float_ceill_d(fp0, cpu_env, fp0);
b6d96bed 7473 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 7474 tcg_temp_free_i64(fp0);
b6d96bed 7475 }
5a5012ec
TS
7476 opn = "ceil.l.d";
7477 break;
bf4120ad 7478 case OPC_FLOOR_L_D:
5e755519 7479 check_cp1_64bitmode(ctx);
b6d96bed 7480 {
a7812ae4 7481 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
7482
7483 gen_load_fpr64(ctx, fp0, fs);
895c2d04 7484 gen_helper_float_floorl_d(fp0, cpu_env, fp0);
b6d96bed 7485 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 7486 tcg_temp_free_i64(fp0);
b6d96bed 7487 }
5a5012ec
TS
7488 opn = "floor.l.d";
7489 break;
bf4120ad 7490 case OPC_ROUND_W_D:
5e755519 7491 check_cp1_registers(ctx, fs);
b6d96bed 7492 {
a7812ae4
PB
7493 TCGv_i32 fp32 = tcg_temp_new_i32();
7494 TCGv_i64 fp64 = tcg_temp_new_i64();
b6d96bed
TS
7495
7496 gen_load_fpr64(ctx, fp64, fs);
895c2d04 7497 gen_helper_float_roundw_d(fp32, cpu_env, fp64);
a7812ae4 7498 tcg_temp_free_i64(fp64);
b6d96bed 7499 gen_store_fpr32(fp32, fd);
a7812ae4 7500 tcg_temp_free_i32(fp32);
b6d96bed 7501 }
6ea83fed
FB
7502 opn = "round.w.d";
7503 break;
bf4120ad 7504 case OPC_TRUNC_W_D:
5e755519 7505 check_cp1_registers(ctx, fs);
b6d96bed 7506 {
a7812ae4
PB
7507 TCGv_i32 fp32 = tcg_temp_new_i32();
7508 TCGv_i64 fp64 = tcg_temp_new_i64();
b6d96bed
TS
7509
7510 gen_load_fpr64(ctx, fp64, fs);
895c2d04 7511 gen_helper_float_truncw_d(fp32, cpu_env, fp64);
a7812ae4 7512 tcg_temp_free_i64(fp64);
b6d96bed 7513 gen_store_fpr32(fp32, fd);
a7812ae4 7514 tcg_temp_free_i32(fp32);
b6d96bed 7515 }
6ea83fed
FB
7516 opn = "trunc.w.d";
7517 break;
bf4120ad 7518 case OPC_CEIL_W_D:
5e755519 7519 check_cp1_registers(ctx, fs);
b6d96bed 7520 {
a7812ae4
PB
7521 TCGv_i32 fp32 = tcg_temp_new_i32();
7522 TCGv_i64 fp64 = tcg_temp_new_i64();
b6d96bed
TS
7523
7524 gen_load_fpr64(ctx, fp64, fs);
895c2d04 7525 gen_helper_float_ceilw_d(fp32, cpu_env, fp64);
a7812ae4 7526 tcg_temp_free_i64(fp64);
b6d96bed 7527 gen_store_fpr32(fp32, fd);
a7812ae4 7528 tcg_temp_free_i32(fp32);
b6d96bed 7529 }
6ea83fed
FB
7530 opn = "ceil.w.d";
7531 break;
bf4120ad 7532 case OPC_FLOOR_W_D:
5e755519 7533 check_cp1_registers(ctx, fs);
b6d96bed 7534 {
a7812ae4
PB
7535 TCGv_i32 fp32 = tcg_temp_new_i32();
7536 TCGv_i64 fp64 = tcg_temp_new_i64();
b6d96bed
TS
7537
7538 gen_load_fpr64(ctx, fp64, fs);
895c2d04 7539 gen_helper_float_floorw_d(fp32, cpu_env, fp64);
a7812ae4 7540 tcg_temp_free_i64(fp64);
b6d96bed 7541 gen_store_fpr32(fp32, fd);
a7812ae4 7542 tcg_temp_free_i32(fp32);
b6d96bed 7543 }
7a387fff 7544 opn = "floor.w.d";
6ea83fed 7545 break;
bf4120ad 7546 case OPC_MOVCF_D:
b6d96bed 7547 gen_movcf_d(ctx, fs, fd, (ft >> 2) & 0x7, ft & 0x1);
5a5012ec 7548 opn = "movcf.d";
dd016883 7549 break;
bf4120ad 7550 case OPC_MOVZ_D:
a16336e4
TS
7551 {
7552 int l1 = gen_new_label();
c9297f4d 7553 TCGv_i64 fp0;
a16336e4 7554
c9297f4d
AJ
7555 if (ft != 0) {
7556 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[ft], 0, l1);
7557 }
7558 fp0 = tcg_temp_new_i64();
b6d96bed
TS
7559 gen_load_fpr64(ctx, fp0, fs);
7560 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 7561 tcg_temp_free_i64(fp0);
a16336e4
TS
7562 gen_set_label(l1);
7563 }
5a5012ec
TS
7564 opn = "movz.d";
7565 break;
bf4120ad 7566 case OPC_MOVN_D:
a16336e4
TS
7567 {
7568 int l1 = gen_new_label();
c9297f4d
AJ
7569 TCGv_i64 fp0;
7570
7571 if (ft != 0) {
7572 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[ft], 0, l1);
7573 fp0 = tcg_temp_new_i64();
7574 gen_load_fpr64(ctx, fp0, fs);
7575 gen_store_fpr64(ctx, fp0, fd);
7576 tcg_temp_free_i64(fp0);
7577 gen_set_label(l1);
7578 }
a16336e4 7579 }
5a5012ec 7580 opn = "movn.d";
6ea83fed 7581 break;
bf4120ad 7582 case OPC_RECIP_D:
b8aa4598 7583 check_cp1_64bitmode(ctx);
b6d96bed 7584 {
a7812ae4 7585 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
7586
7587 gen_load_fpr64(ctx, fp0, fs);
895c2d04 7588 gen_helper_float_recip_d(fp0, cpu_env, fp0);
b6d96bed 7589 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 7590 tcg_temp_free_i64(fp0);
b6d96bed 7591 }
57fa1fb3
TS
7592 opn = "recip.d";
7593 break;
bf4120ad 7594 case OPC_RSQRT_D:
b8aa4598 7595 check_cp1_64bitmode(ctx);
b6d96bed 7596 {
a7812ae4 7597 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
7598
7599 gen_load_fpr64(ctx, fp0, fs);
895c2d04 7600 gen_helper_float_rsqrt_d(fp0, cpu_env, fp0);
b6d96bed 7601 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 7602 tcg_temp_free_i64(fp0);
b6d96bed 7603 }
57fa1fb3
TS
7604 opn = "rsqrt.d";
7605 break;
bf4120ad 7606 case OPC_RECIP2_D:
5e755519 7607 check_cp1_64bitmode(ctx);
b6d96bed 7608 {
a7812ae4
PB
7609 TCGv_i64 fp0 = tcg_temp_new_i64();
7610 TCGv_i64 fp1 = tcg_temp_new_i64();
b6d96bed
TS
7611
7612 gen_load_fpr64(ctx, fp0, fs);
7613 gen_load_fpr64(ctx, fp1, ft);
895c2d04 7614 gen_helper_float_recip2_d(fp0, cpu_env, fp0, fp1);
a7812ae4 7615 tcg_temp_free_i64(fp1);
b6d96bed 7616 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 7617 tcg_temp_free_i64(fp0);
b6d96bed 7618 }
57fa1fb3
TS
7619 opn = "recip2.d";
7620 break;
bf4120ad 7621 case OPC_RECIP1_D:
5e755519 7622 check_cp1_64bitmode(ctx);
b6d96bed 7623 {
a7812ae4 7624 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
7625
7626 gen_load_fpr64(ctx, fp0, fs);
895c2d04 7627 gen_helper_float_recip1_d(fp0, cpu_env, fp0);
b6d96bed 7628 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 7629 tcg_temp_free_i64(fp0);
b6d96bed 7630 }
57fa1fb3
TS
7631 opn = "recip1.d";
7632 break;
bf4120ad 7633 case OPC_RSQRT1_D:
5e755519 7634 check_cp1_64bitmode(ctx);
b6d96bed 7635 {
a7812ae4 7636 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
7637
7638 gen_load_fpr64(ctx, fp0, fs);
895c2d04 7639 gen_helper_float_rsqrt1_d(fp0, cpu_env, fp0);
b6d96bed 7640 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 7641 tcg_temp_free_i64(fp0);
b6d96bed 7642 }
57fa1fb3
TS
7643 opn = "rsqrt1.d";
7644 break;
bf4120ad 7645 case OPC_RSQRT2_D:
5e755519 7646 check_cp1_64bitmode(ctx);
b6d96bed 7647 {
a7812ae4
PB
7648 TCGv_i64 fp0 = tcg_temp_new_i64();
7649 TCGv_i64 fp1 = tcg_temp_new_i64();
b6d96bed
TS
7650
7651 gen_load_fpr64(ctx, fp0, fs);
7652 gen_load_fpr64(ctx, fp1, ft);
895c2d04 7653 gen_helper_float_rsqrt2_d(fp0, cpu_env, fp0, fp1);
a7812ae4 7654 tcg_temp_free_i64(fp1);
b6d96bed 7655 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 7656 tcg_temp_free_i64(fp0);
b6d96bed 7657 }
57fa1fb3
TS
7658 opn = "rsqrt2.d";
7659 break;
bf4120ad
NF
7660 case OPC_CMP_F_D:
7661 case OPC_CMP_UN_D:
7662 case OPC_CMP_EQ_D:
7663 case OPC_CMP_UEQ_D:
7664 case OPC_CMP_OLT_D:
7665 case OPC_CMP_ULT_D:
7666 case OPC_CMP_OLE_D:
7667 case OPC_CMP_ULE_D:
7668 case OPC_CMP_SF_D:
7669 case OPC_CMP_NGLE_D:
7670 case OPC_CMP_SEQ_D:
7671 case OPC_CMP_NGL_D:
7672 case OPC_CMP_LT_D:
7673 case OPC_CMP_NGE_D:
7674 case OPC_CMP_LE_D:
7675 case OPC_CMP_NGT_D:
8153667c
NF
7676 if (ctx->opcode & (1 << 6)) {
7677 gen_cmpabs_d(ctx, func-48, ft, fs, cc);
7678 opn = condnames_abs[func-48];
7679 } else {
7680 gen_cmp_d(ctx, func-48, ft, fs, cc);
7681 opn = condnames[func-48];
5a1e8ffb 7682 }
6ea83fed 7683 break;
bf4120ad 7684 case OPC_CVT_S_D:
5e755519 7685 check_cp1_registers(ctx, fs);
b6d96bed 7686 {
a7812ae4
PB
7687 TCGv_i32 fp32 = tcg_temp_new_i32();
7688 TCGv_i64 fp64 = tcg_temp_new_i64();
b6d96bed
TS
7689
7690 gen_load_fpr64(ctx, fp64, fs);
895c2d04 7691 gen_helper_float_cvts_d(fp32, cpu_env, fp64);
a7812ae4 7692 tcg_temp_free_i64(fp64);
b6d96bed 7693 gen_store_fpr32(fp32, fd);
a7812ae4 7694 tcg_temp_free_i32(fp32);
b6d96bed 7695 }
5a5012ec
TS
7696 opn = "cvt.s.d";
7697 break;
bf4120ad 7698 case OPC_CVT_W_D:
5e755519 7699 check_cp1_registers(ctx, fs);
b6d96bed 7700 {
a7812ae4
PB
7701 TCGv_i32 fp32 = tcg_temp_new_i32();
7702 TCGv_i64 fp64 = tcg_temp_new_i64();
b6d96bed
TS
7703
7704 gen_load_fpr64(ctx, fp64, fs);
895c2d04 7705 gen_helper_float_cvtw_d(fp32, cpu_env, fp64);
a7812ae4 7706 tcg_temp_free_i64(fp64);
b6d96bed 7707 gen_store_fpr32(fp32, fd);
a7812ae4 7708 tcg_temp_free_i32(fp32);
b6d96bed 7709 }
5a5012ec
TS
7710 opn = "cvt.w.d";
7711 break;
bf4120ad 7712 case OPC_CVT_L_D:
5e755519 7713 check_cp1_64bitmode(ctx);
b6d96bed 7714 {
a7812ae4 7715 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
7716
7717 gen_load_fpr64(ctx, fp0, fs);
895c2d04 7718 gen_helper_float_cvtl_d(fp0, cpu_env, fp0);
b6d96bed 7719 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 7720 tcg_temp_free_i64(fp0);
b6d96bed 7721 }
5a5012ec
TS
7722 opn = "cvt.l.d";
7723 break;
bf4120ad 7724 case OPC_CVT_S_W:
b6d96bed 7725 {
a7812ae4 7726 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed
TS
7727
7728 gen_load_fpr32(fp0, fs);
895c2d04 7729 gen_helper_float_cvts_w(fp0, cpu_env, fp0);
b6d96bed 7730 gen_store_fpr32(fp0, fd);
a7812ae4 7731 tcg_temp_free_i32(fp0);
b6d96bed 7732 }
5a5012ec 7733 opn = "cvt.s.w";
6ea83fed 7734 break;
bf4120ad 7735 case OPC_CVT_D_W:
5e755519 7736 check_cp1_registers(ctx, fd);
b6d96bed 7737 {
a7812ae4
PB
7738 TCGv_i32 fp32 = tcg_temp_new_i32();
7739 TCGv_i64 fp64 = tcg_temp_new_i64();
b6d96bed
TS
7740
7741 gen_load_fpr32(fp32, fs);
895c2d04 7742 gen_helper_float_cvtd_w(fp64, cpu_env, fp32);
a7812ae4 7743 tcg_temp_free_i32(fp32);
b6d96bed 7744 gen_store_fpr64(ctx, fp64, fd);
a7812ae4 7745 tcg_temp_free_i64(fp64);
b6d96bed 7746 }
5a5012ec
TS
7747 opn = "cvt.d.w";
7748 break;
bf4120ad 7749 case OPC_CVT_S_L:
5e755519 7750 check_cp1_64bitmode(ctx);
b6d96bed 7751 {
a7812ae4
PB
7752 TCGv_i32 fp32 = tcg_temp_new_i32();
7753 TCGv_i64 fp64 = tcg_temp_new_i64();
b6d96bed
TS
7754
7755 gen_load_fpr64(ctx, fp64, fs);
895c2d04 7756 gen_helper_float_cvts_l(fp32, cpu_env, fp64);
a7812ae4 7757 tcg_temp_free_i64(fp64);
b6d96bed 7758 gen_store_fpr32(fp32, fd);
a7812ae4 7759 tcg_temp_free_i32(fp32);
b6d96bed 7760 }
5a5012ec
TS
7761 opn = "cvt.s.l";
7762 break;
bf4120ad 7763 case OPC_CVT_D_L:
5e755519 7764 check_cp1_64bitmode(ctx);
b6d96bed 7765 {
a7812ae4 7766 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
7767
7768 gen_load_fpr64(ctx, fp0, fs);
895c2d04 7769 gen_helper_float_cvtd_l(fp0, cpu_env, fp0);
b6d96bed 7770 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 7771 tcg_temp_free_i64(fp0);
b6d96bed 7772 }
5a5012ec
TS
7773 opn = "cvt.d.l";
7774 break;
bf4120ad 7775 case OPC_CVT_PS_PW:
5e755519 7776 check_cp1_64bitmode(ctx);
b6d96bed 7777 {
a7812ae4 7778 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
7779
7780 gen_load_fpr64(ctx, fp0, fs);
895c2d04 7781 gen_helper_float_cvtps_pw(fp0, cpu_env, fp0);
b6d96bed 7782 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 7783 tcg_temp_free_i64(fp0);
b6d96bed 7784 }
5a5012ec
TS
7785 opn = "cvt.ps.pw";
7786 break;
bf4120ad 7787 case OPC_ADD_PS:
5e755519 7788 check_cp1_64bitmode(ctx);
b6d96bed 7789 {
a7812ae4
PB
7790 TCGv_i64 fp0 = tcg_temp_new_i64();
7791 TCGv_i64 fp1 = tcg_temp_new_i64();
b6d96bed
TS
7792
7793 gen_load_fpr64(ctx, fp0, fs);
7794 gen_load_fpr64(ctx, fp1, ft);
895c2d04 7795 gen_helper_float_add_ps(fp0, cpu_env, fp0, fp1);
a7812ae4 7796 tcg_temp_free_i64(fp1);
b6d96bed 7797 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 7798 tcg_temp_free_i64(fp0);
b6d96bed 7799 }
5a5012ec 7800 opn = "add.ps";
6ea83fed 7801 break;
bf4120ad 7802 case OPC_SUB_PS:
5e755519 7803 check_cp1_64bitmode(ctx);
b6d96bed 7804 {
a7812ae4
PB
7805 TCGv_i64 fp0 = tcg_temp_new_i64();
7806 TCGv_i64 fp1 = tcg_temp_new_i64();
b6d96bed
TS
7807
7808 gen_load_fpr64(ctx, fp0, fs);
7809 gen_load_fpr64(ctx, fp1, ft);
895c2d04 7810 gen_helper_float_sub_ps(fp0, cpu_env, fp0, fp1);
a7812ae4 7811 tcg_temp_free_i64(fp1);
b6d96bed 7812 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 7813 tcg_temp_free_i64(fp0);
b6d96bed 7814 }
5a5012ec 7815 opn = "sub.ps";
6ea83fed 7816 break;
bf4120ad 7817 case OPC_MUL_PS:
5e755519 7818 check_cp1_64bitmode(ctx);
b6d96bed 7819 {
a7812ae4
PB
7820 TCGv_i64 fp0 = tcg_temp_new_i64();
7821 TCGv_i64 fp1 = tcg_temp_new_i64();
b6d96bed
TS
7822
7823 gen_load_fpr64(ctx, fp0, fs);
7824 gen_load_fpr64(ctx, fp1, ft);
895c2d04 7825 gen_helper_float_mul_ps(fp0, cpu_env, fp0, fp1);
a7812ae4 7826 tcg_temp_free_i64(fp1);
b6d96bed 7827 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 7828 tcg_temp_free_i64(fp0);
b6d96bed 7829 }
5a5012ec 7830 opn = "mul.ps";
6ea83fed 7831 break;
bf4120ad 7832 case OPC_ABS_PS:
5e755519 7833 check_cp1_64bitmode(ctx);
b6d96bed 7834 {
a7812ae4 7835 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
7836
7837 gen_load_fpr64(ctx, fp0, fs);
a7812ae4 7838 gen_helper_float_abs_ps(fp0, fp0);
b6d96bed 7839 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 7840 tcg_temp_free_i64(fp0);
b6d96bed 7841 }
5a5012ec 7842 opn = "abs.ps";
6ea83fed 7843 break;
bf4120ad 7844 case OPC_MOV_PS:
5e755519 7845 check_cp1_64bitmode(ctx);
b6d96bed 7846 {
a7812ae4 7847 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
7848
7849 gen_load_fpr64(ctx, fp0, fs);
7850 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 7851 tcg_temp_free_i64(fp0);
b6d96bed 7852 }
5a5012ec 7853 opn = "mov.ps";
6ea83fed 7854 break;
bf4120ad 7855 case OPC_NEG_PS:
5e755519 7856 check_cp1_64bitmode(ctx);
b6d96bed 7857 {
a7812ae4 7858 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
7859
7860 gen_load_fpr64(ctx, fp0, fs);
a7812ae4 7861 gen_helper_float_chs_ps(fp0, fp0);
b6d96bed 7862 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 7863 tcg_temp_free_i64(fp0);
b6d96bed 7864 }
5a5012ec 7865 opn = "neg.ps";
6ea83fed 7866 break;
bf4120ad 7867 case OPC_MOVCF_PS:
5e755519 7868 check_cp1_64bitmode(ctx);
b6d96bed 7869 gen_movcf_ps(fs, fd, (ft >> 2) & 0x7, ft & 0x1);
5a5012ec 7870 opn = "movcf.ps";
6ea83fed 7871 break;
bf4120ad 7872 case OPC_MOVZ_PS:
5e755519 7873 check_cp1_64bitmode(ctx);
a16336e4
TS
7874 {
7875 int l1 = gen_new_label();
30a3848b 7876 TCGv_i64 fp0;
a16336e4 7877
c9297f4d
AJ
7878 if (ft != 0)
7879 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[ft], 0, l1);
7880 fp0 = tcg_temp_new_i64();
7881 gen_load_fpr64(ctx, fp0, fs);
7882 gen_store_fpr64(ctx, fp0, fd);
7883 tcg_temp_free_i64(fp0);
a16336e4
TS
7884 gen_set_label(l1);
7885 }
5a5012ec 7886 opn = "movz.ps";
6ea83fed 7887 break;
bf4120ad 7888 case OPC_MOVN_PS:
5e755519 7889 check_cp1_64bitmode(ctx);
a16336e4
TS
7890 {
7891 int l1 = gen_new_label();
30a3848b 7892 TCGv_i64 fp0;
c9297f4d
AJ
7893
7894 if (ft != 0) {
7895 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[ft], 0, l1);
7896 fp0 = tcg_temp_new_i64();
7897 gen_load_fpr64(ctx, fp0, fs);
7898 gen_store_fpr64(ctx, fp0, fd);
7899 tcg_temp_free_i64(fp0);
7900 gen_set_label(l1);
7901 }
a16336e4 7902 }
5a5012ec 7903 opn = "movn.ps";
6ea83fed 7904 break;
bf4120ad 7905 case OPC_ADDR_PS:
5e755519 7906 check_cp1_64bitmode(ctx);
b6d96bed 7907 {
a7812ae4
PB
7908 TCGv_i64 fp0 = tcg_temp_new_i64();
7909 TCGv_i64 fp1 = tcg_temp_new_i64();
b6d96bed
TS
7910
7911 gen_load_fpr64(ctx, fp0, ft);
7912 gen_load_fpr64(ctx, fp1, fs);
895c2d04 7913 gen_helper_float_addr_ps(fp0, cpu_env, fp0, fp1);
a7812ae4 7914 tcg_temp_free_i64(fp1);
b6d96bed 7915 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 7916 tcg_temp_free_i64(fp0);
b6d96bed 7917 }
fbcc6828
TS
7918 opn = "addr.ps";
7919 break;
bf4120ad 7920 case OPC_MULR_PS:
5e755519 7921 check_cp1_64bitmode(ctx);
b6d96bed 7922 {
a7812ae4
PB
7923 TCGv_i64 fp0 = tcg_temp_new_i64();
7924 TCGv_i64 fp1 = tcg_temp_new_i64();
b6d96bed
TS
7925
7926 gen_load_fpr64(ctx, fp0, ft);
7927 gen_load_fpr64(ctx, fp1, fs);
895c2d04 7928 gen_helper_float_mulr_ps(fp0, cpu_env, fp0, fp1);
a7812ae4 7929 tcg_temp_free_i64(fp1);
b6d96bed 7930 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 7931 tcg_temp_free_i64(fp0);
b6d96bed 7932 }
57fa1fb3
TS
7933 opn = "mulr.ps";
7934 break;
bf4120ad 7935 case OPC_RECIP2_PS:
5e755519 7936 check_cp1_64bitmode(ctx);
b6d96bed 7937 {
a7812ae4
PB
7938 TCGv_i64 fp0 = tcg_temp_new_i64();
7939 TCGv_i64 fp1 = tcg_temp_new_i64();
b6d96bed
TS
7940
7941 gen_load_fpr64(ctx, fp0, fs);
d22d7289 7942 gen_load_fpr64(ctx, fp1, ft);
895c2d04 7943 gen_helper_float_recip2_ps(fp0, cpu_env, fp0, fp1);
a7812ae4 7944 tcg_temp_free_i64(fp1);
b6d96bed 7945 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 7946 tcg_temp_free_i64(fp0);
b6d96bed 7947 }
57fa1fb3
TS
7948 opn = "recip2.ps";
7949 break;
bf4120ad 7950 case OPC_RECIP1_PS:
5e755519 7951 check_cp1_64bitmode(ctx);
b6d96bed 7952 {
a7812ae4 7953 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
7954
7955 gen_load_fpr64(ctx, fp0, fs);
895c2d04 7956 gen_helper_float_recip1_ps(fp0, cpu_env, fp0);
b6d96bed 7957 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 7958 tcg_temp_free_i64(fp0);
b6d96bed 7959 }
57fa1fb3
TS
7960 opn = "recip1.ps";
7961 break;
bf4120ad 7962 case OPC_RSQRT1_PS:
5e755519 7963 check_cp1_64bitmode(ctx);
b6d96bed 7964 {
a7812ae4 7965 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
7966
7967 gen_load_fpr64(ctx, fp0, fs);
895c2d04 7968 gen_helper_float_rsqrt1_ps(fp0, cpu_env, fp0);
b6d96bed 7969 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 7970 tcg_temp_free_i64(fp0);
b6d96bed 7971 }
57fa1fb3
TS
7972 opn = "rsqrt1.ps";
7973 break;
bf4120ad 7974 case OPC_RSQRT2_PS:
5e755519 7975 check_cp1_64bitmode(ctx);
b6d96bed 7976 {
a7812ae4
PB
7977 TCGv_i64 fp0 = tcg_temp_new_i64();
7978 TCGv_i64 fp1 = tcg_temp_new_i64();
b6d96bed
TS
7979
7980 gen_load_fpr64(ctx, fp0, fs);
7981 gen_load_fpr64(ctx, fp1, ft);
895c2d04 7982 gen_helper_float_rsqrt2_ps(fp0, cpu_env, fp0, fp1);
a7812ae4 7983 tcg_temp_free_i64(fp1);
b6d96bed 7984 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 7985 tcg_temp_free_i64(fp0);
b6d96bed 7986 }
57fa1fb3
TS
7987 opn = "rsqrt2.ps";
7988 break;
bf4120ad 7989 case OPC_CVT_S_PU:
5e755519 7990 check_cp1_64bitmode(ctx);
b6d96bed 7991 {
a7812ae4 7992 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed
TS
7993
7994 gen_load_fpr32h(fp0, fs);
895c2d04 7995 gen_helper_float_cvts_pu(fp0, cpu_env, fp0);
b6d96bed 7996 gen_store_fpr32(fp0, fd);
a7812ae4 7997 tcg_temp_free_i32(fp0);
b6d96bed 7998 }
5a5012ec 7999 opn = "cvt.s.pu";
dd016883 8000 break;
bf4120ad 8001 case OPC_CVT_PW_PS:
5e755519 8002 check_cp1_64bitmode(ctx);
b6d96bed 8003 {
a7812ae4 8004 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
8005
8006 gen_load_fpr64(ctx, fp0, fs);
895c2d04 8007 gen_helper_float_cvtpw_ps(fp0, cpu_env, fp0);
b6d96bed 8008 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 8009 tcg_temp_free_i64(fp0);
b6d96bed 8010 }
5a5012ec 8011 opn = "cvt.pw.ps";
6ea83fed 8012 break;
bf4120ad 8013 case OPC_CVT_S_PL:
5e755519 8014 check_cp1_64bitmode(ctx);
b6d96bed 8015 {
a7812ae4 8016 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed
TS
8017
8018 gen_load_fpr32(fp0, fs);
895c2d04 8019 gen_helper_float_cvts_pl(fp0, cpu_env, fp0);
b6d96bed 8020 gen_store_fpr32(fp0, fd);
a7812ae4 8021 tcg_temp_free_i32(fp0);
b6d96bed 8022 }
5a5012ec 8023 opn = "cvt.s.pl";
6ea83fed 8024 break;
bf4120ad 8025 case OPC_PLL_PS:
5e755519 8026 check_cp1_64bitmode(ctx);
b6d96bed 8027 {
a7812ae4
PB
8028 TCGv_i32 fp0 = tcg_temp_new_i32();
8029 TCGv_i32 fp1 = tcg_temp_new_i32();
b6d96bed
TS
8030
8031 gen_load_fpr32(fp0, fs);
8032 gen_load_fpr32(fp1, ft);
8033 gen_store_fpr32h(fp0, fd);
8034 gen_store_fpr32(fp1, fd);
a7812ae4
PB
8035 tcg_temp_free_i32(fp0);
8036 tcg_temp_free_i32(fp1);
b6d96bed 8037 }
5a5012ec 8038 opn = "pll.ps";
6ea83fed 8039 break;
bf4120ad 8040 case OPC_PLU_PS:
5e755519 8041 check_cp1_64bitmode(ctx);
b6d96bed 8042 {
a7812ae4
PB
8043 TCGv_i32 fp0 = tcg_temp_new_i32();
8044 TCGv_i32 fp1 = tcg_temp_new_i32();
b6d96bed
TS
8045
8046 gen_load_fpr32(fp0, fs);
8047 gen_load_fpr32h(fp1, ft);
8048 gen_store_fpr32(fp1, fd);
8049 gen_store_fpr32h(fp0, fd);
a7812ae4
PB
8050 tcg_temp_free_i32(fp0);
8051 tcg_temp_free_i32(fp1);
b6d96bed 8052 }
5a5012ec
TS
8053 opn = "plu.ps";
8054 break;
bf4120ad 8055 case OPC_PUL_PS:
5e755519 8056 check_cp1_64bitmode(ctx);
b6d96bed 8057 {
a7812ae4
PB
8058 TCGv_i32 fp0 = tcg_temp_new_i32();
8059 TCGv_i32 fp1 = tcg_temp_new_i32();
b6d96bed
TS
8060
8061 gen_load_fpr32h(fp0, fs);
8062 gen_load_fpr32(fp1, ft);
8063 gen_store_fpr32(fp1, fd);
8064 gen_store_fpr32h(fp0, fd);
a7812ae4
PB
8065 tcg_temp_free_i32(fp0);
8066 tcg_temp_free_i32(fp1);
b6d96bed 8067 }
5a5012ec
TS
8068 opn = "pul.ps";
8069 break;
bf4120ad 8070 case OPC_PUU_PS:
5e755519 8071 check_cp1_64bitmode(ctx);
b6d96bed 8072 {
a7812ae4
PB
8073 TCGv_i32 fp0 = tcg_temp_new_i32();
8074 TCGv_i32 fp1 = tcg_temp_new_i32();
b6d96bed
TS
8075
8076 gen_load_fpr32h(fp0, fs);
8077 gen_load_fpr32h(fp1, ft);
8078 gen_store_fpr32(fp1, fd);
8079 gen_store_fpr32h(fp0, fd);
a7812ae4
PB
8080 tcg_temp_free_i32(fp0);
8081 tcg_temp_free_i32(fp1);
b6d96bed 8082 }
5a5012ec
TS
8083 opn = "puu.ps";
8084 break;
bf4120ad
NF
8085 case OPC_CMP_F_PS:
8086 case OPC_CMP_UN_PS:
8087 case OPC_CMP_EQ_PS:
8088 case OPC_CMP_UEQ_PS:
8089 case OPC_CMP_OLT_PS:
8090 case OPC_CMP_ULT_PS:
8091 case OPC_CMP_OLE_PS:
8092 case OPC_CMP_ULE_PS:
8093 case OPC_CMP_SF_PS:
8094 case OPC_CMP_NGLE_PS:
8095 case OPC_CMP_SEQ_PS:
8096 case OPC_CMP_NGL_PS:
8097 case OPC_CMP_LT_PS:
8098 case OPC_CMP_NGE_PS:
8099 case OPC_CMP_LE_PS:
8100 case OPC_CMP_NGT_PS:
8153667c
NF
8101 if (ctx->opcode & (1 << 6)) {
8102 gen_cmpabs_ps(ctx, func-48, ft, fs, cc);
8103 opn = condnames_abs[func-48];
8104 } else {
8105 gen_cmp_ps(ctx, func-48, ft, fs, cc);
8106 opn = condnames[func-48];
5a1e8ffb 8107 }
6ea83fed 8108 break;
5a5012ec 8109 default:
923617a3 8110 MIPS_INVAL(opn);
e397ee33 8111 generate_exception (ctx, EXCP_RI);
6ea83fed
FB
8112 return;
8113 }
2abf314d 8114 (void)opn; /* avoid a compiler warning */
5a1e8ffb
TS
8115 switch (optype) {
8116 case BINOP:
6ea83fed 8117 MIPS_DEBUG("%s %s, %s, %s", opn, fregnames[fd], fregnames[fs], fregnames[ft]);
5a1e8ffb
TS
8118 break;
8119 case CMPOP:
8120 MIPS_DEBUG("%s %s,%s", opn, fregnames[fs], fregnames[ft]);
8121 break;
8122 default:
6ea83fed 8123 MIPS_DEBUG("%s %s,%s", opn, fregnames[fd], fregnames[fs]);
5a1e8ffb
TS
8124 break;
8125 }
6ea83fed 8126}
6af0bf9c 8127
5a5012ec 8128/* Coprocessor 3 (FPU) */
5e755519
TS
8129static void gen_flt3_ldst (DisasContext *ctx, uint32_t opc,
8130 int fd, int fs, int base, int index)
7a387fff 8131{
923617a3 8132 const char *opn = "extended float load/store";
93b12ccc 8133 int store = 0;
4e2474d6 8134 TCGv t0 = tcg_temp_new();
7a387fff 8135
93b12ccc 8136 if (base == 0) {
6c5c1e20 8137 gen_load_gpr(t0, index);
93b12ccc 8138 } else if (index == 0) {
6c5c1e20 8139 gen_load_gpr(t0, base);
93b12ccc 8140 } else {
05168674 8141 gen_op_addr_add(ctx, t0, cpu_gpr[base], cpu_gpr[index]);
93b12ccc 8142 }
5a5012ec 8143 /* Don't do NOP if destination is zero: we must perform the actual
ead9360e 8144 memory access. */
4e2474d6 8145 save_cpu_state(ctx, 0);
5a5012ec
TS
8146 switch (opc) {
8147 case OPC_LWXC1:
8c0ab41f 8148 check_cop1x(ctx);
b6d96bed 8149 {
a7812ae4 8150 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed 8151
585c88d5
AJ
8152 tcg_gen_qemu_ld32s(t0, t0, ctx->mem_idx);
8153 tcg_gen_trunc_tl_i32(fp0, t0);
b6d96bed 8154 gen_store_fpr32(fp0, fd);
a7812ae4 8155 tcg_temp_free_i32(fp0);
b6d96bed 8156 }
5a5012ec
TS
8157 opn = "lwxc1";
8158 break;
8159 case OPC_LDXC1:
8c0ab41f
AJ
8160 check_cop1x(ctx);
8161 check_cp1_registers(ctx, fd);
b6d96bed 8162 {
a7812ae4 8163 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
8164
8165 tcg_gen_qemu_ld64(fp0, t0, ctx->mem_idx);
8166 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 8167 tcg_temp_free_i64(fp0);
b6d96bed 8168 }
5a5012ec
TS
8169 opn = "ldxc1";
8170 break;
8171 case OPC_LUXC1:
8c0ab41f 8172 check_cp1_64bitmode(ctx);
6c5c1e20 8173 tcg_gen_andi_tl(t0, t0, ~0x7);
b6d96bed 8174 {
a7812ae4 8175 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
8176
8177 tcg_gen_qemu_ld64(fp0, t0, ctx->mem_idx);
8178 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 8179 tcg_temp_free_i64(fp0);
b6d96bed 8180 }
5a5012ec
TS
8181 opn = "luxc1";
8182 break;
8183 case OPC_SWXC1:
8c0ab41f 8184 check_cop1x(ctx);
b6d96bed 8185 {
a7812ae4 8186 TCGv_i32 fp0 = tcg_temp_new_i32();
585c88d5 8187 TCGv t1 = tcg_temp_new();
b6d96bed
TS
8188
8189 gen_load_fpr32(fp0, fs);
a7812ae4
PB
8190 tcg_gen_extu_i32_tl(t1, fp0);
8191 tcg_gen_qemu_st32(t1, t0, ctx->mem_idx);
8192 tcg_temp_free_i32(fp0);
a6035857 8193 tcg_temp_free(t1);
b6d96bed 8194 }
5a5012ec 8195 opn = "swxc1";
93b12ccc 8196 store = 1;
5a5012ec
TS
8197 break;
8198 case OPC_SDXC1:
8c0ab41f
AJ
8199 check_cop1x(ctx);
8200 check_cp1_registers(ctx, fs);
b6d96bed 8201 {
a7812ae4 8202 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
8203
8204 gen_load_fpr64(ctx, fp0, fs);
8205 tcg_gen_qemu_st64(fp0, t0, ctx->mem_idx);
a7812ae4 8206 tcg_temp_free_i64(fp0);
b6d96bed 8207 }
5a5012ec 8208 opn = "sdxc1";
93b12ccc 8209 store = 1;
5a5012ec
TS
8210 break;
8211 case OPC_SUXC1:
8c0ab41f 8212 check_cp1_64bitmode(ctx);
6c5c1e20 8213 tcg_gen_andi_tl(t0, t0, ~0x7);
b6d96bed 8214 {
a7812ae4 8215 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
8216
8217 gen_load_fpr64(ctx, fp0, fs);
8218 tcg_gen_qemu_st64(fp0, t0, ctx->mem_idx);
a7812ae4 8219 tcg_temp_free_i64(fp0);
b6d96bed 8220 }
5a5012ec 8221 opn = "suxc1";
93b12ccc 8222 store = 1;
5a5012ec 8223 break;
5a5012ec 8224 }
6c5c1e20 8225 tcg_temp_free(t0);
2abf314d 8226 (void)opn; (void)store; /* avoid compiler warnings */
93b12ccc
TS
8227 MIPS_DEBUG("%s %s, %s(%s)", opn, fregnames[store ? fs : fd],
8228 regnames[index], regnames[base]);
5a5012ec
TS
8229}
8230
5e755519
TS
8231static void gen_flt3_arith (DisasContext *ctx, uint32_t opc,
8232 int fd, int fr, int fs, int ft)
5a5012ec 8233{
923617a3 8234 const char *opn = "flt3_arith";
5a5012ec 8235
5a5012ec
TS
8236 switch (opc) {
8237 case OPC_ALNV_PS:
b8aa4598 8238 check_cp1_64bitmode(ctx);
a16336e4 8239 {
a7812ae4 8240 TCGv t0 = tcg_temp_local_new();
c905fdac
AJ
8241 TCGv_i32 fp = tcg_temp_new_i32();
8242 TCGv_i32 fph = tcg_temp_new_i32();
a16336e4
TS
8243 int l1 = gen_new_label();
8244 int l2 = gen_new_label();
8245
6c5c1e20
TS
8246 gen_load_gpr(t0, fr);
8247 tcg_gen_andi_tl(t0, t0, 0x7);
6c5c1e20
TS
8248
8249 tcg_gen_brcondi_tl(TCG_COND_NE, t0, 0, l1);
c905fdac
AJ
8250 gen_load_fpr32(fp, fs);
8251 gen_load_fpr32h(fph, fs);
8252 gen_store_fpr32(fp, fd);
8253 gen_store_fpr32h(fph, fd);
a16336e4
TS
8254 tcg_gen_br(l2);
8255 gen_set_label(l1);
6c5c1e20
TS
8256 tcg_gen_brcondi_tl(TCG_COND_NE, t0, 4, l2);
8257 tcg_temp_free(t0);
a16336e4 8258#ifdef TARGET_WORDS_BIGENDIAN
c905fdac
AJ
8259 gen_load_fpr32(fp, fs);
8260 gen_load_fpr32h(fph, ft);
8261 gen_store_fpr32h(fp, fd);
8262 gen_store_fpr32(fph, fd);
a16336e4 8263#else
c905fdac
AJ
8264 gen_load_fpr32h(fph, fs);
8265 gen_load_fpr32(fp, ft);
8266 gen_store_fpr32(fph, fd);
8267 gen_store_fpr32h(fp, fd);
a16336e4
TS
8268#endif
8269 gen_set_label(l2);
c905fdac
AJ
8270 tcg_temp_free_i32(fp);
8271 tcg_temp_free_i32(fph);
a16336e4 8272 }
5a5012ec
TS
8273 opn = "alnv.ps";
8274 break;
8275 case OPC_MADD_S:
b8aa4598 8276 check_cop1x(ctx);
b6d96bed 8277 {
a7812ae4
PB
8278 TCGv_i32 fp0 = tcg_temp_new_i32();
8279 TCGv_i32 fp1 = tcg_temp_new_i32();
8280 TCGv_i32 fp2 = tcg_temp_new_i32();
b6d96bed
TS
8281
8282 gen_load_fpr32(fp0, fs);
8283 gen_load_fpr32(fp1, ft);
8284 gen_load_fpr32(fp2, fr);
895c2d04 8285 gen_helper_float_muladd_s(fp2, cpu_env, fp0, fp1, fp2);
a7812ae4
PB
8286 tcg_temp_free_i32(fp0);
8287 tcg_temp_free_i32(fp1);
b6d96bed 8288 gen_store_fpr32(fp2, fd);
a7812ae4 8289 tcg_temp_free_i32(fp2);
b6d96bed 8290 }
5a5012ec
TS
8291 opn = "madd.s";
8292 break;
8293 case OPC_MADD_D:
b8aa4598
TS
8294 check_cop1x(ctx);
8295 check_cp1_registers(ctx, fd | fs | ft | fr);
b6d96bed 8296 {
a7812ae4
PB
8297 TCGv_i64 fp0 = tcg_temp_new_i64();
8298 TCGv_i64 fp1 = tcg_temp_new_i64();
8299 TCGv_i64 fp2 = tcg_temp_new_i64();
b6d96bed
TS
8300
8301 gen_load_fpr64(ctx, fp0, fs);
8302 gen_load_fpr64(ctx, fp1, ft);
8303 gen_load_fpr64(ctx, fp2, fr);
895c2d04 8304 gen_helper_float_muladd_d(fp2, cpu_env, fp0, fp1, fp2);
a7812ae4
PB
8305 tcg_temp_free_i64(fp0);
8306 tcg_temp_free_i64(fp1);
b6d96bed 8307 gen_store_fpr64(ctx, fp2, fd);
a7812ae4 8308 tcg_temp_free_i64(fp2);
b6d96bed 8309 }
5a5012ec
TS
8310 opn = "madd.d";
8311 break;
8312 case OPC_MADD_PS:
b8aa4598 8313 check_cp1_64bitmode(ctx);
b6d96bed 8314 {
a7812ae4
PB
8315 TCGv_i64 fp0 = tcg_temp_new_i64();
8316 TCGv_i64 fp1 = tcg_temp_new_i64();
8317 TCGv_i64 fp2 = tcg_temp_new_i64();
b6d96bed
TS
8318
8319 gen_load_fpr64(ctx, fp0, fs);
8320 gen_load_fpr64(ctx, fp1, ft);
8321 gen_load_fpr64(ctx, fp2, fr);
895c2d04 8322 gen_helper_float_muladd_ps(fp2, cpu_env, fp0, fp1, fp2);
a7812ae4
PB
8323 tcg_temp_free_i64(fp0);
8324 tcg_temp_free_i64(fp1);
b6d96bed 8325 gen_store_fpr64(ctx, fp2, fd);
a7812ae4 8326 tcg_temp_free_i64(fp2);
b6d96bed 8327 }
5a5012ec
TS
8328 opn = "madd.ps";
8329 break;
8330 case OPC_MSUB_S:
b8aa4598 8331 check_cop1x(ctx);
b6d96bed 8332 {
a7812ae4
PB
8333 TCGv_i32 fp0 = tcg_temp_new_i32();
8334 TCGv_i32 fp1 = tcg_temp_new_i32();
8335 TCGv_i32 fp2 = tcg_temp_new_i32();
b6d96bed
TS
8336
8337 gen_load_fpr32(fp0, fs);
8338 gen_load_fpr32(fp1, ft);
8339 gen_load_fpr32(fp2, fr);
895c2d04 8340 gen_helper_float_mulsub_s(fp2, cpu_env, fp0, fp1, fp2);
a7812ae4
PB
8341 tcg_temp_free_i32(fp0);
8342 tcg_temp_free_i32(fp1);
b6d96bed 8343 gen_store_fpr32(fp2, fd);
a7812ae4 8344 tcg_temp_free_i32(fp2);
b6d96bed 8345 }
5a5012ec
TS
8346 opn = "msub.s";
8347 break;
8348 case OPC_MSUB_D:
b8aa4598
TS
8349 check_cop1x(ctx);
8350 check_cp1_registers(ctx, fd | fs | ft | fr);
b6d96bed 8351 {
a7812ae4
PB
8352 TCGv_i64 fp0 = tcg_temp_new_i64();
8353 TCGv_i64 fp1 = tcg_temp_new_i64();
8354 TCGv_i64 fp2 = tcg_temp_new_i64();
b6d96bed
TS
8355
8356 gen_load_fpr64(ctx, fp0, fs);
8357 gen_load_fpr64(ctx, fp1, ft);
8358 gen_load_fpr64(ctx, fp2, fr);
895c2d04 8359 gen_helper_float_mulsub_d(fp2, cpu_env, fp0, fp1, fp2);
a7812ae4
PB
8360 tcg_temp_free_i64(fp0);
8361 tcg_temp_free_i64(fp1);
b6d96bed 8362 gen_store_fpr64(ctx, fp2, fd);
a7812ae4 8363 tcg_temp_free_i64(fp2);
b6d96bed 8364 }
5a5012ec
TS
8365 opn = "msub.d";
8366 break;
8367 case OPC_MSUB_PS:
b8aa4598 8368 check_cp1_64bitmode(ctx);
b6d96bed 8369 {
a7812ae4
PB
8370 TCGv_i64 fp0 = tcg_temp_new_i64();
8371 TCGv_i64 fp1 = tcg_temp_new_i64();
8372 TCGv_i64 fp2 = tcg_temp_new_i64();
b6d96bed
TS
8373
8374 gen_load_fpr64(ctx, fp0, fs);
8375 gen_load_fpr64(ctx, fp1, ft);
8376 gen_load_fpr64(ctx, fp2, fr);
895c2d04 8377 gen_helper_float_mulsub_ps(fp2, cpu_env, fp0, fp1, fp2);
a7812ae4
PB
8378 tcg_temp_free_i64(fp0);
8379 tcg_temp_free_i64(fp1);
b6d96bed 8380 gen_store_fpr64(ctx, fp2, fd);
a7812ae4 8381 tcg_temp_free_i64(fp2);
b6d96bed 8382 }
5a5012ec
TS
8383 opn = "msub.ps";
8384 break;
8385 case OPC_NMADD_S:
b8aa4598 8386 check_cop1x(ctx);
b6d96bed 8387 {
a7812ae4
PB
8388 TCGv_i32 fp0 = tcg_temp_new_i32();
8389 TCGv_i32 fp1 = tcg_temp_new_i32();
8390 TCGv_i32 fp2 = tcg_temp_new_i32();
b6d96bed
TS
8391
8392 gen_load_fpr32(fp0, fs);
8393 gen_load_fpr32(fp1, ft);
8394 gen_load_fpr32(fp2, fr);
895c2d04 8395 gen_helper_float_nmuladd_s(fp2, cpu_env, fp0, fp1, fp2);
a7812ae4
PB
8396 tcg_temp_free_i32(fp0);
8397 tcg_temp_free_i32(fp1);
b6d96bed 8398 gen_store_fpr32(fp2, fd);
a7812ae4 8399 tcg_temp_free_i32(fp2);
b6d96bed 8400 }
5a5012ec
TS
8401 opn = "nmadd.s";
8402 break;
8403 case OPC_NMADD_D:
b8aa4598
TS
8404 check_cop1x(ctx);
8405 check_cp1_registers(ctx, fd | fs | ft | fr);
b6d96bed 8406 {
a7812ae4
PB
8407 TCGv_i64 fp0 = tcg_temp_new_i64();
8408 TCGv_i64 fp1 = tcg_temp_new_i64();
8409 TCGv_i64 fp2 = tcg_temp_new_i64();
b6d96bed
TS
8410
8411 gen_load_fpr64(ctx, fp0, fs);
8412 gen_load_fpr64(ctx, fp1, ft);
8413 gen_load_fpr64(ctx, fp2, fr);
895c2d04 8414 gen_helper_float_nmuladd_d(fp2, cpu_env, fp0, fp1, fp2);
a7812ae4
PB
8415 tcg_temp_free_i64(fp0);
8416 tcg_temp_free_i64(fp1);
b6d96bed 8417 gen_store_fpr64(ctx, fp2, fd);
a7812ae4 8418 tcg_temp_free_i64(fp2);
b6d96bed 8419 }
5a5012ec
TS
8420 opn = "nmadd.d";
8421 break;
8422 case OPC_NMADD_PS:
b8aa4598 8423 check_cp1_64bitmode(ctx);
b6d96bed 8424 {
a7812ae4
PB
8425 TCGv_i64 fp0 = tcg_temp_new_i64();
8426 TCGv_i64 fp1 = tcg_temp_new_i64();
8427 TCGv_i64 fp2 = tcg_temp_new_i64();
b6d96bed
TS
8428
8429 gen_load_fpr64(ctx, fp0, fs);
8430 gen_load_fpr64(ctx, fp1, ft);
8431 gen_load_fpr64(ctx, fp2, fr);
895c2d04 8432 gen_helper_float_nmuladd_ps(fp2, cpu_env, fp0, fp1, fp2);
a7812ae4
PB
8433 tcg_temp_free_i64(fp0);
8434 tcg_temp_free_i64(fp1);
b6d96bed 8435 gen_store_fpr64(ctx, fp2, fd);
a7812ae4 8436 tcg_temp_free_i64(fp2);
b6d96bed 8437 }
5a5012ec
TS
8438 opn = "nmadd.ps";
8439 break;
8440 case OPC_NMSUB_S:
b8aa4598 8441 check_cop1x(ctx);
b6d96bed 8442 {
a7812ae4
PB
8443 TCGv_i32 fp0 = tcg_temp_new_i32();
8444 TCGv_i32 fp1 = tcg_temp_new_i32();
8445 TCGv_i32 fp2 = tcg_temp_new_i32();
b6d96bed
TS
8446
8447 gen_load_fpr32(fp0, fs);
8448 gen_load_fpr32(fp1, ft);
8449 gen_load_fpr32(fp2, fr);
895c2d04 8450 gen_helper_float_nmulsub_s(fp2, cpu_env, fp0, fp1, fp2);
a7812ae4
PB
8451 tcg_temp_free_i32(fp0);
8452 tcg_temp_free_i32(fp1);
b6d96bed 8453 gen_store_fpr32(fp2, fd);
a7812ae4 8454 tcg_temp_free_i32(fp2);
b6d96bed 8455 }
5a5012ec
TS
8456 opn = "nmsub.s";
8457 break;
8458 case OPC_NMSUB_D:
b8aa4598
TS
8459 check_cop1x(ctx);
8460 check_cp1_registers(ctx, fd | fs | ft | fr);
b6d96bed 8461 {
a7812ae4
PB
8462 TCGv_i64 fp0 = tcg_temp_new_i64();
8463 TCGv_i64 fp1 = tcg_temp_new_i64();
8464 TCGv_i64 fp2 = tcg_temp_new_i64();
b6d96bed
TS
8465
8466 gen_load_fpr64(ctx, fp0, fs);
8467 gen_load_fpr64(ctx, fp1, ft);
8468 gen_load_fpr64(ctx, fp2, fr);
895c2d04 8469 gen_helper_float_nmulsub_d(fp2, cpu_env, fp0, fp1, fp2);
a7812ae4
PB
8470 tcg_temp_free_i64(fp0);
8471 tcg_temp_free_i64(fp1);
b6d96bed 8472 gen_store_fpr64(ctx, fp2, fd);
a7812ae4 8473 tcg_temp_free_i64(fp2);
b6d96bed 8474 }
5a5012ec
TS
8475 opn = "nmsub.d";
8476 break;
8477 case OPC_NMSUB_PS:
b8aa4598 8478 check_cp1_64bitmode(ctx);
b6d96bed 8479 {
a7812ae4
PB
8480 TCGv_i64 fp0 = tcg_temp_new_i64();
8481 TCGv_i64 fp1 = tcg_temp_new_i64();
8482 TCGv_i64 fp2 = tcg_temp_new_i64();
b6d96bed
TS
8483
8484 gen_load_fpr64(ctx, fp0, fs);
8485 gen_load_fpr64(ctx, fp1, ft);
8486 gen_load_fpr64(ctx, fp2, fr);
895c2d04 8487 gen_helper_float_nmulsub_ps(fp2, cpu_env, fp0, fp1, fp2);
a7812ae4
PB
8488 tcg_temp_free_i64(fp0);
8489 tcg_temp_free_i64(fp1);
b6d96bed 8490 gen_store_fpr64(ctx, fp2, fd);
a7812ae4 8491 tcg_temp_free_i64(fp2);
b6d96bed 8492 }
5a5012ec
TS
8493 opn = "nmsub.ps";
8494 break;
923617a3
TS
8495 default:
8496 MIPS_INVAL(opn);
5a5012ec
TS
8497 generate_exception (ctx, EXCP_RI);
8498 return;
8499 }
2abf314d 8500 (void)opn; /* avoid a compiler warning */
5a5012ec
TS
8501 MIPS_DEBUG("%s %s, %s, %s, %s", opn, fregnames[fd], fregnames[fr],
8502 fregnames[fs], fregnames[ft]);
7a387fff
TS
8503}
8504
26ebe468 8505static void
7db13fae 8506gen_rdhwr (CPUMIPSState *env, DisasContext *ctx, int rt, int rd)
26ebe468
NF
8507{
8508 TCGv t0;
8509
b3167288
RH
8510#if !defined(CONFIG_USER_ONLY)
8511 /* The Linux kernel will emulate rdhwr if it's not supported natively.
8512 Therefore only check the ISA in system mode. */
26ebe468 8513 check_insn(env, ctx, ISA_MIPS32R2);
b3167288 8514#endif
26ebe468
NF
8515 t0 = tcg_temp_new();
8516
8517 switch (rd) {
8518 case 0:
8519 save_cpu_state(ctx, 1);
895c2d04 8520 gen_helper_rdhwr_cpunum(t0, cpu_env);
26ebe468
NF
8521 gen_store_gpr(t0, rt);
8522 break;
8523 case 1:
8524 save_cpu_state(ctx, 1);
895c2d04 8525 gen_helper_rdhwr_synci_step(t0, cpu_env);
26ebe468
NF
8526 gen_store_gpr(t0, rt);
8527 break;
8528 case 2:
8529 save_cpu_state(ctx, 1);
895c2d04 8530 gen_helper_rdhwr_cc(t0, cpu_env);
26ebe468
NF
8531 gen_store_gpr(t0, rt);
8532 break;
8533 case 3:
8534 save_cpu_state(ctx, 1);
895c2d04 8535 gen_helper_rdhwr_ccres(t0, cpu_env);
26ebe468
NF
8536 gen_store_gpr(t0, rt);
8537 break;
8538 case 29:
8539#if defined(CONFIG_USER_ONLY)
7db13fae 8540 tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUMIPSState, tls_value));
26ebe468
NF
8541 gen_store_gpr(t0, rt);
8542 break;
8543#else
8544 /* XXX: Some CPUs implement this in hardware.
8545 Not supported yet. */
8546#endif
8547 default: /* Invalid */
8548 MIPS_INVAL("rdhwr");
8549 generate_exception(ctx, EXCP_RI);
8550 break;
8551 }
8552 tcg_temp_free(t0);
8553}
8554
7db13fae 8555static void handle_delay_slot (CPUMIPSState *env, DisasContext *ctx,
c9602061
NF
8556 int insn_bytes)
8557{
8558 if (ctx->hflags & MIPS_HFLAG_BMASK) {
364d4831 8559 int proc_hflags = ctx->hflags & MIPS_HFLAG_BMASK;
c9602061
NF
8560 /* Branches completion */
8561 ctx->hflags &= ~MIPS_HFLAG_BMASK;
8562 ctx->bstate = BS_BRANCH;
8563 save_cpu_state(ctx, 0);
8564 /* FIXME: Need to clear can_do_io. */
364d4831 8565 switch (proc_hflags & MIPS_HFLAG_BMASK_BASE) {
c9602061
NF
8566 case MIPS_HFLAG_B:
8567 /* unconditional branch */
8568 MIPS_DEBUG("unconditional branch");
364d4831
NF
8569 if (proc_hflags & MIPS_HFLAG_BX) {
8570 tcg_gen_xori_i32(hflags, hflags, MIPS_HFLAG_M16);
8571 }
c9602061
NF
8572 gen_goto_tb(ctx, 0, ctx->btarget);
8573 break;
8574 case MIPS_HFLAG_BL:
8575 /* blikely taken case */
8576 MIPS_DEBUG("blikely branch taken");
8577 gen_goto_tb(ctx, 0, ctx->btarget);
8578 break;
8579 case MIPS_HFLAG_BC:
8580 /* Conditional branch */
8581 MIPS_DEBUG("conditional branch");
8582 {
8583 int l1 = gen_new_label();
8584
8585 tcg_gen_brcondi_tl(TCG_COND_NE, bcond, 0, l1);
8586 gen_goto_tb(ctx, 1, ctx->pc + insn_bytes);
8587 gen_set_label(l1);
8588 gen_goto_tb(ctx, 0, ctx->btarget);
8589 }
8590 break;
8591 case MIPS_HFLAG_BR:
8592 /* unconditional branch to register */
8593 MIPS_DEBUG("branch to register");
3c824109 8594 if (env->insn_flags & (ASE_MIPS16 | ASE_MICROMIPS)) {
364d4831
NF
8595 TCGv t0 = tcg_temp_new();
8596 TCGv_i32 t1 = tcg_temp_new_i32();
8597
8598 tcg_gen_andi_tl(t0, btarget, 0x1);
8599 tcg_gen_trunc_tl_i32(t1, t0);
8600 tcg_temp_free(t0);
8601 tcg_gen_andi_i32(hflags, hflags, ~(uint32_t)MIPS_HFLAG_M16);
8602 tcg_gen_shli_i32(t1, t1, MIPS_HFLAG_M16_SHIFT);
8603 tcg_gen_or_i32(hflags, hflags, t1);
8604 tcg_temp_free_i32(t1);
8605
8606 tcg_gen_andi_tl(cpu_PC, btarget, ~(target_ulong)0x1);
8607 } else {
8608 tcg_gen_mov_tl(cpu_PC, btarget);
8609 }
c9602061
NF
8610 if (ctx->singlestep_enabled) {
8611 save_cpu_state(ctx, 0);
895c2d04 8612 gen_helper_0e0i(raise_exception, EXCP_DEBUG);
c9602061
NF
8613 }
8614 tcg_gen_exit_tb(0);
8615 break;
8616 default:
8617 MIPS_DEBUG("unknown branch");
8618 break;
8619 }
8620 }
8621}
8622
7a387fff 8623/* ISA extensions (ASEs) */
6af0bf9c 8624/* MIPS16 extension to MIPS32 */
6ea219d0
NF
8625
8626/* MIPS16 major opcodes */
8627enum {
8628 M16_OPC_ADDIUSP = 0x00,
8629 M16_OPC_ADDIUPC = 0x01,
8630 M16_OPC_B = 0x02,
8631 M16_OPC_JAL = 0x03,
8632 M16_OPC_BEQZ = 0x04,
8633 M16_OPC_BNEQZ = 0x05,
8634 M16_OPC_SHIFT = 0x06,
8635 M16_OPC_LD = 0x07,
8636 M16_OPC_RRIA = 0x08,
8637 M16_OPC_ADDIU8 = 0x09,
8638 M16_OPC_SLTI = 0x0a,
8639 M16_OPC_SLTIU = 0x0b,
8640 M16_OPC_I8 = 0x0c,
8641 M16_OPC_LI = 0x0d,
8642 M16_OPC_CMPI = 0x0e,
8643 M16_OPC_SD = 0x0f,
8644 M16_OPC_LB = 0x10,
8645 M16_OPC_LH = 0x11,
8646 M16_OPC_LWSP = 0x12,
8647 M16_OPC_LW = 0x13,
8648 M16_OPC_LBU = 0x14,
8649 M16_OPC_LHU = 0x15,
8650 M16_OPC_LWPC = 0x16,
8651 M16_OPC_LWU = 0x17,
8652 M16_OPC_SB = 0x18,
8653 M16_OPC_SH = 0x19,
8654 M16_OPC_SWSP = 0x1a,
8655 M16_OPC_SW = 0x1b,
8656 M16_OPC_RRR = 0x1c,
8657 M16_OPC_RR = 0x1d,
8658 M16_OPC_EXTEND = 0x1e,
8659 M16_OPC_I64 = 0x1f
8660};
8661
8662/* I8 funct field */
8663enum {
8664 I8_BTEQZ = 0x0,
8665 I8_BTNEZ = 0x1,
8666 I8_SWRASP = 0x2,
8667 I8_ADJSP = 0x3,
8668 I8_SVRS = 0x4,
8669 I8_MOV32R = 0x5,
8670 I8_MOVR32 = 0x7
8671};
8672
8673/* RRR f field */
8674enum {
8675 RRR_DADDU = 0x0,
8676 RRR_ADDU = 0x1,
8677 RRR_DSUBU = 0x2,
8678 RRR_SUBU = 0x3
8679};
8680
8681/* RR funct field */
8682enum {
8683 RR_JR = 0x00,
8684 RR_SDBBP = 0x01,
8685 RR_SLT = 0x02,
8686 RR_SLTU = 0x03,
8687 RR_SLLV = 0x04,
8688 RR_BREAK = 0x05,
8689 RR_SRLV = 0x06,
8690 RR_SRAV = 0x07,
8691 RR_DSRL = 0x08,
8692 RR_CMP = 0x0a,
8693 RR_NEG = 0x0b,
8694 RR_AND = 0x0c,
8695 RR_OR = 0x0d,
8696 RR_XOR = 0x0e,
8697 RR_NOT = 0x0f,
8698 RR_MFHI = 0x10,
8699 RR_CNVT = 0x11,
8700 RR_MFLO = 0x12,
8701 RR_DSRA = 0x13,
8702 RR_DSLLV = 0x14,
8703 RR_DSRLV = 0x16,
8704 RR_DSRAV = 0x17,
8705 RR_MULT = 0x18,
8706 RR_MULTU = 0x19,
8707 RR_DIV = 0x1a,
8708 RR_DIVU = 0x1b,
8709 RR_DMULT = 0x1c,
8710 RR_DMULTU = 0x1d,
8711 RR_DDIV = 0x1e,
8712 RR_DDIVU = 0x1f
8713};
8714
8715/* I64 funct field */
8716enum {
8717 I64_LDSP = 0x0,
8718 I64_SDSP = 0x1,
8719 I64_SDRASP = 0x2,
8720 I64_DADJSP = 0x3,
8721 I64_LDPC = 0x4,
364d4831 8722 I64_DADDIU5 = 0x5,
6ea219d0
NF
8723 I64_DADDIUPC = 0x6,
8724 I64_DADDIUSP = 0x7
8725};
8726
8727/* RR ry field for CNVT */
8728enum {
8729 RR_RY_CNVT_ZEB = 0x0,
8730 RR_RY_CNVT_ZEH = 0x1,
8731 RR_RY_CNVT_ZEW = 0x2,
8732 RR_RY_CNVT_SEB = 0x4,
8733 RR_RY_CNVT_SEH = 0x5,
8734 RR_RY_CNVT_SEW = 0x6,
8735};
8736
364d4831
NF
8737static int xlat (int r)
8738{
8739 static int map[] = { 16, 17, 2, 3, 4, 5, 6, 7 };
8740
8741 return map[r];
8742}
8743
8744static void gen_mips16_save (DisasContext *ctx,
8745 int xsregs, int aregs,
8746 int do_ra, int do_s0, int do_s1,
8747 int framesize)
8748{
8749 TCGv t0 = tcg_temp_new();
8750 TCGv t1 = tcg_temp_new();
8751 int args, astatic;
8752
8753 switch (aregs) {
8754 case 0:
8755 case 1:
8756 case 2:
8757 case 3:
8758 case 11:
8759 args = 0;
8760 break;
8761 case 4:
8762 case 5:
8763 case 6:
8764 case 7:
8765 args = 1;
8766 break;
8767 case 8:
8768 case 9:
8769 case 10:
8770 args = 2;
8771 break;
8772 case 12:
8773 case 13:
8774 args = 3;
8775 break;
8776 case 14:
8777 args = 4;
8778 break;
8779 default:
8780 generate_exception(ctx, EXCP_RI);
8781 return;
8782 }
8783
8784 switch (args) {
8785 case 4:
8786 gen_base_offset_addr(ctx, t0, 29, 12);
8787 gen_load_gpr(t1, 7);
5c13fdfd 8788 op_st_sw(t1, t0, ctx);
364d4831
NF
8789 /* Fall through */
8790 case 3:
8791 gen_base_offset_addr(ctx, t0, 29, 8);
8792 gen_load_gpr(t1, 6);
5c13fdfd 8793 op_st_sw(t1, t0, ctx);
364d4831
NF
8794 /* Fall through */
8795 case 2:
8796 gen_base_offset_addr(ctx, t0, 29, 4);
8797 gen_load_gpr(t1, 5);
5c13fdfd 8798 op_st_sw(t1, t0, ctx);
364d4831
NF
8799 /* Fall through */
8800 case 1:
8801 gen_base_offset_addr(ctx, t0, 29, 0);
8802 gen_load_gpr(t1, 4);
5c13fdfd 8803 op_st_sw(t1, t0, ctx);
364d4831
NF
8804 }
8805
8806 gen_load_gpr(t0, 29);
8807
8808#define DECR_AND_STORE(reg) do { \
8809 tcg_gen_subi_tl(t0, t0, 4); \
8810 gen_load_gpr(t1, reg); \
5c13fdfd 8811 op_st_sw(t1, t0, ctx); \
364d4831
NF
8812 } while (0)
8813
8814 if (do_ra) {
8815 DECR_AND_STORE(31);
8816 }
8817
8818 switch (xsregs) {
8819 case 7:
8820 DECR_AND_STORE(30);
8821 /* Fall through */
8822 case 6:
8823 DECR_AND_STORE(23);
8824 /* Fall through */
8825 case 5:
8826 DECR_AND_STORE(22);
8827 /* Fall through */
8828 case 4:
8829 DECR_AND_STORE(21);
8830 /* Fall through */
8831 case 3:
8832 DECR_AND_STORE(20);
8833 /* Fall through */
8834 case 2:
8835 DECR_AND_STORE(19);
8836 /* Fall through */
8837 case 1:
8838 DECR_AND_STORE(18);
8839 }
8840
8841 if (do_s1) {
8842 DECR_AND_STORE(17);
8843 }
8844 if (do_s0) {
8845 DECR_AND_STORE(16);
8846 }
8847
8848 switch (aregs) {
8849 case 0:
8850 case 4:
8851 case 8:
8852 case 12:
8853 case 14:
8854 astatic = 0;
8855 break;
8856 case 1:
8857 case 5:
8858 case 9:
8859 case 13:
8860 astatic = 1;
8861 break;
8862 case 2:
8863 case 6:
8864 case 10:
8865 astatic = 2;
8866 break;
8867 case 3:
8868 case 7:
8869 astatic = 3;
8870 break;
8871 case 11:
8872 astatic = 4;
8873 break;
8874 default:
8875 generate_exception(ctx, EXCP_RI);
8876 return;
8877 }
8878
8879 if (astatic > 0) {
8880 DECR_AND_STORE(7);
8881 if (astatic > 1) {
8882 DECR_AND_STORE(6);
8883 if (astatic > 2) {
8884 DECR_AND_STORE(5);
8885 if (astatic > 3) {
8886 DECR_AND_STORE(4);
8887 }
8888 }
8889 }
8890 }
8891#undef DECR_AND_STORE
8892
8893 tcg_gen_subi_tl(cpu_gpr[29], cpu_gpr[29], framesize);
8894 tcg_temp_free(t0);
8895 tcg_temp_free(t1);
8896}
8897
8898static void gen_mips16_restore (DisasContext *ctx,
8899 int xsregs, int aregs,
8900 int do_ra, int do_s0, int do_s1,
8901 int framesize)
8902{
8903 int astatic;
8904 TCGv t0 = tcg_temp_new();
8905 TCGv t1 = tcg_temp_new();
8906
8907 tcg_gen_addi_tl(t0, cpu_gpr[29], framesize);
8908
8909#define DECR_AND_LOAD(reg) do { \
8910 tcg_gen_subi_tl(t0, t0, 4); \
5c13fdfd 8911 op_ld_lw(t1, t0, ctx); \
364d4831
NF
8912 gen_store_gpr(t1, reg); \
8913 } while (0)
8914
8915 if (do_ra) {
8916 DECR_AND_LOAD(31);
8917 }
8918
8919 switch (xsregs) {
8920 case 7:
8921 DECR_AND_LOAD(30);
8922 /* Fall through */
8923 case 6:
8924 DECR_AND_LOAD(23);
8925 /* Fall through */
8926 case 5:
8927 DECR_AND_LOAD(22);
8928 /* Fall through */
8929 case 4:
8930 DECR_AND_LOAD(21);
8931 /* Fall through */
8932 case 3:
8933 DECR_AND_LOAD(20);
8934 /* Fall through */
8935 case 2:
8936 DECR_AND_LOAD(19);
8937 /* Fall through */
8938 case 1:
8939 DECR_AND_LOAD(18);
8940 }
8941
8942 if (do_s1) {
8943 DECR_AND_LOAD(17);
8944 }
8945 if (do_s0) {
8946 DECR_AND_LOAD(16);
8947 }
8948
8949 switch (aregs) {
8950 case 0:
8951 case 4:
8952 case 8:
8953 case 12:
8954 case 14:
8955 astatic = 0;
8956 break;
8957 case 1:
8958 case 5:
8959 case 9:
8960 case 13:
8961 astatic = 1;
8962 break;
8963 case 2:
8964 case 6:
8965 case 10:
8966 astatic = 2;
8967 break;
8968 case 3:
8969 case 7:
8970 astatic = 3;
8971 break;
8972 case 11:
8973 astatic = 4;
8974 break;
8975 default:
8976 generate_exception(ctx, EXCP_RI);
8977 return;
8978 }
8979
8980 if (astatic > 0) {
8981 DECR_AND_LOAD(7);
8982 if (astatic > 1) {
8983 DECR_AND_LOAD(6);
8984 if (astatic > 2) {
8985 DECR_AND_LOAD(5);
8986 if (astatic > 3) {
8987 DECR_AND_LOAD(4);
8988 }
8989 }
8990 }
8991 }
8992#undef DECR_AND_LOAD
8993
8994 tcg_gen_addi_tl(cpu_gpr[29], cpu_gpr[29], framesize);
8995 tcg_temp_free(t0);
8996 tcg_temp_free(t1);
8997}
8998
8999static void gen_addiupc (DisasContext *ctx, int rx, int imm,
9000 int is_64_bit, int extended)
9001{
9002 TCGv t0;
9003
9004 if (extended && (ctx->hflags & MIPS_HFLAG_BMASK)) {
9005 generate_exception(ctx, EXCP_RI);
9006 return;
9007 }
9008
9009 t0 = tcg_temp_new();
9010
9011 tcg_gen_movi_tl(t0, pc_relative_pc(ctx));
9012 tcg_gen_addi_tl(cpu_gpr[rx], t0, imm);
9013 if (!is_64_bit) {
9014 tcg_gen_ext32s_tl(cpu_gpr[rx], cpu_gpr[rx]);
9015 }
9016
9017 tcg_temp_free(t0);
9018}
9019
9020#if defined(TARGET_MIPS64)
7db13fae 9021static void decode_i64_mips16 (CPUMIPSState *env, DisasContext *ctx,
364d4831
NF
9022 int ry, int funct, int16_t offset,
9023 int extended)
9024{
9025 switch (funct) {
9026 case I64_LDSP:
9027 check_mips_64(ctx);
9028 offset = extended ? offset : offset << 3;
afa88c3a 9029 gen_ld(env, ctx, OPC_LD, ry, 29, offset);
364d4831
NF
9030 break;
9031 case I64_SDSP:
9032 check_mips_64(ctx);
9033 offset = extended ? offset : offset << 3;
5c13fdfd 9034 gen_st(ctx, OPC_SD, ry, 29, offset);
364d4831
NF
9035 break;
9036 case I64_SDRASP:
9037 check_mips_64(ctx);
9038 offset = extended ? offset : (ctx->opcode & 0xff) << 3;
5c13fdfd 9039 gen_st(ctx, OPC_SD, 31, 29, offset);
364d4831
NF
9040 break;
9041 case I64_DADJSP:
9042 check_mips_64(ctx);
9043 offset = extended ? offset : ((int8_t)ctx->opcode) << 3;
9044 gen_arith_imm(env, ctx, OPC_DADDIU, 29, 29, offset);
9045 break;
9046 case I64_LDPC:
9047 if (extended && (ctx->hflags & MIPS_HFLAG_BMASK)) {
9048 generate_exception(ctx, EXCP_RI);
9049 } else {
9050 offset = extended ? offset : offset << 3;
afa88c3a 9051 gen_ld(env, ctx, OPC_LDPC, ry, 0, offset);
364d4831
NF
9052 }
9053 break;
9054 case I64_DADDIU5:
9055 check_mips_64(ctx);
9056 offset = extended ? offset : ((int8_t)(offset << 3)) >> 3;
9057 gen_arith_imm(env, ctx, OPC_DADDIU, ry, ry, offset);
9058 break;
9059 case I64_DADDIUPC:
9060 check_mips_64(ctx);
9061 offset = extended ? offset : offset << 2;
9062 gen_addiupc(ctx, ry, offset, 1, extended);
9063 break;
9064 case I64_DADDIUSP:
9065 check_mips_64(ctx);
9066 offset = extended ? offset : offset << 2;
9067 gen_arith_imm(env, ctx, OPC_DADDIU, ry, 29, offset);
9068 break;
9069 }
9070}
9071#endif
9072
7db13fae 9073static int decode_extended_mips16_opc (CPUMIPSState *env, DisasContext *ctx,
364d4831
NF
9074 int *is_branch)
9075{
895c2d04 9076 int extend = cpu_lduw_code(env, ctx->pc + 2);
364d4831
NF
9077 int op, rx, ry, funct, sa;
9078 int16_t imm, offset;
9079
9080 ctx->opcode = (ctx->opcode << 16) | extend;
9081 op = (ctx->opcode >> 11) & 0x1f;
9082 sa = (ctx->opcode >> 22) & 0x1f;
9083 funct = (ctx->opcode >> 8) & 0x7;
9084 rx = xlat((ctx->opcode >> 8) & 0x7);
9085 ry = xlat((ctx->opcode >> 5) & 0x7);
9086 offset = imm = (int16_t) (((ctx->opcode >> 16) & 0x1f) << 11
9087 | ((ctx->opcode >> 21) & 0x3f) << 5
9088 | (ctx->opcode & 0x1f));
9089
9090 /* The extended opcodes cleverly reuse the opcodes from their 16-bit
9091 counterparts. */
9092 switch (op) {
9093 case M16_OPC_ADDIUSP:
9094 gen_arith_imm(env, ctx, OPC_ADDIU, rx, 29, imm);
9095 break;
9096 case M16_OPC_ADDIUPC:
9097 gen_addiupc(ctx, rx, imm, 0, 1);
9098 break;
9099 case M16_OPC_B:
9100 gen_compute_branch(ctx, OPC_BEQ, 4, 0, 0, offset << 1);
9101 /* No delay slot, so just process as a normal instruction */
9102 break;
9103 case M16_OPC_BEQZ:
9104 gen_compute_branch(ctx, OPC_BEQ, 4, rx, 0, offset << 1);
9105 /* No delay slot, so just process as a normal instruction */
9106 break;
9107 case M16_OPC_BNEQZ:
9108 gen_compute_branch(ctx, OPC_BNE, 4, rx, 0, offset << 1);
9109 /* No delay slot, so just process as a normal instruction */
9110 break;
9111 case M16_OPC_SHIFT:
9112 switch (ctx->opcode & 0x3) {
9113 case 0x0:
9114 gen_shift_imm(env, ctx, OPC_SLL, rx, ry, sa);
9115 break;
9116 case 0x1:
9117#if defined(TARGET_MIPS64)
9118 check_mips_64(ctx);
9119 gen_shift_imm(env, ctx, OPC_DSLL, rx, ry, sa);
9120#else
9121 generate_exception(ctx, EXCP_RI);
9122#endif
9123 break;
9124 case 0x2:
9125 gen_shift_imm(env, ctx, OPC_SRL, rx, ry, sa);
9126 break;
9127 case 0x3:
9128 gen_shift_imm(env, ctx, OPC_SRA, rx, ry, sa);
9129 break;
9130 }
9131 break;
9132#if defined(TARGET_MIPS64)
9133 case M16_OPC_LD:
9134 check_mips_64(ctx);
afa88c3a 9135 gen_ld(env, ctx, OPC_LD, ry, rx, offset);
364d4831
NF
9136 break;
9137#endif
9138 case M16_OPC_RRIA:
9139 imm = ctx->opcode & 0xf;
9140 imm = imm | ((ctx->opcode >> 20) & 0x7f) << 4;
9141 imm = imm | ((ctx->opcode >> 16) & 0xf) << 11;
9142 imm = (int16_t) (imm << 1) >> 1;
9143 if ((ctx->opcode >> 4) & 0x1) {
9144#if defined(TARGET_MIPS64)
9145 check_mips_64(ctx);
9146 gen_arith_imm(env, ctx, OPC_DADDIU, ry, rx, imm);
9147#else
9148 generate_exception(ctx, EXCP_RI);
9149#endif
9150 } else {
9151 gen_arith_imm(env, ctx, OPC_ADDIU, ry, rx, imm);
9152 }
9153 break;
9154 case M16_OPC_ADDIU8:
9155 gen_arith_imm(env, ctx, OPC_ADDIU, rx, rx, imm);
9156 break;
9157 case M16_OPC_SLTI:
9fa77488 9158 gen_slt_imm(env, ctx, OPC_SLTI, 24, rx, imm);
364d4831
NF
9159 break;
9160 case M16_OPC_SLTIU:
9fa77488 9161 gen_slt_imm(env, ctx, OPC_SLTIU, 24, rx, imm);
364d4831
NF
9162 break;
9163 case M16_OPC_I8:
9164 switch (funct) {
9165 case I8_BTEQZ:
9166 gen_compute_branch(ctx, OPC_BEQ, 4, 24, 0, offset << 1);
9167 break;
9168 case I8_BTNEZ:
9169 gen_compute_branch(ctx, OPC_BNE, 4, 24, 0, offset << 1);
9170 break;
9171 case I8_SWRASP:
5c13fdfd 9172 gen_st(ctx, OPC_SW, 31, 29, imm);
364d4831
NF
9173 break;
9174 case I8_ADJSP:
9175 gen_arith_imm(env, ctx, OPC_ADDIU, 29, 29, imm);
9176 break;
9177 case I8_SVRS:
9178 {
9179 int xsregs = (ctx->opcode >> 24) & 0x7;
9180 int aregs = (ctx->opcode >> 16) & 0xf;
9181 int do_ra = (ctx->opcode >> 6) & 0x1;
9182 int do_s0 = (ctx->opcode >> 5) & 0x1;
9183 int do_s1 = (ctx->opcode >> 4) & 0x1;
9184 int framesize = (((ctx->opcode >> 20) & 0xf) << 4
9185 | (ctx->opcode & 0xf)) << 3;
9186
9187 if (ctx->opcode & (1 << 7)) {
9188 gen_mips16_save(ctx, xsregs, aregs,
9189 do_ra, do_s0, do_s1,
9190 framesize);
9191 } else {
9192 gen_mips16_restore(ctx, xsregs, aregs,
9193 do_ra, do_s0, do_s1,
9194 framesize);
9195 }
9196 }
9197 break;
9198 default:
9199 generate_exception(ctx, EXCP_RI);
9200 break;
9201 }
9202 break;
9203 case M16_OPC_LI:
9204 tcg_gen_movi_tl(cpu_gpr[rx], (uint16_t) imm);
9205 break;
9206 case M16_OPC_CMPI:
9207 tcg_gen_xori_tl(cpu_gpr[24], cpu_gpr[rx], (uint16_t) imm);
9208 break;
9209#if defined(TARGET_MIPS64)
9210 case M16_OPC_SD:
5c13fdfd 9211 gen_st(ctx, OPC_SD, ry, rx, offset);
364d4831
NF
9212 break;
9213#endif
9214 case M16_OPC_LB:
afa88c3a 9215 gen_ld(env, ctx, OPC_LB, ry, rx, offset);
364d4831
NF
9216 break;
9217 case M16_OPC_LH:
afa88c3a 9218 gen_ld(env, ctx, OPC_LH, ry, rx, offset);
364d4831
NF
9219 break;
9220 case M16_OPC_LWSP:
afa88c3a 9221 gen_ld(env, ctx, OPC_LW, rx, 29, offset);
364d4831
NF
9222 break;
9223 case M16_OPC_LW:
afa88c3a 9224 gen_ld(env, ctx, OPC_LW, ry, rx, offset);
364d4831
NF
9225 break;
9226 case M16_OPC_LBU:
afa88c3a 9227 gen_ld(env, ctx, OPC_LBU, ry, rx, offset);
364d4831
NF
9228 break;
9229 case M16_OPC_LHU:
afa88c3a 9230 gen_ld(env, ctx, OPC_LHU, ry, rx, offset);
364d4831
NF
9231 break;
9232 case M16_OPC_LWPC:
afa88c3a 9233 gen_ld(env, ctx, OPC_LWPC, rx, 0, offset);
364d4831
NF
9234 break;
9235#if defined(TARGET_MIPS64)
9236 case M16_OPC_LWU:
afa88c3a 9237 gen_ld(env, ctx, OPC_LWU, ry, rx, offset);
364d4831
NF
9238 break;
9239#endif
9240 case M16_OPC_SB:
5c13fdfd 9241 gen_st(ctx, OPC_SB, ry, rx, offset);
364d4831
NF
9242 break;
9243 case M16_OPC_SH:
5c13fdfd 9244 gen_st(ctx, OPC_SH, ry, rx, offset);
364d4831
NF
9245 break;
9246 case M16_OPC_SWSP:
5c13fdfd 9247 gen_st(ctx, OPC_SW, rx, 29, offset);
364d4831
NF
9248 break;
9249 case M16_OPC_SW:
5c13fdfd 9250 gen_st(ctx, OPC_SW, ry, rx, offset);
364d4831
NF
9251 break;
9252#if defined(TARGET_MIPS64)
9253 case M16_OPC_I64:
9254 decode_i64_mips16(env, ctx, ry, funct, offset, 1);
9255 break;
9256#endif
9257 default:
9258 generate_exception(ctx, EXCP_RI);
9259 break;
9260 }
9261
9262 return 4;
9263}
9264
7db13fae 9265static int decode_mips16_opc (CPUMIPSState *env, DisasContext *ctx,
364d4831
NF
9266 int *is_branch)
9267{
9268 int rx, ry;
9269 int sa;
9270 int op, cnvt_op, op1, offset;
9271 int funct;
9272 int n_bytes;
9273
9274 op = (ctx->opcode >> 11) & 0x1f;
9275 sa = (ctx->opcode >> 2) & 0x7;
9276 sa = sa == 0 ? 8 : sa;
9277 rx = xlat((ctx->opcode >> 8) & 0x7);
9278 cnvt_op = (ctx->opcode >> 5) & 0x7;
9279 ry = xlat((ctx->opcode >> 5) & 0x7);
9280 op1 = offset = ctx->opcode & 0x1f;
9281
9282 n_bytes = 2;
9283
9284 switch (op) {
9285 case M16_OPC_ADDIUSP:
9286 {
9287 int16_t imm = ((uint8_t) ctx->opcode) << 2;
9288
9289 gen_arith_imm(env, ctx, OPC_ADDIU, rx, 29, imm);
9290 }
9291 break;
9292 case M16_OPC_ADDIUPC:
9293 gen_addiupc(ctx, rx, ((uint8_t) ctx->opcode) << 2, 0, 0);
9294 break;
9295 case M16_OPC_B:
9296 offset = (ctx->opcode & 0x7ff) << 1;
9297 offset = (int16_t)(offset << 4) >> 4;
9298 gen_compute_branch(ctx, OPC_BEQ, 2, 0, 0, offset);
9299 /* No delay slot, so just process as a normal instruction */
9300 break;
9301 case M16_OPC_JAL:
895c2d04 9302 offset = cpu_lduw_code(env, ctx->pc + 2);
364d4831
NF
9303 offset = (((ctx->opcode & 0x1f) << 21)
9304 | ((ctx->opcode >> 5) & 0x1f) << 16
9305 | offset) << 2;
620e48f6 9306 op = ((ctx->opcode >> 10) & 0x1) ? OPC_JALXS : OPC_JALS;
364d4831
NF
9307 gen_compute_branch(ctx, op, 4, rx, ry, offset);
9308 n_bytes = 4;
9309 *is_branch = 1;
9310 break;
9311 case M16_OPC_BEQZ:
9312 gen_compute_branch(ctx, OPC_BEQ, 2, rx, 0, ((int8_t)ctx->opcode) << 1);
9313 /* No delay slot, so just process as a normal instruction */
9314 break;
9315 case M16_OPC_BNEQZ:
9316 gen_compute_branch(ctx, OPC_BNE, 2, rx, 0, ((int8_t)ctx->opcode) << 1);
9317 /* No delay slot, so just process as a normal instruction */
9318 break;
9319 case M16_OPC_SHIFT:
9320 switch (ctx->opcode & 0x3) {
9321 case 0x0:
9322 gen_shift_imm(env, ctx, OPC_SLL, rx, ry, sa);
9323 break;
9324 case 0x1:
9325#if defined(TARGET_MIPS64)
9326 check_mips_64(ctx);
9327 gen_shift_imm(env, ctx, OPC_DSLL, rx, ry, sa);
9328#else
9329 generate_exception(ctx, EXCP_RI);
9330#endif
9331 break;
9332 case 0x2:
9333 gen_shift_imm(env, ctx, OPC_SRL, rx, ry, sa);
9334 break;
9335 case 0x3:
9336 gen_shift_imm(env, ctx, OPC_SRA, rx, ry, sa);
9337 break;
9338 }
9339 break;
9340#if defined(TARGET_MIPS64)
9341 case M16_OPC_LD:
9342 check_mips_64(ctx);
afa88c3a 9343 gen_ld(env, ctx, OPC_LD, ry, rx, offset << 3);
364d4831
NF
9344 break;
9345#endif
9346 case M16_OPC_RRIA:
9347 {
9348 int16_t imm = (int8_t)((ctx->opcode & 0xf) << 4) >> 4;
9349
9350 if ((ctx->opcode >> 4) & 1) {
9351#if defined(TARGET_MIPS64)
9352 check_mips_64(ctx);
9353 gen_arith_imm(env, ctx, OPC_DADDIU, ry, rx, imm);
9354#else
9355 generate_exception(ctx, EXCP_RI);
9356#endif
9357 } else {
9358 gen_arith_imm(env, ctx, OPC_ADDIU, ry, rx, imm);
9359 }
9360 }
9361 break;
9362 case M16_OPC_ADDIU8:
9363 {
9364 int16_t imm = (int8_t) ctx->opcode;
9365
9366 gen_arith_imm(env, ctx, OPC_ADDIU, rx, rx, imm);
9367 }
9368 break;
9369 case M16_OPC_SLTI:
9370 {
9371 int16_t imm = (uint8_t) ctx->opcode;
9fa77488 9372 gen_slt_imm(env, ctx, OPC_SLTI, 24, rx, imm);
364d4831
NF
9373 }
9374 break;
9375 case M16_OPC_SLTIU:
9376 {
9377 int16_t imm = (uint8_t) ctx->opcode;
9fa77488 9378 gen_slt_imm(env, ctx, OPC_SLTIU, 24, rx, imm);
364d4831
NF
9379 }
9380 break;
9381 case M16_OPC_I8:
9382 {
9383 int reg32;
9384
9385 funct = (ctx->opcode >> 8) & 0x7;
9386 switch (funct) {
9387 case I8_BTEQZ:
9388 gen_compute_branch(ctx, OPC_BEQ, 2, 24, 0,
9389 ((int8_t)ctx->opcode) << 1);
9390 break;
9391 case I8_BTNEZ:
9392 gen_compute_branch(ctx, OPC_BNE, 2, 24, 0,
9393 ((int8_t)ctx->opcode) << 1);
9394 break;
9395 case I8_SWRASP:
5c13fdfd 9396 gen_st(ctx, OPC_SW, 31, 29, (ctx->opcode & 0xff) << 2);
364d4831
NF
9397 break;
9398 case I8_ADJSP:
9399 gen_arith_imm(env, ctx, OPC_ADDIU, 29, 29,
9400 ((int8_t)ctx->opcode) << 3);
9401 break;
9402 case I8_SVRS:
9403 {
9404 int do_ra = ctx->opcode & (1 << 6);
9405 int do_s0 = ctx->opcode & (1 << 5);
9406 int do_s1 = ctx->opcode & (1 << 4);
9407 int framesize = ctx->opcode & 0xf;
9408
9409 if (framesize == 0) {
9410 framesize = 128;
9411 } else {
9412 framesize = framesize << 3;
9413 }
9414
9415 if (ctx->opcode & (1 << 7)) {
9416 gen_mips16_save(ctx, 0, 0,
9417 do_ra, do_s0, do_s1, framesize);
9418 } else {
9419 gen_mips16_restore(ctx, 0, 0,
9420 do_ra, do_s0, do_s1, framesize);
9421 }
9422 }
9423 break;
9424 case I8_MOV32R:
9425 {
9426 int rz = xlat(ctx->opcode & 0x7);
9427
9428 reg32 = (((ctx->opcode >> 3) & 0x3) << 3) |
9429 ((ctx->opcode >> 5) & 0x7);
9430 gen_arith(env, ctx, OPC_ADDU, reg32, rz, 0);
9431 }
9432 break;
9433 case I8_MOVR32:
9434 reg32 = ctx->opcode & 0x1f;
9435 gen_arith(env, ctx, OPC_ADDU, ry, reg32, 0);
9436 break;
9437 default:
9438 generate_exception(ctx, EXCP_RI);
9439 break;
9440 }
9441 }
9442 break;
9443 case M16_OPC_LI:
9444 {
9445 int16_t imm = (uint8_t) ctx->opcode;
9446
9447 gen_arith_imm(env, ctx, OPC_ADDIU, rx, 0, imm);
9448 }
9449 break;
9450 case M16_OPC_CMPI:
9451 {
9452 int16_t imm = (uint8_t) ctx->opcode;
9fa77488 9453 gen_logic_imm(env, ctx, OPC_XORI, 24, rx, imm);
364d4831
NF
9454 }
9455 break;
9456#if defined(TARGET_MIPS64)
9457 case M16_OPC_SD:
9458 check_mips_64(ctx);
5c13fdfd 9459 gen_st(ctx, OPC_SD, ry, rx, offset << 3);
364d4831
NF
9460 break;
9461#endif
9462 case M16_OPC_LB:
afa88c3a 9463 gen_ld(env, ctx, OPC_LB, ry, rx, offset);
364d4831
NF
9464 break;
9465 case M16_OPC_LH:
afa88c3a 9466 gen_ld(env, ctx, OPC_LH, ry, rx, offset << 1);
364d4831
NF
9467 break;
9468 case M16_OPC_LWSP:
afa88c3a 9469 gen_ld(env, ctx, OPC_LW, rx, 29, ((uint8_t)ctx->opcode) << 2);
364d4831
NF
9470 break;
9471 case M16_OPC_LW:
afa88c3a 9472 gen_ld(env, ctx, OPC_LW, ry, rx, offset << 2);
364d4831
NF
9473 break;
9474 case M16_OPC_LBU:
afa88c3a 9475 gen_ld(env, ctx, OPC_LBU, ry, rx, offset);
364d4831
NF
9476 break;
9477 case M16_OPC_LHU:
afa88c3a 9478 gen_ld(env, ctx, OPC_LHU, ry, rx, offset << 1);
364d4831
NF
9479 break;
9480 case M16_OPC_LWPC:
afa88c3a 9481 gen_ld(env, ctx, OPC_LWPC, rx, 0, ((uint8_t)ctx->opcode) << 2);
364d4831
NF
9482 break;
9483#if defined (TARGET_MIPS64)
9484 case M16_OPC_LWU:
9485 check_mips_64(ctx);
afa88c3a 9486 gen_ld(env, ctx, OPC_LWU, ry, rx, offset << 2);
364d4831
NF
9487 break;
9488#endif
9489 case M16_OPC_SB:
5c13fdfd 9490 gen_st(ctx, OPC_SB, ry, rx, offset);
364d4831
NF
9491 break;
9492 case M16_OPC_SH:
5c13fdfd 9493 gen_st(ctx, OPC_SH, ry, rx, offset << 1);
364d4831
NF
9494 break;
9495 case M16_OPC_SWSP:
5c13fdfd 9496 gen_st(ctx, OPC_SW, rx, 29, ((uint8_t)ctx->opcode) << 2);
364d4831
NF
9497 break;
9498 case M16_OPC_SW:
5c13fdfd 9499 gen_st(ctx, OPC_SW, ry, rx, offset << 2);
364d4831
NF
9500 break;
9501 case M16_OPC_RRR:
9502 {
9503 int rz = xlat((ctx->opcode >> 2) & 0x7);
9504 int mips32_op;
9505
9506 switch (ctx->opcode & 0x3) {
9507 case RRR_ADDU:
9508 mips32_op = OPC_ADDU;
9509 break;
9510 case RRR_SUBU:
9511 mips32_op = OPC_SUBU;
9512 break;
9513#if defined(TARGET_MIPS64)
9514 case RRR_DADDU:
9515 mips32_op = OPC_DADDU;
9516 check_mips_64(ctx);
9517 break;
9518 case RRR_DSUBU:
9519 mips32_op = OPC_DSUBU;
9520 check_mips_64(ctx);
9521 break;
9522#endif
9523 default:
9524 generate_exception(ctx, EXCP_RI);
9525 goto done;
9526 }
9527
9528 gen_arith(env, ctx, mips32_op, rz, rx, ry);
9529 done:
9530 ;
9531 }
9532 break;
9533 case M16_OPC_RR:
9534 switch (op1) {
9535 case RR_JR:
9536 {
9537 int nd = (ctx->opcode >> 7) & 0x1;
9538 int link = (ctx->opcode >> 6) & 0x1;
9539 int ra = (ctx->opcode >> 5) & 0x1;
9540
9541 if (link) {
620e48f6 9542 op = nd ? OPC_JALRC : OPC_JALRS;
364d4831
NF
9543 } else {
9544 op = OPC_JR;
9545 }
9546
9547 gen_compute_branch(ctx, op, 2, ra ? 31 : rx, 31, 0);
9548 if (!nd) {
9549 *is_branch = 1;
9550 }
9551 }
9552 break;
9553 case RR_SDBBP:
9554 /* XXX: not clear which exception should be raised
9555 * when in debug mode...
9556 */
9557 check_insn(env, ctx, ISA_MIPS32);
9558 if (!(ctx->hflags & MIPS_HFLAG_DM)) {
9559 generate_exception(ctx, EXCP_DBp);
9560 } else {
9561 generate_exception(ctx, EXCP_DBp);
9562 }
9563 break;
9564 case RR_SLT:
9fa77488 9565 gen_slt(env, ctx, OPC_SLT, 24, rx, ry);
364d4831
NF
9566 break;
9567 case RR_SLTU:
9fa77488 9568 gen_slt(env, ctx, OPC_SLTU, 24, rx, ry);
364d4831
NF
9569 break;
9570 case RR_BREAK:
9571 generate_exception(ctx, EXCP_BREAK);
9572 break;
9573 case RR_SLLV:
9574 gen_shift(env, ctx, OPC_SLLV, ry, rx, ry);
9575 break;
9576 case RR_SRLV:
9577 gen_shift(env, ctx, OPC_SRLV, ry, rx, ry);
9578 break;
9579 case RR_SRAV:
9580 gen_shift(env, ctx, OPC_SRAV, ry, rx, ry);
9581 break;
9582#if defined (TARGET_MIPS64)
9583 case RR_DSRL:
9584 check_mips_64(ctx);
9585 gen_shift_imm(env, ctx, OPC_DSRL, ry, ry, sa);
9586 break;
9587#endif
9588 case RR_CMP:
9fa77488 9589 gen_logic(env, ctx, OPC_XOR, 24, rx, ry);
364d4831
NF
9590 break;
9591 case RR_NEG:
9592 gen_arith(env, ctx, OPC_SUBU, rx, 0, ry);
9593 break;
9594 case RR_AND:
9fa77488 9595 gen_logic(env, ctx, OPC_AND, rx, rx, ry);
364d4831
NF
9596 break;
9597 case RR_OR:
9fa77488 9598 gen_logic(env, ctx, OPC_OR, rx, rx, ry);
364d4831
NF
9599 break;
9600 case RR_XOR:
9fa77488 9601 gen_logic(env, ctx, OPC_XOR, rx, rx, ry);
364d4831
NF
9602 break;
9603 case RR_NOT:
9fa77488 9604 gen_logic(env, ctx, OPC_NOR, rx, ry, 0);
364d4831
NF
9605 break;
9606 case RR_MFHI:
9607 gen_HILO(ctx, OPC_MFHI, rx);
9608 break;
9609 case RR_CNVT:
9610 switch (cnvt_op) {
9611 case RR_RY_CNVT_ZEB:
9612 tcg_gen_ext8u_tl(cpu_gpr[rx], cpu_gpr[rx]);
9613 break;
9614 case RR_RY_CNVT_ZEH:
9615 tcg_gen_ext16u_tl(cpu_gpr[rx], cpu_gpr[rx]);
9616 break;
9617 case RR_RY_CNVT_SEB:
9618 tcg_gen_ext8s_tl(cpu_gpr[rx], cpu_gpr[rx]);
9619 break;
9620 case RR_RY_CNVT_SEH:
9621 tcg_gen_ext16s_tl(cpu_gpr[rx], cpu_gpr[rx]);
9622 break;
9623#if defined (TARGET_MIPS64)
9624 case RR_RY_CNVT_ZEW:
9625 check_mips_64(ctx);
9626 tcg_gen_ext32u_tl(cpu_gpr[rx], cpu_gpr[rx]);
9627 break;
9628 case RR_RY_CNVT_SEW:
9629 check_mips_64(ctx);
9630 tcg_gen_ext32s_tl(cpu_gpr[rx], cpu_gpr[rx]);
9631 break;
9632#endif
9633 default:
9634 generate_exception(ctx, EXCP_RI);
9635 break;
9636 }
9637 break;
9638 case RR_MFLO:
9639 gen_HILO(ctx, OPC_MFLO, rx);
9640 break;
9641#if defined (TARGET_MIPS64)
9642 case RR_DSRA:
9643 check_mips_64(ctx);
9644 gen_shift_imm(env, ctx, OPC_DSRA, ry, ry, sa);
9645 break;
9646 case RR_DSLLV:
9647 check_mips_64(ctx);
9648 gen_shift(env, ctx, OPC_DSLLV, ry, rx, ry);
9649 break;
9650 case RR_DSRLV:
9651 check_mips_64(ctx);
9652 gen_shift(env, ctx, OPC_DSRLV, ry, rx, ry);
9653 break;
9654 case RR_DSRAV:
9655 check_mips_64(ctx);
9656 gen_shift(env, ctx, OPC_DSRAV, ry, rx, ry);
9657 break;
9658#endif
9659 case RR_MULT:
9660 gen_muldiv(ctx, OPC_MULT, rx, ry);
9661 break;
9662 case RR_MULTU:
9663 gen_muldiv(ctx, OPC_MULTU, rx, ry);
9664 break;
9665 case RR_DIV:
9666 gen_muldiv(ctx, OPC_DIV, rx, ry);
9667 break;
9668 case RR_DIVU:
9669 gen_muldiv(ctx, OPC_DIVU, rx, ry);
9670 break;
9671#if defined (TARGET_MIPS64)
9672 case RR_DMULT:
9673 check_mips_64(ctx);
9674 gen_muldiv(ctx, OPC_DMULT, rx, ry);
9675 break;
9676 case RR_DMULTU:
9677 check_mips_64(ctx);
9678 gen_muldiv(ctx, OPC_DMULTU, rx, ry);
9679 break;
9680 case RR_DDIV:
9681 check_mips_64(ctx);
9682 gen_muldiv(ctx, OPC_DDIV, rx, ry);
9683 break;
9684 case RR_DDIVU:
9685 check_mips_64(ctx);
9686 gen_muldiv(ctx, OPC_DDIVU, rx, ry);
9687 break;
9688#endif
9689 default:
9690 generate_exception(ctx, EXCP_RI);
9691 break;
9692 }
9693 break;
9694 case M16_OPC_EXTEND:
9695 decode_extended_mips16_opc(env, ctx, is_branch);
9696 n_bytes = 4;
9697 break;
9698#if defined(TARGET_MIPS64)
9699 case M16_OPC_I64:
9700 funct = (ctx->opcode >> 8) & 0x7;
9701 decode_i64_mips16(env, ctx, ry, funct, offset, 0);
9702 break;
9703#endif
9704 default:
9705 generate_exception(ctx, EXCP_RI);
9706 break;
9707 }
9708
9709 return n_bytes;
9710}
9711
3c824109 9712/* microMIPS extension to MIPS32 */
6af0bf9c 9713
3c824109 9714/* microMIPS32 major opcodes */
6af0bf9c 9715
3c824109
NF
9716enum {
9717 POOL32A = 0x00,
9718 POOL16A = 0x01,
9719 LBU16 = 0x02,
9720 MOVE16 = 0x03,
9721 ADDI32 = 0x04,
9722 LBU32 = 0x05,
9723 SB32 = 0x06,
9724 LB32 = 0x07,
9725
9726 POOL32B = 0x08,
9727 POOL16B = 0x09,
9728 LHU16 = 0x0a,
9729 ANDI16 = 0x0b,
9730 ADDIU32 = 0x0c,
9731 LHU32 = 0x0d,
9732 SH32 = 0x0e,
9733 LH32 = 0x0f,
9734
9735 POOL32I = 0x10,
9736 POOL16C = 0x11,
9737 LWSP16 = 0x12,
9738 POOL16D = 0x13,
9739 ORI32 = 0x14,
9740 POOL32F = 0x15,
9741 POOL32S = 0x16,
9742 DADDIU32 = 0x17,
9743
9744 POOL32C = 0x18,
9745 LWGP16 = 0x19,
9746 LW16 = 0x1a,
9747 POOL16E = 0x1b,
9748 XORI32 = 0x1c,
9749 JALS32 = 0x1d,
9750 ADDIUPC = 0x1e,
9751 POOL48A = 0x1f,
9752
9753 /* 0x20 is reserved */
9754 RES_20 = 0x20,
9755 POOL16F = 0x21,
9756 SB16 = 0x22,
9757 BEQZ16 = 0x23,
9758 SLTI32 = 0x24,
9759 BEQ32 = 0x25,
9760 SWC132 = 0x26,
9761 LWC132 = 0x27,
9762
9763 /* 0x28 and 0x29 are reserved */
9764 RES_28 = 0x28,
9765 RES_29 = 0x29,
9766 SH16 = 0x2a,
9767 BNEZ16 = 0x2b,
9768 SLTIU32 = 0x2c,
9769 BNE32 = 0x2d,
9770 SDC132 = 0x2e,
9771 LDC132 = 0x2f,
9772
9773 /* 0x30 and 0x31 are reserved */
9774 RES_30 = 0x30,
9775 RES_31 = 0x31,
9776 SWSP16 = 0x32,
9777 B16 = 0x33,
9778 ANDI32 = 0x34,
9779 J32 = 0x35,
9780 SD32 = 0x36,
9781 LD32 = 0x37,
9782
9783 /* 0x38 and 0x39 are reserved */
9784 RES_38 = 0x38,
9785 RES_39 = 0x39,
9786 SW16 = 0x3a,
9787 LI16 = 0x3b,
9788 JALX32 = 0x3c,
9789 JAL32 = 0x3d,
9790 SW32 = 0x3e,
9791 LW32 = 0x3f
9792};
9793
9794/* POOL32A encoding of minor opcode field */
9795
9796enum {
9797 /* These opcodes are distinguished only by bits 9..6; those bits are
9798 * what are recorded below. */
9799 SLL32 = 0x0,
9800 SRL32 = 0x1,
9801 SRA = 0x2,
9802 ROTR = 0x3,
9803
9804 SLLV = 0x0,
9805 SRLV = 0x1,
9806 SRAV = 0x2,
9807 ROTRV = 0x3,
9808 ADD = 0x4,
9809 ADDU32 = 0x5,
9810 SUB = 0x6,
9811 SUBU32 = 0x7,
9812 MUL = 0x8,
9813 AND = 0x9,
9814 OR32 = 0xa,
9815 NOR = 0xb,
9816 XOR32 = 0xc,
9817 SLT = 0xd,
9818 SLTU = 0xe,
9819
9820 MOVN = 0x0,
9821 MOVZ = 0x1,
9822 LWXS = 0x4,
9823
9824 /* The following can be distinguished by their lower 6 bits. */
9825 INS = 0x0c,
9826 EXT = 0x2c,
9827 POOL32AXF = 0x3c
9828};
9829
9830/* POOL32AXF encoding of minor opcode field extension */
9831
9832enum {
9833 /* bits 11..6 */
9834 TEQ = 0x00,
9835 TGE = 0x08,
9836 TGEU = 0x10,
9837 TLT = 0x20,
9838 TLTU = 0x28,
9839 TNE = 0x30,
9840
9841 MFC0 = 0x03,
9842 MTC0 = 0x0b,
9843
9844 /* bits 13..12 for 0x01 */
9845 MFHI_ACC = 0x0,
9846 MFLO_ACC = 0x1,
9847 MTHI_ACC = 0x2,
9848 MTLO_ACC = 0x3,
9849
9850 /* bits 13..12 for 0x2a */
9851 MADD_ACC = 0x0,
9852 MADDU_ACC = 0x1,
9853 MSUB_ACC = 0x2,
9854 MSUBU_ACC = 0x3,
9855
9856 /* bits 13..12 for 0x32 */
9857 MULT_ACC = 0x0,
9858 MULTU_ACC = 0x0,
9859
9860 /* bits 15..12 for 0x2c */
9861 SEB = 0x2,
9862 SEH = 0x3,
9863 CLO = 0x4,
9864 CLZ = 0x5,
9865 RDHWR = 0x6,
9866 WSBH = 0x7,
9867 MULT = 0x8,
9868 MULTU = 0x9,
9869 DIV = 0xa,
9870 DIVU = 0xb,
9871 MADD = 0xc,
9872 MADDU = 0xd,
9873 MSUB = 0xe,
9874 MSUBU = 0xf,
9875
9876 /* bits 15..12 for 0x34 */
9877 MFC2 = 0x4,
9878 MTC2 = 0x5,
9879 MFHC2 = 0x8,
9880 MTHC2 = 0x9,
9881 CFC2 = 0xc,
9882 CTC2 = 0xd,
9883
9884 /* bits 15..12 for 0x3c */
9885 JALR = 0x0,
9886 JR = 0x0, /* alias */
9887 JALR_HB = 0x1,
9888 JALRS = 0x4,
9889 JALRS_HB = 0x5,
9890
9891 /* bits 15..12 for 0x05 */
9892 RDPGPR = 0xe,
9893 WRPGPR = 0xf,
9894
9895 /* bits 15..12 for 0x0d */
9896 TLBP = 0x0,
9897 TLBR = 0x1,
9898 TLBWI = 0x2,
9899 TLBWR = 0x3,
9900 WAIT = 0x9,
9901 IRET = 0xd,
9902 DERET = 0xe,
9903 ERET = 0xf,
9904
9905 /* bits 15..12 for 0x15 */
9906 DMT = 0x0,
9907 DVPE = 0x1,
9908 EMT = 0x2,
9909 EVPE = 0x3,
9910
9911 /* bits 15..12 for 0x1d */
9912 DI = 0x4,
9913 EI = 0x5,
9914
9915 /* bits 15..12 for 0x2d */
9916 SYNC = 0x6,
9917 SYSCALL = 0x8,
9918 SDBBP = 0xd,
9919
9920 /* bits 15..12 for 0x35 */
9921 MFHI32 = 0x0,
9922 MFLO32 = 0x1,
9923 MTHI32 = 0x2,
9924 MTLO32 = 0x3,
9925};
9926
9927/* POOL32B encoding of minor opcode field (bits 15..12) */
9928
9929enum {
9930 LWC2 = 0x0,
9931 LWP = 0x1,
9932 LDP = 0x4,
9933 LWM32 = 0x5,
9934 CACHE = 0x6,
9935 LDM = 0x7,
9936 SWC2 = 0x8,
9937 SWP = 0x9,
9938 SDP = 0xc,
9939 SWM32 = 0xd,
9940 SDM = 0xf
9941};
9942
9943/* POOL32C encoding of minor opcode field (bits 15..12) */
9944
9945enum {
9946 LWL = 0x0,
9947 SWL = 0x8,
9948 LWR = 0x1,
9949 SWR = 0x9,
9950 PREF = 0x2,
9951 /* 0xa is reserved */
9952 LL = 0x3,
9953 SC = 0xb,
9954 LDL = 0x4,
9955 SDL = 0xc,
9956 LDR = 0x5,
9957 SDR = 0xd,
9958 /* 0x6 is reserved */
9959 LWU = 0xe,
9960 LLD = 0x7,
9961 SCD = 0xf
9962};
9963
9964/* POOL32F encoding of minor opcode field (bits 5..0) */
9965
9966enum {
9967 /* These are the bit 7..6 values */
9968 ADD_FMT = 0x0,
9969 MOVN_FMT = 0x0,
9970
9971 SUB_FMT = 0x1,
9972 MOVZ_FMT = 0x1,
9973
9974 MUL_FMT = 0x2,
9975
9976 DIV_FMT = 0x3,
9977
9978 /* These are the bit 8..6 values */
9979 RSQRT2_FMT = 0x0,
9980 MOVF_FMT = 0x0,
9981
9982 LWXC1 = 0x1,
9983 MOVT_FMT = 0x1,
9984
9985 PLL_PS = 0x2,
9986 SWXC1 = 0x2,
9987
9988 PLU_PS = 0x3,
9989 LDXC1 = 0x3,
9990
9991 PUL_PS = 0x4,
9992 SDXC1 = 0x4,
9993 RECIP2_FMT = 0x4,
9994
9995 PUU_PS = 0x5,
9996 LUXC1 = 0x5,
9997
9998 CVT_PS_S = 0x6,
9999 SUXC1 = 0x6,
10000 ADDR_PS = 0x6,
10001 PREFX = 0x6,
10002
10003 MULR_PS = 0x7,
10004
10005 MADD_S = 0x01,
10006 MADD_D = 0x09,
10007 MADD_PS = 0x11,
10008 ALNV_PS = 0x19,
10009 MSUB_S = 0x21,
10010 MSUB_D = 0x29,
10011 MSUB_PS = 0x31,
10012
10013 NMADD_S = 0x02,
10014 NMADD_D = 0x0a,
10015 NMADD_PS = 0x12,
10016 NMSUB_S = 0x22,
10017 NMSUB_D = 0x2a,
10018 NMSUB_PS = 0x32,
10019
10020 POOL32FXF = 0x3b,
10021
10022 CABS_COND_FMT = 0x1c, /* MIPS3D */
10023 C_COND_FMT = 0x3c
10024};
10025
10026/* POOL32Fxf encoding of minor opcode extension field */
10027
10028enum {
10029 CVT_L = 0x04,
10030 RSQRT_FMT = 0x08,
10031 FLOOR_L = 0x0c,
10032 CVT_PW_PS = 0x1c,
10033 CVT_W = 0x24,
10034 SQRT_FMT = 0x28,
10035 FLOOR_W = 0x2c,
10036 CVT_PS_PW = 0x3c,
10037 CFC1 = 0x40,
10038 RECIP_FMT = 0x48,
10039 CEIL_L = 0x4c,
10040 CTC1 = 0x60,
10041 CEIL_W = 0x6c,
10042 MFC1 = 0x80,
10043 CVT_S_PL = 0x84,
10044 TRUNC_L = 0x8c,
10045 MTC1 = 0xa0,
10046 CVT_S_PU = 0xa4,
10047 TRUNC_W = 0xac,
10048 MFHC1 = 0xc0,
10049 ROUND_L = 0xcc,
10050 MTHC1 = 0xe0,
10051 ROUND_W = 0xec,
10052
10053 MOV_FMT = 0x01,
10054 MOVF = 0x05,
10055 ABS_FMT = 0x0d,
10056 RSQRT1_FMT = 0x1d,
10057 MOVT = 0x25,
10058 NEG_FMT = 0x2d,
10059 CVT_D = 0x4d,
10060 RECIP1_FMT = 0x5d,
10061 CVT_S = 0x6d
10062};
10063
10064/* POOL32I encoding of minor opcode field (bits 25..21) */
10065
10066enum {
10067 BLTZ = 0x00,
10068 BLTZAL = 0x01,
10069 BGEZ = 0x02,
10070 BGEZAL = 0x03,
10071 BLEZ = 0x04,
10072 BNEZC = 0x05,
10073 BGTZ = 0x06,
10074 BEQZC = 0x07,
10075 TLTI = 0x08,
10076 TGEI = 0x09,
10077 TLTIU = 0x0a,
10078 TGEIU = 0x0b,
10079 TNEI = 0x0c,
10080 LUI = 0x0d,
10081 TEQI = 0x0e,
10082 SYNCI = 0x10,
10083 BLTZALS = 0x11,
10084 BGEZALS = 0x13,
10085 BC2F = 0x14,
10086 BC2T = 0x15,
10087 BPOSGE64 = 0x1a,
10088 BPOSGE32 = 0x1b,
10089 /* These overlap and are distinguished by bit16 of the instruction */
10090 BC1F = 0x1c,
10091 BC1T = 0x1d,
10092 BC1ANY2F = 0x1c,
10093 BC1ANY2T = 0x1d,
10094 BC1ANY4F = 0x1e,
10095 BC1ANY4T = 0x1f
10096};
10097
10098/* POOL16A encoding of minor opcode field */
10099
10100enum {
10101 ADDU16 = 0x0,
10102 SUBU16 = 0x1
10103};
10104
10105/* POOL16B encoding of minor opcode field */
10106
10107enum {
10108 SLL16 = 0x0,
10109 SRL16 = 0x1
10110};
10111
10112/* POOL16C encoding of minor opcode field */
10113
10114enum {
10115 NOT16 = 0x00,
10116 XOR16 = 0x04,
10117 AND16 = 0x08,
10118 OR16 = 0x0c,
10119 LWM16 = 0x10,
10120 SWM16 = 0x14,
10121 JR16 = 0x18,
10122 JRC16 = 0x1a,
10123 JALR16 = 0x1c,
10124 JALR16S = 0x1e,
10125 MFHI16 = 0x20,
10126 MFLO16 = 0x24,
10127 BREAK16 = 0x28,
10128 SDBBP16 = 0x2c,
10129 JRADDIUSP = 0x30
10130};
10131
10132/* POOL16D encoding of minor opcode field */
10133
10134enum {
10135 ADDIUS5 = 0x0,
10136 ADDIUSP = 0x1
10137};
10138
10139/* POOL16E encoding of minor opcode field */
10140
10141enum {
10142 ADDIUR2 = 0x0,
10143 ADDIUR1SP = 0x1
10144};
10145
10146static int mmreg (int r)
10147{
10148 static const int map[] = { 16, 17, 2, 3, 4, 5, 6, 7 };
10149
10150 return map[r];
10151}
10152
10153/* Used for 16-bit store instructions. */
10154static int mmreg2 (int r)
10155{
10156 static const int map[] = { 0, 17, 2, 3, 4, 5, 6, 7 };
10157
10158 return map[r];
10159}
10160
10161#define uMIPS_RD(op) ((op >> 7) & 0x7)
10162#define uMIPS_RS(op) ((op >> 4) & 0x7)
10163#define uMIPS_RS2(op) uMIPS_RS(op)
10164#define uMIPS_RS1(op) ((op >> 1) & 0x7)
10165#define uMIPS_RD5(op) ((op >> 5) & 0x1f)
10166#define uMIPS_RS5(op) (op & 0x1f)
10167
10168/* Signed immediate */
10169#define SIMM(op, start, width) \
10170 ((int32_t)(((op >> start) & ((~0U) >> (32-width))) \
10171 << (32-width)) \
10172 >> (32-width))
10173/* Zero-extended immediate */
10174#define ZIMM(op, start, width) ((op >> start) & ((~0U) >> (32-width)))
10175
7db13fae 10176static void gen_addiur1sp (CPUMIPSState *env, DisasContext *ctx)
3c824109
NF
10177{
10178 int rd = mmreg(uMIPS_RD(ctx->opcode));
10179
10180 gen_arith_imm(env, ctx, OPC_ADDIU, rd, 29, ((ctx->opcode >> 1) & 0x3f) << 2);
10181}
10182
7db13fae 10183static void gen_addiur2 (CPUMIPSState *env, DisasContext *ctx)
3c824109
NF
10184{
10185 static const int decoded_imm[] = { 1, 4, 8, 12, 16, 20, 24, -1 };
10186 int rd = mmreg(uMIPS_RD(ctx->opcode));
10187 int rs = mmreg(uMIPS_RS(ctx->opcode));
10188
10189 gen_arith_imm(env, ctx, OPC_ADDIU, rd, rs, decoded_imm[ZIMM(ctx->opcode, 1, 3)]);
10190}
10191
7db13fae 10192static void gen_addiusp (CPUMIPSState *env, DisasContext *ctx)
3c824109
NF
10193{
10194 int encoded = ZIMM(ctx->opcode, 1, 9);
10195 int decoded;
10196
10197 if (encoded <= 1) {
10198 decoded = 256 + encoded;
10199 } else if (encoded <= 255) {
10200 decoded = encoded;
10201 } else if (encoded <= 509) {
10202 decoded = encoded - 512;
10203 } else {
10204 decoded = encoded - 768;
10205 }
10206
10207 gen_arith_imm(env, ctx, OPC_ADDIU, 29, 29, decoded << 2);
10208}
10209
7db13fae 10210static void gen_addius5 (CPUMIPSState *env, DisasContext *ctx)
3c824109
NF
10211{
10212 int imm = SIMM(ctx->opcode, 1, 4);
10213 int rd = (ctx->opcode >> 5) & 0x1f;
10214
10215 gen_arith_imm(env, ctx, OPC_ADDIU, rd, rd, imm);
10216}
10217
7db13fae 10218static void gen_andi16 (CPUMIPSState *env, DisasContext *ctx)
3c824109
NF
10219{
10220 static const int decoded_imm[] = { 128, 1, 2, 3, 4, 7, 8, 15, 16,
10221 31, 32, 63, 64, 255, 32768, 65535 };
10222 int rd = mmreg(uMIPS_RD(ctx->opcode));
10223 int rs = mmreg(uMIPS_RS(ctx->opcode));
10224 int encoded = ZIMM(ctx->opcode, 0, 4);
10225
9fa77488 10226 gen_logic_imm(env, ctx, OPC_ANDI, rd, rs, decoded_imm[encoded]);
3c824109
NF
10227}
10228
10229static void gen_ldst_multiple (DisasContext *ctx, uint32_t opc, int reglist,
10230 int base, int16_t offset)
10231{
e1050a76 10232 const char *opn = "ldst_multiple";
3c824109
NF
10233 TCGv t0, t1;
10234 TCGv_i32 t2;
10235
10236 if (ctx->hflags & MIPS_HFLAG_BMASK) {
10237 generate_exception(ctx, EXCP_RI);
10238 return;
10239 }
10240
10241 t0 = tcg_temp_new();
10242
10243 gen_base_offset_addr(ctx, t0, base, offset);
10244
10245 t1 = tcg_const_tl(reglist);
10246 t2 = tcg_const_i32(ctx->mem_idx);
6af0bf9c 10247
3c824109
NF
10248 save_cpu_state(ctx, 1);
10249 switch (opc) {
10250 case LWM32:
895c2d04 10251 gen_helper_lwm(cpu_env, t0, t1, t2);
e1050a76 10252 opn = "lwm";
3c824109
NF
10253 break;
10254 case SWM32:
895c2d04 10255 gen_helper_swm(cpu_env, t0, t1, t2);
e1050a76 10256 opn = "swm";
3c824109
NF
10257 break;
10258#ifdef TARGET_MIPS64
10259 case LDM:
895c2d04 10260 gen_helper_ldm(cpu_env, t0, t1, t2);
e1050a76 10261 opn = "ldm";
3c824109
NF
10262 break;
10263 case SDM:
895c2d04 10264 gen_helper_sdm(cpu_env, t0, t1, t2);
e1050a76 10265 opn = "sdm";
3c824109 10266 break;
6af0bf9c 10267#endif
3c824109 10268 }
e1050a76 10269 (void)opn;
3c824109
NF
10270 MIPS_DEBUG("%s, %x, %d(%s)", opn, reglist, offset, regnames[base]);
10271 tcg_temp_free(t0);
33087598 10272 tcg_temp_free(t1);
3c824109
NF
10273 tcg_temp_free_i32(t2);
10274}
6af0bf9c 10275
3c824109 10276
7db13fae 10277static void gen_pool16c_insn (CPUMIPSState *env, DisasContext *ctx, int *is_branch)
6af0bf9c 10278{
3c824109
NF
10279 int rd = mmreg((ctx->opcode >> 3) & 0x7);
10280 int rs = mmreg(ctx->opcode & 0x7);
10281 int opc;
6af0bf9c 10282
3c824109
NF
10283 switch (((ctx->opcode) >> 4) & 0x3f) {
10284 case NOT16 + 0:
10285 case NOT16 + 1:
10286 case NOT16 + 2:
10287 case NOT16 + 3:
9fa77488 10288 gen_logic(env, ctx, OPC_NOR, rd, rs, 0);
3c824109
NF
10289 break;
10290 case XOR16 + 0:
10291 case XOR16 + 1:
10292 case XOR16 + 2:
10293 case XOR16 + 3:
9fa77488 10294 gen_logic(env, ctx, OPC_XOR, rd, rd, rs);
3c824109
NF
10295 break;
10296 case AND16 + 0:
10297 case AND16 + 1:
10298 case AND16 + 2:
10299 case AND16 + 3:
9fa77488 10300 gen_logic(env, ctx, OPC_AND, rd, rd, rs);
3c824109
NF
10301 break;
10302 case OR16 + 0:
10303 case OR16 + 1:
10304 case OR16 + 2:
10305 case OR16 + 3:
9fa77488 10306 gen_logic(env, ctx, OPC_OR, rd, rd, rs);
3c824109
NF
10307 break;
10308 case LWM16 + 0:
10309 case LWM16 + 1:
10310 case LWM16 + 2:
10311 case LWM16 + 3:
10312 {
10313 static const int lwm_convert[] = { 0x11, 0x12, 0x13, 0x14 };
10314 int offset = ZIMM(ctx->opcode, 0, 4);
10315
10316 gen_ldst_multiple(ctx, LWM32, lwm_convert[(ctx->opcode >> 4) & 0x3],
10317 29, offset << 2);
10318 }
10319 break;
10320 case SWM16 + 0:
10321 case SWM16 + 1:
10322 case SWM16 + 2:
10323 case SWM16 + 3:
10324 {
10325 static const int swm_convert[] = { 0x11, 0x12, 0x13, 0x14 };
10326 int offset = ZIMM(ctx->opcode, 0, 4);
10327
10328 gen_ldst_multiple(ctx, SWM32, swm_convert[(ctx->opcode >> 4) & 0x3],
10329 29, offset << 2);
10330 }
10331 break;
10332 case JR16 + 0:
10333 case JR16 + 1:
10334 {
10335 int reg = ctx->opcode & 0x1f;
10336
10337 gen_compute_branch(ctx, OPC_JR, 2, reg, 0, 0);
10338 }
10339 *is_branch = 1;
10340 break;
10341 case JRC16 + 0:
10342 case JRC16 + 1:
10343 {
10344 int reg = ctx->opcode & 0x1f;
10345
10346 gen_compute_branch(ctx, OPC_JR, 2, reg, 0, 0);
10347 /* Let normal delay slot handling in our caller take us
10348 to the branch target. */
10349 }
10350 break;
10351 case JALR16 + 0:
10352 case JALR16 + 1:
10353 opc = OPC_JALR;
10354 goto do_jalr;
10355 case JALR16S + 0:
10356 case JALR16S + 1:
10357 opc = OPC_JALRS;
10358 do_jalr:
10359 {
10360 int reg = ctx->opcode & 0x1f;
10361
10362 gen_compute_branch(ctx, opc, 2, reg, 31, 0);
10363 }
10364 *is_branch = 1;
10365 break;
10366 case MFHI16 + 0:
10367 case MFHI16 + 1:
10368 gen_HILO(ctx, OPC_MFHI, uMIPS_RS5(ctx->opcode));
10369 break;
10370 case MFLO16 + 0:
10371 case MFLO16 + 1:
10372 gen_HILO(ctx, OPC_MFLO, uMIPS_RS5(ctx->opcode));
10373 break;
10374 case BREAK16:
10375 generate_exception(ctx, EXCP_BREAK);
10376 break;
10377 case SDBBP16:
10378 /* XXX: not clear which exception should be raised
10379 * when in debug mode...
10380 */
10381 check_insn(env, ctx, ISA_MIPS32);
10382 if (!(ctx->hflags & MIPS_HFLAG_DM)) {
10383 generate_exception(ctx, EXCP_DBp);
10384 } else {
10385 generate_exception(ctx, EXCP_DBp);
10386 }
10387 break;
10388 case JRADDIUSP + 0:
10389 case JRADDIUSP + 1:
10390 {
10391 int imm = ZIMM(ctx->opcode, 0, 5);
10392
10393 gen_compute_branch(ctx, OPC_JR, 2, 31, 0, 0);
10394 gen_arith_imm(env, ctx, OPC_ADDIU, 29, 29, imm << 2);
10395 /* Let normal delay slot handling in our caller take us
10396 to the branch target. */
10397 }
10398 break;
10399 default:
10400 generate_exception(ctx, EXCP_RI);
10401 break;
10402 }
10403}
10404
10405static void gen_ldxs (DisasContext *ctx, int base, int index, int rd)
10406{
10407 TCGv t0 = tcg_temp_new();
10408 TCGv t1 = tcg_temp_new();
10409
10410 gen_load_gpr(t0, base);
10411
10412 if (index != 0) {
10413 gen_load_gpr(t1, index);
10414 tcg_gen_shli_tl(t1, t1, 2);
10415 gen_op_addr_add(ctx, t0, t1, t0);
10416 }
10417
10418 save_cpu_state(ctx, 0);
5c13fdfd 10419 op_ld_lw(t1, t0, ctx);
3c824109
NF
10420 gen_store_gpr(t1, rd);
10421
10422 tcg_temp_free(t0);
10423 tcg_temp_free(t1);
10424}
10425
10426static void gen_ldst_pair (DisasContext *ctx, uint32_t opc, int rd,
10427 int base, int16_t offset)
10428{
10429 const char *opn = "ldst_pair";
10430 TCGv t0, t1;
10431
36c6711b 10432 if (ctx->hflags & MIPS_HFLAG_BMASK || rd == 31) {
3c824109 10433 generate_exception(ctx, EXCP_RI);
d796321b
FB
10434 return;
10435 }
10436
3c824109
NF
10437 t0 = tcg_temp_new();
10438 t1 = tcg_temp_new();
8e9ade68 10439
3c824109
NF
10440 gen_base_offset_addr(ctx, t0, base, offset);
10441
10442 switch (opc) {
10443 case LWP:
36c6711b
EJ
10444 if (rd == base) {
10445 generate_exception(ctx, EXCP_RI);
10446 return;
10447 }
3c824109 10448 save_cpu_state(ctx, 0);
5c13fdfd 10449 op_ld_lw(t1, t0, ctx);
3c824109
NF
10450 gen_store_gpr(t1, rd);
10451 tcg_gen_movi_tl(t1, 4);
10452 gen_op_addr_add(ctx, t0, t0, t1);
5c13fdfd 10453 op_ld_lw(t1, t0, ctx);
3c824109
NF
10454 gen_store_gpr(t1, rd+1);
10455 opn = "lwp";
10456 break;
10457 case SWP:
b835e919 10458 save_cpu_state(ctx, 0);
3c824109 10459 gen_load_gpr(t1, rd);
5c13fdfd 10460 op_st_sw(t1, t0, ctx);
3c824109
NF
10461 tcg_gen_movi_tl(t1, 4);
10462 gen_op_addr_add(ctx, t0, t0, t1);
10463 gen_load_gpr(t1, rd+1);
5c13fdfd 10464 op_st_sw(t1, t0, ctx);
3c824109
NF
10465 opn = "swp";
10466 break;
10467#ifdef TARGET_MIPS64
10468 case LDP:
36c6711b
EJ
10469 if (rd == base) {
10470 generate_exception(ctx, EXCP_RI);
10471 return;
10472 }
3c824109 10473 save_cpu_state(ctx, 0);
5c13fdfd 10474 op_ld_ld(t1, t0, ctx);
3c824109
NF
10475 gen_store_gpr(t1, rd);
10476 tcg_gen_movi_tl(t1, 8);
10477 gen_op_addr_add(ctx, t0, t0, t1);
5c13fdfd 10478 op_ld_ld(t1, t0, ctx);
3c824109
NF
10479 gen_store_gpr(t1, rd+1);
10480 opn = "ldp";
10481 break;
10482 case SDP:
b835e919 10483 save_cpu_state(ctx, 0);
3c824109 10484 gen_load_gpr(t1, rd);
5c13fdfd 10485 op_st_sd(t1, t0, ctx);
3c824109
NF
10486 tcg_gen_movi_tl(t1, 8);
10487 gen_op_addr_add(ctx, t0, t0, t1);
10488 gen_load_gpr(t1, rd+1);
5c13fdfd 10489 op_st_sd(t1, t0, ctx);
3c824109
NF
10490 opn = "sdp";
10491 break;
10492#endif
6af0bf9c 10493 }
2abf314d 10494 (void)opn; /* avoid a compiler warning */
3c824109
NF
10495 MIPS_DEBUG("%s, %s, %d(%s)", opn, regnames[rd], offset, regnames[base]);
10496 tcg_temp_free(t0);
10497 tcg_temp_free(t1);
10498}
618b0fe9 10499
7db13fae 10500static void gen_pool32axf (CPUMIPSState *env, DisasContext *ctx, int rt, int rs,
3c824109
NF
10501 int *is_branch)
10502{
10503 int extension = (ctx->opcode >> 6) & 0x3f;
10504 int minor = (ctx->opcode >> 12) & 0xf;
10505 uint32_t mips32_op;
10506
10507 switch (extension) {
10508 case TEQ:
10509 mips32_op = OPC_TEQ;
10510 goto do_trap;
10511 case TGE:
10512 mips32_op = OPC_TGE;
10513 goto do_trap;
10514 case TGEU:
10515 mips32_op = OPC_TGEU;
10516 goto do_trap;
10517 case TLT:
10518 mips32_op = OPC_TLT;
10519 goto do_trap;
10520 case TLTU:
10521 mips32_op = OPC_TLTU;
10522 goto do_trap;
10523 case TNE:
10524 mips32_op = OPC_TNE;
10525 do_trap:
10526 gen_trap(ctx, mips32_op, rs, rt, -1);
10527 break;
10528#ifndef CONFIG_USER_ONLY
10529 case MFC0:
10530 case MFC0 + 32:
2e15497c 10531 check_cp0_enabled(ctx);
3c824109
NF
10532 if (rt == 0) {
10533 /* Treat as NOP. */
10534 break;
10535 }
10536 gen_mfc0(env, ctx, cpu_gpr[rt], rs, (ctx->opcode >> 11) & 0x7);
10537 break;
10538 case MTC0:
10539 case MTC0 + 32:
2e15497c 10540 check_cp0_enabled(ctx);
3c824109
NF
10541 {
10542 TCGv t0 = tcg_temp_new();
618b0fe9 10543
3c824109
NF
10544 gen_load_gpr(t0, rt);
10545 gen_mtc0(env, ctx, t0, rs, (ctx->opcode >> 11) & 0x7);
10546 tcg_temp_free(t0);
10547 }
10548 break;
10549#endif
10550 case 0x2c:
10551 switch (minor) {
10552 case SEB:
10553 gen_bshfl(ctx, OPC_SEB, rs, rt);
10554 break;
10555 case SEH:
10556 gen_bshfl(ctx, OPC_SEH, rs, rt);
10557 break;
10558 case CLO:
10559 mips32_op = OPC_CLO;
10560 goto do_cl;
10561 case CLZ:
10562 mips32_op = OPC_CLZ;
10563 do_cl:
10564 check_insn(env, ctx, ISA_MIPS32);
10565 gen_cl(ctx, mips32_op, rt, rs);
10566 break;
10567 case RDHWR:
10568 gen_rdhwr(env, ctx, rt, rs);
10569 break;
10570 case WSBH:
10571 gen_bshfl(ctx, OPC_WSBH, rs, rt);
10572 break;
10573 case MULT:
10574 mips32_op = OPC_MULT;
10575 goto do_muldiv;
10576 case MULTU:
10577 mips32_op = OPC_MULTU;
10578 goto do_muldiv;
10579 case DIV:
10580 mips32_op = OPC_DIV;
10581 goto do_muldiv;
10582 case DIVU:
10583 mips32_op = OPC_DIVU;
10584 goto do_muldiv;
10585 case MADD:
10586 mips32_op = OPC_MADD;
10587 goto do_muldiv;
10588 case MADDU:
10589 mips32_op = OPC_MADDU;
10590 goto do_muldiv;
10591 case MSUB:
10592 mips32_op = OPC_MSUB;
10593 goto do_muldiv;
10594 case MSUBU:
10595 mips32_op = OPC_MSUBU;
10596 do_muldiv:
10597 check_insn(env, ctx, ISA_MIPS32);
10598 gen_muldiv(ctx, mips32_op, rs, rt);
10599 break;
10600 default:
10601 goto pool32axf_invalid;
10602 }
10603 break;
10604 case 0x34:
10605 switch (minor) {
10606 case MFC2:
10607 case MTC2:
10608 case MFHC2:
10609 case MTHC2:
10610 case CFC2:
10611 case CTC2:
10612 generate_exception_err(ctx, EXCP_CpU, 2);
10613 break;
10614 default:
10615 goto pool32axf_invalid;
10616 }
10617 break;
10618 case 0x3c:
10619 switch (minor) {
10620 case JALR:
10621 case JALR_HB:
10622 gen_compute_branch (ctx, OPC_JALR, 4, rs, rt, 0);
10623 *is_branch = 1;
10624 break;
10625 case JALRS:
10626 case JALRS_HB:
10627 gen_compute_branch (ctx, OPC_JALRS, 4, rs, rt, 0);
10628 *is_branch = 1;
10629 break;
10630 default:
10631 goto pool32axf_invalid;
10632 }
10633 break;
10634 case 0x05:
10635 switch (minor) {
10636 case RDPGPR:
2e15497c 10637 check_cp0_enabled(ctx);
3c824109
NF
10638 check_insn(env, ctx, ISA_MIPS32R2);
10639 gen_load_srsgpr(rt, rs);
10640 break;
10641 case WRPGPR:
2e15497c 10642 check_cp0_enabled(ctx);
3c824109
NF
10643 check_insn(env, ctx, ISA_MIPS32R2);
10644 gen_store_srsgpr(rt, rs);
10645 break;
10646 default:
10647 goto pool32axf_invalid;
10648 }
10649 break;
10650#ifndef CONFIG_USER_ONLY
10651 case 0x0d:
10652 switch (minor) {
10653 case TLBP:
10654 mips32_op = OPC_TLBP;
10655 goto do_cp0;
10656 case TLBR:
10657 mips32_op = OPC_TLBR;
10658 goto do_cp0;
10659 case TLBWI:
10660 mips32_op = OPC_TLBWI;
10661 goto do_cp0;
10662 case TLBWR:
10663 mips32_op = OPC_TLBWR;
10664 goto do_cp0;
10665 case WAIT:
10666 mips32_op = OPC_WAIT;
10667 goto do_cp0;
10668 case DERET:
10669 mips32_op = OPC_DERET;
10670 goto do_cp0;
10671 case ERET:
10672 mips32_op = OPC_ERET;
10673 do_cp0:
10674 gen_cp0(env, ctx, mips32_op, rt, rs);
10675 break;
10676 default:
10677 goto pool32axf_invalid;
10678 }
10679 break;
10680 case 0x1d:
10681 switch (minor) {
10682 case DI:
2e15497c 10683 check_cp0_enabled(ctx);
3c824109
NF
10684 {
10685 TCGv t0 = tcg_temp_new();
10686
10687 save_cpu_state(ctx, 1);
895c2d04 10688 gen_helper_di(t0, cpu_env);
3c824109
NF
10689 gen_store_gpr(t0, rs);
10690 /* Stop translation as we may have switched the execution mode */
10691 ctx->bstate = BS_STOP;
10692 tcg_temp_free(t0);
10693 }
10694 break;
10695 case EI:
2e15497c 10696 check_cp0_enabled(ctx);
3c824109
NF
10697 {
10698 TCGv t0 = tcg_temp_new();
10699
10700 save_cpu_state(ctx, 1);
895c2d04 10701 gen_helper_ei(t0, cpu_env);
3c824109
NF
10702 gen_store_gpr(t0, rs);
10703 /* Stop translation as we may have switched the execution mode */
10704 ctx->bstate = BS_STOP;
10705 tcg_temp_free(t0);
10706 }
10707 break;
10708 default:
10709 goto pool32axf_invalid;
10710 }
10711 break;
10712#endif
10713 case 0x2d:
10714 switch (minor) {
10715 case SYNC:
10716 /* NOP */
10717 break;
10718 case SYSCALL:
10719 generate_exception(ctx, EXCP_SYSCALL);
10720 ctx->bstate = BS_STOP;
10721 break;
10722 case SDBBP:
10723 check_insn(env, ctx, ISA_MIPS32);
10724 if (!(ctx->hflags & MIPS_HFLAG_DM)) {
10725 generate_exception(ctx, EXCP_DBp);
10726 } else {
10727 generate_exception(ctx, EXCP_DBp);
10728 }
10729 break;
10730 default:
10731 goto pool32axf_invalid;
10732 }
10733 break;
10734 case 0x35:
10735 switch (minor) {
10736 case MFHI32:
10737 gen_HILO(ctx, OPC_MFHI, rs);
10738 break;
10739 case MFLO32:
10740 gen_HILO(ctx, OPC_MFLO, rs);
10741 break;
10742 case MTHI32:
10743 gen_HILO(ctx, OPC_MTHI, rs);
10744 break;
10745 case MTLO32:
10746 gen_HILO(ctx, OPC_MTLO, rs);
10747 break;
10748 default:
10749 goto pool32axf_invalid;
10750 }
10751 break;
10752 default:
10753 pool32axf_invalid:
10754 MIPS_INVAL("pool32axf");
10755 generate_exception(ctx, EXCP_RI);
10756 break;
10757 }
10758}
10759
10760/* Values for microMIPS fmt field. Variable-width, depending on which
10761 formats the instruction supports. */
10762
10763enum {
10764 FMT_SD_S = 0,
10765 FMT_SD_D = 1,
10766
10767 FMT_SDPS_S = 0,
10768 FMT_SDPS_D = 1,
10769 FMT_SDPS_PS = 2,
10770
10771 FMT_SWL_S = 0,
10772 FMT_SWL_W = 1,
10773 FMT_SWL_L = 2,
10774
10775 FMT_DWL_D = 0,
10776 FMT_DWL_W = 1,
10777 FMT_DWL_L = 2
10778};
10779
7db13fae 10780static void gen_pool32fxf (CPUMIPSState *env, DisasContext *ctx, int rt, int rs)
3c824109
NF
10781{
10782 int extension = (ctx->opcode >> 6) & 0x3ff;
10783 uint32_t mips32_op;
10784
10785#define FLOAT_1BIT_FMT(opc, fmt) (fmt << 8) | opc
10786#define FLOAT_2BIT_FMT(opc, fmt) (fmt << 7) | opc
10787#define COND_FLOAT_MOV(opc, cond) (cond << 7) | opc
10788
10789 switch (extension) {
10790 case FLOAT_1BIT_FMT(CFC1, 0):
10791 mips32_op = OPC_CFC1;
10792 goto do_cp1;
10793 case FLOAT_1BIT_FMT(CTC1, 0):
10794 mips32_op = OPC_CTC1;
10795 goto do_cp1;
10796 case FLOAT_1BIT_FMT(MFC1, 0):
10797 mips32_op = OPC_MFC1;
10798 goto do_cp1;
10799 case FLOAT_1BIT_FMT(MTC1, 0):
10800 mips32_op = OPC_MTC1;
10801 goto do_cp1;
10802 case FLOAT_1BIT_FMT(MFHC1, 0):
10803 mips32_op = OPC_MFHC1;
10804 goto do_cp1;
10805 case FLOAT_1BIT_FMT(MTHC1, 0):
10806 mips32_op = OPC_MTHC1;
10807 do_cp1:
10808 gen_cp1(ctx, mips32_op, rt, rs);
10809 break;
10810
10811 /* Reciprocal square root */
10812 case FLOAT_1BIT_FMT(RSQRT_FMT, FMT_SD_S):
10813 mips32_op = OPC_RSQRT_S;
10814 goto do_unaryfp;
10815 case FLOAT_1BIT_FMT(RSQRT_FMT, FMT_SD_D):
10816 mips32_op = OPC_RSQRT_D;
10817 goto do_unaryfp;
10818
10819 /* Square root */
10820 case FLOAT_1BIT_FMT(SQRT_FMT, FMT_SD_S):
10821 mips32_op = OPC_SQRT_S;
10822 goto do_unaryfp;
10823 case FLOAT_1BIT_FMT(SQRT_FMT, FMT_SD_D):
10824 mips32_op = OPC_SQRT_D;
10825 goto do_unaryfp;
10826
10827 /* Reciprocal */
10828 case FLOAT_1BIT_FMT(RECIP_FMT, FMT_SD_S):
10829 mips32_op = OPC_RECIP_S;
10830 goto do_unaryfp;
10831 case FLOAT_1BIT_FMT(RECIP_FMT, FMT_SD_D):
10832 mips32_op = OPC_RECIP_D;
10833 goto do_unaryfp;
10834
10835 /* Floor */
10836 case FLOAT_1BIT_FMT(FLOOR_L, FMT_SD_S):
10837 mips32_op = OPC_FLOOR_L_S;
10838 goto do_unaryfp;
10839 case FLOAT_1BIT_FMT(FLOOR_L, FMT_SD_D):
10840 mips32_op = OPC_FLOOR_L_D;
10841 goto do_unaryfp;
10842 case FLOAT_1BIT_FMT(FLOOR_W, FMT_SD_S):
10843 mips32_op = OPC_FLOOR_W_S;
10844 goto do_unaryfp;
10845 case FLOAT_1BIT_FMT(FLOOR_W, FMT_SD_D):
10846 mips32_op = OPC_FLOOR_W_D;
10847 goto do_unaryfp;
10848
10849 /* Ceiling */
10850 case FLOAT_1BIT_FMT(CEIL_L, FMT_SD_S):
10851 mips32_op = OPC_CEIL_L_S;
10852 goto do_unaryfp;
10853 case FLOAT_1BIT_FMT(CEIL_L, FMT_SD_D):
10854 mips32_op = OPC_CEIL_L_D;
10855 goto do_unaryfp;
10856 case FLOAT_1BIT_FMT(CEIL_W, FMT_SD_S):
10857 mips32_op = OPC_CEIL_W_S;
10858 goto do_unaryfp;
10859 case FLOAT_1BIT_FMT(CEIL_W, FMT_SD_D):
10860 mips32_op = OPC_CEIL_W_D;
10861 goto do_unaryfp;
10862
10863 /* Truncation */
10864 case FLOAT_1BIT_FMT(TRUNC_L, FMT_SD_S):
10865 mips32_op = OPC_TRUNC_L_S;
10866 goto do_unaryfp;
10867 case FLOAT_1BIT_FMT(TRUNC_L, FMT_SD_D):
10868 mips32_op = OPC_TRUNC_L_D;
10869 goto do_unaryfp;
10870 case FLOAT_1BIT_FMT(TRUNC_W, FMT_SD_S):
10871 mips32_op = OPC_TRUNC_W_S;
10872 goto do_unaryfp;
10873 case FLOAT_1BIT_FMT(TRUNC_W, FMT_SD_D):
10874 mips32_op = OPC_TRUNC_W_D;
10875 goto do_unaryfp;
10876
10877 /* Round */
10878 case FLOAT_1BIT_FMT(ROUND_L, FMT_SD_S):
10879 mips32_op = OPC_ROUND_L_S;
10880 goto do_unaryfp;
10881 case FLOAT_1BIT_FMT(ROUND_L, FMT_SD_D):
10882 mips32_op = OPC_ROUND_L_D;
10883 goto do_unaryfp;
10884 case FLOAT_1BIT_FMT(ROUND_W, FMT_SD_S):
10885 mips32_op = OPC_ROUND_W_S;
10886 goto do_unaryfp;
10887 case FLOAT_1BIT_FMT(ROUND_W, FMT_SD_D):
10888 mips32_op = OPC_ROUND_W_D;
10889 goto do_unaryfp;
10890
10891 /* Integer to floating-point conversion */
10892 case FLOAT_1BIT_FMT(CVT_L, FMT_SD_S):
10893 mips32_op = OPC_CVT_L_S;
10894 goto do_unaryfp;
10895 case FLOAT_1BIT_FMT(CVT_L, FMT_SD_D):
10896 mips32_op = OPC_CVT_L_D;
10897 goto do_unaryfp;
10898 case FLOAT_1BIT_FMT(CVT_W, FMT_SD_S):
10899 mips32_op = OPC_CVT_W_S;
10900 goto do_unaryfp;
10901 case FLOAT_1BIT_FMT(CVT_W, FMT_SD_D):
10902 mips32_op = OPC_CVT_W_D;
10903 goto do_unaryfp;
10904
10905 /* Paired-foo conversions */
10906 case FLOAT_1BIT_FMT(CVT_S_PL, 0):
10907 mips32_op = OPC_CVT_S_PL;
10908 goto do_unaryfp;
10909 case FLOAT_1BIT_FMT(CVT_S_PU, 0):
10910 mips32_op = OPC_CVT_S_PU;
10911 goto do_unaryfp;
10912 case FLOAT_1BIT_FMT(CVT_PW_PS, 0):
10913 mips32_op = OPC_CVT_PW_PS;
10914 goto do_unaryfp;
10915 case FLOAT_1BIT_FMT(CVT_PS_PW, 0):
10916 mips32_op = OPC_CVT_PS_PW;
10917 goto do_unaryfp;
10918
10919 /* Floating-point moves */
10920 case FLOAT_2BIT_FMT(MOV_FMT, FMT_SDPS_S):
10921 mips32_op = OPC_MOV_S;
10922 goto do_unaryfp;
10923 case FLOAT_2BIT_FMT(MOV_FMT, FMT_SDPS_D):
10924 mips32_op = OPC_MOV_D;
10925 goto do_unaryfp;
10926 case FLOAT_2BIT_FMT(MOV_FMT, FMT_SDPS_PS):
10927 mips32_op = OPC_MOV_PS;
10928 goto do_unaryfp;
10929
10930 /* Absolute value */
10931 case FLOAT_2BIT_FMT(ABS_FMT, FMT_SDPS_S):
10932 mips32_op = OPC_ABS_S;
10933 goto do_unaryfp;
10934 case FLOAT_2BIT_FMT(ABS_FMT, FMT_SDPS_D):
10935 mips32_op = OPC_ABS_D;
10936 goto do_unaryfp;
10937 case FLOAT_2BIT_FMT(ABS_FMT, FMT_SDPS_PS):
10938 mips32_op = OPC_ABS_PS;
10939 goto do_unaryfp;
10940
10941 /* Negation */
10942 case FLOAT_2BIT_FMT(NEG_FMT, FMT_SDPS_S):
10943 mips32_op = OPC_NEG_S;
10944 goto do_unaryfp;
10945 case FLOAT_2BIT_FMT(NEG_FMT, FMT_SDPS_D):
10946 mips32_op = OPC_NEG_D;
10947 goto do_unaryfp;
10948 case FLOAT_2BIT_FMT(NEG_FMT, FMT_SDPS_PS):
10949 mips32_op = OPC_NEG_PS;
10950 goto do_unaryfp;
10951
10952 /* Reciprocal square root step */
10953 case FLOAT_2BIT_FMT(RSQRT1_FMT, FMT_SDPS_S):
10954 mips32_op = OPC_RSQRT1_S;
10955 goto do_unaryfp;
10956 case FLOAT_2BIT_FMT(RSQRT1_FMT, FMT_SDPS_D):
10957 mips32_op = OPC_RSQRT1_D;
10958 goto do_unaryfp;
10959 case FLOAT_2BIT_FMT(RSQRT1_FMT, FMT_SDPS_PS):
10960 mips32_op = OPC_RSQRT1_PS;
10961 goto do_unaryfp;
10962
10963 /* Reciprocal step */
10964 case FLOAT_2BIT_FMT(RECIP1_FMT, FMT_SDPS_S):
10965 mips32_op = OPC_RECIP1_S;
10966 goto do_unaryfp;
10967 case FLOAT_2BIT_FMT(RECIP1_FMT, FMT_SDPS_D):
10968 mips32_op = OPC_RECIP1_S;
10969 goto do_unaryfp;
10970 case FLOAT_2BIT_FMT(RECIP1_FMT, FMT_SDPS_PS):
10971 mips32_op = OPC_RECIP1_PS;
10972 goto do_unaryfp;
10973
10974 /* Conversions from double */
10975 case FLOAT_2BIT_FMT(CVT_D, FMT_SWL_S):
10976 mips32_op = OPC_CVT_D_S;
10977 goto do_unaryfp;
10978 case FLOAT_2BIT_FMT(CVT_D, FMT_SWL_W):
10979 mips32_op = OPC_CVT_D_W;
10980 goto do_unaryfp;
10981 case FLOAT_2BIT_FMT(CVT_D, FMT_SWL_L):
10982 mips32_op = OPC_CVT_D_L;
10983 goto do_unaryfp;
10984
10985 /* Conversions from single */
10986 case FLOAT_2BIT_FMT(CVT_S, FMT_DWL_D):
10987 mips32_op = OPC_CVT_S_D;
10988 goto do_unaryfp;
10989 case FLOAT_2BIT_FMT(CVT_S, FMT_DWL_W):
10990 mips32_op = OPC_CVT_S_W;
10991 goto do_unaryfp;
10992 case FLOAT_2BIT_FMT(CVT_S, FMT_DWL_L):
10993 mips32_op = OPC_CVT_S_L;
10994 do_unaryfp:
10995 gen_farith(ctx, mips32_op, -1, rs, rt, 0);
10996 break;
10997
10998 /* Conditional moves on floating-point codes */
10999 case COND_FLOAT_MOV(MOVT, 0):
11000 case COND_FLOAT_MOV(MOVT, 1):
11001 case COND_FLOAT_MOV(MOVT, 2):
11002 case COND_FLOAT_MOV(MOVT, 3):
11003 case COND_FLOAT_MOV(MOVT, 4):
11004 case COND_FLOAT_MOV(MOVT, 5):
11005 case COND_FLOAT_MOV(MOVT, 6):
11006 case COND_FLOAT_MOV(MOVT, 7):
11007 gen_movci(ctx, rt, rs, (ctx->opcode >> 13) & 0x7, 1);
11008 break;
11009 case COND_FLOAT_MOV(MOVF, 0):
11010 case COND_FLOAT_MOV(MOVF, 1):
11011 case COND_FLOAT_MOV(MOVF, 2):
11012 case COND_FLOAT_MOV(MOVF, 3):
11013 case COND_FLOAT_MOV(MOVF, 4):
11014 case COND_FLOAT_MOV(MOVF, 5):
11015 case COND_FLOAT_MOV(MOVF, 6):
11016 case COND_FLOAT_MOV(MOVF, 7):
11017 gen_movci(ctx, rt, rs, (ctx->opcode >> 13) & 0x7, 0);
11018 break;
11019 default:
11020 MIPS_INVAL("pool32fxf");
11021 generate_exception(ctx, EXCP_RI);
11022 break;
11023 }
11024}
11025
7db13fae 11026static void decode_micromips32_opc (CPUMIPSState *env, DisasContext *ctx,
3c824109
NF
11027 uint16_t insn_hw1, int *is_branch)
11028{
11029 int32_t offset;
11030 uint16_t insn;
11031 int rt, rs, rd, rr;
11032 int16_t imm;
11033 uint32_t op, minor, mips32_op;
11034 uint32_t cond, fmt, cc;
11035
895c2d04 11036 insn = cpu_lduw_code(env, ctx->pc + 2);
3c824109
NF
11037 ctx->opcode = (ctx->opcode << 16) | insn;
11038
11039 rt = (ctx->opcode >> 21) & 0x1f;
11040 rs = (ctx->opcode >> 16) & 0x1f;
11041 rd = (ctx->opcode >> 11) & 0x1f;
11042 rr = (ctx->opcode >> 6) & 0x1f;
11043 imm = (int16_t) ctx->opcode;
11044
11045 op = (ctx->opcode >> 26) & 0x3f;
11046 switch (op) {
11047 case POOL32A:
11048 minor = ctx->opcode & 0x3f;
11049 switch (minor) {
11050 case 0x00:
11051 minor = (ctx->opcode >> 6) & 0xf;
11052 switch (minor) {
11053 case SLL32:
11054 mips32_op = OPC_SLL;
11055 goto do_shifti;
11056 case SRA:
11057 mips32_op = OPC_SRA;
11058 goto do_shifti;
11059 case SRL32:
11060 mips32_op = OPC_SRL;
11061 goto do_shifti;
11062 case ROTR:
11063 mips32_op = OPC_ROTR;
11064 do_shifti:
11065 gen_shift_imm(env, ctx, mips32_op, rt, rs, rd);
11066 break;
11067 default:
11068 goto pool32a_invalid;
11069 }
11070 break;
11071 case 0x10:
11072 minor = (ctx->opcode >> 6) & 0xf;
11073 switch (minor) {
11074 /* Arithmetic */
11075 case ADD:
11076 mips32_op = OPC_ADD;
11077 goto do_arith;
11078 case ADDU32:
11079 mips32_op = OPC_ADDU;
11080 goto do_arith;
11081 case SUB:
11082 mips32_op = OPC_SUB;
11083 goto do_arith;
11084 case SUBU32:
11085 mips32_op = OPC_SUBU;
11086 goto do_arith;
11087 case MUL:
11088 mips32_op = OPC_MUL;
11089 do_arith:
11090 gen_arith(env, ctx, mips32_op, rd, rs, rt);
11091 break;
11092 /* Shifts */
11093 case SLLV:
11094 mips32_op = OPC_SLLV;
11095 goto do_shift;
11096 case SRLV:
11097 mips32_op = OPC_SRLV;
11098 goto do_shift;
11099 case SRAV:
11100 mips32_op = OPC_SRAV;
11101 goto do_shift;
11102 case ROTRV:
11103 mips32_op = OPC_ROTRV;
11104 do_shift:
11105 gen_shift(env, ctx, mips32_op, rd, rs, rt);
11106 break;
11107 /* Logical operations */
11108 case AND:
11109 mips32_op = OPC_AND;
11110 goto do_logic;
11111 case OR32:
11112 mips32_op = OPC_OR;
11113 goto do_logic;
11114 case NOR:
11115 mips32_op = OPC_NOR;
11116 goto do_logic;
11117 case XOR32:
11118 mips32_op = OPC_XOR;
11119 do_logic:
9fa77488 11120 gen_logic(env, ctx, mips32_op, rd, rs, rt);
3c824109
NF
11121 break;
11122 /* Set less than */
11123 case SLT:
11124 mips32_op = OPC_SLT;
11125 goto do_slt;
11126 case SLTU:
11127 mips32_op = OPC_SLTU;
11128 do_slt:
9fa77488 11129 gen_slt(env, ctx, mips32_op, rd, rs, rt);
3c824109
NF
11130 break;
11131 default:
11132 goto pool32a_invalid;
11133 }
11134 break;
11135 case 0x18:
11136 minor = (ctx->opcode >> 6) & 0xf;
11137 switch (minor) {
11138 /* Conditional moves */
11139 case MOVN:
11140 mips32_op = OPC_MOVN;
11141 goto do_cmov;
11142 case MOVZ:
11143 mips32_op = OPC_MOVZ;
11144 do_cmov:
9fa77488 11145 gen_cond_move(env, ctx, mips32_op, rd, rs, rt);
3c824109
NF
11146 break;
11147 case LWXS:
11148 gen_ldxs(ctx, rs, rt, rd);
11149 break;
11150 default:
11151 goto pool32a_invalid;
11152 }
11153 break;
11154 case INS:
11155 gen_bitops(ctx, OPC_INS, rt, rs, rr, rd);
11156 return;
11157 case EXT:
11158 gen_bitops(ctx, OPC_EXT, rt, rs, rr, rd);
11159 return;
11160 case POOL32AXF:
11161 gen_pool32axf(env, ctx, rt, rs, is_branch);
11162 break;
11163 case 0x07:
11164 generate_exception(ctx, EXCP_BREAK);
11165 break;
11166 default:
11167 pool32a_invalid:
11168 MIPS_INVAL("pool32a");
11169 generate_exception(ctx, EXCP_RI);
11170 break;
11171 }
11172 break;
11173 case POOL32B:
11174 minor = (ctx->opcode >> 12) & 0xf;
11175 switch (minor) {
11176 case CACHE:
2e15497c 11177 check_cp0_enabled(ctx);
3c824109
NF
11178 /* Treat as no-op. */
11179 break;
11180 case LWC2:
11181 case SWC2:
11182 /* COP2: Not implemented. */
11183 generate_exception_err(ctx, EXCP_CpU, 2);
11184 break;
11185 case LWP:
11186 case SWP:
11187#ifdef TARGET_MIPS64
11188 case LDP:
11189 case SDP:
11190#endif
11191 gen_ldst_pair(ctx, minor, rt, rs, SIMM(ctx->opcode, 0, 12));
11192 break;
11193 case LWM32:
11194 case SWM32:
11195#ifdef TARGET_MIPS64
11196 case LDM:
11197 case SDM:
11198#endif
11199 gen_ldst_multiple(ctx, minor, rt, rs, SIMM(ctx->opcode, 0, 12));
11200 break;
11201 default:
11202 MIPS_INVAL("pool32b");
11203 generate_exception(ctx, EXCP_RI);
11204 break;
11205 }
11206 break;
11207 case POOL32F:
11208 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
11209 minor = ctx->opcode & 0x3f;
11210 check_cp1_enabled(ctx);
11211 switch (minor) {
11212 case ALNV_PS:
11213 mips32_op = OPC_ALNV_PS;
11214 goto do_madd;
11215 case MADD_S:
11216 mips32_op = OPC_MADD_S;
11217 goto do_madd;
11218 case MADD_D:
11219 mips32_op = OPC_MADD_D;
11220 goto do_madd;
11221 case MADD_PS:
11222 mips32_op = OPC_MADD_PS;
11223 goto do_madd;
11224 case MSUB_S:
11225 mips32_op = OPC_MSUB_S;
11226 goto do_madd;
11227 case MSUB_D:
11228 mips32_op = OPC_MSUB_D;
11229 goto do_madd;
11230 case MSUB_PS:
11231 mips32_op = OPC_MSUB_PS;
11232 goto do_madd;
11233 case NMADD_S:
11234 mips32_op = OPC_NMADD_S;
11235 goto do_madd;
11236 case NMADD_D:
11237 mips32_op = OPC_NMADD_D;
11238 goto do_madd;
11239 case NMADD_PS:
11240 mips32_op = OPC_NMADD_PS;
11241 goto do_madd;
11242 case NMSUB_S:
11243 mips32_op = OPC_NMSUB_S;
11244 goto do_madd;
11245 case NMSUB_D:
11246 mips32_op = OPC_NMSUB_D;
11247 goto do_madd;
11248 case NMSUB_PS:
11249 mips32_op = OPC_NMSUB_PS;
11250 do_madd:
11251 gen_flt3_arith(ctx, mips32_op, rd, rr, rs, rt);
11252 break;
11253 case CABS_COND_FMT:
11254 cond = (ctx->opcode >> 6) & 0xf;
11255 cc = (ctx->opcode >> 13) & 0x7;
11256 fmt = (ctx->opcode >> 10) & 0x3;
11257 switch (fmt) {
11258 case 0x0:
11259 gen_cmpabs_s(ctx, cond, rt, rs, cc);
11260 break;
11261 case 0x1:
11262 gen_cmpabs_d(ctx, cond, rt, rs, cc);
11263 break;
11264 case 0x2:
11265 gen_cmpabs_ps(ctx, cond, rt, rs, cc);
11266 break;
11267 default:
11268 goto pool32f_invalid;
11269 }
11270 break;
11271 case C_COND_FMT:
11272 cond = (ctx->opcode >> 6) & 0xf;
11273 cc = (ctx->opcode >> 13) & 0x7;
11274 fmt = (ctx->opcode >> 10) & 0x3;
11275 switch (fmt) {
11276 case 0x0:
11277 gen_cmp_s(ctx, cond, rt, rs, cc);
11278 break;
11279 case 0x1:
11280 gen_cmp_d(ctx, cond, rt, rs, cc);
11281 break;
11282 case 0x2:
11283 gen_cmp_ps(ctx, cond, rt, rs, cc);
11284 break;
11285 default:
11286 goto pool32f_invalid;
11287 }
11288 break;
11289 case POOL32FXF:
11290 gen_pool32fxf(env, ctx, rt, rs);
11291 break;
11292 case 0x00:
11293 /* PLL foo */
11294 switch ((ctx->opcode >> 6) & 0x7) {
11295 case PLL_PS:
11296 mips32_op = OPC_PLL_PS;
11297 goto do_ps;
11298 case PLU_PS:
11299 mips32_op = OPC_PLU_PS;
11300 goto do_ps;
11301 case PUL_PS:
11302 mips32_op = OPC_PUL_PS;
11303 goto do_ps;
11304 case PUU_PS:
11305 mips32_op = OPC_PUU_PS;
11306 goto do_ps;
11307 case CVT_PS_S:
11308 mips32_op = OPC_CVT_PS_S;
11309 do_ps:
11310 gen_farith(ctx, mips32_op, rt, rs, rd, 0);
11311 break;
11312 default:
11313 goto pool32f_invalid;
11314 }
11315 break;
11316 case 0x08:
11317 /* [LS][WDU]XC1 */
11318 switch ((ctx->opcode >> 6) & 0x7) {
11319 case LWXC1:
11320 mips32_op = OPC_LWXC1;
11321 goto do_ldst_cp1;
11322 case SWXC1:
11323 mips32_op = OPC_SWXC1;
11324 goto do_ldst_cp1;
11325 case LDXC1:
11326 mips32_op = OPC_LDXC1;
11327 goto do_ldst_cp1;
11328 case SDXC1:
11329 mips32_op = OPC_SDXC1;
11330 goto do_ldst_cp1;
11331 case LUXC1:
11332 mips32_op = OPC_LUXC1;
11333 goto do_ldst_cp1;
11334 case SUXC1:
11335 mips32_op = OPC_SUXC1;
11336 do_ldst_cp1:
11337 gen_flt3_ldst(ctx, mips32_op, rd, rd, rt, rs);
11338 break;
11339 default:
11340 goto pool32f_invalid;
11341 }
11342 break;
11343 case 0x18:
11344 /* 3D insns */
11345 fmt = (ctx->opcode >> 9) & 0x3;
11346 switch ((ctx->opcode >> 6) & 0x7) {
11347 case RSQRT2_FMT:
11348 switch (fmt) {
11349 case FMT_SDPS_S:
11350 mips32_op = OPC_RSQRT2_S;
11351 goto do_3d;
11352 case FMT_SDPS_D:
11353 mips32_op = OPC_RSQRT2_D;
11354 goto do_3d;
11355 case FMT_SDPS_PS:
11356 mips32_op = OPC_RSQRT2_PS;
11357 goto do_3d;
11358 default:
11359 goto pool32f_invalid;
11360 }
11361 break;
11362 case RECIP2_FMT:
11363 switch (fmt) {
11364 case FMT_SDPS_S:
11365 mips32_op = OPC_RECIP2_S;
11366 goto do_3d;
11367 case FMT_SDPS_D:
11368 mips32_op = OPC_RECIP2_D;
11369 goto do_3d;
11370 case FMT_SDPS_PS:
11371 mips32_op = OPC_RECIP2_PS;
11372 goto do_3d;
11373 default:
11374 goto pool32f_invalid;
11375 }
11376 break;
11377 case ADDR_PS:
11378 mips32_op = OPC_ADDR_PS;
11379 goto do_3d;
11380 case MULR_PS:
11381 mips32_op = OPC_MULR_PS;
11382 do_3d:
11383 gen_farith(ctx, mips32_op, rt, rs, rd, 0);
11384 break;
11385 default:
11386 goto pool32f_invalid;
11387 }
11388 break;
11389 case 0x20:
11390 /* MOV[FT].fmt and PREFX */
11391 cc = (ctx->opcode >> 13) & 0x7;
11392 fmt = (ctx->opcode >> 9) & 0x3;
11393 switch ((ctx->opcode >> 6) & 0x7) {
11394 case MOVF_FMT:
11395 switch (fmt) {
11396 case FMT_SDPS_S:
11397 gen_movcf_s(rs, rt, cc, 0);
11398 break;
11399 case FMT_SDPS_D:
11400 gen_movcf_d(ctx, rs, rt, cc, 0);
11401 break;
11402 case FMT_SDPS_PS:
11403 gen_movcf_ps(rs, rt, cc, 0);
11404 break;
11405 default:
11406 goto pool32f_invalid;
11407 }
11408 break;
11409 case MOVT_FMT:
11410 switch (fmt) {
11411 case FMT_SDPS_S:
11412 gen_movcf_s(rs, rt, cc, 1);
11413 break;
11414 case FMT_SDPS_D:
11415 gen_movcf_d(ctx, rs, rt, cc, 1);
11416 break;
11417 case FMT_SDPS_PS:
11418 gen_movcf_ps(rs, rt, cc, 1);
11419 break;
11420 default:
11421 goto pool32f_invalid;
11422 }
11423 break;
11424 case PREFX:
11425 break;
11426 default:
11427 goto pool32f_invalid;
11428 }
11429 break;
11430#define FINSN_3ARG_SDPS(prfx) \
11431 switch ((ctx->opcode >> 8) & 0x3) { \
11432 case FMT_SDPS_S: \
11433 mips32_op = OPC_##prfx##_S; \
11434 goto do_fpop; \
11435 case FMT_SDPS_D: \
11436 mips32_op = OPC_##prfx##_D; \
11437 goto do_fpop; \
11438 case FMT_SDPS_PS: \
11439 mips32_op = OPC_##prfx##_PS; \
11440 goto do_fpop; \
11441 default: \
11442 goto pool32f_invalid; \
11443 }
11444 case 0x30:
11445 /* regular FP ops */
11446 switch ((ctx->opcode >> 6) & 0x3) {
11447 case ADD_FMT:
11448 FINSN_3ARG_SDPS(ADD);
11449 break;
11450 case SUB_FMT:
11451 FINSN_3ARG_SDPS(SUB);
11452 break;
11453 case MUL_FMT:
11454 FINSN_3ARG_SDPS(MUL);
11455 break;
11456 case DIV_FMT:
11457 fmt = (ctx->opcode >> 8) & 0x3;
11458 if (fmt == 1) {
11459 mips32_op = OPC_DIV_D;
11460 } else if (fmt == 0) {
11461 mips32_op = OPC_DIV_S;
11462 } else {
11463 goto pool32f_invalid;
11464 }
11465 goto do_fpop;
11466 default:
11467 goto pool32f_invalid;
11468 }
11469 break;
11470 case 0x38:
11471 /* cmovs */
11472 switch ((ctx->opcode >> 6) & 0x3) {
11473 case MOVN_FMT:
11474 FINSN_3ARG_SDPS(MOVN);
11475 break;
11476 case MOVZ_FMT:
11477 FINSN_3ARG_SDPS(MOVZ);
11478 break;
11479 default:
11480 goto pool32f_invalid;
11481 }
11482 break;
11483 do_fpop:
11484 gen_farith(ctx, mips32_op, rt, rs, rd, 0);
11485 break;
11486 default:
11487 pool32f_invalid:
11488 MIPS_INVAL("pool32f");
11489 generate_exception(ctx, EXCP_RI);
11490 break;
11491 }
11492 } else {
11493 generate_exception_err(ctx, EXCP_CpU, 1);
11494 }
11495 break;
11496 case POOL32I:
11497 minor = (ctx->opcode >> 21) & 0x1f;
11498 switch (minor) {
11499 case BLTZ:
11500 mips32_op = OPC_BLTZ;
11501 goto do_branch;
11502 case BLTZAL:
11503 mips32_op = OPC_BLTZAL;
11504 goto do_branch;
11505 case BLTZALS:
11506 mips32_op = OPC_BLTZALS;
11507 goto do_branch;
11508 case BGEZ:
11509 mips32_op = OPC_BGEZ;
11510 goto do_branch;
11511 case BGEZAL:
11512 mips32_op = OPC_BGEZAL;
11513 goto do_branch;
11514 case BGEZALS:
11515 mips32_op = OPC_BGEZALS;
11516 goto do_branch;
11517 case BLEZ:
11518 mips32_op = OPC_BLEZ;
11519 goto do_branch;
11520 case BGTZ:
11521 mips32_op = OPC_BGTZ;
11522 do_branch:
11523 gen_compute_branch(ctx, mips32_op, 4, rs, -1, imm << 1);
11524 *is_branch = 1;
11525 break;
11526
11527 /* Traps */
11528 case TLTI:
11529 mips32_op = OPC_TLTI;
11530 goto do_trapi;
11531 case TGEI:
11532 mips32_op = OPC_TGEI;
11533 goto do_trapi;
11534 case TLTIU:
11535 mips32_op = OPC_TLTIU;
11536 goto do_trapi;
11537 case TGEIU:
11538 mips32_op = OPC_TGEIU;
11539 goto do_trapi;
11540 case TNEI:
11541 mips32_op = OPC_TNEI;
11542 goto do_trapi;
11543 case TEQI:
11544 mips32_op = OPC_TEQI;
11545 do_trapi:
11546 gen_trap(ctx, mips32_op, rs, -1, imm);
11547 break;
11548
11549 case BNEZC:
11550 case BEQZC:
11551 gen_compute_branch(ctx, minor == BNEZC ? OPC_BNE : OPC_BEQ,
11552 4, rs, 0, imm << 1);
11553 /* Compact branches don't have a delay slot, so just let
11554 the normal delay slot handling take us to the branch
11555 target. */
11556 break;
11557 case LUI:
9fa77488 11558 gen_logic_imm(env, ctx, OPC_LUI, rs, -1, imm);
3c824109
NF
11559 break;
11560 case SYNCI:
11561 break;
11562 case BC2F:
11563 case BC2T:
11564 /* COP2: Not implemented. */
11565 generate_exception_err(ctx, EXCP_CpU, 2);
11566 break;
11567 case BC1F:
11568 mips32_op = (ctx->opcode & (1 << 16)) ? OPC_BC1FANY2 : OPC_BC1F;
11569 goto do_cp1branch;
11570 case BC1T:
11571 mips32_op = (ctx->opcode & (1 << 16)) ? OPC_BC1TANY2 : OPC_BC1T;
11572 goto do_cp1branch;
11573 case BC1ANY4F:
11574 mips32_op = OPC_BC1FANY4;
11575 goto do_cp1mips3d;
11576 case BC1ANY4T:
11577 mips32_op = OPC_BC1TANY4;
11578 do_cp1mips3d:
11579 check_cop1x(ctx);
11580 check_insn(env, ctx, ASE_MIPS3D);
11581 /* Fall through */
11582 do_cp1branch:
11583 gen_compute_branch1(env, ctx, mips32_op,
11584 (ctx->opcode >> 18) & 0x7, imm << 1);
11585 *is_branch = 1;
11586 break;
11587 case BPOSGE64:
11588 case BPOSGE32:
11589 /* MIPS DSP: not implemented */
11590 /* Fall through */
11591 default:
11592 MIPS_INVAL("pool32i");
11593 generate_exception(ctx, EXCP_RI);
11594 break;
11595 }
11596 break;
11597 case POOL32C:
11598 minor = (ctx->opcode >> 12) & 0xf;
11599 switch (minor) {
11600 case LWL:
11601 mips32_op = OPC_LWL;
5c13fdfd 11602 goto do_ld_lr;
3c824109
NF
11603 case SWL:
11604 mips32_op = OPC_SWL;
5c13fdfd 11605 goto do_st_lr;
3c824109
NF
11606 case LWR:
11607 mips32_op = OPC_LWR;
5c13fdfd 11608 goto do_ld_lr;
3c824109
NF
11609 case SWR:
11610 mips32_op = OPC_SWR;
5c13fdfd 11611 goto do_st_lr;
3c824109
NF
11612#if defined(TARGET_MIPS64)
11613 case LDL:
11614 mips32_op = OPC_LDL;
5c13fdfd 11615 goto do_ld_lr;
3c824109
NF
11616 case SDL:
11617 mips32_op = OPC_SDL;
5c13fdfd 11618 goto do_st_lr;
3c824109
NF
11619 case LDR:
11620 mips32_op = OPC_LDR;
5c13fdfd 11621 goto do_ld_lr;
3c824109
NF
11622 case SDR:
11623 mips32_op = OPC_SDR;
5c13fdfd 11624 goto do_st_lr;
3c824109
NF
11625 case LWU:
11626 mips32_op = OPC_LWU;
5c13fdfd 11627 goto do_ld_lr;
3c824109
NF
11628 case LLD:
11629 mips32_op = OPC_LLD;
5c13fdfd 11630 goto do_ld_lr;
3c824109
NF
11631#endif
11632 case LL:
11633 mips32_op = OPC_LL;
5c13fdfd
AJ
11634 goto do_ld_lr;
11635 do_ld_lr:
afa88c3a 11636 gen_ld(env, ctx, mips32_op, rt, rs, SIMM(ctx->opcode, 0, 12));
5c13fdfd
AJ
11637 break;
11638 do_st_lr:
11639 gen_st(ctx, mips32_op, rt, rs, SIMM(ctx->opcode, 0, 12));
3c824109
NF
11640 break;
11641 case SC:
11642 gen_st_cond(ctx, OPC_SC, rt, rs, SIMM(ctx->opcode, 0, 12));
11643 break;
11644#if defined(TARGET_MIPS64)
11645 case SCD:
11646 gen_st_cond(ctx, OPC_SCD, rt, rs, SIMM(ctx->opcode, 0, 12));
11647 break;
11648#endif
11649 case PREF:
11650 /* Treat as no-op */
11651 break;
11652 default:
11653 MIPS_INVAL("pool32c");
11654 generate_exception(ctx, EXCP_RI);
11655 break;
11656 }
11657 break;
11658 case ADDI32:
11659 mips32_op = OPC_ADDI;
11660 goto do_addi;
11661 case ADDIU32:
11662 mips32_op = OPC_ADDIU;
11663 do_addi:
11664 gen_arith_imm(env, ctx, mips32_op, rt, rs, imm);
11665 break;
11666
11667 /* Logical operations */
11668 case ORI32:
11669 mips32_op = OPC_ORI;
11670 goto do_logici;
11671 case XORI32:
11672 mips32_op = OPC_XORI;
11673 goto do_logici;
11674 case ANDI32:
11675 mips32_op = OPC_ANDI;
11676 do_logici:
9fa77488 11677 gen_logic_imm(env, ctx, mips32_op, rt, rs, imm);
3c824109
NF
11678 break;
11679
11680 /* Set less than immediate */
11681 case SLTI32:
11682 mips32_op = OPC_SLTI;
11683 goto do_slti;
11684 case SLTIU32:
11685 mips32_op = OPC_SLTIU;
11686 do_slti:
9fa77488 11687 gen_slt_imm(env, ctx, mips32_op, rt, rs, imm);
3c824109
NF
11688 break;
11689 case JALX32:
11690 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2;
11691 gen_compute_branch(ctx, OPC_JALX, 4, rt, rs, offset);
11692 *is_branch = 1;
11693 break;
11694 case JALS32:
11695 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 1;
11696 gen_compute_branch(ctx, OPC_JALS, 4, rt, rs, offset);
11697 *is_branch = 1;
11698 break;
11699 case BEQ32:
11700 gen_compute_branch(ctx, OPC_BEQ, 4, rt, rs, imm << 1);
11701 *is_branch = 1;
11702 break;
11703 case BNE32:
11704 gen_compute_branch(ctx, OPC_BNE, 4, rt, rs, imm << 1);
11705 *is_branch = 1;
11706 break;
11707 case J32:
11708 gen_compute_branch(ctx, OPC_J, 4, rt, rs,
11709 (int32_t)(ctx->opcode & 0x3FFFFFF) << 1);
11710 *is_branch = 1;
11711 break;
11712 case JAL32:
11713 gen_compute_branch(ctx, OPC_JAL, 4, rt, rs,
11714 (int32_t)(ctx->opcode & 0x3FFFFFF) << 1);
11715 *is_branch = 1;
11716 break;
11717 /* Floating point (COP1) */
11718 case LWC132:
11719 mips32_op = OPC_LWC1;
11720 goto do_cop1;
11721 case LDC132:
11722 mips32_op = OPC_LDC1;
11723 goto do_cop1;
11724 case SWC132:
11725 mips32_op = OPC_SWC1;
11726 goto do_cop1;
11727 case SDC132:
11728 mips32_op = OPC_SDC1;
11729 do_cop1:
11730 gen_cop1_ldst(env, ctx, mips32_op, rt, rs, imm);
11731 break;
11732 case ADDIUPC:
11733 {
11734 int reg = mmreg(ZIMM(ctx->opcode, 23, 3));
11735 int offset = SIMM(ctx->opcode, 0, 23) << 2;
11736
11737 gen_addiupc(ctx, reg, offset, 0, 0);
11738 }
11739 break;
11740 /* Loads and stores */
11741 case LB32:
11742 mips32_op = OPC_LB;
5c13fdfd 11743 goto do_ld;
3c824109
NF
11744 case LBU32:
11745 mips32_op = OPC_LBU;
5c13fdfd 11746 goto do_ld;
3c824109
NF
11747 case LH32:
11748 mips32_op = OPC_LH;
5c13fdfd 11749 goto do_ld;
3c824109
NF
11750 case LHU32:
11751 mips32_op = OPC_LHU;
5c13fdfd 11752 goto do_ld;
3c824109
NF
11753 case LW32:
11754 mips32_op = OPC_LW;
5c13fdfd 11755 goto do_ld;
3c824109
NF
11756#ifdef TARGET_MIPS64
11757 case LD32:
11758 mips32_op = OPC_LD;
5c13fdfd 11759 goto do_ld;
3c824109
NF
11760 case SD32:
11761 mips32_op = OPC_SD;
5c13fdfd 11762 goto do_st;
3c824109
NF
11763#endif
11764 case SB32:
11765 mips32_op = OPC_SB;
5c13fdfd 11766 goto do_st;
3c824109
NF
11767 case SH32:
11768 mips32_op = OPC_SH;
5c13fdfd 11769 goto do_st;
3c824109
NF
11770 case SW32:
11771 mips32_op = OPC_SW;
5c13fdfd
AJ
11772 goto do_st;
11773 do_ld:
afa88c3a 11774 gen_ld(env, ctx, mips32_op, rt, rs, imm);
5c13fdfd
AJ
11775 break;
11776 do_st:
11777 gen_st(ctx, mips32_op, rt, rs, imm);
3c824109
NF
11778 break;
11779 default:
11780 generate_exception(ctx, EXCP_RI);
11781 break;
11782 }
11783}
11784
7db13fae 11785static int decode_micromips_opc (CPUMIPSState *env, DisasContext *ctx, int *is_branch)
3c824109
NF
11786{
11787 uint32_t op;
11788
11789 /* make sure instructions are on a halfword boundary */
11790 if (ctx->pc & 0x1) {
11791 env->CP0_BadVAddr = ctx->pc;
11792 generate_exception(ctx, EXCP_AdEL);
11793 ctx->bstate = BS_STOP;
11794 return 2;
11795 }
11796
11797 op = (ctx->opcode >> 10) & 0x3f;
11798 /* Enforce properly-sized instructions in a delay slot */
11799 if (ctx->hflags & MIPS_HFLAG_BMASK) {
11800 int bits = ctx->hflags & MIPS_HFLAG_BMASK_EXT;
11801
11802 switch (op) {
11803 case POOL32A:
11804 case POOL32B:
11805 case POOL32I:
11806 case POOL32C:
11807 case ADDI32:
11808 case ADDIU32:
11809 case ORI32:
11810 case XORI32:
11811 case SLTI32:
11812 case SLTIU32:
11813 case ANDI32:
11814 case JALX32:
11815 case LBU32:
11816 case LHU32:
11817 case POOL32F:
11818 case JALS32:
11819 case BEQ32:
11820 case BNE32:
11821 case J32:
11822 case JAL32:
11823 case SB32:
11824 case SH32:
11825 case POOL32S:
11826 case ADDIUPC:
11827 case SWC132:
11828 case SDC132:
11829 case SD32:
11830 case SW32:
11831 case LB32:
11832 case LH32:
11833 case DADDIU32:
11834 case POOL48A: /* ??? */
11835 case LWC132:
11836 case LDC132:
11837 case LD32:
11838 case LW32:
11839 if (bits & MIPS_HFLAG_BDS16) {
11840 generate_exception(ctx, EXCP_RI);
11841 /* Just stop translation; the user is confused. */
11842 ctx->bstate = BS_STOP;
11843 return 2;
11844 }
11845 break;
11846 case POOL16A:
11847 case POOL16B:
11848 case POOL16C:
11849 case LWGP16:
11850 case POOL16F:
11851 case LBU16:
11852 case LHU16:
11853 case LWSP16:
11854 case LW16:
11855 case SB16:
11856 case SH16:
11857 case SWSP16:
11858 case SW16:
11859 case MOVE16:
11860 case ANDI16:
11861 case POOL16D:
11862 case POOL16E:
11863 case BEQZ16:
11864 case BNEZ16:
11865 case B16:
11866 case LI16:
11867 if (bits & MIPS_HFLAG_BDS32) {
11868 generate_exception(ctx, EXCP_RI);
11869 /* Just stop translation; the user is confused. */
11870 ctx->bstate = BS_STOP;
11871 return 2;
11872 }
11873 break;
11874 default:
11875 break;
11876 }
11877 }
11878 switch (op) {
11879 case POOL16A:
11880 {
11881 int rd = mmreg(uMIPS_RD(ctx->opcode));
11882 int rs1 = mmreg(uMIPS_RS1(ctx->opcode));
11883 int rs2 = mmreg(uMIPS_RS2(ctx->opcode));
11884 uint32_t opc = 0;
11885
11886 switch (ctx->opcode & 0x1) {
11887 case ADDU16:
11888 opc = OPC_ADDU;
11889 break;
11890 case SUBU16:
11891 opc = OPC_SUBU;
11892 break;
11893 }
11894
11895 gen_arith(env, ctx, opc, rd, rs1, rs2);
11896 }
11897 break;
11898 case POOL16B:
11899 {
11900 int rd = mmreg(uMIPS_RD(ctx->opcode));
11901 int rs = mmreg(uMIPS_RS(ctx->opcode));
11902 int amount = (ctx->opcode >> 1) & 0x7;
11903 uint32_t opc = 0;
11904 amount = amount == 0 ? 8 : amount;
11905
11906 switch (ctx->opcode & 0x1) {
11907 case SLL16:
11908 opc = OPC_SLL;
11909 break;
11910 case SRL16:
11911 opc = OPC_SRL;
11912 break;
11913 }
11914
11915 gen_shift_imm(env, ctx, opc, rd, rs, amount);
11916 }
11917 break;
11918 case POOL16C:
11919 gen_pool16c_insn(env, ctx, is_branch);
11920 break;
11921 case LWGP16:
11922 {
11923 int rd = mmreg(uMIPS_RD(ctx->opcode));
11924 int rb = 28; /* GP */
11925 int16_t offset = SIMM(ctx->opcode, 0, 7) << 2;
11926
afa88c3a 11927 gen_ld(env, ctx, OPC_LW, rd, rb, offset);
3c824109
NF
11928 }
11929 break;
11930 case POOL16F:
11931 if (ctx->opcode & 1) {
11932 generate_exception(ctx, EXCP_RI);
11933 } else {
11934 /* MOVEP */
11935 int enc_dest = uMIPS_RD(ctx->opcode);
11936 int enc_rt = uMIPS_RS2(ctx->opcode);
11937 int enc_rs = uMIPS_RS1(ctx->opcode);
11938 int rd, rs, re, rt;
11939 static const int rd_enc[] = { 5, 5, 6, 4, 4, 4, 4, 4 };
11940 static const int re_enc[] = { 6, 7, 7, 21, 22, 5, 6, 7 };
11941 static const int rs_rt_enc[] = { 0, 17, 2, 3, 16, 18, 19, 20 };
11942
11943 rd = rd_enc[enc_dest];
11944 re = re_enc[enc_dest];
11945 rs = rs_rt_enc[enc_rs];
11946 rt = rs_rt_enc[enc_rt];
11947
11948 gen_arith_imm(env, ctx, OPC_ADDIU, rd, rs, 0);
11949 gen_arith_imm(env, ctx, OPC_ADDIU, re, rt, 0);
11950 }
11951 break;
11952 case LBU16:
11953 {
11954 int rd = mmreg(uMIPS_RD(ctx->opcode));
11955 int rb = mmreg(uMIPS_RS(ctx->opcode));
11956 int16_t offset = ZIMM(ctx->opcode, 0, 4);
11957 offset = (offset == 0xf ? -1 : offset);
11958
afa88c3a 11959 gen_ld(env, ctx, OPC_LBU, rd, rb, offset);
3c824109
NF
11960 }
11961 break;
11962 case LHU16:
11963 {
11964 int rd = mmreg(uMIPS_RD(ctx->opcode));
11965 int rb = mmreg(uMIPS_RS(ctx->opcode));
11966 int16_t offset = ZIMM(ctx->opcode, 0, 4) << 1;
11967
afa88c3a 11968 gen_ld(env, ctx, OPC_LHU, rd, rb, offset);
3c824109
NF
11969 }
11970 break;
11971 case LWSP16:
11972 {
11973 int rd = (ctx->opcode >> 5) & 0x1f;
11974 int rb = 29; /* SP */
11975 int16_t offset = ZIMM(ctx->opcode, 0, 5) << 2;
11976
afa88c3a 11977 gen_ld(env, ctx, OPC_LW, rd, rb, offset);
3c824109
NF
11978 }
11979 break;
11980 case LW16:
11981 {
11982 int rd = mmreg(uMIPS_RD(ctx->opcode));
11983 int rb = mmreg(uMIPS_RS(ctx->opcode));
11984 int16_t offset = ZIMM(ctx->opcode, 0, 4) << 2;
11985
afa88c3a 11986 gen_ld(env, ctx, OPC_LW, rd, rb, offset);
3c824109
NF
11987 }
11988 break;
11989 case SB16:
11990 {
11991 int rd = mmreg2(uMIPS_RD(ctx->opcode));
11992 int rb = mmreg(uMIPS_RS(ctx->opcode));
11993 int16_t offset = ZIMM(ctx->opcode, 0, 4);
11994
5c13fdfd 11995 gen_st(ctx, OPC_SB, rd, rb, offset);
3c824109
NF
11996 }
11997 break;
11998 case SH16:
11999 {
12000 int rd = mmreg2(uMIPS_RD(ctx->opcode));
12001 int rb = mmreg(uMIPS_RS(ctx->opcode));
12002 int16_t offset = ZIMM(ctx->opcode, 0, 4) << 1;
12003
5c13fdfd 12004 gen_st(ctx, OPC_SH, rd, rb, offset);
3c824109
NF
12005 }
12006 break;
12007 case SWSP16:
12008 {
12009 int rd = (ctx->opcode >> 5) & 0x1f;
12010 int rb = 29; /* SP */
12011 int16_t offset = ZIMM(ctx->opcode, 0, 5) << 2;
12012
5c13fdfd 12013 gen_st(ctx, OPC_SW, rd, rb, offset);
3c824109
NF
12014 }
12015 break;
12016 case SW16:
12017 {
12018 int rd = mmreg2(uMIPS_RD(ctx->opcode));
12019 int rb = mmreg(uMIPS_RS(ctx->opcode));
12020 int16_t offset = ZIMM(ctx->opcode, 0, 4) << 2;
12021
5c13fdfd 12022 gen_st(ctx, OPC_SW, rd, rb, offset);
3c824109
NF
12023 }
12024 break;
12025 case MOVE16:
12026 {
12027 int rd = uMIPS_RD5(ctx->opcode);
12028 int rs = uMIPS_RS5(ctx->opcode);
12029
12030 gen_arith_imm(env, ctx, OPC_ADDIU, rd, rs, 0);
12031 }
12032 break;
12033 case ANDI16:
12034 gen_andi16(env, ctx);
12035 break;
12036 case POOL16D:
12037 switch (ctx->opcode & 0x1) {
12038 case ADDIUS5:
12039 gen_addius5(env, ctx);
12040 break;
12041 case ADDIUSP:
12042 gen_addiusp(env, ctx);
12043 break;
12044 }
12045 break;
12046 case POOL16E:
12047 switch (ctx->opcode & 0x1) {
12048 case ADDIUR2:
12049 gen_addiur2(env, ctx);
12050 break;
12051 case ADDIUR1SP:
12052 gen_addiur1sp(env, ctx);
12053 break;
12054 }
12055 break;
12056 case B16:
12057 gen_compute_branch(ctx, OPC_BEQ, 2, 0, 0,
12058 SIMM(ctx->opcode, 0, 10) << 1);
12059 *is_branch = 1;
12060 break;
12061 case BNEZ16:
12062 case BEQZ16:
12063 gen_compute_branch(ctx, op == BNEZ16 ? OPC_BNE : OPC_BEQ, 2,
12064 mmreg(uMIPS_RD(ctx->opcode)),
12065 0, SIMM(ctx->opcode, 0, 7) << 1);
12066 *is_branch = 1;
12067 break;
12068 case LI16:
12069 {
12070 int reg = mmreg(uMIPS_RD(ctx->opcode));
12071 int imm = ZIMM(ctx->opcode, 0, 7);
12072
12073 imm = (imm == 0x7f ? -1 : imm);
12074 tcg_gen_movi_tl(cpu_gpr[reg], imm);
12075 }
12076 break;
12077 case RES_20:
12078 case RES_28:
12079 case RES_29:
12080 case RES_30:
12081 case RES_31:
12082 case RES_38:
12083 case RES_39:
12084 generate_exception(ctx, EXCP_RI);
12085 break;
12086 default:
12087 decode_micromips32_opc (env, ctx, op, is_branch);
12088 return 4;
12089 }
12090
12091 return 2;
12092}
12093
12094/* SmartMIPS extension to MIPS32 */
12095
12096#if defined(TARGET_MIPS64)
12097
12098/* MDMX extension to MIPS64 */
12099
12100#endif
12101
7db13fae 12102static void decode_opc (CPUMIPSState *env, DisasContext *ctx, int *is_branch)
3c824109
NF
12103{
12104 int32_t offset;
12105 int rs, rt, rd, sa;
12106 uint32_t op, op1, op2;
12107 int16_t imm;
12108
12109 /* make sure instructions are on a word boundary */
12110 if (ctx->pc & 0x3) {
12111 env->CP0_BadVAddr = ctx->pc;
12112 generate_exception(ctx, EXCP_AdEL);
12113 return;
12114 }
12115
12116 /* Handle blikely not taken case */
12117 if ((ctx->hflags & MIPS_HFLAG_BMASK_BASE) == MIPS_HFLAG_BL) {
12118 int l1 = gen_new_label();
12119
12120 MIPS_DEBUG("blikely condition (" TARGET_FMT_lx ")", ctx->pc + 4);
12121 tcg_gen_brcondi_tl(TCG_COND_NE, bcond, 0, l1);
12122 tcg_gen_movi_i32(hflags, ctx->hflags & ~MIPS_HFLAG_BMASK);
12123 gen_goto_tb(ctx, 1, ctx->pc + 4);
12124 gen_set_label(l1);
12125 }
12126
fdefe51c 12127 if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP | CPU_LOG_TB_OP_OPT))) {
3c824109 12128 tcg_gen_debug_insn_start(ctx->pc);
fdefe51c 12129 }
3c824109
NF
12130
12131 op = MASK_OP_MAJOR(ctx->opcode);
12132 rs = (ctx->opcode >> 21) & 0x1f;
12133 rt = (ctx->opcode >> 16) & 0x1f;
12134 rd = (ctx->opcode >> 11) & 0x1f;
12135 sa = (ctx->opcode >> 6) & 0x1f;
12136 imm = (int16_t)ctx->opcode;
12137 switch (op) {
7a387fff
TS
12138 case OPC_SPECIAL:
12139 op1 = MASK_SPECIAL(ctx->opcode);
6af0bf9c 12140 switch (op1) {
324d9e32
AJ
12141 case OPC_SLL: /* Shift with immediate */
12142 case OPC_SRA:
324d9e32 12143 gen_shift_imm(env, ctx, op1, rd, rt, sa);
7a387fff 12144 break;
ea63e2c3
NF
12145 case OPC_SRL:
12146 switch ((ctx->opcode >> 21) & 0x1f) {
12147 case 1:
12148 /* rotr is decoded as srl on non-R2 CPUs */
12149 if (env->insn_flags & ISA_MIPS32R2) {
12150 op1 = OPC_ROTR;
12151 }
12152 /* Fallthrough */
12153 case 0:
12154 gen_shift_imm(env, ctx, op1, rd, rt, sa);
12155 break;
12156 default:
12157 generate_exception(ctx, EXCP_RI);
12158 break;
12159 }
12160 break;
460f00c4
AJ
12161 case OPC_MOVN: /* Conditional move */
12162 case OPC_MOVZ:
aa8f4009
AJ
12163 check_insn(env, ctx, ISA_MIPS4 | ISA_MIPS32 |
12164 INSN_LOONGSON2E | INSN_LOONGSON2F);
9fa77488 12165 gen_cond_move(env, ctx, op1, rd, rs, rt);
460f00c4
AJ
12166 break;
12167 case OPC_ADD ... OPC_SUBU:
e189e748 12168 gen_arith(env, ctx, op1, rd, rs, rt);
7a387fff 12169 break;
460f00c4 12170 case OPC_SLLV: /* Shifts */
460f00c4
AJ
12171 case OPC_SRAV:
12172 gen_shift(env, ctx, op1, rd, rs, rt);
12173 break;
ea63e2c3
NF
12174 case OPC_SRLV:
12175 switch ((ctx->opcode >> 6) & 0x1f) {
12176 case 1:
12177 /* rotrv is decoded as srlv on non-R2 CPUs */
12178 if (env->insn_flags & ISA_MIPS32R2) {
12179 op1 = OPC_ROTRV;
12180 }
12181 /* Fallthrough */
12182 case 0:
12183 gen_shift(env, ctx, op1, rd, rs, rt);
12184 break;
12185 default:
12186 generate_exception(ctx, EXCP_RI);
12187 break;
12188 }
12189 break;
460f00c4
AJ
12190 case OPC_SLT: /* Set on less than */
12191 case OPC_SLTU:
9fa77488 12192 gen_slt(env, ctx, op1, rd, rs, rt);
460f00c4
AJ
12193 break;
12194 case OPC_AND: /* Logic*/
12195 case OPC_OR:
12196 case OPC_NOR:
12197 case OPC_XOR:
9fa77488 12198 gen_logic(env, ctx, op1, rd, rs, rt);
460f00c4 12199 break;
7a387fff 12200 case OPC_MULT ... OPC_DIVU:
e9c71dd1
TS
12201 if (sa) {
12202 check_insn(env, ctx, INSN_VR54XX);
12203 op1 = MASK_MUL_VR54XX(ctx->opcode);
12204 gen_mul_vr54xx(ctx, op1, rd, rs, rt);
12205 } else
12206 gen_muldiv(ctx, op1, rs, rt);
7a387fff
TS
12207 break;
12208 case OPC_JR ... OPC_JALR:
7dca4ad0 12209 gen_compute_branch(ctx, op1, 4, rs, rd, sa);
c9602061
NF
12210 *is_branch = 1;
12211 break;
7a387fff
TS
12212 case OPC_TGE ... OPC_TEQ: /* Traps */
12213 case OPC_TNE:
12214 gen_trap(ctx, op1, rs, rt, -1);
6af0bf9c 12215 break;
7a387fff
TS
12216 case OPC_MFHI: /* Move from HI/LO */
12217 case OPC_MFLO:
12218 gen_HILO(ctx, op1, rd);
6af0bf9c 12219 break;
7a387fff
TS
12220 case OPC_MTHI:
12221 case OPC_MTLO: /* Move to HI/LO */
12222 gen_HILO(ctx, op1, rs);
6af0bf9c 12223 break;
b48cfdff
TS
12224 case OPC_PMON: /* Pmon entry point, also R4010 selsl */
12225#ifdef MIPS_STRICT_STANDARD
12226 MIPS_INVAL("PMON / selsl");
12227 generate_exception(ctx, EXCP_RI);
12228#else
895c2d04 12229 gen_helper_0e0i(pmon, sa);
b48cfdff 12230#endif
7a387fff
TS
12231 break;
12232 case OPC_SYSCALL:
6af0bf9c 12233 generate_exception(ctx, EXCP_SYSCALL);
8e0f950d 12234 ctx->bstate = BS_STOP;
6af0bf9c 12235 break;
7a387fff 12236 case OPC_BREAK:
6af0bf9c
FB
12237 generate_exception(ctx, EXCP_BREAK);
12238 break;
b48cfdff
TS
12239 case OPC_SPIM:
12240#ifdef MIPS_STRICT_STANDARD
12241 MIPS_INVAL("SPIM");
12242 generate_exception(ctx, EXCP_RI);
12243#else
7a387fff
TS
12244 /* Implemented as RI exception for now. */
12245 MIPS_INVAL("spim (unofficial)");
12246 generate_exception(ctx, EXCP_RI);
b48cfdff 12247#endif
6af0bf9c 12248 break;
7a387fff 12249 case OPC_SYNC:
ead9360e 12250 /* Treat as NOP. */
6af0bf9c 12251 break;
4ad40f36 12252
7a387fff 12253 case OPC_MOVCI:
e189e748 12254 check_insn(env, ctx, ISA_MIPS4 | ISA_MIPS32);
36d23958 12255 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
5e755519 12256 check_cp1_enabled(ctx);
36d23958
TS
12257 gen_movci(ctx, rd, rs, (ctx->opcode >> 18) & 0x7,
12258 (ctx->opcode >> 16) & 1);
12259 } else {
e397ee33 12260 generate_exception_err(ctx, EXCP_CpU, 1);
36d23958 12261 }
4ad40f36
FB
12262 break;
12263
d26bc211 12264#if defined(TARGET_MIPS64)
7a387fff
TS
12265 /* MIPS64 specific opcodes */
12266 case OPC_DSLL:
324d9e32 12267 case OPC_DSRA:
7a387fff 12268 case OPC_DSLL32:
324d9e32 12269 case OPC_DSRA32:
e189e748
TS
12270 check_insn(env, ctx, ISA_MIPS3);
12271 check_mips_64(ctx);
324d9e32 12272 gen_shift_imm(env, ctx, op1, rd, rt, sa);
7a387fff 12273 break;
ea63e2c3
NF
12274 case OPC_DSRL:
12275 switch ((ctx->opcode >> 21) & 0x1f) {
12276 case 1:
12277 /* drotr is decoded as dsrl on non-R2 CPUs */
12278 if (env->insn_flags & ISA_MIPS32R2) {
12279 op1 = OPC_DROTR;
12280 }
12281 /* Fallthrough */
12282 case 0:
12283 check_insn(env, ctx, ISA_MIPS3);
12284 check_mips_64(ctx);
12285 gen_shift_imm(env, ctx, op1, rd, rt, sa);
12286 break;
12287 default:
12288 generate_exception(ctx, EXCP_RI);
12289 break;
12290 }
12291 break;
12292 case OPC_DSRL32:
12293 switch ((ctx->opcode >> 21) & 0x1f) {
12294 case 1:
12295 /* drotr32 is decoded as dsrl32 on non-R2 CPUs */
12296 if (env->insn_flags & ISA_MIPS32R2) {
12297 op1 = OPC_DROTR32;
12298 }
12299 /* Fallthrough */
12300 case 0:
12301 check_insn(env, ctx, ISA_MIPS3);
12302 check_mips_64(ctx);
12303 gen_shift_imm(env, ctx, op1, rd, rt, sa);
12304 break;
12305 default:
12306 generate_exception(ctx, EXCP_RI);
12307 break;
12308 }
12309 break;
7a387fff 12310 case OPC_DADD ... OPC_DSUBU:
e189e748
TS
12311 check_insn(env, ctx, ISA_MIPS3);
12312 check_mips_64(ctx);
12313 gen_arith(env, ctx, op1, rd, rs, rt);
7a387fff 12314 break;
460f00c4
AJ
12315 case OPC_DSLLV:
12316 case OPC_DSRAV:
460f00c4
AJ
12317 check_insn(env, ctx, ISA_MIPS3);
12318 check_mips_64(ctx);
12319 gen_shift(env, ctx, op1, rd, rs, rt);
12320 break;
ea63e2c3
NF
12321 case OPC_DSRLV:
12322 switch ((ctx->opcode >> 6) & 0x1f) {
12323 case 1:
12324 /* drotrv is decoded as dsrlv on non-R2 CPUs */
12325 if (env->insn_flags & ISA_MIPS32R2) {
12326 op1 = OPC_DROTRV;
12327 }
12328 /* Fallthrough */
12329 case 0:
12330 check_insn(env, ctx, ISA_MIPS3);
12331 check_mips_64(ctx);
12332 gen_shift(env, ctx, op1, rd, rs, rt);
12333 break;
12334 default:
12335 generate_exception(ctx, EXCP_RI);
12336 break;
12337 }
12338 break;
7a387fff 12339 case OPC_DMULT ... OPC_DDIVU:
e189e748
TS
12340 check_insn(env, ctx, ISA_MIPS3);
12341 check_mips_64(ctx);
7a387fff
TS
12342 gen_muldiv(ctx, op1, rs, rt);
12343 break;
6af0bf9c
FB
12344#endif
12345 default: /* Invalid */
12346 MIPS_INVAL("special");
12347 generate_exception(ctx, EXCP_RI);
12348 break;
12349 }
12350 break;
7a387fff
TS
12351 case OPC_SPECIAL2:
12352 op1 = MASK_SPECIAL2(ctx->opcode);
6af0bf9c 12353 switch (op1) {
7a387fff
TS
12354 case OPC_MADD ... OPC_MADDU: /* Multiply and add/sub */
12355 case OPC_MSUB ... OPC_MSUBU:
e189e748 12356 check_insn(env, ctx, ISA_MIPS32);
7a387fff 12357 gen_muldiv(ctx, op1, rs, rt);
6af0bf9c 12358 break;
7a387fff 12359 case OPC_MUL:
e189e748 12360 gen_arith(env, ctx, op1, rd, rs, rt);
6af0bf9c 12361 break;
20e1fb52
AJ
12362 case OPC_CLO:
12363 case OPC_CLZ:
e189e748 12364 check_insn(env, ctx, ISA_MIPS32);
7a387fff 12365 gen_cl(ctx, op1, rd, rs);
6af0bf9c 12366 break;
7a387fff 12367 case OPC_SDBBP:
6af0bf9c
FB
12368 /* XXX: not clear which exception should be raised
12369 * when in debug mode...
12370 */
e189e748 12371 check_insn(env, ctx, ISA_MIPS32);
6af0bf9c
FB
12372 if (!(ctx->hflags & MIPS_HFLAG_DM)) {
12373 generate_exception(ctx, EXCP_DBp);
12374 } else {
12375 generate_exception(ctx, EXCP_DBp);
12376 }
ead9360e 12377 /* Treat as NOP. */
6af0bf9c 12378 break;
161f85e6
AJ
12379 case OPC_DIV_G_2F:
12380 case OPC_DIVU_G_2F:
12381 case OPC_MULT_G_2F:
12382 case OPC_MULTU_G_2F:
12383 case OPC_MOD_G_2F:
12384 case OPC_MODU_G_2F:
12385 check_insn(env, ctx, INSN_LOONGSON2F);
12386 gen_loongson_integer(ctx, op1, rd, rs, rt);
12387 break;
d26bc211 12388#if defined(TARGET_MIPS64)
20e1fb52
AJ
12389 case OPC_DCLO:
12390 case OPC_DCLZ:
e189e748
TS
12391 check_insn(env, ctx, ISA_MIPS64);
12392 check_mips_64(ctx);
7a387fff
TS
12393 gen_cl(ctx, op1, rd, rs);
12394 break;
161f85e6
AJ
12395 case OPC_DMULT_G_2F:
12396 case OPC_DMULTU_G_2F:
12397 case OPC_DDIV_G_2F:
12398 case OPC_DDIVU_G_2F:
12399 case OPC_DMOD_G_2F:
12400 case OPC_DMODU_G_2F:
12401 check_insn(env, ctx, INSN_LOONGSON2F);
12402 gen_loongson_integer(ctx, op1, rd, rs, rt);
12403 break;
7a387fff 12404#endif
6af0bf9c
FB
12405 default: /* Invalid */
12406 MIPS_INVAL("special2");
12407 generate_exception(ctx, EXCP_RI);
12408 break;
12409 }
12410 break;
7a387fff 12411 case OPC_SPECIAL3:
2b0233ab
TS
12412 op1 = MASK_SPECIAL3(ctx->opcode);
12413 switch (op1) {
12414 case OPC_EXT:
12415 case OPC_INS:
12416 check_insn(env, ctx, ISA_MIPS32R2);
12417 gen_bitops(ctx, op1, rt, rs, sa, rd);
12418 break;
12419 case OPC_BSHFL:
12420 check_insn(env, ctx, ISA_MIPS32R2);
12421 op2 = MASK_BSHFL(ctx->opcode);
49bcf33c 12422 gen_bshfl(ctx, op2, rt, rd);
7a387fff 12423 break;
1579a72e 12424 case OPC_RDHWR:
26ebe468 12425 gen_rdhwr(env, ctx, rt, rd);
1579a72e 12426 break;
ead9360e 12427 case OPC_FORK:
7385ac0b 12428 check_insn(env, ctx, ASE_MT);
6c5c1e20 12429 {
35fbce2c
AJ
12430 TCGv t0 = tcg_temp_new();
12431 TCGv t1 = tcg_temp_new();
6c5c1e20
TS
12432
12433 gen_load_gpr(t0, rt);
12434 gen_load_gpr(t1, rs);
a7812ae4 12435 gen_helper_fork(t0, t1);
6c5c1e20
TS
12436 tcg_temp_free(t0);
12437 tcg_temp_free(t1);
12438 }
ead9360e
TS
12439 break;
12440 case OPC_YIELD:
7385ac0b 12441 check_insn(env, ctx, ASE_MT);
6c5c1e20 12442 {
35fbce2c 12443 TCGv t0 = tcg_temp_new();
6c5c1e20 12444
35fbce2c 12445 save_cpu_state(ctx, 1);
6c5c1e20 12446 gen_load_gpr(t0, rs);
895c2d04 12447 gen_helper_yield(t0, cpu_env, t0);
6c5c1e20
TS
12448 gen_store_gpr(t0, rd);
12449 tcg_temp_free(t0);
12450 }
ead9360e 12451 break;
161f85e6
AJ
12452 case OPC_DIV_G_2E ... OPC_DIVU_G_2E:
12453 case OPC_MULT_G_2E ... OPC_MULTU_G_2E:
12454 case OPC_MOD_G_2E ... OPC_MODU_G_2E:
12455 check_insn(env, ctx, INSN_LOONGSON2E);
12456 gen_loongson_integer(ctx, op1, rd, rs, rt);
12457 break;
d26bc211 12458#if defined(TARGET_MIPS64)
1579a72e
TS
12459 case OPC_DEXTM ... OPC_DEXT:
12460 case OPC_DINSM ... OPC_DINS:
e189e748
TS
12461 check_insn(env, ctx, ISA_MIPS64R2);
12462 check_mips_64(ctx);
1579a72e 12463 gen_bitops(ctx, op1, rt, rs, sa, rd);
7a387fff 12464 break;
1579a72e 12465 case OPC_DBSHFL:
e189e748
TS
12466 check_insn(env, ctx, ISA_MIPS64R2);
12467 check_mips_64(ctx);
1579a72e 12468 op2 = MASK_DBSHFL(ctx->opcode);
49bcf33c 12469 gen_bshfl(ctx, op2, rt, rd);
c6d6dd7c 12470 break;
161f85e6
AJ
12471 case OPC_DDIV_G_2E ... OPC_DDIVU_G_2E:
12472 case OPC_DMULT_G_2E ... OPC_DMULTU_G_2E:
12473 case OPC_DMOD_G_2E ... OPC_DMODU_G_2E:
12474 check_insn(env, ctx, INSN_LOONGSON2E);
12475 gen_loongson_integer(ctx, op1, rd, rs, rt);
12476 break;
7a387fff
TS
12477#endif
12478 default: /* Invalid */
12479 MIPS_INVAL("special3");
12480 generate_exception(ctx, EXCP_RI);
12481 break;
12482 }
12483 break;
12484 case OPC_REGIMM:
12485 op1 = MASK_REGIMM(ctx->opcode);
12486 switch (op1) {
12487 case OPC_BLTZ ... OPC_BGEZL: /* REGIMM branches */
12488 case OPC_BLTZAL ... OPC_BGEZALL:
7dca4ad0 12489 gen_compute_branch(ctx, op1, 4, rs, -1, imm << 2);
c9602061
NF
12490 *is_branch = 1;
12491 break;
7a387fff
TS
12492 case OPC_TGEI ... OPC_TEQI: /* REGIMM traps */
12493 case OPC_TNEI:
12494 gen_trap(ctx, op1, rs, -1, imm);
12495 break;
12496 case OPC_SYNCI:
e189e748 12497 check_insn(env, ctx, ISA_MIPS32R2);
ead9360e 12498 /* Treat as NOP. */
6af0bf9c
FB
12499 break;
12500 default: /* Invalid */
923617a3 12501 MIPS_INVAL("regimm");
6af0bf9c
FB
12502 generate_exception(ctx, EXCP_RI);
12503 break;
12504 }
12505 break;
7a387fff 12506 case OPC_CP0:
387a8fe5 12507 check_cp0_enabled(ctx);
7a387fff 12508 op1 = MASK_CP0(ctx->opcode);
6af0bf9c 12509 switch (op1) {
7a387fff
TS
12510 case OPC_MFC0:
12511 case OPC_MTC0:
ead9360e
TS
12512 case OPC_MFTR:
12513 case OPC_MTTR:
d26bc211 12514#if defined(TARGET_MIPS64)
7a387fff
TS
12515 case OPC_DMFC0:
12516 case OPC_DMTC0:
12517#endif
f1aa6320 12518#ifndef CONFIG_USER_ONLY
932e71cd 12519 gen_cp0(env, ctx, op1, rt, rd);
0eaef5aa 12520#endif /* !CONFIG_USER_ONLY */
7a387fff
TS
12521 break;
12522 case OPC_C0_FIRST ... OPC_C0_LAST:
f1aa6320 12523#ifndef CONFIG_USER_ONLY
932e71cd 12524 gen_cp0(env, ctx, MASK_C0(ctx->opcode), rt, rd);
0eaef5aa 12525#endif /* !CONFIG_USER_ONLY */
7a387fff
TS
12526 break;
12527 case OPC_MFMC0:
8706c382 12528#ifndef CONFIG_USER_ONLY
932e71cd 12529 {
35fbce2c 12530 TCGv t0 = tcg_temp_new();
6c5c1e20 12531
0eaef5aa 12532 op2 = MASK_MFMC0(ctx->opcode);
6c5c1e20
TS
12533 switch (op2) {
12534 case OPC_DMT:
12535 check_insn(env, ctx, ASE_MT);
9ed5726c 12536 gen_helper_dmt(t0);
35fbce2c 12537 gen_store_gpr(t0, rt);
6c5c1e20
TS
12538 break;
12539 case OPC_EMT:
12540 check_insn(env, ctx, ASE_MT);
9ed5726c 12541 gen_helper_emt(t0);
35fbce2c 12542 gen_store_gpr(t0, rt);
da80682b 12543 break;
6c5c1e20
TS
12544 case OPC_DVPE:
12545 check_insn(env, ctx, ASE_MT);
895c2d04 12546 gen_helper_dvpe(t0, cpu_env);
35fbce2c 12547 gen_store_gpr(t0, rt);
6c5c1e20
TS
12548 break;
12549 case OPC_EVPE:
12550 check_insn(env, ctx, ASE_MT);
895c2d04 12551 gen_helper_evpe(t0, cpu_env);
35fbce2c 12552 gen_store_gpr(t0, rt);
6c5c1e20
TS
12553 break;
12554 case OPC_DI:
12555 check_insn(env, ctx, ISA_MIPS32R2);
867abc7e 12556 save_cpu_state(ctx, 1);
895c2d04 12557 gen_helper_di(t0, cpu_env);
35fbce2c 12558 gen_store_gpr(t0, rt);
6c5c1e20
TS
12559 /* Stop translation as we may have switched the execution mode */
12560 ctx->bstate = BS_STOP;
12561 break;
12562 case OPC_EI:
12563 check_insn(env, ctx, ISA_MIPS32R2);
867abc7e 12564 save_cpu_state(ctx, 1);
895c2d04 12565 gen_helper_ei(t0, cpu_env);
35fbce2c 12566 gen_store_gpr(t0, rt);
6c5c1e20
TS
12567 /* Stop translation as we may have switched the execution mode */
12568 ctx->bstate = BS_STOP;
12569 break;
12570 default: /* Invalid */
12571 MIPS_INVAL("mfmc0");
12572 generate_exception(ctx, EXCP_RI);
12573 break;
12574 }
6c5c1e20 12575 tcg_temp_free(t0);
7a387fff 12576 }
0eaef5aa 12577#endif /* !CONFIG_USER_ONLY */
6af0bf9c 12578 break;
7a387fff 12579 case OPC_RDPGPR:
e189e748 12580 check_insn(env, ctx, ISA_MIPS32R2);
be24bb4f 12581 gen_load_srsgpr(rt, rd);
ead9360e 12582 break;
7a387fff 12583 case OPC_WRPGPR:
e189e748 12584 check_insn(env, ctx, ISA_MIPS32R2);
be24bb4f 12585 gen_store_srsgpr(rt, rd);
38121543 12586 break;
6af0bf9c 12587 default:
923617a3 12588 MIPS_INVAL("cp0");
7a387fff 12589 generate_exception(ctx, EXCP_RI);
6af0bf9c
FB
12590 break;
12591 }
12592 break;
324d9e32
AJ
12593 case OPC_ADDI: /* Arithmetic with immediate opcode */
12594 case OPC_ADDIU:
e189e748 12595 gen_arith_imm(env, ctx, op, rt, rs, imm);
7a387fff 12596 break;
324d9e32
AJ
12597 case OPC_SLTI: /* Set on less than with immediate opcode */
12598 case OPC_SLTIU:
9fa77488 12599 gen_slt_imm(env, ctx, op, rt, rs, imm);
324d9e32
AJ
12600 break;
12601 case OPC_ANDI: /* Arithmetic with immediate opcode */
12602 case OPC_LUI:
12603 case OPC_ORI:
12604 case OPC_XORI:
9fa77488 12605 gen_logic_imm(env, ctx, op, rt, rs, imm);
324d9e32 12606 break;
7a387fff
TS
12607 case OPC_J ... OPC_JAL: /* Jump */
12608 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2;
7dca4ad0 12609 gen_compute_branch(ctx, op, 4, rs, rt, offset);
c9602061
NF
12610 *is_branch = 1;
12611 break;
7a387fff
TS
12612 case OPC_BEQ ... OPC_BGTZ: /* Branch */
12613 case OPC_BEQL ... OPC_BGTZL:
7dca4ad0 12614 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2);
c9602061
NF
12615 *is_branch = 1;
12616 break;
7a387fff 12617 case OPC_LB ... OPC_LWR: /* Load and stores */
5c13fdfd 12618 case OPC_LL:
afa88c3a 12619 gen_ld(env, ctx, op, rt, rs, imm);
5c13fdfd 12620 break;
7a387fff
TS
12621 case OPC_SB ... OPC_SW:
12622 case OPC_SWR:
5c13fdfd 12623 gen_st(ctx, op, rt, rs, imm);
7a387fff 12624 break;
d66c7132
AJ
12625 case OPC_SC:
12626 gen_st_cond(ctx, op, rt, rs, imm);
12627 break;
7a387fff 12628 case OPC_CACHE:
2e15497c 12629 check_cp0_enabled(ctx);
e189e748 12630 check_insn(env, ctx, ISA_MIPS3 | ISA_MIPS32);
ead9360e 12631 /* Treat as NOP. */
34ae7b51 12632 break;
7a387fff 12633 case OPC_PREF:
e189e748 12634 check_insn(env, ctx, ISA_MIPS4 | ISA_MIPS32);
ead9360e 12635 /* Treat as NOP. */
6af0bf9c 12636 break;
4ad40f36 12637
923617a3 12638 /* Floating point (COP1). */
7a387fff
TS
12639 case OPC_LWC1:
12640 case OPC_LDC1:
12641 case OPC_SWC1:
12642 case OPC_SDC1:
26ebe468 12643 gen_cop1_ldst(env, ctx, op, rt, rs, imm);
6ea83fed
FB
12644 break;
12645
7a387fff 12646 case OPC_CP1:
36d23958 12647 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
5e755519 12648 check_cp1_enabled(ctx);
36d23958
TS
12649 op1 = MASK_CP1(ctx->opcode);
12650 switch (op1) {
3a95e3a7
TS
12651 case OPC_MFHC1:
12652 case OPC_MTHC1:
e189e748 12653 check_insn(env, ctx, ISA_MIPS32R2);
36d23958
TS
12654 case OPC_MFC1:
12655 case OPC_CFC1:
12656 case OPC_MTC1:
12657 case OPC_CTC1:
e189e748
TS
12658 gen_cp1(ctx, op1, rt, rd);
12659 break;
d26bc211 12660#if defined(TARGET_MIPS64)
36d23958
TS
12661 case OPC_DMFC1:
12662 case OPC_DMTC1:
e189e748 12663 check_insn(env, ctx, ISA_MIPS3);
36d23958
TS
12664 gen_cp1(ctx, op1, rt, rd);
12665 break;
e189e748 12666#endif
fbcc6828
TS
12667 case OPC_BC1ANY2:
12668 case OPC_BC1ANY4:
b8aa4598 12669 check_cop1x(ctx);
7385ac0b 12670 check_insn(env, ctx, ASE_MIPS3D);
d8a5950a
TS
12671 /* fall through */
12672 case OPC_BC1:
e189e748 12673 gen_compute_branch1(env, ctx, MASK_BC1(ctx->opcode),
5a5012ec 12674 (rt >> 2) & 0x7, imm << 2);
c9602061
NF
12675 *is_branch = 1;
12676 break;
36d23958
TS
12677 case OPC_S_FMT:
12678 case OPC_D_FMT:
12679 case OPC_W_FMT:
12680 case OPC_L_FMT:
5a5012ec 12681 case OPC_PS_FMT:
bf4120ad 12682 gen_farith(ctx, ctx->opcode & FOP(0x3f, 0x1f), rt, rd, sa,
5a5012ec 12683 (imm >> 8) & 0x7);
36d23958
TS
12684 break;
12685 default:
923617a3 12686 MIPS_INVAL("cp1");
e397ee33 12687 generate_exception (ctx, EXCP_RI);
36d23958
TS
12688 break;
12689 }
12690 } else {
12691 generate_exception_err(ctx, EXCP_CpU, 1);
6ea83fed 12692 }
4ad40f36
FB
12693 break;
12694
12695 /* COP2. */
7a387fff
TS
12696 case OPC_LWC2:
12697 case OPC_LDC2:
12698 case OPC_SWC2:
12699 case OPC_SDC2:
7a387fff 12700 /* COP2: Not implemented. */
4ad40f36
FB
12701 generate_exception_err(ctx, EXCP_CpU, 2);
12702 break;
bd277fa1
RH
12703 case OPC_CP2:
12704 check_insn(env, ctx, INSN_LOONGSON2F);
12705 /* Note that these instructions use different fields. */
12706 gen_loongson_multimedia(ctx, sa, rd, rt);
12707 break;
4ad40f36 12708
7a387fff 12709 case OPC_CP3:
36d23958 12710 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
5e755519 12711 check_cp1_enabled(ctx);
36d23958
TS
12712 op1 = MASK_CP3(ctx->opcode);
12713 switch (op1) {
5a5012ec
TS
12714 case OPC_LWXC1:
12715 case OPC_LDXC1:
12716 case OPC_LUXC1:
12717 case OPC_SWXC1:
12718 case OPC_SDXC1:
12719 case OPC_SUXC1:
93b12ccc 12720 gen_flt3_ldst(ctx, op1, sa, rd, rs, rt);
5a5012ec 12721 break;
e0c84da7 12722 case OPC_PREFX:
ead9360e 12723 /* Treat as NOP. */
e0c84da7 12724 break;
5a5012ec
TS
12725 case OPC_ALNV_PS:
12726 case OPC_MADD_S:
12727 case OPC_MADD_D:
12728 case OPC_MADD_PS:
12729 case OPC_MSUB_S:
12730 case OPC_MSUB_D:
12731 case OPC_MSUB_PS:
12732 case OPC_NMADD_S:
12733 case OPC_NMADD_D:
12734 case OPC_NMADD_PS:
12735 case OPC_NMSUB_S:
12736 case OPC_NMSUB_D:
12737 case OPC_NMSUB_PS:
12738 gen_flt3_arith(ctx, op1, sa, rs, rd, rt);
12739 break;
36d23958 12740 default:
923617a3 12741 MIPS_INVAL("cp3");
e397ee33 12742 generate_exception (ctx, EXCP_RI);
36d23958
TS
12743 break;
12744 }
12745 } else {
e397ee33 12746 generate_exception_err(ctx, EXCP_CpU, 1);
7a387fff 12747 }
4ad40f36
FB
12748 break;
12749
d26bc211 12750#if defined(TARGET_MIPS64)
7a387fff
TS
12751 /* MIPS64 opcodes */
12752 case OPC_LWU:
12753 case OPC_LDL ... OPC_LDR:
7a387fff
TS
12754 case OPC_LLD:
12755 case OPC_LD:
5c13fdfd
AJ
12756 check_insn(env, ctx, ISA_MIPS3);
12757 check_mips_64(ctx);
afa88c3a 12758 gen_ld(env, ctx, op, rt, rs, imm);
5c13fdfd
AJ
12759 break;
12760 case OPC_SDL ... OPC_SDR:
7a387fff 12761 case OPC_SD:
e189e748
TS
12762 check_insn(env, ctx, ISA_MIPS3);
12763 check_mips_64(ctx);
5c13fdfd 12764 gen_st(ctx, op, rt, rs, imm);
7a387fff 12765 break;
d66c7132
AJ
12766 case OPC_SCD:
12767 check_insn(env, ctx, ISA_MIPS3);
12768 check_mips_64(ctx);
12769 gen_st_cond(ctx, op, rt, rs, imm);
12770 break;
324d9e32
AJ
12771 case OPC_DADDI:
12772 case OPC_DADDIU:
e189e748
TS
12773 check_insn(env, ctx, ISA_MIPS3);
12774 check_mips_64(ctx);
12775 gen_arith_imm(env, ctx, op, rt, rs, imm);
7a387fff 12776 break;
6af0bf9c 12777#endif
7a387fff 12778 case OPC_JALX:
3c824109 12779 check_insn(env, ctx, ASE_MIPS16 | ASE_MICROMIPS);
364d4831
NF
12780 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2;
12781 gen_compute_branch(ctx, op, 4, rs, rt, offset);
12782 *is_branch = 1;
12783 break;
7a387fff 12784 case OPC_MDMX:
e189e748 12785 check_insn(env, ctx, ASE_MDMX);
7a387fff 12786 /* MDMX: Not implemented. */
6af0bf9c 12787 default: /* Invalid */
923617a3 12788 MIPS_INVAL("major opcode");
6af0bf9c
FB
12789 generate_exception(ctx, EXCP_RI);
12790 break;
12791 }
6af0bf9c
FB
12792}
12793
2cfc5f17 12794static inline void
7db13fae 12795gen_intermediate_code_internal (CPUMIPSState *env, TranslationBlock *tb,
820e00f2 12796 int search_pc)
6af0bf9c 12797{
278d0702 12798 DisasContext ctx;
6af0bf9c
FB
12799 target_ulong pc_start;
12800 uint16_t *gen_opc_end;
a1d1bb31 12801 CPUBreakpoint *bp;
6af0bf9c 12802 int j, lj = -1;
2e70f6ef
PB
12803 int num_insns;
12804 int max_insns;
c9602061
NF
12805 int insn_bytes;
12806 int is_branch;
6af0bf9c 12807
93fcfe39
AL
12808 if (search_pc)
12809 qemu_log("search pc %d\n", search_pc);
4ad40f36 12810
6af0bf9c 12811 pc_start = tb->pc;
d42320c2 12812 gen_opc_end = gen_opc_buf + OPC_MAX_SIZE;
6af0bf9c 12813 ctx.pc = pc_start;
4ad40f36 12814 ctx.saved_pc = -1;
7b270ef2 12815 ctx.singlestep_enabled = env->singlestep_enabled;
6af0bf9c
FB
12816 ctx.tb = tb;
12817 ctx.bstate = BS_NONE;
4ad40f36 12818 /* Restore delay slot state from the tb context. */
c068688b 12819 ctx.hflags = (uint32_t)tb->flags; /* FIXME: maybe use 64 bits here? */
fd4a04eb 12820 restore_cpu_state(env, &ctx);
932e71cd 12821#ifdef CONFIG_USER_ONLY
0eaef5aa 12822 ctx.mem_idx = MIPS_HFLAG_UM;
932e71cd 12823#else
0eaef5aa 12824 ctx.mem_idx = ctx.hflags & MIPS_HFLAG_KSU;
932e71cd 12825#endif
2e70f6ef
PB
12826 num_insns = 0;
12827 max_insns = tb->cflags & CF_COUNT_MASK;
12828 if (max_insns == 0)
12829 max_insns = CF_COUNT_MASK;
d12d51d5 12830 LOG_DISAS("\ntb %p idx %d hflags %04x\n", tb, ctx.mem_idx, ctx.hflags);
2e70f6ef 12831 gen_icount_start();
faf7aaa9 12832 while (ctx.bstate == BS_NONE) {
72cf2d4f
BS
12833 if (unlikely(!QTAILQ_EMPTY(&env->breakpoints))) {
12834 QTAILQ_FOREACH(bp, &env->breakpoints, entry) {
a1d1bb31 12835 if (bp->pc == ctx.pc) {
278d0702 12836 save_cpu_state(&ctx, 1);
4ad40f36 12837 ctx.bstate = BS_BRANCH;
895c2d04 12838 gen_helper_0e0i(raise_exception, EXCP_DEBUG);
ce62e5ba
TS
12839 /* Include the breakpoint location or the tb won't
12840 * be flushed when it must be. */
12841 ctx.pc += 4;
4ad40f36
FB
12842 goto done_generating;
12843 }
12844 }
12845 }
12846
6af0bf9c
FB
12847 if (search_pc) {
12848 j = gen_opc_ptr - gen_opc_buf;
6af0bf9c
FB
12849 if (lj < j) {
12850 lj++;
12851 while (lj < j)
12852 gen_opc_instr_start[lj++] = 0;
6af0bf9c 12853 }
4ad40f36
FB
12854 gen_opc_pc[lj] = ctx.pc;
12855 gen_opc_hflags[lj] = ctx.hflags & MIPS_HFLAG_BMASK;
12856 gen_opc_instr_start[lj] = 1;
2e70f6ef 12857 gen_opc_icount[lj] = num_insns;
6af0bf9c 12858 }
2e70f6ef
PB
12859 if (num_insns + 1 == max_insns && (tb->cflags & CF_LAST_IO))
12860 gen_io_start();
c9602061
NF
12861
12862 is_branch = 0;
364d4831 12863 if (!(ctx.hflags & MIPS_HFLAG_M16)) {
895c2d04 12864 ctx.opcode = cpu_ldl_code(env, ctx.pc);
c9602061
NF
12865 insn_bytes = 4;
12866 decode_opc(env, &ctx, &is_branch);
3c824109 12867 } else if (env->insn_flags & ASE_MICROMIPS) {
895c2d04 12868 ctx.opcode = cpu_lduw_code(env, ctx.pc);
3c824109 12869 insn_bytes = decode_micromips_opc(env, &ctx, &is_branch);
364d4831 12870 } else if (env->insn_flags & ASE_MIPS16) {
895c2d04 12871 ctx.opcode = cpu_lduw_code(env, ctx.pc);
364d4831 12872 insn_bytes = decode_mips16_opc(env, &ctx, &is_branch);
c9602061
NF
12873 } else {
12874 generate_exception(&ctx, EXCP_RI);
3c824109 12875 ctx.bstate = BS_STOP;
c9602061
NF
12876 break;
12877 }
12878 if (!is_branch) {
12879 handle_delay_slot(env, &ctx, insn_bytes);
12880 }
12881 ctx.pc += insn_bytes;
12882
2e70f6ef 12883 num_insns++;
4ad40f36 12884
7b270ef2
NF
12885 /* Execute a branch and its delay slot as a single instruction.
12886 This is what GDB expects and is consistent with what the
12887 hardware does (e.g. if a delay slot instruction faults, the
12888 reported PC is the PC of the branch). */
12889 if (env->singlestep_enabled && (ctx.hflags & MIPS_HFLAG_BMASK) == 0)
4ad40f36
FB
12890 break;
12891
6af0bf9c
FB
12892 if ((ctx.pc & (TARGET_PAGE_SIZE - 1)) == 0)
12893 break;
4ad40f36 12894
faf7aaa9
TS
12895 if (gen_opc_ptr >= gen_opc_end)
12896 break;
12897
2e70f6ef
PB
12898 if (num_insns >= max_insns)
12899 break;
1b530a6d
AJ
12900
12901 if (singlestep)
12902 break;
6af0bf9c 12903 }
2e70f6ef
PB
12904 if (tb->cflags & CF_LAST_IO)
12905 gen_io_end();
7b270ef2 12906 if (env->singlestep_enabled && ctx.bstate != BS_BRANCH) {
278d0702 12907 save_cpu_state(&ctx, ctx.bstate == BS_NONE);
895c2d04 12908 gen_helper_0e0i(raise_exception, EXCP_DEBUG);
16c00cb2 12909 } else {
6958549d 12910 switch (ctx.bstate) {
16c00cb2 12911 case BS_STOP:
df1561e2
TS
12912 gen_goto_tb(&ctx, 0, ctx.pc);
12913 break;
16c00cb2 12914 case BS_NONE:
278d0702 12915 save_cpu_state(&ctx, 0);
16c00cb2
TS
12916 gen_goto_tb(&ctx, 0, ctx.pc);
12917 break;
5a5012ec 12918 case BS_EXCP:
57fec1fe 12919 tcg_gen_exit_tb(0);
16c00cb2 12920 break;
5a5012ec
TS
12921 case BS_BRANCH:
12922 default:
12923 break;
6958549d 12924 }
6af0bf9c 12925 }
4ad40f36 12926done_generating:
2e70f6ef 12927 gen_icount_end(tb, num_insns);
6af0bf9c
FB
12928 *gen_opc_ptr = INDEX_op_end;
12929 if (search_pc) {
12930 j = gen_opc_ptr - gen_opc_buf;
12931 lj++;
12932 while (lj <= j)
12933 gen_opc_instr_start[lj++] = 0;
6af0bf9c
FB
12934 } else {
12935 tb->size = ctx.pc - pc_start;
2e70f6ef 12936 tb->icount = num_insns;
6af0bf9c
FB
12937 }
12938#ifdef DEBUG_DISAS
d12d51d5 12939 LOG_DISAS("\n");
8fec2b8c 12940 if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) {
93fcfe39
AL
12941 qemu_log("IN: %s\n", lookup_symbol(pc_start));
12942 log_target_disas(pc_start, ctx.pc - pc_start, 0);
12943 qemu_log("\n");
6af0bf9c
FB
12944 }
12945#endif
6af0bf9c
FB
12946}
12947
7db13fae 12948void gen_intermediate_code (CPUMIPSState *env, struct TranslationBlock *tb)
6af0bf9c 12949{
2cfc5f17 12950 gen_intermediate_code_internal(env, tb, 0);
6af0bf9c
FB
12951}
12952
7db13fae 12953void gen_intermediate_code_pc (CPUMIPSState *env, struct TranslationBlock *tb)
6af0bf9c 12954{
2cfc5f17 12955 gen_intermediate_code_internal(env, tb, 1);
6af0bf9c
FB
12956}
12957
7db13fae 12958static void fpu_dump_state(CPUMIPSState *env, FILE *f, fprintf_function fpu_fprintf,
8706c382 12959 int flags)
6ea83fed
FB
12960{
12961 int i;
5e755519 12962 int is_fpu64 = !!(env->hflags & MIPS_HFLAG_F64);
5a5012ec 12963
2a5612e6
SW
12964#define printfpr(fp) \
12965 do { \
12966 if (is_fpu64) \
12967 fpu_fprintf(f, "w:%08x d:%016" PRIx64 \
12968 " fd:%13g fs:%13g psu: %13g\n", \
12969 (fp)->w[FP_ENDIAN_IDX], (fp)->d, \
12970 (double)(fp)->fd, \
12971 (double)(fp)->fs[FP_ENDIAN_IDX], \
12972 (double)(fp)->fs[!FP_ENDIAN_IDX]); \
12973 else { \
12974 fpr_t tmp; \
12975 tmp.w[FP_ENDIAN_IDX] = (fp)->w[FP_ENDIAN_IDX]; \
12976 tmp.w[!FP_ENDIAN_IDX] = ((fp) + 1)->w[FP_ENDIAN_IDX]; \
12977 fpu_fprintf(f, "w:%08x d:%016" PRIx64 \
12978 " fd:%13g fs:%13g psu:%13g\n", \
12979 tmp.w[FP_ENDIAN_IDX], tmp.d, \
12980 (double)tmp.fd, \
12981 (double)tmp.fs[FP_ENDIAN_IDX], \
12982 (double)tmp.fs[!FP_ENDIAN_IDX]); \
12983 } \
6ea83fed
FB
12984 } while(0)
12985
5a5012ec 12986
9a78eead
SW
12987 fpu_fprintf(f, "CP1 FCR0 0x%08x FCR31 0x%08x SR.FR %d fp_status 0x%02x\n",
12988 env->active_fpu.fcr0, env->active_fpu.fcr31, is_fpu64,
f01be154 12989 get_float_exception_flags(&env->active_fpu.fp_status));
5a5012ec
TS
12990 for (i = 0; i < 32; (is_fpu64) ? i++ : (i += 2)) {
12991 fpu_fprintf(f, "%3s: ", fregnames[i]);
f01be154 12992 printfpr(&env->active_fpu.fpr[i]);
6ea83fed
FB
12993 }
12994
12995#undef printfpr
12996}
12997
d26bc211 12998#if defined(TARGET_MIPS64) && defined(MIPS_DEBUG_SIGN_EXTENSIONS)
c570fd16 12999/* Debug help: The architecture requires 32bit code to maintain proper
c7e8a937 13000 sign-extended values on 64bit machines. */
c570fd16
TS
13001
13002#define SIGN_EXT_P(val) ((((val) & ~0x7fffffff) == 0) || (((val) & ~0x7fffffff) == ~0x7fffffff))
13003
8706c382 13004static void
7db13fae 13005cpu_mips_check_sign_extensions (CPUMIPSState *env, FILE *f,
9a78eead 13006 fprintf_function cpu_fprintf,
8706c382 13007 int flags)
c570fd16
TS
13008{
13009 int i;
13010
b5dc7732
TS
13011 if (!SIGN_EXT_P(env->active_tc.PC))
13012 cpu_fprintf(f, "BROKEN: pc=0x" TARGET_FMT_lx "\n", env->active_tc.PC);
13013 if (!SIGN_EXT_P(env->active_tc.HI[0]))
13014 cpu_fprintf(f, "BROKEN: HI=0x" TARGET_FMT_lx "\n", env->active_tc.HI[0]);
13015 if (!SIGN_EXT_P(env->active_tc.LO[0]))
13016 cpu_fprintf(f, "BROKEN: LO=0x" TARGET_FMT_lx "\n", env->active_tc.LO[0]);
c570fd16 13017 if (!SIGN_EXT_P(env->btarget))
3594c774 13018 cpu_fprintf(f, "BROKEN: btarget=0x" TARGET_FMT_lx "\n", env->btarget);
c570fd16
TS
13019
13020 for (i = 0; i < 32; i++) {
b5dc7732
TS
13021 if (!SIGN_EXT_P(env->active_tc.gpr[i]))
13022 cpu_fprintf(f, "BROKEN: %s=0x" TARGET_FMT_lx "\n", regnames[i], env->active_tc.gpr[i]);
c570fd16
TS
13023 }
13024
13025 if (!SIGN_EXT_P(env->CP0_EPC))
3594c774 13026 cpu_fprintf(f, "BROKEN: EPC=0x" TARGET_FMT_lx "\n", env->CP0_EPC);
5499b6ff
AJ
13027 if (!SIGN_EXT_P(env->lladdr))
13028 cpu_fprintf(f, "BROKEN: LLAddr=0x" TARGET_FMT_lx "\n", env->lladdr);
c570fd16
TS
13029}
13030#endif
13031
7db13fae 13032void cpu_dump_state (CPUMIPSState *env, FILE *f, fprintf_function cpu_fprintf,
6af0bf9c
FB
13033 int flags)
13034{
13035 int i;
3b46e624 13036
a7200c9f
SW
13037 cpu_fprintf(f, "pc=0x" TARGET_FMT_lx " HI=0x" TARGET_FMT_lx
13038 " LO=0x" TARGET_FMT_lx " ds %04x "
13039 TARGET_FMT_lx " " TARGET_FMT_ld "\n",
3d5be870
TS
13040 env->active_tc.PC, env->active_tc.HI[0], env->active_tc.LO[0],
13041 env->hflags, env->btarget, env->bcond);
6af0bf9c
FB
13042 for (i = 0; i < 32; i++) {
13043 if ((i & 3) == 0)
13044 cpu_fprintf(f, "GPR%02d:", i);
b5dc7732 13045 cpu_fprintf(f, " %s " TARGET_FMT_lx, regnames[i], env->active_tc.gpr[i]);
6af0bf9c
FB
13046 if ((i & 3) == 3)
13047 cpu_fprintf(f, "\n");
13048 }
568b600d 13049
3594c774 13050 cpu_fprintf(f, "CP0 Status 0x%08x Cause 0x%08x EPC 0x" TARGET_FMT_lx "\n",
5e755519 13051 env->CP0_Status, env->CP0_Cause, env->CP0_EPC);
3594c774 13052 cpu_fprintf(f, " Config0 0x%08x Config1 0x%08x LLAddr 0x" TARGET_FMT_lx "\n",
5499b6ff 13053 env->CP0_Config0, env->CP0_Config1, env->lladdr);
5e755519 13054 if (env->hflags & MIPS_HFLAG_FPU)
7a387fff 13055 fpu_dump_state(env, f, cpu_fprintf, flags);
d26bc211 13056#if defined(TARGET_MIPS64) && defined(MIPS_DEBUG_SIGN_EXTENSIONS)
c570fd16
TS
13057 cpu_mips_check_sign_extensions(env, f, cpu_fprintf, flags);
13058#endif
6af0bf9c
FB
13059}
13060
39454628
TS
13061static void mips_tcg_init(void)
13062{
f01be154 13063 int i;
39454628
TS
13064 static int inited;
13065
13066 /* Initialize various static tables. */
13067 if (inited)
6958549d 13068 return;
39454628 13069
a7812ae4 13070 cpu_env = tcg_global_reg_new_ptr(TCG_AREG0, "env");
f2c94b92 13071 TCGV_UNUSED(cpu_gpr[0]);
bb928dbe 13072 for (i = 1; i < 32; i++)
a7812ae4 13073 cpu_gpr[i] = tcg_global_mem_new(TCG_AREG0,
7db13fae 13074 offsetof(CPUMIPSState, active_tc.gpr[i]),
4b2eb8d2 13075 regnames[i]);
a7812ae4 13076 cpu_PC = tcg_global_mem_new(TCG_AREG0,
7db13fae 13077 offsetof(CPUMIPSState, active_tc.PC), "PC");
4b2eb8d2 13078 for (i = 0; i < MIPS_DSP_ACC; i++) {
a7812ae4 13079 cpu_HI[i] = tcg_global_mem_new(TCG_AREG0,
7db13fae 13080 offsetof(CPUMIPSState, active_tc.HI[i]),
4b2eb8d2 13081 regnames_HI[i]);
a7812ae4 13082 cpu_LO[i] = tcg_global_mem_new(TCG_AREG0,
7db13fae 13083 offsetof(CPUMIPSState, active_tc.LO[i]),
4b2eb8d2 13084 regnames_LO[i]);
a7812ae4 13085 cpu_ACX[i] = tcg_global_mem_new(TCG_AREG0,
7db13fae 13086 offsetof(CPUMIPSState, active_tc.ACX[i]),
4b2eb8d2
TS
13087 regnames_ACX[i]);
13088 }
a7812ae4 13089 cpu_dspctrl = tcg_global_mem_new(TCG_AREG0,
7db13fae 13090 offsetof(CPUMIPSState, active_tc.DSPControl),
4b2eb8d2 13091 "DSPControl");
1ba74fb8 13092 bcond = tcg_global_mem_new(TCG_AREG0,
7db13fae 13093 offsetof(CPUMIPSState, bcond), "bcond");
a7812ae4 13094 btarget = tcg_global_mem_new(TCG_AREG0,
7db13fae 13095 offsetof(CPUMIPSState, btarget), "btarget");
41db4607 13096 hflags = tcg_global_mem_new_i32(TCG_AREG0,
7db13fae 13097 offsetof(CPUMIPSState, hflags), "hflags");
41db4607 13098
a7812ae4 13099 fpu_fcr0 = tcg_global_mem_new_i32(TCG_AREG0,
7db13fae 13100 offsetof(CPUMIPSState, active_fpu.fcr0),
a7812ae4
PB
13101 "fcr0");
13102 fpu_fcr31 = tcg_global_mem_new_i32(TCG_AREG0,
7db13fae 13103 offsetof(CPUMIPSState, active_fpu.fcr31),
a7812ae4 13104 "fcr31");
39454628 13105
7dd9e556 13106 /* register helpers */
a7812ae4 13107#define GEN_HELPER 2
7dd9e556
TS
13108#include "helper.h"
13109
39454628
TS
13110 inited = 1;
13111}
13112
aaed909a
FB
13113#include "translate_init.c"
13114
30bf942d 13115MIPSCPU *cpu_mips_init(const char *cpu_model)
6af0bf9c 13116{
0f71a709 13117 MIPSCPU *cpu;
6af0bf9c 13118 CPUMIPSState *env;
c227f099 13119 const mips_def_t *def;
6af0bf9c 13120
aaed909a
FB
13121 def = cpu_mips_find_by_name(cpu_model);
13122 if (!def)
13123 return NULL;
0f71a709
AF
13124 cpu = MIPS_CPU(object_new(TYPE_MIPS_CPU));
13125 env = &cpu->env;
aaed909a 13126 env->cpu_model = def;
51cc2e78 13127 env->cpu_model_str = cpu_model;
aaed909a 13128
51cc2e78
BS
13129#ifndef CONFIG_USER_ONLY
13130 mmu_init(env, def);
13131#endif
13132 fpu_init(env, def);
13133 mvp_init(env, def);
39454628 13134 mips_tcg_init();
3bd4122e 13135 cpu_reset(CPU(cpu));
0bf46a40 13136 qemu_init_vcpu(env);
30bf942d 13137 return cpu;
6ae81775
TS
13138}
13139
1bba0dc9 13140void cpu_state_reset(CPUMIPSState *env)
6ae81775 13141{
eca1bdf4
AL
13142 if (qemu_loglevel_mask(CPU_LOG_RESET)) {
13143 qemu_log("CPU Reset (CPU %d)\n", env->cpu_index);
13144 log_cpu_state(env, 0);
13145 }
13146
6ae81775 13147 memset(env, 0, offsetof(CPUMIPSState, breakpoints));
6af0bf9c 13148 tlb_flush(env, 1);
6ae81775 13149
51cc2e78
BS
13150 /* Reset registers to their default values */
13151 env->CP0_PRid = env->cpu_model->CP0_PRid;
13152 env->CP0_Config0 = env->cpu_model->CP0_Config0;
13153#ifdef TARGET_WORDS_BIGENDIAN
13154 env->CP0_Config0 |= (1 << CP0C0_BE);
13155#endif
13156 env->CP0_Config1 = env->cpu_model->CP0_Config1;
13157 env->CP0_Config2 = env->cpu_model->CP0_Config2;
13158 env->CP0_Config3 = env->cpu_model->CP0_Config3;
13159 env->CP0_Config6 = env->cpu_model->CP0_Config6;
13160 env->CP0_Config7 = env->cpu_model->CP0_Config7;
2a6e32dd
AJ
13161 env->CP0_LLAddr_rw_bitmask = env->cpu_model->CP0_LLAddr_rw_bitmask
13162 << env->cpu_model->CP0_LLAddr_shift;
13163 env->CP0_LLAddr_shift = env->cpu_model->CP0_LLAddr_shift;
51cc2e78
BS
13164 env->SYNCI_Step = env->cpu_model->SYNCI_Step;
13165 env->CCRes = env->cpu_model->CCRes;
13166 env->CP0_Status_rw_bitmask = env->cpu_model->CP0_Status_rw_bitmask;
13167 env->CP0_TCStatus_rw_bitmask = env->cpu_model->CP0_TCStatus_rw_bitmask;
13168 env->CP0_SRSCtl = env->cpu_model->CP0_SRSCtl;
13169 env->current_tc = 0;
13170 env->SEGBITS = env->cpu_model->SEGBITS;
13171 env->SEGMask = (target_ulong)((1ULL << env->cpu_model->SEGBITS) - 1);
13172#if defined(TARGET_MIPS64)
13173 if (env->cpu_model->insn_flags & ISA_MIPS3) {
13174 env->SEGMask |= 3ULL << 62;
13175 }
13176#endif
13177 env->PABITS = env->cpu_model->PABITS;
13178 env->PAMask = (target_ulong)((1ULL << env->cpu_model->PABITS) - 1);
13179 env->CP0_SRSConf0_rw_bitmask = env->cpu_model->CP0_SRSConf0_rw_bitmask;
13180 env->CP0_SRSConf0 = env->cpu_model->CP0_SRSConf0;
13181 env->CP0_SRSConf1_rw_bitmask = env->cpu_model->CP0_SRSConf1_rw_bitmask;
13182 env->CP0_SRSConf1 = env->cpu_model->CP0_SRSConf1;
13183 env->CP0_SRSConf2_rw_bitmask = env->cpu_model->CP0_SRSConf2_rw_bitmask;
13184 env->CP0_SRSConf2 = env->cpu_model->CP0_SRSConf2;
13185 env->CP0_SRSConf3_rw_bitmask = env->cpu_model->CP0_SRSConf3_rw_bitmask;
13186 env->CP0_SRSConf3 = env->cpu_model->CP0_SRSConf3;
13187 env->CP0_SRSConf4_rw_bitmask = env->cpu_model->CP0_SRSConf4_rw_bitmask;
13188 env->CP0_SRSConf4 = env->cpu_model->CP0_SRSConf4;
f1cb0951 13189 env->active_fpu.fcr0 = env->cpu_model->CP1_fcr0;
51cc2e78
BS
13190 env->insn_flags = env->cpu_model->insn_flags;
13191
0eaef5aa 13192#if defined(CONFIG_USER_ONLY)
03e6e501 13193 env->CP0_Status = (MIPS_HFLAG_UM << CP0St_KSU);
94159135
MI
13194 /* Enable access to the CPUNum, SYNCI_Step, CC, and CCRes RDHWR
13195 hardware registers. */
13196 env->CP0_HWREna |= 0x0000000F;
91a75935 13197 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
03e6e501 13198 env->CP0_Status |= (1 << CP0St_CU1);
91a75935 13199 }
932e71cd
AJ
13200#else
13201 if (env->hflags & MIPS_HFLAG_BMASK) {
13202 /* If the exception was raised from a delay slot,
13203 come back to the jump. */
13204 env->CP0_ErrorEPC = env->active_tc.PC - 4;
aa328add 13205 } else {
932e71cd
AJ
13206 env->CP0_ErrorEPC = env->active_tc.PC;
13207 }
13208 env->active_tc.PC = (int32_t)0xBFC00000;
51cc2e78
BS
13209 env->CP0_Random = env->tlb->nb_tlb - 1;
13210 env->tlb->tlb_in_use = env->tlb->nb_tlb;
932e71cd 13211 env->CP0_Wired = 0;
671b0f36 13212 env->CP0_EBase = 0x80000000 | (env->cpu_index & 0x3FF);
932e71cd
AJ
13213 env->CP0_Status = (1 << CP0St_BEV) | (1 << CP0St_ERL);
13214 /* vectored interrupts not implemented, timer on int 7,
13215 no performance counters. */
13216 env->CP0_IntCtl = 0xe0000000;
13217 {
13218 int i;
13219
13220 for (i = 0; i < 7; i++) {
13221 env->CP0_WatchLo[i] = 0;
13222 env->CP0_WatchHi[i] = 0x80000000;
fd88b6ab 13223 }
932e71cd
AJ
13224 env->CP0_WatchLo[7] = 0;
13225 env->CP0_WatchHi[7] = 0;
fd88b6ab 13226 }
932e71cd
AJ
13227 /* Count register increments in debug mode, EJTAG version 1 */
13228 env->CP0_Debug = (1 << CP0DB_CNT) | (0x1 << CP0DB_VER);
9e56e756
EI
13229
13230 if (env->CP0_Config3 & (1 << CP0C3_MT)) {
13231 int i;
13232
13233 /* Only TC0 on VPE 0 starts as active. */
13234 for (i = 0; i < ARRAY_SIZE(env->tcs); i++) {
13235 env->tcs[i].CP0_TCBind = env->cpu_index << CP0TCBd_CurVPE;
13236 env->tcs[i].CP0_TCHalt = 1;
13237 }
13238 env->active_tc.CP0_TCHalt = 1;
13239 env->halted = 1;
13240
13241 if (!env->cpu_index) {
13242 /* VPE0 starts up enabled. */
13243 env->mvp->CP0_MVPControl |= (1 << CP0MVPCo_EVP);
13244 env->CP0_VPEConf0 |= (1 << CP0VPEC0_MVP) | (1 << CP0VPEC0_VPA);
13245
13246 /* TC0 starts up unhalted. */
13247 env->halted = 0;
13248 env->active_tc.CP0_TCHalt = 0;
13249 env->tcs[0].CP0_TCHalt = 0;
13250 /* With thread 0 active. */
13251 env->active_tc.CP0_TCStatus = (1 << CP0TCSt_A);
13252 env->tcs[0].CP0_TCStatus = (1 << CP0TCSt_A);
13253 }
13254 }
51cc2e78 13255#endif
03e6e501 13256 compute_hflags(env);
6af0bf9c 13257 env->exception_index = EXCP_NONE;
6af0bf9c 13258}
d2856f1a 13259
7db13fae 13260void restore_state_to_opc(CPUMIPSState *env, TranslationBlock *tb, int pc_pos)
d2856f1a 13261{
b5dc7732 13262 env->active_tc.PC = gen_opc_pc[pc_pos];
d2856f1a
AJ
13263 env->hflags &= ~MIPS_HFLAG_BMASK;
13264 env->hflags |= gen_opc_hflags[pc_pos];
13265}