]> git.proxmox.com Git - qemu.git/blame - target-mips/translate.c
Fix order of CVT.PS.S operands
[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
eeef26cd 31//#define MIPS_DEBUG_DISAS
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
449#define MASK_CP3(op) MASK_OP_MAJOR(op) | (op & 0x3F)
450
451enum {
452 OPC_LWXC1 = 0x00 | OPC_CP3,
453 OPC_LDXC1 = 0x01 | OPC_CP3,
454 OPC_LUXC1 = 0x05 | OPC_CP3,
455 OPC_SWXC1 = 0x08 | OPC_CP3,
456 OPC_SDXC1 = 0x09 | OPC_CP3,
457 OPC_SUXC1 = 0x0D | OPC_CP3,
458 OPC_PREFX = 0x0F | OPC_CP3,
459 OPC_ALNV_PS = 0x1E | OPC_CP3,
460 OPC_MADD_S = 0x20 | OPC_CP3,
461 OPC_MADD_D = 0x21 | OPC_CP3,
462 OPC_MADD_PS = 0x26 | OPC_CP3,
463 OPC_MSUB_S = 0x28 | OPC_CP3,
464 OPC_MSUB_D = 0x29 | OPC_CP3,
465 OPC_MSUB_PS = 0x2E | OPC_CP3,
466 OPC_NMADD_S = 0x30 | OPC_CP3,
fbcc6828 467 OPC_NMADD_D = 0x31 | OPC_CP3,
e0c84da7
TS
468 OPC_NMADD_PS= 0x36 | OPC_CP3,
469 OPC_NMSUB_S = 0x38 | OPC_CP3,
470 OPC_NMSUB_D = 0x39 | OPC_CP3,
471 OPC_NMSUB_PS= 0x3E | OPC_CP3,
472};
473
39454628 474/* global register indices */
a7812ae4
PB
475static TCGv_ptr cpu_env;
476static TCGv cpu_gpr[32], cpu_PC;
4b2eb8d2 477static TCGv cpu_HI[MIPS_DSP_ACC], cpu_LO[MIPS_DSP_ACC], cpu_ACX[MIPS_DSP_ACC];
41db4607
AJ
478static TCGv cpu_dspctrl, btarget, bcond;
479static TCGv_i32 hflags;
a7812ae4 480static TCGv_i32 fpu_fcr0, fpu_fcr31;
aa0bf00b 481
1a7ff922
PB
482static uint32_t gen_opc_hflags[OPC_BUF_SIZE];
483
2e70f6ef
PB
484#include "gen-icount.h"
485
a7812ae4
PB
486#define gen_helper_0i(name, arg) do { \
487 TCGv_i32 helper_tmp = tcg_const_i32(arg); \
488 gen_helper_##name(helper_tmp); \
489 tcg_temp_free_i32(helper_tmp); \
490 } while(0)
be24bb4f 491
a7812ae4
PB
492#define gen_helper_1i(name, arg1, arg2) do { \
493 TCGv_i32 helper_tmp = tcg_const_i32(arg2); \
494 gen_helper_##name(arg1, helper_tmp); \
495 tcg_temp_free_i32(helper_tmp); \
496 } while(0)
be24bb4f 497
a7812ae4
PB
498#define gen_helper_2i(name, arg1, arg2, arg3) do { \
499 TCGv_i32 helper_tmp = tcg_const_i32(arg3); \
500 gen_helper_##name(arg1, arg2, helper_tmp); \
501 tcg_temp_free_i32(helper_tmp); \
502 } while(0)
be24bb4f 503
a7812ae4
PB
504#define gen_helper_3i(name, arg1, arg2, arg3, arg4) do { \
505 TCGv_i32 helper_tmp = tcg_const_i32(arg4); \
506 gen_helper_##name(arg1, arg2, arg3, helper_tmp); \
507 tcg_temp_free_i32(helper_tmp); \
508 } while(0)
c239529e 509
8e9ade68
TS
510typedef struct DisasContext {
511 struct TranslationBlock *tb;
512 target_ulong pc, saved_pc;
513 uint32_t opcode;
7b270ef2 514 int singlestep_enabled;
8e9ade68
TS
515 /* Routine used to access memory */
516 int mem_idx;
517 uint32_t hflags, saved_hflags;
518 int bstate;
519 target_ulong btarget;
520} DisasContext;
521
522enum {
523 BS_NONE = 0, /* We go out of the TB without reaching a branch or an
d077b6f7 524 * exception condition */
8e9ade68
TS
525 BS_STOP = 1, /* We want to stop translation for any reason */
526 BS_BRANCH = 2, /* We reached a branch condition */
527 BS_EXCP = 3, /* We reached an exception condition */
528};
529
530static const char *regnames[] =
6af0bf9c
FB
531 { "r0", "at", "v0", "v1", "a0", "a1", "a2", "a3",
532 "t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7",
533 "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7",
534 "t8", "t9", "k0", "k1", "gp", "sp", "s8", "ra", };
535
4b2eb8d2
TS
536static const char *regnames_HI[] =
537 { "HI0", "HI1", "HI2", "HI3", };
538
539static const char *regnames_LO[] =
540 { "LO0", "LO1", "LO2", "LO3", };
541
542static const char *regnames_ACX[] =
543 { "ACX0", "ACX1", "ACX2", "ACX3", };
544
8e9ade68
TS
545static const char *fregnames[] =
546 { "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7",
547 "f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15",
548 "f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23",
549 "f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31", };
958fb4a9 550
8e9ade68 551#ifdef MIPS_DEBUG_DISAS
001faf32 552#define MIPS_DEBUG(fmt, ...) \
93fcfe39
AL
553 qemu_log_mask(CPU_LOG_TB_IN_ASM, \
554 TARGET_FMT_lx ": %08x " fmt "\n", \
001faf32 555 ctx->pc, ctx->opcode , ## __VA_ARGS__)
93fcfe39 556#define LOG_DISAS(...) qemu_log_mask(CPU_LOG_TB_IN_ASM, ## __VA_ARGS__)
8e9ade68 557#else
001faf32 558#define MIPS_DEBUG(fmt, ...) do { } while(0)
d12d51d5 559#define LOG_DISAS(...) do { } while (0)
8e9ade68 560#endif
958fb4a9 561
8e9ade68
TS
562#define MIPS_INVAL(op) \
563do { \
564 MIPS_DEBUG("Invalid %s %03x %03x %03x", op, ctx->opcode >> 26, \
565 ctx->opcode & 0x3F, ((ctx->opcode >> 16) & 0x1F)); \
566} while (0)
ead9360e 567
8e9ade68
TS
568/* General purpose registers moves. */
569static inline void gen_load_gpr (TCGv t, int reg)
aaa9128a 570{
8e9ade68
TS
571 if (reg == 0)
572 tcg_gen_movi_tl(t, 0);
573 else
4b2eb8d2 574 tcg_gen_mov_tl(t, cpu_gpr[reg]);
aaa9128a
TS
575}
576
8e9ade68 577static inline void gen_store_gpr (TCGv t, int reg)
aaa9128a 578{
8e9ade68 579 if (reg != 0)
4b2eb8d2 580 tcg_gen_mov_tl(cpu_gpr[reg], t);
aaa9128a
TS
581}
582
b10fa3c9 583/* Moves to/from ACX register. */
4b2eb8d2 584static inline void gen_load_ACX (TCGv t, int reg)
893f9865 585{
4b2eb8d2 586 tcg_gen_mov_tl(t, cpu_ACX[reg]);
893f9865
TS
587}
588
4b2eb8d2 589static inline void gen_store_ACX (TCGv t, int reg)
893f9865 590{
4b2eb8d2 591 tcg_gen_mov_tl(cpu_ACX[reg], t);
893f9865
TS
592}
593
8e9ade68 594/* Moves to/from shadow registers. */
be24bb4f 595static inline void gen_load_srsgpr (int from, int to)
aaa9128a 596{
d9bea114 597 TCGv t0 = tcg_temp_new();
be24bb4f
TS
598
599 if (from == 0)
d9bea114 600 tcg_gen_movi_tl(t0, 0);
8e9ade68 601 else {
d9bea114 602 TCGv_i32 t2 = tcg_temp_new_i32();
a7812ae4 603 TCGv_ptr addr = tcg_temp_new_ptr();
aaa9128a 604
7db13fae 605 tcg_gen_ld_i32(t2, cpu_env, offsetof(CPUMIPSState, CP0_SRSCtl));
d9bea114
AJ
606 tcg_gen_shri_i32(t2, t2, CP0SRSCtl_PSS);
607 tcg_gen_andi_i32(t2, t2, 0xf);
608 tcg_gen_muli_i32(t2, t2, sizeof(target_ulong) * 32);
609 tcg_gen_ext_i32_ptr(addr, t2);
a7812ae4 610 tcg_gen_add_ptr(addr, cpu_env, addr);
aaa9128a 611
d9bea114 612 tcg_gen_ld_tl(t0, addr, sizeof(target_ulong) * from);
a7812ae4 613 tcg_temp_free_ptr(addr);
d9bea114 614 tcg_temp_free_i32(t2);
8e9ade68 615 }
d9bea114
AJ
616 gen_store_gpr(t0, to);
617 tcg_temp_free(t0);
aaa9128a
TS
618}
619
be24bb4f 620static inline void gen_store_srsgpr (int from, int to)
aaa9128a 621{
be24bb4f 622 if (to != 0) {
d9bea114
AJ
623 TCGv t0 = tcg_temp_new();
624 TCGv_i32 t2 = tcg_temp_new_i32();
a7812ae4 625 TCGv_ptr addr = tcg_temp_new_ptr();
be24bb4f 626
d9bea114 627 gen_load_gpr(t0, from);
7db13fae 628 tcg_gen_ld_i32(t2, cpu_env, offsetof(CPUMIPSState, CP0_SRSCtl));
d9bea114
AJ
629 tcg_gen_shri_i32(t2, t2, CP0SRSCtl_PSS);
630 tcg_gen_andi_i32(t2, t2, 0xf);
631 tcg_gen_muli_i32(t2, t2, sizeof(target_ulong) * 32);
632 tcg_gen_ext_i32_ptr(addr, t2);
a7812ae4 633 tcg_gen_add_ptr(addr, cpu_env, addr);
be24bb4f 634
d9bea114 635 tcg_gen_st_tl(t0, addr, sizeof(target_ulong) * to);
a7812ae4 636 tcg_temp_free_ptr(addr);
d9bea114
AJ
637 tcg_temp_free_i32(t2);
638 tcg_temp_free(t0);
8e9ade68 639 }
aaa9128a
TS
640}
641
aaa9128a 642/* Floating point register moves. */
a7812ae4 643static inline void gen_load_fpr32 (TCGv_i32 t, int reg)
aa0bf00b 644{
7db13fae 645 tcg_gen_ld_i32(t, cpu_env, offsetof(CPUMIPSState, active_fpu.fpr[reg].w[FP_ENDIAN_IDX]));
6ea83fed
FB
646}
647
a7812ae4 648static inline void gen_store_fpr32 (TCGv_i32 t, int reg)
aa0bf00b 649{
7db13fae 650 tcg_gen_st_i32(t, cpu_env, offsetof(CPUMIPSState, active_fpu.fpr[reg].w[FP_ENDIAN_IDX]));
6d066274
AJ
651}
652
653static inline void gen_load_fpr32h (TCGv_i32 t, int reg)
654{
7db13fae 655 tcg_gen_ld_i32(t, cpu_env, offsetof(CPUMIPSState, active_fpu.fpr[reg].w[!FP_ENDIAN_IDX]));
6d066274
AJ
656}
657
658static inline void gen_store_fpr32h (TCGv_i32 t, int reg)
659{
7db13fae 660 tcg_gen_st_i32(t, cpu_env, offsetof(CPUMIPSState, active_fpu.fpr[reg].w[!FP_ENDIAN_IDX]));
aa0bf00b 661}
6ea83fed 662
a7812ae4 663static inline void gen_load_fpr64 (DisasContext *ctx, TCGv_i64 t, int reg)
aa0bf00b 664{
f364515c 665 if (ctx->hflags & MIPS_HFLAG_F64) {
7db13fae 666 tcg_gen_ld_i64(t, cpu_env, offsetof(CPUMIPSState, active_fpu.fpr[reg].d));
f364515c 667 } else {
6d066274
AJ
668 TCGv_i32 t0 = tcg_temp_new_i32();
669 TCGv_i32 t1 = tcg_temp_new_i32();
670 gen_load_fpr32(t0, reg & ~1);
671 gen_load_fpr32(t1, reg | 1);
672 tcg_gen_concat_i32_i64(t, t0, t1);
673 tcg_temp_free_i32(t0);
674 tcg_temp_free_i32(t1);
aa0bf00b
TS
675 }
676}
6ea83fed 677
a7812ae4 678static inline void gen_store_fpr64 (DisasContext *ctx, TCGv_i64 t, int reg)
aa0bf00b 679{
f364515c 680 if (ctx->hflags & MIPS_HFLAG_F64) {
7db13fae 681 tcg_gen_st_i64(t, cpu_env, offsetof(CPUMIPSState, active_fpu.fpr[reg].d));
f364515c 682 } else {
6d066274
AJ
683 TCGv_i64 t0 = tcg_temp_new_i64();
684 TCGv_i32 t1 = tcg_temp_new_i32();
685 tcg_gen_trunc_i64_i32(t1, t);
686 gen_store_fpr32(t1, reg & ~1);
687 tcg_gen_shri_i64(t0, t, 32);
688 tcg_gen_trunc_i64_i32(t1, t0);
689 gen_store_fpr32(t1, reg | 1);
690 tcg_temp_free_i32(t1);
691 tcg_temp_free_i64(t0);
aa0bf00b
TS
692 }
693}
6ea83fed 694
d94536f4 695static inline int get_fp_bit (int cc)
a16336e4 696{
d94536f4
AJ
697 if (cc)
698 return 24 + cc;
699 else
700 return 23;
a16336e4
TS
701}
702
30898801 703/* Tests */
8e9ade68
TS
704static inline void gen_save_pc(target_ulong pc)
705{
1eb75d4a 706 tcg_gen_movi_tl(cpu_PC, pc);
8e9ade68 707}
30898801 708
356265ae 709static inline void save_cpu_state (DisasContext *ctx, int do_save_pc)
6af0bf9c 710{
d12d51d5 711 LOG_DISAS("hflags %08x saved %08x\n", ctx->hflags, ctx->saved_hflags);
6af0bf9c 712 if (do_save_pc && ctx->pc != ctx->saved_pc) {
9b9e4393 713 gen_save_pc(ctx->pc);
6af0bf9c
FB
714 ctx->saved_pc = ctx->pc;
715 }
716 if (ctx->hflags != ctx->saved_hflags) {
41db4607 717 tcg_gen_movi_i32(hflags, ctx->hflags);
6af0bf9c 718 ctx->saved_hflags = ctx->hflags;
364d4831 719 switch (ctx->hflags & MIPS_HFLAG_BMASK_BASE) {
5a5012ec 720 case MIPS_HFLAG_BR:
5a5012ec
TS
721 break;
722 case MIPS_HFLAG_BC:
5a5012ec 723 case MIPS_HFLAG_BL:
5a5012ec 724 case MIPS_HFLAG_B:
d077b6f7 725 tcg_gen_movi_tl(btarget, ctx->btarget);
5a5012ec 726 break;
6af0bf9c
FB
727 }
728 }
729}
730
7db13fae 731static inline void restore_cpu_state (CPUMIPSState *env, DisasContext *ctx)
5a5012ec 732{
fd4a04eb 733 ctx->saved_hflags = ctx->hflags;
364d4831 734 switch (ctx->hflags & MIPS_HFLAG_BMASK_BASE) {
fd4a04eb 735 case MIPS_HFLAG_BR:
fd4a04eb
TS
736 break;
737 case MIPS_HFLAG_BC:
738 case MIPS_HFLAG_BL:
39454628 739 case MIPS_HFLAG_B:
fd4a04eb 740 ctx->btarget = env->btarget;
fd4a04eb 741 break;
5a5012ec
TS
742 }
743}
744
356265ae 745static inline void
48d38ca5 746generate_exception_err (DisasContext *ctx, int excp, int err)
aaa9128a 747{
a7812ae4
PB
748 TCGv_i32 texcp = tcg_const_i32(excp);
749 TCGv_i32 terr = tcg_const_i32(err);
aaa9128a 750 save_cpu_state(ctx, 1);
a7812ae4
PB
751 gen_helper_raise_exception_err(texcp, terr);
752 tcg_temp_free_i32(terr);
753 tcg_temp_free_i32(texcp);
aaa9128a
TS
754}
755
356265ae 756static inline void
48d38ca5 757generate_exception (DisasContext *ctx, int excp)
aaa9128a 758{
6af0bf9c 759 save_cpu_state(ctx, 1);
a7812ae4 760 gen_helper_0i(raise_exception, excp);
6af0bf9c
FB
761}
762
48d38ca5 763/* Addresses computation */
941694d0 764static inline void gen_op_addr_add (DisasContext *ctx, TCGv ret, TCGv arg0, TCGv arg1)
4ad40f36 765{
941694d0 766 tcg_gen_add_tl(ret, arg0, arg1);
48d38ca5
TS
767
768#if defined(TARGET_MIPS64)
769 /* For compatibility with 32-bit code, data reference in user mode
770 with Status_UX = 0 should be casted to 32-bit and sign extended.
771 See the MIPS64 PRA manual, section 4.10. */
2623c1ec
AJ
772 if (((ctx->hflags & MIPS_HFLAG_KSU) == MIPS_HFLAG_UM) &&
773 !(ctx->hflags & MIPS_HFLAG_UX)) {
941694d0 774 tcg_gen_ext32s_i64(ret, ret);
48d38ca5
TS
775 }
776#endif
4ad40f36
FB
777}
778
356265ae 779static inline void check_cp0_enabled(DisasContext *ctx)
387a8fe5 780{
fe253235 781 if (unlikely(!(ctx->hflags & MIPS_HFLAG_CP0)))
c2c65dab 782 generate_exception_err(ctx, EXCP_CpU, 0);
387a8fe5
TS
783}
784
356265ae 785static inline void check_cp1_enabled(DisasContext *ctx)
5e755519 786{
fe253235 787 if (unlikely(!(ctx->hflags & MIPS_HFLAG_FPU)))
5e755519
TS
788 generate_exception_err(ctx, EXCP_CpU, 1);
789}
790
b8aa4598
TS
791/* Verify that the processor is running with COP1X instructions enabled.
792 This is associated with the nabla symbol in the MIPS32 and MIPS64
793 opcode tables. */
794
356265ae 795static inline void check_cop1x(DisasContext *ctx)
b8aa4598
TS
796{
797 if (unlikely(!(ctx->hflags & MIPS_HFLAG_COP1X)))
798 generate_exception(ctx, EXCP_RI);
799}
800
801/* Verify that the processor is running with 64-bit floating-point
802 operations enabled. */
803
356265ae 804static inline void check_cp1_64bitmode(DisasContext *ctx)
5e755519 805{
b8aa4598 806 if (unlikely(~ctx->hflags & (MIPS_HFLAG_F64 | MIPS_HFLAG_COP1X)))
5e755519
TS
807 generate_exception(ctx, EXCP_RI);
808}
809
810/*
811 * Verify if floating point register is valid; an operation is not defined
812 * if bit 0 of any register specification is set and the FR bit in the
813 * Status register equals zero, since the register numbers specify an
814 * even-odd pair of adjacent coprocessor general registers. When the FR bit
815 * in the Status register equals one, both even and odd register numbers
816 * are valid. This limitation exists only for 64 bit wide (d,l,ps) registers.
817 *
818 * Multiple 64 bit wide registers can be checked by calling
819 * gen_op_cp1_registers(freg1 | freg2 | ... | fregN);
820 */
356265ae 821static inline void check_cp1_registers(DisasContext *ctx, int regs)
5e755519 822{
fe253235 823 if (unlikely(!(ctx->hflags & MIPS_HFLAG_F64) && (regs & 1)))
5e755519
TS
824 generate_exception(ctx, EXCP_RI);
825}
826
3a95e3a7 827/* This code generates a "reserved instruction" exception if the
e189e748 828 CPU does not support the instruction set corresponding to flags. */
7db13fae 829static inline void check_insn(CPUMIPSState *env, DisasContext *ctx, int flags)
3a95e3a7 830{
e189e748 831 if (unlikely(!(env->insn_flags & flags)))
3a95e3a7
TS
832 generate_exception(ctx, EXCP_RI);
833}
834
e189e748
TS
835/* This code generates a "reserved instruction" exception if 64-bit
836 instructions are not enabled. */
356265ae 837static inline void check_mips_64(DisasContext *ctx)
e189e748 838{
fe253235 839 if (unlikely(!(ctx->hflags & MIPS_HFLAG_64)))
e189e748
TS
840 generate_exception(ctx, EXCP_RI);
841}
842
8153667c
NF
843/* Define small wrappers for gen_load_fpr* so that we have a uniform
844 calling interface for 32 and 64-bit FPRs. No sense in changing
845 all callers for gen_load_fpr32 when we need the CTX parameter for
846 this one use. */
847#define gen_ldcmp_fpr32(ctx, x, y) gen_load_fpr32(x, y)
848#define gen_ldcmp_fpr64(ctx, x, y) gen_load_fpr64(ctx, x, y)
849#define FOP_CONDS(type, abs, fmt, ifmt, bits) \
850static inline void gen_cmp ## type ## _ ## fmt(DisasContext *ctx, int n, \
851 int ft, int fs, int cc) \
852{ \
853 TCGv_i##bits fp0 = tcg_temp_new_i##bits (); \
854 TCGv_i##bits fp1 = tcg_temp_new_i##bits (); \
855 switch (ifmt) { \
856 case FMT_PS: \
857 check_cp1_64bitmode(ctx); \
858 break; \
859 case FMT_D: \
860 if (abs) { \
861 check_cop1x(ctx); \
862 } \
863 check_cp1_registers(ctx, fs | ft); \
864 break; \
865 case FMT_S: \
866 if (abs) { \
867 check_cop1x(ctx); \
868 } \
869 break; \
870 } \
871 gen_ldcmp_fpr##bits (ctx, fp0, fs); \
872 gen_ldcmp_fpr##bits (ctx, fp1, ft); \
873 switch (n) { \
874 case 0: gen_helper_2i(cmp ## type ## _ ## fmt ## _f, fp0, fp1, cc); break;\
875 case 1: gen_helper_2i(cmp ## type ## _ ## fmt ## _un, fp0, fp1, cc); break;\
876 case 2: gen_helper_2i(cmp ## type ## _ ## fmt ## _eq, fp0, fp1, cc); break;\
877 case 3: gen_helper_2i(cmp ## type ## _ ## fmt ## _ueq, fp0, fp1, cc); break;\
878 case 4: gen_helper_2i(cmp ## type ## _ ## fmt ## _olt, fp0, fp1, cc); break;\
879 case 5: gen_helper_2i(cmp ## type ## _ ## fmt ## _ult, fp0, fp1, cc); break;\
880 case 6: gen_helper_2i(cmp ## type ## _ ## fmt ## _ole, fp0, fp1, cc); break;\
881 case 7: gen_helper_2i(cmp ## type ## _ ## fmt ## _ule, fp0, fp1, cc); break;\
882 case 8: gen_helper_2i(cmp ## type ## _ ## fmt ## _sf, fp0, fp1, cc); break;\
883 case 9: gen_helper_2i(cmp ## type ## _ ## fmt ## _ngle, fp0, fp1, cc); break;\
884 case 10: gen_helper_2i(cmp ## type ## _ ## fmt ## _seq, fp0, fp1, cc); break;\
885 case 11: gen_helper_2i(cmp ## type ## _ ## fmt ## _ngl, fp0, fp1, cc); break;\
886 case 12: gen_helper_2i(cmp ## type ## _ ## fmt ## _lt, fp0, fp1, cc); break;\
887 case 13: gen_helper_2i(cmp ## type ## _ ## fmt ## _nge, fp0, fp1, cc); break;\
888 case 14: gen_helper_2i(cmp ## type ## _ ## fmt ## _le, fp0, fp1, cc); break;\
889 case 15: gen_helper_2i(cmp ## type ## _ ## fmt ## _ngt, fp0, fp1, cc); break;\
890 default: abort(); \
891 } \
892 tcg_temp_free_i##bits (fp0); \
893 tcg_temp_free_i##bits (fp1); \
894}
895
896FOP_CONDS(, 0, d, FMT_D, 64)
897FOP_CONDS(abs, 1, d, FMT_D, 64)
898FOP_CONDS(, 0, s, FMT_S, 32)
899FOP_CONDS(abs, 1, s, FMT_S, 32)
900FOP_CONDS(, 0, ps, FMT_PS, 64)
901FOP_CONDS(abs, 1, ps, FMT_PS, 64)
902#undef FOP_CONDS
903#undef gen_ldcmp_fpr32
904#undef gen_ldcmp_fpr64
905
958fb4a9 906/* load/store instructions. */
d9bea114 907#define OP_LD(insn,fname) \
5c13fdfd 908static inline void op_ld_##insn(TCGv ret, TCGv arg1, DisasContext *ctx) \
d9bea114
AJ
909{ \
910 tcg_gen_qemu_##fname(ret, arg1, ctx->mem_idx); \
aaa9128a
TS
911}
912OP_LD(lb,ld8s);
913OP_LD(lbu,ld8u);
914OP_LD(lh,ld16s);
915OP_LD(lhu,ld16u);
916OP_LD(lw,ld32s);
917#if defined(TARGET_MIPS64)
918OP_LD(lwu,ld32u);
919OP_LD(ld,ld64);
920#endif
921#undef OP_LD
922
d9bea114 923#define OP_ST(insn,fname) \
5c13fdfd 924static inline void op_st_##insn(TCGv arg1, TCGv arg2, DisasContext *ctx) \
d9bea114
AJ
925{ \
926 tcg_gen_qemu_##fname(arg1, arg2, ctx->mem_idx); \
aaa9128a
TS
927}
928OP_ST(sb,st8);
929OP_ST(sh,st16);
930OP_ST(sw,st32);
931#if defined(TARGET_MIPS64)
932OP_ST(sd,st64);
933#endif
934#undef OP_ST
935
e7139c44 936#ifdef CONFIG_USER_ONLY
d9bea114 937#define OP_LD_ATOMIC(insn,fname) \
5c13fdfd 938static inline void op_ld_##insn(TCGv ret, TCGv arg1, DisasContext *ctx) \
d9bea114
AJ
939{ \
940 TCGv t0 = tcg_temp_new(); \
941 tcg_gen_mov_tl(t0, arg1); \
942 tcg_gen_qemu_##fname(ret, arg1, ctx->mem_idx); \
7db13fae
AF
943 tcg_gen_st_tl(t0, cpu_env, offsetof(CPUMIPSState, lladdr)); \
944 tcg_gen_st_tl(ret, cpu_env, offsetof(CPUMIPSState, llval)); \
d9bea114 945 tcg_temp_free(t0); \
aaa9128a 946}
e7139c44
AJ
947#else
948#define OP_LD_ATOMIC(insn,fname) \
5c13fdfd 949static inline void op_ld_##insn(TCGv ret, TCGv arg1, DisasContext *ctx) \
e7139c44
AJ
950{ \
951 gen_helper_2i(insn, ret, arg1, ctx->mem_idx); \
952}
953#endif
aaa9128a
TS
954OP_LD_ATOMIC(ll,ld32s);
955#if defined(TARGET_MIPS64)
956OP_LD_ATOMIC(lld,ld64);
957#endif
958#undef OP_LD_ATOMIC
959
590bc601
PB
960#ifdef CONFIG_USER_ONLY
961#define OP_ST_ATOMIC(insn,fname,ldname,almask) \
5c13fdfd 962static inline void op_st_##insn(TCGv arg1, TCGv arg2, int rt, DisasContext *ctx) \
590bc601
PB
963{ \
964 TCGv t0 = tcg_temp_new(); \
965 int l1 = gen_new_label(); \
966 int l2 = gen_new_label(); \
967 \
968 tcg_gen_andi_tl(t0, arg2, almask); \
969 tcg_gen_brcondi_tl(TCG_COND_EQ, t0, 0, l1); \
7db13fae 970 tcg_gen_st_tl(arg2, cpu_env, offsetof(CPUMIPSState, CP0_BadVAddr)); \
590bc601
PB
971 generate_exception(ctx, EXCP_AdES); \
972 gen_set_label(l1); \
7db13fae 973 tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUMIPSState, lladdr)); \
590bc601
PB
974 tcg_gen_brcond_tl(TCG_COND_NE, arg2, t0, l2); \
975 tcg_gen_movi_tl(t0, rt | ((almask << 3) & 0x20)); \
7db13fae
AF
976 tcg_gen_st_tl(t0, cpu_env, offsetof(CPUMIPSState, llreg)); \
977 tcg_gen_st_tl(arg1, cpu_env, offsetof(CPUMIPSState, llnewval)); \
590bc601
PB
978 gen_helper_0i(raise_exception, EXCP_SC); \
979 gen_set_label(l2); \
980 tcg_gen_movi_tl(t0, 0); \
981 gen_store_gpr(t0, rt); \
982 tcg_temp_free(t0); \
983}
984#else
985#define OP_ST_ATOMIC(insn,fname,ldname,almask) \
5c13fdfd 986static inline void op_st_##insn(TCGv arg1, TCGv arg2, int rt, DisasContext *ctx) \
590bc601
PB
987{ \
988 TCGv t0 = tcg_temp_new(); \
e7139c44 989 gen_helper_3i(insn, t0, arg1, arg2, ctx->mem_idx); \
590bc601 990 gen_store_gpr(t0, rt); \
590bc601
PB
991 tcg_temp_free(t0); \
992}
993#endif
590bc601 994OP_ST_ATOMIC(sc,st32,ld32s,0x3);
aaa9128a 995#if defined(TARGET_MIPS64)
590bc601 996OP_ST_ATOMIC(scd,st64,ld64,0x7);
aaa9128a
TS
997#endif
998#undef OP_ST_ATOMIC
999
662d7485
NF
1000static void gen_base_offset_addr (DisasContext *ctx, TCGv addr,
1001 int base, int16_t offset)
1002{
1003 if (base == 0) {
1004 tcg_gen_movi_tl(addr, offset);
1005 } else if (offset == 0) {
1006 gen_load_gpr(addr, base);
1007 } else {
1008 tcg_gen_movi_tl(addr, offset);
1009 gen_op_addr_add(ctx, addr, cpu_gpr[base], addr);
1010 }
1011}
1012
364d4831
NF
1013static target_ulong pc_relative_pc (DisasContext *ctx)
1014{
1015 target_ulong pc = ctx->pc;
1016
1017 if (ctx->hflags & MIPS_HFLAG_BMASK) {
1018 int branch_bytes = ctx->hflags & MIPS_HFLAG_BDS16 ? 2 : 4;
1019
1020 pc -= branch_bytes;
1021 }
1022
1023 pc &= ~(target_ulong)3;
1024 return pc;
1025}
1026
5c13fdfd 1027/* Load */
7db13fae 1028static void gen_ld (CPUMIPSState *env, DisasContext *ctx, uint32_t opc,
afa88c3a 1029 int rt, int base, int16_t offset)
6af0bf9c 1030{
5c13fdfd 1031 const char *opn = "ld";
afa88c3a
AJ
1032 TCGv t0, t1;
1033
1034 if (rt == 0 && env->insn_flags & (INSN_LOONGSON2E | INSN_LOONGSON2F)) {
1035 /* Loongson CPU uses a load to zero register for prefetch.
1036 We emulate it as a NOP. On other CPU we must perform the
1037 actual memory access. */
1038 MIPS_DEBUG("NOP");
1039 return;
1040 }
6af0bf9c 1041
afa88c3a
AJ
1042 t0 = tcg_temp_new();
1043 t1 = tcg_temp_new();
662d7485 1044 gen_base_offset_addr(ctx, t0, base, offset);
afa88c3a 1045
6af0bf9c 1046 switch (opc) {
d26bc211 1047#if defined(TARGET_MIPS64)
6e473128 1048 case OPC_LWU:
d66c7132 1049 save_cpu_state(ctx, 0);
5c13fdfd 1050 op_ld_lwu(t0, t0, ctx);
78723684 1051 gen_store_gpr(t0, rt);
6e473128
TS
1052 opn = "lwu";
1053 break;
6af0bf9c 1054 case OPC_LD:
d66c7132 1055 save_cpu_state(ctx, 0);
5c13fdfd 1056 op_ld_ld(t0, t0, ctx);
78723684 1057 gen_store_gpr(t0, rt);
6af0bf9c
FB
1058 opn = "ld";
1059 break;
7a387fff 1060 case OPC_LLD:
b835e919 1061 save_cpu_state(ctx, 1);
5c13fdfd 1062 op_ld_lld(t0, t0, ctx);
78723684 1063 gen_store_gpr(t0, rt);
7a387fff
TS
1064 opn = "lld";
1065 break;
6af0bf9c 1066 case OPC_LDL:
c8c2227e 1067 save_cpu_state(ctx, 1);
78723684 1068 gen_load_gpr(t1, rt);
d9bea114 1069 gen_helper_3i(ldl, t1, t1, t0, ctx->mem_idx);
78723684 1070 gen_store_gpr(t1, rt);
6af0bf9c
FB
1071 opn = "ldl";
1072 break;
6af0bf9c 1073 case OPC_LDR:
c8c2227e 1074 save_cpu_state(ctx, 1);
78723684 1075 gen_load_gpr(t1, rt);
d9bea114 1076 gen_helper_3i(ldr, t1, t1, t0, ctx->mem_idx);
78723684 1077 gen_store_gpr(t1, rt);
6af0bf9c
FB
1078 opn = "ldr";
1079 break;
364d4831 1080 case OPC_LDPC:
b835e919 1081 save_cpu_state(ctx, 0);
364d4831
NF
1082 tcg_gen_movi_tl(t1, pc_relative_pc(ctx));
1083 gen_op_addr_add(ctx, t0, t0, t1);
5c13fdfd 1084 op_ld_ld(t0, t0, ctx);
364d4831 1085 gen_store_gpr(t0, rt);
5c13fdfd 1086 opn = "ldpc";
364d4831 1087 break;
6af0bf9c 1088#endif
364d4831 1089 case OPC_LWPC:
b835e919 1090 save_cpu_state(ctx, 0);
364d4831
NF
1091 tcg_gen_movi_tl(t1, pc_relative_pc(ctx));
1092 gen_op_addr_add(ctx, t0, t0, t1);
5c13fdfd 1093 op_ld_lw(t0, t0, ctx);
364d4831 1094 gen_store_gpr(t0, rt);
5c13fdfd 1095 opn = "lwpc";
364d4831 1096 break;
6af0bf9c 1097 case OPC_LW:
d66c7132 1098 save_cpu_state(ctx, 0);
5c13fdfd 1099 op_ld_lw(t0, t0, ctx);
78723684 1100 gen_store_gpr(t0, rt);
6af0bf9c
FB
1101 opn = "lw";
1102 break;
6af0bf9c 1103 case OPC_LH:
d66c7132 1104 save_cpu_state(ctx, 0);
5c13fdfd 1105 op_ld_lh(t0, t0, ctx);
78723684 1106 gen_store_gpr(t0, rt);
6af0bf9c
FB
1107 opn = "lh";
1108 break;
6af0bf9c 1109 case OPC_LHU:
d66c7132 1110 save_cpu_state(ctx, 0);
5c13fdfd 1111 op_ld_lhu(t0, t0, ctx);
78723684 1112 gen_store_gpr(t0, rt);
6af0bf9c
FB
1113 opn = "lhu";
1114 break;
1115 case OPC_LB:
d66c7132 1116 save_cpu_state(ctx, 0);
5c13fdfd 1117 op_ld_lb(t0, t0, ctx);
78723684 1118 gen_store_gpr(t0, rt);
6af0bf9c
FB
1119 opn = "lb";
1120 break;
6af0bf9c 1121 case OPC_LBU:
d66c7132 1122 save_cpu_state(ctx, 0);
5c13fdfd 1123 op_ld_lbu(t0, t0, ctx);
78723684 1124 gen_store_gpr(t0, rt);
6af0bf9c
FB
1125 opn = "lbu";
1126 break;
1127 case OPC_LWL:
c8c2227e 1128 save_cpu_state(ctx, 1);
6958549d 1129 gen_load_gpr(t1, rt);
d9bea114 1130 gen_helper_3i(lwl, t1, t1, t0, ctx->mem_idx);
78723684 1131 gen_store_gpr(t1, rt);
6af0bf9c
FB
1132 opn = "lwl";
1133 break;
6af0bf9c 1134 case OPC_LWR:
c8c2227e 1135 save_cpu_state(ctx, 1);
6958549d 1136 gen_load_gpr(t1, rt);
d9bea114 1137 gen_helper_3i(lwr, t1, t1, t0, ctx->mem_idx);
78723684 1138 gen_store_gpr(t1, rt);
6af0bf9c
FB
1139 opn = "lwr";
1140 break;
6af0bf9c 1141 case OPC_LL:
e7139c44 1142 save_cpu_state(ctx, 1);
5c13fdfd 1143 op_ld_ll(t0, t0, ctx);
78723684 1144 gen_store_gpr(t0, rt);
6af0bf9c
FB
1145 opn = "ll";
1146 break;
d66c7132 1147 }
2abf314d 1148 (void)opn; /* avoid a compiler warning */
d66c7132
AJ
1149 MIPS_DEBUG("%s %s, %d(%s)", opn, regnames[rt], offset, regnames[base]);
1150 tcg_temp_free(t0);
1151 tcg_temp_free(t1);
1152}
1153
5c13fdfd
AJ
1154/* Store */
1155static void gen_st (DisasContext *ctx, uint32_t opc, int rt,
1156 int base, int16_t offset)
1157{
1158 const char *opn = "st";
1159 TCGv t0 = tcg_temp_new();
1160 TCGv t1 = tcg_temp_new();
1161
1162 gen_base_offset_addr(ctx, t0, base, offset);
1163 gen_load_gpr(t1, rt);
1164 switch (opc) {
1165#if defined(TARGET_MIPS64)
1166 case OPC_SD:
1167 save_cpu_state(ctx, 0);
1168 op_st_sd(t1, t0, ctx);
1169 opn = "sd";
1170 break;
1171 case OPC_SDL:
1172 save_cpu_state(ctx, 1);
1173 gen_helper_2i(sdl, t1, t0, ctx->mem_idx);
1174 opn = "sdl";
1175 break;
1176 case OPC_SDR:
1177 save_cpu_state(ctx, 1);
1178 gen_helper_2i(sdr, t1, t0, ctx->mem_idx);
1179 opn = "sdr";
1180 break;
1181#endif
1182 case OPC_SW:
1183 save_cpu_state(ctx, 0);
1184 op_st_sw(t1, t0, ctx);
1185 opn = "sw";
1186 break;
1187 case OPC_SH:
1188 save_cpu_state(ctx, 0);
1189 op_st_sh(t1, t0, ctx);
1190 opn = "sh";
1191 break;
1192 case OPC_SB:
1193 save_cpu_state(ctx, 0);
1194 op_st_sb(t1, t0, ctx);
1195 opn = "sb";
1196 break;
1197 case OPC_SWL:
1198 save_cpu_state(ctx, 1);
1199 gen_helper_2i(swl, t1, t0, ctx->mem_idx);
1200 opn = "swl";
1201 break;
1202 case OPC_SWR:
1203 save_cpu_state(ctx, 1);
1204 gen_helper_2i(swr, t1, t0, ctx->mem_idx);
1205 opn = "swr";
1206 break;
1207 }
2abf314d 1208 (void)opn; /* avoid a compiler warning */
5c13fdfd
AJ
1209 MIPS_DEBUG("%s %s, %d(%s)", opn, regnames[rt], offset, regnames[base]);
1210 tcg_temp_free(t0);
1211 tcg_temp_free(t1);
1212}
1213
1214
d66c7132
AJ
1215/* Store conditional */
1216static void gen_st_cond (DisasContext *ctx, uint32_t opc, int rt,
1217 int base, int16_t offset)
1218{
1219 const char *opn = "st_cond";
1220 TCGv t0, t1;
1221
1222 t0 = tcg_temp_local_new();
1223
662d7485 1224 gen_base_offset_addr(ctx, t0, base, offset);
d66c7132
AJ
1225 /* Don't do NOP if destination is zero: we must perform the actual
1226 memory access. */
1227
1228 t1 = tcg_temp_local_new();
1229 gen_load_gpr(t1, rt);
1230 switch (opc) {
1231#if defined(TARGET_MIPS64)
1232 case OPC_SCD:
b835e919 1233 save_cpu_state(ctx, 1);
5c13fdfd 1234 op_st_scd(t1, t0, rt, ctx);
d66c7132
AJ
1235 opn = "scd";
1236 break;
1237#endif
6af0bf9c 1238 case OPC_SC:
e7139c44 1239 save_cpu_state(ctx, 1);
5c13fdfd 1240 op_st_sc(t1, t0, rt, ctx);
6af0bf9c
FB
1241 opn = "sc";
1242 break;
6af0bf9c 1243 }
2abf314d 1244 (void)opn; /* avoid a compiler warning */
6af0bf9c 1245 MIPS_DEBUG("%s %s, %d(%s)", opn, regnames[rt], offset, regnames[base]);
78723684 1246 tcg_temp_free(t1);
d66c7132 1247 tcg_temp_free(t0);
6af0bf9c
FB
1248}
1249
6ea83fed 1250/* Load and store */
7a387fff 1251static void gen_flt_ldst (DisasContext *ctx, uint32_t opc, int ft,
356265ae 1252 int base, int16_t offset)
6ea83fed 1253{
923617a3 1254 const char *opn = "flt_ldst";
4e2474d6 1255 TCGv t0 = tcg_temp_new();
6ea83fed 1256
662d7485 1257 gen_base_offset_addr(ctx, t0, base, offset);
6ea83fed 1258 /* Don't do NOP if destination is zero: we must perform the actual
ead9360e 1259 memory access. */
6ea83fed
FB
1260 switch (opc) {
1261 case OPC_LWC1:
b6d96bed 1262 {
a7812ae4 1263 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed 1264
c407df81
AJ
1265 tcg_gen_qemu_ld32s(t0, t0, ctx->mem_idx);
1266 tcg_gen_trunc_tl_i32(fp0, t0);
b6d96bed 1267 gen_store_fpr32(fp0, ft);
a7812ae4 1268 tcg_temp_free_i32(fp0);
b6d96bed 1269 }
6ea83fed
FB
1270 opn = "lwc1";
1271 break;
1272 case OPC_SWC1:
b6d96bed 1273 {
a7812ae4
PB
1274 TCGv_i32 fp0 = tcg_temp_new_i32();
1275 TCGv t1 = tcg_temp_new();
b6d96bed
TS
1276
1277 gen_load_fpr32(fp0, ft);
a7812ae4
PB
1278 tcg_gen_extu_i32_tl(t1, fp0);
1279 tcg_gen_qemu_st32(t1, t0, ctx->mem_idx);
1280 tcg_temp_free(t1);
1281 tcg_temp_free_i32(fp0);
b6d96bed 1282 }
6ea83fed
FB
1283 opn = "swc1";
1284 break;
1285 case OPC_LDC1:
b6d96bed 1286 {
a7812ae4 1287 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
1288
1289 tcg_gen_qemu_ld64(fp0, t0, ctx->mem_idx);
1290 gen_store_fpr64(ctx, fp0, ft);
a7812ae4 1291 tcg_temp_free_i64(fp0);
b6d96bed 1292 }
6ea83fed
FB
1293 opn = "ldc1";
1294 break;
1295 case OPC_SDC1:
b6d96bed 1296 {
a7812ae4 1297 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
1298
1299 gen_load_fpr64(ctx, fp0, ft);
1300 tcg_gen_qemu_st64(fp0, t0, ctx->mem_idx);
a7812ae4 1301 tcg_temp_free_i64(fp0);
b6d96bed 1302 }
6ea83fed
FB
1303 opn = "sdc1";
1304 break;
1305 default:
923617a3 1306 MIPS_INVAL(opn);
e397ee33 1307 generate_exception(ctx, EXCP_RI);
78723684 1308 goto out;
6ea83fed 1309 }
2abf314d 1310 (void)opn; /* avoid a compiler warning */
6ea83fed 1311 MIPS_DEBUG("%s %s, %d(%s)", opn, fregnames[ft], offset, regnames[base]);
78723684
TS
1312 out:
1313 tcg_temp_free(t0);
6ea83fed 1314}
6ea83fed 1315
7db13fae 1316static void gen_cop1_ldst(CPUMIPSState *env, DisasContext *ctx,
26ebe468
NF
1317 uint32_t op, int rt, int rs, int16_t imm)
1318{
1319 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
1320 check_cp1_enabled(ctx);
1321 gen_flt_ldst(ctx, op, rt, rs, imm);
1322 } else {
1323 generate_exception_err(ctx, EXCP_CpU, 1);
1324 }
1325}
1326
6af0bf9c 1327/* Arithmetic with immediate operand */
7db13fae 1328static void gen_arith_imm (CPUMIPSState *env, DisasContext *ctx, uint32_t opc,
e189e748 1329 int rt, int rs, int16_t imm)
6af0bf9c 1330{
324d9e32 1331 target_ulong uimm = (target_long)imm; /* Sign extend to 32/64 bits */
923617a3 1332 const char *opn = "imm arith";
6af0bf9c 1333
7a387fff 1334 if (rt == 0 && opc != OPC_ADDI && opc != OPC_DADDI) {
ead9360e
TS
1335 /* If no destination, treat it as a NOP.
1336 For addi, we must generate the overflow exception when needed. */
6af0bf9c 1337 MIPS_DEBUG("NOP");
324d9e32 1338 return;
6af0bf9c
FB
1339 }
1340 switch (opc) {
1341 case OPC_ADDI:
48d38ca5 1342 {
324d9e32
AJ
1343 TCGv t0 = tcg_temp_local_new();
1344 TCGv t1 = tcg_temp_new();
1345 TCGv t2 = tcg_temp_new();
48d38ca5
TS
1346 int l1 = gen_new_label();
1347
324d9e32
AJ
1348 gen_load_gpr(t1, rs);
1349 tcg_gen_addi_tl(t0, t1, uimm);
1350 tcg_gen_ext32s_tl(t0, t0);
48d38ca5 1351
324d9e32
AJ
1352 tcg_gen_xori_tl(t1, t1, ~uimm);
1353 tcg_gen_xori_tl(t2, t0, uimm);
1354 tcg_gen_and_tl(t1, t1, t2);
1355 tcg_temp_free(t2);
1356 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
1357 tcg_temp_free(t1);
48d38ca5
TS
1358 /* operands of same sign, result different sign */
1359 generate_exception(ctx, EXCP_OVERFLOW);
1360 gen_set_label(l1);
78723684 1361 tcg_gen_ext32s_tl(t0, t0);
324d9e32
AJ
1362 gen_store_gpr(t0, rt);
1363 tcg_temp_free(t0);
48d38ca5 1364 }
6af0bf9c
FB
1365 opn = "addi";
1366 break;
1367 case OPC_ADDIU:
324d9e32
AJ
1368 if (rs != 0) {
1369 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
1370 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
1371 } else {
1372 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
1373 }
6af0bf9c
FB
1374 opn = "addiu";
1375 break;
d26bc211 1376#if defined(TARGET_MIPS64)
7a387fff 1377 case OPC_DADDI:
48d38ca5 1378 {
324d9e32
AJ
1379 TCGv t0 = tcg_temp_local_new();
1380 TCGv t1 = tcg_temp_new();
1381 TCGv t2 = tcg_temp_new();
48d38ca5
TS
1382 int l1 = gen_new_label();
1383
324d9e32
AJ
1384 gen_load_gpr(t1, rs);
1385 tcg_gen_addi_tl(t0, t1, uimm);
48d38ca5 1386
324d9e32
AJ
1387 tcg_gen_xori_tl(t1, t1, ~uimm);
1388 tcg_gen_xori_tl(t2, t0, uimm);
1389 tcg_gen_and_tl(t1, t1, t2);
1390 tcg_temp_free(t2);
1391 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
1392 tcg_temp_free(t1);
48d38ca5
TS
1393 /* operands of same sign, result different sign */
1394 generate_exception(ctx, EXCP_OVERFLOW);
1395 gen_set_label(l1);
324d9e32
AJ
1396 gen_store_gpr(t0, rt);
1397 tcg_temp_free(t0);
48d38ca5 1398 }
7a387fff
TS
1399 opn = "daddi";
1400 break;
1401 case OPC_DADDIU:
324d9e32
AJ
1402 if (rs != 0) {
1403 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
1404 } else {
1405 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
1406 }
7a387fff
TS
1407 opn = "daddiu";
1408 break;
1409#endif
324d9e32 1410 }
2abf314d 1411 (void)opn; /* avoid a compiler warning */
324d9e32
AJ
1412 MIPS_DEBUG("%s %s, %s, " TARGET_FMT_lx, opn, regnames[rt], regnames[rs], uimm);
1413}
1414
1415/* Logic with immediate operand */
7db13fae 1416static void gen_logic_imm (CPUMIPSState *env, uint32_t opc, int rt, int rs, int16_t imm)
324d9e32
AJ
1417{
1418 target_ulong uimm;
1419 const char *opn = "imm logic";
1420
1421 if (rt == 0) {
1422 /* If no destination, treat it as a NOP. */
1423 MIPS_DEBUG("NOP");
1424 return;
1425 }
1426 uimm = (uint16_t)imm;
1427 switch (opc) {
6af0bf9c 1428 case OPC_ANDI:
324d9e32
AJ
1429 if (likely(rs != 0))
1430 tcg_gen_andi_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
1431 else
1432 tcg_gen_movi_tl(cpu_gpr[rt], 0);
6af0bf9c
FB
1433 opn = "andi";
1434 break;
1435 case OPC_ORI:
324d9e32
AJ
1436 if (rs != 0)
1437 tcg_gen_ori_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
1438 else
1439 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
6af0bf9c
FB
1440 opn = "ori";
1441 break;
1442 case OPC_XORI:
324d9e32
AJ
1443 if (likely(rs != 0))
1444 tcg_gen_xori_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
1445 else
1446 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
6af0bf9c
FB
1447 opn = "xori";
1448 break;
1449 case OPC_LUI:
324d9e32 1450 tcg_gen_movi_tl(cpu_gpr[rt], imm << 16);
6af0bf9c
FB
1451 opn = "lui";
1452 break;
324d9e32 1453 }
2abf314d 1454 (void)opn; /* avoid a compiler warning */
324d9e32
AJ
1455 MIPS_DEBUG("%s %s, %s, " TARGET_FMT_lx, opn, regnames[rt], regnames[rs], uimm);
1456}
1457
1458/* Set on less than with immediate operand */
7db13fae 1459static void gen_slt_imm (CPUMIPSState *env, uint32_t opc, int rt, int rs, int16_t imm)
324d9e32
AJ
1460{
1461 target_ulong uimm = (target_long)imm; /* Sign extend to 32/64 bits */
1462 const char *opn = "imm arith";
1463 TCGv t0;
1464
1465 if (rt == 0) {
1466 /* If no destination, treat it as a NOP. */
1467 MIPS_DEBUG("NOP");
1468 return;
1469 }
1470 t0 = tcg_temp_new();
1471 gen_load_gpr(t0, rs);
1472 switch (opc) {
1473 case OPC_SLTI:
e68dd28f 1474 tcg_gen_setcondi_tl(TCG_COND_LT, cpu_gpr[rt], t0, uimm);
324d9e32
AJ
1475 opn = "slti";
1476 break;
1477 case OPC_SLTIU:
e68dd28f 1478 tcg_gen_setcondi_tl(TCG_COND_LTU, cpu_gpr[rt], t0, uimm);
324d9e32
AJ
1479 opn = "sltiu";
1480 break;
1481 }
2abf314d 1482 (void)opn; /* avoid a compiler warning */
324d9e32
AJ
1483 MIPS_DEBUG("%s %s, %s, " TARGET_FMT_lx, opn, regnames[rt], regnames[rs], uimm);
1484 tcg_temp_free(t0);
1485}
1486
1487/* Shifts with immediate operand */
7db13fae 1488static void gen_shift_imm(CPUMIPSState *env, DisasContext *ctx, uint32_t opc,
324d9e32
AJ
1489 int rt, int rs, int16_t imm)
1490{
1491 target_ulong uimm = ((uint16_t)imm) & 0x1f;
1492 const char *opn = "imm shift";
1493 TCGv t0;
1494
1495 if (rt == 0) {
1496 /* If no destination, treat it as a NOP. */
1497 MIPS_DEBUG("NOP");
1498 return;
1499 }
1500
1501 t0 = tcg_temp_new();
1502 gen_load_gpr(t0, rs);
1503 switch (opc) {
6af0bf9c 1504 case OPC_SLL:
78723684 1505 tcg_gen_shli_tl(t0, t0, uimm);
324d9e32 1506 tcg_gen_ext32s_tl(cpu_gpr[rt], t0);
6af0bf9c
FB
1507 opn = "sll";
1508 break;
1509 case OPC_SRA:
324d9e32 1510 tcg_gen_sari_tl(cpu_gpr[rt], t0, uimm);
6af0bf9c
FB
1511 opn = "sra";
1512 break;
1513 case OPC_SRL:
ea63e2c3
NF
1514 if (uimm != 0) {
1515 tcg_gen_ext32u_tl(t0, t0);
1516 tcg_gen_shri_tl(cpu_gpr[rt], t0, uimm);
1517 } else {
1518 tcg_gen_ext32s_tl(cpu_gpr[rt], t0);
5a63bcb2 1519 }
ea63e2c3
NF
1520 opn = "srl";
1521 break;
1522 case OPC_ROTR:
1523 if (uimm != 0) {
1524 TCGv_i32 t1 = tcg_temp_new_i32();
1525
1526 tcg_gen_trunc_tl_i32(t1, t0);
1527 tcg_gen_rotri_i32(t1, t1, uimm);
1528 tcg_gen_ext_i32_tl(cpu_gpr[rt], t1);
1529 tcg_temp_free_i32(t1);
3399e30f
NF
1530 } else {
1531 tcg_gen_ext32s_tl(cpu_gpr[rt], t0);
ea63e2c3
NF
1532 }
1533 opn = "rotr";
7a387fff 1534 break;
d26bc211 1535#if defined(TARGET_MIPS64)
7a387fff 1536 case OPC_DSLL:
324d9e32 1537 tcg_gen_shli_tl(cpu_gpr[rt], t0, uimm);
7a387fff
TS
1538 opn = "dsll";
1539 break;
1540 case OPC_DSRA:
324d9e32 1541 tcg_gen_sari_tl(cpu_gpr[rt], t0, uimm);
7a387fff
TS
1542 opn = "dsra";
1543 break;
1544 case OPC_DSRL:
ea63e2c3
NF
1545 tcg_gen_shri_tl(cpu_gpr[rt], t0, uimm);
1546 opn = "dsrl";
1547 break;
1548 case OPC_DROTR:
1549 if (uimm != 0) {
1550 tcg_gen_rotri_tl(cpu_gpr[rt], t0, uimm);
3399e30f
NF
1551 } else {
1552 tcg_gen_mov_tl(cpu_gpr[rt], t0);
5a63bcb2 1553 }
ea63e2c3 1554 opn = "drotr";
7a387fff
TS
1555 break;
1556 case OPC_DSLL32:
324d9e32 1557 tcg_gen_shli_tl(cpu_gpr[rt], t0, uimm + 32);
7a387fff
TS
1558 opn = "dsll32";
1559 break;
1560 case OPC_DSRA32:
324d9e32 1561 tcg_gen_sari_tl(cpu_gpr[rt], t0, uimm + 32);
7a387fff
TS
1562 opn = "dsra32";
1563 break;
1564 case OPC_DSRL32:
ea63e2c3
NF
1565 tcg_gen_shri_tl(cpu_gpr[rt], t0, uimm + 32);
1566 opn = "dsrl32";
1567 break;
1568 case OPC_DROTR32:
1569 tcg_gen_rotri_tl(cpu_gpr[rt], t0, uimm + 32);
1570 opn = "drotr32";
6af0bf9c 1571 break;
7a387fff 1572#endif
6af0bf9c 1573 }
2abf314d 1574 (void)opn; /* avoid a compiler warning */
93b12ccc 1575 MIPS_DEBUG("%s %s, %s, " TARGET_FMT_lx, opn, regnames[rt], regnames[rs], uimm);
78723684 1576 tcg_temp_free(t0);
6af0bf9c
FB
1577}
1578
1579/* Arithmetic */
7db13fae 1580static void gen_arith (CPUMIPSState *env, DisasContext *ctx, uint32_t opc,
6af0bf9c
FB
1581 int rd, int rs, int rt)
1582{
923617a3 1583 const char *opn = "arith";
6af0bf9c 1584
7a387fff
TS
1585 if (rd == 0 && opc != OPC_ADD && opc != OPC_SUB
1586 && opc != OPC_DADD && opc != OPC_DSUB) {
ead9360e
TS
1587 /* If no destination, treat it as a NOP.
1588 For add & sub, we must generate the overflow exception when needed. */
6af0bf9c 1589 MIPS_DEBUG("NOP");
460f00c4 1590 return;
185f0762 1591 }
460f00c4 1592
6af0bf9c
FB
1593 switch (opc) {
1594 case OPC_ADD:
48d38ca5 1595 {
460f00c4
AJ
1596 TCGv t0 = tcg_temp_local_new();
1597 TCGv t1 = tcg_temp_new();
1598 TCGv t2 = tcg_temp_new();
48d38ca5
TS
1599 int l1 = gen_new_label();
1600
460f00c4
AJ
1601 gen_load_gpr(t1, rs);
1602 gen_load_gpr(t2, rt);
1603 tcg_gen_add_tl(t0, t1, t2);
1604 tcg_gen_ext32s_tl(t0, t0);
1605 tcg_gen_xor_tl(t1, t1, t2);
460f00c4 1606 tcg_gen_xor_tl(t2, t0, t2);
deb4203d 1607 tcg_gen_andc_tl(t1, t2, t1);
460f00c4
AJ
1608 tcg_temp_free(t2);
1609 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
1610 tcg_temp_free(t1);
48d38ca5
TS
1611 /* operands of same sign, result different sign */
1612 generate_exception(ctx, EXCP_OVERFLOW);
1613 gen_set_label(l1);
460f00c4
AJ
1614 gen_store_gpr(t0, rd);
1615 tcg_temp_free(t0);
48d38ca5 1616 }
6af0bf9c
FB
1617 opn = "add";
1618 break;
1619 case OPC_ADDU:
460f00c4
AJ
1620 if (rs != 0 && rt != 0) {
1621 tcg_gen_add_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
1622 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
1623 } else if (rs == 0 && rt != 0) {
1624 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
1625 } else if (rs != 0 && rt == 0) {
1626 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
1627 } else {
1628 tcg_gen_movi_tl(cpu_gpr[rd], 0);
1629 }
6af0bf9c
FB
1630 opn = "addu";
1631 break;
1632 case OPC_SUB:
48d38ca5 1633 {
460f00c4
AJ
1634 TCGv t0 = tcg_temp_local_new();
1635 TCGv t1 = tcg_temp_new();
1636 TCGv t2 = tcg_temp_new();
48d38ca5
TS
1637 int l1 = gen_new_label();
1638
460f00c4
AJ
1639 gen_load_gpr(t1, rs);
1640 gen_load_gpr(t2, rt);
1641 tcg_gen_sub_tl(t0, t1, t2);
1642 tcg_gen_ext32s_tl(t0, t0);
1643 tcg_gen_xor_tl(t2, t1, t2);
1644 tcg_gen_xor_tl(t1, t0, t1);
1645 tcg_gen_and_tl(t1, t1, t2);
1646 tcg_temp_free(t2);
1647 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
1648 tcg_temp_free(t1);
31e3104f 1649 /* operands of different sign, first operand and result different sign */
48d38ca5
TS
1650 generate_exception(ctx, EXCP_OVERFLOW);
1651 gen_set_label(l1);
460f00c4
AJ
1652 gen_store_gpr(t0, rd);
1653 tcg_temp_free(t0);
48d38ca5 1654 }
6af0bf9c
FB
1655 opn = "sub";
1656 break;
1657 case OPC_SUBU:
460f00c4
AJ
1658 if (rs != 0 && rt != 0) {
1659 tcg_gen_sub_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
1660 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
1661 } else if (rs == 0 && rt != 0) {
1662 tcg_gen_neg_tl(cpu_gpr[rd], cpu_gpr[rt]);
6bb72b18 1663 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
460f00c4
AJ
1664 } else if (rs != 0 && rt == 0) {
1665 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
1666 } else {
1667 tcg_gen_movi_tl(cpu_gpr[rd], 0);
1668 }
6af0bf9c
FB
1669 opn = "subu";
1670 break;
d26bc211 1671#if defined(TARGET_MIPS64)
7a387fff 1672 case OPC_DADD:
48d38ca5 1673 {
460f00c4
AJ
1674 TCGv t0 = tcg_temp_local_new();
1675 TCGv t1 = tcg_temp_new();
1676 TCGv t2 = tcg_temp_new();
48d38ca5
TS
1677 int l1 = gen_new_label();
1678
460f00c4
AJ
1679 gen_load_gpr(t1, rs);
1680 gen_load_gpr(t2, rt);
1681 tcg_gen_add_tl(t0, t1, t2);
1682 tcg_gen_xor_tl(t1, t1, t2);
460f00c4 1683 tcg_gen_xor_tl(t2, t0, t2);
deb4203d 1684 tcg_gen_andc_tl(t1, t2, t1);
460f00c4
AJ
1685 tcg_temp_free(t2);
1686 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
1687 tcg_temp_free(t1);
48d38ca5
TS
1688 /* operands of same sign, result different sign */
1689 generate_exception(ctx, EXCP_OVERFLOW);
1690 gen_set_label(l1);
460f00c4
AJ
1691 gen_store_gpr(t0, rd);
1692 tcg_temp_free(t0);
48d38ca5 1693 }
7a387fff
TS
1694 opn = "dadd";
1695 break;
1696 case OPC_DADDU:
460f00c4
AJ
1697 if (rs != 0 && rt != 0) {
1698 tcg_gen_add_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
1699 } else if (rs == 0 && rt != 0) {
1700 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
1701 } else if (rs != 0 && rt == 0) {
1702 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
1703 } else {
1704 tcg_gen_movi_tl(cpu_gpr[rd], 0);
1705 }
7a387fff
TS
1706 opn = "daddu";
1707 break;
1708 case OPC_DSUB:
48d38ca5 1709 {
460f00c4
AJ
1710 TCGv t0 = tcg_temp_local_new();
1711 TCGv t1 = tcg_temp_new();
1712 TCGv t2 = tcg_temp_new();
48d38ca5
TS
1713 int l1 = gen_new_label();
1714
460f00c4
AJ
1715 gen_load_gpr(t1, rs);
1716 gen_load_gpr(t2, rt);
1717 tcg_gen_sub_tl(t0, t1, t2);
1718 tcg_gen_xor_tl(t2, t1, t2);
1719 tcg_gen_xor_tl(t1, t0, t1);
1720 tcg_gen_and_tl(t1, t1, t2);
1721 tcg_temp_free(t2);
1722 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
1723 tcg_temp_free(t1);
31e3104f 1724 /* operands of different sign, first operand and result different sign */
48d38ca5
TS
1725 generate_exception(ctx, EXCP_OVERFLOW);
1726 gen_set_label(l1);
460f00c4
AJ
1727 gen_store_gpr(t0, rd);
1728 tcg_temp_free(t0);
48d38ca5 1729 }
7a387fff
TS
1730 opn = "dsub";
1731 break;
1732 case OPC_DSUBU:
460f00c4
AJ
1733 if (rs != 0 && rt != 0) {
1734 tcg_gen_sub_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
1735 } else if (rs == 0 && rt != 0) {
1736 tcg_gen_neg_tl(cpu_gpr[rd], cpu_gpr[rt]);
1737 } else if (rs != 0 && rt == 0) {
1738 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
1739 } else {
1740 tcg_gen_movi_tl(cpu_gpr[rd], 0);
1741 }
7a387fff
TS
1742 opn = "dsubu";
1743 break;
1744#endif
460f00c4
AJ
1745 case OPC_MUL:
1746 if (likely(rs != 0 && rt != 0)) {
1747 tcg_gen_mul_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
1748 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
1749 } else {
1750 tcg_gen_movi_tl(cpu_gpr[rd], 0);
1751 }
1752 opn = "mul";
6af0bf9c 1753 break;
460f00c4 1754 }
2abf314d 1755 (void)opn; /* avoid a compiler warning */
460f00c4
AJ
1756 MIPS_DEBUG("%s %s, %s, %s", opn, regnames[rd], regnames[rs], regnames[rt]);
1757}
1758
1759/* Conditional move */
7db13fae 1760static void gen_cond_move (CPUMIPSState *env, uint32_t opc, int rd, int rs, int rt)
460f00c4
AJ
1761{
1762 const char *opn = "cond move";
1763 int l1;
1764
1765 if (rd == 0) {
1766 /* If no destination, treat it as a NOP.
1767 For add & sub, we must generate the overflow exception when needed. */
1768 MIPS_DEBUG("NOP");
1769 return;
1770 }
1771
1772 l1 = gen_new_label();
1773 switch (opc) {
1774 case OPC_MOVN:
1775 if (likely(rt != 0))
1776 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[rt], 0, l1);
1777 else
1778 tcg_gen_br(l1);
1779 opn = "movn";
6af0bf9c 1780 break;
460f00c4
AJ
1781 case OPC_MOVZ:
1782 if (likely(rt != 0))
1783 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[rt], 0, l1);
1784 opn = "movz";
1785 break;
1786 }
1787 if (rs != 0)
1788 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
1789 else
1790 tcg_gen_movi_tl(cpu_gpr[rd], 0);
1791 gen_set_label(l1);
1792
2abf314d 1793 (void)opn; /* avoid a compiler warning */
460f00c4
AJ
1794 MIPS_DEBUG("%s %s, %s, %s", opn, regnames[rd], regnames[rs], regnames[rt]);
1795}
1796
1797/* Logic */
7db13fae 1798static void gen_logic (CPUMIPSState *env, uint32_t opc, int rd, int rs, int rt)
460f00c4
AJ
1799{
1800 const char *opn = "logic";
1801
1802 if (rd == 0) {
1803 /* If no destination, treat it as a NOP. */
1804 MIPS_DEBUG("NOP");
1805 return;
1806 }
1807
1808 switch (opc) {
6af0bf9c 1809 case OPC_AND:
460f00c4
AJ
1810 if (likely(rs != 0 && rt != 0)) {
1811 tcg_gen_and_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
1812 } else {
1813 tcg_gen_movi_tl(cpu_gpr[rd], 0);
1814 }
6af0bf9c
FB
1815 opn = "and";
1816 break;
1817 case OPC_NOR:
460f00c4
AJ
1818 if (rs != 0 && rt != 0) {
1819 tcg_gen_nor_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
1820 } else if (rs == 0 && rt != 0) {
1821 tcg_gen_not_tl(cpu_gpr[rd], cpu_gpr[rt]);
1822 } else if (rs != 0 && rt == 0) {
1823 tcg_gen_not_tl(cpu_gpr[rd], cpu_gpr[rs]);
1824 } else {
1825 tcg_gen_movi_tl(cpu_gpr[rd], ~((target_ulong)0));
1826 }
6af0bf9c
FB
1827 opn = "nor";
1828 break;
1829 case OPC_OR:
460f00c4
AJ
1830 if (likely(rs != 0 && rt != 0)) {
1831 tcg_gen_or_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
1832 } else if (rs == 0 && rt != 0) {
1833 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
1834 } else if (rs != 0 && rt == 0) {
1835 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
1836 } else {
1837 tcg_gen_movi_tl(cpu_gpr[rd], 0);
1838 }
6af0bf9c
FB
1839 opn = "or";
1840 break;
1841 case OPC_XOR:
460f00c4
AJ
1842 if (likely(rs != 0 && rt != 0)) {
1843 tcg_gen_xor_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
1844 } else if (rs == 0 && rt != 0) {
1845 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
1846 } else if (rs != 0 && rt == 0) {
1847 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
1848 } else {
1849 tcg_gen_movi_tl(cpu_gpr[rd], 0);
1850 }
6af0bf9c
FB
1851 opn = "xor";
1852 break;
460f00c4 1853 }
2abf314d 1854 (void)opn; /* avoid a compiler warning */
460f00c4
AJ
1855 MIPS_DEBUG("%s %s, %s, %s", opn, regnames[rd], regnames[rs], regnames[rt]);
1856}
1857
1858/* Set on lower than */
7db13fae 1859static void gen_slt (CPUMIPSState *env, uint32_t opc, int rd, int rs, int rt)
460f00c4
AJ
1860{
1861 const char *opn = "slt";
1862 TCGv t0, t1;
1863
1864 if (rd == 0) {
1865 /* If no destination, treat it as a NOP. */
1866 MIPS_DEBUG("NOP");
1867 return;
1868 }
1869
1870 t0 = tcg_temp_new();
1871 t1 = tcg_temp_new();
1872 gen_load_gpr(t0, rs);
1873 gen_load_gpr(t1, rt);
1874 switch (opc) {
1875 case OPC_SLT:
e68dd28f 1876 tcg_gen_setcond_tl(TCG_COND_LT, cpu_gpr[rd], t0, t1);
460f00c4 1877 opn = "slt";
6af0bf9c 1878 break;
460f00c4 1879 case OPC_SLTU:
e68dd28f 1880 tcg_gen_setcond_tl(TCG_COND_LTU, cpu_gpr[rd], t0, t1);
460f00c4
AJ
1881 opn = "sltu";
1882 break;
1883 }
2abf314d 1884 (void)opn; /* avoid a compiler warning */
460f00c4
AJ
1885 MIPS_DEBUG("%s %s, %s, %s", opn, regnames[rd], regnames[rs], regnames[rt]);
1886 tcg_temp_free(t0);
1887 tcg_temp_free(t1);
1888}
20c4c97c 1889
460f00c4 1890/* Shifts */
7db13fae 1891static void gen_shift (CPUMIPSState *env, DisasContext *ctx, uint32_t opc,
460f00c4
AJ
1892 int rd, int rs, int rt)
1893{
1894 const char *opn = "shifts";
1895 TCGv t0, t1;
20c4c97c 1896
460f00c4
AJ
1897 if (rd == 0) {
1898 /* If no destination, treat it as a NOP.
1899 For add & sub, we must generate the overflow exception when needed. */
1900 MIPS_DEBUG("NOP");
1901 return;
1902 }
1903
1904 t0 = tcg_temp_new();
1905 t1 = tcg_temp_new();
1906 gen_load_gpr(t0, rs);
1907 gen_load_gpr(t1, rt);
1908 switch (opc) {
6af0bf9c 1909 case OPC_SLLV:
78723684
TS
1910 tcg_gen_andi_tl(t0, t0, 0x1f);
1911 tcg_gen_shl_tl(t0, t1, t0);
460f00c4 1912 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
6af0bf9c
FB
1913 opn = "sllv";
1914 break;
1915 case OPC_SRAV:
78723684 1916 tcg_gen_andi_tl(t0, t0, 0x1f);
460f00c4 1917 tcg_gen_sar_tl(cpu_gpr[rd], t1, t0);
6af0bf9c
FB
1918 opn = "srav";
1919 break;
1920 case OPC_SRLV:
ea63e2c3
NF
1921 tcg_gen_ext32u_tl(t1, t1);
1922 tcg_gen_andi_tl(t0, t0, 0x1f);
1923 tcg_gen_shr_tl(t0, t1, t0);
1924 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
1925 opn = "srlv";
1926 break;
1927 case OPC_ROTRV:
1928 {
1929 TCGv_i32 t2 = tcg_temp_new_i32();
1930 TCGv_i32 t3 = tcg_temp_new_i32();
1931
1932 tcg_gen_trunc_tl_i32(t2, t0);
1933 tcg_gen_trunc_tl_i32(t3, t1);
1934 tcg_gen_andi_i32(t2, t2, 0x1f);
1935 tcg_gen_rotr_i32(t2, t3, t2);
1936 tcg_gen_ext_i32_tl(cpu_gpr[rd], t2);
1937 tcg_temp_free_i32(t2);
1938 tcg_temp_free_i32(t3);
1939 opn = "rotrv";
5a63bcb2 1940 }
7a387fff 1941 break;
d26bc211 1942#if defined(TARGET_MIPS64)
7a387fff 1943 case OPC_DSLLV:
78723684 1944 tcg_gen_andi_tl(t0, t0, 0x3f);
460f00c4 1945 tcg_gen_shl_tl(cpu_gpr[rd], t1, t0);
7a387fff
TS
1946 opn = "dsllv";
1947 break;
1948 case OPC_DSRAV:
78723684 1949 tcg_gen_andi_tl(t0, t0, 0x3f);
460f00c4 1950 tcg_gen_sar_tl(cpu_gpr[rd], t1, t0);
7a387fff
TS
1951 opn = "dsrav";
1952 break;
1953 case OPC_DSRLV:
ea63e2c3
NF
1954 tcg_gen_andi_tl(t0, t0, 0x3f);
1955 tcg_gen_shr_tl(cpu_gpr[rd], t1, t0);
1956 opn = "dsrlv";
1957 break;
1958 case OPC_DROTRV:
1959 tcg_gen_andi_tl(t0, t0, 0x3f);
1960 tcg_gen_rotr_tl(cpu_gpr[rd], t1, t0);
1961 opn = "drotrv";
6af0bf9c 1962 break;
7a387fff 1963#endif
6af0bf9c 1964 }
2abf314d 1965 (void)opn; /* avoid a compiler warning */
6af0bf9c 1966 MIPS_DEBUG("%s %s, %s, %s", opn, regnames[rd], regnames[rs], regnames[rt]);
78723684
TS
1967 tcg_temp_free(t0);
1968 tcg_temp_free(t1);
6af0bf9c
FB
1969}
1970
1971/* Arithmetic on HI/LO registers */
7a387fff 1972static void gen_HILO (DisasContext *ctx, uint32_t opc, int reg)
6af0bf9c 1973{
923617a3 1974 const char *opn = "hilo";
6af0bf9c
FB
1975
1976 if (reg == 0 && (opc == OPC_MFHI || opc == OPC_MFLO)) {
ead9360e 1977 /* Treat as NOP. */
6af0bf9c 1978 MIPS_DEBUG("NOP");
a1f6684d 1979 return;
6af0bf9c
FB
1980 }
1981 switch (opc) {
1982 case OPC_MFHI:
a1f6684d 1983 tcg_gen_mov_tl(cpu_gpr[reg], cpu_HI[0]);
6af0bf9c
FB
1984 opn = "mfhi";
1985 break;
1986 case OPC_MFLO:
a1f6684d 1987 tcg_gen_mov_tl(cpu_gpr[reg], cpu_LO[0]);
6af0bf9c
FB
1988 opn = "mflo";
1989 break;
1990 case OPC_MTHI:
a1f6684d
AJ
1991 if (reg != 0)
1992 tcg_gen_mov_tl(cpu_HI[0], cpu_gpr[reg]);
1993 else
1994 tcg_gen_movi_tl(cpu_HI[0], 0);
6af0bf9c
FB
1995 opn = "mthi";
1996 break;
1997 case OPC_MTLO:
a1f6684d
AJ
1998 if (reg != 0)
1999 tcg_gen_mov_tl(cpu_LO[0], cpu_gpr[reg]);
2000 else
2001 tcg_gen_movi_tl(cpu_LO[0], 0);
6af0bf9c
FB
2002 opn = "mtlo";
2003 break;
6af0bf9c 2004 }
2abf314d 2005 (void)opn; /* avoid a compiler warning */
6af0bf9c
FB
2006 MIPS_DEBUG("%s %s", opn, regnames[reg]);
2007}
2008
7a387fff 2009static void gen_muldiv (DisasContext *ctx, uint32_t opc,
6af0bf9c
FB
2010 int rs, int rt)
2011{
923617a3 2012 const char *opn = "mul/div";
d45f89f4
AJ
2013 TCGv t0, t1;
2014
2015 switch (opc) {
2016 case OPC_DIV:
2017 case OPC_DIVU:
2018#if defined(TARGET_MIPS64)
2019 case OPC_DDIV:
2020 case OPC_DDIVU:
2021#endif
2022 t0 = tcg_temp_local_new();
2023 t1 = tcg_temp_local_new();
2024 break;
2025 default:
2026 t0 = tcg_temp_new();
2027 t1 = tcg_temp_new();
2028 break;
2029 }
6af0bf9c 2030
78723684
TS
2031 gen_load_gpr(t0, rs);
2032 gen_load_gpr(t1, rt);
6af0bf9c
FB
2033 switch (opc) {
2034 case OPC_DIV:
48d38ca5
TS
2035 {
2036 int l1 = gen_new_label();
d45f89f4 2037 int l2 = gen_new_label();
48d38ca5 2038
d45f89f4
AJ
2039 tcg_gen_ext32s_tl(t0, t0);
2040 tcg_gen_ext32s_tl(t1, t1);
78723684 2041 tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
d45f89f4
AJ
2042 tcg_gen_brcondi_tl(TCG_COND_NE, t0, INT_MIN, l2);
2043 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1, l2);
2044
2045 tcg_gen_mov_tl(cpu_LO[0], t0);
2046 tcg_gen_movi_tl(cpu_HI[0], 0);
2047 tcg_gen_br(l1);
2048 gen_set_label(l2);
2049 tcg_gen_div_tl(cpu_LO[0], t0, t1);
2050 tcg_gen_rem_tl(cpu_HI[0], t0, t1);
2051 tcg_gen_ext32s_tl(cpu_LO[0], cpu_LO[0]);
2052 tcg_gen_ext32s_tl(cpu_HI[0], cpu_HI[0]);
48d38ca5
TS
2053 gen_set_label(l1);
2054 }
6af0bf9c
FB
2055 opn = "div";
2056 break;
2057 case OPC_DIVU:
48d38ca5
TS
2058 {
2059 int l1 = gen_new_label();
2060
0c0ed03b
AJ
2061 tcg_gen_ext32u_tl(t0, t0);
2062 tcg_gen_ext32u_tl(t1, t1);
78723684 2063 tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
d45f89f4
AJ
2064 tcg_gen_divu_tl(cpu_LO[0], t0, t1);
2065 tcg_gen_remu_tl(cpu_HI[0], t0, t1);
2066 tcg_gen_ext32s_tl(cpu_LO[0], cpu_LO[0]);
2067 tcg_gen_ext32s_tl(cpu_HI[0], cpu_HI[0]);
48d38ca5
TS
2068 gen_set_label(l1);
2069 }
6af0bf9c
FB
2070 opn = "divu";
2071 break;
2072 case OPC_MULT:
214c465f 2073 {
d45f89f4
AJ
2074 TCGv_i64 t2 = tcg_temp_new_i64();
2075 TCGv_i64 t3 = tcg_temp_new_i64();
2076
2077 tcg_gen_ext_tl_i64(t2, t0);
2078 tcg_gen_ext_tl_i64(t3, t1);
2079 tcg_gen_mul_i64(t2, t2, t3);
2080 tcg_temp_free_i64(t3);
2081 tcg_gen_trunc_i64_tl(t0, t2);
2082 tcg_gen_shri_i64(t2, t2, 32);
2083 tcg_gen_trunc_i64_tl(t1, t2);
2084 tcg_temp_free_i64(t2);
b10fa3c9
AJ
2085 tcg_gen_ext32s_tl(cpu_LO[0], t0);
2086 tcg_gen_ext32s_tl(cpu_HI[0], t1);
214c465f 2087 }
6af0bf9c
FB
2088 opn = "mult";
2089 break;
2090 case OPC_MULTU:
214c465f 2091 {
d45f89f4
AJ
2092 TCGv_i64 t2 = tcg_temp_new_i64();
2093 TCGv_i64 t3 = tcg_temp_new_i64();
214c465f 2094
78723684
TS
2095 tcg_gen_ext32u_tl(t0, t0);
2096 tcg_gen_ext32u_tl(t1, t1);
d45f89f4
AJ
2097 tcg_gen_extu_tl_i64(t2, t0);
2098 tcg_gen_extu_tl_i64(t3, t1);
2099 tcg_gen_mul_i64(t2, t2, t3);
2100 tcg_temp_free_i64(t3);
2101 tcg_gen_trunc_i64_tl(t0, t2);
2102 tcg_gen_shri_i64(t2, t2, 32);
2103 tcg_gen_trunc_i64_tl(t1, t2);
2104 tcg_temp_free_i64(t2);
b10fa3c9
AJ
2105 tcg_gen_ext32s_tl(cpu_LO[0], t0);
2106 tcg_gen_ext32s_tl(cpu_HI[0], t1);
214c465f 2107 }
6af0bf9c
FB
2108 opn = "multu";
2109 break;
d26bc211 2110#if defined(TARGET_MIPS64)
7a387fff 2111 case OPC_DDIV:
48d38ca5
TS
2112 {
2113 int l1 = gen_new_label();
d45f89f4 2114 int l2 = gen_new_label();
48d38ca5 2115
78723684 2116 tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
d45f89f4
AJ
2117 tcg_gen_brcondi_tl(TCG_COND_NE, t0, -1LL << 63, l2);
2118 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1LL, l2);
2119 tcg_gen_mov_tl(cpu_LO[0], t0);
2120 tcg_gen_movi_tl(cpu_HI[0], 0);
2121 tcg_gen_br(l1);
2122 gen_set_label(l2);
2123 tcg_gen_div_i64(cpu_LO[0], t0, t1);
2124 tcg_gen_rem_i64(cpu_HI[0], t0, t1);
48d38ca5
TS
2125 gen_set_label(l1);
2126 }
7a387fff
TS
2127 opn = "ddiv";
2128 break;
2129 case OPC_DDIVU:
48d38ca5
TS
2130 {
2131 int l1 = gen_new_label();
2132
78723684 2133 tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
b10fa3c9
AJ
2134 tcg_gen_divu_i64(cpu_LO[0], t0, t1);
2135 tcg_gen_remu_i64(cpu_HI[0], t0, t1);
48d38ca5
TS
2136 gen_set_label(l1);
2137 }
7a387fff
TS
2138 opn = "ddivu";
2139 break;
2140 case OPC_DMULT:
a7812ae4 2141 gen_helper_dmult(t0, t1);
7a387fff
TS
2142 opn = "dmult";
2143 break;
2144 case OPC_DMULTU:
a7812ae4 2145 gen_helper_dmultu(t0, t1);
7a387fff
TS
2146 opn = "dmultu";
2147 break;
2148#endif
6af0bf9c 2149 case OPC_MADD:
214c465f 2150 {
d45f89f4
AJ
2151 TCGv_i64 t2 = tcg_temp_new_i64();
2152 TCGv_i64 t3 = tcg_temp_new_i64();
2153
2154 tcg_gen_ext_tl_i64(t2, t0);
2155 tcg_gen_ext_tl_i64(t3, t1);
2156 tcg_gen_mul_i64(t2, t2, t3);
2157 tcg_gen_concat_tl_i64(t3, cpu_LO[0], cpu_HI[0]);
2158 tcg_gen_add_i64(t2, t2, t3);
2159 tcg_temp_free_i64(t3);
2160 tcg_gen_trunc_i64_tl(t0, t2);
2161 tcg_gen_shri_i64(t2, t2, 32);
2162 tcg_gen_trunc_i64_tl(t1, t2);
2163 tcg_temp_free_i64(t2);
b10fa3c9 2164 tcg_gen_ext32s_tl(cpu_LO[0], t0);
98070ce0 2165 tcg_gen_ext32s_tl(cpu_HI[0], t1);
214c465f 2166 }
6af0bf9c
FB
2167 opn = "madd";
2168 break;
2169 case OPC_MADDU:
214c465f 2170 {
d45f89f4
AJ
2171 TCGv_i64 t2 = tcg_temp_new_i64();
2172 TCGv_i64 t3 = tcg_temp_new_i64();
214c465f 2173
78723684
TS
2174 tcg_gen_ext32u_tl(t0, t0);
2175 tcg_gen_ext32u_tl(t1, t1);
d45f89f4
AJ
2176 tcg_gen_extu_tl_i64(t2, t0);
2177 tcg_gen_extu_tl_i64(t3, t1);
2178 tcg_gen_mul_i64(t2, t2, t3);
2179 tcg_gen_concat_tl_i64(t3, cpu_LO[0], cpu_HI[0]);
2180 tcg_gen_add_i64(t2, t2, t3);
2181 tcg_temp_free_i64(t3);
2182 tcg_gen_trunc_i64_tl(t0, t2);
2183 tcg_gen_shri_i64(t2, t2, 32);
2184 tcg_gen_trunc_i64_tl(t1, t2);
2185 tcg_temp_free_i64(t2);
b10fa3c9
AJ
2186 tcg_gen_ext32s_tl(cpu_LO[0], t0);
2187 tcg_gen_ext32s_tl(cpu_HI[0], t1);
214c465f 2188 }
6af0bf9c
FB
2189 opn = "maddu";
2190 break;
2191 case OPC_MSUB:
214c465f 2192 {
d45f89f4
AJ
2193 TCGv_i64 t2 = tcg_temp_new_i64();
2194 TCGv_i64 t3 = tcg_temp_new_i64();
2195
2196 tcg_gen_ext_tl_i64(t2, t0);
2197 tcg_gen_ext_tl_i64(t3, t1);
2198 tcg_gen_mul_i64(t2, t2, t3);
2199 tcg_gen_concat_tl_i64(t3, cpu_LO[0], cpu_HI[0]);
98070ce0 2200 tcg_gen_sub_i64(t2, t3, t2);
d45f89f4
AJ
2201 tcg_temp_free_i64(t3);
2202 tcg_gen_trunc_i64_tl(t0, t2);
2203 tcg_gen_shri_i64(t2, t2, 32);
2204 tcg_gen_trunc_i64_tl(t1, t2);
2205 tcg_temp_free_i64(t2);
b10fa3c9
AJ
2206 tcg_gen_ext32s_tl(cpu_LO[0], t0);
2207 tcg_gen_ext32s_tl(cpu_HI[0], t1);
214c465f 2208 }
6af0bf9c
FB
2209 opn = "msub";
2210 break;
2211 case OPC_MSUBU:
214c465f 2212 {
d45f89f4
AJ
2213 TCGv_i64 t2 = tcg_temp_new_i64();
2214 TCGv_i64 t3 = tcg_temp_new_i64();
214c465f 2215
78723684
TS
2216 tcg_gen_ext32u_tl(t0, t0);
2217 tcg_gen_ext32u_tl(t1, t1);
d45f89f4
AJ
2218 tcg_gen_extu_tl_i64(t2, t0);
2219 tcg_gen_extu_tl_i64(t3, t1);
2220 tcg_gen_mul_i64(t2, t2, t3);
2221 tcg_gen_concat_tl_i64(t3, cpu_LO[0], cpu_HI[0]);
98070ce0 2222 tcg_gen_sub_i64(t2, t3, t2);
d45f89f4
AJ
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 = "msubu";
2232 break;
2233 default:
923617a3 2234 MIPS_INVAL(opn);
6af0bf9c 2235 generate_exception(ctx, EXCP_RI);
78723684 2236 goto out;
6af0bf9c 2237 }
2abf314d 2238 (void)opn; /* avoid a compiler warning */
6af0bf9c 2239 MIPS_DEBUG("%s %s %s", opn, regnames[rs], regnames[rt]);
78723684
TS
2240 out:
2241 tcg_temp_free(t0);
2242 tcg_temp_free(t1);
6af0bf9c
FB
2243}
2244
e9c71dd1
TS
2245static void gen_mul_vr54xx (DisasContext *ctx, uint32_t opc,
2246 int rd, int rs, int rt)
2247{
2248 const char *opn = "mul vr54xx";
f157bfe1
AJ
2249 TCGv t0 = tcg_temp_new();
2250 TCGv t1 = tcg_temp_new();
e9c71dd1 2251
6c5c1e20
TS
2252 gen_load_gpr(t0, rs);
2253 gen_load_gpr(t1, rt);
e9c71dd1
TS
2254
2255 switch (opc) {
2256 case OPC_VR54XX_MULS:
a7812ae4 2257 gen_helper_muls(t0, t0, t1);
e9c71dd1 2258 opn = "muls";
6958549d 2259 break;
e9c71dd1 2260 case OPC_VR54XX_MULSU:
a7812ae4 2261 gen_helper_mulsu(t0, t0, t1);
e9c71dd1 2262 opn = "mulsu";
6958549d 2263 break;
e9c71dd1 2264 case OPC_VR54XX_MACC:
a7812ae4 2265 gen_helper_macc(t0, t0, t1);
e9c71dd1 2266 opn = "macc";
6958549d 2267 break;
e9c71dd1 2268 case OPC_VR54XX_MACCU:
a7812ae4 2269 gen_helper_maccu(t0, t0, t1);
e9c71dd1 2270 opn = "maccu";
6958549d 2271 break;
e9c71dd1 2272 case OPC_VR54XX_MSAC:
a7812ae4 2273 gen_helper_msac(t0, t0, t1);
e9c71dd1 2274 opn = "msac";
6958549d 2275 break;
e9c71dd1 2276 case OPC_VR54XX_MSACU:
a7812ae4 2277 gen_helper_msacu(t0, t0, t1);
e9c71dd1 2278 opn = "msacu";
6958549d 2279 break;
e9c71dd1 2280 case OPC_VR54XX_MULHI:
a7812ae4 2281 gen_helper_mulhi(t0, t0, t1);
e9c71dd1 2282 opn = "mulhi";
6958549d 2283 break;
e9c71dd1 2284 case OPC_VR54XX_MULHIU:
a7812ae4 2285 gen_helper_mulhiu(t0, t0, t1);
e9c71dd1 2286 opn = "mulhiu";
6958549d 2287 break;
e9c71dd1 2288 case OPC_VR54XX_MULSHI:
a7812ae4 2289 gen_helper_mulshi(t0, t0, t1);
e9c71dd1 2290 opn = "mulshi";
6958549d 2291 break;
e9c71dd1 2292 case OPC_VR54XX_MULSHIU:
a7812ae4 2293 gen_helper_mulshiu(t0, t0, t1);
e9c71dd1 2294 opn = "mulshiu";
6958549d 2295 break;
e9c71dd1 2296 case OPC_VR54XX_MACCHI:
a7812ae4 2297 gen_helper_macchi(t0, t0, t1);
e9c71dd1 2298 opn = "macchi";
6958549d 2299 break;
e9c71dd1 2300 case OPC_VR54XX_MACCHIU:
a7812ae4 2301 gen_helper_macchiu(t0, t0, t1);
e9c71dd1 2302 opn = "macchiu";
6958549d 2303 break;
e9c71dd1 2304 case OPC_VR54XX_MSACHI:
a7812ae4 2305 gen_helper_msachi(t0, t0, t1);
e9c71dd1 2306 opn = "msachi";
6958549d 2307 break;
e9c71dd1 2308 case OPC_VR54XX_MSACHIU:
a7812ae4 2309 gen_helper_msachiu(t0, t0, t1);
e9c71dd1 2310 opn = "msachiu";
6958549d 2311 break;
e9c71dd1
TS
2312 default:
2313 MIPS_INVAL("mul vr54xx");
2314 generate_exception(ctx, EXCP_RI);
6c5c1e20 2315 goto out;
e9c71dd1 2316 }
6c5c1e20 2317 gen_store_gpr(t0, rd);
2abf314d 2318 (void)opn; /* avoid a compiler warning */
e9c71dd1 2319 MIPS_DEBUG("%s %s, %s, %s", opn, regnames[rd], regnames[rs], regnames[rt]);
6c5c1e20
TS
2320
2321 out:
2322 tcg_temp_free(t0);
2323 tcg_temp_free(t1);
e9c71dd1
TS
2324}
2325
7a387fff 2326static void gen_cl (DisasContext *ctx, uint32_t opc,
6af0bf9c
FB
2327 int rd, int rs)
2328{
923617a3 2329 const char *opn = "CLx";
20e1fb52 2330 TCGv t0;
6c5c1e20 2331
6af0bf9c 2332 if (rd == 0) {
ead9360e 2333 /* Treat as NOP. */
6af0bf9c 2334 MIPS_DEBUG("NOP");
20e1fb52 2335 return;
6af0bf9c 2336 }
20e1fb52 2337 t0 = tcg_temp_new();
6c5c1e20 2338 gen_load_gpr(t0, rs);
6af0bf9c
FB
2339 switch (opc) {
2340 case OPC_CLO:
20e1fb52 2341 gen_helper_clo(cpu_gpr[rd], t0);
6af0bf9c
FB
2342 opn = "clo";
2343 break;
2344 case OPC_CLZ:
20e1fb52 2345 gen_helper_clz(cpu_gpr[rd], t0);
6af0bf9c
FB
2346 opn = "clz";
2347 break;
d26bc211 2348#if defined(TARGET_MIPS64)
7a387fff 2349 case OPC_DCLO:
20e1fb52 2350 gen_helper_dclo(cpu_gpr[rd], t0);
7a387fff
TS
2351 opn = "dclo";
2352 break;
2353 case OPC_DCLZ:
20e1fb52 2354 gen_helper_dclz(cpu_gpr[rd], t0);
7a387fff
TS
2355 opn = "dclz";
2356 break;
2357#endif
6af0bf9c 2358 }
2abf314d 2359 (void)opn; /* avoid a compiler warning */
6af0bf9c 2360 MIPS_DEBUG("%s %s, %s", opn, regnames[rd], regnames[rs]);
6c5c1e20 2361 tcg_temp_free(t0);
6af0bf9c
FB
2362}
2363
161f85e6
AJ
2364/* Godson integer instructions */
2365static void gen_loongson_integer (DisasContext *ctx, uint32_t opc,
2366 int rd, int rs, int rt)
2367{
2368 const char *opn = "loongson";
2369 TCGv t0, t1;
2370
2371 if (rd == 0) {
2372 /* Treat as NOP. */
2373 MIPS_DEBUG("NOP");
2374 return;
2375 }
2376
2377 switch (opc) {
2378 case OPC_MULT_G_2E:
2379 case OPC_MULT_G_2F:
2380 case OPC_MULTU_G_2E:
2381 case OPC_MULTU_G_2F:
2382#if defined(TARGET_MIPS64)
2383 case OPC_DMULT_G_2E:
2384 case OPC_DMULT_G_2F:
2385 case OPC_DMULTU_G_2E:
2386 case OPC_DMULTU_G_2F:
2387#endif
2388 t0 = tcg_temp_new();
2389 t1 = tcg_temp_new();
2390 break;
2391 default:
2392 t0 = tcg_temp_local_new();
2393 t1 = tcg_temp_local_new();
2394 break;
2395 }
2396
2397 gen_load_gpr(t0, rs);
2398 gen_load_gpr(t1, rt);
2399
2400 switch (opc) {
2401 case OPC_MULT_G_2E:
2402 case OPC_MULT_G_2F:
2403 tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
2404 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
2405 opn = "mult.g";
2406 break;
2407 case OPC_MULTU_G_2E:
2408 case OPC_MULTU_G_2F:
2409 tcg_gen_ext32u_tl(t0, t0);
2410 tcg_gen_ext32u_tl(t1, t1);
2411 tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
2412 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
2413 opn = "multu.g";
2414 break;
2415 case OPC_DIV_G_2E:
2416 case OPC_DIV_G_2F:
2417 {
2418 int l1 = gen_new_label();
2419 int l2 = gen_new_label();
2420 int l3 = gen_new_label();
2421 tcg_gen_ext32s_tl(t0, t0);
2422 tcg_gen_ext32s_tl(t1, t1);
2423 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
2424 tcg_gen_movi_tl(cpu_gpr[rd], 0);
2425 tcg_gen_br(l3);
2426 gen_set_label(l1);
2427 tcg_gen_brcondi_tl(TCG_COND_NE, t0, INT_MIN, l2);
2428 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1, l2);
2429 tcg_gen_mov_tl(cpu_gpr[rd], t0);
2430 tcg_gen_br(l3);
2431 gen_set_label(l2);
2432 tcg_gen_div_tl(cpu_gpr[rd], t0, t1);
2433 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
2434 gen_set_label(l3);
2435 }
2436 opn = "div.g";
2437 break;
2438 case OPC_DIVU_G_2E:
2439 case OPC_DIVU_G_2F:
2440 {
2441 int l1 = gen_new_label();
2442 int l2 = gen_new_label();
2443 tcg_gen_ext32u_tl(t0, t0);
2444 tcg_gen_ext32u_tl(t1, t1);
2445 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
2446 tcg_gen_movi_tl(cpu_gpr[rd], 0);
2447 tcg_gen_br(l2);
2448 gen_set_label(l1);
2449 tcg_gen_divu_tl(cpu_gpr[rd], t0, t1);
2450 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
2451 gen_set_label(l2);
2452 }
2453 opn = "divu.g";
2454 break;
2455 case OPC_MOD_G_2E:
2456 case OPC_MOD_G_2F:
2457 {
2458 int l1 = gen_new_label();
2459 int l2 = gen_new_label();
2460 int l3 = gen_new_label();
2461 tcg_gen_ext32u_tl(t0, t0);
2462 tcg_gen_ext32u_tl(t1, t1);
2463 tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
2464 tcg_gen_brcondi_tl(TCG_COND_NE, t0, INT_MIN, l2);
2465 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1, l2);
2466 gen_set_label(l1);
2467 tcg_gen_movi_tl(cpu_gpr[rd], 0);
2468 tcg_gen_br(l3);
2469 gen_set_label(l2);
2470 tcg_gen_rem_tl(cpu_gpr[rd], t0, t1);
2471 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
2472 gen_set_label(l3);
2473 }
2474 opn = "mod.g";
2475 break;
2476 case OPC_MODU_G_2E:
2477 case OPC_MODU_G_2F:
2478 {
2479 int l1 = gen_new_label();
2480 int l2 = gen_new_label();
2481 tcg_gen_ext32u_tl(t0, t0);
2482 tcg_gen_ext32u_tl(t1, t1);
2483 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
2484 tcg_gen_movi_tl(cpu_gpr[rd], 0);
2485 tcg_gen_br(l2);
2486 gen_set_label(l1);
2487 tcg_gen_remu_tl(cpu_gpr[rd], t0, t1);
2488 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
2489 gen_set_label(l2);
2490 }
2491 opn = "modu.g";
2492 break;
2493#if defined(TARGET_MIPS64)
2494 case OPC_DMULT_G_2E:
2495 case OPC_DMULT_G_2F:
2496 tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
2497 opn = "dmult.g";
2498 break;
2499 case OPC_DMULTU_G_2E:
2500 case OPC_DMULTU_G_2F:
2501 tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
2502 opn = "dmultu.g";
2503 break;
2504 case OPC_DDIV_G_2E:
2505 case OPC_DDIV_G_2F:
2506 {
2507 int l1 = gen_new_label();
2508 int l2 = gen_new_label();
2509 int l3 = gen_new_label();
2510 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
2511 tcg_gen_movi_tl(cpu_gpr[rd], 0);
2512 tcg_gen_br(l3);
2513 gen_set_label(l1);
2514 tcg_gen_brcondi_tl(TCG_COND_NE, t0, -1LL << 63, l2);
2515 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1LL, l2);
2516 tcg_gen_mov_tl(cpu_gpr[rd], t0);
2517 tcg_gen_br(l3);
2518 gen_set_label(l2);
2519 tcg_gen_div_tl(cpu_gpr[rd], t0, t1);
2520 gen_set_label(l3);
2521 }
2522 opn = "ddiv.g";
2523 break;
2524 case OPC_DDIVU_G_2E:
2525 case OPC_DDIVU_G_2F:
2526 {
2527 int l1 = gen_new_label();
2528 int l2 = gen_new_label();
2529 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
2530 tcg_gen_movi_tl(cpu_gpr[rd], 0);
2531 tcg_gen_br(l2);
2532 gen_set_label(l1);
2533 tcg_gen_divu_tl(cpu_gpr[rd], t0, t1);
2534 gen_set_label(l2);
2535 }
2536 opn = "ddivu.g";
2537 break;
2538 case OPC_DMOD_G_2E:
2539 case OPC_DMOD_G_2F:
2540 {
2541 int l1 = gen_new_label();
2542 int l2 = gen_new_label();
2543 int l3 = gen_new_label();
2544 tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
2545 tcg_gen_brcondi_tl(TCG_COND_NE, t0, -1LL << 63, l2);
2546 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1LL, l2);
2547 gen_set_label(l1);
2548 tcg_gen_movi_tl(cpu_gpr[rd], 0);
2549 tcg_gen_br(l3);
2550 gen_set_label(l2);
2551 tcg_gen_rem_tl(cpu_gpr[rd], t0, t1);
2552 gen_set_label(l3);
2553 }
2554 opn = "dmod.g";
2555 break;
2556 case OPC_DMODU_G_2E:
2557 case OPC_DMODU_G_2F:
2558 {
2559 int l1 = gen_new_label();
2560 int l2 = gen_new_label();
2561 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
2562 tcg_gen_movi_tl(cpu_gpr[rd], 0);
2563 tcg_gen_br(l2);
2564 gen_set_label(l1);
2565 tcg_gen_remu_tl(cpu_gpr[rd], t0, t1);
2566 gen_set_label(l2);
2567 }
2568 opn = "dmodu.g";
2569 break;
2570#endif
2571 }
2572
2abf314d 2573 (void)opn; /* avoid a compiler warning */
161f85e6
AJ
2574 MIPS_DEBUG("%s %s, %s", opn, regnames[rd], regnames[rs]);
2575 tcg_temp_free(t0);
2576 tcg_temp_free(t1);
2577}
2578
6af0bf9c 2579/* Traps */
7a387fff 2580static void gen_trap (DisasContext *ctx, uint32_t opc,
6af0bf9c
FB
2581 int rs, int rt, int16_t imm)
2582{
2583 int cond;
cdc0faa6 2584 TCGv t0 = tcg_temp_new();
1ba74fb8 2585 TCGv t1 = tcg_temp_new();
6af0bf9c
FB
2586
2587 cond = 0;
2588 /* Load needed operands */
2589 switch (opc) {
2590 case OPC_TEQ:
2591 case OPC_TGE:
2592 case OPC_TGEU:
2593 case OPC_TLT:
2594 case OPC_TLTU:
2595 case OPC_TNE:
2596 /* Compare two registers */
2597 if (rs != rt) {
be24bb4f
TS
2598 gen_load_gpr(t0, rs);
2599 gen_load_gpr(t1, rt);
6af0bf9c
FB
2600 cond = 1;
2601 }
179e32bb 2602 break;
6af0bf9c
FB
2603 case OPC_TEQI:
2604 case OPC_TGEI:
2605 case OPC_TGEIU:
2606 case OPC_TLTI:
2607 case OPC_TLTIU:
2608 case OPC_TNEI:
2609 /* Compare register to immediate */
2610 if (rs != 0 || imm != 0) {
be24bb4f
TS
2611 gen_load_gpr(t0, rs);
2612 tcg_gen_movi_tl(t1, (int32_t)imm);
6af0bf9c
FB
2613 cond = 1;
2614 }
2615 break;
2616 }
2617 if (cond == 0) {
2618 switch (opc) {
2619 case OPC_TEQ: /* rs == rs */
2620 case OPC_TEQI: /* r0 == 0 */
2621 case OPC_TGE: /* rs >= rs */
2622 case OPC_TGEI: /* r0 >= 0 */
2623 case OPC_TGEU: /* rs >= rs unsigned */
2624 case OPC_TGEIU: /* r0 >= 0 unsigned */
2625 /* Always trap */
cdc0faa6 2626 generate_exception(ctx, EXCP_TRAP);
6af0bf9c
FB
2627 break;
2628 case OPC_TLT: /* rs < rs */
2629 case OPC_TLTI: /* r0 < 0 */
2630 case OPC_TLTU: /* rs < rs unsigned */
2631 case OPC_TLTIU: /* r0 < 0 unsigned */
2632 case OPC_TNE: /* rs != rs */
2633 case OPC_TNEI: /* r0 != 0 */
ead9360e 2634 /* Never trap: treat as NOP. */
cdc0faa6 2635 break;
6af0bf9c
FB
2636 }
2637 } else {
cdc0faa6
AJ
2638 int l1 = gen_new_label();
2639
6af0bf9c
FB
2640 switch (opc) {
2641 case OPC_TEQ:
2642 case OPC_TEQI:
cdc0faa6 2643 tcg_gen_brcond_tl(TCG_COND_NE, t0, t1, l1);
6af0bf9c
FB
2644 break;
2645 case OPC_TGE:
2646 case OPC_TGEI:
cdc0faa6 2647 tcg_gen_brcond_tl(TCG_COND_LT, t0, t1, l1);
6af0bf9c
FB
2648 break;
2649 case OPC_TGEU:
2650 case OPC_TGEIU:
cdc0faa6 2651 tcg_gen_brcond_tl(TCG_COND_LTU, t0, t1, l1);
6af0bf9c
FB
2652 break;
2653 case OPC_TLT:
2654 case OPC_TLTI:
cdc0faa6 2655 tcg_gen_brcond_tl(TCG_COND_GE, t0, t1, l1);
6af0bf9c
FB
2656 break;
2657 case OPC_TLTU:
2658 case OPC_TLTIU:
cdc0faa6 2659 tcg_gen_brcond_tl(TCG_COND_GEU, t0, t1, l1);
6af0bf9c
FB
2660 break;
2661 case OPC_TNE:
2662 case OPC_TNEI:
cdc0faa6 2663 tcg_gen_brcond_tl(TCG_COND_EQ, t0, t1, l1);
6af0bf9c 2664 break;
6af0bf9c 2665 }
cdc0faa6 2666 generate_exception(ctx, EXCP_TRAP);
08ba7963
TS
2667 gen_set_label(l1);
2668 }
be24bb4f
TS
2669 tcg_temp_free(t0);
2670 tcg_temp_free(t1);
6af0bf9c
FB
2671}
2672
356265ae 2673static inline void gen_goto_tb(DisasContext *ctx, int n, target_ulong dest)
c53be334 2674{
6e256c93
FB
2675 TranslationBlock *tb;
2676 tb = ctx->tb;
7b270ef2
NF
2677 if ((tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK) &&
2678 likely(!ctx->singlestep_enabled)) {
57fec1fe 2679 tcg_gen_goto_tb(n);
9b9e4393 2680 gen_save_pc(dest);
4b4a72e5 2681 tcg_gen_exit_tb((tcg_target_long)tb + n);
6e256c93 2682 } else {
9b9e4393 2683 gen_save_pc(dest);
7b270ef2
NF
2684 if (ctx->singlestep_enabled) {
2685 save_cpu_state(ctx, 0);
2686 gen_helper_0i(raise_exception, EXCP_DEBUG);
2687 }
57fec1fe 2688 tcg_gen_exit_tb(0);
6e256c93 2689 }
c53be334
FB
2690}
2691
6af0bf9c 2692/* Branches (before delay slot) */
7a387fff 2693static void gen_compute_branch (DisasContext *ctx, uint32_t opc,
7dca4ad0 2694 int insn_bytes,
6af0bf9c
FB
2695 int rs, int rt, int32_t offset)
2696{
d077b6f7 2697 target_ulong btgt = -1;
3ad4bb2d 2698 int blink = 0;
2fdbad25 2699 int bcond_compute = 0;
1ba74fb8
AJ
2700 TCGv t0 = tcg_temp_new();
2701 TCGv t1 = tcg_temp_new();
3ad4bb2d
TS
2702
2703 if (ctx->hflags & MIPS_HFLAG_BMASK) {
923617a3 2704#ifdef MIPS_DEBUG_DISAS
d12d51d5 2705 LOG_DISAS("Branch in delay slot at PC 0x" TARGET_FMT_lx "\n", ctx->pc);
923617a3 2706#endif
3ad4bb2d 2707 generate_exception(ctx, EXCP_RI);
6c5c1e20 2708 goto out;
3ad4bb2d 2709 }
6af0bf9c 2710
6af0bf9c
FB
2711 /* Load needed operands */
2712 switch (opc) {
2713 case OPC_BEQ:
2714 case OPC_BEQL:
2715 case OPC_BNE:
2716 case OPC_BNEL:
2717 /* Compare two registers */
2718 if (rs != rt) {
6c5c1e20
TS
2719 gen_load_gpr(t0, rs);
2720 gen_load_gpr(t1, rt);
2fdbad25 2721 bcond_compute = 1;
6af0bf9c 2722 }
7dca4ad0 2723 btgt = ctx->pc + insn_bytes + offset;
6af0bf9c
FB
2724 break;
2725 case OPC_BGEZ:
2726 case OPC_BGEZAL:
3c824109 2727 case OPC_BGEZALS:
6af0bf9c
FB
2728 case OPC_BGEZALL:
2729 case OPC_BGEZL:
2730 case OPC_BGTZ:
2731 case OPC_BGTZL:
2732 case OPC_BLEZ:
2733 case OPC_BLEZL:
2734 case OPC_BLTZ:
2735 case OPC_BLTZAL:
3c824109 2736 case OPC_BLTZALS:
6af0bf9c
FB
2737 case OPC_BLTZALL:
2738 case OPC_BLTZL:
2739 /* Compare to zero */
2740 if (rs != 0) {
6c5c1e20 2741 gen_load_gpr(t0, rs);
2fdbad25 2742 bcond_compute = 1;
6af0bf9c 2743 }
7dca4ad0 2744 btgt = ctx->pc + insn_bytes + offset;
6af0bf9c
FB
2745 break;
2746 case OPC_J:
2747 case OPC_JAL:
364d4831 2748 case OPC_JALX:
620e48f6
NF
2749 case OPC_JALS:
2750 case OPC_JALXS:
6af0bf9c 2751 /* Jump to immediate */
7dca4ad0 2752 btgt = ((ctx->pc + insn_bytes) & (int32_t)0xF0000000) | (uint32_t)offset;
6af0bf9c
FB
2753 break;
2754 case OPC_JR:
2755 case OPC_JALR:
364d4831 2756 case OPC_JALRC:
620e48f6 2757 case OPC_JALRS:
6af0bf9c 2758 /* Jump to register */
7a387fff
TS
2759 if (offset != 0 && offset != 16) {
2760 /* Hint = 0 is JR/JALR, hint 16 is JR.HB/JALR.HB, the
cbeb0857 2761 others are reserved. */
923617a3 2762 MIPS_INVAL("jump hint");
6af0bf9c 2763 generate_exception(ctx, EXCP_RI);
6c5c1e20 2764 goto out;
6af0bf9c 2765 }
d077b6f7 2766 gen_load_gpr(btarget, rs);
6af0bf9c
FB
2767 break;
2768 default:
2769 MIPS_INVAL("branch/jump");
2770 generate_exception(ctx, EXCP_RI);
6c5c1e20 2771 goto out;
6af0bf9c 2772 }
2fdbad25 2773 if (bcond_compute == 0) {
6af0bf9c
FB
2774 /* No condition to be computed */
2775 switch (opc) {
2776 case OPC_BEQ: /* rx == rx */
2777 case OPC_BEQL: /* rx == rx likely */
2778 case OPC_BGEZ: /* 0 >= 0 */
2779 case OPC_BGEZL: /* 0 >= 0 likely */
2780 case OPC_BLEZ: /* 0 <= 0 */
2781 case OPC_BLEZL: /* 0 <= 0 likely */
2782 /* Always take */
4ad40f36 2783 ctx->hflags |= MIPS_HFLAG_B;
6af0bf9c
FB
2784 MIPS_DEBUG("balways");
2785 break;
3c824109 2786 case OPC_BGEZALS:
6af0bf9c
FB
2787 case OPC_BGEZAL: /* 0 >= 0 */
2788 case OPC_BGEZALL: /* 0 >= 0 likely */
3c824109
NF
2789 ctx->hflags |= (opc == OPC_BGEZALS
2790 ? MIPS_HFLAG_BDS16
2791 : MIPS_HFLAG_BDS32);
6af0bf9c
FB
2792 /* Always take and link */
2793 blink = 31;
4ad40f36 2794 ctx->hflags |= MIPS_HFLAG_B;
6af0bf9c
FB
2795 MIPS_DEBUG("balways and link");
2796 break;
2797 case OPC_BNE: /* rx != rx */
2798 case OPC_BGTZ: /* 0 > 0 */
2799 case OPC_BLTZ: /* 0 < 0 */
ead9360e 2800 /* Treat as NOP. */
6af0bf9c 2801 MIPS_DEBUG("bnever (NOP)");
6c5c1e20 2802 goto out;
3c824109 2803 case OPC_BLTZALS:
eeef26cd 2804 case OPC_BLTZAL: /* 0 < 0 */
3c824109
NF
2805 ctx->hflags |= (opc == OPC_BLTZALS
2806 ? MIPS_HFLAG_BDS16
2807 : MIPS_HFLAG_BDS32);
2808 /* Handle as an unconditional branch to get correct delay
2809 slot checking. */
2810 blink = 31;
2811 btgt = ctx->pc + (opc == OPC_BLTZALS ? 6 : 8);
2812 ctx->hflags |= MIPS_HFLAG_B;
9898128f 2813 MIPS_DEBUG("bnever and link");
3c824109 2814 break;
eeef26cd 2815 case OPC_BLTZALL: /* 0 < 0 likely */
1ba74fb8 2816 tcg_gen_movi_tl(cpu_gpr[31], ctx->pc + 8);
9898128f
TS
2817 /* Skip the instruction in the delay slot */
2818 MIPS_DEBUG("bnever, link and skip");
2819 ctx->pc += 4;
6c5c1e20 2820 goto out;
6af0bf9c
FB
2821 case OPC_BNEL: /* rx != rx likely */
2822 case OPC_BGTZL: /* 0 > 0 likely */
6af0bf9c
FB
2823 case OPC_BLTZL: /* 0 < 0 likely */
2824 /* Skip the instruction in the delay slot */
2825 MIPS_DEBUG("bnever and skip");
9898128f 2826 ctx->pc += 4;
6c5c1e20 2827 goto out;
6af0bf9c 2828 case OPC_J:
4ad40f36 2829 ctx->hflags |= MIPS_HFLAG_B;
d077b6f7 2830 MIPS_DEBUG("j " TARGET_FMT_lx, btgt);
6af0bf9c 2831 break;
620e48f6 2832 case OPC_JALXS:
364d4831
NF
2833 case OPC_JALX:
2834 ctx->hflags |= MIPS_HFLAG_BX;
2835 /* Fallthrough */
620e48f6 2836 case OPC_JALS:
6af0bf9c
FB
2837 case OPC_JAL:
2838 blink = 31;
4ad40f36 2839 ctx->hflags |= MIPS_HFLAG_B;
620e48f6 2840 ctx->hflags |= ((opc == OPC_JALS || opc == OPC_JALXS)
364d4831
NF
2841 ? MIPS_HFLAG_BDS16
2842 : MIPS_HFLAG_BDS32);
d077b6f7 2843 MIPS_DEBUG("jal " TARGET_FMT_lx, btgt);
6af0bf9c
FB
2844 break;
2845 case OPC_JR:
4ad40f36 2846 ctx->hflags |= MIPS_HFLAG_BR;
620e48f6
NF
2847 if (insn_bytes == 4)
2848 ctx->hflags |= MIPS_HFLAG_BDS32;
6af0bf9c
FB
2849 MIPS_DEBUG("jr %s", regnames[rs]);
2850 break;
620e48f6 2851 case OPC_JALRS:
6af0bf9c 2852 case OPC_JALR:
364d4831 2853 case OPC_JALRC:
6af0bf9c 2854 blink = rt;
4ad40f36 2855 ctx->hflags |= MIPS_HFLAG_BR;
620e48f6
NF
2856 ctx->hflags |= (opc == OPC_JALRS
2857 ? MIPS_HFLAG_BDS16
2858 : MIPS_HFLAG_BDS32);
6af0bf9c
FB
2859 MIPS_DEBUG("jalr %s, %s", regnames[rt], regnames[rs]);
2860 break;
2861 default:
2862 MIPS_INVAL("branch/jump");
2863 generate_exception(ctx, EXCP_RI);
6c5c1e20 2864 goto out;
6af0bf9c
FB
2865 }
2866 } else {
2867 switch (opc) {
2868 case OPC_BEQ:
e68dd28f 2869 tcg_gen_setcond_tl(TCG_COND_EQ, bcond, t0, t1);
923617a3 2870 MIPS_DEBUG("beq %s, %s, " TARGET_FMT_lx,
d077b6f7 2871 regnames[rs], regnames[rt], btgt);
6af0bf9c
FB
2872 goto not_likely;
2873 case OPC_BEQL:
e68dd28f 2874 tcg_gen_setcond_tl(TCG_COND_EQ, bcond, t0, t1);
923617a3 2875 MIPS_DEBUG("beql %s, %s, " TARGET_FMT_lx,
d077b6f7 2876 regnames[rs], regnames[rt], btgt);
6af0bf9c
FB
2877 goto likely;
2878 case OPC_BNE:
e68dd28f 2879 tcg_gen_setcond_tl(TCG_COND_NE, bcond, t0, t1);
923617a3 2880 MIPS_DEBUG("bne %s, %s, " TARGET_FMT_lx,
d077b6f7 2881 regnames[rs], regnames[rt], btgt);
6af0bf9c
FB
2882 goto not_likely;
2883 case OPC_BNEL:
e68dd28f 2884 tcg_gen_setcond_tl(TCG_COND_NE, bcond, t0, t1);
923617a3 2885 MIPS_DEBUG("bnel %s, %s, " TARGET_FMT_lx,
d077b6f7 2886 regnames[rs], regnames[rt], btgt);
6af0bf9c
FB
2887 goto likely;
2888 case OPC_BGEZ:
e68dd28f 2889 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
d077b6f7 2890 MIPS_DEBUG("bgez %s, " TARGET_FMT_lx, regnames[rs], btgt);
6af0bf9c
FB
2891 goto not_likely;
2892 case OPC_BGEZL:
e68dd28f 2893 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
d077b6f7 2894 MIPS_DEBUG("bgezl %s, " TARGET_FMT_lx, regnames[rs], btgt);
6af0bf9c 2895 goto likely;
3c824109 2896 case OPC_BGEZALS:
6af0bf9c 2897 case OPC_BGEZAL:
3c824109
NF
2898 ctx->hflags |= (opc == OPC_BGEZALS
2899 ? MIPS_HFLAG_BDS16
2900 : MIPS_HFLAG_BDS32);
e68dd28f 2901 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
d077b6f7 2902 MIPS_DEBUG("bgezal %s, " TARGET_FMT_lx, regnames[rs], btgt);
6af0bf9c
FB
2903 blink = 31;
2904 goto not_likely;
2905 case OPC_BGEZALL:
e68dd28f 2906 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
6af0bf9c 2907 blink = 31;
d077b6f7 2908 MIPS_DEBUG("bgezall %s, " TARGET_FMT_lx, regnames[rs], btgt);
6af0bf9c
FB
2909 goto likely;
2910 case OPC_BGTZ:
e68dd28f 2911 tcg_gen_setcondi_tl(TCG_COND_GT, bcond, t0, 0);
d077b6f7 2912 MIPS_DEBUG("bgtz %s, " TARGET_FMT_lx, regnames[rs], btgt);
6af0bf9c
FB
2913 goto not_likely;
2914 case OPC_BGTZL:
e68dd28f 2915 tcg_gen_setcondi_tl(TCG_COND_GT, bcond, t0, 0);
d077b6f7 2916 MIPS_DEBUG("bgtzl %s, " TARGET_FMT_lx, regnames[rs], btgt);
6af0bf9c
FB
2917 goto likely;
2918 case OPC_BLEZ:
e68dd28f 2919 tcg_gen_setcondi_tl(TCG_COND_LE, bcond, t0, 0);
d077b6f7 2920 MIPS_DEBUG("blez %s, " TARGET_FMT_lx, regnames[rs], btgt);
6af0bf9c
FB
2921 goto not_likely;
2922 case OPC_BLEZL:
e68dd28f 2923 tcg_gen_setcondi_tl(TCG_COND_LE, bcond, t0, 0);
d077b6f7 2924 MIPS_DEBUG("blezl %s, " TARGET_FMT_lx, regnames[rs], btgt);
6af0bf9c
FB
2925 goto likely;
2926 case OPC_BLTZ:
e68dd28f 2927 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
d077b6f7 2928 MIPS_DEBUG("bltz %s, " TARGET_FMT_lx, regnames[rs], btgt);
6af0bf9c
FB
2929 goto not_likely;
2930 case OPC_BLTZL:
e68dd28f 2931 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
d077b6f7 2932 MIPS_DEBUG("bltzl %s, " TARGET_FMT_lx, regnames[rs], btgt);
6af0bf9c 2933 goto likely;
3c824109 2934 case OPC_BLTZALS:
6af0bf9c 2935 case OPC_BLTZAL:
3c824109
NF
2936 ctx->hflags |= (opc == OPC_BLTZALS
2937 ? MIPS_HFLAG_BDS16
2938 : MIPS_HFLAG_BDS32);
e68dd28f 2939 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
6af0bf9c 2940 blink = 31;
d077b6f7 2941 MIPS_DEBUG("bltzal %s, " TARGET_FMT_lx, regnames[rs], btgt);
6af0bf9c 2942 not_likely:
4ad40f36 2943 ctx->hflags |= MIPS_HFLAG_BC;
6af0bf9c
FB
2944 break;
2945 case OPC_BLTZALL:
e68dd28f 2946 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
6af0bf9c 2947 blink = 31;
d077b6f7 2948 MIPS_DEBUG("bltzall %s, " TARGET_FMT_lx, regnames[rs], btgt);
6af0bf9c 2949 likely:
4ad40f36 2950 ctx->hflags |= MIPS_HFLAG_BL;
6af0bf9c 2951 break;
c53f4a62
TS
2952 default:
2953 MIPS_INVAL("conditional branch/jump");
2954 generate_exception(ctx, EXCP_RI);
6c5c1e20 2955 goto out;
6af0bf9c 2956 }
6af0bf9c 2957 }
923617a3 2958 MIPS_DEBUG("enter ds: link %d cond %02x target " TARGET_FMT_lx,
d077b6f7 2959 blink, ctx->hflags, btgt);
9b9e4393 2960
d077b6f7 2961 ctx->btarget = btgt;
6af0bf9c 2962 if (blink > 0) {
364d4831
NF
2963 int post_delay = insn_bytes;
2964 int lowbit = !!(ctx->hflags & MIPS_HFLAG_M16);
2965
2966 if (opc != OPC_JALRC)
2967 post_delay += ((ctx->hflags & MIPS_HFLAG_BDS16) ? 2 : 4);
2968
2969 tcg_gen_movi_tl(cpu_gpr[blink], ctx->pc + post_delay + lowbit);
6af0bf9c 2970 }
6c5c1e20
TS
2971
2972 out:
364d4831
NF
2973 if (insn_bytes == 2)
2974 ctx->hflags |= MIPS_HFLAG_B16;
6c5c1e20
TS
2975 tcg_temp_free(t0);
2976 tcg_temp_free(t1);
6af0bf9c
FB
2977}
2978
7a387fff
TS
2979/* special3 bitfield operations */
2980static void gen_bitops (DisasContext *ctx, uint32_t opc, int rt,
356265ae 2981 int rs, int lsb, int msb)
7a387fff 2982{
a7812ae4
PB
2983 TCGv t0 = tcg_temp_new();
2984 TCGv t1 = tcg_temp_new();
505ad7c2 2985 target_ulong mask;
6c5c1e20
TS
2986
2987 gen_load_gpr(t1, rs);
7a387fff
TS
2988 switch (opc) {
2989 case OPC_EXT:
2990 if (lsb + msb > 31)
2991 goto fail;
505ad7c2
AJ
2992 tcg_gen_shri_tl(t0, t1, lsb);
2993 if (msb != 31) {
2994 tcg_gen_andi_tl(t0, t0, (1 << (msb + 1)) - 1);
2995 } else {
2996 tcg_gen_ext32s_tl(t0, t0);
2997 }
7a387fff 2998 break;
c6d6dd7c 2999#if defined(TARGET_MIPS64)
7a387fff 3000 case OPC_DEXTM:
505ad7c2
AJ
3001 tcg_gen_shri_tl(t0, t1, lsb);
3002 if (msb != 31) {
3003 tcg_gen_andi_tl(t0, t0, (1ULL << (msb + 1 + 32)) - 1);
3004 }
7a387fff
TS
3005 break;
3006 case OPC_DEXTU:
505ad7c2
AJ
3007 tcg_gen_shri_tl(t0, t1, lsb + 32);
3008 tcg_gen_andi_tl(t0, t0, (1ULL << (msb + 1)) - 1);
7a387fff
TS
3009 break;
3010 case OPC_DEXT:
505ad7c2
AJ
3011 tcg_gen_shri_tl(t0, t1, lsb);
3012 tcg_gen_andi_tl(t0, t0, (1ULL << (msb + 1)) - 1);
7a387fff 3013 break;
c6d6dd7c 3014#endif
7a387fff
TS
3015 case OPC_INS:
3016 if (lsb > msb)
3017 goto fail;
505ad7c2 3018 mask = ((msb - lsb + 1 < 32) ? ((1 << (msb - lsb + 1)) - 1) : ~0) << lsb;
6c5c1e20 3019 gen_load_gpr(t0, rt);
505ad7c2
AJ
3020 tcg_gen_andi_tl(t0, t0, ~mask);
3021 tcg_gen_shli_tl(t1, t1, lsb);
3022 tcg_gen_andi_tl(t1, t1, mask);
3023 tcg_gen_or_tl(t0, t0, t1);
3024 tcg_gen_ext32s_tl(t0, t0);
7a387fff 3025 break;
c6d6dd7c 3026#if defined(TARGET_MIPS64)
7a387fff
TS
3027 case OPC_DINSM:
3028 if (lsb > msb)
3029 goto fail;
505ad7c2 3030 mask = ((msb - lsb + 1 + 32 < 64) ? ((1ULL << (msb - lsb + 1 + 32)) - 1) : ~0ULL) << lsb;
6c5c1e20 3031 gen_load_gpr(t0, rt);
505ad7c2
AJ
3032 tcg_gen_andi_tl(t0, t0, ~mask);
3033 tcg_gen_shli_tl(t1, t1, lsb);
3034 tcg_gen_andi_tl(t1, t1, mask);
3035 tcg_gen_or_tl(t0, t0, t1);
7a387fff
TS
3036 break;
3037 case OPC_DINSU:
3038 if (lsb > msb)
3039 goto fail;
6fbab869 3040 mask = ((1ULL << (msb - lsb + 1)) - 1) << (lsb + 32);
6c5c1e20 3041 gen_load_gpr(t0, rt);
505ad7c2
AJ
3042 tcg_gen_andi_tl(t0, t0, ~mask);
3043 tcg_gen_shli_tl(t1, t1, lsb + 32);
3044 tcg_gen_andi_tl(t1, t1, mask);
3045 tcg_gen_or_tl(t0, t0, t1);
7a387fff
TS
3046 break;
3047 case OPC_DINS:
3048 if (lsb > msb)
3049 goto fail;
6c5c1e20 3050 gen_load_gpr(t0, rt);
505ad7c2
AJ
3051 mask = ((1ULL << (msb - lsb + 1)) - 1) << lsb;
3052 gen_load_gpr(t0, rt);
3053 tcg_gen_andi_tl(t0, t0, ~mask);
3054 tcg_gen_shli_tl(t1, t1, lsb);
3055 tcg_gen_andi_tl(t1, t1, mask);
3056 tcg_gen_or_tl(t0, t0, t1);
7a387fff 3057 break;
c6d6dd7c 3058#endif
7a387fff
TS
3059 default:
3060fail:
3061 MIPS_INVAL("bitops");
3062 generate_exception(ctx, EXCP_RI);
6c5c1e20
TS
3063 tcg_temp_free(t0);
3064 tcg_temp_free(t1);
7a387fff
TS
3065 return;
3066 }
6c5c1e20
TS
3067 gen_store_gpr(t0, rt);
3068 tcg_temp_free(t0);
3069 tcg_temp_free(t1);
7a387fff
TS
3070}
3071
49bcf33c
AJ
3072static void gen_bshfl (DisasContext *ctx, uint32_t op2, int rt, int rd)
3073{
3a55fa47 3074 TCGv t0;
49bcf33c 3075
3a55fa47
AJ
3076 if (rd == 0) {
3077 /* If no destination, treat it as a NOP. */
3078 MIPS_DEBUG("NOP");
3079 return;
3080 }
3081
3082 t0 = tcg_temp_new();
3083 gen_load_gpr(t0, rt);
49bcf33c
AJ
3084 switch (op2) {
3085 case OPC_WSBH:
3a55fa47
AJ
3086 {
3087 TCGv t1 = tcg_temp_new();
3088
3089 tcg_gen_shri_tl(t1, t0, 8);
3090 tcg_gen_andi_tl(t1, t1, 0x00FF00FF);
3091 tcg_gen_shli_tl(t0, t0, 8);
3092 tcg_gen_andi_tl(t0, t0, ~0x00FF00FF);
3093 tcg_gen_or_tl(t0, t0, t1);
3094 tcg_temp_free(t1);
3095 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
3096 }
49bcf33c
AJ
3097 break;
3098 case OPC_SEB:
3a55fa47 3099 tcg_gen_ext8s_tl(cpu_gpr[rd], t0);
49bcf33c
AJ
3100 break;
3101 case OPC_SEH:
3a55fa47 3102 tcg_gen_ext16s_tl(cpu_gpr[rd], t0);
49bcf33c
AJ
3103 break;
3104#if defined(TARGET_MIPS64)
3105 case OPC_DSBH:
3a55fa47
AJ
3106 {
3107 TCGv t1 = tcg_temp_new();
3108
3109 tcg_gen_shri_tl(t1, t0, 8);
3110 tcg_gen_andi_tl(t1, t1, 0x00FF00FF00FF00FFULL);
3111 tcg_gen_shli_tl(t0, t0, 8);
3112 tcg_gen_andi_tl(t0, t0, ~0x00FF00FF00FF00FFULL);
3113 tcg_gen_or_tl(cpu_gpr[rd], t0, t1);
3114 tcg_temp_free(t1);
3115 }
49bcf33c
AJ
3116 break;
3117 case OPC_DSHD:
3a55fa47
AJ
3118 {
3119 TCGv t1 = tcg_temp_new();
3120
3121 tcg_gen_shri_tl(t1, t0, 16);
3122 tcg_gen_andi_tl(t1, t1, 0x0000FFFF0000FFFFULL);
3123 tcg_gen_shli_tl(t0, t0, 16);
3124 tcg_gen_andi_tl(t0, t0, ~0x0000FFFF0000FFFFULL);
3125 tcg_gen_or_tl(t0, t0, t1);
3126 tcg_gen_shri_tl(t1, t0, 32);
3127 tcg_gen_shli_tl(t0, t0, 32);
3128 tcg_gen_or_tl(cpu_gpr[rd], t0, t1);
3129 tcg_temp_free(t1);
3130 }
49bcf33c
AJ
3131 break;
3132#endif
3133 default:
3134 MIPS_INVAL("bsfhl");
3135 generate_exception(ctx, EXCP_RI);
3136 tcg_temp_free(t0);
49bcf33c
AJ
3137 return;
3138 }
49bcf33c 3139 tcg_temp_free(t0);
49bcf33c
AJ
3140}
3141
f1aa6320 3142#ifndef CONFIG_USER_ONLY
0eaef5aa 3143/* CP0 (MMU and control) */
d9bea114 3144static inline void gen_mfc0_load32 (TCGv arg, target_ulong off)
4f57689a 3145{
d9bea114 3146 TCGv_i32 t0 = tcg_temp_new_i32();
4f57689a 3147
d9bea114
AJ
3148 tcg_gen_ld_i32(t0, cpu_env, off);
3149 tcg_gen_ext_i32_tl(arg, t0);
3150 tcg_temp_free_i32(t0);
4f57689a
TS
3151}
3152
d9bea114 3153static inline void gen_mfc0_load64 (TCGv arg, target_ulong off)
4f57689a 3154{
d9bea114
AJ
3155 tcg_gen_ld_tl(arg, cpu_env, off);
3156 tcg_gen_ext32s_tl(arg, arg);
4f57689a
TS
3157}
3158
d9bea114 3159static inline void gen_mtc0_store32 (TCGv arg, target_ulong off)
f1aa6320 3160{
d9bea114 3161 TCGv_i32 t0 = tcg_temp_new_i32();
f1aa6320 3162
d9bea114
AJ
3163 tcg_gen_trunc_tl_i32(t0, arg);
3164 tcg_gen_st_i32(t0, cpu_env, off);
3165 tcg_temp_free_i32(t0);
f1aa6320
TS
3166}
3167
d9bea114 3168static inline void gen_mtc0_store64 (TCGv arg, target_ulong off)
f1aa6320 3169{
d9bea114
AJ
3170 tcg_gen_ext32s_tl(arg, arg);
3171 tcg_gen_st_tl(arg, cpu_env, off);
f1aa6320
TS
3172}
3173
7db13fae 3174static void gen_mfc0 (CPUMIPSState *env, DisasContext *ctx, TCGv arg, int reg, int sel)
873eb012 3175{
7a387fff 3176 const char *rn = "invalid";
873eb012 3177
e189e748
TS
3178 if (sel != 0)
3179 check_insn(env, ctx, ISA_MIPS32);
3180
873eb012
TS
3181 switch (reg) {
3182 case 0:
7a387fff
TS
3183 switch (sel) {
3184 case 0:
7db13fae 3185 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Index));
7a387fff
TS
3186 rn = "Index";
3187 break;
3188 case 1:
7385ac0b 3189 check_insn(env, ctx, ASE_MT);
d9bea114 3190 gen_helper_mfc0_mvpcontrol(arg);
7a387fff 3191 rn = "MVPControl";
ead9360e 3192 break;
7a387fff 3193 case 2:
7385ac0b 3194 check_insn(env, ctx, ASE_MT);
d9bea114 3195 gen_helper_mfc0_mvpconf0(arg);
7a387fff 3196 rn = "MVPConf0";
ead9360e 3197 break;
7a387fff 3198 case 3:
7385ac0b 3199 check_insn(env, ctx, ASE_MT);
d9bea114 3200 gen_helper_mfc0_mvpconf1(arg);
7a387fff 3201 rn = "MVPConf1";
ead9360e 3202 break;
7a387fff
TS
3203 default:
3204 goto die;
3205 }
873eb012
TS
3206 break;
3207 case 1:
7a387fff
TS
3208 switch (sel) {
3209 case 0:
d9bea114 3210 gen_helper_mfc0_random(arg);
7a387fff 3211 rn = "Random";
2423f660 3212 break;
7a387fff 3213 case 1:
7385ac0b 3214 check_insn(env, ctx, ASE_MT);
7db13fae 3215 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEControl));
7a387fff 3216 rn = "VPEControl";
ead9360e 3217 break;
7a387fff 3218 case 2:
7385ac0b 3219 check_insn(env, ctx, ASE_MT);
7db13fae 3220 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf0));
7a387fff 3221 rn = "VPEConf0";
ead9360e 3222 break;
7a387fff 3223 case 3:
7385ac0b 3224 check_insn(env, ctx, ASE_MT);
7db13fae 3225 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf1));
7a387fff 3226 rn = "VPEConf1";
ead9360e 3227 break;
7a387fff 3228 case 4:
7385ac0b 3229 check_insn(env, ctx, ASE_MT);
7db13fae 3230 gen_mfc0_load64(arg, offsetof(CPUMIPSState, CP0_YQMask));
7a387fff 3231 rn = "YQMask";
ead9360e 3232 break;
7a387fff 3233 case 5:
7385ac0b 3234 check_insn(env, ctx, ASE_MT);
7db13fae 3235 gen_mfc0_load64(arg, offsetof(CPUMIPSState, CP0_VPESchedule));
7a387fff 3236 rn = "VPESchedule";
ead9360e 3237 break;
7a387fff 3238 case 6:
7385ac0b 3239 check_insn(env, ctx, ASE_MT);
7db13fae 3240 gen_mfc0_load64(arg, offsetof(CPUMIPSState, CP0_VPEScheFBack));
7a387fff 3241 rn = "VPEScheFBack";
ead9360e 3242 break;
7a387fff 3243 case 7:
7385ac0b 3244 check_insn(env, ctx, ASE_MT);
7db13fae 3245 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEOpt));
7a387fff 3246 rn = "VPEOpt";
ead9360e 3247 break;
7a387fff
TS
3248 default:
3249 goto die;
3250 }
873eb012
TS
3251 break;
3252 case 2:
7a387fff
TS
3253 switch (sel) {
3254 case 0:
7db13fae 3255 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryLo0));
d9bea114 3256 tcg_gen_ext32s_tl(arg, arg);
2423f660
TS
3257 rn = "EntryLo0";
3258 break;
7a387fff 3259 case 1:
7385ac0b 3260 check_insn(env, ctx, ASE_MT);
d9bea114 3261 gen_helper_mfc0_tcstatus(arg);
2423f660 3262 rn = "TCStatus";
ead9360e 3263 break;
7a387fff 3264 case 2:
7385ac0b 3265 check_insn(env, ctx, ASE_MT);
d9bea114 3266 gen_helper_mfc0_tcbind(arg);
2423f660 3267 rn = "TCBind";
ead9360e 3268 break;
7a387fff 3269 case 3:
7385ac0b 3270 check_insn(env, ctx, ASE_MT);
d9bea114 3271 gen_helper_mfc0_tcrestart(arg);
2423f660 3272 rn = "TCRestart";
ead9360e 3273 break;
7a387fff 3274 case 4:
7385ac0b 3275 check_insn(env, ctx, ASE_MT);
d9bea114 3276 gen_helper_mfc0_tchalt(arg);
2423f660 3277 rn = "TCHalt";
ead9360e 3278 break;
7a387fff 3279 case 5:
7385ac0b 3280 check_insn(env, ctx, ASE_MT);
d9bea114 3281 gen_helper_mfc0_tccontext(arg);
2423f660 3282 rn = "TCContext";
ead9360e 3283 break;
7a387fff 3284 case 6:
7385ac0b 3285 check_insn(env, ctx, ASE_MT);
d9bea114 3286 gen_helper_mfc0_tcschedule(arg);
2423f660 3287 rn = "TCSchedule";
ead9360e 3288 break;
7a387fff 3289 case 7:
7385ac0b 3290 check_insn(env, ctx, ASE_MT);
d9bea114 3291 gen_helper_mfc0_tcschefback(arg);
2423f660 3292 rn = "TCScheFBack";
ead9360e 3293 break;
7a387fff
TS
3294 default:
3295 goto die;
3296 }
873eb012
TS
3297 break;
3298 case 3:
7a387fff
TS
3299 switch (sel) {
3300 case 0:
7db13fae 3301 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryLo1));
d9bea114 3302 tcg_gen_ext32s_tl(arg, arg);
2423f660
TS
3303 rn = "EntryLo1";
3304 break;
7a387fff
TS
3305 default:
3306 goto die;
1579a72e 3307 }
873eb012
TS
3308 break;
3309 case 4:
7a387fff
TS
3310 switch (sel) {
3311 case 0:
7db13fae 3312 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_Context));
d9bea114 3313 tcg_gen_ext32s_tl(arg, arg);
2423f660
TS
3314 rn = "Context";
3315 break;
7a387fff 3316 case 1:
d9bea114 3317// gen_helper_mfc0_contextconfig(arg); /* SmartMIPS ASE */
2423f660
TS
3318 rn = "ContextConfig";
3319// break;
7a387fff
TS
3320 default:
3321 goto die;
1579a72e 3322 }
873eb012
TS
3323 break;
3324 case 5:
7a387fff
TS
3325 switch (sel) {
3326 case 0:
7db13fae 3327 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageMask));
2423f660
TS
3328 rn = "PageMask";
3329 break;
7a387fff 3330 case 1:
e189e748 3331 check_insn(env, ctx, ISA_MIPS32R2);
7db13fae 3332 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageGrain));
2423f660
TS
3333 rn = "PageGrain";
3334 break;
7a387fff
TS
3335 default:
3336 goto die;
1579a72e 3337 }
873eb012
TS
3338 break;
3339 case 6:
7a387fff
TS
3340 switch (sel) {
3341 case 0:
7db13fae 3342 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Wired));
2423f660
TS
3343 rn = "Wired";
3344 break;
7a387fff 3345 case 1:
e189e748 3346 check_insn(env, ctx, ISA_MIPS32R2);
7db13fae 3347 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf0));
2423f660 3348 rn = "SRSConf0";
ead9360e 3349 break;
7a387fff 3350 case 2:
e189e748 3351 check_insn(env, ctx, ISA_MIPS32R2);
7db13fae 3352 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf1));
2423f660 3353 rn = "SRSConf1";
ead9360e 3354 break;
7a387fff 3355 case 3:
e189e748 3356 check_insn(env, ctx, ISA_MIPS32R2);
7db13fae 3357 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf2));
2423f660 3358 rn = "SRSConf2";
ead9360e 3359 break;
7a387fff 3360 case 4:
e189e748 3361 check_insn(env, ctx, ISA_MIPS32R2);
7db13fae 3362 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf3));
2423f660 3363 rn = "SRSConf3";
ead9360e 3364 break;
7a387fff 3365 case 5:
e189e748 3366 check_insn(env, ctx, ISA_MIPS32R2);
7db13fae 3367 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf4));
2423f660 3368 rn = "SRSConf4";
ead9360e 3369 break;
7a387fff
TS
3370 default:
3371 goto die;
1579a72e 3372 }
873eb012 3373 break;
8c0fdd85 3374 case 7:
7a387fff
TS
3375 switch (sel) {
3376 case 0:
e189e748 3377 check_insn(env, ctx, ISA_MIPS32R2);
7db13fae 3378 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_HWREna));
2423f660
TS
3379 rn = "HWREna";
3380 break;
7a387fff
TS
3381 default:
3382 goto die;
1579a72e 3383 }
8c0fdd85 3384 break;
873eb012 3385 case 8:
7a387fff
TS
3386 switch (sel) {
3387 case 0:
7db13fae 3388 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_BadVAddr));
d9bea114 3389 tcg_gen_ext32s_tl(arg, arg);
f0b3f3ae 3390 rn = "BadVAddr";
2423f660 3391 break;
7a387fff
TS
3392 default:
3393 goto die;
3394 }
873eb012
TS
3395 break;
3396 case 9:
7a387fff
TS
3397 switch (sel) {
3398 case 0:
2e70f6ef
PB
3399 /* Mark as an IO operation because we read the time. */
3400 if (use_icount)
3401 gen_io_start();
d9bea114 3402 gen_helper_mfc0_count(arg);
2e70f6ef
PB
3403 if (use_icount) {
3404 gen_io_end();
2e70f6ef 3405 }
55807224
EI
3406 /* Break the TB to be able to take timer interrupts immediately
3407 after reading count. */
3408 ctx->bstate = BS_STOP;
2423f660
TS
3409 rn = "Count";
3410 break;
3411 /* 6,7 are implementation dependent */
7a387fff
TS
3412 default:
3413 goto die;
2423f660 3414 }
873eb012
TS
3415 break;
3416 case 10:
7a387fff
TS
3417 switch (sel) {
3418 case 0:
7db13fae 3419 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryHi));
d9bea114 3420 tcg_gen_ext32s_tl(arg, arg);
2423f660
TS
3421 rn = "EntryHi";
3422 break;
7a387fff
TS
3423 default:
3424 goto die;
1579a72e 3425 }
873eb012
TS
3426 break;
3427 case 11:
7a387fff
TS
3428 switch (sel) {
3429 case 0:
7db13fae 3430 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Compare));
2423f660
TS
3431 rn = "Compare";
3432 break;
3433 /* 6,7 are implementation dependent */
7a387fff
TS
3434 default:
3435 goto die;
2423f660 3436 }
873eb012
TS
3437 break;
3438 case 12:
7a387fff
TS
3439 switch (sel) {
3440 case 0:
7db13fae 3441 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Status));
2423f660
TS
3442 rn = "Status";
3443 break;
7a387fff 3444 case 1:
e189e748 3445 check_insn(env, ctx, ISA_MIPS32R2);
7db13fae 3446 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_IntCtl));
2423f660
TS
3447 rn = "IntCtl";
3448 break;
7a387fff 3449 case 2:
e189e748 3450 check_insn(env, ctx, ISA_MIPS32R2);
7db13fae 3451 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSCtl));
2423f660
TS
3452 rn = "SRSCtl";
3453 break;
7a387fff 3454 case 3:
e189e748 3455 check_insn(env, ctx, ISA_MIPS32R2);
7db13fae 3456 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
2423f660 3457 rn = "SRSMap";
fd88b6ab 3458 break;
7a387fff
TS
3459 default:
3460 goto die;
3461 }
873eb012
TS
3462 break;
3463 case 13:
7a387fff
TS
3464 switch (sel) {
3465 case 0:
7db13fae 3466 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Cause));
2423f660
TS
3467 rn = "Cause";
3468 break;
7a387fff
TS
3469 default:
3470 goto die;
3471 }
873eb012
TS
3472 break;
3473 case 14:
7a387fff
TS
3474 switch (sel) {
3475 case 0:
7db13fae 3476 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EPC));
d9bea114 3477 tcg_gen_ext32s_tl(arg, arg);
2423f660
TS
3478 rn = "EPC";
3479 break;
7a387fff
TS
3480 default:
3481 goto die;
1579a72e 3482 }
873eb012
TS
3483 break;
3484 case 15:
7a387fff
TS
3485 switch (sel) {
3486 case 0:
7db13fae 3487 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PRid));
2423f660
TS
3488 rn = "PRid";
3489 break;
7a387fff 3490 case 1:
e189e748 3491 check_insn(env, ctx, ISA_MIPS32R2);
7db13fae 3492 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_EBase));
2423f660
TS
3493 rn = "EBase";
3494 break;
7a387fff
TS
3495 default:
3496 goto die;
3497 }
873eb012
TS
3498 break;
3499 case 16:
3500 switch (sel) {
3501 case 0:
7db13fae 3502 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config0));
873eb012
TS
3503 rn = "Config";
3504 break;
3505 case 1:
7db13fae 3506 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config1));
873eb012
TS
3507 rn = "Config1";
3508 break;
7a387fff 3509 case 2:
7db13fae 3510 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config2));
7a387fff
TS
3511 rn = "Config2";
3512 break;
3513 case 3:
7db13fae 3514 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config3));
7a387fff
TS
3515 rn = "Config3";
3516 break;
e397ee33
TS
3517 /* 4,5 are reserved */
3518 /* 6,7 are implementation dependent */
3519 case 6:
7db13fae 3520 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config6));
e397ee33
TS
3521 rn = "Config6";
3522 break;
3523 case 7:
7db13fae 3524 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config7));
e397ee33
TS
3525 rn = "Config7";
3526 break;
873eb012 3527 default:
873eb012
TS
3528 goto die;
3529 }
3530 break;
3531 case 17:
7a387fff
TS
3532 switch (sel) {
3533 case 0:
d9bea114 3534 gen_helper_mfc0_lladdr(arg);
2423f660
TS
3535 rn = "LLAddr";
3536 break;
7a387fff
TS
3537 default:
3538 goto die;
3539 }
873eb012
TS
3540 break;
3541 case 18:
7a387fff 3542 switch (sel) {
fd88b6ab 3543 case 0 ... 7:
d9bea114 3544 gen_helper_1i(mfc0_watchlo, arg, sel);
2423f660
TS
3545 rn = "WatchLo";
3546 break;
7a387fff
TS
3547 default:
3548 goto die;
3549 }
873eb012
TS
3550 break;
3551 case 19:
7a387fff 3552 switch (sel) {
fd88b6ab 3553 case 0 ...7:
d9bea114 3554 gen_helper_1i(mfc0_watchhi, arg, sel);
2423f660
TS
3555 rn = "WatchHi";
3556 break;
7a387fff
TS
3557 default:
3558 goto die;
3559 }
873eb012 3560 break;
8c0fdd85 3561 case 20:
7a387fff
TS
3562 switch (sel) {
3563 case 0:
d26bc211 3564#if defined(TARGET_MIPS64)
e189e748 3565 check_insn(env, ctx, ISA_MIPS3);
7db13fae 3566 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_XContext));
d9bea114 3567 tcg_gen_ext32s_tl(arg, arg);
2423f660
TS
3568 rn = "XContext";
3569 break;
703eaf37 3570#endif
7a387fff
TS
3571 default:
3572 goto die;
3573 }
8c0fdd85
TS
3574 break;
3575 case 21:
7a387fff
TS
3576 /* Officially reserved, but sel 0 is used for R1x000 framemask */
3577 switch (sel) {
3578 case 0:
7db13fae 3579 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Framemask));
2423f660
TS
3580 rn = "Framemask";
3581 break;
7a387fff
TS
3582 default:
3583 goto die;
3584 }
8c0fdd85
TS
3585 break;
3586 case 22:
d9bea114 3587 tcg_gen_movi_tl(arg, 0); /* unimplemented */
2423f660
TS
3588 rn = "'Diagnostic"; /* implementation dependent */
3589 break;
873eb012 3590 case 23:
7a387fff
TS
3591 switch (sel) {
3592 case 0:
d9bea114 3593 gen_helper_mfc0_debug(arg); /* EJTAG support */
2423f660
TS
3594 rn = "Debug";
3595 break;
7a387fff 3596 case 1:
d9bea114 3597// gen_helper_mfc0_tracecontrol(arg); /* PDtrace support */
2423f660
TS
3598 rn = "TraceControl";
3599// break;
7a387fff 3600 case 2:
d9bea114 3601// gen_helper_mfc0_tracecontrol2(arg); /* PDtrace support */
2423f660
TS
3602 rn = "TraceControl2";
3603// break;
7a387fff 3604 case 3:
d9bea114 3605// gen_helper_mfc0_usertracedata(arg); /* PDtrace support */
2423f660
TS
3606 rn = "UserTraceData";
3607// break;
7a387fff 3608 case 4:
d9bea114 3609// gen_helper_mfc0_tracebpc(arg); /* PDtrace support */
2423f660
TS
3610 rn = "TraceBPC";
3611// break;
7a387fff
TS
3612 default:
3613 goto die;
3614 }
873eb012
TS
3615 break;
3616 case 24:
7a387fff
TS
3617 switch (sel) {
3618 case 0:
f0b3f3ae 3619 /* EJTAG support */
7db13fae 3620 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_DEPC));
d9bea114 3621 tcg_gen_ext32s_tl(arg, arg);
2423f660
TS
3622 rn = "DEPC";
3623 break;
7a387fff
TS
3624 default:
3625 goto die;
3626 }
873eb012 3627 break;
8c0fdd85 3628 case 25:
7a387fff
TS
3629 switch (sel) {
3630 case 0:
7db13fae 3631 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Performance0));
2423f660 3632 rn = "Performance0";
7a387fff
TS
3633 break;
3634 case 1:
d9bea114 3635// gen_helper_mfc0_performance1(arg);
2423f660
TS
3636 rn = "Performance1";
3637// break;
7a387fff 3638 case 2:
d9bea114 3639// gen_helper_mfc0_performance2(arg);
2423f660
TS
3640 rn = "Performance2";
3641// break;
7a387fff 3642 case 3:
d9bea114 3643// gen_helper_mfc0_performance3(arg);
2423f660
TS
3644 rn = "Performance3";
3645// break;
7a387fff 3646 case 4:
d9bea114 3647// gen_helper_mfc0_performance4(arg);
2423f660
TS
3648 rn = "Performance4";
3649// break;
7a387fff 3650 case 5:
d9bea114 3651// gen_helper_mfc0_performance5(arg);
2423f660
TS
3652 rn = "Performance5";
3653// break;
7a387fff 3654 case 6:
d9bea114 3655// gen_helper_mfc0_performance6(arg);
2423f660
TS
3656 rn = "Performance6";
3657// break;
7a387fff 3658 case 7:
d9bea114 3659// gen_helper_mfc0_performance7(arg);
2423f660
TS
3660 rn = "Performance7";
3661// break;
7a387fff
TS
3662 default:
3663 goto die;
3664 }
8c0fdd85
TS
3665 break;
3666 case 26:
d9bea114 3667 tcg_gen_movi_tl(arg, 0); /* unimplemented */
da80682b
AJ
3668 rn = "ECC";
3669 break;
8c0fdd85 3670 case 27:
7a387fff 3671 switch (sel) {
7a387fff 3672 case 0 ... 3:
d9bea114 3673 tcg_gen_movi_tl(arg, 0); /* unimplemented */
2423f660
TS
3674 rn = "CacheErr";
3675 break;
7a387fff
TS
3676 default:
3677 goto die;
3678 }
8c0fdd85 3679 break;
873eb012
TS
3680 case 28:
3681 switch (sel) {
3682 case 0:
7a387fff
TS
3683 case 2:
3684 case 4:
3685 case 6:
7db13fae 3686 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_TagLo));
873eb012
TS
3687 rn = "TagLo";
3688 break;
3689 case 1:
7a387fff
TS
3690 case 3:
3691 case 5:
3692 case 7:
7db13fae 3693 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataLo));
873eb012
TS
3694 rn = "DataLo";
3695 break;
3696 default:
873eb012
TS
3697 goto die;
3698 }
3699 break;
8c0fdd85 3700 case 29:
7a387fff
TS
3701 switch (sel) {
3702 case 0:
3703 case 2:
3704 case 4:
3705 case 6:
7db13fae 3706 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_TagHi));
7a387fff
TS
3707 rn = "TagHi";
3708 break;
3709 case 1:
3710 case 3:
3711 case 5:
3712 case 7:
7db13fae 3713 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataHi));
7a387fff
TS
3714 rn = "DataHi";
3715 break;
3716 default:
3717 goto die;
3718 }
8c0fdd85 3719 break;
873eb012 3720 case 30:
7a387fff
TS
3721 switch (sel) {
3722 case 0:
7db13fae 3723 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_ErrorEPC));
d9bea114 3724 tcg_gen_ext32s_tl(arg, arg);
2423f660
TS
3725 rn = "ErrorEPC";
3726 break;
7a387fff
TS
3727 default:
3728 goto die;
3729 }
873eb012
TS
3730 break;
3731 case 31:
7a387fff
TS
3732 switch (sel) {
3733 case 0:
f0b3f3ae 3734 /* EJTAG support */
7db13fae 3735 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
2423f660
TS
3736 rn = "DESAVE";
3737 break;
7a387fff
TS
3738 default:
3739 goto die;
3740 }
873eb012
TS
3741 break;
3742 default:
873eb012
TS
3743 goto die;
3744 }
2abf314d 3745 (void)rn; /* avoid a compiler warning */
d12d51d5 3746 LOG_DISAS("mfc0 %s (reg %d sel %d)\n", rn, reg, sel);
873eb012
TS
3747 return;
3748
3749die:
d12d51d5 3750 LOG_DISAS("mfc0 %s (reg %d sel %d)\n", rn, reg, sel);
873eb012
TS
3751 generate_exception(ctx, EXCP_RI);
3752}
3753
7db13fae 3754static void gen_mtc0 (CPUMIPSState *env, DisasContext *ctx, TCGv arg, int reg, int sel)
8c0fdd85 3755{
7a387fff
TS
3756 const char *rn = "invalid";
3757
e189e748
TS
3758 if (sel != 0)
3759 check_insn(env, ctx, ISA_MIPS32);
3760
2e70f6ef
PB
3761 if (use_icount)
3762 gen_io_start();
3763
8c0fdd85
TS
3764 switch (reg) {
3765 case 0:
7a387fff
TS
3766 switch (sel) {
3767 case 0:
d9bea114 3768 gen_helper_mtc0_index(arg);
7a387fff
TS
3769 rn = "Index";
3770 break;
3771 case 1:
7385ac0b 3772 check_insn(env, ctx, ASE_MT);
d9bea114 3773 gen_helper_mtc0_mvpcontrol(arg);
7a387fff 3774 rn = "MVPControl";
ead9360e 3775 break;
7a387fff 3776 case 2:
7385ac0b 3777 check_insn(env, ctx, ASE_MT);
ead9360e 3778 /* ignored */
7a387fff 3779 rn = "MVPConf0";
ead9360e 3780 break;
7a387fff 3781 case 3:
7385ac0b 3782 check_insn(env, ctx, ASE_MT);
ead9360e 3783 /* ignored */
7a387fff 3784 rn = "MVPConf1";
ead9360e 3785 break;
7a387fff
TS
3786 default:
3787 goto die;
3788 }
8c0fdd85
TS
3789 break;
3790 case 1:
7a387fff
TS
3791 switch (sel) {
3792 case 0:
2423f660 3793 /* ignored */
7a387fff 3794 rn = "Random";
2423f660 3795 break;
7a387fff 3796 case 1:
7385ac0b 3797 check_insn(env, ctx, ASE_MT);
d9bea114 3798 gen_helper_mtc0_vpecontrol(arg);
7a387fff 3799 rn = "VPEControl";
ead9360e 3800 break;
7a387fff 3801 case 2:
7385ac0b 3802 check_insn(env, ctx, ASE_MT);
d9bea114 3803 gen_helper_mtc0_vpeconf0(arg);
7a387fff 3804 rn = "VPEConf0";
ead9360e 3805 break;
7a387fff 3806 case 3:
7385ac0b 3807 check_insn(env, ctx, ASE_MT);
d9bea114 3808 gen_helper_mtc0_vpeconf1(arg);
7a387fff 3809 rn = "VPEConf1";
ead9360e 3810 break;
7a387fff 3811 case 4:
7385ac0b 3812 check_insn(env, ctx, ASE_MT);
d9bea114 3813 gen_helper_mtc0_yqmask(arg);
7a387fff 3814 rn = "YQMask";
ead9360e 3815 break;
7a387fff 3816 case 5:
7385ac0b 3817 check_insn(env, ctx, ASE_MT);
7db13fae 3818 gen_mtc0_store64(arg, offsetof(CPUMIPSState, CP0_VPESchedule));
7a387fff 3819 rn = "VPESchedule";
ead9360e 3820 break;
7a387fff 3821 case 6:
7385ac0b 3822 check_insn(env, ctx, ASE_MT);
7db13fae 3823 gen_mtc0_store64(arg, offsetof(CPUMIPSState, CP0_VPEScheFBack));
7a387fff 3824 rn = "VPEScheFBack";
ead9360e 3825 break;
7a387fff 3826 case 7:
7385ac0b 3827 check_insn(env, ctx, ASE_MT);
d9bea114 3828 gen_helper_mtc0_vpeopt(arg);
7a387fff 3829 rn = "VPEOpt";
ead9360e 3830 break;
7a387fff
TS
3831 default:
3832 goto die;
3833 }
8c0fdd85
TS
3834 break;
3835 case 2:
7a387fff
TS
3836 switch (sel) {
3837 case 0:
d9bea114 3838 gen_helper_mtc0_entrylo0(arg);
2423f660
TS
3839 rn = "EntryLo0";
3840 break;
7a387fff 3841 case 1:
7385ac0b 3842 check_insn(env, ctx, ASE_MT);
d9bea114 3843 gen_helper_mtc0_tcstatus(arg);
2423f660 3844 rn = "TCStatus";
ead9360e 3845 break;
7a387fff 3846 case 2:
7385ac0b 3847 check_insn(env, ctx, ASE_MT);
d9bea114 3848 gen_helper_mtc0_tcbind(arg);
2423f660 3849 rn = "TCBind";
ead9360e 3850 break;
7a387fff 3851 case 3:
7385ac0b 3852 check_insn(env, ctx, ASE_MT);
d9bea114 3853 gen_helper_mtc0_tcrestart(arg);
2423f660 3854 rn = "TCRestart";
ead9360e 3855 break;
7a387fff 3856 case 4:
7385ac0b 3857 check_insn(env, ctx, ASE_MT);
d9bea114 3858 gen_helper_mtc0_tchalt(arg);
2423f660 3859 rn = "TCHalt";
ead9360e 3860 break;
7a387fff 3861 case 5:
7385ac0b 3862 check_insn(env, ctx, ASE_MT);
d9bea114 3863 gen_helper_mtc0_tccontext(arg);
2423f660 3864 rn = "TCContext";
ead9360e 3865 break;
7a387fff 3866 case 6:
7385ac0b 3867 check_insn(env, ctx, ASE_MT);
d9bea114 3868 gen_helper_mtc0_tcschedule(arg);
2423f660 3869 rn = "TCSchedule";
ead9360e 3870 break;
7a387fff 3871 case 7:
7385ac0b 3872 check_insn(env, ctx, ASE_MT);
d9bea114 3873 gen_helper_mtc0_tcschefback(arg);
2423f660 3874 rn = "TCScheFBack";
ead9360e 3875 break;
7a387fff
TS
3876 default:
3877 goto die;
3878 }
8c0fdd85
TS
3879 break;
3880 case 3:
7a387fff
TS
3881 switch (sel) {
3882 case 0:
d9bea114 3883 gen_helper_mtc0_entrylo1(arg);
2423f660
TS
3884 rn = "EntryLo1";
3885 break;
7a387fff
TS
3886 default:
3887 goto die;
876d4b07 3888 }
8c0fdd85
TS
3889 break;
3890 case 4:
7a387fff
TS
3891 switch (sel) {
3892 case 0:
d9bea114 3893 gen_helper_mtc0_context(arg);
2423f660
TS
3894 rn = "Context";
3895 break;
7a387fff 3896 case 1:
d9bea114 3897// gen_helper_mtc0_contextconfig(arg); /* SmartMIPS ASE */
2423f660
TS
3898 rn = "ContextConfig";
3899// break;
7a387fff
TS
3900 default:
3901 goto die;
876d4b07 3902 }
8c0fdd85
TS
3903 break;
3904 case 5:
7a387fff
TS
3905 switch (sel) {
3906 case 0:
d9bea114 3907 gen_helper_mtc0_pagemask(arg);
2423f660
TS
3908 rn = "PageMask";
3909 break;
7a387fff 3910 case 1:
e189e748 3911 check_insn(env, ctx, ISA_MIPS32R2);
d9bea114 3912 gen_helper_mtc0_pagegrain(arg);
2423f660
TS
3913 rn = "PageGrain";
3914 break;
7a387fff
TS
3915 default:
3916 goto die;
876d4b07 3917 }
8c0fdd85
TS
3918 break;
3919 case 6:
7a387fff
TS
3920 switch (sel) {
3921 case 0:
d9bea114 3922 gen_helper_mtc0_wired(arg);
2423f660
TS
3923 rn = "Wired";
3924 break;
7a387fff 3925 case 1:
e189e748 3926 check_insn(env, ctx, ISA_MIPS32R2);
d9bea114 3927 gen_helper_mtc0_srsconf0(arg);
2423f660 3928 rn = "SRSConf0";
ead9360e 3929 break;
7a387fff 3930 case 2:
e189e748 3931 check_insn(env, ctx, ISA_MIPS32R2);
d9bea114 3932 gen_helper_mtc0_srsconf1(arg);
2423f660 3933 rn = "SRSConf1";
ead9360e 3934 break;
7a387fff 3935 case 3:
e189e748 3936 check_insn(env, ctx, ISA_MIPS32R2);
d9bea114 3937 gen_helper_mtc0_srsconf2(arg);
2423f660 3938 rn = "SRSConf2";
ead9360e 3939 break;
7a387fff 3940 case 4:
e189e748 3941 check_insn(env, ctx, ISA_MIPS32R2);
d9bea114 3942 gen_helper_mtc0_srsconf3(arg);
2423f660 3943 rn = "SRSConf3";
ead9360e 3944 break;
7a387fff 3945 case 5:
e189e748 3946 check_insn(env, ctx, ISA_MIPS32R2);
d9bea114 3947 gen_helper_mtc0_srsconf4(arg);
2423f660 3948 rn = "SRSConf4";
ead9360e 3949 break;
7a387fff
TS
3950 default:
3951 goto die;
876d4b07 3952 }
8c0fdd85
TS
3953 break;
3954 case 7:
7a387fff
TS
3955 switch (sel) {
3956 case 0:
e189e748 3957 check_insn(env, ctx, ISA_MIPS32R2);
d9bea114 3958 gen_helper_mtc0_hwrena(arg);
2423f660
TS
3959 rn = "HWREna";
3960 break;
7a387fff
TS
3961 default:
3962 goto die;
876d4b07 3963 }
8c0fdd85
TS
3964 break;
3965 case 8:
7a387fff 3966 /* ignored */
f0b3f3ae 3967 rn = "BadVAddr";
8c0fdd85
TS
3968 break;
3969 case 9:
7a387fff
TS
3970 switch (sel) {
3971 case 0:
d9bea114 3972 gen_helper_mtc0_count(arg);
2423f660
TS
3973 rn = "Count";
3974 break;
876d4b07 3975 /* 6,7 are implementation dependent */
7a387fff
TS
3976 default:
3977 goto die;
876d4b07 3978 }
8c0fdd85
TS
3979 break;
3980 case 10:
7a387fff
TS
3981 switch (sel) {
3982 case 0:
d9bea114 3983 gen_helper_mtc0_entryhi(arg);
2423f660
TS
3984 rn = "EntryHi";
3985 break;
7a387fff
TS
3986 default:
3987 goto die;
876d4b07 3988 }
8c0fdd85
TS
3989 break;
3990 case 11:
7a387fff
TS
3991 switch (sel) {
3992 case 0:
d9bea114 3993 gen_helper_mtc0_compare(arg);
2423f660
TS
3994 rn = "Compare";
3995 break;
3996 /* 6,7 are implementation dependent */
7a387fff
TS
3997 default:
3998 goto die;
876d4b07 3999 }
8c0fdd85
TS
4000 break;
4001 case 12:
7a387fff
TS
4002 switch (sel) {
4003 case 0:
867abc7e 4004 save_cpu_state(ctx, 1);
d9bea114 4005 gen_helper_mtc0_status(arg);
8487327a
TS
4006 /* BS_STOP isn't good enough here, hflags may have changed. */
4007 gen_save_pc(ctx->pc + 4);
4008 ctx->bstate = BS_EXCP;
2423f660
TS
4009 rn = "Status";
4010 break;
7a387fff 4011 case 1:
e189e748 4012 check_insn(env, ctx, ISA_MIPS32R2);
d9bea114 4013 gen_helper_mtc0_intctl(arg);
8487327a
TS
4014 /* Stop translation as we may have switched the execution mode */
4015 ctx->bstate = BS_STOP;
2423f660
TS
4016 rn = "IntCtl";
4017 break;
7a387fff 4018 case 2:
e189e748 4019 check_insn(env, ctx, ISA_MIPS32R2);
d9bea114 4020 gen_helper_mtc0_srsctl(arg);
8487327a
TS
4021 /* Stop translation as we may have switched the execution mode */
4022 ctx->bstate = BS_STOP;
2423f660
TS
4023 rn = "SRSCtl";
4024 break;
7a387fff 4025 case 3:
e189e748 4026 check_insn(env, ctx, ISA_MIPS32R2);
7db13fae 4027 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
8487327a
TS
4028 /* Stop translation as we may have switched the execution mode */
4029 ctx->bstate = BS_STOP;
2423f660 4030 rn = "SRSMap";
fd88b6ab 4031 break;
7a387fff
TS
4032 default:
4033 goto die;
876d4b07 4034 }
8c0fdd85
TS
4035 break;
4036 case 13:
7a387fff
TS
4037 switch (sel) {
4038 case 0:
867abc7e 4039 save_cpu_state(ctx, 1);
d9bea114 4040 gen_helper_mtc0_cause(arg);
2423f660
TS
4041 rn = "Cause";
4042 break;
7a387fff
TS
4043 default:
4044 goto die;
876d4b07 4045 }
8c0fdd85
TS
4046 break;
4047 case 14:
7a387fff
TS
4048 switch (sel) {
4049 case 0:
7db13fae 4050 gen_mtc0_store64(arg, offsetof(CPUMIPSState, CP0_EPC));
2423f660
TS
4051 rn = "EPC";
4052 break;
7a387fff
TS
4053 default:
4054 goto die;
876d4b07 4055 }
8c0fdd85
TS
4056 break;
4057 case 15:
7a387fff
TS
4058 switch (sel) {
4059 case 0:
2423f660
TS
4060 /* ignored */
4061 rn = "PRid";
4062 break;
7a387fff 4063 case 1:
e189e748 4064 check_insn(env, ctx, ISA_MIPS32R2);
d9bea114 4065 gen_helper_mtc0_ebase(arg);
2423f660
TS
4066 rn = "EBase";
4067 break;
7a387fff
TS
4068 default:
4069 goto die;
1579a72e 4070 }
8c0fdd85
TS
4071 break;
4072 case 16:
4073 switch (sel) {
4074 case 0:
d9bea114 4075 gen_helper_mtc0_config0(arg);
7a387fff 4076 rn = "Config";
2423f660
TS
4077 /* Stop translation as we may have switched the execution mode */
4078 ctx->bstate = BS_STOP;
7a387fff
TS
4079 break;
4080 case 1:
e397ee33 4081 /* ignored, read only */
7a387fff
TS
4082 rn = "Config1";
4083 break;
4084 case 2:
d9bea114 4085 gen_helper_mtc0_config2(arg);
7a387fff 4086 rn = "Config2";
2423f660
TS
4087 /* Stop translation as we may have switched the execution mode */
4088 ctx->bstate = BS_STOP;
8c0fdd85 4089 break;
7a387fff 4090 case 3:
e397ee33 4091 /* ignored, read only */
7a387fff
TS
4092 rn = "Config3";
4093 break;
e397ee33
TS
4094 /* 4,5 are reserved */
4095 /* 6,7 are implementation dependent */
4096 case 6:
4097 /* ignored */
4098 rn = "Config6";
4099 break;
4100 case 7:
4101 /* ignored */
4102 rn = "Config7";
4103 break;
8c0fdd85
TS
4104 default:
4105 rn = "Invalid config selector";
4106 goto die;
4107 }
4108 break;
4109 case 17:
7a387fff
TS
4110 switch (sel) {
4111 case 0:
2a6e32dd 4112 gen_helper_mtc0_lladdr(arg);
2423f660
TS
4113 rn = "LLAddr";
4114 break;
7a387fff
TS
4115 default:
4116 goto die;
4117 }
8c0fdd85
TS
4118 break;
4119 case 18:
7a387fff 4120 switch (sel) {
fd88b6ab 4121 case 0 ... 7:
d9bea114 4122 gen_helper_1i(mtc0_watchlo, arg, sel);
2423f660
TS
4123 rn = "WatchLo";
4124 break;
7a387fff
TS
4125 default:
4126 goto die;
4127 }
8c0fdd85
TS
4128 break;
4129 case 19:
7a387fff 4130 switch (sel) {
fd88b6ab 4131 case 0 ... 7:
d9bea114 4132 gen_helper_1i(mtc0_watchhi, arg, sel);
2423f660
TS
4133 rn = "WatchHi";
4134 break;
7a387fff
TS
4135 default:
4136 goto die;
4137 }
8c0fdd85
TS
4138 break;
4139 case 20:
7a387fff
TS
4140 switch (sel) {
4141 case 0:
d26bc211 4142#if defined(TARGET_MIPS64)
e189e748 4143 check_insn(env, ctx, ISA_MIPS3);
d9bea114 4144 gen_helper_mtc0_xcontext(arg);
2423f660
TS
4145 rn = "XContext";
4146 break;
703eaf37 4147#endif
7a387fff
TS
4148 default:
4149 goto die;
4150 }
8c0fdd85
TS
4151 break;
4152 case 21:
7a387fff
TS
4153 /* Officially reserved, but sel 0 is used for R1x000 framemask */
4154 switch (sel) {
4155 case 0:
d9bea114 4156 gen_helper_mtc0_framemask(arg);
2423f660
TS
4157 rn = "Framemask";
4158 break;
7a387fff
TS
4159 default:
4160 goto die;
4161 }
4162 break;
8c0fdd85 4163 case 22:
7a387fff
TS
4164 /* ignored */
4165 rn = "Diagnostic"; /* implementation dependent */
2423f660 4166 break;
8c0fdd85 4167 case 23:
7a387fff
TS
4168 switch (sel) {
4169 case 0:
d9bea114 4170 gen_helper_mtc0_debug(arg); /* EJTAG support */
8487327a
TS
4171 /* BS_STOP isn't good enough here, hflags may have changed. */
4172 gen_save_pc(ctx->pc + 4);
4173 ctx->bstate = BS_EXCP;
2423f660
TS
4174 rn = "Debug";
4175 break;
7a387fff 4176 case 1:
d9bea114 4177// gen_helper_mtc0_tracecontrol(arg); /* PDtrace support */
2423f660 4178 rn = "TraceControl";
8487327a
TS
4179 /* Stop translation as we may have switched the execution mode */
4180 ctx->bstate = BS_STOP;
2423f660 4181// break;
7a387fff 4182 case 2:
d9bea114 4183// gen_helper_mtc0_tracecontrol2(arg); /* PDtrace support */
2423f660 4184 rn = "TraceControl2";
8487327a
TS
4185 /* Stop translation as we may have switched the execution mode */
4186 ctx->bstate = BS_STOP;
2423f660 4187// break;
7a387fff 4188 case 3:
8487327a
TS
4189 /* Stop translation as we may have switched the execution mode */
4190 ctx->bstate = BS_STOP;
d9bea114 4191// gen_helper_mtc0_usertracedata(arg); /* PDtrace support */
2423f660 4192 rn = "UserTraceData";
8487327a
TS
4193 /* Stop translation as we may have switched the execution mode */
4194 ctx->bstate = BS_STOP;
2423f660 4195// break;
7a387fff 4196 case 4:
d9bea114 4197// gen_helper_mtc0_tracebpc(arg); /* PDtrace support */
8487327a
TS
4198 /* Stop translation as we may have switched the execution mode */
4199 ctx->bstate = BS_STOP;
2423f660
TS
4200 rn = "TraceBPC";
4201// break;
7a387fff
TS
4202 default:
4203 goto die;
4204 }
8c0fdd85
TS
4205 break;
4206 case 24:
7a387fff
TS
4207 switch (sel) {
4208 case 0:
f1aa6320 4209 /* EJTAG support */
7db13fae 4210 gen_mtc0_store64(arg, offsetof(CPUMIPSState, CP0_DEPC));
2423f660
TS
4211 rn = "DEPC";
4212 break;
7a387fff
TS
4213 default:
4214 goto die;
4215 }
8c0fdd85
TS
4216 break;
4217 case 25:
7a387fff
TS
4218 switch (sel) {
4219 case 0:
d9bea114 4220 gen_helper_mtc0_performance0(arg);
2423f660
TS
4221 rn = "Performance0";
4222 break;
7a387fff 4223 case 1:
d9bea114 4224// gen_helper_mtc0_performance1(arg);
2423f660
TS
4225 rn = "Performance1";
4226// break;
7a387fff 4227 case 2:
d9bea114 4228// gen_helper_mtc0_performance2(arg);
2423f660
TS
4229 rn = "Performance2";
4230// break;
7a387fff 4231 case 3:
d9bea114 4232// gen_helper_mtc0_performance3(arg);
2423f660
TS
4233 rn = "Performance3";
4234// break;
7a387fff 4235 case 4:
d9bea114 4236// gen_helper_mtc0_performance4(arg);
2423f660
TS
4237 rn = "Performance4";
4238// break;
7a387fff 4239 case 5:
d9bea114 4240// gen_helper_mtc0_performance5(arg);
2423f660
TS
4241 rn = "Performance5";
4242// break;
7a387fff 4243 case 6:
d9bea114 4244// gen_helper_mtc0_performance6(arg);
2423f660
TS
4245 rn = "Performance6";
4246// break;
7a387fff 4247 case 7:
d9bea114 4248// gen_helper_mtc0_performance7(arg);
2423f660
TS
4249 rn = "Performance7";
4250// break;
7a387fff
TS
4251 default:
4252 goto die;
4253 }
8c0fdd85
TS
4254 break;
4255 case 26:
2423f660 4256 /* ignored */
8c0fdd85 4257 rn = "ECC";
2423f660 4258 break;
8c0fdd85 4259 case 27:
7a387fff
TS
4260 switch (sel) {
4261 case 0 ... 3:
2423f660
TS
4262 /* ignored */
4263 rn = "CacheErr";
4264 break;
7a387fff
TS
4265 default:
4266 goto die;
4267 }
8c0fdd85
TS
4268 break;
4269 case 28:
4270 switch (sel) {
4271 case 0:
7a387fff
TS
4272 case 2:
4273 case 4:
4274 case 6:
d9bea114 4275 gen_helper_mtc0_taglo(arg);
8c0fdd85
TS
4276 rn = "TagLo";
4277 break;
7a387fff
TS
4278 case 1:
4279 case 3:
4280 case 5:
4281 case 7:
d9bea114 4282 gen_helper_mtc0_datalo(arg);
7a387fff
TS
4283 rn = "DataLo";
4284 break;
8c0fdd85 4285 default:
8c0fdd85
TS
4286 goto die;
4287 }
4288 break;
4289 case 29:
7a387fff
TS
4290 switch (sel) {
4291 case 0:
4292 case 2:
4293 case 4:
4294 case 6:
d9bea114 4295 gen_helper_mtc0_taghi(arg);
7a387fff
TS
4296 rn = "TagHi";
4297 break;
4298 case 1:
4299 case 3:
4300 case 5:
4301 case 7:
d9bea114 4302 gen_helper_mtc0_datahi(arg);
7a387fff
TS
4303 rn = "DataHi";
4304 break;
4305 default:
4306 rn = "invalid sel";
4307 goto die;
4308 }
8c0fdd85
TS
4309 break;
4310 case 30:
7a387fff
TS
4311 switch (sel) {
4312 case 0:
7db13fae 4313 gen_mtc0_store64(arg, offsetof(CPUMIPSState, CP0_ErrorEPC));
2423f660
TS
4314 rn = "ErrorEPC";
4315 break;
7a387fff
TS
4316 default:
4317 goto die;
4318 }
8c0fdd85
TS
4319 break;
4320 case 31:
7a387fff
TS
4321 switch (sel) {
4322 case 0:
f1aa6320 4323 /* EJTAG support */
7db13fae 4324 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
2423f660
TS
4325 rn = "DESAVE";
4326 break;
7a387fff
TS
4327 default:
4328 goto die;
4329 }
2423f660
TS
4330 /* Stop translation as we may have switched the execution mode */
4331 ctx->bstate = BS_STOP;
8c0fdd85
TS
4332 break;
4333 default:
8c0fdd85
TS
4334 goto die;
4335 }
2abf314d 4336 (void)rn; /* avoid a compiler warning */
d12d51d5 4337 LOG_DISAS("mtc0 %s (reg %d sel %d)\n", rn, reg, sel);
bf20dc07 4338 /* For simplicity assume that all writes can cause interrupts. */
2e70f6ef
PB
4339 if (use_icount) {
4340 gen_io_end();
4341 ctx->bstate = BS_STOP;
4342 }
8c0fdd85
TS
4343 return;
4344
4345die:
d12d51d5 4346 LOG_DISAS("mtc0 %s (reg %d sel %d)\n", rn, reg, sel);
8c0fdd85
TS
4347 generate_exception(ctx, EXCP_RI);
4348}
4349
d26bc211 4350#if defined(TARGET_MIPS64)
7db13fae 4351static void gen_dmfc0 (CPUMIPSState *env, DisasContext *ctx, TCGv arg, int reg, int sel)
9c2149c8
TS
4352{
4353 const char *rn = "invalid";
4354
e189e748
TS
4355 if (sel != 0)
4356 check_insn(env, ctx, ISA_MIPS64);
4357
9c2149c8
TS
4358 switch (reg) {
4359 case 0:
4360 switch (sel) {
4361 case 0:
7db13fae 4362 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Index));
9c2149c8
TS
4363 rn = "Index";
4364 break;
4365 case 1:
7385ac0b 4366 check_insn(env, ctx, ASE_MT);
d9bea114 4367 gen_helper_mfc0_mvpcontrol(arg);
9c2149c8 4368 rn = "MVPControl";
ead9360e 4369 break;
9c2149c8 4370 case 2:
7385ac0b 4371 check_insn(env, ctx, ASE_MT);
d9bea114 4372 gen_helper_mfc0_mvpconf0(arg);
9c2149c8 4373 rn = "MVPConf0";
ead9360e 4374 break;
9c2149c8 4375 case 3:
7385ac0b 4376 check_insn(env, ctx, ASE_MT);
d9bea114 4377 gen_helper_mfc0_mvpconf1(arg);
9c2149c8 4378 rn = "MVPConf1";
ead9360e 4379 break;
9c2149c8
TS
4380 default:
4381 goto die;
4382 }
4383 break;
4384 case 1:
4385 switch (sel) {
4386 case 0:
d9bea114 4387 gen_helper_mfc0_random(arg);
9c2149c8 4388 rn = "Random";
2423f660 4389 break;
9c2149c8 4390 case 1:
7385ac0b 4391 check_insn(env, ctx, ASE_MT);
7db13fae 4392 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEControl));
9c2149c8 4393 rn = "VPEControl";
ead9360e 4394 break;
9c2149c8 4395 case 2:
7385ac0b 4396 check_insn(env, ctx, ASE_MT);
7db13fae 4397 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf0));
9c2149c8 4398 rn = "VPEConf0";
ead9360e 4399 break;
9c2149c8 4400 case 3:
7385ac0b 4401 check_insn(env, ctx, ASE_MT);
7db13fae 4402 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf1));
9c2149c8 4403 rn = "VPEConf1";
ead9360e 4404 break;
9c2149c8 4405 case 4:
7385ac0b 4406 check_insn(env, ctx, ASE_MT);
7db13fae 4407 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_YQMask));
9c2149c8 4408 rn = "YQMask";
ead9360e 4409 break;
9c2149c8 4410 case 5:
7385ac0b 4411 check_insn(env, ctx, ASE_MT);
7db13fae 4412 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_VPESchedule));
9c2149c8 4413 rn = "VPESchedule";
ead9360e 4414 break;
9c2149c8 4415 case 6:
7385ac0b 4416 check_insn(env, ctx, ASE_MT);
7db13fae 4417 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_VPEScheFBack));
9c2149c8 4418 rn = "VPEScheFBack";
ead9360e 4419 break;
9c2149c8 4420 case 7:
7385ac0b 4421 check_insn(env, ctx, ASE_MT);
7db13fae 4422 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEOpt));
9c2149c8 4423 rn = "VPEOpt";
ead9360e 4424 break;
9c2149c8
TS
4425 default:
4426 goto die;
4427 }
4428 break;
4429 case 2:
4430 switch (sel) {
4431 case 0:
7db13fae 4432 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryLo0));
2423f660
TS
4433 rn = "EntryLo0";
4434 break;
9c2149c8 4435 case 1:
7385ac0b 4436 check_insn(env, ctx, ASE_MT);
d9bea114 4437 gen_helper_mfc0_tcstatus(arg);
2423f660 4438 rn = "TCStatus";
ead9360e 4439 break;
9c2149c8 4440 case 2:
7385ac0b 4441 check_insn(env, ctx, ASE_MT);
d9bea114 4442 gen_helper_mfc0_tcbind(arg);
2423f660 4443 rn = "TCBind";
ead9360e 4444 break;
9c2149c8 4445 case 3:
7385ac0b 4446 check_insn(env, ctx, ASE_MT);
d9bea114 4447 gen_helper_dmfc0_tcrestart(arg);
2423f660 4448 rn = "TCRestart";
ead9360e 4449 break;
9c2149c8 4450 case 4:
7385ac0b 4451 check_insn(env, ctx, ASE_MT);
d9bea114 4452 gen_helper_dmfc0_tchalt(arg);
2423f660 4453 rn = "TCHalt";
ead9360e 4454 break;
9c2149c8 4455 case 5:
7385ac0b 4456 check_insn(env, ctx, ASE_MT);
d9bea114 4457 gen_helper_dmfc0_tccontext(arg);
2423f660 4458 rn = "TCContext";
ead9360e 4459 break;
9c2149c8 4460 case 6:
7385ac0b 4461 check_insn(env, ctx, ASE_MT);
d9bea114 4462 gen_helper_dmfc0_tcschedule(arg);
2423f660 4463 rn = "TCSchedule";
ead9360e 4464 break;
9c2149c8 4465 case 7:
7385ac0b 4466 check_insn(env, ctx, ASE_MT);
d9bea114 4467 gen_helper_dmfc0_tcschefback(arg);
2423f660 4468 rn = "TCScheFBack";
ead9360e 4469 break;
9c2149c8
TS
4470 default:
4471 goto die;
4472 }
4473 break;
4474 case 3:
4475 switch (sel) {
4476 case 0:
7db13fae 4477 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryLo1));
2423f660
TS
4478 rn = "EntryLo1";
4479 break;
9c2149c8
TS
4480 default:
4481 goto die;
1579a72e 4482 }
9c2149c8
TS
4483 break;
4484 case 4:
4485 switch (sel) {
4486 case 0:
7db13fae 4487 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_Context));
2423f660
TS
4488 rn = "Context";
4489 break;
9c2149c8 4490 case 1:
d9bea114 4491// gen_helper_dmfc0_contextconfig(arg); /* SmartMIPS ASE */
2423f660
TS
4492 rn = "ContextConfig";
4493// break;
9c2149c8
TS
4494 default:
4495 goto die;
876d4b07 4496 }
9c2149c8
TS
4497 break;
4498 case 5:
4499 switch (sel) {
4500 case 0:
7db13fae 4501 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageMask));
2423f660
TS
4502 rn = "PageMask";
4503 break;
9c2149c8 4504 case 1:
e189e748 4505 check_insn(env, ctx, ISA_MIPS32R2);
7db13fae 4506 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageGrain));
2423f660
TS
4507 rn = "PageGrain";
4508 break;
9c2149c8
TS
4509 default:
4510 goto die;
876d4b07 4511 }
9c2149c8
TS
4512 break;
4513 case 6:
4514 switch (sel) {
4515 case 0:
7db13fae 4516 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Wired));
2423f660
TS
4517 rn = "Wired";
4518 break;
9c2149c8 4519 case 1:
e189e748 4520 check_insn(env, ctx, ISA_MIPS32R2);
7db13fae 4521 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf0));
2423f660 4522 rn = "SRSConf0";
ead9360e 4523 break;
9c2149c8 4524 case 2:
e189e748 4525 check_insn(env, ctx, ISA_MIPS32R2);
7db13fae 4526 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf1));
2423f660 4527 rn = "SRSConf1";
ead9360e 4528 break;
9c2149c8 4529 case 3:
e189e748 4530 check_insn(env, ctx, ISA_MIPS32R2);
7db13fae 4531 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf2));
2423f660 4532 rn = "SRSConf2";
ead9360e 4533 break;
9c2149c8 4534 case 4:
e189e748 4535 check_insn(env, ctx, ISA_MIPS32R2);
7db13fae 4536 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf3));
2423f660 4537 rn = "SRSConf3";
ead9360e 4538 break;
9c2149c8 4539 case 5:
e189e748 4540 check_insn(env, ctx, ISA_MIPS32R2);
7db13fae 4541 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf4));
2423f660 4542 rn = "SRSConf4";
ead9360e 4543 break;
9c2149c8
TS
4544 default:
4545 goto die;
876d4b07 4546 }
9c2149c8
TS
4547 break;
4548 case 7:
4549 switch (sel) {
4550 case 0:
e189e748 4551 check_insn(env, ctx, ISA_MIPS32R2);
7db13fae 4552 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_HWREna));
2423f660
TS
4553 rn = "HWREna";
4554 break;
9c2149c8
TS
4555 default:
4556 goto die;
876d4b07 4557 }
9c2149c8
TS
4558 break;
4559 case 8:
4560 switch (sel) {
4561 case 0:
7db13fae 4562 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_BadVAddr));
f0b3f3ae 4563 rn = "BadVAddr";
2423f660 4564 break;
9c2149c8
TS
4565 default:
4566 goto die;
876d4b07 4567 }
9c2149c8
TS
4568 break;
4569 case 9:
4570 switch (sel) {
4571 case 0:
2e70f6ef
PB
4572 /* Mark as an IO operation because we read the time. */
4573 if (use_icount)
4574 gen_io_start();
d9bea114 4575 gen_helper_mfc0_count(arg);
2e70f6ef
PB
4576 if (use_icount) {
4577 gen_io_end();
2e70f6ef 4578 }
55807224
EI
4579 /* Break the TB to be able to take timer interrupts immediately
4580 after reading count. */
4581 ctx->bstate = BS_STOP;
2423f660
TS
4582 rn = "Count";
4583 break;
4584 /* 6,7 are implementation dependent */
9c2149c8
TS
4585 default:
4586 goto die;
876d4b07 4587 }
9c2149c8
TS
4588 break;
4589 case 10:
4590 switch (sel) {
4591 case 0:
7db13fae 4592 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryHi));
2423f660
TS
4593 rn = "EntryHi";
4594 break;
9c2149c8
TS
4595 default:
4596 goto die;
876d4b07 4597 }
9c2149c8
TS
4598 break;
4599 case 11:
4600 switch (sel) {
4601 case 0:
7db13fae 4602 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Compare));
2423f660
TS
4603 rn = "Compare";
4604 break;
876d4b07 4605 /* 6,7 are implementation dependent */
9c2149c8
TS
4606 default:
4607 goto die;
876d4b07 4608 }
9c2149c8
TS
4609 break;
4610 case 12:
4611 switch (sel) {
4612 case 0:
7db13fae 4613 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Status));
2423f660
TS
4614 rn = "Status";
4615 break;
9c2149c8 4616 case 1:
e189e748 4617 check_insn(env, ctx, ISA_MIPS32R2);
7db13fae 4618 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_IntCtl));
2423f660
TS
4619 rn = "IntCtl";
4620 break;
9c2149c8 4621 case 2:
e189e748 4622 check_insn(env, ctx, ISA_MIPS32R2);
7db13fae 4623 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSCtl));
2423f660
TS
4624 rn = "SRSCtl";
4625 break;
9c2149c8 4626 case 3:
e189e748 4627 check_insn(env, ctx, ISA_MIPS32R2);
7db13fae 4628 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
2423f660
TS
4629 rn = "SRSMap";
4630 break;
9c2149c8
TS
4631 default:
4632 goto die;
876d4b07 4633 }
9c2149c8
TS
4634 break;
4635 case 13:
4636 switch (sel) {
4637 case 0:
7db13fae 4638 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Cause));
2423f660
TS
4639 rn = "Cause";
4640 break;
9c2149c8
TS
4641 default:
4642 goto die;
876d4b07 4643 }
9c2149c8
TS
4644 break;
4645 case 14:
4646 switch (sel) {
4647 case 0:
7db13fae 4648 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EPC));
2423f660
TS
4649 rn = "EPC";
4650 break;
9c2149c8
TS
4651 default:
4652 goto die;
876d4b07 4653 }
9c2149c8
TS
4654 break;
4655 case 15:
4656 switch (sel) {
4657 case 0:
7db13fae 4658 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PRid));
2423f660
TS
4659 rn = "PRid";
4660 break;
9c2149c8 4661 case 1:
e189e748 4662 check_insn(env, ctx, ISA_MIPS32R2);
7db13fae 4663 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_EBase));
2423f660
TS
4664 rn = "EBase";
4665 break;
9c2149c8
TS
4666 default:
4667 goto die;
876d4b07 4668 }
9c2149c8
TS
4669 break;
4670 case 16:
4671 switch (sel) {
4672 case 0:
7db13fae 4673 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config0));
9c2149c8
TS
4674 rn = "Config";
4675 break;
4676 case 1:
7db13fae 4677 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config1));
9c2149c8
TS
4678 rn = "Config1";
4679 break;
4680 case 2:
7db13fae 4681 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config2));
9c2149c8
TS
4682 rn = "Config2";
4683 break;
4684 case 3:
7db13fae 4685 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config3));
9c2149c8
TS
4686 rn = "Config3";
4687 break;
4688 /* 6,7 are implementation dependent */
f0b3f3ae 4689 case 6:
7db13fae 4690 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config6));
f0b3f3ae
TS
4691 rn = "Config6";
4692 break;
4693 case 7:
7db13fae 4694 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config7));
f0b3f3ae
TS
4695 rn = "Config7";
4696 break;
9c2149c8
TS
4697 default:
4698 goto die;
4699 }
4700 break;
4701 case 17:
4702 switch (sel) {
4703 case 0:
d9bea114 4704 gen_helper_dmfc0_lladdr(arg);
2423f660
TS
4705 rn = "LLAddr";
4706 break;
9c2149c8
TS
4707 default:
4708 goto die;
4709 }
4710 break;
4711 case 18:
4712 switch (sel) {
fd88b6ab 4713 case 0 ... 7:
d9bea114 4714 gen_helper_1i(dmfc0_watchlo, arg, sel);
2423f660
TS
4715 rn = "WatchLo";
4716 break;
9c2149c8
TS
4717 default:
4718 goto die;
4719 }
4720 break;
4721 case 19:
4722 switch (sel) {
fd88b6ab 4723 case 0 ... 7:
d9bea114 4724 gen_helper_1i(mfc0_watchhi, arg, sel);
2423f660
TS
4725 rn = "WatchHi";
4726 break;
9c2149c8
TS
4727 default:
4728 goto die;
4729 }
4730 break;
4731 case 20:
4732 switch (sel) {
4733 case 0:
e189e748 4734 check_insn(env, ctx, ISA_MIPS3);
7db13fae 4735 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_XContext));
2423f660
TS
4736 rn = "XContext";
4737 break;
9c2149c8
TS
4738 default:
4739 goto die;
4740 }
4741 break;
4742 case 21:
4743 /* Officially reserved, but sel 0 is used for R1x000 framemask */
4744 switch (sel) {
4745 case 0:
7db13fae 4746 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Framemask));
2423f660
TS
4747 rn = "Framemask";
4748 break;
9c2149c8
TS
4749 default:
4750 goto die;
4751 }
4752 break;
4753 case 22:
d9bea114 4754 tcg_gen_movi_tl(arg, 0); /* unimplemented */
2423f660
TS
4755 rn = "'Diagnostic"; /* implementation dependent */
4756 break;
9c2149c8
TS
4757 case 23:
4758 switch (sel) {
4759 case 0:
d9bea114 4760 gen_helper_mfc0_debug(arg); /* EJTAG support */
2423f660
TS
4761 rn = "Debug";
4762 break;
9c2149c8 4763 case 1:
d9bea114 4764// gen_helper_dmfc0_tracecontrol(arg); /* PDtrace support */
2423f660
TS
4765 rn = "TraceControl";
4766// break;
9c2149c8 4767 case 2:
d9bea114 4768// gen_helper_dmfc0_tracecontrol2(arg); /* PDtrace support */
2423f660
TS
4769 rn = "TraceControl2";
4770// break;
9c2149c8 4771 case 3:
d9bea114 4772// gen_helper_dmfc0_usertracedata(arg); /* PDtrace support */
2423f660
TS
4773 rn = "UserTraceData";
4774// break;
9c2149c8 4775 case 4:
d9bea114 4776// gen_helper_dmfc0_tracebpc(arg); /* PDtrace support */
2423f660
TS
4777 rn = "TraceBPC";
4778// break;
9c2149c8
TS
4779 default:
4780 goto die;
4781 }
4782 break;
4783 case 24:
4784 switch (sel) {
4785 case 0:
f0b3f3ae 4786 /* EJTAG support */
7db13fae 4787 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_DEPC));
2423f660
TS
4788 rn = "DEPC";
4789 break;
9c2149c8
TS
4790 default:
4791 goto die;
4792 }
4793 break;
4794 case 25:
4795 switch (sel) {
4796 case 0:
7db13fae 4797 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Performance0));
2423f660 4798 rn = "Performance0";
9c2149c8
TS
4799 break;
4800 case 1:
d9bea114 4801// gen_helper_dmfc0_performance1(arg);
2423f660
TS
4802 rn = "Performance1";
4803// break;
9c2149c8 4804 case 2:
d9bea114 4805// gen_helper_dmfc0_performance2(arg);
2423f660
TS
4806 rn = "Performance2";
4807// break;
9c2149c8 4808 case 3:
d9bea114 4809// gen_helper_dmfc0_performance3(arg);
2423f660
TS
4810 rn = "Performance3";
4811// break;
9c2149c8 4812 case 4:
d9bea114 4813// gen_helper_dmfc0_performance4(arg);
2423f660
TS
4814 rn = "Performance4";
4815// break;
9c2149c8 4816 case 5:
d9bea114 4817// gen_helper_dmfc0_performance5(arg);
2423f660
TS
4818 rn = "Performance5";
4819// break;
9c2149c8 4820 case 6:
d9bea114 4821// gen_helper_dmfc0_performance6(arg);
2423f660
TS
4822 rn = "Performance6";
4823// break;
9c2149c8 4824 case 7:
d9bea114 4825// gen_helper_dmfc0_performance7(arg);
2423f660
TS
4826 rn = "Performance7";
4827// break;
9c2149c8
TS
4828 default:
4829 goto die;
4830 }
4831 break;
4832 case 26:
d9bea114 4833 tcg_gen_movi_tl(arg, 0); /* unimplemented */
da80682b
AJ
4834 rn = "ECC";
4835 break;
9c2149c8
TS
4836 case 27:
4837 switch (sel) {
4838 /* ignored */
4839 case 0 ... 3:
d9bea114 4840 tcg_gen_movi_tl(arg, 0); /* unimplemented */
2423f660
TS
4841 rn = "CacheErr";
4842 break;
9c2149c8
TS
4843 default:
4844 goto die;
4845 }
4846 break;
4847 case 28:
4848 switch (sel) {
4849 case 0:
4850 case 2:
4851 case 4:
4852 case 6:
7db13fae 4853 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_TagLo));
9c2149c8
TS
4854 rn = "TagLo";
4855 break;
4856 case 1:
4857 case 3:
4858 case 5:
4859 case 7:
7db13fae 4860 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataLo));
9c2149c8
TS
4861 rn = "DataLo";
4862 break;
4863 default:
4864 goto die;
4865 }
4866 break;
4867 case 29:
4868 switch (sel) {
4869 case 0:
4870 case 2:
4871 case 4:
4872 case 6:
7db13fae 4873 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_TagHi));
9c2149c8
TS
4874 rn = "TagHi";
4875 break;
4876 case 1:
4877 case 3:
4878 case 5:
4879 case 7:
7db13fae 4880 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataHi));
9c2149c8
TS
4881 rn = "DataHi";
4882 break;
4883 default:
4884 goto die;
4885 }
4886 break;
4887 case 30:
4888 switch (sel) {
4889 case 0:
7db13fae 4890 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_ErrorEPC));
2423f660
TS
4891 rn = "ErrorEPC";
4892 break;
9c2149c8
TS
4893 default:
4894 goto die;
4895 }
4896 break;
4897 case 31:
4898 switch (sel) {
4899 case 0:
f0b3f3ae 4900 /* EJTAG support */
7db13fae 4901 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
2423f660
TS
4902 rn = "DESAVE";
4903 break;
9c2149c8
TS
4904 default:
4905 goto die;
4906 }
4907 break;
4908 default:
876d4b07 4909 goto die;
9c2149c8 4910 }
2abf314d 4911 (void)rn; /* avoid a compiler warning */
d12d51d5 4912 LOG_DISAS("dmfc0 %s (reg %d sel %d)\n", rn, reg, sel);
9c2149c8
TS
4913 return;
4914
4915die:
d12d51d5 4916 LOG_DISAS("dmfc0 %s (reg %d sel %d)\n", rn, reg, sel);
9c2149c8
TS
4917 generate_exception(ctx, EXCP_RI);
4918}
4919
7db13fae 4920static void gen_dmtc0 (CPUMIPSState *env, DisasContext *ctx, TCGv arg, int reg, int sel)
9c2149c8
TS
4921{
4922 const char *rn = "invalid";
4923
e189e748
TS
4924 if (sel != 0)
4925 check_insn(env, ctx, ISA_MIPS64);
4926
2e70f6ef
PB
4927 if (use_icount)
4928 gen_io_start();
4929
9c2149c8
TS
4930 switch (reg) {
4931 case 0:
4932 switch (sel) {
4933 case 0:
d9bea114 4934 gen_helper_mtc0_index(arg);
9c2149c8
TS
4935 rn = "Index";
4936 break;
4937 case 1:
7385ac0b 4938 check_insn(env, ctx, ASE_MT);
d9bea114 4939 gen_helper_mtc0_mvpcontrol(arg);
9c2149c8 4940 rn = "MVPControl";
ead9360e 4941 break;
9c2149c8 4942 case 2:
7385ac0b 4943 check_insn(env, ctx, ASE_MT);
ead9360e 4944 /* ignored */
9c2149c8 4945 rn = "MVPConf0";
ead9360e 4946 break;
9c2149c8 4947 case 3:
7385ac0b 4948 check_insn(env, ctx, ASE_MT);
ead9360e 4949 /* ignored */
9c2149c8 4950 rn = "MVPConf1";
ead9360e 4951 break;
9c2149c8
TS
4952 default:
4953 goto die;
4954 }
4955 break;
4956 case 1:
4957 switch (sel) {
4958 case 0:
2423f660 4959 /* ignored */
9c2149c8 4960 rn = "Random";
2423f660 4961 break;
9c2149c8 4962 case 1:
7385ac0b 4963 check_insn(env, ctx, ASE_MT);
d9bea114 4964 gen_helper_mtc0_vpecontrol(arg);
9c2149c8 4965 rn = "VPEControl";
ead9360e 4966 break;
9c2149c8 4967 case 2:
7385ac0b 4968 check_insn(env, ctx, ASE_MT);
d9bea114 4969 gen_helper_mtc0_vpeconf0(arg);
9c2149c8 4970 rn = "VPEConf0";
ead9360e 4971 break;
9c2149c8 4972 case 3:
7385ac0b 4973 check_insn(env, ctx, ASE_MT);
d9bea114 4974 gen_helper_mtc0_vpeconf1(arg);
9c2149c8 4975 rn = "VPEConf1";
ead9360e 4976 break;
9c2149c8 4977 case 4:
7385ac0b 4978 check_insn(env, ctx, ASE_MT);
d9bea114 4979 gen_helper_mtc0_yqmask(arg);
9c2149c8 4980 rn = "YQMask";
ead9360e 4981 break;
9c2149c8 4982 case 5:
7385ac0b 4983 check_insn(env, ctx, ASE_MT);
7db13fae 4984 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_VPESchedule));
9c2149c8 4985 rn = "VPESchedule";
ead9360e 4986 break;
9c2149c8 4987 case 6:
7385ac0b 4988 check_insn(env, ctx, ASE_MT);
7db13fae 4989 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_VPEScheFBack));
9c2149c8 4990 rn = "VPEScheFBack";
ead9360e 4991 break;
9c2149c8 4992 case 7:
7385ac0b 4993 check_insn(env, ctx, ASE_MT);
d9bea114 4994 gen_helper_mtc0_vpeopt(arg);
9c2149c8 4995 rn = "VPEOpt";
ead9360e 4996 break;
9c2149c8
TS
4997 default:
4998 goto die;
4999 }
5000 break;
5001 case 2:
5002 switch (sel) {
5003 case 0:
d9bea114 5004 gen_helper_mtc0_entrylo0(arg);
2423f660
TS
5005 rn = "EntryLo0";
5006 break;
9c2149c8 5007 case 1:
7385ac0b 5008 check_insn(env, ctx, ASE_MT);
d9bea114 5009 gen_helper_mtc0_tcstatus(arg);
2423f660 5010 rn = "TCStatus";
ead9360e 5011 break;
9c2149c8 5012 case 2:
7385ac0b 5013 check_insn(env, ctx, ASE_MT);
d9bea114 5014 gen_helper_mtc0_tcbind(arg);
2423f660 5015 rn = "TCBind";
ead9360e 5016 break;
9c2149c8 5017 case 3:
7385ac0b 5018 check_insn(env, ctx, ASE_MT);
d9bea114 5019 gen_helper_mtc0_tcrestart(arg);
2423f660 5020 rn = "TCRestart";
ead9360e 5021 break;
9c2149c8 5022 case 4:
7385ac0b 5023 check_insn(env, ctx, ASE_MT);
d9bea114 5024 gen_helper_mtc0_tchalt(arg);
2423f660 5025 rn = "TCHalt";
ead9360e 5026 break;
9c2149c8 5027 case 5:
7385ac0b 5028 check_insn(env, ctx, ASE_MT);
d9bea114 5029 gen_helper_mtc0_tccontext(arg);
2423f660 5030 rn = "TCContext";
ead9360e 5031 break;
9c2149c8 5032 case 6:
7385ac0b 5033 check_insn(env, ctx, ASE_MT);
d9bea114 5034 gen_helper_mtc0_tcschedule(arg);
2423f660 5035 rn = "TCSchedule";
ead9360e 5036 break;
9c2149c8 5037 case 7:
7385ac0b 5038 check_insn(env, ctx, ASE_MT);
d9bea114 5039 gen_helper_mtc0_tcschefback(arg);
2423f660 5040 rn = "TCScheFBack";
ead9360e 5041 break;
9c2149c8
TS
5042 default:
5043 goto die;
5044 }
5045 break;
5046 case 3:
5047 switch (sel) {
5048 case 0:
d9bea114 5049 gen_helper_mtc0_entrylo1(arg);
2423f660
TS
5050 rn = "EntryLo1";
5051 break;
9c2149c8
TS
5052 default:
5053 goto die;
876d4b07 5054 }
9c2149c8
TS
5055 break;
5056 case 4:
5057 switch (sel) {
5058 case 0:
d9bea114 5059 gen_helper_mtc0_context(arg);
2423f660
TS
5060 rn = "Context";
5061 break;
9c2149c8 5062 case 1:
d9bea114 5063// gen_helper_mtc0_contextconfig(arg); /* SmartMIPS ASE */
2423f660
TS
5064 rn = "ContextConfig";
5065// break;
9c2149c8
TS
5066 default:
5067 goto die;
876d4b07 5068 }
9c2149c8
TS
5069 break;
5070 case 5:
5071 switch (sel) {
5072 case 0:
d9bea114 5073 gen_helper_mtc0_pagemask(arg);
2423f660
TS
5074 rn = "PageMask";
5075 break;
9c2149c8 5076 case 1:
e189e748 5077 check_insn(env, ctx, ISA_MIPS32R2);
d9bea114 5078 gen_helper_mtc0_pagegrain(arg);
2423f660
TS
5079 rn = "PageGrain";
5080 break;
9c2149c8
TS
5081 default:
5082 goto die;
876d4b07 5083 }
9c2149c8
TS
5084 break;
5085 case 6:
5086 switch (sel) {
5087 case 0:
d9bea114 5088 gen_helper_mtc0_wired(arg);
2423f660
TS
5089 rn = "Wired";
5090 break;
9c2149c8 5091 case 1:
e189e748 5092 check_insn(env, ctx, ISA_MIPS32R2);
d9bea114 5093 gen_helper_mtc0_srsconf0(arg);
2423f660 5094 rn = "SRSConf0";
ead9360e 5095 break;
9c2149c8 5096 case 2:
e189e748 5097 check_insn(env, ctx, ISA_MIPS32R2);
d9bea114 5098 gen_helper_mtc0_srsconf1(arg);
2423f660 5099 rn = "SRSConf1";
ead9360e 5100 break;
9c2149c8 5101 case 3:
e189e748 5102 check_insn(env, ctx, ISA_MIPS32R2);
d9bea114 5103 gen_helper_mtc0_srsconf2(arg);
2423f660 5104 rn = "SRSConf2";
ead9360e 5105 break;
9c2149c8 5106 case 4:
e189e748 5107 check_insn(env, ctx, ISA_MIPS32R2);
d9bea114 5108 gen_helper_mtc0_srsconf3(arg);
2423f660 5109 rn = "SRSConf3";
ead9360e 5110 break;
9c2149c8 5111 case 5:
e189e748 5112 check_insn(env, ctx, ISA_MIPS32R2);
d9bea114 5113 gen_helper_mtc0_srsconf4(arg);
2423f660 5114 rn = "SRSConf4";
ead9360e 5115 break;
9c2149c8
TS
5116 default:
5117 goto die;
876d4b07 5118 }
9c2149c8
TS
5119 break;
5120 case 7:
5121 switch (sel) {
5122 case 0:
e189e748 5123 check_insn(env, ctx, ISA_MIPS32R2);
d9bea114 5124 gen_helper_mtc0_hwrena(arg);
2423f660
TS
5125 rn = "HWREna";
5126 break;
9c2149c8
TS
5127 default:
5128 goto die;
876d4b07 5129 }
9c2149c8
TS
5130 break;
5131 case 8:
5132 /* ignored */
f0b3f3ae 5133 rn = "BadVAddr";
9c2149c8
TS
5134 break;
5135 case 9:
5136 switch (sel) {
5137 case 0:
d9bea114 5138 gen_helper_mtc0_count(arg);
2423f660
TS
5139 rn = "Count";
5140 break;
876d4b07 5141 /* 6,7 are implementation dependent */
9c2149c8
TS
5142 default:
5143 goto die;
876d4b07
TS
5144 }
5145 /* Stop translation as we may have switched the execution mode */
5146 ctx->bstate = BS_STOP;
9c2149c8
TS
5147 break;
5148 case 10:
5149 switch (sel) {
5150 case 0:
d9bea114 5151 gen_helper_mtc0_entryhi(arg);
2423f660
TS
5152 rn = "EntryHi";
5153 break;
9c2149c8
TS
5154 default:
5155 goto die;
876d4b07 5156 }
9c2149c8
TS
5157 break;
5158 case 11:
5159 switch (sel) {
5160 case 0:
d9bea114 5161 gen_helper_mtc0_compare(arg);
2423f660
TS
5162 rn = "Compare";
5163 break;
876d4b07 5164 /* 6,7 are implementation dependent */
9c2149c8
TS
5165 default:
5166 goto die;
876d4b07 5167 }
de9a95f0
AJ
5168 /* Stop translation as we may have switched the execution mode */
5169 ctx->bstate = BS_STOP;
9c2149c8
TS
5170 break;
5171 case 12:
5172 switch (sel) {
5173 case 0:
867abc7e 5174 save_cpu_state(ctx, 1);
d9bea114 5175 gen_helper_mtc0_status(arg);
8487327a
TS
5176 /* BS_STOP isn't good enough here, hflags may have changed. */
5177 gen_save_pc(ctx->pc + 4);
5178 ctx->bstate = BS_EXCP;
2423f660
TS
5179 rn = "Status";
5180 break;
9c2149c8 5181 case 1:
e189e748 5182 check_insn(env, ctx, ISA_MIPS32R2);
d9bea114 5183 gen_helper_mtc0_intctl(arg);
8487327a
TS
5184 /* Stop translation as we may have switched the execution mode */
5185 ctx->bstate = BS_STOP;
2423f660
TS
5186 rn = "IntCtl";
5187 break;
9c2149c8 5188 case 2:
e189e748 5189 check_insn(env, ctx, ISA_MIPS32R2);
d9bea114 5190 gen_helper_mtc0_srsctl(arg);
8487327a
TS
5191 /* Stop translation as we may have switched the execution mode */
5192 ctx->bstate = BS_STOP;
2423f660
TS
5193 rn = "SRSCtl";
5194 break;
9c2149c8 5195 case 3:
e189e748 5196 check_insn(env, ctx, ISA_MIPS32R2);
7db13fae 5197 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
8487327a
TS
5198 /* Stop translation as we may have switched the execution mode */
5199 ctx->bstate = BS_STOP;
2423f660
TS
5200 rn = "SRSMap";
5201 break;
5202 default:
9c2149c8 5203 goto die;
876d4b07 5204 }
9c2149c8
TS
5205 break;
5206 case 13:
5207 switch (sel) {
5208 case 0:
867abc7e 5209 save_cpu_state(ctx, 1);
5dc5d9f0
AJ
5210 /* Mark as an IO operation because we may trigger a software
5211 interrupt. */
5212 if (use_icount) {
5213 gen_io_start();
5214 }
d9bea114 5215 gen_helper_mtc0_cause(arg);
5dc5d9f0
AJ
5216 if (use_icount) {
5217 gen_io_end();
5218 }
5219 /* Stop translation as we may have triggered an intetrupt */
5220 ctx->bstate = BS_STOP;
2423f660
TS
5221 rn = "Cause";
5222 break;
9c2149c8
TS
5223 default:
5224 goto die;
876d4b07 5225 }
9c2149c8
TS
5226 break;
5227 case 14:
5228 switch (sel) {
5229 case 0:
7db13fae 5230 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EPC));
2423f660
TS
5231 rn = "EPC";
5232 break;
9c2149c8
TS
5233 default:
5234 goto die;
876d4b07 5235 }
9c2149c8
TS
5236 break;
5237 case 15:
5238 switch (sel) {
5239 case 0:
2423f660
TS
5240 /* ignored */
5241 rn = "PRid";
5242 break;
9c2149c8 5243 case 1:
e189e748 5244 check_insn(env, ctx, ISA_MIPS32R2);
d9bea114 5245 gen_helper_mtc0_ebase(arg);
2423f660
TS
5246 rn = "EBase";
5247 break;
9c2149c8
TS
5248 default:
5249 goto die;
876d4b07 5250 }
9c2149c8
TS
5251 break;
5252 case 16:
5253 switch (sel) {
5254 case 0:
d9bea114 5255 gen_helper_mtc0_config0(arg);
9c2149c8 5256 rn = "Config";
2423f660
TS
5257 /* Stop translation as we may have switched the execution mode */
5258 ctx->bstate = BS_STOP;
9c2149c8
TS
5259 break;
5260 case 1:
1fc7bf6e 5261 /* ignored, read only */
9c2149c8
TS
5262 rn = "Config1";
5263 break;
5264 case 2:
d9bea114 5265 gen_helper_mtc0_config2(arg);
9c2149c8 5266 rn = "Config2";
2423f660
TS
5267 /* Stop translation as we may have switched the execution mode */
5268 ctx->bstate = BS_STOP;
9c2149c8
TS
5269 break;
5270 case 3:
2423f660 5271 /* ignored */
9c2149c8
TS
5272 rn = "Config3";
5273 break;
5274 /* 6,7 are implementation dependent */
5275 default:
5276 rn = "Invalid config selector";
5277 goto die;
5278 }
9c2149c8
TS
5279 break;
5280 case 17:
5281 switch (sel) {
5282 case 0:
2a6e32dd 5283 gen_helper_mtc0_lladdr(arg);
2423f660
TS
5284 rn = "LLAddr";
5285 break;
9c2149c8
TS
5286 default:
5287 goto die;
5288 }
5289 break;
5290 case 18:
5291 switch (sel) {
fd88b6ab 5292 case 0 ... 7:
d9bea114 5293 gen_helper_1i(mtc0_watchlo, arg, sel);
2423f660
TS
5294 rn = "WatchLo";
5295 break;
9c2149c8
TS
5296 default:
5297 goto die;
5298 }
5299 break;
5300 case 19:
5301 switch (sel) {
fd88b6ab 5302 case 0 ... 7:
d9bea114 5303 gen_helper_1i(mtc0_watchhi, arg, sel);
2423f660
TS
5304 rn = "WatchHi";
5305 break;
9c2149c8
TS
5306 default:
5307 goto die;
5308 }
5309 break;
5310 case 20:
5311 switch (sel) {
5312 case 0:
e189e748 5313 check_insn(env, ctx, ISA_MIPS3);
d9bea114 5314 gen_helper_mtc0_xcontext(arg);
2423f660
TS
5315 rn = "XContext";
5316 break;
9c2149c8
TS
5317 default:
5318 goto die;
5319 }
5320 break;
5321 case 21:
5322 /* Officially reserved, but sel 0 is used for R1x000 framemask */
5323 switch (sel) {
5324 case 0:
d9bea114 5325 gen_helper_mtc0_framemask(arg);
2423f660
TS
5326 rn = "Framemask";
5327 break;
9c2149c8
TS
5328 default:
5329 goto die;
5330 }
5331 break;
5332 case 22:
5333 /* ignored */
5334 rn = "Diagnostic"; /* implementation dependent */
876d4b07 5335 break;
9c2149c8
TS
5336 case 23:
5337 switch (sel) {
5338 case 0:
d9bea114 5339 gen_helper_mtc0_debug(arg); /* EJTAG support */
8487327a
TS
5340 /* BS_STOP isn't good enough here, hflags may have changed. */
5341 gen_save_pc(ctx->pc + 4);
5342 ctx->bstate = BS_EXCP;
2423f660
TS
5343 rn = "Debug";
5344 break;
9c2149c8 5345 case 1:
d9bea114 5346// gen_helper_mtc0_tracecontrol(arg); /* PDtrace support */
8487327a
TS
5347 /* Stop translation as we may have switched the execution mode */
5348 ctx->bstate = BS_STOP;
2423f660
TS
5349 rn = "TraceControl";
5350// break;
9c2149c8 5351 case 2:
d9bea114 5352// gen_helper_mtc0_tracecontrol2(arg); /* PDtrace support */
8487327a
TS
5353 /* Stop translation as we may have switched the execution mode */
5354 ctx->bstate = BS_STOP;
2423f660
TS
5355 rn = "TraceControl2";
5356// break;
9c2149c8 5357 case 3:
d9bea114 5358// gen_helper_mtc0_usertracedata(arg); /* PDtrace support */
8487327a
TS
5359 /* Stop translation as we may have switched the execution mode */
5360 ctx->bstate = BS_STOP;
2423f660
TS
5361 rn = "UserTraceData";
5362// break;
9c2149c8 5363 case 4:
d9bea114 5364// gen_helper_mtc0_tracebpc(arg); /* PDtrace support */
8487327a
TS
5365 /* Stop translation as we may have switched the execution mode */
5366 ctx->bstate = BS_STOP;
2423f660
TS
5367 rn = "TraceBPC";
5368// break;
9c2149c8
TS
5369 default:
5370 goto die;
5371 }
9c2149c8
TS
5372 break;
5373 case 24:
5374 switch (sel) {
5375 case 0:
f1aa6320 5376 /* EJTAG support */
7db13fae 5377 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_DEPC));
2423f660
TS
5378 rn = "DEPC";
5379 break;
9c2149c8
TS
5380 default:
5381 goto die;
5382 }
5383 break;
5384 case 25:
5385 switch (sel) {
5386 case 0:
d9bea114 5387 gen_helper_mtc0_performance0(arg);
2423f660
TS
5388 rn = "Performance0";
5389 break;
9c2149c8 5390 case 1:
d9bea114 5391// gen_helper_mtc0_performance1(arg);
2423f660
TS
5392 rn = "Performance1";
5393// break;
9c2149c8 5394 case 2:
d9bea114 5395// gen_helper_mtc0_performance2(arg);
2423f660
TS
5396 rn = "Performance2";
5397// break;
9c2149c8 5398 case 3:
d9bea114 5399// gen_helper_mtc0_performance3(arg);
2423f660
TS
5400 rn = "Performance3";
5401// break;
9c2149c8 5402 case 4:
d9bea114 5403// gen_helper_mtc0_performance4(arg);
2423f660
TS
5404 rn = "Performance4";
5405// break;
9c2149c8 5406 case 5:
d9bea114 5407// gen_helper_mtc0_performance5(arg);
2423f660
TS
5408 rn = "Performance5";
5409// break;
9c2149c8 5410 case 6:
d9bea114 5411// gen_helper_mtc0_performance6(arg);
2423f660
TS
5412 rn = "Performance6";
5413// break;
9c2149c8 5414 case 7:
d9bea114 5415// gen_helper_mtc0_performance7(arg);
2423f660
TS
5416 rn = "Performance7";
5417// break;
9c2149c8
TS
5418 default:
5419 goto die;
5420 }
876d4b07 5421 break;
9c2149c8 5422 case 26:
876d4b07 5423 /* ignored */
9c2149c8 5424 rn = "ECC";
876d4b07 5425 break;
9c2149c8
TS
5426 case 27:
5427 switch (sel) {
5428 case 0 ... 3:
2423f660
TS
5429 /* ignored */
5430 rn = "CacheErr";
5431 break;
9c2149c8
TS
5432 default:
5433 goto die;
5434 }
876d4b07 5435 break;
9c2149c8
TS
5436 case 28:
5437 switch (sel) {
5438 case 0:
5439 case 2:
5440 case 4:
5441 case 6:
d9bea114 5442 gen_helper_mtc0_taglo(arg);
9c2149c8
TS
5443 rn = "TagLo";
5444 break;
5445 case 1:
5446 case 3:
5447 case 5:
5448 case 7:
d9bea114 5449 gen_helper_mtc0_datalo(arg);
9c2149c8
TS
5450 rn = "DataLo";
5451 break;
5452 default:
5453 goto die;
5454 }
5455 break;
5456 case 29:
5457 switch (sel) {
5458 case 0:
5459 case 2:
5460 case 4:
5461 case 6:
d9bea114 5462 gen_helper_mtc0_taghi(arg);
9c2149c8
TS
5463 rn = "TagHi";
5464 break;
5465 case 1:
5466 case 3:
5467 case 5:
5468 case 7:
d9bea114 5469 gen_helper_mtc0_datahi(arg);
9c2149c8
TS
5470 rn = "DataHi";
5471 break;
5472 default:
5473 rn = "invalid sel";
5474 goto die;
5475 }
876d4b07 5476 break;
9c2149c8
TS
5477 case 30:
5478 switch (sel) {
5479 case 0:
7db13fae 5480 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_ErrorEPC));
2423f660
TS
5481 rn = "ErrorEPC";
5482 break;
9c2149c8
TS
5483 default:
5484 goto die;
5485 }
5486 break;
5487 case 31:
5488 switch (sel) {
5489 case 0:
f1aa6320 5490 /* EJTAG support */
7db13fae 5491 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
2423f660
TS
5492 rn = "DESAVE";
5493 break;
9c2149c8
TS
5494 default:
5495 goto die;
5496 }
876d4b07
TS
5497 /* Stop translation as we may have switched the execution mode */
5498 ctx->bstate = BS_STOP;
9c2149c8
TS
5499 break;
5500 default:
876d4b07 5501 goto die;
9c2149c8 5502 }
2abf314d 5503 (void)rn; /* avoid a compiler warning */
d12d51d5 5504 LOG_DISAS("dmtc0 %s (reg %d sel %d)\n", rn, reg, sel);
bf20dc07 5505 /* For simplicity assume that all writes can cause interrupts. */
2e70f6ef
PB
5506 if (use_icount) {
5507 gen_io_end();
5508 ctx->bstate = BS_STOP;
5509 }
9c2149c8
TS
5510 return;
5511
5512die:
d12d51d5 5513 LOG_DISAS("dmtc0 %s (reg %d sel %d)\n", rn, reg, sel);
9c2149c8
TS
5514 generate_exception(ctx, EXCP_RI);
5515}
d26bc211 5516#endif /* TARGET_MIPS64 */
9c2149c8 5517
7db13fae 5518static void gen_mftr(CPUMIPSState *env, DisasContext *ctx, int rt, int rd,
ead9360e
TS
5519 int u, int sel, int h)
5520{
5521 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
a7812ae4 5522 TCGv t0 = tcg_temp_local_new();
ead9360e
TS
5523
5524 if ((env->CP0_VPEConf0 & (1 << CP0VPEC0_MVP)) == 0 &&
b5dc7732
TS
5525 ((env->tcs[other_tc].CP0_TCBind & (0xf << CP0TCBd_CurVPE)) !=
5526 (env->active_tc.CP0_TCBind & (0xf << CP0TCBd_CurVPE))))
1a3fd9c3 5527 tcg_gen_movi_tl(t0, -1);
ead9360e
TS
5528 else if ((env->CP0_VPEControl & (0xff << CP0VPECo_TargTC)) >
5529 (env->mvp->CP0_MVPConf0 & (0xff << CP0MVPC0_PTC)))
1a3fd9c3 5530 tcg_gen_movi_tl(t0, -1);
ead9360e
TS
5531 else if (u == 0) {
5532 switch (rt) {
5a25ce94
EI
5533 case 1:
5534 switch (sel) {
5535 case 1:
5536 gen_helper_mftc0_vpecontrol(t0);
5537 break;
5538 case 2:
5539 gen_helper_mftc0_vpeconf0(t0);
5540 break;
5541 default:
5542 goto die;
5543 break;
5544 }
5545 break;
ead9360e
TS
5546 case 2:
5547 switch (sel) {
5548 case 1:
a7812ae4 5549 gen_helper_mftc0_tcstatus(t0);
ead9360e
TS
5550 break;
5551 case 2:
a7812ae4 5552 gen_helper_mftc0_tcbind(t0);
ead9360e
TS
5553 break;
5554 case 3:
a7812ae4 5555 gen_helper_mftc0_tcrestart(t0);
ead9360e
TS
5556 break;
5557 case 4:
a7812ae4 5558 gen_helper_mftc0_tchalt(t0);
ead9360e
TS
5559 break;
5560 case 5:
a7812ae4 5561 gen_helper_mftc0_tccontext(t0);
ead9360e
TS
5562 break;
5563 case 6:
a7812ae4 5564 gen_helper_mftc0_tcschedule(t0);
ead9360e
TS
5565 break;
5566 case 7:
a7812ae4 5567 gen_helper_mftc0_tcschefback(t0);
ead9360e
TS
5568 break;
5569 default:
1a3fd9c3 5570 gen_mfc0(env, ctx, t0, rt, sel);
ead9360e
TS
5571 break;
5572 }
5573 break;
5574 case 10:
5575 switch (sel) {
5576 case 0:
a7812ae4 5577 gen_helper_mftc0_entryhi(t0);
ead9360e
TS
5578 break;
5579 default:
1a3fd9c3 5580 gen_mfc0(env, ctx, t0, rt, sel);
ead9360e
TS
5581 break;
5582 }
5583 case 12:
5584 switch (sel) {
5585 case 0:
a7812ae4 5586 gen_helper_mftc0_status(t0);
ead9360e
TS
5587 break;
5588 default:
1a3fd9c3 5589 gen_mfc0(env, ctx, t0, rt, sel);
ead9360e
TS
5590 break;
5591 }
5a25ce94
EI
5592 case 13:
5593 switch (sel) {
5594 case 0:
5595 gen_helper_mftc0_cause(t0);
5596 break;
5597 default:
5598 goto die;
5599 break;
5600 }
5601 break;
5602 case 14:
5603 switch (sel) {
5604 case 0:
5605 gen_helper_mftc0_epc(t0);
5606 break;
5607 default:
5608 goto die;
5609 break;
5610 }
5611 break;
5612 case 15:
5613 switch (sel) {
5614 case 1:
5615 gen_helper_mftc0_ebase(t0);
5616 break;
5617 default:
5618 goto die;
5619 break;
5620 }
5621 break;
5622 case 16:
5623 switch (sel) {
5624 case 0 ... 7:
5625 gen_helper_mftc0_configx(t0, tcg_const_tl(sel));
5626 break;
5627 default:
5628 goto die;
5629 break;
5630 }
5631 break;
ead9360e
TS
5632 case 23:
5633 switch (sel) {
5634 case 0:
a7812ae4 5635 gen_helper_mftc0_debug(t0);
ead9360e
TS
5636 break;
5637 default:
1a3fd9c3 5638 gen_mfc0(env, ctx, t0, rt, sel);
ead9360e
TS
5639 break;
5640 }
5641 break;
5642 default:
1a3fd9c3 5643 gen_mfc0(env, ctx, t0, rt, sel);
ead9360e
TS
5644 }
5645 } else switch (sel) {
5646 /* GPR registers. */
5647 case 0:
a7812ae4 5648 gen_helper_1i(mftgpr, t0, rt);
ead9360e
TS
5649 break;
5650 /* Auxiliary CPU registers */
5651 case 1:
5652 switch (rt) {
5653 case 0:
a7812ae4 5654 gen_helper_1i(mftlo, t0, 0);
ead9360e
TS
5655 break;
5656 case 1:
a7812ae4 5657 gen_helper_1i(mfthi, t0, 0);
ead9360e
TS
5658 break;
5659 case 2:
a7812ae4 5660 gen_helper_1i(mftacx, t0, 0);
ead9360e
TS
5661 break;
5662 case 4:
a7812ae4 5663 gen_helper_1i(mftlo, t0, 1);
ead9360e
TS
5664 break;
5665 case 5:
a7812ae4 5666 gen_helper_1i(mfthi, t0, 1);
ead9360e
TS
5667 break;
5668 case 6:
a7812ae4 5669 gen_helper_1i(mftacx, t0, 1);
ead9360e
TS
5670 break;
5671 case 8:
a7812ae4 5672 gen_helper_1i(mftlo, t0, 2);
ead9360e
TS
5673 break;
5674 case 9:
a7812ae4 5675 gen_helper_1i(mfthi, t0, 2);
ead9360e
TS
5676 break;
5677 case 10:
a7812ae4 5678 gen_helper_1i(mftacx, t0, 2);
ead9360e
TS
5679 break;
5680 case 12:
a7812ae4 5681 gen_helper_1i(mftlo, t0, 3);
ead9360e
TS
5682 break;
5683 case 13:
a7812ae4 5684 gen_helper_1i(mfthi, t0, 3);
ead9360e
TS
5685 break;
5686 case 14:
a7812ae4 5687 gen_helper_1i(mftacx, t0, 3);
ead9360e
TS
5688 break;
5689 case 16:
a7812ae4 5690 gen_helper_mftdsp(t0);
ead9360e
TS
5691 break;
5692 default:
5693 goto die;
5694 }
5695 break;
5696 /* Floating point (COP1). */
5697 case 2:
5698 /* XXX: For now we support only a single FPU context. */
5699 if (h == 0) {
a7812ae4 5700 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed
TS
5701
5702 gen_load_fpr32(fp0, rt);
5703 tcg_gen_ext_i32_tl(t0, fp0);
a7812ae4 5704 tcg_temp_free_i32(fp0);
ead9360e 5705 } else {
a7812ae4 5706 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed
TS
5707
5708 gen_load_fpr32h(fp0, rt);
5709 tcg_gen_ext_i32_tl(t0, fp0);
a7812ae4 5710 tcg_temp_free_i32(fp0);
ead9360e
TS
5711 }
5712 break;
5713 case 3:
5714 /* XXX: For now we support only a single FPU context. */
a7812ae4 5715 gen_helper_1i(cfc1, t0, rt);
ead9360e
TS
5716 break;
5717 /* COP2: Not implemented. */
5718 case 4:
5719 case 5:
5720 /* fall through */
5721 default:
5722 goto die;
5723 }
d12d51d5 5724 LOG_DISAS("mftr (reg %d u %d sel %d h %d)\n", rt, u, sel, h);
1a3fd9c3
TS
5725 gen_store_gpr(t0, rd);
5726 tcg_temp_free(t0);
ead9360e
TS
5727 return;
5728
5729die:
1a3fd9c3 5730 tcg_temp_free(t0);
d12d51d5 5731 LOG_DISAS("mftr (reg %d u %d sel %d h %d)\n", rt, u, sel, h);
ead9360e
TS
5732 generate_exception(ctx, EXCP_RI);
5733}
5734
7db13fae 5735static void gen_mttr(CPUMIPSState *env, DisasContext *ctx, int rd, int rt,
ead9360e
TS
5736 int u, int sel, int h)
5737{
5738 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
a7812ae4 5739 TCGv t0 = tcg_temp_local_new();
ead9360e 5740
1a3fd9c3 5741 gen_load_gpr(t0, rt);
ead9360e 5742 if ((env->CP0_VPEConf0 & (1 << CP0VPEC0_MVP)) == 0 &&
b5dc7732
TS
5743 ((env->tcs[other_tc].CP0_TCBind & (0xf << CP0TCBd_CurVPE)) !=
5744 (env->active_tc.CP0_TCBind & (0xf << CP0TCBd_CurVPE))))
ead9360e
TS
5745 /* NOP */ ;
5746 else if ((env->CP0_VPEControl & (0xff << CP0VPECo_TargTC)) >
5747 (env->mvp->CP0_MVPConf0 & (0xff << CP0MVPC0_PTC)))
5748 /* NOP */ ;
5749 else if (u == 0) {
5750 switch (rd) {
5a25ce94
EI
5751 case 1:
5752 switch (sel) {
5753 case 1:
5754 gen_helper_mttc0_vpecontrol(t0);
5755 break;
5756 case 2:
5757 gen_helper_mttc0_vpeconf0(t0);
5758 break;
5759 default:
5760 goto die;
5761 break;
5762 }
5763 break;
ead9360e
TS
5764 case 2:
5765 switch (sel) {
5766 case 1:
a7812ae4 5767 gen_helper_mttc0_tcstatus(t0);
ead9360e
TS
5768 break;
5769 case 2:
a7812ae4 5770 gen_helper_mttc0_tcbind(t0);
ead9360e
TS
5771 break;
5772 case 3:
a7812ae4 5773 gen_helper_mttc0_tcrestart(t0);
ead9360e
TS
5774 break;
5775 case 4:
a7812ae4 5776 gen_helper_mttc0_tchalt(t0);
ead9360e
TS
5777 break;
5778 case 5:
a7812ae4 5779 gen_helper_mttc0_tccontext(t0);
ead9360e
TS
5780 break;
5781 case 6:
a7812ae4 5782 gen_helper_mttc0_tcschedule(t0);
ead9360e
TS
5783 break;
5784 case 7:
a7812ae4 5785 gen_helper_mttc0_tcschefback(t0);
ead9360e
TS
5786 break;
5787 default:
1a3fd9c3 5788 gen_mtc0(env, ctx, t0, rd, sel);
ead9360e
TS
5789 break;
5790 }
5791 break;
5792 case 10:
5793 switch (sel) {
5794 case 0:
a7812ae4 5795 gen_helper_mttc0_entryhi(t0);
ead9360e
TS
5796 break;
5797 default:
1a3fd9c3 5798 gen_mtc0(env, ctx, t0, rd, sel);
ead9360e
TS
5799 break;
5800 }
5801 case 12:
5802 switch (sel) {
5803 case 0:
a7812ae4 5804 gen_helper_mttc0_status(t0);
ead9360e
TS
5805 break;
5806 default:
1a3fd9c3 5807 gen_mtc0(env, ctx, t0, rd, sel);
ead9360e
TS
5808 break;
5809 }
5a25ce94
EI
5810 case 13:
5811 switch (sel) {
5812 case 0:
5813 gen_helper_mttc0_cause(t0);
5814 break;
5815 default:
5816 goto die;
5817 break;
5818 }
5819 break;
5820 case 15:
5821 switch (sel) {
5822 case 1:
5823 gen_helper_mttc0_ebase(t0);
5824 break;
5825 default:
5826 goto die;
5827 break;
5828 }
5829 break;
ead9360e
TS
5830 case 23:
5831 switch (sel) {
5832 case 0:
a7812ae4 5833 gen_helper_mttc0_debug(t0);
ead9360e
TS
5834 break;
5835 default:
1a3fd9c3 5836 gen_mtc0(env, ctx, t0, rd, sel);
ead9360e
TS
5837 break;
5838 }
5839 break;
5840 default:
1a3fd9c3 5841 gen_mtc0(env, ctx, t0, rd, sel);
ead9360e
TS
5842 }
5843 } else switch (sel) {
5844 /* GPR registers. */
5845 case 0:
a7812ae4 5846 gen_helper_1i(mttgpr, t0, rd);
ead9360e
TS
5847 break;
5848 /* Auxiliary CPU registers */
5849 case 1:
5850 switch (rd) {
5851 case 0:
a7812ae4 5852 gen_helper_1i(mttlo, t0, 0);
ead9360e
TS
5853 break;
5854 case 1:
a7812ae4 5855 gen_helper_1i(mtthi, t0, 0);
ead9360e
TS
5856 break;
5857 case 2:
a7812ae4 5858 gen_helper_1i(mttacx, t0, 0);
ead9360e
TS
5859 break;
5860 case 4:
a7812ae4 5861 gen_helper_1i(mttlo, t0, 1);
ead9360e
TS
5862 break;
5863 case 5:
a7812ae4 5864 gen_helper_1i(mtthi, t0, 1);
ead9360e
TS
5865 break;
5866 case 6:
a7812ae4 5867 gen_helper_1i(mttacx, t0, 1);
ead9360e
TS
5868 break;
5869 case 8:
a7812ae4 5870 gen_helper_1i(mttlo, t0, 2);
ead9360e
TS
5871 break;
5872 case 9:
a7812ae4 5873 gen_helper_1i(mtthi, t0, 2);
ead9360e
TS
5874 break;
5875 case 10:
a7812ae4 5876 gen_helper_1i(mttacx, t0, 2);
ead9360e
TS
5877 break;
5878 case 12:
a7812ae4 5879 gen_helper_1i(mttlo, t0, 3);
ead9360e
TS
5880 break;
5881 case 13:
a7812ae4 5882 gen_helper_1i(mtthi, t0, 3);
ead9360e
TS
5883 break;
5884 case 14:
a7812ae4 5885 gen_helper_1i(mttacx, t0, 3);
ead9360e
TS
5886 break;
5887 case 16:
a7812ae4 5888 gen_helper_mttdsp(t0);
ead9360e
TS
5889 break;
5890 default:
5891 goto die;
5892 }
5893 break;
5894 /* Floating point (COP1). */
5895 case 2:
5896 /* XXX: For now we support only a single FPU context. */
5897 if (h == 0) {
a7812ae4 5898 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed
TS
5899
5900 tcg_gen_trunc_tl_i32(fp0, t0);
5901 gen_store_fpr32(fp0, rd);
a7812ae4 5902 tcg_temp_free_i32(fp0);
ead9360e 5903 } else {
a7812ae4 5904 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed
TS
5905
5906 tcg_gen_trunc_tl_i32(fp0, t0);
5907 gen_store_fpr32h(fp0, rd);
a7812ae4 5908 tcg_temp_free_i32(fp0);
ead9360e
TS
5909 }
5910 break;
5911 case 3:
5912 /* XXX: For now we support only a single FPU context. */
a7812ae4 5913 gen_helper_1i(ctc1, t0, rd);
ead9360e
TS
5914 break;
5915 /* COP2: Not implemented. */
5916 case 4:
5917 case 5:
5918 /* fall through */
5919 default:
5920 goto die;
5921 }
d12d51d5 5922 LOG_DISAS("mttr (reg %d u %d sel %d h %d)\n", rd, u, sel, h);
1a3fd9c3 5923 tcg_temp_free(t0);
ead9360e
TS
5924 return;
5925
5926die:
1a3fd9c3 5927 tcg_temp_free(t0);
d12d51d5 5928 LOG_DISAS("mttr (reg %d u %d sel %d h %d)\n", rd, u, sel, h);
ead9360e
TS
5929 generate_exception(ctx, EXCP_RI);
5930}
5931
7db13fae 5932static void gen_cp0 (CPUMIPSState *env, DisasContext *ctx, uint32_t opc, int rt, int rd)
6af0bf9c 5933{
287c4b84 5934 const char *opn = "ldst";
6af0bf9c 5935
6af0bf9c
FB
5936 switch (opc) {
5937 case OPC_MFC0:
5938 if (rt == 0) {
ead9360e 5939 /* Treat as NOP. */
6af0bf9c
FB
5940 return;
5941 }
1fc7bf6e 5942 gen_mfc0(env, ctx, cpu_gpr[rt], rd, ctx->opcode & 0x7);
6af0bf9c
FB
5943 opn = "mfc0";
5944 break;
5945 case OPC_MTC0:
1a3fd9c3 5946 {
1fc7bf6e 5947 TCGv t0 = tcg_temp_new();
1a3fd9c3
TS
5948
5949 gen_load_gpr(t0, rt);
1a3fd9c3
TS
5950 gen_mtc0(env, ctx, t0, rd, ctx->opcode & 0x7);
5951 tcg_temp_free(t0);
5952 }
6af0bf9c
FB
5953 opn = "mtc0";
5954 break;
d26bc211 5955#if defined(TARGET_MIPS64)
9c2149c8 5956 case OPC_DMFC0:
e189e748 5957 check_insn(env, ctx, ISA_MIPS3);
9c2149c8 5958 if (rt == 0) {
ead9360e 5959 /* Treat as NOP. */
9c2149c8
TS
5960 return;
5961 }
1fc7bf6e 5962 gen_dmfc0(env, ctx, cpu_gpr[rt], rd, ctx->opcode & 0x7);
9c2149c8
TS
5963 opn = "dmfc0";
5964 break;
5965 case OPC_DMTC0:
e189e748 5966 check_insn(env, ctx, ISA_MIPS3);
1a3fd9c3 5967 {
1fc7bf6e 5968 TCGv t0 = tcg_temp_new();
1a3fd9c3
TS
5969
5970 gen_load_gpr(t0, rt);
1a3fd9c3
TS
5971 gen_dmtc0(env, ctx, t0, rd, ctx->opcode & 0x7);
5972 tcg_temp_free(t0);
5973 }
9c2149c8
TS
5974 opn = "dmtc0";
5975 break;
534ce69f 5976#endif
ead9360e 5977 case OPC_MFTR:
7385ac0b 5978 check_insn(env, ctx, ASE_MT);
ead9360e
TS
5979 if (rd == 0) {
5980 /* Treat as NOP. */
5981 return;
5982 }
6c5c1e20 5983 gen_mftr(env, ctx, rt, rd, (ctx->opcode >> 5) & 1,
ead9360e 5984 ctx->opcode & 0x7, (ctx->opcode >> 4) & 1);
ead9360e
TS
5985 opn = "mftr";
5986 break;
5987 case OPC_MTTR:
7385ac0b 5988 check_insn(env, ctx, ASE_MT);
6c5c1e20 5989 gen_mttr(env, ctx, rd, rt, (ctx->opcode >> 5) & 1,
ead9360e
TS
5990 ctx->opcode & 0x7, (ctx->opcode >> 4) & 1);
5991 opn = "mttr";
5992 break;
6af0bf9c 5993 case OPC_TLBWI:
6af0bf9c 5994 opn = "tlbwi";
c01fccd2 5995 if (!env->tlb->helper_tlbwi)
29929e34 5996 goto die;
a7812ae4 5997 gen_helper_tlbwi();
6af0bf9c
FB
5998 break;
5999 case OPC_TLBWR:
6af0bf9c 6000 opn = "tlbwr";
c01fccd2 6001 if (!env->tlb->helper_tlbwr)
29929e34 6002 goto die;
a7812ae4 6003 gen_helper_tlbwr();
6af0bf9c
FB
6004 break;
6005 case OPC_TLBP:
6af0bf9c 6006 opn = "tlbp";
c01fccd2 6007 if (!env->tlb->helper_tlbp)
29929e34 6008 goto die;
a7812ae4 6009 gen_helper_tlbp();
6af0bf9c
FB
6010 break;
6011 case OPC_TLBR:
6af0bf9c 6012 opn = "tlbr";
c01fccd2 6013 if (!env->tlb->helper_tlbr)
29929e34 6014 goto die;
a7812ae4 6015 gen_helper_tlbr();
6af0bf9c 6016 break;
6af0bf9c
FB
6017 case OPC_ERET:
6018 opn = "eret";
e189e748 6019 check_insn(env, ctx, ISA_MIPS2);
a7812ae4 6020 gen_helper_eret();
6af0bf9c
FB
6021 ctx->bstate = BS_EXCP;
6022 break;
6023 case OPC_DERET:
6024 opn = "deret";
e189e748 6025 check_insn(env, ctx, ISA_MIPS32);
6af0bf9c 6026 if (!(ctx->hflags & MIPS_HFLAG_DM)) {
923617a3 6027 MIPS_INVAL(opn);
6af0bf9c
FB
6028 generate_exception(ctx, EXCP_RI);
6029 } else {
a7812ae4 6030 gen_helper_deret();
6af0bf9c
FB
6031 ctx->bstate = BS_EXCP;
6032 }
6033 break;
4ad40f36
FB
6034 case OPC_WAIT:
6035 opn = "wait";
e189e748 6036 check_insn(env, ctx, ISA_MIPS3 | ISA_MIPS32);
4ad40f36
FB
6037 /* If we get an exception, we want to restart at next instruction */
6038 ctx->pc += 4;
6039 save_cpu_state(ctx, 1);
6040 ctx->pc -= 4;
a7812ae4 6041 gen_helper_wait();
4ad40f36
FB
6042 ctx->bstate = BS_EXCP;
6043 break;
6af0bf9c 6044 default:
29929e34 6045 die:
923617a3 6046 MIPS_INVAL(opn);
6af0bf9c
FB
6047 generate_exception(ctx, EXCP_RI);
6048 return;
6049 }
2abf314d 6050 (void)opn; /* avoid a compiler warning */
6af0bf9c
FB
6051 MIPS_DEBUG("%s %s %d", opn, regnames[rt], rd);
6052}
f1aa6320 6053#endif /* !CONFIG_USER_ONLY */
6af0bf9c 6054
6ea83fed 6055/* CP1 Branches (before delay slot) */
7db13fae 6056static void gen_compute_branch1 (CPUMIPSState *env, DisasContext *ctx, uint32_t op,
5a5012ec 6057 int32_t cc, int32_t offset)
6ea83fed
FB
6058{
6059 target_ulong btarget;
923617a3 6060 const char *opn = "cp1 cond branch";
a7812ae4 6061 TCGv_i32 t0 = tcg_temp_new_i32();
6ea83fed 6062
e189e748
TS
6063 if (cc != 0)
6064 check_insn(env, ctx, ISA_MIPS4 | ISA_MIPS32);
6065
6ea83fed
FB
6066 btarget = ctx->pc + 4 + offset;
6067
7a387fff
TS
6068 switch (op) {
6069 case OPC_BC1F:
d94536f4
AJ
6070 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
6071 tcg_gen_not_i32(t0, t0);
6072 tcg_gen_andi_i32(t0, t0, 1);
6073 tcg_gen_extu_i32_tl(bcond, t0);
923617a3 6074 opn = "bc1f";
6ea83fed 6075 goto not_likely;
7a387fff 6076 case OPC_BC1FL:
d94536f4
AJ
6077 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
6078 tcg_gen_not_i32(t0, t0);
6079 tcg_gen_andi_i32(t0, t0, 1);
6080 tcg_gen_extu_i32_tl(bcond, t0);
923617a3 6081 opn = "bc1fl";
6ea83fed 6082 goto likely;
7a387fff 6083 case OPC_BC1T:
d94536f4
AJ
6084 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
6085 tcg_gen_andi_i32(t0, t0, 1);
6086 tcg_gen_extu_i32_tl(bcond, t0);
923617a3 6087 opn = "bc1t";
5a5012ec 6088 goto not_likely;
7a387fff 6089 case OPC_BC1TL:
d94536f4
AJ
6090 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
6091 tcg_gen_andi_i32(t0, t0, 1);
6092 tcg_gen_extu_i32_tl(bcond, t0);
923617a3 6093 opn = "bc1tl";
6ea83fed
FB
6094 likely:
6095 ctx->hflags |= MIPS_HFLAG_BL;
6096 break;
5a5012ec 6097 case OPC_BC1FANY2:
a16336e4 6098 {
d94536f4
AJ
6099 TCGv_i32 t1 = tcg_temp_new_i32();
6100 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
6101 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+1));
d7f66b52 6102 tcg_gen_nand_i32(t0, t0, t1);
d94536f4 6103 tcg_temp_free_i32(t1);
d94536f4
AJ
6104 tcg_gen_andi_i32(t0, t0, 1);
6105 tcg_gen_extu_i32_tl(bcond, t0);
a16336e4 6106 }
fd4a04eb 6107 opn = "bc1any2f";
5a5012ec
TS
6108 goto not_likely;
6109 case OPC_BC1TANY2:
a16336e4 6110 {
d94536f4
AJ
6111 TCGv_i32 t1 = tcg_temp_new_i32();
6112 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
6113 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+1));
6114 tcg_gen_or_i32(t0, t0, t1);
6115 tcg_temp_free_i32(t1);
6116 tcg_gen_andi_i32(t0, t0, 1);
6117 tcg_gen_extu_i32_tl(bcond, t0);
a16336e4 6118 }
fd4a04eb 6119 opn = "bc1any2t";
5a5012ec
TS
6120 goto not_likely;
6121 case OPC_BC1FANY4:
a16336e4 6122 {
d94536f4
AJ
6123 TCGv_i32 t1 = tcg_temp_new_i32();
6124 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
6125 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+1));
d7f66b52 6126 tcg_gen_and_i32(t0, t0, t1);
d94536f4 6127 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+2));
d7f66b52 6128 tcg_gen_and_i32(t0, t0, t1);
d94536f4 6129 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+3));
d7f66b52 6130 tcg_gen_nand_i32(t0, t0, t1);
d94536f4 6131 tcg_temp_free_i32(t1);
d94536f4
AJ
6132 tcg_gen_andi_i32(t0, t0, 1);
6133 tcg_gen_extu_i32_tl(bcond, t0);
a16336e4 6134 }
fd4a04eb 6135 opn = "bc1any4f";
5a5012ec
TS
6136 goto not_likely;
6137 case OPC_BC1TANY4:
a16336e4 6138 {
d94536f4
AJ
6139 TCGv_i32 t1 = tcg_temp_new_i32();
6140 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
6141 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+1));
6142 tcg_gen_or_i32(t0, t0, t1);
6143 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+2));
6144 tcg_gen_or_i32(t0, t0, t1);
6145 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+3));
6146 tcg_gen_or_i32(t0, t0, t1);
6147 tcg_temp_free_i32(t1);
6148 tcg_gen_andi_i32(t0, t0, 1);
6149 tcg_gen_extu_i32_tl(bcond, t0);
a16336e4 6150 }
fd4a04eb 6151 opn = "bc1any4t";
5a5012ec
TS
6152 not_likely:
6153 ctx->hflags |= MIPS_HFLAG_BC;
5a5012ec
TS
6154 break;
6155 default:
923617a3 6156 MIPS_INVAL(opn);
e397ee33 6157 generate_exception (ctx, EXCP_RI);
6c5c1e20 6158 goto out;
6ea83fed 6159 }
2abf314d 6160 (void)opn; /* avoid a compiler warning */
923617a3 6161 MIPS_DEBUG("%s: cond %02x target " TARGET_FMT_lx, opn,
6ea83fed
FB
6162 ctx->hflags, btarget);
6163 ctx->btarget = btarget;
6c5c1e20
TS
6164
6165 out:
a7812ae4 6166 tcg_temp_free_i32(t0);
6ea83fed
FB
6167}
6168
6af0bf9c 6169/* Coprocessor 1 (FPU) */
5a5012ec 6170
5a5012ec
TS
6171#define FOP(func, fmt) (((fmt) << 21) | (func))
6172
bf4120ad
NF
6173enum fopcode {
6174 OPC_ADD_S = FOP(0, FMT_S),
6175 OPC_SUB_S = FOP(1, FMT_S),
6176 OPC_MUL_S = FOP(2, FMT_S),
6177 OPC_DIV_S = FOP(3, FMT_S),
6178 OPC_SQRT_S = FOP(4, FMT_S),
6179 OPC_ABS_S = FOP(5, FMT_S),
6180 OPC_MOV_S = FOP(6, FMT_S),
6181 OPC_NEG_S = FOP(7, FMT_S),
6182 OPC_ROUND_L_S = FOP(8, FMT_S),
6183 OPC_TRUNC_L_S = FOP(9, FMT_S),
6184 OPC_CEIL_L_S = FOP(10, FMT_S),
6185 OPC_FLOOR_L_S = FOP(11, FMT_S),
6186 OPC_ROUND_W_S = FOP(12, FMT_S),
6187 OPC_TRUNC_W_S = FOP(13, FMT_S),
6188 OPC_CEIL_W_S = FOP(14, FMT_S),
6189 OPC_FLOOR_W_S = FOP(15, FMT_S),
6190 OPC_MOVCF_S = FOP(17, FMT_S),
6191 OPC_MOVZ_S = FOP(18, FMT_S),
6192 OPC_MOVN_S = FOP(19, FMT_S),
6193 OPC_RECIP_S = FOP(21, FMT_S),
6194 OPC_RSQRT_S = FOP(22, FMT_S),
6195 OPC_RECIP2_S = FOP(28, FMT_S),
6196 OPC_RECIP1_S = FOP(29, FMT_S),
6197 OPC_RSQRT1_S = FOP(30, FMT_S),
6198 OPC_RSQRT2_S = FOP(31, FMT_S),
6199 OPC_CVT_D_S = FOP(33, FMT_S),
6200 OPC_CVT_W_S = FOP(36, FMT_S),
6201 OPC_CVT_L_S = FOP(37, FMT_S),
6202 OPC_CVT_PS_S = FOP(38, FMT_S),
6203 OPC_CMP_F_S = FOP (48, FMT_S),
6204 OPC_CMP_UN_S = FOP (49, FMT_S),
6205 OPC_CMP_EQ_S = FOP (50, FMT_S),
6206 OPC_CMP_UEQ_S = FOP (51, FMT_S),
6207 OPC_CMP_OLT_S = FOP (52, FMT_S),
6208 OPC_CMP_ULT_S = FOP (53, FMT_S),
6209 OPC_CMP_OLE_S = FOP (54, FMT_S),
6210 OPC_CMP_ULE_S = FOP (55, FMT_S),
6211 OPC_CMP_SF_S = FOP (56, FMT_S),
6212 OPC_CMP_NGLE_S = FOP (57, FMT_S),
6213 OPC_CMP_SEQ_S = FOP (58, FMT_S),
6214 OPC_CMP_NGL_S = FOP (59, FMT_S),
6215 OPC_CMP_LT_S = FOP (60, FMT_S),
6216 OPC_CMP_NGE_S = FOP (61, FMT_S),
6217 OPC_CMP_LE_S = FOP (62, FMT_S),
6218 OPC_CMP_NGT_S = FOP (63, FMT_S),
6219
6220 OPC_ADD_D = FOP(0, FMT_D),
6221 OPC_SUB_D = FOP(1, FMT_D),
6222 OPC_MUL_D = FOP(2, FMT_D),
6223 OPC_DIV_D = FOP(3, FMT_D),
6224 OPC_SQRT_D = FOP(4, FMT_D),
6225 OPC_ABS_D = FOP(5, FMT_D),
6226 OPC_MOV_D = FOP(6, FMT_D),
6227 OPC_NEG_D = FOP(7, FMT_D),
6228 OPC_ROUND_L_D = FOP(8, FMT_D),
6229 OPC_TRUNC_L_D = FOP(9, FMT_D),
6230 OPC_CEIL_L_D = FOP(10, FMT_D),
6231 OPC_FLOOR_L_D = FOP(11, FMT_D),
6232 OPC_ROUND_W_D = FOP(12, FMT_D),
6233 OPC_TRUNC_W_D = FOP(13, FMT_D),
6234 OPC_CEIL_W_D = FOP(14, FMT_D),
6235 OPC_FLOOR_W_D = FOP(15, FMT_D),
6236 OPC_MOVCF_D = FOP(17, FMT_D),
6237 OPC_MOVZ_D = FOP(18, FMT_D),
6238 OPC_MOVN_D = FOP(19, FMT_D),
6239 OPC_RECIP_D = FOP(21, FMT_D),
6240 OPC_RSQRT_D = FOP(22, FMT_D),
6241 OPC_RECIP2_D = FOP(28, FMT_D),
6242 OPC_RECIP1_D = FOP(29, FMT_D),
6243 OPC_RSQRT1_D = FOP(30, FMT_D),
6244 OPC_RSQRT2_D = FOP(31, FMT_D),
6245 OPC_CVT_S_D = FOP(32, FMT_D),
6246 OPC_CVT_W_D = FOP(36, FMT_D),
6247 OPC_CVT_L_D = FOP(37, FMT_D),
6248 OPC_CMP_F_D = FOP (48, FMT_D),
6249 OPC_CMP_UN_D = FOP (49, FMT_D),
6250 OPC_CMP_EQ_D = FOP (50, FMT_D),
6251 OPC_CMP_UEQ_D = FOP (51, FMT_D),
6252 OPC_CMP_OLT_D = FOP (52, FMT_D),
6253 OPC_CMP_ULT_D = FOP (53, FMT_D),
6254 OPC_CMP_OLE_D = FOP (54, FMT_D),
6255 OPC_CMP_ULE_D = FOP (55, FMT_D),
6256 OPC_CMP_SF_D = FOP (56, FMT_D),
6257 OPC_CMP_NGLE_D = FOP (57, FMT_D),
6258 OPC_CMP_SEQ_D = FOP (58, FMT_D),
6259 OPC_CMP_NGL_D = FOP (59, FMT_D),
6260 OPC_CMP_LT_D = FOP (60, FMT_D),
6261 OPC_CMP_NGE_D = FOP (61, FMT_D),
6262 OPC_CMP_LE_D = FOP (62, FMT_D),
6263 OPC_CMP_NGT_D = FOP (63, FMT_D),
6264
6265 OPC_CVT_S_W = FOP(32, FMT_W),
6266 OPC_CVT_D_W = FOP(33, FMT_W),
6267 OPC_CVT_S_L = FOP(32, FMT_L),
6268 OPC_CVT_D_L = FOP(33, FMT_L),
6269 OPC_CVT_PS_PW = FOP(38, FMT_W),
6270
6271 OPC_ADD_PS = FOP(0, FMT_PS),
6272 OPC_SUB_PS = FOP(1, FMT_PS),
6273 OPC_MUL_PS = FOP(2, FMT_PS),
6274 OPC_DIV_PS = FOP(3, FMT_PS),
6275 OPC_ABS_PS = FOP(5, FMT_PS),
6276 OPC_MOV_PS = FOP(6, FMT_PS),
6277 OPC_NEG_PS = FOP(7, FMT_PS),
6278 OPC_MOVCF_PS = FOP(17, FMT_PS),
6279 OPC_MOVZ_PS = FOP(18, FMT_PS),
6280 OPC_MOVN_PS = FOP(19, FMT_PS),
6281 OPC_ADDR_PS = FOP(24, FMT_PS),
6282 OPC_MULR_PS = FOP(26, FMT_PS),
6283 OPC_RECIP2_PS = FOP(28, FMT_PS),
6284 OPC_RECIP1_PS = FOP(29, FMT_PS),
6285 OPC_RSQRT1_PS = FOP(30, FMT_PS),
6286 OPC_RSQRT2_PS = FOP(31, FMT_PS),
6287
6288 OPC_CVT_S_PU = FOP(32, FMT_PS),
6289 OPC_CVT_PW_PS = FOP(36, FMT_PS),
6290 OPC_CVT_S_PL = FOP(40, FMT_PS),
6291 OPC_PLL_PS = FOP(44, FMT_PS),
6292 OPC_PLU_PS = FOP(45, FMT_PS),
6293 OPC_PUL_PS = FOP(46, FMT_PS),
6294 OPC_PUU_PS = FOP(47, FMT_PS),
6295 OPC_CMP_F_PS = FOP (48, FMT_PS),
6296 OPC_CMP_UN_PS = FOP (49, FMT_PS),
6297 OPC_CMP_EQ_PS = FOP (50, FMT_PS),
6298 OPC_CMP_UEQ_PS = FOP (51, FMT_PS),
6299 OPC_CMP_OLT_PS = FOP (52, FMT_PS),
6300 OPC_CMP_ULT_PS = FOP (53, FMT_PS),
6301 OPC_CMP_OLE_PS = FOP (54, FMT_PS),
6302 OPC_CMP_ULE_PS = FOP (55, FMT_PS),
6303 OPC_CMP_SF_PS = FOP (56, FMT_PS),
6304 OPC_CMP_NGLE_PS = FOP (57, FMT_PS),
6305 OPC_CMP_SEQ_PS = FOP (58, FMT_PS),
6306 OPC_CMP_NGL_PS = FOP (59, FMT_PS),
6307 OPC_CMP_LT_PS = FOP (60, FMT_PS),
6308 OPC_CMP_NGE_PS = FOP (61, FMT_PS),
6309 OPC_CMP_LE_PS = FOP (62, FMT_PS),
6310 OPC_CMP_NGT_PS = FOP (63, FMT_PS),
6311};
6312
7a387fff 6313static void gen_cp1 (DisasContext *ctx, uint32_t opc, int rt, int fs)
6ea83fed 6314{
923617a3 6315 const char *opn = "cp1 move";
72c3a3ee 6316 TCGv t0 = tcg_temp_new();
6ea83fed
FB
6317
6318 switch (opc) {
6319 case OPC_MFC1:
b6d96bed 6320 {
a7812ae4 6321 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed
TS
6322
6323 gen_load_fpr32(fp0, fs);
6324 tcg_gen_ext_i32_tl(t0, fp0);
a7812ae4 6325 tcg_temp_free_i32(fp0);
6958549d 6326 }
6c5c1e20 6327 gen_store_gpr(t0, rt);
6ea83fed
FB
6328 opn = "mfc1";
6329 break;
6330 case OPC_MTC1:
6c5c1e20 6331 gen_load_gpr(t0, rt);
b6d96bed 6332 {
a7812ae4 6333 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed
TS
6334
6335 tcg_gen_trunc_tl_i32(fp0, t0);
6336 gen_store_fpr32(fp0, fs);
a7812ae4 6337 tcg_temp_free_i32(fp0);
6958549d 6338 }
6ea83fed
FB
6339 opn = "mtc1";
6340 break;
6341 case OPC_CFC1:
a7812ae4 6342 gen_helper_1i(cfc1, t0, fs);
6c5c1e20 6343 gen_store_gpr(t0, rt);
6ea83fed
FB
6344 opn = "cfc1";
6345 break;
6346 case OPC_CTC1:
6c5c1e20 6347 gen_load_gpr(t0, rt);
a7812ae4 6348 gen_helper_1i(ctc1, t0, fs);
6ea83fed
FB
6349 opn = "ctc1";
6350 break;
72c3a3ee 6351#if defined(TARGET_MIPS64)
9c2149c8 6352 case OPC_DMFC1:
72c3a3ee 6353 gen_load_fpr64(ctx, t0, fs);
6c5c1e20 6354 gen_store_gpr(t0, rt);
5a5012ec
TS
6355 opn = "dmfc1";
6356 break;
9c2149c8 6357 case OPC_DMTC1:
6c5c1e20 6358 gen_load_gpr(t0, rt);
72c3a3ee 6359 gen_store_fpr64(ctx, t0, fs);
5a5012ec
TS
6360 opn = "dmtc1";
6361 break;
72c3a3ee 6362#endif
5a5012ec 6363 case OPC_MFHC1:
b6d96bed 6364 {
a7812ae4 6365 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed
TS
6366
6367 gen_load_fpr32h(fp0, fs);
6368 tcg_gen_ext_i32_tl(t0, fp0);
a7812ae4 6369 tcg_temp_free_i32(fp0);
6958549d 6370 }
6c5c1e20 6371 gen_store_gpr(t0, rt);
5a5012ec
TS
6372 opn = "mfhc1";
6373 break;
6374 case OPC_MTHC1:
6c5c1e20 6375 gen_load_gpr(t0, rt);
b6d96bed 6376 {
a7812ae4 6377 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed
TS
6378
6379 tcg_gen_trunc_tl_i32(fp0, t0);
6380 gen_store_fpr32h(fp0, fs);
a7812ae4 6381 tcg_temp_free_i32(fp0);
6958549d 6382 }
5a5012ec
TS
6383 opn = "mthc1";
6384 break;
6ea83fed 6385 default:
923617a3 6386 MIPS_INVAL(opn);
e397ee33 6387 generate_exception (ctx, EXCP_RI);
6c5c1e20 6388 goto out;
6ea83fed 6389 }
2abf314d 6390 (void)opn; /* avoid a compiler warning */
6ea83fed 6391 MIPS_DEBUG("%s %s %s", opn, regnames[rt], fregnames[fs]);
6c5c1e20
TS
6392
6393 out:
6394 tcg_temp_free(t0);
6ea83fed
FB
6395}
6396
5a5012ec
TS
6397static void gen_movci (DisasContext *ctx, int rd, int rs, int cc, int tf)
6398{
af58f9ca 6399 int l1;
e214b9bb 6400 TCGCond cond;
af58f9ca
AJ
6401 TCGv_i32 t0;
6402
6403 if (rd == 0) {
6404 /* Treat as NOP. */
6405 return;
6406 }
6ea83fed 6407
e214b9bb 6408 if (tf)
e214b9bb 6409 cond = TCG_COND_EQ;
27848470
TS
6410 else
6411 cond = TCG_COND_NE;
6412
af58f9ca
AJ
6413 l1 = gen_new_label();
6414 t0 = tcg_temp_new_i32();
fa31af0e 6415 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
af58f9ca 6416 tcg_gen_brcondi_i32(cond, t0, 0, l1);
a4e8338d 6417 tcg_temp_free_i32(t0);
af58f9ca
AJ
6418 if (rs == 0) {
6419 tcg_gen_movi_tl(cpu_gpr[rd], 0);
6420 } else {
6421 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
6422 }
e214b9bb 6423 gen_set_label(l1);
5a5012ec
TS
6424}
6425
b6d96bed 6426static inline void gen_movcf_s (int fs, int fd, int cc, int tf)
a16336e4 6427{
a16336e4 6428 int cond;
cbc37b28 6429 TCGv_i32 t0 = tcg_temp_new_i32();
a16336e4
TS
6430 int l1 = gen_new_label();
6431
a16336e4
TS
6432 if (tf)
6433 cond = TCG_COND_EQ;
6434 else
6435 cond = TCG_COND_NE;
6436
fa31af0e 6437 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
cbc37b28
AJ
6438 tcg_gen_brcondi_i32(cond, t0, 0, l1);
6439 gen_load_fpr32(t0, fs);
6440 gen_store_fpr32(t0, fd);
a16336e4 6441 gen_set_label(l1);
cbc37b28 6442 tcg_temp_free_i32(t0);
5a5012ec 6443}
a16336e4 6444
b6d96bed 6445static inline void gen_movcf_d (DisasContext *ctx, int fs, int fd, int cc, int tf)
a16336e4 6446{
a16336e4 6447 int cond;
cbc37b28
AJ
6448 TCGv_i32 t0 = tcg_temp_new_i32();
6449 TCGv_i64 fp0;
a16336e4
TS
6450 int l1 = gen_new_label();
6451
a16336e4
TS
6452 if (tf)
6453 cond = TCG_COND_EQ;
6454 else
6455 cond = TCG_COND_NE;
6456
fa31af0e 6457 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
cbc37b28 6458 tcg_gen_brcondi_i32(cond, t0, 0, l1);
a4e8338d 6459 tcg_temp_free_i32(t0);
11f94258 6460 fp0 = tcg_temp_new_i64();
9bf3eb2c 6461 gen_load_fpr64(ctx, fp0, fs);
9bf3eb2c 6462 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 6463 tcg_temp_free_i64(fp0);
cbc37b28 6464 gen_set_label(l1);
a16336e4
TS
6465}
6466
b6d96bed 6467static inline void gen_movcf_ps (int fs, int fd, int cc, int tf)
a16336e4
TS
6468{
6469 int cond;
cbc37b28 6470 TCGv_i32 t0 = tcg_temp_new_i32();
a16336e4
TS
6471 int l1 = gen_new_label();
6472 int l2 = gen_new_label();
6473
6474 if (tf)
6475 cond = TCG_COND_EQ;
6476 else
6477 cond = TCG_COND_NE;
6478
fa31af0e 6479 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
cbc37b28
AJ
6480 tcg_gen_brcondi_i32(cond, t0, 0, l1);
6481 gen_load_fpr32(t0, fs);
6482 gen_store_fpr32(t0, fd);
a16336e4 6483 gen_set_label(l1);
9bf3eb2c 6484
fa31af0e 6485 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc+1));
cbc37b28
AJ
6486 tcg_gen_brcondi_i32(cond, t0, 0, l2);
6487 gen_load_fpr32h(t0, fs);
6488 gen_store_fpr32h(t0, fd);
52a0e9eb 6489 tcg_temp_free_i32(t0);
a16336e4 6490 gen_set_label(l2);
a16336e4
TS
6491}
6492
6ea83fed 6493
bf4120ad 6494static void gen_farith (DisasContext *ctx, enum fopcode op1,
5e755519 6495 int ft, int fs, int fd, int cc)
6ea83fed 6496{
923617a3 6497 const char *opn = "farith";
6ea83fed
FB
6498 const char *condnames[] = {
6499 "c.f",
6500 "c.un",
6501 "c.eq",
6502 "c.ueq",
6503 "c.olt",
6504 "c.ult",
6505 "c.ole",
6506 "c.ule",
6507 "c.sf",
6508 "c.ngle",
6509 "c.seq",
6510 "c.ngl",
6511 "c.lt",
6512 "c.nge",
6513 "c.le",
6514 "c.ngt",
6515 };
5a1e8ffb
TS
6516 const char *condnames_abs[] = {
6517 "cabs.f",
6518 "cabs.un",
6519 "cabs.eq",
6520 "cabs.ueq",
6521 "cabs.olt",
6522 "cabs.ult",
6523 "cabs.ole",
6524 "cabs.ule",
6525 "cabs.sf",
6526 "cabs.ngle",
6527 "cabs.seq",
6528 "cabs.ngl",
6529 "cabs.lt",
6530 "cabs.nge",
6531 "cabs.le",
6532 "cabs.ngt",
6533 };
6534 enum { BINOP, CMPOP, OTHEROP } optype = OTHEROP;
7a387fff
TS
6535 uint32_t func = ctx->opcode & 0x3f;
6536
bf4120ad
NF
6537 switch (op1) {
6538 case OPC_ADD_S:
b6d96bed 6539 {
a7812ae4
PB
6540 TCGv_i32 fp0 = tcg_temp_new_i32();
6541 TCGv_i32 fp1 = tcg_temp_new_i32();
b6d96bed
TS
6542
6543 gen_load_fpr32(fp0, fs);
6544 gen_load_fpr32(fp1, ft);
a7812ae4
PB
6545 gen_helper_float_add_s(fp0, fp0, fp1);
6546 tcg_temp_free_i32(fp1);
b6d96bed 6547 gen_store_fpr32(fp0, fd);
a7812ae4 6548 tcg_temp_free_i32(fp0);
b6d96bed 6549 }
5a5012ec 6550 opn = "add.s";
5a1e8ffb 6551 optype = BINOP;
5a5012ec 6552 break;
bf4120ad 6553 case OPC_SUB_S:
b6d96bed 6554 {
a7812ae4
PB
6555 TCGv_i32 fp0 = tcg_temp_new_i32();
6556 TCGv_i32 fp1 = tcg_temp_new_i32();
b6d96bed
TS
6557
6558 gen_load_fpr32(fp0, fs);
6559 gen_load_fpr32(fp1, ft);
a7812ae4
PB
6560 gen_helper_float_sub_s(fp0, fp0, fp1);
6561 tcg_temp_free_i32(fp1);
b6d96bed 6562 gen_store_fpr32(fp0, fd);
a7812ae4 6563 tcg_temp_free_i32(fp0);
b6d96bed 6564 }
5a5012ec 6565 opn = "sub.s";
5a1e8ffb 6566 optype = BINOP;
5a5012ec 6567 break;
bf4120ad 6568 case OPC_MUL_S:
b6d96bed 6569 {
a7812ae4
PB
6570 TCGv_i32 fp0 = tcg_temp_new_i32();
6571 TCGv_i32 fp1 = tcg_temp_new_i32();
b6d96bed
TS
6572
6573 gen_load_fpr32(fp0, fs);
6574 gen_load_fpr32(fp1, ft);
a7812ae4
PB
6575 gen_helper_float_mul_s(fp0, fp0, fp1);
6576 tcg_temp_free_i32(fp1);
b6d96bed 6577 gen_store_fpr32(fp0, fd);
a7812ae4 6578 tcg_temp_free_i32(fp0);
b6d96bed 6579 }
5a5012ec 6580 opn = "mul.s";
5a1e8ffb 6581 optype = BINOP;
5a5012ec 6582 break;
bf4120ad 6583 case OPC_DIV_S:
b6d96bed 6584 {
a7812ae4
PB
6585 TCGv_i32 fp0 = tcg_temp_new_i32();
6586 TCGv_i32 fp1 = tcg_temp_new_i32();
b6d96bed
TS
6587
6588 gen_load_fpr32(fp0, fs);
6589 gen_load_fpr32(fp1, ft);
a7812ae4
PB
6590 gen_helper_float_div_s(fp0, fp0, fp1);
6591 tcg_temp_free_i32(fp1);
b6d96bed 6592 gen_store_fpr32(fp0, fd);
a7812ae4 6593 tcg_temp_free_i32(fp0);
b6d96bed 6594 }
5a5012ec 6595 opn = "div.s";
5a1e8ffb 6596 optype = BINOP;
5a5012ec 6597 break;
bf4120ad 6598 case OPC_SQRT_S:
b6d96bed 6599 {
a7812ae4 6600 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed
TS
6601
6602 gen_load_fpr32(fp0, fs);
a7812ae4 6603 gen_helper_float_sqrt_s(fp0, fp0);
b6d96bed 6604 gen_store_fpr32(fp0, fd);
a7812ae4 6605 tcg_temp_free_i32(fp0);
b6d96bed 6606 }
5a5012ec
TS
6607 opn = "sqrt.s";
6608 break;
bf4120ad 6609 case OPC_ABS_S:
b6d96bed 6610 {
a7812ae4 6611 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed
TS
6612
6613 gen_load_fpr32(fp0, fs);
a7812ae4 6614 gen_helper_float_abs_s(fp0, fp0);
b6d96bed 6615 gen_store_fpr32(fp0, fd);
a7812ae4 6616 tcg_temp_free_i32(fp0);
b6d96bed 6617 }
5a5012ec
TS
6618 opn = "abs.s";
6619 break;
bf4120ad 6620 case OPC_MOV_S:
b6d96bed 6621 {
a7812ae4 6622 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed
TS
6623
6624 gen_load_fpr32(fp0, fs);
6625 gen_store_fpr32(fp0, fd);
a7812ae4 6626 tcg_temp_free_i32(fp0);
b6d96bed 6627 }
5a5012ec
TS
6628 opn = "mov.s";
6629 break;
bf4120ad 6630 case OPC_NEG_S:
b6d96bed 6631 {
a7812ae4 6632 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed
TS
6633
6634 gen_load_fpr32(fp0, fs);
a7812ae4 6635 gen_helper_float_chs_s(fp0, fp0);
b6d96bed 6636 gen_store_fpr32(fp0, fd);
a7812ae4 6637 tcg_temp_free_i32(fp0);
b6d96bed 6638 }
5a5012ec
TS
6639 opn = "neg.s";
6640 break;
bf4120ad 6641 case OPC_ROUND_L_S:
5e755519 6642 check_cp1_64bitmode(ctx);
b6d96bed 6643 {
a7812ae4
PB
6644 TCGv_i32 fp32 = tcg_temp_new_i32();
6645 TCGv_i64 fp64 = tcg_temp_new_i64();
b6d96bed
TS
6646
6647 gen_load_fpr32(fp32, fs);
a7812ae4
PB
6648 gen_helper_float_roundl_s(fp64, fp32);
6649 tcg_temp_free_i32(fp32);
b6d96bed 6650 gen_store_fpr64(ctx, fp64, fd);
a7812ae4 6651 tcg_temp_free_i64(fp64);
b6d96bed 6652 }
5a5012ec
TS
6653 opn = "round.l.s";
6654 break;
bf4120ad 6655 case OPC_TRUNC_L_S:
5e755519 6656 check_cp1_64bitmode(ctx);
b6d96bed 6657 {
a7812ae4
PB
6658 TCGv_i32 fp32 = tcg_temp_new_i32();
6659 TCGv_i64 fp64 = tcg_temp_new_i64();
b6d96bed
TS
6660
6661 gen_load_fpr32(fp32, fs);
a7812ae4
PB
6662 gen_helper_float_truncl_s(fp64, fp32);
6663 tcg_temp_free_i32(fp32);
b6d96bed 6664 gen_store_fpr64(ctx, fp64, fd);
a7812ae4 6665 tcg_temp_free_i64(fp64);
b6d96bed 6666 }
5a5012ec
TS
6667 opn = "trunc.l.s";
6668 break;
bf4120ad 6669 case OPC_CEIL_L_S:
5e755519 6670 check_cp1_64bitmode(ctx);
b6d96bed 6671 {
a7812ae4
PB
6672 TCGv_i32 fp32 = tcg_temp_new_i32();
6673 TCGv_i64 fp64 = tcg_temp_new_i64();
b6d96bed
TS
6674
6675 gen_load_fpr32(fp32, fs);
a7812ae4
PB
6676 gen_helper_float_ceill_s(fp64, fp32);
6677 tcg_temp_free_i32(fp32);
b6d96bed 6678 gen_store_fpr64(ctx, fp64, fd);
a7812ae4 6679 tcg_temp_free_i64(fp64);
b6d96bed 6680 }
5a5012ec
TS
6681 opn = "ceil.l.s";
6682 break;
bf4120ad 6683 case OPC_FLOOR_L_S:
5e755519 6684 check_cp1_64bitmode(ctx);
b6d96bed 6685 {
a7812ae4
PB
6686 TCGv_i32 fp32 = tcg_temp_new_i32();
6687 TCGv_i64 fp64 = tcg_temp_new_i64();
b6d96bed
TS
6688
6689 gen_load_fpr32(fp32, fs);
a7812ae4
PB
6690 gen_helper_float_floorl_s(fp64, fp32);
6691 tcg_temp_free_i32(fp32);
b6d96bed 6692 gen_store_fpr64(ctx, fp64, fd);
a7812ae4 6693 tcg_temp_free_i64(fp64);
b6d96bed 6694 }
5a5012ec
TS
6695 opn = "floor.l.s";
6696 break;
bf4120ad 6697 case OPC_ROUND_W_S:
b6d96bed 6698 {
a7812ae4 6699 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed
TS
6700
6701 gen_load_fpr32(fp0, fs);
a7812ae4 6702 gen_helper_float_roundw_s(fp0, fp0);
b6d96bed 6703 gen_store_fpr32(fp0, fd);
a7812ae4 6704 tcg_temp_free_i32(fp0);
b6d96bed 6705 }
5a5012ec
TS
6706 opn = "round.w.s";
6707 break;
bf4120ad 6708 case OPC_TRUNC_W_S:
b6d96bed 6709 {
a7812ae4 6710 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed
TS
6711
6712 gen_load_fpr32(fp0, fs);
a7812ae4 6713 gen_helper_float_truncw_s(fp0, fp0);
b6d96bed 6714 gen_store_fpr32(fp0, fd);
a7812ae4 6715 tcg_temp_free_i32(fp0);
b6d96bed 6716 }
5a5012ec
TS
6717 opn = "trunc.w.s";
6718 break;
bf4120ad 6719 case OPC_CEIL_W_S:
b6d96bed 6720 {
a7812ae4 6721 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed
TS
6722
6723 gen_load_fpr32(fp0, fs);
a7812ae4 6724 gen_helper_float_ceilw_s(fp0, fp0);
b6d96bed 6725 gen_store_fpr32(fp0, fd);
a7812ae4 6726 tcg_temp_free_i32(fp0);
b6d96bed 6727 }
5a5012ec
TS
6728 opn = "ceil.w.s";
6729 break;
bf4120ad 6730 case OPC_FLOOR_W_S:
b6d96bed 6731 {
a7812ae4 6732 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed
TS
6733
6734 gen_load_fpr32(fp0, fs);
a7812ae4 6735 gen_helper_float_floorw_s(fp0, fp0);
b6d96bed 6736 gen_store_fpr32(fp0, fd);
a7812ae4 6737 tcg_temp_free_i32(fp0);
b6d96bed 6738 }
5a5012ec
TS
6739 opn = "floor.w.s";
6740 break;
bf4120ad 6741 case OPC_MOVCF_S:
b6d96bed 6742 gen_movcf_s(fs, fd, (ft >> 2) & 0x7, ft & 0x1);
5a5012ec
TS
6743 opn = "movcf.s";
6744 break;
bf4120ad 6745 case OPC_MOVZ_S:
a16336e4
TS
6746 {
6747 int l1 = gen_new_label();
c9297f4d 6748 TCGv_i32 fp0;
a16336e4 6749
c9297f4d
AJ
6750 if (ft != 0) {
6751 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[ft], 0, l1);
6752 }
6753 fp0 = tcg_temp_new_i32();
b6d96bed
TS
6754 gen_load_fpr32(fp0, fs);
6755 gen_store_fpr32(fp0, fd);
a7812ae4 6756 tcg_temp_free_i32(fp0);
a16336e4
TS
6757 gen_set_label(l1);
6758 }
5a5012ec
TS
6759 opn = "movz.s";
6760 break;
bf4120ad 6761 case OPC_MOVN_S:
a16336e4
TS
6762 {
6763 int l1 = gen_new_label();
c9297f4d
AJ
6764 TCGv_i32 fp0;
6765
6766 if (ft != 0) {
6767 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[ft], 0, l1);
6768 fp0 = tcg_temp_new_i32();
6769 gen_load_fpr32(fp0, fs);
6770 gen_store_fpr32(fp0, fd);
6771 tcg_temp_free_i32(fp0);
6772 gen_set_label(l1);
6773 }
a16336e4 6774 }
5a5012ec
TS
6775 opn = "movn.s";
6776 break;
bf4120ad 6777 case OPC_RECIP_S:
b8aa4598 6778 check_cop1x(ctx);
b6d96bed 6779 {
a7812ae4 6780 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed
TS
6781
6782 gen_load_fpr32(fp0, fs);
a7812ae4 6783 gen_helper_float_recip_s(fp0, fp0);
b6d96bed 6784 gen_store_fpr32(fp0, fd);
a7812ae4 6785 tcg_temp_free_i32(fp0);
b6d96bed 6786 }
57fa1fb3
TS
6787 opn = "recip.s";
6788 break;
bf4120ad 6789 case OPC_RSQRT_S:
b8aa4598 6790 check_cop1x(ctx);
b6d96bed 6791 {
a7812ae4 6792 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed
TS
6793
6794 gen_load_fpr32(fp0, fs);
a7812ae4 6795 gen_helper_float_rsqrt_s(fp0, fp0);
b6d96bed 6796 gen_store_fpr32(fp0, fd);
a7812ae4 6797 tcg_temp_free_i32(fp0);
b6d96bed 6798 }
57fa1fb3
TS
6799 opn = "rsqrt.s";
6800 break;
bf4120ad 6801 case OPC_RECIP2_S:
5e755519 6802 check_cp1_64bitmode(ctx);
b6d96bed 6803 {
a7812ae4
PB
6804 TCGv_i32 fp0 = tcg_temp_new_i32();
6805 TCGv_i32 fp1 = tcg_temp_new_i32();
b6d96bed
TS
6806
6807 gen_load_fpr32(fp0, fs);
d22d7289 6808 gen_load_fpr32(fp1, ft);
a7812ae4
PB
6809 gen_helper_float_recip2_s(fp0, fp0, fp1);
6810 tcg_temp_free_i32(fp1);
b6d96bed 6811 gen_store_fpr32(fp0, fd);
a7812ae4 6812 tcg_temp_free_i32(fp0);
b6d96bed 6813 }
57fa1fb3
TS
6814 opn = "recip2.s";
6815 break;
bf4120ad 6816 case OPC_RECIP1_S:
5e755519 6817 check_cp1_64bitmode(ctx);
b6d96bed 6818 {
a7812ae4 6819 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed
TS
6820
6821 gen_load_fpr32(fp0, fs);
a7812ae4 6822 gen_helper_float_recip1_s(fp0, fp0);
b6d96bed 6823 gen_store_fpr32(fp0, fd);
a7812ae4 6824 tcg_temp_free_i32(fp0);
b6d96bed 6825 }
57fa1fb3
TS
6826 opn = "recip1.s";
6827 break;
bf4120ad 6828 case OPC_RSQRT1_S:
5e755519 6829 check_cp1_64bitmode(ctx);
b6d96bed 6830 {
a7812ae4 6831 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed
TS
6832
6833 gen_load_fpr32(fp0, fs);
a7812ae4 6834 gen_helper_float_rsqrt1_s(fp0, fp0);
b6d96bed 6835 gen_store_fpr32(fp0, fd);
a7812ae4 6836 tcg_temp_free_i32(fp0);
b6d96bed 6837 }
57fa1fb3
TS
6838 opn = "rsqrt1.s";
6839 break;
bf4120ad 6840 case OPC_RSQRT2_S:
5e755519 6841 check_cp1_64bitmode(ctx);
b6d96bed 6842 {
a7812ae4
PB
6843 TCGv_i32 fp0 = tcg_temp_new_i32();
6844 TCGv_i32 fp1 = tcg_temp_new_i32();
b6d96bed
TS
6845
6846 gen_load_fpr32(fp0, fs);
6847 gen_load_fpr32(fp1, ft);
a7812ae4
PB
6848 gen_helper_float_rsqrt2_s(fp0, fp0, fp1);
6849 tcg_temp_free_i32(fp1);
b6d96bed 6850 gen_store_fpr32(fp0, fd);
a7812ae4 6851 tcg_temp_free_i32(fp0);
b6d96bed 6852 }
57fa1fb3
TS
6853 opn = "rsqrt2.s";
6854 break;
bf4120ad 6855 case OPC_CVT_D_S:
5e755519 6856 check_cp1_registers(ctx, fd);
b6d96bed 6857 {
a7812ae4
PB
6858 TCGv_i32 fp32 = tcg_temp_new_i32();
6859 TCGv_i64 fp64 = tcg_temp_new_i64();
b6d96bed
TS
6860
6861 gen_load_fpr32(fp32, fs);
a7812ae4
PB
6862 gen_helper_float_cvtd_s(fp64, fp32);
6863 tcg_temp_free_i32(fp32);
b6d96bed 6864 gen_store_fpr64(ctx, fp64, fd);
a7812ae4 6865 tcg_temp_free_i64(fp64);
b6d96bed 6866 }
5a5012ec
TS
6867 opn = "cvt.d.s";
6868 break;
bf4120ad 6869 case OPC_CVT_W_S:
b6d96bed 6870 {
a7812ae4 6871 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed
TS
6872
6873 gen_load_fpr32(fp0, fs);
a7812ae4 6874 gen_helper_float_cvtw_s(fp0, fp0);
b6d96bed 6875 gen_store_fpr32(fp0, fd);
a7812ae4 6876 tcg_temp_free_i32(fp0);
b6d96bed 6877 }
5a5012ec
TS
6878 opn = "cvt.w.s";
6879 break;
bf4120ad 6880 case OPC_CVT_L_S:
5e755519 6881 check_cp1_64bitmode(ctx);
b6d96bed 6882 {
a7812ae4
PB
6883 TCGv_i32 fp32 = tcg_temp_new_i32();
6884 TCGv_i64 fp64 = tcg_temp_new_i64();
b6d96bed
TS
6885
6886 gen_load_fpr32(fp32, fs);
a7812ae4
PB
6887 gen_helper_float_cvtl_s(fp64, fp32);
6888 tcg_temp_free_i32(fp32);
b6d96bed 6889 gen_store_fpr64(ctx, fp64, fd);
a7812ae4 6890 tcg_temp_free_i64(fp64);
b6d96bed 6891 }
5a5012ec
TS
6892 opn = "cvt.l.s";
6893 break;
bf4120ad 6894 case OPC_CVT_PS_S:
5e755519 6895 check_cp1_64bitmode(ctx);
b6d96bed 6896 {
a7812ae4
PB
6897 TCGv_i64 fp64 = tcg_temp_new_i64();
6898 TCGv_i32 fp32_0 = tcg_temp_new_i32();
6899 TCGv_i32 fp32_1 = tcg_temp_new_i32();
b6d96bed
TS
6900
6901 gen_load_fpr32(fp32_0, fs);
6902 gen_load_fpr32(fp32_1, ft);
13d24f49 6903 tcg_gen_concat_i32_i64(fp64, fp32_1, fp32_0);
a7812ae4
PB
6904 tcg_temp_free_i32(fp32_1);
6905 tcg_temp_free_i32(fp32_0);
36aa55dc 6906 gen_store_fpr64(ctx, fp64, fd);
a7812ae4 6907 tcg_temp_free_i64(fp64);
b6d96bed 6908 }
5a5012ec
TS
6909 opn = "cvt.ps.s";
6910 break;
bf4120ad
NF
6911 case OPC_CMP_F_S:
6912 case OPC_CMP_UN_S:
6913 case OPC_CMP_EQ_S:
6914 case OPC_CMP_UEQ_S:
6915 case OPC_CMP_OLT_S:
6916 case OPC_CMP_ULT_S:
6917 case OPC_CMP_OLE_S:
6918 case OPC_CMP_ULE_S:
6919 case OPC_CMP_SF_S:
6920 case OPC_CMP_NGLE_S:
6921 case OPC_CMP_SEQ_S:
6922 case OPC_CMP_NGL_S:
6923 case OPC_CMP_LT_S:
6924 case OPC_CMP_NGE_S:
6925 case OPC_CMP_LE_S:
6926 case OPC_CMP_NGT_S:
8153667c
NF
6927 if (ctx->opcode & (1 << 6)) {
6928 gen_cmpabs_s(ctx, func-48, ft, fs, cc);
6929 opn = condnames_abs[func-48];
6930 } else {
6931 gen_cmp_s(ctx, func-48, ft, fs, cc);
6932 opn = condnames[func-48];
5a1e8ffb 6933 }
5a5012ec 6934 break;
bf4120ad 6935 case OPC_ADD_D:
5e755519 6936 check_cp1_registers(ctx, fs | ft | fd);
b6d96bed 6937 {
a7812ae4
PB
6938 TCGv_i64 fp0 = tcg_temp_new_i64();
6939 TCGv_i64 fp1 = tcg_temp_new_i64();
b6d96bed
TS
6940
6941 gen_load_fpr64(ctx, fp0, fs);
6942 gen_load_fpr64(ctx, fp1, ft);
a7812ae4
PB
6943 gen_helper_float_add_d(fp0, fp0, fp1);
6944 tcg_temp_free_i64(fp1);
b6d96bed 6945 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 6946 tcg_temp_free_i64(fp0);
b6d96bed 6947 }
6ea83fed 6948 opn = "add.d";
5a1e8ffb 6949 optype = BINOP;
6ea83fed 6950 break;
bf4120ad 6951 case OPC_SUB_D:
5e755519 6952 check_cp1_registers(ctx, fs | ft | fd);
b6d96bed 6953 {
a7812ae4
PB
6954 TCGv_i64 fp0 = tcg_temp_new_i64();
6955 TCGv_i64 fp1 = tcg_temp_new_i64();
b6d96bed
TS
6956
6957 gen_load_fpr64(ctx, fp0, fs);
6958 gen_load_fpr64(ctx, fp1, ft);
a7812ae4
PB
6959 gen_helper_float_sub_d(fp0, fp0, fp1);
6960 tcg_temp_free_i64(fp1);
b6d96bed 6961 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 6962 tcg_temp_free_i64(fp0);
b6d96bed 6963 }
6ea83fed 6964 opn = "sub.d";
5a1e8ffb 6965 optype = BINOP;
6ea83fed 6966 break;
bf4120ad 6967 case OPC_MUL_D:
5e755519 6968 check_cp1_registers(ctx, fs | ft | fd);
b6d96bed 6969 {
a7812ae4
PB
6970 TCGv_i64 fp0 = tcg_temp_new_i64();
6971 TCGv_i64 fp1 = tcg_temp_new_i64();
b6d96bed
TS
6972
6973 gen_load_fpr64(ctx, fp0, fs);
6974 gen_load_fpr64(ctx, fp1, ft);
a7812ae4
PB
6975 gen_helper_float_mul_d(fp0, fp0, fp1);
6976 tcg_temp_free_i64(fp1);
b6d96bed 6977 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 6978 tcg_temp_free_i64(fp0);
b6d96bed 6979 }
6ea83fed 6980 opn = "mul.d";
5a1e8ffb 6981 optype = BINOP;
6ea83fed 6982 break;
bf4120ad 6983 case OPC_DIV_D:
5e755519 6984 check_cp1_registers(ctx, fs | ft | fd);
b6d96bed 6985 {
a7812ae4
PB
6986 TCGv_i64 fp0 = tcg_temp_new_i64();
6987 TCGv_i64 fp1 = tcg_temp_new_i64();
b6d96bed
TS
6988
6989 gen_load_fpr64(ctx, fp0, fs);
6990 gen_load_fpr64(ctx, fp1, ft);
a7812ae4
PB
6991 gen_helper_float_div_d(fp0, fp0, fp1);
6992 tcg_temp_free_i64(fp1);
b6d96bed 6993 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 6994 tcg_temp_free_i64(fp0);
b6d96bed 6995 }
6ea83fed 6996 opn = "div.d";
5a1e8ffb 6997 optype = BINOP;
6ea83fed 6998 break;
bf4120ad 6999 case OPC_SQRT_D:
5e755519 7000 check_cp1_registers(ctx, fs | fd);
b6d96bed 7001 {
a7812ae4 7002 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
7003
7004 gen_load_fpr64(ctx, fp0, fs);
a7812ae4 7005 gen_helper_float_sqrt_d(fp0, fp0);
b6d96bed 7006 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 7007 tcg_temp_free_i64(fp0);
b6d96bed 7008 }
6ea83fed
FB
7009 opn = "sqrt.d";
7010 break;
bf4120ad 7011 case OPC_ABS_D:
5e755519 7012 check_cp1_registers(ctx, fs | fd);
b6d96bed 7013 {
a7812ae4 7014 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
7015
7016 gen_load_fpr64(ctx, fp0, fs);
a7812ae4 7017 gen_helper_float_abs_d(fp0, fp0);
b6d96bed 7018 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 7019 tcg_temp_free_i64(fp0);
b6d96bed 7020 }
6ea83fed
FB
7021 opn = "abs.d";
7022 break;
bf4120ad 7023 case OPC_MOV_D:
5e755519 7024 check_cp1_registers(ctx, fs | fd);
b6d96bed 7025 {
a7812ae4 7026 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
7027
7028 gen_load_fpr64(ctx, fp0, fs);
7029 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 7030 tcg_temp_free_i64(fp0);
b6d96bed 7031 }
6ea83fed
FB
7032 opn = "mov.d";
7033 break;
bf4120ad 7034 case OPC_NEG_D:
5e755519 7035 check_cp1_registers(ctx, fs | fd);
b6d96bed 7036 {
a7812ae4 7037 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
7038
7039 gen_load_fpr64(ctx, fp0, fs);
a7812ae4 7040 gen_helper_float_chs_d(fp0, fp0);
b6d96bed 7041 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 7042 tcg_temp_free_i64(fp0);
b6d96bed 7043 }
6ea83fed
FB
7044 opn = "neg.d";
7045 break;
bf4120ad 7046 case OPC_ROUND_L_D:
5e755519 7047 check_cp1_64bitmode(ctx);
b6d96bed 7048 {
a7812ae4 7049 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
7050
7051 gen_load_fpr64(ctx, fp0, fs);
a7812ae4 7052 gen_helper_float_roundl_d(fp0, fp0);
b6d96bed 7053 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 7054 tcg_temp_free_i64(fp0);
b6d96bed 7055 }
5a5012ec
TS
7056 opn = "round.l.d";
7057 break;
bf4120ad 7058 case OPC_TRUNC_L_D:
5e755519 7059 check_cp1_64bitmode(ctx);
b6d96bed 7060 {
a7812ae4 7061 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
7062
7063 gen_load_fpr64(ctx, fp0, fs);
a7812ae4 7064 gen_helper_float_truncl_d(fp0, fp0);
b6d96bed 7065 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 7066 tcg_temp_free_i64(fp0);
b6d96bed 7067 }
5a5012ec
TS
7068 opn = "trunc.l.d";
7069 break;
bf4120ad 7070 case OPC_CEIL_L_D:
5e755519 7071 check_cp1_64bitmode(ctx);
b6d96bed 7072 {
a7812ae4 7073 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
7074
7075 gen_load_fpr64(ctx, fp0, fs);
a7812ae4 7076 gen_helper_float_ceill_d(fp0, fp0);
b6d96bed 7077 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 7078 tcg_temp_free_i64(fp0);
b6d96bed 7079 }
5a5012ec
TS
7080 opn = "ceil.l.d";
7081 break;
bf4120ad 7082 case OPC_FLOOR_L_D:
5e755519 7083 check_cp1_64bitmode(ctx);
b6d96bed 7084 {
a7812ae4 7085 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
7086
7087 gen_load_fpr64(ctx, fp0, fs);
a7812ae4 7088 gen_helper_float_floorl_d(fp0, fp0);
b6d96bed 7089 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 7090 tcg_temp_free_i64(fp0);
b6d96bed 7091 }
5a5012ec
TS
7092 opn = "floor.l.d";
7093 break;
bf4120ad 7094 case OPC_ROUND_W_D:
5e755519 7095 check_cp1_registers(ctx, fs);
b6d96bed 7096 {
a7812ae4
PB
7097 TCGv_i32 fp32 = tcg_temp_new_i32();
7098 TCGv_i64 fp64 = tcg_temp_new_i64();
b6d96bed
TS
7099
7100 gen_load_fpr64(ctx, fp64, fs);
a7812ae4
PB
7101 gen_helper_float_roundw_d(fp32, fp64);
7102 tcg_temp_free_i64(fp64);
b6d96bed 7103 gen_store_fpr32(fp32, fd);
a7812ae4 7104 tcg_temp_free_i32(fp32);
b6d96bed 7105 }
6ea83fed
FB
7106 opn = "round.w.d";
7107 break;
bf4120ad 7108 case OPC_TRUNC_W_D:
5e755519 7109 check_cp1_registers(ctx, fs);
b6d96bed 7110 {
a7812ae4
PB
7111 TCGv_i32 fp32 = tcg_temp_new_i32();
7112 TCGv_i64 fp64 = tcg_temp_new_i64();
b6d96bed
TS
7113
7114 gen_load_fpr64(ctx, fp64, fs);
a7812ae4
PB
7115 gen_helper_float_truncw_d(fp32, fp64);
7116 tcg_temp_free_i64(fp64);
b6d96bed 7117 gen_store_fpr32(fp32, fd);
a7812ae4 7118 tcg_temp_free_i32(fp32);
b6d96bed 7119 }
6ea83fed
FB
7120 opn = "trunc.w.d";
7121 break;
bf4120ad 7122 case OPC_CEIL_W_D:
5e755519 7123 check_cp1_registers(ctx, fs);
b6d96bed 7124 {
a7812ae4
PB
7125 TCGv_i32 fp32 = tcg_temp_new_i32();
7126 TCGv_i64 fp64 = tcg_temp_new_i64();
b6d96bed
TS
7127
7128 gen_load_fpr64(ctx, fp64, fs);
a7812ae4
PB
7129 gen_helper_float_ceilw_d(fp32, fp64);
7130 tcg_temp_free_i64(fp64);
b6d96bed 7131 gen_store_fpr32(fp32, fd);
a7812ae4 7132 tcg_temp_free_i32(fp32);
b6d96bed 7133 }
6ea83fed
FB
7134 opn = "ceil.w.d";
7135 break;
bf4120ad 7136 case OPC_FLOOR_W_D:
5e755519 7137 check_cp1_registers(ctx, fs);
b6d96bed 7138 {
a7812ae4
PB
7139 TCGv_i32 fp32 = tcg_temp_new_i32();
7140 TCGv_i64 fp64 = tcg_temp_new_i64();
b6d96bed
TS
7141
7142 gen_load_fpr64(ctx, fp64, fs);
a7812ae4
PB
7143 gen_helper_float_floorw_d(fp32, fp64);
7144 tcg_temp_free_i64(fp64);
b6d96bed 7145 gen_store_fpr32(fp32, fd);
a7812ae4 7146 tcg_temp_free_i32(fp32);
b6d96bed 7147 }
7a387fff 7148 opn = "floor.w.d";
6ea83fed 7149 break;
bf4120ad 7150 case OPC_MOVCF_D:
b6d96bed 7151 gen_movcf_d(ctx, fs, fd, (ft >> 2) & 0x7, ft & 0x1);
5a5012ec 7152 opn = "movcf.d";
dd016883 7153 break;
bf4120ad 7154 case OPC_MOVZ_D:
a16336e4
TS
7155 {
7156 int l1 = gen_new_label();
c9297f4d 7157 TCGv_i64 fp0;
a16336e4 7158
c9297f4d
AJ
7159 if (ft != 0) {
7160 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[ft], 0, l1);
7161 }
7162 fp0 = tcg_temp_new_i64();
b6d96bed
TS
7163 gen_load_fpr64(ctx, fp0, fs);
7164 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 7165 tcg_temp_free_i64(fp0);
a16336e4
TS
7166 gen_set_label(l1);
7167 }
5a5012ec
TS
7168 opn = "movz.d";
7169 break;
bf4120ad 7170 case OPC_MOVN_D:
a16336e4
TS
7171 {
7172 int l1 = gen_new_label();
c9297f4d
AJ
7173 TCGv_i64 fp0;
7174
7175 if (ft != 0) {
7176 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[ft], 0, l1);
7177 fp0 = tcg_temp_new_i64();
7178 gen_load_fpr64(ctx, fp0, fs);
7179 gen_store_fpr64(ctx, fp0, fd);
7180 tcg_temp_free_i64(fp0);
7181 gen_set_label(l1);
7182 }
a16336e4 7183 }
5a5012ec 7184 opn = "movn.d";
6ea83fed 7185 break;
bf4120ad 7186 case OPC_RECIP_D:
b8aa4598 7187 check_cp1_64bitmode(ctx);
b6d96bed 7188 {
a7812ae4 7189 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
7190
7191 gen_load_fpr64(ctx, fp0, fs);
a7812ae4 7192 gen_helper_float_recip_d(fp0, fp0);
b6d96bed 7193 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 7194 tcg_temp_free_i64(fp0);
b6d96bed 7195 }
57fa1fb3
TS
7196 opn = "recip.d";
7197 break;
bf4120ad 7198 case OPC_RSQRT_D:
b8aa4598 7199 check_cp1_64bitmode(ctx);
b6d96bed 7200 {
a7812ae4 7201 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
7202
7203 gen_load_fpr64(ctx, fp0, fs);
a7812ae4 7204 gen_helper_float_rsqrt_d(fp0, fp0);
b6d96bed 7205 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 7206 tcg_temp_free_i64(fp0);
b6d96bed 7207 }
57fa1fb3
TS
7208 opn = "rsqrt.d";
7209 break;
bf4120ad 7210 case OPC_RECIP2_D:
5e755519 7211 check_cp1_64bitmode(ctx);
b6d96bed 7212 {
a7812ae4
PB
7213 TCGv_i64 fp0 = tcg_temp_new_i64();
7214 TCGv_i64 fp1 = tcg_temp_new_i64();
b6d96bed
TS
7215
7216 gen_load_fpr64(ctx, fp0, fs);
7217 gen_load_fpr64(ctx, fp1, ft);
a7812ae4
PB
7218 gen_helper_float_recip2_d(fp0, fp0, fp1);
7219 tcg_temp_free_i64(fp1);
b6d96bed 7220 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 7221 tcg_temp_free_i64(fp0);
b6d96bed 7222 }
57fa1fb3
TS
7223 opn = "recip2.d";
7224 break;
bf4120ad 7225 case OPC_RECIP1_D:
5e755519 7226 check_cp1_64bitmode(ctx);
b6d96bed 7227 {
a7812ae4 7228 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
7229
7230 gen_load_fpr64(ctx, fp0, fs);
a7812ae4 7231 gen_helper_float_recip1_d(fp0, fp0);
b6d96bed 7232 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 7233 tcg_temp_free_i64(fp0);
b6d96bed 7234 }
57fa1fb3
TS
7235 opn = "recip1.d";
7236 break;
bf4120ad 7237 case OPC_RSQRT1_D:
5e755519 7238 check_cp1_64bitmode(ctx);
b6d96bed 7239 {
a7812ae4 7240 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
7241
7242 gen_load_fpr64(ctx, fp0, fs);
a7812ae4 7243 gen_helper_float_rsqrt1_d(fp0, fp0);
b6d96bed 7244 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 7245 tcg_temp_free_i64(fp0);
b6d96bed 7246 }
57fa1fb3
TS
7247 opn = "rsqrt1.d";
7248 break;
bf4120ad 7249 case OPC_RSQRT2_D:
5e755519 7250 check_cp1_64bitmode(ctx);
b6d96bed 7251 {
a7812ae4
PB
7252 TCGv_i64 fp0 = tcg_temp_new_i64();
7253 TCGv_i64 fp1 = tcg_temp_new_i64();
b6d96bed
TS
7254
7255 gen_load_fpr64(ctx, fp0, fs);
7256 gen_load_fpr64(ctx, fp1, ft);
a7812ae4
PB
7257 gen_helper_float_rsqrt2_d(fp0, fp0, fp1);
7258 tcg_temp_free_i64(fp1);
b6d96bed 7259 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 7260 tcg_temp_free_i64(fp0);
b6d96bed 7261 }
57fa1fb3
TS
7262 opn = "rsqrt2.d";
7263 break;
bf4120ad
NF
7264 case OPC_CMP_F_D:
7265 case OPC_CMP_UN_D:
7266 case OPC_CMP_EQ_D:
7267 case OPC_CMP_UEQ_D:
7268 case OPC_CMP_OLT_D:
7269 case OPC_CMP_ULT_D:
7270 case OPC_CMP_OLE_D:
7271 case OPC_CMP_ULE_D:
7272 case OPC_CMP_SF_D:
7273 case OPC_CMP_NGLE_D:
7274 case OPC_CMP_SEQ_D:
7275 case OPC_CMP_NGL_D:
7276 case OPC_CMP_LT_D:
7277 case OPC_CMP_NGE_D:
7278 case OPC_CMP_LE_D:
7279 case OPC_CMP_NGT_D:
8153667c
NF
7280 if (ctx->opcode & (1 << 6)) {
7281 gen_cmpabs_d(ctx, func-48, ft, fs, cc);
7282 opn = condnames_abs[func-48];
7283 } else {
7284 gen_cmp_d(ctx, func-48, ft, fs, cc);
7285 opn = condnames[func-48];
5a1e8ffb 7286 }
6ea83fed 7287 break;
bf4120ad 7288 case OPC_CVT_S_D:
5e755519 7289 check_cp1_registers(ctx, fs);
b6d96bed 7290 {
a7812ae4
PB
7291 TCGv_i32 fp32 = tcg_temp_new_i32();
7292 TCGv_i64 fp64 = tcg_temp_new_i64();
b6d96bed
TS
7293
7294 gen_load_fpr64(ctx, fp64, fs);
a7812ae4
PB
7295 gen_helper_float_cvts_d(fp32, fp64);
7296 tcg_temp_free_i64(fp64);
b6d96bed 7297 gen_store_fpr32(fp32, fd);
a7812ae4 7298 tcg_temp_free_i32(fp32);
b6d96bed 7299 }
5a5012ec
TS
7300 opn = "cvt.s.d";
7301 break;
bf4120ad 7302 case OPC_CVT_W_D:
5e755519 7303 check_cp1_registers(ctx, fs);
b6d96bed 7304 {
a7812ae4
PB
7305 TCGv_i32 fp32 = tcg_temp_new_i32();
7306 TCGv_i64 fp64 = tcg_temp_new_i64();
b6d96bed
TS
7307
7308 gen_load_fpr64(ctx, fp64, fs);
a7812ae4
PB
7309 gen_helper_float_cvtw_d(fp32, fp64);
7310 tcg_temp_free_i64(fp64);
b6d96bed 7311 gen_store_fpr32(fp32, fd);
a7812ae4 7312 tcg_temp_free_i32(fp32);
b6d96bed 7313 }
5a5012ec
TS
7314 opn = "cvt.w.d";
7315 break;
bf4120ad 7316 case OPC_CVT_L_D:
5e755519 7317 check_cp1_64bitmode(ctx);
b6d96bed 7318 {
a7812ae4 7319 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
7320
7321 gen_load_fpr64(ctx, fp0, fs);
a7812ae4 7322 gen_helper_float_cvtl_d(fp0, fp0);
b6d96bed 7323 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 7324 tcg_temp_free_i64(fp0);
b6d96bed 7325 }
5a5012ec
TS
7326 opn = "cvt.l.d";
7327 break;
bf4120ad 7328 case OPC_CVT_S_W:
b6d96bed 7329 {
a7812ae4 7330 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed
TS
7331
7332 gen_load_fpr32(fp0, fs);
a7812ae4 7333 gen_helper_float_cvts_w(fp0, fp0);
b6d96bed 7334 gen_store_fpr32(fp0, fd);
a7812ae4 7335 tcg_temp_free_i32(fp0);
b6d96bed 7336 }
5a5012ec 7337 opn = "cvt.s.w";
6ea83fed 7338 break;
bf4120ad 7339 case OPC_CVT_D_W:
5e755519 7340 check_cp1_registers(ctx, fd);
b6d96bed 7341 {
a7812ae4
PB
7342 TCGv_i32 fp32 = tcg_temp_new_i32();
7343 TCGv_i64 fp64 = tcg_temp_new_i64();
b6d96bed
TS
7344
7345 gen_load_fpr32(fp32, fs);
a7812ae4
PB
7346 gen_helper_float_cvtd_w(fp64, fp32);
7347 tcg_temp_free_i32(fp32);
b6d96bed 7348 gen_store_fpr64(ctx, fp64, fd);
a7812ae4 7349 tcg_temp_free_i64(fp64);
b6d96bed 7350 }
5a5012ec
TS
7351 opn = "cvt.d.w";
7352 break;
bf4120ad 7353 case OPC_CVT_S_L:
5e755519 7354 check_cp1_64bitmode(ctx);
b6d96bed 7355 {
a7812ae4
PB
7356 TCGv_i32 fp32 = tcg_temp_new_i32();
7357 TCGv_i64 fp64 = tcg_temp_new_i64();
b6d96bed
TS
7358
7359 gen_load_fpr64(ctx, fp64, fs);
a7812ae4
PB
7360 gen_helper_float_cvts_l(fp32, fp64);
7361 tcg_temp_free_i64(fp64);
b6d96bed 7362 gen_store_fpr32(fp32, fd);
a7812ae4 7363 tcg_temp_free_i32(fp32);
b6d96bed 7364 }
5a5012ec
TS
7365 opn = "cvt.s.l";
7366 break;
bf4120ad 7367 case OPC_CVT_D_L:
5e755519 7368 check_cp1_64bitmode(ctx);
b6d96bed 7369 {
a7812ae4 7370 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
7371
7372 gen_load_fpr64(ctx, fp0, fs);
a7812ae4 7373 gen_helper_float_cvtd_l(fp0, fp0);
b6d96bed 7374 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 7375 tcg_temp_free_i64(fp0);
b6d96bed 7376 }
5a5012ec
TS
7377 opn = "cvt.d.l";
7378 break;
bf4120ad 7379 case OPC_CVT_PS_PW:
5e755519 7380 check_cp1_64bitmode(ctx);
b6d96bed 7381 {
a7812ae4 7382 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
7383
7384 gen_load_fpr64(ctx, fp0, fs);
a7812ae4 7385 gen_helper_float_cvtps_pw(fp0, fp0);
b6d96bed 7386 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 7387 tcg_temp_free_i64(fp0);
b6d96bed 7388 }
5a5012ec
TS
7389 opn = "cvt.ps.pw";
7390 break;
bf4120ad 7391 case OPC_ADD_PS:
5e755519 7392 check_cp1_64bitmode(ctx);
b6d96bed 7393 {
a7812ae4
PB
7394 TCGv_i64 fp0 = tcg_temp_new_i64();
7395 TCGv_i64 fp1 = tcg_temp_new_i64();
b6d96bed
TS
7396
7397 gen_load_fpr64(ctx, fp0, fs);
7398 gen_load_fpr64(ctx, fp1, ft);
a7812ae4
PB
7399 gen_helper_float_add_ps(fp0, fp0, fp1);
7400 tcg_temp_free_i64(fp1);
b6d96bed 7401 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 7402 tcg_temp_free_i64(fp0);
b6d96bed 7403 }
5a5012ec 7404 opn = "add.ps";
6ea83fed 7405 break;
bf4120ad 7406 case OPC_SUB_PS:
5e755519 7407 check_cp1_64bitmode(ctx);
b6d96bed 7408 {
a7812ae4
PB
7409 TCGv_i64 fp0 = tcg_temp_new_i64();
7410 TCGv_i64 fp1 = tcg_temp_new_i64();
b6d96bed
TS
7411
7412 gen_load_fpr64(ctx, fp0, fs);
7413 gen_load_fpr64(ctx, fp1, ft);
a7812ae4
PB
7414 gen_helper_float_sub_ps(fp0, fp0, fp1);
7415 tcg_temp_free_i64(fp1);
b6d96bed 7416 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 7417 tcg_temp_free_i64(fp0);
b6d96bed 7418 }
5a5012ec 7419 opn = "sub.ps";
6ea83fed 7420 break;
bf4120ad 7421 case OPC_MUL_PS:
5e755519 7422 check_cp1_64bitmode(ctx);
b6d96bed 7423 {
a7812ae4
PB
7424 TCGv_i64 fp0 = tcg_temp_new_i64();
7425 TCGv_i64 fp1 = tcg_temp_new_i64();
b6d96bed
TS
7426
7427 gen_load_fpr64(ctx, fp0, fs);
7428 gen_load_fpr64(ctx, fp1, ft);
a7812ae4
PB
7429 gen_helper_float_mul_ps(fp0, fp0, fp1);
7430 tcg_temp_free_i64(fp1);
b6d96bed 7431 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 7432 tcg_temp_free_i64(fp0);
b6d96bed 7433 }
5a5012ec 7434 opn = "mul.ps";
6ea83fed 7435 break;
bf4120ad 7436 case OPC_ABS_PS:
5e755519 7437 check_cp1_64bitmode(ctx);
b6d96bed 7438 {
a7812ae4 7439 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
7440
7441 gen_load_fpr64(ctx, fp0, fs);
a7812ae4 7442 gen_helper_float_abs_ps(fp0, fp0);
b6d96bed 7443 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 7444 tcg_temp_free_i64(fp0);
b6d96bed 7445 }
5a5012ec 7446 opn = "abs.ps";
6ea83fed 7447 break;
bf4120ad 7448 case OPC_MOV_PS:
5e755519 7449 check_cp1_64bitmode(ctx);
b6d96bed 7450 {
a7812ae4 7451 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
7452
7453 gen_load_fpr64(ctx, fp0, fs);
7454 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 7455 tcg_temp_free_i64(fp0);
b6d96bed 7456 }
5a5012ec 7457 opn = "mov.ps";
6ea83fed 7458 break;
bf4120ad 7459 case OPC_NEG_PS:
5e755519 7460 check_cp1_64bitmode(ctx);
b6d96bed 7461 {
a7812ae4 7462 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
7463
7464 gen_load_fpr64(ctx, fp0, fs);
a7812ae4 7465 gen_helper_float_chs_ps(fp0, fp0);
b6d96bed 7466 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 7467 tcg_temp_free_i64(fp0);
b6d96bed 7468 }
5a5012ec 7469 opn = "neg.ps";
6ea83fed 7470 break;
bf4120ad 7471 case OPC_MOVCF_PS:
5e755519 7472 check_cp1_64bitmode(ctx);
b6d96bed 7473 gen_movcf_ps(fs, fd, (ft >> 2) & 0x7, ft & 0x1);
5a5012ec 7474 opn = "movcf.ps";
6ea83fed 7475 break;
bf4120ad 7476 case OPC_MOVZ_PS:
5e755519 7477 check_cp1_64bitmode(ctx);
a16336e4
TS
7478 {
7479 int l1 = gen_new_label();
30a3848b 7480 TCGv_i64 fp0;
a16336e4 7481
c9297f4d
AJ
7482 if (ft != 0)
7483 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[ft], 0, l1);
7484 fp0 = tcg_temp_new_i64();
7485 gen_load_fpr64(ctx, fp0, fs);
7486 gen_store_fpr64(ctx, fp0, fd);
7487 tcg_temp_free_i64(fp0);
a16336e4
TS
7488 gen_set_label(l1);
7489 }
5a5012ec 7490 opn = "movz.ps";
6ea83fed 7491 break;
bf4120ad 7492 case OPC_MOVN_PS:
5e755519 7493 check_cp1_64bitmode(ctx);
a16336e4
TS
7494 {
7495 int l1 = gen_new_label();
30a3848b 7496 TCGv_i64 fp0;
c9297f4d
AJ
7497
7498 if (ft != 0) {
7499 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[ft], 0, l1);
7500 fp0 = tcg_temp_new_i64();
7501 gen_load_fpr64(ctx, fp0, fs);
7502 gen_store_fpr64(ctx, fp0, fd);
7503 tcg_temp_free_i64(fp0);
7504 gen_set_label(l1);
7505 }
a16336e4 7506 }
5a5012ec 7507 opn = "movn.ps";
6ea83fed 7508 break;
bf4120ad 7509 case OPC_ADDR_PS:
5e755519 7510 check_cp1_64bitmode(ctx);
b6d96bed 7511 {
a7812ae4
PB
7512 TCGv_i64 fp0 = tcg_temp_new_i64();
7513 TCGv_i64 fp1 = tcg_temp_new_i64();
b6d96bed
TS
7514
7515 gen_load_fpr64(ctx, fp0, ft);
7516 gen_load_fpr64(ctx, fp1, fs);
a7812ae4
PB
7517 gen_helper_float_addr_ps(fp0, fp0, fp1);
7518 tcg_temp_free_i64(fp1);
b6d96bed 7519 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 7520 tcg_temp_free_i64(fp0);
b6d96bed 7521 }
fbcc6828
TS
7522 opn = "addr.ps";
7523 break;
bf4120ad 7524 case OPC_MULR_PS:
5e755519 7525 check_cp1_64bitmode(ctx);
b6d96bed 7526 {
a7812ae4
PB
7527 TCGv_i64 fp0 = tcg_temp_new_i64();
7528 TCGv_i64 fp1 = tcg_temp_new_i64();
b6d96bed
TS
7529
7530 gen_load_fpr64(ctx, fp0, ft);
7531 gen_load_fpr64(ctx, fp1, fs);
a7812ae4
PB
7532 gen_helper_float_mulr_ps(fp0, fp0, fp1);
7533 tcg_temp_free_i64(fp1);
b6d96bed 7534 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 7535 tcg_temp_free_i64(fp0);
b6d96bed 7536 }
57fa1fb3
TS
7537 opn = "mulr.ps";
7538 break;
bf4120ad 7539 case OPC_RECIP2_PS:
5e755519 7540 check_cp1_64bitmode(ctx);
b6d96bed 7541 {
a7812ae4
PB
7542 TCGv_i64 fp0 = tcg_temp_new_i64();
7543 TCGv_i64 fp1 = tcg_temp_new_i64();
b6d96bed
TS
7544
7545 gen_load_fpr64(ctx, fp0, fs);
d22d7289 7546 gen_load_fpr64(ctx, fp1, ft);
a7812ae4
PB
7547 gen_helper_float_recip2_ps(fp0, fp0, fp1);
7548 tcg_temp_free_i64(fp1);
b6d96bed 7549 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 7550 tcg_temp_free_i64(fp0);
b6d96bed 7551 }
57fa1fb3
TS
7552 opn = "recip2.ps";
7553 break;
bf4120ad 7554 case OPC_RECIP1_PS:
5e755519 7555 check_cp1_64bitmode(ctx);
b6d96bed 7556 {
a7812ae4 7557 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
7558
7559 gen_load_fpr64(ctx, fp0, fs);
a7812ae4 7560 gen_helper_float_recip1_ps(fp0, fp0);
b6d96bed 7561 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 7562 tcg_temp_free_i64(fp0);
b6d96bed 7563 }
57fa1fb3
TS
7564 opn = "recip1.ps";
7565 break;
bf4120ad 7566 case OPC_RSQRT1_PS:
5e755519 7567 check_cp1_64bitmode(ctx);
b6d96bed 7568 {
a7812ae4 7569 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
7570
7571 gen_load_fpr64(ctx, fp0, fs);
a7812ae4 7572 gen_helper_float_rsqrt1_ps(fp0, fp0);
b6d96bed 7573 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 7574 tcg_temp_free_i64(fp0);
b6d96bed 7575 }
57fa1fb3
TS
7576 opn = "rsqrt1.ps";
7577 break;
bf4120ad 7578 case OPC_RSQRT2_PS:
5e755519 7579 check_cp1_64bitmode(ctx);
b6d96bed 7580 {
a7812ae4
PB
7581 TCGv_i64 fp0 = tcg_temp_new_i64();
7582 TCGv_i64 fp1 = tcg_temp_new_i64();
b6d96bed
TS
7583
7584 gen_load_fpr64(ctx, fp0, fs);
7585 gen_load_fpr64(ctx, fp1, ft);
a7812ae4
PB
7586 gen_helper_float_rsqrt2_ps(fp0, fp0, fp1);
7587 tcg_temp_free_i64(fp1);
b6d96bed 7588 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 7589 tcg_temp_free_i64(fp0);
b6d96bed 7590 }
57fa1fb3
TS
7591 opn = "rsqrt2.ps";
7592 break;
bf4120ad 7593 case OPC_CVT_S_PU:
5e755519 7594 check_cp1_64bitmode(ctx);
b6d96bed 7595 {
a7812ae4 7596 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed
TS
7597
7598 gen_load_fpr32h(fp0, fs);
a7812ae4 7599 gen_helper_float_cvts_pu(fp0, fp0);
b6d96bed 7600 gen_store_fpr32(fp0, fd);
a7812ae4 7601 tcg_temp_free_i32(fp0);
b6d96bed 7602 }
5a5012ec 7603 opn = "cvt.s.pu";
dd016883 7604 break;
bf4120ad 7605 case OPC_CVT_PW_PS:
5e755519 7606 check_cp1_64bitmode(ctx);
b6d96bed 7607 {
a7812ae4 7608 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
7609
7610 gen_load_fpr64(ctx, fp0, fs);
a7812ae4 7611 gen_helper_float_cvtpw_ps(fp0, fp0);
b6d96bed 7612 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 7613 tcg_temp_free_i64(fp0);
b6d96bed 7614 }
5a5012ec 7615 opn = "cvt.pw.ps";
6ea83fed 7616 break;
bf4120ad 7617 case OPC_CVT_S_PL:
5e755519 7618 check_cp1_64bitmode(ctx);
b6d96bed 7619 {
a7812ae4 7620 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed
TS
7621
7622 gen_load_fpr32(fp0, fs);
a7812ae4 7623 gen_helper_float_cvts_pl(fp0, fp0);
b6d96bed 7624 gen_store_fpr32(fp0, fd);
a7812ae4 7625 tcg_temp_free_i32(fp0);
b6d96bed 7626 }
5a5012ec 7627 opn = "cvt.s.pl";
6ea83fed 7628 break;
bf4120ad 7629 case OPC_PLL_PS:
5e755519 7630 check_cp1_64bitmode(ctx);
b6d96bed 7631 {
a7812ae4
PB
7632 TCGv_i32 fp0 = tcg_temp_new_i32();
7633 TCGv_i32 fp1 = tcg_temp_new_i32();
b6d96bed
TS
7634
7635 gen_load_fpr32(fp0, fs);
7636 gen_load_fpr32(fp1, ft);
7637 gen_store_fpr32h(fp0, fd);
7638 gen_store_fpr32(fp1, fd);
a7812ae4
PB
7639 tcg_temp_free_i32(fp0);
7640 tcg_temp_free_i32(fp1);
b6d96bed 7641 }
5a5012ec 7642 opn = "pll.ps";
6ea83fed 7643 break;
bf4120ad 7644 case OPC_PLU_PS:
5e755519 7645 check_cp1_64bitmode(ctx);
b6d96bed 7646 {
a7812ae4
PB
7647 TCGv_i32 fp0 = tcg_temp_new_i32();
7648 TCGv_i32 fp1 = tcg_temp_new_i32();
b6d96bed
TS
7649
7650 gen_load_fpr32(fp0, fs);
7651 gen_load_fpr32h(fp1, ft);
7652 gen_store_fpr32(fp1, fd);
7653 gen_store_fpr32h(fp0, fd);
a7812ae4
PB
7654 tcg_temp_free_i32(fp0);
7655 tcg_temp_free_i32(fp1);
b6d96bed 7656 }
5a5012ec
TS
7657 opn = "plu.ps";
7658 break;
bf4120ad 7659 case OPC_PUL_PS:
5e755519 7660 check_cp1_64bitmode(ctx);
b6d96bed 7661 {
a7812ae4
PB
7662 TCGv_i32 fp0 = tcg_temp_new_i32();
7663 TCGv_i32 fp1 = tcg_temp_new_i32();
b6d96bed
TS
7664
7665 gen_load_fpr32h(fp0, fs);
7666 gen_load_fpr32(fp1, ft);
7667 gen_store_fpr32(fp1, fd);
7668 gen_store_fpr32h(fp0, fd);
a7812ae4
PB
7669 tcg_temp_free_i32(fp0);
7670 tcg_temp_free_i32(fp1);
b6d96bed 7671 }
5a5012ec
TS
7672 opn = "pul.ps";
7673 break;
bf4120ad 7674 case OPC_PUU_PS:
5e755519 7675 check_cp1_64bitmode(ctx);
b6d96bed 7676 {
a7812ae4
PB
7677 TCGv_i32 fp0 = tcg_temp_new_i32();
7678 TCGv_i32 fp1 = tcg_temp_new_i32();
b6d96bed
TS
7679
7680 gen_load_fpr32h(fp0, fs);
7681 gen_load_fpr32h(fp1, ft);
7682 gen_store_fpr32(fp1, fd);
7683 gen_store_fpr32h(fp0, fd);
a7812ae4
PB
7684 tcg_temp_free_i32(fp0);
7685 tcg_temp_free_i32(fp1);
b6d96bed 7686 }
5a5012ec
TS
7687 opn = "puu.ps";
7688 break;
bf4120ad
NF
7689 case OPC_CMP_F_PS:
7690 case OPC_CMP_UN_PS:
7691 case OPC_CMP_EQ_PS:
7692 case OPC_CMP_UEQ_PS:
7693 case OPC_CMP_OLT_PS:
7694 case OPC_CMP_ULT_PS:
7695 case OPC_CMP_OLE_PS:
7696 case OPC_CMP_ULE_PS:
7697 case OPC_CMP_SF_PS:
7698 case OPC_CMP_NGLE_PS:
7699 case OPC_CMP_SEQ_PS:
7700 case OPC_CMP_NGL_PS:
7701 case OPC_CMP_LT_PS:
7702 case OPC_CMP_NGE_PS:
7703 case OPC_CMP_LE_PS:
7704 case OPC_CMP_NGT_PS:
8153667c
NF
7705 if (ctx->opcode & (1 << 6)) {
7706 gen_cmpabs_ps(ctx, func-48, ft, fs, cc);
7707 opn = condnames_abs[func-48];
7708 } else {
7709 gen_cmp_ps(ctx, func-48, ft, fs, cc);
7710 opn = condnames[func-48];
5a1e8ffb 7711 }
6ea83fed 7712 break;
5a5012ec 7713 default:
923617a3 7714 MIPS_INVAL(opn);
e397ee33 7715 generate_exception (ctx, EXCP_RI);
6ea83fed
FB
7716 return;
7717 }
2abf314d 7718 (void)opn; /* avoid a compiler warning */
5a1e8ffb
TS
7719 switch (optype) {
7720 case BINOP:
6ea83fed 7721 MIPS_DEBUG("%s %s, %s, %s", opn, fregnames[fd], fregnames[fs], fregnames[ft]);
5a1e8ffb
TS
7722 break;
7723 case CMPOP:
7724 MIPS_DEBUG("%s %s,%s", opn, fregnames[fs], fregnames[ft]);
7725 break;
7726 default:
6ea83fed 7727 MIPS_DEBUG("%s %s,%s", opn, fregnames[fd], fregnames[fs]);
5a1e8ffb
TS
7728 break;
7729 }
6ea83fed 7730}
6af0bf9c 7731
5a5012ec 7732/* Coprocessor 3 (FPU) */
5e755519
TS
7733static void gen_flt3_ldst (DisasContext *ctx, uint32_t opc,
7734 int fd, int fs, int base, int index)
7a387fff 7735{
923617a3 7736 const char *opn = "extended float load/store";
93b12ccc 7737 int store = 0;
4e2474d6 7738 TCGv t0 = tcg_temp_new();
7a387fff 7739
93b12ccc 7740 if (base == 0) {
6c5c1e20 7741 gen_load_gpr(t0, index);
93b12ccc 7742 } else if (index == 0) {
6c5c1e20 7743 gen_load_gpr(t0, base);
93b12ccc 7744 } else {
e9203484 7745 gen_load_gpr(t0, index);
941694d0 7746 gen_op_addr_add(ctx, t0, cpu_gpr[base], t0);
93b12ccc 7747 }
5a5012ec 7748 /* Don't do NOP if destination is zero: we must perform the actual
ead9360e 7749 memory access. */
4e2474d6 7750 save_cpu_state(ctx, 0);
5a5012ec
TS
7751 switch (opc) {
7752 case OPC_LWXC1:
8c0ab41f 7753 check_cop1x(ctx);
b6d96bed 7754 {
a7812ae4 7755 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed 7756
585c88d5
AJ
7757 tcg_gen_qemu_ld32s(t0, t0, ctx->mem_idx);
7758 tcg_gen_trunc_tl_i32(fp0, t0);
b6d96bed 7759 gen_store_fpr32(fp0, fd);
a7812ae4 7760 tcg_temp_free_i32(fp0);
b6d96bed 7761 }
5a5012ec
TS
7762 opn = "lwxc1";
7763 break;
7764 case OPC_LDXC1:
8c0ab41f
AJ
7765 check_cop1x(ctx);
7766 check_cp1_registers(ctx, fd);
b6d96bed 7767 {
a7812ae4 7768 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
7769
7770 tcg_gen_qemu_ld64(fp0, t0, ctx->mem_idx);
7771 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 7772 tcg_temp_free_i64(fp0);
b6d96bed 7773 }
5a5012ec
TS
7774 opn = "ldxc1";
7775 break;
7776 case OPC_LUXC1:
8c0ab41f 7777 check_cp1_64bitmode(ctx);
6c5c1e20 7778 tcg_gen_andi_tl(t0, t0, ~0x7);
b6d96bed 7779 {
a7812ae4 7780 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
7781
7782 tcg_gen_qemu_ld64(fp0, t0, ctx->mem_idx);
7783 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 7784 tcg_temp_free_i64(fp0);
b6d96bed 7785 }
5a5012ec
TS
7786 opn = "luxc1";
7787 break;
7788 case OPC_SWXC1:
8c0ab41f 7789 check_cop1x(ctx);
b6d96bed 7790 {
a7812ae4 7791 TCGv_i32 fp0 = tcg_temp_new_i32();
585c88d5 7792 TCGv t1 = tcg_temp_new();
b6d96bed
TS
7793
7794 gen_load_fpr32(fp0, fs);
a7812ae4
PB
7795 tcg_gen_extu_i32_tl(t1, fp0);
7796 tcg_gen_qemu_st32(t1, t0, ctx->mem_idx);
7797 tcg_temp_free_i32(fp0);
a6035857 7798 tcg_temp_free(t1);
b6d96bed 7799 }
5a5012ec 7800 opn = "swxc1";
93b12ccc 7801 store = 1;
5a5012ec
TS
7802 break;
7803 case OPC_SDXC1:
8c0ab41f
AJ
7804 check_cop1x(ctx);
7805 check_cp1_registers(ctx, fs);
b6d96bed 7806 {
a7812ae4 7807 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
7808
7809 gen_load_fpr64(ctx, fp0, fs);
7810 tcg_gen_qemu_st64(fp0, t0, ctx->mem_idx);
a7812ae4 7811 tcg_temp_free_i64(fp0);
b6d96bed 7812 }
5a5012ec 7813 opn = "sdxc1";
93b12ccc 7814 store = 1;
5a5012ec
TS
7815 break;
7816 case OPC_SUXC1:
8c0ab41f 7817 check_cp1_64bitmode(ctx);
6c5c1e20 7818 tcg_gen_andi_tl(t0, t0, ~0x7);
b6d96bed 7819 {
a7812ae4 7820 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
7821
7822 gen_load_fpr64(ctx, fp0, fs);
7823 tcg_gen_qemu_st64(fp0, t0, ctx->mem_idx);
a7812ae4 7824 tcg_temp_free_i64(fp0);
b6d96bed 7825 }
5a5012ec 7826 opn = "suxc1";
93b12ccc 7827 store = 1;
5a5012ec 7828 break;
5a5012ec 7829 }
6c5c1e20 7830 tcg_temp_free(t0);
2abf314d 7831 (void)opn; (void)store; /* avoid compiler warnings */
93b12ccc
TS
7832 MIPS_DEBUG("%s %s, %s(%s)", opn, fregnames[store ? fs : fd],
7833 regnames[index], regnames[base]);
5a5012ec
TS
7834}
7835
5e755519
TS
7836static void gen_flt3_arith (DisasContext *ctx, uint32_t opc,
7837 int fd, int fr, int fs, int ft)
5a5012ec 7838{
923617a3 7839 const char *opn = "flt3_arith";
5a5012ec 7840
5a5012ec
TS
7841 switch (opc) {
7842 case OPC_ALNV_PS:
b8aa4598 7843 check_cp1_64bitmode(ctx);
a16336e4 7844 {
a7812ae4 7845 TCGv t0 = tcg_temp_local_new();
c905fdac
AJ
7846 TCGv_i32 fp = tcg_temp_new_i32();
7847 TCGv_i32 fph = tcg_temp_new_i32();
a16336e4
TS
7848 int l1 = gen_new_label();
7849 int l2 = gen_new_label();
7850
6c5c1e20
TS
7851 gen_load_gpr(t0, fr);
7852 tcg_gen_andi_tl(t0, t0, 0x7);
6c5c1e20
TS
7853
7854 tcg_gen_brcondi_tl(TCG_COND_NE, t0, 0, l1);
c905fdac
AJ
7855 gen_load_fpr32(fp, fs);
7856 gen_load_fpr32h(fph, fs);
7857 gen_store_fpr32(fp, fd);
7858 gen_store_fpr32h(fph, fd);
a16336e4
TS
7859 tcg_gen_br(l2);
7860 gen_set_label(l1);
6c5c1e20
TS
7861 tcg_gen_brcondi_tl(TCG_COND_NE, t0, 4, l2);
7862 tcg_temp_free(t0);
a16336e4 7863#ifdef TARGET_WORDS_BIGENDIAN
c905fdac
AJ
7864 gen_load_fpr32(fp, fs);
7865 gen_load_fpr32h(fph, ft);
7866 gen_store_fpr32h(fp, fd);
7867 gen_store_fpr32(fph, fd);
a16336e4 7868#else
c905fdac
AJ
7869 gen_load_fpr32h(fph, fs);
7870 gen_load_fpr32(fp, ft);
7871 gen_store_fpr32(fph, fd);
7872 gen_store_fpr32h(fp, fd);
a16336e4
TS
7873#endif
7874 gen_set_label(l2);
c905fdac
AJ
7875 tcg_temp_free_i32(fp);
7876 tcg_temp_free_i32(fph);
a16336e4 7877 }
5a5012ec
TS
7878 opn = "alnv.ps";
7879 break;
7880 case OPC_MADD_S:
b8aa4598 7881 check_cop1x(ctx);
b6d96bed 7882 {
a7812ae4
PB
7883 TCGv_i32 fp0 = tcg_temp_new_i32();
7884 TCGv_i32 fp1 = tcg_temp_new_i32();
7885 TCGv_i32 fp2 = tcg_temp_new_i32();
b6d96bed
TS
7886
7887 gen_load_fpr32(fp0, fs);
7888 gen_load_fpr32(fp1, ft);
7889 gen_load_fpr32(fp2, fr);
a7812ae4
PB
7890 gen_helper_float_muladd_s(fp2, fp0, fp1, fp2);
7891 tcg_temp_free_i32(fp0);
7892 tcg_temp_free_i32(fp1);
b6d96bed 7893 gen_store_fpr32(fp2, fd);
a7812ae4 7894 tcg_temp_free_i32(fp2);
b6d96bed 7895 }
5a5012ec
TS
7896 opn = "madd.s";
7897 break;
7898 case OPC_MADD_D:
b8aa4598
TS
7899 check_cop1x(ctx);
7900 check_cp1_registers(ctx, fd | fs | ft | fr);
b6d96bed 7901 {
a7812ae4
PB
7902 TCGv_i64 fp0 = tcg_temp_new_i64();
7903 TCGv_i64 fp1 = tcg_temp_new_i64();
7904 TCGv_i64 fp2 = tcg_temp_new_i64();
b6d96bed
TS
7905
7906 gen_load_fpr64(ctx, fp0, fs);
7907 gen_load_fpr64(ctx, fp1, ft);
7908 gen_load_fpr64(ctx, fp2, fr);
a7812ae4
PB
7909 gen_helper_float_muladd_d(fp2, fp0, fp1, fp2);
7910 tcg_temp_free_i64(fp0);
7911 tcg_temp_free_i64(fp1);
b6d96bed 7912 gen_store_fpr64(ctx, fp2, fd);
a7812ae4 7913 tcg_temp_free_i64(fp2);
b6d96bed 7914 }
5a5012ec
TS
7915 opn = "madd.d";
7916 break;
7917 case OPC_MADD_PS:
b8aa4598 7918 check_cp1_64bitmode(ctx);
b6d96bed 7919 {
a7812ae4
PB
7920 TCGv_i64 fp0 = tcg_temp_new_i64();
7921 TCGv_i64 fp1 = tcg_temp_new_i64();
7922 TCGv_i64 fp2 = tcg_temp_new_i64();
b6d96bed
TS
7923
7924 gen_load_fpr64(ctx, fp0, fs);
7925 gen_load_fpr64(ctx, fp1, ft);
7926 gen_load_fpr64(ctx, fp2, fr);
a7812ae4
PB
7927 gen_helper_float_muladd_ps(fp2, fp0, fp1, fp2);
7928 tcg_temp_free_i64(fp0);
7929 tcg_temp_free_i64(fp1);
b6d96bed 7930 gen_store_fpr64(ctx, fp2, fd);
a7812ae4 7931 tcg_temp_free_i64(fp2);
b6d96bed 7932 }
5a5012ec
TS
7933 opn = "madd.ps";
7934 break;
7935 case OPC_MSUB_S:
b8aa4598 7936 check_cop1x(ctx);
b6d96bed 7937 {
a7812ae4
PB
7938 TCGv_i32 fp0 = tcg_temp_new_i32();
7939 TCGv_i32 fp1 = tcg_temp_new_i32();
7940 TCGv_i32 fp2 = tcg_temp_new_i32();
b6d96bed
TS
7941
7942 gen_load_fpr32(fp0, fs);
7943 gen_load_fpr32(fp1, ft);
7944 gen_load_fpr32(fp2, fr);
a7812ae4
PB
7945 gen_helper_float_mulsub_s(fp2, fp0, fp1, fp2);
7946 tcg_temp_free_i32(fp0);
7947 tcg_temp_free_i32(fp1);
b6d96bed 7948 gen_store_fpr32(fp2, fd);
a7812ae4 7949 tcg_temp_free_i32(fp2);
b6d96bed 7950 }
5a5012ec
TS
7951 opn = "msub.s";
7952 break;
7953 case OPC_MSUB_D:
b8aa4598
TS
7954 check_cop1x(ctx);
7955 check_cp1_registers(ctx, fd | fs | ft | fr);
b6d96bed 7956 {
a7812ae4
PB
7957 TCGv_i64 fp0 = tcg_temp_new_i64();
7958 TCGv_i64 fp1 = tcg_temp_new_i64();
7959 TCGv_i64 fp2 = tcg_temp_new_i64();
b6d96bed
TS
7960
7961 gen_load_fpr64(ctx, fp0, fs);
7962 gen_load_fpr64(ctx, fp1, ft);
7963 gen_load_fpr64(ctx, fp2, fr);
a7812ae4
PB
7964 gen_helper_float_mulsub_d(fp2, fp0, fp1, fp2);
7965 tcg_temp_free_i64(fp0);
7966 tcg_temp_free_i64(fp1);
b6d96bed 7967 gen_store_fpr64(ctx, fp2, fd);
a7812ae4 7968 tcg_temp_free_i64(fp2);
b6d96bed 7969 }
5a5012ec
TS
7970 opn = "msub.d";
7971 break;
7972 case OPC_MSUB_PS:
b8aa4598 7973 check_cp1_64bitmode(ctx);
b6d96bed 7974 {
a7812ae4
PB
7975 TCGv_i64 fp0 = tcg_temp_new_i64();
7976 TCGv_i64 fp1 = tcg_temp_new_i64();
7977 TCGv_i64 fp2 = tcg_temp_new_i64();
b6d96bed
TS
7978
7979 gen_load_fpr64(ctx, fp0, fs);
7980 gen_load_fpr64(ctx, fp1, ft);
7981 gen_load_fpr64(ctx, fp2, fr);
a7812ae4
PB
7982 gen_helper_float_mulsub_ps(fp2, fp0, fp1, fp2);
7983 tcg_temp_free_i64(fp0);
7984 tcg_temp_free_i64(fp1);
b6d96bed 7985 gen_store_fpr64(ctx, fp2, fd);
a7812ae4 7986 tcg_temp_free_i64(fp2);
b6d96bed 7987 }
5a5012ec
TS
7988 opn = "msub.ps";
7989 break;
7990 case OPC_NMADD_S:
b8aa4598 7991 check_cop1x(ctx);
b6d96bed 7992 {
a7812ae4
PB
7993 TCGv_i32 fp0 = tcg_temp_new_i32();
7994 TCGv_i32 fp1 = tcg_temp_new_i32();
7995 TCGv_i32 fp2 = tcg_temp_new_i32();
b6d96bed
TS
7996
7997 gen_load_fpr32(fp0, fs);
7998 gen_load_fpr32(fp1, ft);
7999 gen_load_fpr32(fp2, fr);
a7812ae4
PB
8000 gen_helper_float_nmuladd_s(fp2, fp0, fp1, fp2);
8001 tcg_temp_free_i32(fp0);
8002 tcg_temp_free_i32(fp1);
b6d96bed 8003 gen_store_fpr32(fp2, fd);
a7812ae4 8004 tcg_temp_free_i32(fp2);
b6d96bed 8005 }
5a5012ec
TS
8006 opn = "nmadd.s";
8007 break;
8008 case OPC_NMADD_D:
b8aa4598
TS
8009 check_cop1x(ctx);
8010 check_cp1_registers(ctx, fd | fs | ft | fr);
b6d96bed 8011 {
a7812ae4
PB
8012 TCGv_i64 fp0 = tcg_temp_new_i64();
8013 TCGv_i64 fp1 = tcg_temp_new_i64();
8014 TCGv_i64 fp2 = tcg_temp_new_i64();
b6d96bed
TS
8015
8016 gen_load_fpr64(ctx, fp0, fs);
8017 gen_load_fpr64(ctx, fp1, ft);
8018 gen_load_fpr64(ctx, fp2, fr);
a7812ae4
PB
8019 gen_helper_float_nmuladd_d(fp2, fp0, fp1, fp2);
8020 tcg_temp_free_i64(fp0);
8021 tcg_temp_free_i64(fp1);
b6d96bed 8022 gen_store_fpr64(ctx, fp2, fd);
a7812ae4 8023 tcg_temp_free_i64(fp2);
b6d96bed 8024 }
5a5012ec
TS
8025 opn = "nmadd.d";
8026 break;
8027 case OPC_NMADD_PS:
b8aa4598 8028 check_cp1_64bitmode(ctx);
b6d96bed 8029 {
a7812ae4
PB
8030 TCGv_i64 fp0 = tcg_temp_new_i64();
8031 TCGv_i64 fp1 = tcg_temp_new_i64();
8032 TCGv_i64 fp2 = tcg_temp_new_i64();
b6d96bed
TS
8033
8034 gen_load_fpr64(ctx, fp0, fs);
8035 gen_load_fpr64(ctx, fp1, ft);
8036 gen_load_fpr64(ctx, fp2, fr);
a7812ae4
PB
8037 gen_helper_float_nmuladd_ps(fp2, fp0, fp1, fp2);
8038 tcg_temp_free_i64(fp0);
8039 tcg_temp_free_i64(fp1);
b6d96bed 8040 gen_store_fpr64(ctx, fp2, fd);
a7812ae4 8041 tcg_temp_free_i64(fp2);
b6d96bed 8042 }
5a5012ec
TS
8043 opn = "nmadd.ps";
8044 break;
8045 case OPC_NMSUB_S:
b8aa4598 8046 check_cop1x(ctx);
b6d96bed 8047 {
a7812ae4
PB
8048 TCGv_i32 fp0 = tcg_temp_new_i32();
8049 TCGv_i32 fp1 = tcg_temp_new_i32();
8050 TCGv_i32 fp2 = tcg_temp_new_i32();
b6d96bed
TS
8051
8052 gen_load_fpr32(fp0, fs);
8053 gen_load_fpr32(fp1, ft);
8054 gen_load_fpr32(fp2, fr);
a7812ae4
PB
8055 gen_helper_float_nmulsub_s(fp2, fp0, fp1, fp2);
8056 tcg_temp_free_i32(fp0);
8057 tcg_temp_free_i32(fp1);
b6d96bed 8058 gen_store_fpr32(fp2, fd);
a7812ae4 8059 tcg_temp_free_i32(fp2);
b6d96bed 8060 }
5a5012ec
TS
8061 opn = "nmsub.s";
8062 break;
8063 case OPC_NMSUB_D:
b8aa4598
TS
8064 check_cop1x(ctx);
8065 check_cp1_registers(ctx, fd | fs | ft | fr);
b6d96bed 8066 {
a7812ae4
PB
8067 TCGv_i64 fp0 = tcg_temp_new_i64();
8068 TCGv_i64 fp1 = tcg_temp_new_i64();
8069 TCGv_i64 fp2 = tcg_temp_new_i64();
b6d96bed
TS
8070
8071 gen_load_fpr64(ctx, fp0, fs);
8072 gen_load_fpr64(ctx, fp1, ft);
8073 gen_load_fpr64(ctx, fp2, fr);
a7812ae4
PB
8074 gen_helper_float_nmulsub_d(fp2, fp0, fp1, fp2);
8075 tcg_temp_free_i64(fp0);
8076 tcg_temp_free_i64(fp1);
b6d96bed 8077 gen_store_fpr64(ctx, fp2, fd);
a7812ae4 8078 tcg_temp_free_i64(fp2);
b6d96bed 8079 }
5a5012ec
TS
8080 opn = "nmsub.d";
8081 break;
8082 case OPC_NMSUB_PS:
b8aa4598 8083 check_cp1_64bitmode(ctx);
b6d96bed 8084 {
a7812ae4
PB
8085 TCGv_i64 fp0 = tcg_temp_new_i64();
8086 TCGv_i64 fp1 = tcg_temp_new_i64();
8087 TCGv_i64 fp2 = tcg_temp_new_i64();
b6d96bed
TS
8088
8089 gen_load_fpr64(ctx, fp0, fs);
8090 gen_load_fpr64(ctx, fp1, ft);
8091 gen_load_fpr64(ctx, fp2, fr);
a7812ae4
PB
8092 gen_helper_float_nmulsub_ps(fp2, fp0, fp1, fp2);
8093 tcg_temp_free_i64(fp0);
8094 tcg_temp_free_i64(fp1);
b6d96bed 8095 gen_store_fpr64(ctx, fp2, fd);
a7812ae4 8096 tcg_temp_free_i64(fp2);
b6d96bed 8097 }
5a5012ec
TS
8098 opn = "nmsub.ps";
8099 break;
923617a3
TS
8100 default:
8101 MIPS_INVAL(opn);
5a5012ec
TS
8102 generate_exception (ctx, EXCP_RI);
8103 return;
8104 }
2abf314d 8105 (void)opn; /* avoid a compiler warning */
5a5012ec
TS
8106 MIPS_DEBUG("%s %s, %s, %s, %s", opn, fregnames[fd], fregnames[fr],
8107 fregnames[fs], fregnames[ft]);
7a387fff
TS
8108}
8109
26ebe468 8110static void
7db13fae 8111gen_rdhwr (CPUMIPSState *env, DisasContext *ctx, int rt, int rd)
26ebe468
NF
8112{
8113 TCGv t0;
8114
8115 check_insn(env, ctx, ISA_MIPS32R2);
8116 t0 = tcg_temp_new();
8117
8118 switch (rd) {
8119 case 0:
8120 save_cpu_state(ctx, 1);
8121 gen_helper_rdhwr_cpunum(t0);
8122 gen_store_gpr(t0, rt);
8123 break;
8124 case 1:
8125 save_cpu_state(ctx, 1);
8126 gen_helper_rdhwr_synci_step(t0);
8127 gen_store_gpr(t0, rt);
8128 break;
8129 case 2:
8130 save_cpu_state(ctx, 1);
8131 gen_helper_rdhwr_cc(t0);
8132 gen_store_gpr(t0, rt);
8133 break;
8134 case 3:
8135 save_cpu_state(ctx, 1);
8136 gen_helper_rdhwr_ccres(t0);
8137 gen_store_gpr(t0, rt);
8138 break;
8139 case 29:
8140#if defined(CONFIG_USER_ONLY)
7db13fae 8141 tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUMIPSState, tls_value));
26ebe468
NF
8142 gen_store_gpr(t0, rt);
8143 break;
8144#else
8145 /* XXX: Some CPUs implement this in hardware.
8146 Not supported yet. */
8147#endif
8148 default: /* Invalid */
8149 MIPS_INVAL("rdhwr");
8150 generate_exception(ctx, EXCP_RI);
8151 break;
8152 }
8153 tcg_temp_free(t0);
8154}
8155
7db13fae 8156static void handle_delay_slot (CPUMIPSState *env, DisasContext *ctx,
c9602061
NF
8157 int insn_bytes)
8158{
8159 if (ctx->hflags & MIPS_HFLAG_BMASK) {
364d4831 8160 int proc_hflags = ctx->hflags & MIPS_HFLAG_BMASK;
c9602061
NF
8161 /* Branches completion */
8162 ctx->hflags &= ~MIPS_HFLAG_BMASK;
8163 ctx->bstate = BS_BRANCH;
8164 save_cpu_state(ctx, 0);
8165 /* FIXME: Need to clear can_do_io. */
364d4831 8166 switch (proc_hflags & MIPS_HFLAG_BMASK_BASE) {
c9602061
NF
8167 case MIPS_HFLAG_B:
8168 /* unconditional branch */
8169 MIPS_DEBUG("unconditional branch");
364d4831
NF
8170 if (proc_hflags & MIPS_HFLAG_BX) {
8171 tcg_gen_xori_i32(hflags, hflags, MIPS_HFLAG_M16);
8172 }
c9602061
NF
8173 gen_goto_tb(ctx, 0, ctx->btarget);
8174 break;
8175 case MIPS_HFLAG_BL:
8176 /* blikely taken case */
8177 MIPS_DEBUG("blikely branch taken");
8178 gen_goto_tb(ctx, 0, ctx->btarget);
8179 break;
8180 case MIPS_HFLAG_BC:
8181 /* Conditional branch */
8182 MIPS_DEBUG("conditional branch");
8183 {
8184 int l1 = gen_new_label();
8185
8186 tcg_gen_brcondi_tl(TCG_COND_NE, bcond, 0, l1);
8187 gen_goto_tb(ctx, 1, ctx->pc + insn_bytes);
8188 gen_set_label(l1);
8189 gen_goto_tb(ctx, 0, ctx->btarget);
8190 }
8191 break;
8192 case MIPS_HFLAG_BR:
8193 /* unconditional branch to register */
8194 MIPS_DEBUG("branch to register");
3c824109 8195 if (env->insn_flags & (ASE_MIPS16 | ASE_MICROMIPS)) {
364d4831
NF
8196 TCGv t0 = tcg_temp_new();
8197 TCGv_i32 t1 = tcg_temp_new_i32();
8198
8199 tcg_gen_andi_tl(t0, btarget, 0x1);
8200 tcg_gen_trunc_tl_i32(t1, t0);
8201 tcg_temp_free(t0);
8202 tcg_gen_andi_i32(hflags, hflags, ~(uint32_t)MIPS_HFLAG_M16);
8203 tcg_gen_shli_i32(t1, t1, MIPS_HFLAG_M16_SHIFT);
8204 tcg_gen_or_i32(hflags, hflags, t1);
8205 tcg_temp_free_i32(t1);
8206
8207 tcg_gen_andi_tl(cpu_PC, btarget, ~(target_ulong)0x1);
8208 } else {
8209 tcg_gen_mov_tl(cpu_PC, btarget);
8210 }
c9602061
NF
8211 if (ctx->singlestep_enabled) {
8212 save_cpu_state(ctx, 0);
8213 gen_helper_0i(raise_exception, EXCP_DEBUG);
8214 }
8215 tcg_gen_exit_tb(0);
8216 break;
8217 default:
8218 MIPS_DEBUG("unknown branch");
8219 break;
8220 }
8221 }
8222}
8223
7a387fff 8224/* ISA extensions (ASEs) */
6af0bf9c 8225/* MIPS16 extension to MIPS32 */
6ea219d0
NF
8226
8227/* MIPS16 major opcodes */
8228enum {
8229 M16_OPC_ADDIUSP = 0x00,
8230 M16_OPC_ADDIUPC = 0x01,
8231 M16_OPC_B = 0x02,
8232 M16_OPC_JAL = 0x03,
8233 M16_OPC_BEQZ = 0x04,
8234 M16_OPC_BNEQZ = 0x05,
8235 M16_OPC_SHIFT = 0x06,
8236 M16_OPC_LD = 0x07,
8237 M16_OPC_RRIA = 0x08,
8238 M16_OPC_ADDIU8 = 0x09,
8239 M16_OPC_SLTI = 0x0a,
8240 M16_OPC_SLTIU = 0x0b,
8241 M16_OPC_I8 = 0x0c,
8242 M16_OPC_LI = 0x0d,
8243 M16_OPC_CMPI = 0x0e,
8244 M16_OPC_SD = 0x0f,
8245 M16_OPC_LB = 0x10,
8246 M16_OPC_LH = 0x11,
8247 M16_OPC_LWSP = 0x12,
8248 M16_OPC_LW = 0x13,
8249 M16_OPC_LBU = 0x14,
8250 M16_OPC_LHU = 0x15,
8251 M16_OPC_LWPC = 0x16,
8252 M16_OPC_LWU = 0x17,
8253 M16_OPC_SB = 0x18,
8254 M16_OPC_SH = 0x19,
8255 M16_OPC_SWSP = 0x1a,
8256 M16_OPC_SW = 0x1b,
8257 M16_OPC_RRR = 0x1c,
8258 M16_OPC_RR = 0x1d,
8259 M16_OPC_EXTEND = 0x1e,
8260 M16_OPC_I64 = 0x1f
8261};
8262
8263/* I8 funct field */
8264enum {
8265 I8_BTEQZ = 0x0,
8266 I8_BTNEZ = 0x1,
8267 I8_SWRASP = 0x2,
8268 I8_ADJSP = 0x3,
8269 I8_SVRS = 0x4,
8270 I8_MOV32R = 0x5,
8271 I8_MOVR32 = 0x7
8272};
8273
8274/* RRR f field */
8275enum {
8276 RRR_DADDU = 0x0,
8277 RRR_ADDU = 0x1,
8278 RRR_DSUBU = 0x2,
8279 RRR_SUBU = 0x3
8280};
8281
8282/* RR funct field */
8283enum {
8284 RR_JR = 0x00,
8285 RR_SDBBP = 0x01,
8286 RR_SLT = 0x02,
8287 RR_SLTU = 0x03,
8288 RR_SLLV = 0x04,
8289 RR_BREAK = 0x05,
8290 RR_SRLV = 0x06,
8291 RR_SRAV = 0x07,
8292 RR_DSRL = 0x08,
8293 RR_CMP = 0x0a,
8294 RR_NEG = 0x0b,
8295 RR_AND = 0x0c,
8296 RR_OR = 0x0d,
8297 RR_XOR = 0x0e,
8298 RR_NOT = 0x0f,
8299 RR_MFHI = 0x10,
8300 RR_CNVT = 0x11,
8301 RR_MFLO = 0x12,
8302 RR_DSRA = 0x13,
8303 RR_DSLLV = 0x14,
8304 RR_DSRLV = 0x16,
8305 RR_DSRAV = 0x17,
8306 RR_MULT = 0x18,
8307 RR_MULTU = 0x19,
8308 RR_DIV = 0x1a,
8309 RR_DIVU = 0x1b,
8310 RR_DMULT = 0x1c,
8311 RR_DMULTU = 0x1d,
8312 RR_DDIV = 0x1e,
8313 RR_DDIVU = 0x1f
8314};
8315
8316/* I64 funct field */
8317enum {
8318 I64_LDSP = 0x0,
8319 I64_SDSP = 0x1,
8320 I64_SDRASP = 0x2,
8321 I64_DADJSP = 0x3,
8322 I64_LDPC = 0x4,
364d4831 8323 I64_DADDIU5 = 0x5,
6ea219d0
NF
8324 I64_DADDIUPC = 0x6,
8325 I64_DADDIUSP = 0x7
8326};
8327
8328/* RR ry field for CNVT */
8329enum {
8330 RR_RY_CNVT_ZEB = 0x0,
8331 RR_RY_CNVT_ZEH = 0x1,
8332 RR_RY_CNVT_ZEW = 0x2,
8333 RR_RY_CNVT_SEB = 0x4,
8334 RR_RY_CNVT_SEH = 0x5,
8335 RR_RY_CNVT_SEW = 0x6,
8336};
8337
364d4831
NF
8338static int xlat (int r)
8339{
8340 static int map[] = { 16, 17, 2, 3, 4, 5, 6, 7 };
8341
8342 return map[r];
8343}
8344
8345static void gen_mips16_save (DisasContext *ctx,
8346 int xsregs, int aregs,
8347 int do_ra, int do_s0, int do_s1,
8348 int framesize)
8349{
8350 TCGv t0 = tcg_temp_new();
8351 TCGv t1 = tcg_temp_new();
8352 int args, astatic;
8353
8354 switch (aregs) {
8355 case 0:
8356 case 1:
8357 case 2:
8358 case 3:
8359 case 11:
8360 args = 0;
8361 break;
8362 case 4:
8363 case 5:
8364 case 6:
8365 case 7:
8366 args = 1;
8367 break;
8368 case 8:
8369 case 9:
8370 case 10:
8371 args = 2;
8372 break;
8373 case 12:
8374 case 13:
8375 args = 3;
8376 break;
8377 case 14:
8378 args = 4;
8379 break;
8380 default:
8381 generate_exception(ctx, EXCP_RI);
8382 return;
8383 }
8384
8385 switch (args) {
8386 case 4:
8387 gen_base_offset_addr(ctx, t0, 29, 12);
8388 gen_load_gpr(t1, 7);
5c13fdfd 8389 op_st_sw(t1, t0, ctx);
364d4831
NF
8390 /* Fall through */
8391 case 3:
8392 gen_base_offset_addr(ctx, t0, 29, 8);
8393 gen_load_gpr(t1, 6);
5c13fdfd 8394 op_st_sw(t1, t0, ctx);
364d4831
NF
8395 /* Fall through */
8396 case 2:
8397 gen_base_offset_addr(ctx, t0, 29, 4);
8398 gen_load_gpr(t1, 5);
5c13fdfd 8399 op_st_sw(t1, t0, ctx);
364d4831
NF
8400 /* Fall through */
8401 case 1:
8402 gen_base_offset_addr(ctx, t0, 29, 0);
8403 gen_load_gpr(t1, 4);
5c13fdfd 8404 op_st_sw(t1, t0, ctx);
364d4831
NF
8405 }
8406
8407 gen_load_gpr(t0, 29);
8408
8409#define DECR_AND_STORE(reg) do { \
8410 tcg_gen_subi_tl(t0, t0, 4); \
8411 gen_load_gpr(t1, reg); \
5c13fdfd 8412 op_st_sw(t1, t0, ctx); \
364d4831
NF
8413 } while (0)
8414
8415 if (do_ra) {
8416 DECR_AND_STORE(31);
8417 }
8418
8419 switch (xsregs) {
8420 case 7:
8421 DECR_AND_STORE(30);
8422 /* Fall through */
8423 case 6:
8424 DECR_AND_STORE(23);
8425 /* Fall through */
8426 case 5:
8427 DECR_AND_STORE(22);
8428 /* Fall through */
8429 case 4:
8430 DECR_AND_STORE(21);
8431 /* Fall through */
8432 case 3:
8433 DECR_AND_STORE(20);
8434 /* Fall through */
8435 case 2:
8436 DECR_AND_STORE(19);
8437 /* Fall through */
8438 case 1:
8439 DECR_AND_STORE(18);
8440 }
8441
8442 if (do_s1) {
8443 DECR_AND_STORE(17);
8444 }
8445 if (do_s0) {
8446 DECR_AND_STORE(16);
8447 }
8448
8449 switch (aregs) {
8450 case 0:
8451 case 4:
8452 case 8:
8453 case 12:
8454 case 14:
8455 astatic = 0;
8456 break;
8457 case 1:
8458 case 5:
8459 case 9:
8460 case 13:
8461 astatic = 1;
8462 break;
8463 case 2:
8464 case 6:
8465 case 10:
8466 astatic = 2;
8467 break;
8468 case 3:
8469 case 7:
8470 astatic = 3;
8471 break;
8472 case 11:
8473 astatic = 4;
8474 break;
8475 default:
8476 generate_exception(ctx, EXCP_RI);
8477 return;
8478 }
8479
8480 if (astatic > 0) {
8481 DECR_AND_STORE(7);
8482 if (astatic > 1) {
8483 DECR_AND_STORE(6);
8484 if (astatic > 2) {
8485 DECR_AND_STORE(5);
8486 if (astatic > 3) {
8487 DECR_AND_STORE(4);
8488 }
8489 }
8490 }
8491 }
8492#undef DECR_AND_STORE
8493
8494 tcg_gen_subi_tl(cpu_gpr[29], cpu_gpr[29], framesize);
8495 tcg_temp_free(t0);
8496 tcg_temp_free(t1);
8497}
8498
8499static void gen_mips16_restore (DisasContext *ctx,
8500 int xsregs, int aregs,
8501 int do_ra, int do_s0, int do_s1,
8502 int framesize)
8503{
8504 int astatic;
8505 TCGv t0 = tcg_temp_new();
8506 TCGv t1 = tcg_temp_new();
8507
8508 tcg_gen_addi_tl(t0, cpu_gpr[29], framesize);
8509
8510#define DECR_AND_LOAD(reg) do { \
8511 tcg_gen_subi_tl(t0, t0, 4); \
5c13fdfd 8512 op_ld_lw(t1, t0, ctx); \
364d4831
NF
8513 gen_store_gpr(t1, reg); \
8514 } while (0)
8515
8516 if (do_ra) {
8517 DECR_AND_LOAD(31);
8518 }
8519
8520 switch (xsregs) {
8521 case 7:
8522 DECR_AND_LOAD(30);
8523 /* Fall through */
8524 case 6:
8525 DECR_AND_LOAD(23);
8526 /* Fall through */
8527 case 5:
8528 DECR_AND_LOAD(22);
8529 /* Fall through */
8530 case 4:
8531 DECR_AND_LOAD(21);
8532 /* Fall through */
8533 case 3:
8534 DECR_AND_LOAD(20);
8535 /* Fall through */
8536 case 2:
8537 DECR_AND_LOAD(19);
8538 /* Fall through */
8539 case 1:
8540 DECR_AND_LOAD(18);
8541 }
8542
8543 if (do_s1) {
8544 DECR_AND_LOAD(17);
8545 }
8546 if (do_s0) {
8547 DECR_AND_LOAD(16);
8548 }
8549
8550 switch (aregs) {
8551 case 0:
8552 case 4:
8553 case 8:
8554 case 12:
8555 case 14:
8556 astatic = 0;
8557 break;
8558 case 1:
8559 case 5:
8560 case 9:
8561 case 13:
8562 astatic = 1;
8563 break;
8564 case 2:
8565 case 6:
8566 case 10:
8567 astatic = 2;
8568 break;
8569 case 3:
8570 case 7:
8571 astatic = 3;
8572 break;
8573 case 11:
8574 astatic = 4;
8575 break;
8576 default:
8577 generate_exception(ctx, EXCP_RI);
8578 return;
8579 }
8580
8581 if (astatic > 0) {
8582 DECR_AND_LOAD(7);
8583 if (astatic > 1) {
8584 DECR_AND_LOAD(6);
8585 if (astatic > 2) {
8586 DECR_AND_LOAD(5);
8587 if (astatic > 3) {
8588 DECR_AND_LOAD(4);
8589 }
8590 }
8591 }
8592 }
8593#undef DECR_AND_LOAD
8594
8595 tcg_gen_addi_tl(cpu_gpr[29], cpu_gpr[29], framesize);
8596 tcg_temp_free(t0);
8597 tcg_temp_free(t1);
8598}
8599
8600static void gen_addiupc (DisasContext *ctx, int rx, int imm,
8601 int is_64_bit, int extended)
8602{
8603 TCGv t0;
8604
8605 if (extended && (ctx->hflags & MIPS_HFLAG_BMASK)) {
8606 generate_exception(ctx, EXCP_RI);
8607 return;
8608 }
8609
8610 t0 = tcg_temp_new();
8611
8612 tcg_gen_movi_tl(t0, pc_relative_pc(ctx));
8613 tcg_gen_addi_tl(cpu_gpr[rx], t0, imm);
8614 if (!is_64_bit) {
8615 tcg_gen_ext32s_tl(cpu_gpr[rx], cpu_gpr[rx]);
8616 }
8617
8618 tcg_temp_free(t0);
8619}
8620
8621#if defined(TARGET_MIPS64)
7db13fae 8622static void decode_i64_mips16 (CPUMIPSState *env, DisasContext *ctx,
364d4831
NF
8623 int ry, int funct, int16_t offset,
8624 int extended)
8625{
8626 switch (funct) {
8627 case I64_LDSP:
8628 check_mips_64(ctx);
8629 offset = extended ? offset : offset << 3;
afa88c3a 8630 gen_ld(env, ctx, OPC_LD, ry, 29, offset);
364d4831
NF
8631 break;
8632 case I64_SDSP:
8633 check_mips_64(ctx);
8634 offset = extended ? offset : offset << 3;
5c13fdfd 8635 gen_st(ctx, OPC_SD, ry, 29, offset);
364d4831
NF
8636 break;
8637 case I64_SDRASP:
8638 check_mips_64(ctx);
8639 offset = extended ? offset : (ctx->opcode & 0xff) << 3;
5c13fdfd 8640 gen_st(ctx, OPC_SD, 31, 29, offset);
364d4831
NF
8641 break;
8642 case I64_DADJSP:
8643 check_mips_64(ctx);
8644 offset = extended ? offset : ((int8_t)ctx->opcode) << 3;
8645 gen_arith_imm(env, ctx, OPC_DADDIU, 29, 29, offset);
8646 break;
8647 case I64_LDPC:
8648 if (extended && (ctx->hflags & MIPS_HFLAG_BMASK)) {
8649 generate_exception(ctx, EXCP_RI);
8650 } else {
8651 offset = extended ? offset : offset << 3;
afa88c3a 8652 gen_ld(env, ctx, OPC_LDPC, ry, 0, offset);
364d4831
NF
8653 }
8654 break;
8655 case I64_DADDIU5:
8656 check_mips_64(ctx);
8657 offset = extended ? offset : ((int8_t)(offset << 3)) >> 3;
8658 gen_arith_imm(env, ctx, OPC_DADDIU, ry, ry, offset);
8659 break;
8660 case I64_DADDIUPC:
8661 check_mips_64(ctx);
8662 offset = extended ? offset : offset << 2;
8663 gen_addiupc(ctx, ry, offset, 1, extended);
8664 break;
8665 case I64_DADDIUSP:
8666 check_mips_64(ctx);
8667 offset = extended ? offset : offset << 2;
8668 gen_arith_imm(env, ctx, OPC_DADDIU, ry, 29, offset);
8669 break;
8670 }
8671}
8672#endif
8673
7db13fae 8674static int decode_extended_mips16_opc (CPUMIPSState *env, DisasContext *ctx,
364d4831
NF
8675 int *is_branch)
8676{
8677 int extend = lduw_code(ctx->pc + 2);
8678 int op, rx, ry, funct, sa;
8679 int16_t imm, offset;
8680
8681 ctx->opcode = (ctx->opcode << 16) | extend;
8682 op = (ctx->opcode >> 11) & 0x1f;
8683 sa = (ctx->opcode >> 22) & 0x1f;
8684 funct = (ctx->opcode >> 8) & 0x7;
8685 rx = xlat((ctx->opcode >> 8) & 0x7);
8686 ry = xlat((ctx->opcode >> 5) & 0x7);
8687 offset = imm = (int16_t) (((ctx->opcode >> 16) & 0x1f) << 11
8688 | ((ctx->opcode >> 21) & 0x3f) << 5
8689 | (ctx->opcode & 0x1f));
8690
8691 /* The extended opcodes cleverly reuse the opcodes from their 16-bit
8692 counterparts. */
8693 switch (op) {
8694 case M16_OPC_ADDIUSP:
8695 gen_arith_imm(env, ctx, OPC_ADDIU, rx, 29, imm);
8696 break;
8697 case M16_OPC_ADDIUPC:
8698 gen_addiupc(ctx, rx, imm, 0, 1);
8699 break;
8700 case M16_OPC_B:
8701 gen_compute_branch(ctx, OPC_BEQ, 4, 0, 0, offset << 1);
8702 /* No delay slot, so just process as a normal instruction */
8703 break;
8704 case M16_OPC_BEQZ:
8705 gen_compute_branch(ctx, OPC_BEQ, 4, rx, 0, offset << 1);
8706 /* No delay slot, so just process as a normal instruction */
8707 break;
8708 case M16_OPC_BNEQZ:
8709 gen_compute_branch(ctx, OPC_BNE, 4, rx, 0, offset << 1);
8710 /* No delay slot, so just process as a normal instruction */
8711 break;
8712 case M16_OPC_SHIFT:
8713 switch (ctx->opcode & 0x3) {
8714 case 0x0:
8715 gen_shift_imm(env, ctx, OPC_SLL, rx, ry, sa);
8716 break;
8717 case 0x1:
8718#if defined(TARGET_MIPS64)
8719 check_mips_64(ctx);
8720 gen_shift_imm(env, ctx, OPC_DSLL, rx, ry, sa);
8721#else
8722 generate_exception(ctx, EXCP_RI);
8723#endif
8724 break;
8725 case 0x2:
8726 gen_shift_imm(env, ctx, OPC_SRL, rx, ry, sa);
8727 break;
8728 case 0x3:
8729 gen_shift_imm(env, ctx, OPC_SRA, rx, ry, sa);
8730 break;
8731 }
8732 break;
8733#if defined(TARGET_MIPS64)
8734 case M16_OPC_LD:
8735 check_mips_64(ctx);
afa88c3a 8736 gen_ld(env, ctx, OPC_LD, ry, rx, offset);
364d4831
NF
8737 break;
8738#endif
8739 case M16_OPC_RRIA:
8740 imm = ctx->opcode & 0xf;
8741 imm = imm | ((ctx->opcode >> 20) & 0x7f) << 4;
8742 imm = imm | ((ctx->opcode >> 16) & 0xf) << 11;
8743 imm = (int16_t) (imm << 1) >> 1;
8744 if ((ctx->opcode >> 4) & 0x1) {
8745#if defined(TARGET_MIPS64)
8746 check_mips_64(ctx);
8747 gen_arith_imm(env, ctx, OPC_DADDIU, ry, rx, imm);
8748#else
8749 generate_exception(ctx, EXCP_RI);
8750#endif
8751 } else {
8752 gen_arith_imm(env, ctx, OPC_ADDIU, ry, rx, imm);
8753 }
8754 break;
8755 case M16_OPC_ADDIU8:
8756 gen_arith_imm(env, ctx, OPC_ADDIU, rx, rx, imm);
8757 break;
8758 case M16_OPC_SLTI:
8759 gen_slt_imm(env, OPC_SLTI, 24, rx, imm);
8760 break;
8761 case M16_OPC_SLTIU:
8762 gen_slt_imm(env, OPC_SLTIU, 24, rx, imm);
8763 break;
8764 case M16_OPC_I8:
8765 switch (funct) {
8766 case I8_BTEQZ:
8767 gen_compute_branch(ctx, OPC_BEQ, 4, 24, 0, offset << 1);
8768 break;
8769 case I8_BTNEZ:
8770 gen_compute_branch(ctx, OPC_BNE, 4, 24, 0, offset << 1);
8771 break;
8772 case I8_SWRASP:
5c13fdfd 8773 gen_st(ctx, OPC_SW, 31, 29, imm);
364d4831
NF
8774 break;
8775 case I8_ADJSP:
8776 gen_arith_imm(env, ctx, OPC_ADDIU, 29, 29, imm);
8777 break;
8778 case I8_SVRS:
8779 {
8780 int xsregs = (ctx->opcode >> 24) & 0x7;
8781 int aregs = (ctx->opcode >> 16) & 0xf;
8782 int do_ra = (ctx->opcode >> 6) & 0x1;
8783 int do_s0 = (ctx->opcode >> 5) & 0x1;
8784 int do_s1 = (ctx->opcode >> 4) & 0x1;
8785 int framesize = (((ctx->opcode >> 20) & 0xf) << 4
8786 | (ctx->opcode & 0xf)) << 3;
8787
8788 if (ctx->opcode & (1 << 7)) {
8789 gen_mips16_save(ctx, xsregs, aregs,
8790 do_ra, do_s0, do_s1,
8791 framesize);
8792 } else {
8793 gen_mips16_restore(ctx, xsregs, aregs,
8794 do_ra, do_s0, do_s1,
8795 framesize);
8796 }
8797 }
8798 break;
8799 default:
8800 generate_exception(ctx, EXCP_RI);
8801 break;
8802 }
8803 break;
8804 case M16_OPC_LI:
8805 tcg_gen_movi_tl(cpu_gpr[rx], (uint16_t) imm);
8806 break;
8807 case M16_OPC_CMPI:
8808 tcg_gen_xori_tl(cpu_gpr[24], cpu_gpr[rx], (uint16_t) imm);
8809 break;
8810#if defined(TARGET_MIPS64)
8811 case M16_OPC_SD:
5c13fdfd 8812 gen_st(ctx, OPC_SD, ry, rx, offset);
364d4831
NF
8813 break;
8814#endif
8815 case M16_OPC_LB:
afa88c3a 8816 gen_ld(env, ctx, OPC_LB, ry, rx, offset);
364d4831
NF
8817 break;
8818 case M16_OPC_LH:
afa88c3a 8819 gen_ld(env, ctx, OPC_LH, ry, rx, offset);
364d4831
NF
8820 break;
8821 case M16_OPC_LWSP:
afa88c3a 8822 gen_ld(env, ctx, OPC_LW, rx, 29, offset);
364d4831
NF
8823 break;
8824 case M16_OPC_LW:
afa88c3a 8825 gen_ld(env, ctx, OPC_LW, ry, rx, offset);
364d4831
NF
8826 break;
8827 case M16_OPC_LBU:
afa88c3a 8828 gen_ld(env, ctx, OPC_LBU, ry, rx, offset);
364d4831
NF
8829 break;
8830 case M16_OPC_LHU:
afa88c3a 8831 gen_ld(env, ctx, OPC_LHU, ry, rx, offset);
364d4831
NF
8832 break;
8833 case M16_OPC_LWPC:
afa88c3a 8834 gen_ld(env, ctx, OPC_LWPC, rx, 0, offset);
364d4831
NF
8835 break;
8836#if defined(TARGET_MIPS64)
8837 case M16_OPC_LWU:
afa88c3a 8838 gen_ld(env, ctx, OPC_LWU, ry, rx, offset);
364d4831
NF
8839 break;
8840#endif
8841 case M16_OPC_SB:
5c13fdfd 8842 gen_st(ctx, OPC_SB, ry, rx, offset);
364d4831
NF
8843 break;
8844 case M16_OPC_SH:
5c13fdfd 8845 gen_st(ctx, OPC_SH, ry, rx, offset);
364d4831
NF
8846 break;
8847 case M16_OPC_SWSP:
5c13fdfd 8848 gen_st(ctx, OPC_SW, rx, 29, offset);
364d4831
NF
8849 break;
8850 case M16_OPC_SW:
5c13fdfd 8851 gen_st(ctx, OPC_SW, ry, rx, offset);
364d4831
NF
8852 break;
8853#if defined(TARGET_MIPS64)
8854 case M16_OPC_I64:
8855 decode_i64_mips16(env, ctx, ry, funct, offset, 1);
8856 break;
8857#endif
8858 default:
8859 generate_exception(ctx, EXCP_RI);
8860 break;
8861 }
8862
8863 return 4;
8864}
8865
7db13fae 8866static int decode_mips16_opc (CPUMIPSState *env, DisasContext *ctx,
364d4831
NF
8867 int *is_branch)
8868{
8869 int rx, ry;
8870 int sa;
8871 int op, cnvt_op, op1, offset;
8872 int funct;
8873 int n_bytes;
8874
8875 op = (ctx->opcode >> 11) & 0x1f;
8876 sa = (ctx->opcode >> 2) & 0x7;
8877 sa = sa == 0 ? 8 : sa;
8878 rx = xlat((ctx->opcode >> 8) & 0x7);
8879 cnvt_op = (ctx->opcode >> 5) & 0x7;
8880 ry = xlat((ctx->opcode >> 5) & 0x7);
8881 op1 = offset = ctx->opcode & 0x1f;
8882
8883 n_bytes = 2;
8884
8885 switch (op) {
8886 case M16_OPC_ADDIUSP:
8887 {
8888 int16_t imm = ((uint8_t) ctx->opcode) << 2;
8889
8890 gen_arith_imm(env, ctx, OPC_ADDIU, rx, 29, imm);
8891 }
8892 break;
8893 case M16_OPC_ADDIUPC:
8894 gen_addiupc(ctx, rx, ((uint8_t) ctx->opcode) << 2, 0, 0);
8895 break;
8896 case M16_OPC_B:
8897 offset = (ctx->opcode & 0x7ff) << 1;
8898 offset = (int16_t)(offset << 4) >> 4;
8899 gen_compute_branch(ctx, OPC_BEQ, 2, 0, 0, offset);
8900 /* No delay slot, so just process as a normal instruction */
8901 break;
8902 case M16_OPC_JAL:
8903 offset = lduw_code(ctx->pc + 2);
8904 offset = (((ctx->opcode & 0x1f) << 21)
8905 | ((ctx->opcode >> 5) & 0x1f) << 16
8906 | offset) << 2;
620e48f6 8907 op = ((ctx->opcode >> 10) & 0x1) ? OPC_JALXS : OPC_JALS;
364d4831
NF
8908 gen_compute_branch(ctx, op, 4, rx, ry, offset);
8909 n_bytes = 4;
8910 *is_branch = 1;
8911 break;
8912 case M16_OPC_BEQZ:
8913 gen_compute_branch(ctx, OPC_BEQ, 2, rx, 0, ((int8_t)ctx->opcode) << 1);
8914 /* No delay slot, so just process as a normal instruction */
8915 break;
8916 case M16_OPC_BNEQZ:
8917 gen_compute_branch(ctx, OPC_BNE, 2, rx, 0, ((int8_t)ctx->opcode) << 1);
8918 /* No delay slot, so just process as a normal instruction */
8919 break;
8920 case M16_OPC_SHIFT:
8921 switch (ctx->opcode & 0x3) {
8922 case 0x0:
8923 gen_shift_imm(env, ctx, OPC_SLL, rx, ry, sa);
8924 break;
8925 case 0x1:
8926#if defined(TARGET_MIPS64)
8927 check_mips_64(ctx);
8928 gen_shift_imm(env, ctx, OPC_DSLL, rx, ry, sa);
8929#else
8930 generate_exception(ctx, EXCP_RI);
8931#endif
8932 break;
8933 case 0x2:
8934 gen_shift_imm(env, ctx, OPC_SRL, rx, ry, sa);
8935 break;
8936 case 0x3:
8937 gen_shift_imm(env, ctx, OPC_SRA, rx, ry, sa);
8938 break;
8939 }
8940 break;
8941#if defined(TARGET_MIPS64)
8942 case M16_OPC_LD:
8943 check_mips_64(ctx);
afa88c3a 8944 gen_ld(env, ctx, OPC_LD, ry, rx, offset << 3);
364d4831
NF
8945 break;
8946#endif
8947 case M16_OPC_RRIA:
8948 {
8949 int16_t imm = (int8_t)((ctx->opcode & 0xf) << 4) >> 4;
8950
8951 if ((ctx->opcode >> 4) & 1) {
8952#if defined(TARGET_MIPS64)
8953 check_mips_64(ctx);
8954 gen_arith_imm(env, ctx, OPC_DADDIU, ry, rx, imm);
8955#else
8956 generate_exception(ctx, EXCP_RI);
8957#endif
8958 } else {
8959 gen_arith_imm(env, ctx, OPC_ADDIU, ry, rx, imm);
8960 }
8961 }
8962 break;
8963 case M16_OPC_ADDIU8:
8964 {
8965 int16_t imm = (int8_t) ctx->opcode;
8966
8967 gen_arith_imm(env, ctx, OPC_ADDIU, rx, rx, imm);
8968 }
8969 break;
8970 case M16_OPC_SLTI:
8971 {
8972 int16_t imm = (uint8_t) ctx->opcode;
8973
8974 gen_slt_imm(env, OPC_SLTI, 24, rx, imm);
8975 }
8976 break;
8977 case M16_OPC_SLTIU:
8978 {
8979 int16_t imm = (uint8_t) ctx->opcode;
8980
8981 gen_slt_imm(env, OPC_SLTIU, 24, rx, imm);
8982 }
8983 break;
8984 case M16_OPC_I8:
8985 {
8986 int reg32;
8987
8988 funct = (ctx->opcode >> 8) & 0x7;
8989 switch (funct) {
8990 case I8_BTEQZ:
8991 gen_compute_branch(ctx, OPC_BEQ, 2, 24, 0,
8992 ((int8_t)ctx->opcode) << 1);
8993 break;
8994 case I8_BTNEZ:
8995 gen_compute_branch(ctx, OPC_BNE, 2, 24, 0,
8996 ((int8_t)ctx->opcode) << 1);
8997 break;
8998 case I8_SWRASP:
5c13fdfd 8999 gen_st(ctx, OPC_SW, 31, 29, (ctx->opcode & 0xff) << 2);
364d4831
NF
9000 break;
9001 case I8_ADJSP:
9002 gen_arith_imm(env, ctx, OPC_ADDIU, 29, 29,
9003 ((int8_t)ctx->opcode) << 3);
9004 break;
9005 case I8_SVRS:
9006 {
9007 int do_ra = ctx->opcode & (1 << 6);
9008 int do_s0 = ctx->opcode & (1 << 5);
9009 int do_s1 = ctx->opcode & (1 << 4);
9010 int framesize = ctx->opcode & 0xf;
9011
9012 if (framesize == 0) {
9013 framesize = 128;
9014 } else {
9015 framesize = framesize << 3;
9016 }
9017
9018 if (ctx->opcode & (1 << 7)) {
9019 gen_mips16_save(ctx, 0, 0,
9020 do_ra, do_s0, do_s1, framesize);
9021 } else {
9022 gen_mips16_restore(ctx, 0, 0,
9023 do_ra, do_s0, do_s1, framesize);
9024 }
9025 }
9026 break;
9027 case I8_MOV32R:
9028 {
9029 int rz = xlat(ctx->opcode & 0x7);
9030
9031 reg32 = (((ctx->opcode >> 3) & 0x3) << 3) |
9032 ((ctx->opcode >> 5) & 0x7);
9033 gen_arith(env, ctx, OPC_ADDU, reg32, rz, 0);
9034 }
9035 break;
9036 case I8_MOVR32:
9037 reg32 = ctx->opcode & 0x1f;
9038 gen_arith(env, ctx, OPC_ADDU, ry, reg32, 0);
9039 break;
9040 default:
9041 generate_exception(ctx, EXCP_RI);
9042 break;
9043 }
9044 }
9045 break;
9046 case M16_OPC_LI:
9047 {
9048 int16_t imm = (uint8_t) ctx->opcode;
9049
9050 gen_arith_imm(env, ctx, OPC_ADDIU, rx, 0, imm);
9051 }
9052 break;
9053 case M16_OPC_CMPI:
9054 {
9055 int16_t imm = (uint8_t) ctx->opcode;
9056
9057 gen_logic_imm(env, OPC_XORI, 24, rx, imm);
9058 }
9059 break;
9060#if defined(TARGET_MIPS64)
9061 case M16_OPC_SD:
9062 check_mips_64(ctx);
5c13fdfd 9063 gen_st(ctx, OPC_SD, ry, rx, offset << 3);
364d4831
NF
9064 break;
9065#endif
9066 case M16_OPC_LB:
afa88c3a 9067 gen_ld(env, ctx, OPC_LB, ry, rx, offset);
364d4831
NF
9068 break;
9069 case M16_OPC_LH:
afa88c3a 9070 gen_ld(env, ctx, OPC_LH, ry, rx, offset << 1);
364d4831
NF
9071 break;
9072 case M16_OPC_LWSP:
afa88c3a 9073 gen_ld(env, ctx, OPC_LW, rx, 29, ((uint8_t)ctx->opcode) << 2);
364d4831
NF
9074 break;
9075 case M16_OPC_LW:
afa88c3a 9076 gen_ld(env, ctx, OPC_LW, ry, rx, offset << 2);
364d4831
NF
9077 break;
9078 case M16_OPC_LBU:
afa88c3a 9079 gen_ld(env, ctx, OPC_LBU, ry, rx, offset);
364d4831
NF
9080 break;
9081 case M16_OPC_LHU:
afa88c3a 9082 gen_ld(env, ctx, OPC_LHU, ry, rx, offset << 1);
364d4831
NF
9083 break;
9084 case M16_OPC_LWPC:
afa88c3a 9085 gen_ld(env, ctx, OPC_LWPC, rx, 0, ((uint8_t)ctx->opcode) << 2);
364d4831
NF
9086 break;
9087#if defined (TARGET_MIPS64)
9088 case M16_OPC_LWU:
9089 check_mips_64(ctx);
afa88c3a 9090 gen_ld(env, ctx, OPC_LWU, ry, rx, offset << 2);
364d4831
NF
9091 break;
9092#endif
9093 case M16_OPC_SB:
5c13fdfd 9094 gen_st(ctx, OPC_SB, ry, rx, offset);
364d4831
NF
9095 break;
9096 case M16_OPC_SH:
5c13fdfd 9097 gen_st(ctx, OPC_SH, ry, rx, offset << 1);
364d4831
NF
9098 break;
9099 case M16_OPC_SWSP:
5c13fdfd 9100 gen_st(ctx, OPC_SW, rx, 29, ((uint8_t)ctx->opcode) << 2);
364d4831
NF
9101 break;
9102 case M16_OPC_SW:
5c13fdfd 9103 gen_st(ctx, OPC_SW, ry, rx, offset << 2);
364d4831
NF
9104 break;
9105 case M16_OPC_RRR:
9106 {
9107 int rz = xlat((ctx->opcode >> 2) & 0x7);
9108 int mips32_op;
9109
9110 switch (ctx->opcode & 0x3) {
9111 case RRR_ADDU:
9112 mips32_op = OPC_ADDU;
9113 break;
9114 case RRR_SUBU:
9115 mips32_op = OPC_SUBU;
9116 break;
9117#if defined(TARGET_MIPS64)
9118 case RRR_DADDU:
9119 mips32_op = OPC_DADDU;
9120 check_mips_64(ctx);
9121 break;
9122 case RRR_DSUBU:
9123 mips32_op = OPC_DSUBU;
9124 check_mips_64(ctx);
9125 break;
9126#endif
9127 default:
9128 generate_exception(ctx, EXCP_RI);
9129 goto done;
9130 }
9131
9132 gen_arith(env, ctx, mips32_op, rz, rx, ry);
9133 done:
9134 ;
9135 }
9136 break;
9137 case M16_OPC_RR:
9138 switch (op1) {
9139 case RR_JR:
9140 {
9141 int nd = (ctx->opcode >> 7) & 0x1;
9142 int link = (ctx->opcode >> 6) & 0x1;
9143 int ra = (ctx->opcode >> 5) & 0x1;
9144
9145 if (link) {
620e48f6 9146 op = nd ? OPC_JALRC : OPC_JALRS;
364d4831
NF
9147 } else {
9148 op = OPC_JR;
9149 }
9150
9151 gen_compute_branch(ctx, op, 2, ra ? 31 : rx, 31, 0);
9152 if (!nd) {
9153 *is_branch = 1;
9154 }
9155 }
9156 break;
9157 case RR_SDBBP:
9158 /* XXX: not clear which exception should be raised
9159 * when in debug mode...
9160 */
9161 check_insn(env, ctx, ISA_MIPS32);
9162 if (!(ctx->hflags & MIPS_HFLAG_DM)) {
9163 generate_exception(ctx, EXCP_DBp);
9164 } else {
9165 generate_exception(ctx, EXCP_DBp);
9166 }
9167 break;
9168 case RR_SLT:
9169 gen_slt(env, OPC_SLT, 24, rx, ry);
9170 break;
9171 case RR_SLTU:
9172 gen_slt(env, OPC_SLTU, 24, rx, ry);
9173 break;
9174 case RR_BREAK:
9175 generate_exception(ctx, EXCP_BREAK);
9176 break;
9177 case RR_SLLV:
9178 gen_shift(env, ctx, OPC_SLLV, ry, rx, ry);
9179 break;
9180 case RR_SRLV:
9181 gen_shift(env, ctx, OPC_SRLV, ry, rx, ry);
9182 break;
9183 case RR_SRAV:
9184 gen_shift(env, ctx, OPC_SRAV, ry, rx, ry);
9185 break;
9186#if defined (TARGET_MIPS64)
9187 case RR_DSRL:
9188 check_mips_64(ctx);
9189 gen_shift_imm(env, ctx, OPC_DSRL, ry, ry, sa);
9190 break;
9191#endif
9192 case RR_CMP:
9193 gen_logic(env, OPC_XOR, 24, rx, ry);
9194 break;
9195 case RR_NEG:
9196 gen_arith(env, ctx, OPC_SUBU, rx, 0, ry);
9197 break;
9198 case RR_AND:
9199 gen_logic(env, OPC_AND, rx, rx, ry);
9200 break;
9201 case RR_OR:
9202 gen_logic(env, OPC_OR, rx, rx, ry);
9203 break;
9204 case RR_XOR:
9205 gen_logic(env, OPC_XOR, rx, rx, ry);
9206 break;
9207 case RR_NOT:
9208 gen_logic(env, OPC_NOR, rx, ry, 0);
9209 break;
9210 case RR_MFHI:
9211 gen_HILO(ctx, OPC_MFHI, rx);
9212 break;
9213 case RR_CNVT:
9214 switch (cnvt_op) {
9215 case RR_RY_CNVT_ZEB:
9216 tcg_gen_ext8u_tl(cpu_gpr[rx], cpu_gpr[rx]);
9217 break;
9218 case RR_RY_CNVT_ZEH:
9219 tcg_gen_ext16u_tl(cpu_gpr[rx], cpu_gpr[rx]);
9220 break;
9221 case RR_RY_CNVT_SEB:
9222 tcg_gen_ext8s_tl(cpu_gpr[rx], cpu_gpr[rx]);
9223 break;
9224 case RR_RY_CNVT_SEH:
9225 tcg_gen_ext16s_tl(cpu_gpr[rx], cpu_gpr[rx]);
9226 break;
9227#if defined (TARGET_MIPS64)
9228 case RR_RY_CNVT_ZEW:
9229 check_mips_64(ctx);
9230 tcg_gen_ext32u_tl(cpu_gpr[rx], cpu_gpr[rx]);
9231 break;
9232 case RR_RY_CNVT_SEW:
9233 check_mips_64(ctx);
9234 tcg_gen_ext32s_tl(cpu_gpr[rx], cpu_gpr[rx]);
9235 break;
9236#endif
9237 default:
9238 generate_exception(ctx, EXCP_RI);
9239 break;
9240 }
9241 break;
9242 case RR_MFLO:
9243 gen_HILO(ctx, OPC_MFLO, rx);
9244 break;
9245#if defined (TARGET_MIPS64)
9246 case RR_DSRA:
9247 check_mips_64(ctx);
9248 gen_shift_imm(env, ctx, OPC_DSRA, ry, ry, sa);
9249 break;
9250 case RR_DSLLV:
9251 check_mips_64(ctx);
9252 gen_shift(env, ctx, OPC_DSLLV, ry, rx, ry);
9253 break;
9254 case RR_DSRLV:
9255 check_mips_64(ctx);
9256 gen_shift(env, ctx, OPC_DSRLV, ry, rx, ry);
9257 break;
9258 case RR_DSRAV:
9259 check_mips_64(ctx);
9260 gen_shift(env, ctx, OPC_DSRAV, ry, rx, ry);
9261 break;
9262#endif
9263 case RR_MULT:
9264 gen_muldiv(ctx, OPC_MULT, rx, ry);
9265 break;
9266 case RR_MULTU:
9267 gen_muldiv(ctx, OPC_MULTU, rx, ry);
9268 break;
9269 case RR_DIV:
9270 gen_muldiv(ctx, OPC_DIV, rx, ry);
9271 break;
9272 case RR_DIVU:
9273 gen_muldiv(ctx, OPC_DIVU, rx, ry);
9274 break;
9275#if defined (TARGET_MIPS64)
9276 case RR_DMULT:
9277 check_mips_64(ctx);
9278 gen_muldiv(ctx, OPC_DMULT, rx, ry);
9279 break;
9280 case RR_DMULTU:
9281 check_mips_64(ctx);
9282 gen_muldiv(ctx, OPC_DMULTU, rx, ry);
9283 break;
9284 case RR_DDIV:
9285 check_mips_64(ctx);
9286 gen_muldiv(ctx, OPC_DDIV, rx, ry);
9287 break;
9288 case RR_DDIVU:
9289 check_mips_64(ctx);
9290 gen_muldiv(ctx, OPC_DDIVU, rx, ry);
9291 break;
9292#endif
9293 default:
9294 generate_exception(ctx, EXCP_RI);
9295 break;
9296 }
9297 break;
9298 case M16_OPC_EXTEND:
9299 decode_extended_mips16_opc(env, ctx, is_branch);
9300 n_bytes = 4;
9301 break;
9302#if defined(TARGET_MIPS64)
9303 case M16_OPC_I64:
9304 funct = (ctx->opcode >> 8) & 0x7;
9305 decode_i64_mips16(env, ctx, ry, funct, offset, 0);
9306 break;
9307#endif
9308 default:
9309 generate_exception(ctx, EXCP_RI);
9310 break;
9311 }
9312
9313 return n_bytes;
9314}
9315
3c824109 9316/* microMIPS extension to MIPS32 */
6af0bf9c 9317
3c824109 9318/* microMIPS32 major opcodes */
6af0bf9c 9319
3c824109
NF
9320enum {
9321 POOL32A = 0x00,
9322 POOL16A = 0x01,
9323 LBU16 = 0x02,
9324 MOVE16 = 0x03,
9325 ADDI32 = 0x04,
9326 LBU32 = 0x05,
9327 SB32 = 0x06,
9328 LB32 = 0x07,
9329
9330 POOL32B = 0x08,
9331 POOL16B = 0x09,
9332 LHU16 = 0x0a,
9333 ANDI16 = 0x0b,
9334 ADDIU32 = 0x0c,
9335 LHU32 = 0x0d,
9336 SH32 = 0x0e,
9337 LH32 = 0x0f,
9338
9339 POOL32I = 0x10,
9340 POOL16C = 0x11,
9341 LWSP16 = 0x12,
9342 POOL16D = 0x13,
9343 ORI32 = 0x14,
9344 POOL32F = 0x15,
9345 POOL32S = 0x16,
9346 DADDIU32 = 0x17,
9347
9348 POOL32C = 0x18,
9349 LWGP16 = 0x19,
9350 LW16 = 0x1a,
9351 POOL16E = 0x1b,
9352 XORI32 = 0x1c,
9353 JALS32 = 0x1d,
9354 ADDIUPC = 0x1e,
9355 POOL48A = 0x1f,
9356
9357 /* 0x20 is reserved */
9358 RES_20 = 0x20,
9359 POOL16F = 0x21,
9360 SB16 = 0x22,
9361 BEQZ16 = 0x23,
9362 SLTI32 = 0x24,
9363 BEQ32 = 0x25,
9364 SWC132 = 0x26,
9365 LWC132 = 0x27,
9366
9367 /* 0x28 and 0x29 are reserved */
9368 RES_28 = 0x28,
9369 RES_29 = 0x29,
9370 SH16 = 0x2a,
9371 BNEZ16 = 0x2b,
9372 SLTIU32 = 0x2c,
9373 BNE32 = 0x2d,
9374 SDC132 = 0x2e,
9375 LDC132 = 0x2f,
9376
9377 /* 0x30 and 0x31 are reserved */
9378 RES_30 = 0x30,
9379 RES_31 = 0x31,
9380 SWSP16 = 0x32,
9381 B16 = 0x33,
9382 ANDI32 = 0x34,
9383 J32 = 0x35,
9384 SD32 = 0x36,
9385 LD32 = 0x37,
9386
9387 /* 0x38 and 0x39 are reserved */
9388 RES_38 = 0x38,
9389 RES_39 = 0x39,
9390 SW16 = 0x3a,
9391 LI16 = 0x3b,
9392 JALX32 = 0x3c,
9393 JAL32 = 0x3d,
9394 SW32 = 0x3e,
9395 LW32 = 0x3f
9396};
9397
9398/* POOL32A encoding of minor opcode field */
9399
9400enum {
9401 /* These opcodes are distinguished only by bits 9..6; those bits are
9402 * what are recorded below. */
9403 SLL32 = 0x0,
9404 SRL32 = 0x1,
9405 SRA = 0x2,
9406 ROTR = 0x3,
9407
9408 SLLV = 0x0,
9409 SRLV = 0x1,
9410 SRAV = 0x2,
9411 ROTRV = 0x3,
9412 ADD = 0x4,
9413 ADDU32 = 0x5,
9414 SUB = 0x6,
9415 SUBU32 = 0x7,
9416 MUL = 0x8,
9417 AND = 0x9,
9418 OR32 = 0xa,
9419 NOR = 0xb,
9420 XOR32 = 0xc,
9421 SLT = 0xd,
9422 SLTU = 0xe,
9423
9424 MOVN = 0x0,
9425 MOVZ = 0x1,
9426 LWXS = 0x4,
9427
9428 /* The following can be distinguished by their lower 6 bits. */
9429 INS = 0x0c,
9430 EXT = 0x2c,
9431 POOL32AXF = 0x3c
9432};
9433
9434/* POOL32AXF encoding of minor opcode field extension */
9435
9436enum {
9437 /* bits 11..6 */
9438 TEQ = 0x00,
9439 TGE = 0x08,
9440 TGEU = 0x10,
9441 TLT = 0x20,
9442 TLTU = 0x28,
9443 TNE = 0x30,
9444
9445 MFC0 = 0x03,
9446 MTC0 = 0x0b,
9447
9448 /* bits 13..12 for 0x01 */
9449 MFHI_ACC = 0x0,
9450 MFLO_ACC = 0x1,
9451 MTHI_ACC = 0x2,
9452 MTLO_ACC = 0x3,
9453
9454 /* bits 13..12 for 0x2a */
9455 MADD_ACC = 0x0,
9456 MADDU_ACC = 0x1,
9457 MSUB_ACC = 0x2,
9458 MSUBU_ACC = 0x3,
9459
9460 /* bits 13..12 for 0x32 */
9461 MULT_ACC = 0x0,
9462 MULTU_ACC = 0x0,
9463
9464 /* bits 15..12 for 0x2c */
9465 SEB = 0x2,
9466 SEH = 0x3,
9467 CLO = 0x4,
9468 CLZ = 0x5,
9469 RDHWR = 0x6,
9470 WSBH = 0x7,
9471 MULT = 0x8,
9472 MULTU = 0x9,
9473 DIV = 0xa,
9474 DIVU = 0xb,
9475 MADD = 0xc,
9476 MADDU = 0xd,
9477 MSUB = 0xe,
9478 MSUBU = 0xf,
9479
9480 /* bits 15..12 for 0x34 */
9481 MFC2 = 0x4,
9482 MTC2 = 0x5,
9483 MFHC2 = 0x8,
9484 MTHC2 = 0x9,
9485 CFC2 = 0xc,
9486 CTC2 = 0xd,
9487
9488 /* bits 15..12 for 0x3c */
9489 JALR = 0x0,
9490 JR = 0x0, /* alias */
9491 JALR_HB = 0x1,
9492 JALRS = 0x4,
9493 JALRS_HB = 0x5,
9494
9495 /* bits 15..12 for 0x05 */
9496 RDPGPR = 0xe,
9497 WRPGPR = 0xf,
9498
9499 /* bits 15..12 for 0x0d */
9500 TLBP = 0x0,
9501 TLBR = 0x1,
9502 TLBWI = 0x2,
9503 TLBWR = 0x3,
9504 WAIT = 0x9,
9505 IRET = 0xd,
9506 DERET = 0xe,
9507 ERET = 0xf,
9508
9509 /* bits 15..12 for 0x15 */
9510 DMT = 0x0,
9511 DVPE = 0x1,
9512 EMT = 0x2,
9513 EVPE = 0x3,
9514
9515 /* bits 15..12 for 0x1d */
9516 DI = 0x4,
9517 EI = 0x5,
9518
9519 /* bits 15..12 for 0x2d */
9520 SYNC = 0x6,
9521 SYSCALL = 0x8,
9522 SDBBP = 0xd,
9523
9524 /* bits 15..12 for 0x35 */
9525 MFHI32 = 0x0,
9526 MFLO32 = 0x1,
9527 MTHI32 = 0x2,
9528 MTLO32 = 0x3,
9529};
9530
9531/* POOL32B encoding of minor opcode field (bits 15..12) */
9532
9533enum {
9534 LWC2 = 0x0,
9535 LWP = 0x1,
9536 LDP = 0x4,
9537 LWM32 = 0x5,
9538 CACHE = 0x6,
9539 LDM = 0x7,
9540 SWC2 = 0x8,
9541 SWP = 0x9,
9542 SDP = 0xc,
9543 SWM32 = 0xd,
9544 SDM = 0xf
9545};
9546
9547/* POOL32C encoding of minor opcode field (bits 15..12) */
9548
9549enum {
9550 LWL = 0x0,
9551 SWL = 0x8,
9552 LWR = 0x1,
9553 SWR = 0x9,
9554 PREF = 0x2,
9555 /* 0xa is reserved */
9556 LL = 0x3,
9557 SC = 0xb,
9558 LDL = 0x4,
9559 SDL = 0xc,
9560 LDR = 0x5,
9561 SDR = 0xd,
9562 /* 0x6 is reserved */
9563 LWU = 0xe,
9564 LLD = 0x7,
9565 SCD = 0xf
9566};
9567
9568/* POOL32F encoding of minor opcode field (bits 5..0) */
9569
9570enum {
9571 /* These are the bit 7..6 values */
9572 ADD_FMT = 0x0,
9573 MOVN_FMT = 0x0,
9574
9575 SUB_FMT = 0x1,
9576 MOVZ_FMT = 0x1,
9577
9578 MUL_FMT = 0x2,
9579
9580 DIV_FMT = 0x3,
9581
9582 /* These are the bit 8..6 values */
9583 RSQRT2_FMT = 0x0,
9584 MOVF_FMT = 0x0,
9585
9586 LWXC1 = 0x1,
9587 MOVT_FMT = 0x1,
9588
9589 PLL_PS = 0x2,
9590 SWXC1 = 0x2,
9591
9592 PLU_PS = 0x3,
9593 LDXC1 = 0x3,
9594
9595 PUL_PS = 0x4,
9596 SDXC1 = 0x4,
9597 RECIP2_FMT = 0x4,
9598
9599 PUU_PS = 0x5,
9600 LUXC1 = 0x5,
9601
9602 CVT_PS_S = 0x6,
9603 SUXC1 = 0x6,
9604 ADDR_PS = 0x6,
9605 PREFX = 0x6,
9606
9607 MULR_PS = 0x7,
9608
9609 MADD_S = 0x01,
9610 MADD_D = 0x09,
9611 MADD_PS = 0x11,
9612 ALNV_PS = 0x19,
9613 MSUB_S = 0x21,
9614 MSUB_D = 0x29,
9615 MSUB_PS = 0x31,
9616
9617 NMADD_S = 0x02,
9618 NMADD_D = 0x0a,
9619 NMADD_PS = 0x12,
9620 NMSUB_S = 0x22,
9621 NMSUB_D = 0x2a,
9622 NMSUB_PS = 0x32,
9623
9624 POOL32FXF = 0x3b,
9625
9626 CABS_COND_FMT = 0x1c, /* MIPS3D */
9627 C_COND_FMT = 0x3c
9628};
9629
9630/* POOL32Fxf encoding of minor opcode extension field */
9631
9632enum {
9633 CVT_L = 0x04,
9634 RSQRT_FMT = 0x08,
9635 FLOOR_L = 0x0c,
9636 CVT_PW_PS = 0x1c,
9637 CVT_W = 0x24,
9638 SQRT_FMT = 0x28,
9639 FLOOR_W = 0x2c,
9640 CVT_PS_PW = 0x3c,
9641 CFC1 = 0x40,
9642 RECIP_FMT = 0x48,
9643 CEIL_L = 0x4c,
9644 CTC1 = 0x60,
9645 CEIL_W = 0x6c,
9646 MFC1 = 0x80,
9647 CVT_S_PL = 0x84,
9648 TRUNC_L = 0x8c,
9649 MTC1 = 0xa0,
9650 CVT_S_PU = 0xa4,
9651 TRUNC_W = 0xac,
9652 MFHC1 = 0xc0,
9653 ROUND_L = 0xcc,
9654 MTHC1 = 0xe0,
9655 ROUND_W = 0xec,
9656
9657 MOV_FMT = 0x01,
9658 MOVF = 0x05,
9659 ABS_FMT = 0x0d,
9660 RSQRT1_FMT = 0x1d,
9661 MOVT = 0x25,
9662 NEG_FMT = 0x2d,
9663 CVT_D = 0x4d,
9664 RECIP1_FMT = 0x5d,
9665 CVT_S = 0x6d
9666};
9667
9668/* POOL32I encoding of minor opcode field (bits 25..21) */
9669
9670enum {
9671 BLTZ = 0x00,
9672 BLTZAL = 0x01,
9673 BGEZ = 0x02,
9674 BGEZAL = 0x03,
9675 BLEZ = 0x04,
9676 BNEZC = 0x05,
9677 BGTZ = 0x06,
9678 BEQZC = 0x07,
9679 TLTI = 0x08,
9680 TGEI = 0x09,
9681 TLTIU = 0x0a,
9682 TGEIU = 0x0b,
9683 TNEI = 0x0c,
9684 LUI = 0x0d,
9685 TEQI = 0x0e,
9686 SYNCI = 0x10,
9687 BLTZALS = 0x11,
9688 BGEZALS = 0x13,
9689 BC2F = 0x14,
9690 BC2T = 0x15,
9691 BPOSGE64 = 0x1a,
9692 BPOSGE32 = 0x1b,
9693 /* These overlap and are distinguished by bit16 of the instruction */
9694 BC1F = 0x1c,
9695 BC1T = 0x1d,
9696 BC1ANY2F = 0x1c,
9697 BC1ANY2T = 0x1d,
9698 BC1ANY4F = 0x1e,
9699 BC1ANY4T = 0x1f
9700};
9701
9702/* POOL16A encoding of minor opcode field */
9703
9704enum {
9705 ADDU16 = 0x0,
9706 SUBU16 = 0x1
9707};
9708
9709/* POOL16B encoding of minor opcode field */
9710
9711enum {
9712 SLL16 = 0x0,
9713 SRL16 = 0x1
9714};
9715
9716/* POOL16C encoding of minor opcode field */
9717
9718enum {
9719 NOT16 = 0x00,
9720 XOR16 = 0x04,
9721 AND16 = 0x08,
9722 OR16 = 0x0c,
9723 LWM16 = 0x10,
9724 SWM16 = 0x14,
9725 JR16 = 0x18,
9726 JRC16 = 0x1a,
9727 JALR16 = 0x1c,
9728 JALR16S = 0x1e,
9729 MFHI16 = 0x20,
9730 MFLO16 = 0x24,
9731 BREAK16 = 0x28,
9732 SDBBP16 = 0x2c,
9733 JRADDIUSP = 0x30
9734};
9735
9736/* POOL16D encoding of minor opcode field */
9737
9738enum {
9739 ADDIUS5 = 0x0,
9740 ADDIUSP = 0x1
9741};
9742
9743/* POOL16E encoding of minor opcode field */
9744
9745enum {
9746 ADDIUR2 = 0x0,
9747 ADDIUR1SP = 0x1
9748};
9749
9750static int mmreg (int r)
9751{
9752 static const int map[] = { 16, 17, 2, 3, 4, 5, 6, 7 };
9753
9754 return map[r];
9755}
9756
9757/* Used for 16-bit store instructions. */
9758static int mmreg2 (int r)
9759{
9760 static const int map[] = { 0, 17, 2, 3, 4, 5, 6, 7 };
9761
9762 return map[r];
9763}
9764
9765#define uMIPS_RD(op) ((op >> 7) & 0x7)
9766#define uMIPS_RS(op) ((op >> 4) & 0x7)
9767#define uMIPS_RS2(op) uMIPS_RS(op)
9768#define uMIPS_RS1(op) ((op >> 1) & 0x7)
9769#define uMIPS_RD5(op) ((op >> 5) & 0x1f)
9770#define uMIPS_RS5(op) (op & 0x1f)
9771
9772/* Signed immediate */
9773#define SIMM(op, start, width) \
9774 ((int32_t)(((op >> start) & ((~0U) >> (32-width))) \
9775 << (32-width)) \
9776 >> (32-width))
9777/* Zero-extended immediate */
9778#define ZIMM(op, start, width) ((op >> start) & ((~0U) >> (32-width)))
9779
7db13fae 9780static void gen_addiur1sp (CPUMIPSState *env, DisasContext *ctx)
3c824109
NF
9781{
9782 int rd = mmreg(uMIPS_RD(ctx->opcode));
9783
9784 gen_arith_imm(env, ctx, OPC_ADDIU, rd, 29, ((ctx->opcode >> 1) & 0x3f) << 2);
9785}
9786
7db13fae 9787static void gen_addiur2 (CPUMIPSState *env, DisasContext *ctx)
3c824109
NF
9788{
9789 static const int decoded_imm[] = { 1, 4, 8, 12, 16, 20, 24, -1 };
9790 int rd = mmreg(uMIPS_RD(ctx->opcode));
9791 int rs = mmreg(uMIPS_RS(ctx->opcode));
9792
9793 gen_arith_imm(env, ctx, OPC_ADDIU, rd, rs, decoded_imm[ZIMM(ctx->opcode, 1, 3)]);
9794}
9795
7db13fae 9796static void gen_addiusp (CPUMIPSState *env, DisasContext *ctx)
3c824109
NF
9797{
9798 int encoded = ZIMM(ctx->opcode, 1, 9);
9799 int decoded;
9800
9801 if (encoded <= 1) {
9802 decoded = 256 + encoded;
9803 } else if (encoded <= 255) {
9804 decoded = encoded;
9805 } else if (encoded <= 509) {
9806 decoded = encoded - 512;
9807 } else {
9808 decoded = encoded - 768;
9809 }
9810
9811 gen_arith_imm(env, ctx, OPC_ADDIU, 29, 29, decoded << 2);
9812}
9813
7db13fae 9814static void gen_addius5 (CPUMIPSState *env, DisasContext *ctx)
3c824109
NF
9815{
9816 int imm = SIMM(ctx->opcode, 1, 4);
9817 int rd = (ctx->opcode >> 5) & 0x1f;
9818
9819 gen_arith_imm(env, ctx, OPC_ADDIU, rd, rd, imm);
9820}
9821
7db13fae 9822static void gen_andi16 (CPUMIPSState *env, DisasContext *ctx)
3c824109
NF
9823{
9824 static const int decoded_imm[] = { 128, 1, 2, 3, 4, 7, 8, 15, 16,
9825 31, 32, 63, 64, 255, 32768, 65535 };
9826 int rd = mmreg(uMIPS_RD(ctx->opcode));
9827 int rs = mmreg(uMIPS_RS(ctx->opcode));
9828 int encoded = ZIMM(ctx->opcode, 0, 4);
9829
9830 gen_logic_imm(env, OPC_ANDI, rd, rs, decoded_imm[encoded]);
9831}
9832
9833static void gen_ldst_multiple (DisasContext *ctx, uint32_t opc, int reglist,
9834 int base, int16_t offset)
9835{
9836 TCGv t0, t1;
9837 TCGv_i32 t2;
9838
9839 if (ctx->hflags & MIPS_HFLAG_BMASK) {
9840 generate_exception(ctx, EXCP_RI);
9841 return;
9842 }
9843
9844 t0 = tcg_temp_new();
9845
9846 gen_base_offset_addr(ctx, t0, base, offset);
9847
9848 t1 = tcg_const_tl(reglist);
9849 t2 = tcg_const_i32(ctx->mem_idx);
6af0bf9c 9850
3c824109
NF
9851 save_cpu_state(ctx, 1);
9852 switch (opc) {
9853 case LWM32:
9854 gen_helper_lwm(t0, t1, t2);
9855 break;
9856 case SWM32:
9857 gen_helper_swm(t0, t1, t2);
9858 break;
9859#ifdef TARGET_MIPS64
9860 case LDM:
9861 gen_helper_ldm(t0, t1, t2);
9862 break;
9863 case SDM:
9864 gen_helper_sdm(t0, t1, t2);
9865 break;
6af0bf9c 9866#endif
3c824109
NF
9867 }
9868 MIPS_DEBUG("%s, %x, %d(%s)", opn, reglist, offset, regnames[base]);
9869 tcg_temp_free(t0);
33087598 9870 tcg_temp_free(t1);
3c824109
NF
9871 tcg_temp_free_i32(t2);
9872}
6af0bf9c 9873
3c824109 9874
7db13fae 9875static void gen_pool16c_insn (CPUMIPSState *env, DisasContext *ctx, int *is_branch)
6af0bf9c 9876{
3c824109
NF
9877 int rd = mmreg((ctx->opcode >> 3) & 0x7);
9878 int rs = mmreg(ctx->opcode & 0x7);
9879 int opc;
6af0bf9c 9880
3c824109
NF
9881 switch (((ctx->opcode) >> 4) & 0x3f) {
9882 case NOT16 + 0:
9883 case NOT16 + 1:
9884 case NOT16 + 2:
9885 case NOT16 + 3:
9886 gen_logic(env, OPC_NOR, rd, rs, 0);
9887 break;
9888 case XOR16 + 0:
9889 case XOR16 + 1:
9890 case XOR16 + 2:
9891 case XOR16 + 3:
9892 gen_logic(env, OPC_XOR, rd, rd, rs);
9893 break;
9894 case AND16 + 0:
9895 case AND16 + 1:
9896 case AND16 + 2:
9897 case AND16 + 3:
9898 gen_logic(env, OPC_AND, rd, rd, rs);
9899 break;
9900 case OR16 + 0:
9901 case OR16 + 1:
9902 case OR16 + 2:
9903 case OR16 + 3:
9904 gen_logic(env, OPC_OR, rd, rd, rs);
9905 break;
9906 case LWM16 + 0:
9907 case LWM16 + 1:
9908 case LWM16 + 2:
9909 case LWM16 + 3:
9910 {
9911 static const int lwm_convert[] = { 0x11, 0x12, 0x13, 0x14 };
9912 int offset = ZIMM(ctx->opcode, 0, 4);
9913
9914 gen_ldst_multiple(ctx, LWM32, lwm_convert[(ctx->opcode >> 4) & 0x3],
9915 29, offset << 2);
9916 }
9917 break;
9918 case SWM16 + 0:
9919 case SWM16 + 1:
9920 case SWM16 + 2:
9921 case SWM16 + 3:
9922 {
9923 static const int swm_convert[] = { 0x11, 0x12, 0x13, 0x14 };
9924 int offset = ZIMM(ctx->opcode, 0, 4);
9925
9926 gen_ldst_multiple(ctx, SWM32, swm_convert[(ctx->opcode >> 4) & 0x3],
9927 29, offset << 2);
9928 }
9929 break;
9930 case JR16 + 0:
9931 case JR16 + 1:
9932 {
9933 int reg = ctx->opcode & 0x1f;
9934
9935 gen_compute_branch(ctx, OPC_JR, 2, reg, 0, 0);
9936 }
9937 *is_branch = 1;
9938 break;
9939 case JRC16 + 0:
9940 case JRC16 + 1:
9941 {
9942 int reg = ctx->opcode & 0x1f;
9943
9944 gen_compute_branch(ctx, OPC_JR, 2, reg, 0, 0);
9945 /* Let normal delay slot handling in our caller take us
9946 to the branch target. */
9947 }
9948 break;
9949 case JALR16 + 0:
9950 case JALR16 + 1:
9951 opc = OPC_JALR;
9952 goto do_jalr;
9953 case JALR16S + 0:
9954 case JALR16S + 1:
9955 opc = OPC_JALRS;
9956 do_jalr:
9957 {
9958 int reg = ctx->opcode & 0x1f;
9959
9960 gen_compute_branch(ctx, opc, 2, reg, 31, 0);
9961 }
9962 *is_branch = 1;
9963 break;
9964 case MFHI16 + 0:
9965 case MFHI16 + 1:
9966 gen_HILO(ctx, OPC_MFHI, uMIPS_RS5(ctx->opcode));
9967 break;
9968 case MFLO16 + 0:
9969 case MFLO16 + 1:
9970 gen_HILO(ctx, OPC_MFLO, uMIPS_RS5(ctx->opcode));
9971 break;
9972 case BREAK16:
9973 generate_exception(ctx, EXCP_BREAK);
9974 break;
9975 case SDBBP16:
9976 /* XXX: not clear which exception should be raised
9977 * when in debug mode...
9978 */
9979 check_insn(env, ctx, ISA_MIPS32);
9980 if (!(ctx->hflags & MIPS_HFLAG_DM)) {
9981 generate_exception(ctx, EXCP_DBp);
9982 } else {
9983 generate_exception(ctx, EXCP_DBp);
9984 }
9985 break;
9986 case JRADDIUSP + 0:
9987 case JRADDIUSP + 1:
9988 {
9989 int imm = ZIMM(ctx->opcode, 0, 5);
9990
9991 gen_compute_branch(ctx, OPC_JR, 2, 31, 0, 0);
9992 gen_arith_imm(env, ctx, OPC_ADDIU, 29, 29, imm << 2);
9993 /* Let normal delay slot handling in our caller take us
9994 to the branch target. */
9995 }
9996 break;
9997 default:
9998 generate_exception(ctx, EXCP_RI);
9999 break;
10000 }
10001}
10002
10003static void gen_ldxs (DisasContext *ctx, int base, int index, int rd)
10004{
10005 TCGv t0 = tcg_temp_new();
10006 TCGv t1 = tcg_temp_new();
10007
10008 gen_load_gpr(t0, base);
10009
10010 if (index != 0) {
10011 gen_load_gpr(t1, index);
10012 tcg_gen_shli_tl(t1, t1, 2);
10013 gen_op_addr_add(ctx, t0, t1, t0);
10014 }
10015
10016 save_cpu_state(ctx, 0);
5c13fdfd 10017 op_ld_lw(t1, t0, ctx);
3c824109
NF
10018 gen_store_gpr(t1, rd);
10019
10020 tcg_temp_free(t0);
10021 tcg_temp_free(t1);
10022}
10023
10024static void gen_ldst_pair (DisasContext *ctx, uint32_t opc, int rd,
10025 int base, int16_t offset)
10026{
10027 const char *opn = "ldst_pair";
10028 TCGv t0, t1;
10029
10030 if (ctx->hflags & MIPS_HFLAG_BMASK || rd == 31 || rd == base) {
10031 generate_exception(ctx, EXCP_RI);
d796321b
FB
10032 return;
10033 }
10034
3c824109
NF
10035 t0 = tcg_temp_new();
10036 t1 = tcg_temp_new();
8e9ade68 10037
3c824109
NF
10038 gen_base_offset_addr(ctx, t0, base, offset);
10039
10040 switch (opc) {
10041 case LWP:
10042 save_cpu_state(ctx, 0);
5c13fdfd 10043 op_ld_lw(t1, t0, ctx);
3c824109
NF
10044 gen_store_gpr(t1, rd);
10045 tcg_gen_movi_tl(t1, 4);
10046 gen_op_addr_add(ctx, t0, t0, t1);
5c13fdfd 10047 op_ld_lw(t1, t0, ctx);
3c824109
NF
10048 gen_store_gpr(t1, rd+1);
10049 opn = "lwp";
10050 break;
10051 case SWP:
b835e919 10052 save_cpu_state(ctx, 0);
3c824109 10053 gen_load_gpr(t1, rd);
5c13fdfd 10054 op_st_sw(t1, t0, ctx);
3c824109
NF
10055 tcg_gen_movi_tl(t1, 4);
10056 gen_op_addr_add(ctx, t0, t0, t1);
10057 gen_load_gpr(t1, rd+1);
5c13fdfd 10058 op_st_sw(t1, t0, ctx);
3c824109
NF
10059 opn = "swp";
10060 break;
10061#ifdef TARGET_MIPS64
10062 case LDP:
10063 save_cpu_state(ctx, 0);
5c13fdfd 10064 op_ld_ld(t1, t0, ctx);
3c824109
NF
10065 gen_store_gpr(t1, rd);
10066 tcg_gen_movi_tl(t1, 8);
10067 gen_op_addr_add(ctx, t0, t0, t1);
5c13fdfd 10068 op_ld_ld(t1, t0, ctx);
3c824109
NF
10069 gen_store_gpr(t1, rd+1);
10070 opn = "ldp";
10071 break;
10072 case SDP:
b835e919 10073 save_cpu_state(ctx, 0);
3c824109 10074 gen_load_gpr(t1, rd);
5c13fdfd 10075 op_st_sd(t1, t0, ctx);
3c824109
NF
10076 tcg_gen_movi_tl(t1, 8);
10077 gen_op_addr_add(ctx, t0, t0, t1);
10078 gen_load_gpr(t1, rd+1);
5c13fdfd 10079 op_st_sd(t1, t0, ctx);
3c824109
NF
10080 opn = "sdp";
10081 break;
10082#endif
6af0bf9c 10083 }
2abf314d 10084 (void)opn; /* avoid a compiler warning */
3c824109
NF
10085 MIPS_DEBUG("%s, %s, %d(%s)", opn, regnames[rd], offset, regnames[base]);
10086 tcg_temp_free(t0);
10087 tcg_temp_free(t1);
10088}
618b0fe9 10089
7db13fae 10090static void gen_pool32axf (CPUMIPSState *env, DisasContext *ctx, int rt, int rs,
3c824109
NF
10091 int *is_branch)
10092{
10093 int extension = (ctx->opcode >> 6) & 0x3f;
10094 int minor = (ctx->opcode >> 12) & 0xf;
10095 uint32_t mips32_op;
10096
10097 switch (extension) {
10098 case TEQ:
10099 mips32_op = OPC_TEQ;
10100 goto do_trap;
10101 case TGE:
10102 mips32_op = OPC_TGE;
10103 goto do_trap;
10104 case TGEU:
10105 mips32_op = OPC_TGEU;
10106 goto do_trap;
10107 case TLT:
10108 mips32_op = OPC_TLT;
10109 goto do_trap;
10110 case TLTU:
10111 mips32_op = OPC_TLTU;
10112 goto do_trap;
10113 case TNE:
10114 mips32_op = OPC_TNE;
10115 do_trap:
10116 gen_trap(ctx, mips32_op, rs, rt, -1);
10117 break;
10118#ifndef CONFIG_USER_ONLY
10119 case MFC0:
10120 case MFC0 + 32:
10121 if (rt == 0) {
10122 /* Treat as NOP. */
10123 break;
10124 }
10125 gen_mfc0(env, ctx, cpu_gpr[rt], rs, (ctx->opcode >> 11) & 0x7);
10126 break;
10127 case MTC0:
10128 case MTC0 + 32:
10129 {
10130 TCGv t0 = tcg_temp_new();
618b0fe9 10131
3c824109
NF
10132 gen_load_gpr(t0, rt);
10133 gen_mtc0(env, ctx, t0, rs, (ctx->opcode >> 11) & 0x7);
10134 tcg_temp_free(t0);
10135 }
10136 break;
10137#endif
10138 case 0x2c:
10139 switch (minor) {
10140 case SEB:
10141 gen_bshfl(ctx, OPC_SEB, rs, rt);
10142 break;
10143 case SEH:
10144 gen_bshfl(ctx, OPC_SEH, rs, rt);
10145 break;
10146 case CLO:
10147 mips32_op = OPC_CLO;
10148 goto do_cl;
10149 case CLZ:
10150 mips32_op = OPC_CLZ;
10151 do_cl:
10152 check_insn(env, ctx, ISA_MIPS32);
10153 gen_cl(ctx, mips32_op, rt, rs);
10154 break;
10155 case RDHWR:
10156 gen_rdhwr(env, ctx, rt, rs);
10157 break;
10158 case WSBH:
10159 gen_bshfl(ctx, OPC_WSBH, rs, rt);
10160 break;
10161 case MULT:
10162 mips32_op = OPC_MULT;
10163 goto do_muldiv;
10164 case MULTU:
10165 mips32_op = OPC_MULTU;
10166 goto do_muldiv;
10167 case DIV:
10168 mips32_op = OPC_DIV;
10169 goto do_muldiv;
10170 case DIVU:
10171 mips32_op = OPC_DIVU;
10172 goto do_muldiv;
10173 case MADD:
10174 mips32_op = OPC_MADD;
10175 goto do_muldiv;
10176 case MADDU:
10177 mips32_op = OPC_MADDU;
10178 goto do_muldiv;
10179 case MSUB:
10180 mips32_op = OPC_MSUB;
10181 goto do_muldiv;
10182 case MSUBU:
10183 mips32_op = OPC_MSUBU;
10184 do_muldiv:
10185 check_insn(env, ctx, ISA_MIPS32);
10186 gen_muldiv(ctx, mips32_op, rs, rt);
10187 break;
10188 default:
10189 goto pool32axf_invalid;
10190 }
10191 break;
10192 case 0x34:
10193 switch (minor) {
10194 case MFC2:
10195 case MTC2:
10196 case MFHC2:
10197 case MTHC2:
10198 case CFC2:
10199 case CTC2:
10200 generate_exception_err(ctx, EXCP_CpU, 2);
10201 break;
10202 default:
10203 goto pool32axf_invalid;
10204 }
10205 break;
10206 case 0x3c:
10207 switch (minor) {
10208 case JALR:
10209 case JALR_HB:
10210 gen_compute_branch (ctx, OPC_JALR, 4, rs, rt, 0);
10211 *is_branch = 1;
10212 break;
10213 case JALRS:
10214 case JALRS_HB:
10215 gen_compute_branch (ctx, OPC_JALRS, 4, rs, rt, 0);
10216 *is_branch = 1;
10217 break;
10218 default:
10219 goto pool32axf_invalid;
10220 }
10221 break;
10222 case 0x05:
10223 switch (minor) {
10224 case RDPGPR:
10225 check_insn(env, ctx, ISA_MIPS32R2);
10226 gen_load_srsgpr(rt, rs);
10227 break;
10228 case WRPGPR:
10229 check_insn(env, ctx, ISA_MIPS32R2);
10230 gen_store_srsgpr(rt, rs);
10231 break;
10232 default:
10233 goto pool32axf_invalid;
10234 }
10235 break;
10236#ifndef CONFIG_USER_ONLY
10237 case 0x0d:
10238 switch (minor) {
10239 case TLBP:
10240 mips32_op = OPC_TLBP;
10241 goto do_cp0;
10242 case TLBR:
10243 mips32_op = OPC_TLBR;
10244 goto do_cp0;
10245 case TLBWI:
10246 mips32_op = OPC_TLBWI;
10247 goto do_cp0;
10248 case TLBWR:
10249 mips32_op = OPC_TLBWR;
10250 goto do_cp0;
10251 case WAIT:
10252 mips32_op = OPC_WAIT;
10253 goto do_cp0;
10254 case DERET:
10255 mips32_op = OPC_DERET;
10256 goto do_cp0;
10257 case ERET:
10258 mips32_op = OPC_ERET;
10259 do_cp0:
10260 gen_cp0(env, ctx, mips32_op, rt, rs);
10261 break;
10262 default:
10263 goto pool32axf_invalid;
10264 }
10265 break;
10266 case 0x1d:
10267 switch (minor) {
10268 case DI:
10269 {
10270 TCGv t0 = tcg_temp_new();
10271
10272 save_cpu_state(ctx, 1);
10273 gen_helper_di(t0);
10274 gen_store_gpr(t0, rs);
10275 /* Stop translation as we may have switched the execution mode */
10276 ctx->bstate = BS_STOP;
10277 tcg_temp_free(t0);
10278 }
10279 break;
10280 case EI:
10281 {
10282 TCGv t0 = tcg_temp_new();
10283
10284 save_cpu_state(ctx, 1);
10285 gen_helper_ei(t0);
10286 gen_store_gpr(t0, rs);
10287 /* Stop translation as we may have switched the execution mode */
10288 ctx->bstate = BS_STOP;
10289 tcg_temp_free(t0);
10290 }
10291 break;
10292 default:
10293 goto pool32axf_invalid;
10294 }
10295 break;
10296#endif
10297 case 0x2d:
10298 switch (minor) {
10299 case SYNC:
10300 /* NOP */
10301 break;
10302 case SYSCALL:
10303 generate_exception(ctx, EXCP_SYSCALL);
10304 ctx->bstate = BS_STOP;
10305 break;
10306 case SDBBP:
10307 check_insn(env, ctx, ISA_MIPS32);
10308 if (!(ctx->hflags & MIPS_HFLAG_DM)) {
10309 generate_exception(ctx, EXCP_DBp);
10310 } else {
10311 generate_exception(ctx, EXCP_DBp);
10312 }
10313 break;
10314 default:
10315 goto pool32axf_invalid;
10316 }
10317 break;
10318 case 0x35:
10319 switch (minor) {
10320 case MFHI32:
10321 gen_HILO(ctx, OPC_MFHI, rs);
10322 break;
10323 case MFLO32:
10324 gen_HILO(ctx, OPC_MFLO, rs);
10325 break;
10326 case MTHI32:
10327 gen_HILO(ctx, OPC_MTHI, rs);
10328 break;
10329 case MTLO32:
10330 gen_HILO(ctx, OPC_MTLO, rs);
10331 break;
10332 default:
10333 goto pool32axf_invalid;
10334 }
10335 break;
10336 default:
10337 pool32axf_invalid:
10338 MIPS_INVAL("pool32axf");
10339 generate_exception(ctx, EXCP_RI);
10340 break;
10341 }
10342}
10343
10344/* Values for microMIPS fmt field. Variable-width, depending on which
10345 formats the instruction supports. */
10346
10347enum {
10348 FMT_SD_S = 0,
10349 FMT_SD_D = 1,
10350
10351 FMT_SDPS_S = 0,
10352 FMT_SDPS_D = 1,
10353 FMT_SDPS_PS = 2,
10354
10355 FMT_SWL_S = 0,
10356 FMT_SWL_W = 1,
10357 FMT_SWL_L = 2,
10358
10359 FMT_DWL_D = 0,
10360 FMT_DWL_W = 1,
10361 FMT_DWL_L = 2
10362};
10363
7db13fae 10364static void gen_pool32fxf (CPUMIPSState *env, DisasContext *ctx, int rt, int rs)
3c824109
NF
10365{
10366 int extension = (ctx->opcode >> 6) & 0x3ff;
10367 uint32_t mips32_op;
10368
10369#define FLOAT_1BIT_FMT(opc, fmt) (fmt << 8) | opc
10370#define FLOAT_2BIT_FMT(opc, fmt) (fmt << 7) | opc
10371#define COND_FLOAT_MOV(opc, cond) (cond << 7) | opc
10372
10373 switch (extension) {
10374 case FLOAT_1BIT_FMT(CFC1, 0):
10375 mips32_op = OPC_CFC1;
10376 goto do_cp1;
10377 case FLOAT_1BIT_FMT(CTC1, 0):
10378 mips32_op = OPC_CTC1;
10379 goto do_cp1;
10380 case FLOAT_1BIT_FMT(MFC1, 0):
10381 mips32_op = OPC_MFC1;
10382 goto do_cp1;
10383 case FLOAT_1BIT_FMT(MTC1, 0):
10384 mips32_op = OPC_MTC1;
10385 goto do_cp1;
10386 case FLOAT_1BIT_FMT(MFHC1, 0):
10387 mips32_op = OPC_MFHC1;
10388 goto do_cp1;
10389 case FLOAT_1BIT_FMT(MTHC1, 0):
10390 mips32_op = OPC_MTHC1;
10391 do_cp1:
10392 gen_cp1(ctx, mips32_op, rt, rs);
10393 break;
10394
10395 /* Reciprocal square root */
10396 case FLOAT_1BIT_FMT(RSQRT_FMT, FMT_SD_S):
10397 mips32_op = OPC_RSQRT_S;
10398 goto do_unaryfp;
10399 case FLOAT_1BIT_FMT(RSQRT_FMT, FMT_SD_D):
10400 mips32_op = OPC_RSQRT_D;
10401 goto do_unaryfp;
10402
10403 /* Square root */
10404 case FLOAT_1BIT_FMT(SQRT_FMT, FMT_SD_S):
10405 mips32_op = OPC_SQRT_S;
10406 goto do_unaryfp;
10407 case FLOAT_1BIT_FMT(SQRT_FMT, FMT_SD_D):
10408 mips32_op = OPC_SQRT_D;
10409 goto do_unaryfp;
10410
10411 /* Reciprocal */
10412 case FLOAT_1BIT_FMT(RECIP_FMT, FMT_SD_S):
10413 mips32_op = OPC_RECIP_S;
10414 goto do_unaryfp;
10415 case FLOAT_1BIT_FMT(RECIP_FMT, FMT_SD_D):
10416 mips32_op = OPC_RECIP_D;
10417 goto do_unaryfp;
10418
10419 /* Floor */
10420 case FLOAT_1BIT_FMT(FLOOR_L, FMT_SD_S):
10421 mips32_op = OPC_FLOOR_L_S;
10422 goto do_unaryfp;
10423 case FLOAT_1BIT_FMT(FLOOR_L, FMT_SD_D):
10424 mips32_op = OPC_FLOOR_L_D;
10425 goto do_unaryfp;
10426 case FLOAT_1BIT_FMT(FLOOR_W, FMT_SD_S):
10427 mips32_op = OPC_FLOOR_W_S;
10428 goto do_unaryfp;
10429 case FLOAT_1BIT_FMT(FLOOR_W, FMT_SD_D):
10430 mips32_op = OPC_FLOOR_W_D;
10431 goto do_unaryfp;
10432
10433 /* Ceiling */
10434 case FLOAT_1BIT_FMT(CEIL_L, FMT_SD_S):
10435 mips32_op = OPC_CEIL_L_S;
10436 goto do_unaryfp;
10437 case FLOAT_1BIT_FMT(CEIL_L, FMT_SD_D):
10438 mips32_op = OPC_CEIL_L_D;
10439 goto do_unaryfp;
10440 case FLOAT_1BIT_FMT(CEIL_W, FMT_SD_S):
10441 mips32_op = OPC_CEIL_W_S;
10442 goto do_unaryfp;
10443 case FLOAT_1BIT_FMT(CEIL_W, FMT_SD_D):
10444 mips32_op = OPC_CEIL_W_D;
10445 goto do_unaryfp;
10446
10447 /* Truncation */
10448 case FLOAT_1BIT_FMT(TRUNC_L, FMT_SD_S):
10449 mips32_op = OPC_TRUNC_L_S;
10450 goto do_unaryfp;
10451 case FLOAT_1BIT_FMT(TRUNC_L, FMT_SD_D):
10452 mips32_op = OPC_TRUNC_L_D;
10453 goto do_unaryfp;
10454 case FLOAT_1BIT_FMT(TRUNC_W, FMT_SD_S):
10455 mips32_op = OPC_TRUNC_W_S;
10456 goto do_unaryfp;
10457 case FLOAT_1BIT_FMT(TRUNC_W, FMT_SD_D):
10458 mips32_op = OPC_TRUNC_W_D;
10459 goto do_unaryfp;
10460
10461 /* Round */
10462 case FLOAT_1BIT_FMT(ROUND_L, FMT_SD_S):
10463 mips32_op = OPC_ROUND_L_S;
10464 goto do_unaryfp;
10465 case FLOAT_1BIT_FMT(ROUND_L, FMT_SD_D):
10466 mips32_op = OPC_ROUND_L_D;
10467 goto do_unaryfp;
10468 case FLOAT_1BIT_FMT(ROUND_W, FMT_SD_S):
10469 mips32_op = OPC_ROUND_W_S;
10470 goto do_unaryfp;
10471 case FLOAT_1BIT_FMT(ROUND_W, FMT_SD_D):
10472 mips32_op = OPC_ROUND_W_D;
10473 goto do_unaryfp;
10474
10475 /* Integer to floating-point conversion */
10476 case FLOAT_1BIT_FMT(CVT_L, FMT_SD_S):
10477 mips32_op = OPC_CVT_L_S;
10478 goto do_unaryfp;
10479 case FLOAT_1BIT_FMT(CVT_L, FMT_SD_D):
10480 mips32_op = OPC_CVT_L_D;
10481 goto do_unaryfp;
10482 case FLOAT_1BIT_FMT(CVT_W, FMT_SD_S):
10483 mips32_op = OPC_CVT_W_S;
10484 goto do_unaryfp;
10485 case FLOAT_1BIT_FMT(CVT_W, FMT_SD_D):
10486 mips32_op = OPC_CVT_W_D;
10487 goto do_unaryfp;
10488
10489 /* Paired-foo conversions */
10490 case FLOAT_1BIT_FMT(CVT_S_PL, 0):
10491 mips32_op = OPC_CVT_S_PL;
10492 goto do_unaryfp;
10493 case FLOAT_1BIT_FMT(CVT_S_PU, 0):
10494 mips32_op = OPC_CVT_S_PU;
10495 goto do_unaryfp;
10496 case FLOAT_1BIT_FMT(CVT_PW_PS, 0):
10497 mips32_op = OPC_CVT_PW_PS;
10498 goto do_unaryfp;
10499 case FLOAT_1BIT_FMT(CVT_PS_PW, 0):
10500 mips32_op = OPC_CVT_PS_PW;
10501 goto do_unaryfp;
10502
10503 /* Floating-point moves */
10504 case FLOAT_2BIT_FMT(MOV_FMT, FMT_SDPS_S):
10505 mips32_op = OPC_MOV_S;
10506 goto do_unaryfp;
10507 case FLOAT_2BIT_FMT(MOV_FMT, FMT_SDPS_D):
10508 mips32_op = OPC_MOV_D;
10509 goto do_unaryfp;
10510 case FLOAT_2BIT_FMT(MOV_FMT, FMT_SDPS_PS):
10511 mips32_op = OPC_MOV_PS;
10512 goto do_unaryfp;
10513
10514 /* Absolute value */
10515 case FLOAT_2BIT_FMT(ABS_FMT, FMT_SDPS_S):
10516 mips32_op = OPC_ABS_S;
10517 goto do_unaryfp;
10518 case FLOAT_2BIT_FMT(ABS_FMT, FMT_SDPS_D):
10519 mips32_op = OPC_ABS_D;
10520 goto do_unaryfp;
10521 case FLOAT_2BIT_FMT(ABS_FMT, FMT_SDPS_PS):
10522 mips32_op = OPC_ABS_PS;
10523 goto do_unaryfp;
10524
10525 /* Negation */
10526 case FLOAT_2BIT_FMT(NEG_FMT, FMT_SDPS_S):
10527 mips32_op = OPC_NEG_S;
10528 goto do_unaryfp;
10529 case FLOAT_2BIT_FMT(NEG_FMT, FMT_SDPS_D):
10530 mips32_op = OPC_NEG_D;
10531 goto do_unaryfp;
10532 case FLOAT_2BIT_FMT(NEG_FMT, FMT_SDPS_PS):
10533 mips32_op = OPC_NEG_PS;
10534 goto do_unaryfp;
10535
10536 /* Reciprocal square root step */
10537 case FLOAT_2BIT_FMT(RSQRT1_FMT, FMT_SDPS_S):
10538 mips32_op = OPC_RSQRT1_S;
10539 goto do_unaryfp;
10540 case FLOAT_2BIT_FMT(RSQRT1_FMT, FMT_SDPS_D):
10541 mips32_op = OPC_RSQRT1_D;
10542 goto do_unaryfp;
10543 case FLOAT_2BIT_FMT(RSQRT1_FMT, FMT_SDPS_PS):
10544 mips32_op = OPC_RSQRT1_PS;
10545 goto do_unaryfp;
10546
10547 /* Reciprocal step */
10548 case FLOAT_2BIT_FMT(RECIP1_FMT, FMT_SDPS_S):
10549 mips32_op = OPC_RECIP1_S;
10550 goto do_unaryfp;
10551 case FLOAT_2BIT_FMT(RECIP1_FMT, FMT_SDPS_D):
10552 mips32_op = OPC_RECIP1_S;
10553 goto do_unaryfp;
10554 case FLOAT_2BIT_FMT(RECIP1_FMT, FMT_SDPS_PS):
10555 mips32_op = OPC_RECIP1_PS;
10556 goto do_unaryfp;
10557
10558 /* Conversions from double */
10559 case FLOAT_2BIT_FMT(CVT_D, FMT_SWL_S):
10560 mips32_op = OPC_CVT_D_S;
10561 goto do_unaryfp;
10562 case FLOAT_2BIT_FMT(CVT_D, FMT_SWL_W):
10563 mips32_op = OPC_CVT_D_W;
10564 goto do_unaryfp;
10565 case FLOAT_2BIT_FMT(CVT_D, FMT_SWL_L):
10566 mips32_op = OPC_CVT_D_L;
10567 goto do_unaryfp;
10568
10569 /* Conversions from single */
10570 case FLOAT_2BIT_FMT(CVT_S, FMT_DWL_D):
10571 mips32_op = OPC_CVT_S_D;
10572 goto do_unaryfp;
10573 case FLOAT_2BIT_FMT(CVT_S, FMT_DWL_W):
10574 mips32_op = OPC_CVT_S_W;
10575 goto do_unaryfp;
10576 case FLOAT_2BIT_FMT(CVT_S, FMT_DWL_L):
10577 mips32_op = OPC_CVT_S_L;
10578 do_unaryfp:
10579 gen_farith(ctx, mips32_op, -1, rs, rt, 0);
10580 break;
10581
10582 /* Conditional moves on floating-point codes */
10583 case COND_FLOAT_MOV(MOVT, 0):
10584 case COND_FLOAT_MOV(MOVT, 1):
10585 case COND_FLOAT_MOV(MOVT, 2):
10586 case COND_FLOAT_MOV(MOVT, 3):
10587 case COND_FLOAT_MOV(MOVT, 4):
10588 case COND_FLOAT_MOV(MOVT, 5):
10589 case COND_FLOAT_MOV(MOVT, 6):
10590 case COND_FLOAT_MOV(MOVT, 7):
10591 gen_movci(ctx, rt, rs, (ctx->opcode >> 13) & 0x7, 1);
10592 break;
10593 case COND_FLOAT_MOV(MOVF, 0):
10594 case COND_FLOAT_MOV(MOVF, 1):
10595 case COND_FLOAT_MOV(MOVF, 2):
10596 case COND_FLOAT_MOV(MOVF, 3):
10597 case COND_FLOAT_MOV(MOVF, 4):
10598 case COND_FLOAT_MOV(MOVF, 5):
10599 case COND_FLOAT_MOV(MOVF, 6):
10600 case COND_FLOAT_MOV(MOVF, 7):
10601 gen_movci(ctx, rt, rs, (ctx->opcode >> 13) & 0x7, 0);
10602 break;
10603 default:
10604 MIPS_INVAL("pool32fxf");
10605 generate_exception(ctx, EXCP_RI);
10606 break;
10607 }
10608}
10609
7db13fae 10610static void decode_micromips32_opc (CPUMIPSState *env, DisasContext *ctx,
3c824109
NF
10611 uint16_t insn_hw1, int *is_branch)
10612{
10613 int32_t offset;
10614 uint16_t insn;
10615 int rt, rs, rd, rr;
10616 int16_t imm;
10617 uint32_t op, minor, mips32_op;
10618 uint32_t cond, fmt, cc;
10619
10620 insn = lduw_code(ctx->pc + 2);
10621 ctx->opcode = (ctx->opcode << 16) | insn;
10622
10623 rt = (ctx->opcode >> 21) & 0x1f;
10624 rs = (ctx->opcode >> 16) & 0x1f;
10625 rd = (ctx->opcode >> 11) & 0x1f;
10626 rr = (ctx->opcode >> 6) & 0x1f;
10627 imm = (int16_t) ctx->opcode;
10628
10629 op = (ctx->opcode >> 26) & 0x3f;
10630 switch (op) {
10631 case POOL32A:
10632 minor = ctx->opcode & 0x3f;
10633 switch (minor) {
10634 case 0x00:
10635 minor = (ctx->opcode >> 6) & 0xf;
10636 switch (minor) {
10637 case SLL32:
10638 mips32_op = OPC_SLL;
10639 goto do_shifti;
10640 case SRA:
10641 mips32_op = OPC_SRA;
10642 goto do_shifti;
10643 case SRL32:
10644 mips32_op = OPC_SRL;
10645 goto do_shifti;
10646 case ROTR:
10647 mips32_op = OPC_ROTR;
10648 do_shifti:
10649 gen_shift_imm(env, ctx, mips32_op, rt, rs, rd);
10650 break;
10651 default:
10652 goto pool32a_invalid;
10653 }
10654 break;
10655 case 0x10:
10656 minor = (ctx->opcode >> 6) & 0xf;
10657 switch (minor) {
10658 /* Arithmetic */
10659 case ADD:
10660 mips32_op = OPC_ADD;
10661 goto do_arith;
10662 case ADDU32:
10663 mips32_op = OPC_ADDU;
10664 goto do_arith;
10665 case SUB:
10666 mips32_op = OPC_SUB;
10667 goto do_arith;
10668 case SUBU32:
10669 mips32_op = OPC_SUBU;
10670 goto do_arith;
10671 case MUL:
10672 mips32_op = OPC_MUL;
10673 do_arith:
10674 gen_arith(env, ctx, mips32_op, rd, rs, rt);
10675 break;
10676 /* Shifts */
10677 case SLLV:
10678 mips32_op = OPC_SLLV;
10679 goto do_shift;
10680 case SRLV:
10681 mips32_op = OPC_SRLV;
10682 goto do_shift;
10683 case SRAV:
10684 mips32_op = OPC_SRAV;
10685 goto do_shift;
10686 case ROTRV:
10687 mips32_op = OPC_ROTRV;
10688 do_shift:
10689 gen_shift(env, ctx, mips32_op, rd, rs, rt);
10690 break;
10691 /* Logical operations */
10692 case AND:
10693 mips32_op = OPC_AND;
10694 goto do_logic;
10695 case OR32:
10696 mips32_op = OPC_OR;
10697 goto do_logic;
10698 case NOR:
10699 mips32_op = OPC_NOR;
10700 goto do_logic;
10701 case XOR32:
10702 mips32_op = OPC_XOR;
10703 do_logic:
10704 gen_logic(env, mips32_op, rd, rs, rt);
10705 break;
10706 /* Set less than */
10707 case SLT:
10708 mips32_op = OPC_SLT;
10709 goto do_slt;
10710 case SLTU:
10711 mips32_op = OPC_SLTU;
10712 do_slt:
10713 gen_slt(env, mips32_op, rd, rs, rt);
10714 break;
10715 default:
10716 goto pool32a_invalid;
10717 }
10718 break;
10719 case 0x18:
10720 minor = (ctx->opcode >> 6) & 0xf;
10721 switch (minor) {
10722 /* Conditional moves */
10723 case MOVN:
10724 mips32_op = OPC_MOVN;
10725 goto do_cmov;
10726 case MOVZ:
10727 mips32_op = OPC_MOVZ;
10728 do_cmov:
10729 gen_cond_move(env, mips32_op, rd, rs, rt);
10730 break;
10731 case LWXS:
10732 gen_ldxs(ctx, rs, rt, rd);
10733 break;
10734 default:
10735 goto pool32a_invalid;
10736 }
10737 break;
10738 case INS:
10739 gen_bitops(ctx, OPC_INS, rt, rs, rr, rd);
10740 return;
10741 case EXT:
10742 gen_bitops(ctx, OPC_EXT, rt, rs, rr, rd);
10743 return;
10744 case POOL32AXF:
10745 gen_pool32axf(env, ctx, rt, rs, is_branch);
10746 break;
10747 case 0x07:
10748 generate_exception(ctx, EXCP_BREAK);
10749 break;
10750 default:
10751 pool32a_invalid:
10752 MIPS_INVAL("pool32a");
10753 generate_exception(ctx, EXCP_RI);
10754 break;
10755 }
10756 break;
10757 case POOL32B:
10758 minor = (ctx->opcode >> 12) & 0xf;
10759 switch (minor) {
10760 case CACHE:
10761 /* Treat as no-op. */
10762 break;
10763 case LWC2:
10764 case SWC2:
10765 /* COP2: Not implemented. */
10766 generate_exception_err(ctx, EXCP_CpU, 2);
10767 break;
10768 case LWP:
10769 case SWP:
10770#ifdef TARGET_MIPS64
10771 case LDP:
10772 case SDP:
10773#endif
10774 gen_ldst_pair(ctx, minor, rt, rs, SIMM(ctx->opcode, 0, 12));
10775 break;
10776 case LWM32:
10777 case SWM32:
10778#ifdef TARGET_MIPS64
10779 case LDM:
10780 case SDM:
10781#endif
10782 gen_ldst_multiple(ctx, minor, rt, rs, SIMM(ctx->opcode, 0, 12));
10783 break;
10784 default:
10785 MIPS_INVAL("pool32b");
10786 generate_exception(ctx, EXCP_RI);
10787 break;
10788 }
10789 break;
10790 case POOL32F:
10791 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
10792 minor = ctx->opcode & 0x3f;
10793 check_cp1_enabled(ctx);
10794 switch (minor) {
10795 case ALNV_PS:
10796 mips32_op = OPC_ALNV_PS;
10797 goto do_madd;
10798 case MADD_S:
10799 mips32_op = OPC_MADD_S;
10800 goto do_madd;
10801 case MADD_D:
10802 mips32_op = OPC_MADD_D;
10803 goto do_madd;
10804 case MADD_PS:
10805 mips32_op = OPC_MADD_PS;
10806 goto do_madd;
10807 case MSUB_S:
10808 mips32_op = OPC_MSUB_S;
10809 goto do_madd;
10810 case MSUB_D:
10811 mips32_op = OPC_MSUB_D;
10812 goto do_madd;
10813 case MSUB_PS:
10814 mips32_op = OPC_MSUB_PS;
10815 goto do_madd;
10816 case NMADD_S:
10817 mips32_op = OPC_NMADD_S;
10818 goto do_madd;
10819 case NMADD_D:
10820 mips32_op = OPC_NMADD_D;
10821 goto do_madd;
10822 case NMADD_PS:
10823 mips32_op = OPC_NMADD_PS;
10824 goto do_madd;
10825 case NMSUB_S:
10826 mips32_op = OPC_NMSUB_S;
10827 goto do_madd;
10828 case NMSUB_D:
10829 mips32_op = OPC_NMSUB_D;
10830 goto do_madd;
10831 case NMSUB_PS:
10832 mips32_op = OPC_NMSUB_PS;
10833 do_madd:
10834 gen_flt3_arith(ctx, mips32_op, rd, rr, rs, rt);
10835 break;
10836 case CABS_COND_FMT:
10837 cond = (ctx->opcode >> 6) & 0xf;
10838 cc = (ctx->opcode >> 13) & 0x7;
10839 fmt = (ctx->opcode >> 10) & 0x3;
10840 switch (fmt) {
10841 case 0x0:
10842 gen_cmpabs_s(ctx, cond, rt, rs, cc);
10843 break;
10844 case 0x1:
10845 gen_cmpabs_d(ctx, cond, rt, rs, cc);
10846 break;
10847 case 0x2:
10848 gen_cmpabs_ps(ctx, cond, rt, rs, cc);
10849 break;
10850 default:
10851 goto pool32f_invalid;
10852 }
10853 break;
10854 case C_COND_FMT:
10855 cond = (ctx->opcode >> 6) & 0xf;
10856 cc = (ctx->opcode >> 13) & 0x7;
10857 fmt = (ctx->opcode >> 10) & 0x3;
10858 switch (fmt) {
10859 case 0x0:
10860 gen_cmp_s(ctx, cond, rt, rs, cc);
10861 break;
10862 case 0x1:
10863 gen_cmp_d(ctx, cond, rt, rs, cc);
10864 break;
10865 case 0x2:
10866 gen_cmp_ps(ctx, cond, rt, rs, cc);
10867 break;
10868 default:
10869 goto pool32f_invalid;
10870 }
10871 break;
10872 case POOL32FXF:
10873 gen_pool32fxf(env, ctx, rt, rs);
10874 break;
10875 case 0x00:
10876 /* PLL foo */
10877 switch ((ctx->opcode >> 6) & 0x7) {
10878 case PLL_PS:
10879 mips32_op = OPC_PLL_PS;
10880 goto do_ps;
10881 case PLU_PS:
10882 mips32_op = OPC_PLU_PS;
10883 goto do_ps;
10884 case PUL_PS:
10885 mips32_op = OPC_PUL_PS;
10886 goto do_ps;
10887 case PUU_PS:
10888 mips32_op = OPC_PUU_PS;
10889 goto do_ps;
10890 case CVT_PS_S:
10891 mips32_op = OPC_CVT_PS_S;
10892 do_ps:
10893 gen_farith(ctx, mips32_op, rt, rs, rd, 0);
10894 break;
10895 default:
10896 goto pool32f_invalid;
10897 }
10898 break;
10899 case 0x08:
10900 /* [LS][WDU]XC1 */
10901 switch ((ctx->opcode >> 6) & 0x7) {
10902 case LWXC1:
10903 mips32_op = OPC_LWXC1;
10904 goto do_ldst_cp1;
10905 case SWXC1:
10906 mips32_op = OPC_SWXC1;
10907 goto do_ldst_cp1;
10908 case LDXC1:
10909 mips32_op = OPC_LDXC1;
10910 goto do_ldst_cp1;
10911 case SDXC1:
10912 mips32_op = OPC_SDXC1;
10913 goto do_ldst_cp1;
10914 case LUXC1:
10915 mips32_op = OPC_LUXC1;
10916 goto do_ldst_cp1;
10917 case SUXC1:
10918 mips32_op = OPC_SUXC1;
10919 do_ldst_cp1:
10920 gen_flt3_ldst(ctx, mips32_op, rd, rd, rt, rs);
10921 break;
10922 default:
10923 goto pool32f_invalid;
10924 }
10925 break;
10926 case 0x18:
10927 /* 3D insns */
10928 fmt = (ctx->opcode >> 9) & 0x3;
10929 switch ((ctx->opcode >> 6) & 0x7) {
10930 case RSQRT2_FMT:
10931 switch (fmt) {
10932 case FMT_SDPS_S:
10933 mips32_op = OPC_RSQRT2_S;
10934 goto do_3d;
10935 case FMT_SDPS_D:
10936 mips32_op = OPC_RSQRT2_D;
10937 goto do_3d;
10938 case FMT_SDPS_PS:
10939 mips32_op = OPC_RSQRT2_PS;
10940 goto do_3d;
10941 default:
10942 goto pool32f_invalid;
10943 }
10944 break;
10945 case RECIP2_FMT:
10946 switch (fmt) {
10947 case FMT_SDPS_S:
10948 mips32_op = OPC_RECIP2_S;
10949 goto do_3d;
10950 case FMT_SDPS_D:
10951 mips32_op = OPC_RECIP2_D;
10952 goto do_3d;
10953 case FMT_SDPS_PS:
10954 mips32_op = OPC_RECIP2_PS;
10955 goto do_3d;
10956 default:
10957 goto pool32f_invalid;
10958 }
10959 break;
10960 case ADDR_PS:
10961 mips32_op = OPC_ADDR_PS;
10962 goto do_3d;
10963 case MULR_PS:
10964 mips32_op = OPC_MULR_PS;
10965 do_3d:
10966 gen_farith(ctx, mips32_op, rt, rs, rd, 0);
10967 break;
10968 default:
10969 goto pool32f_invalid;
10970 }
10971 break;
10972 case 0x20:
10973 /* MOV[FT].fmt and PREFX */
10974 cc = (ctx->opcode >> 13) & 0x7;
10975 fmt = (ctx->opcode >> 9) & 0x3;
10976 switch ((ctx->opcode >> 6) & 0x7) {
10977 case MOVF_FMT:
10978 switch (fmt) {
10979 case FMT_SDPS_S:
10980 gen_movcf_s(rs, rt, cc, 0);
10981 break;
10982 case FMT_SDPS_D:
10983 gen_movcf_d(ctx, rs, rt, cc, 0);
10984 break;
10985 case FMT_SDPS_PS:
10986 gen_movcf_ps(rs, rt, cc, 0);
10987 break;
10988 default:
10989 goto pool32f_invalid;
10990 }
10991 break;
10992 case MOVT_FMT:
10993 switch (fmt) {
10994 case FMT_SDPS_S:
10995 gen_movcf_s(rs, rt, cc, 1);
10996 break;
10997 case FMT_SDPS_D:
10998 gen_movcf_d(ctx, rs, rt, cc, 1);
10999 break;
11000 case FMT_SDPS_PS:
11001 gen_movcf_ps(rs, rt, cc, 1);
11002 break;
11003 default:
11004 goto pool32f_invalid;
11005 }
11006 break;
11007 case PREFX:
11008 break;
11009 default:
11010 goto pool32f_invalid;
11011 }
11012 break;
11013#define FINSN_3ARG_SDPS(prfx) \
11014 switch ((ctx->opcode >> 8) & 0x3) { \
11015 case FMT_SDPS_S: \
11016 mips32_op = OPC_##prfx##_S; \
11017 goto do_fpop; \
11018 case FMT_SDPS_D: \
11019 mips32_op = OPC_##prfx##_D; \
11020 goto do_fpop; \
11021 case FMT_SDPS_PS: \
11022 mips32_op = OPC_##prfx##_PS; \
11023 goto do_fpop; \
11024 default: \
11025 goto pool32f_invalid; \
11026 }
11027 case 0x30:
11028 /* regular FP ops */
11029 switch ((ctx->opcode >> 6) & 0x3) {
11030 case ADD_FMT:
11031 FINSN_3ARG_SDPS(ADD);
11032 break;
11033 case SUB_FMT:
11034 FINSN_3ARG_SDPS(SUB);
11035 break;
11036 case MUL_FMT:
11037 FINSN_3ARG_SDPS(MUL);
11038 break;
11039 case DIV_FMT:
11040 fmt = (ctx->opcode >> 8) & 0x3;
11041 if (fmt == 1) {
11042 mips32_op = OPC_DIV_D;
11043 } else if (fmt == 0) {
11044 mips32_op = OPC_DIV_S;
11045 } else {
11046 goto pool32f_invalid;
11047 }
11048 goto do_fpop;
11049 default:
11050 goto pool32f_invalid;
11051 }
11052 break;
11053 case 0x38:
11054 /* cmovs */
11055 switch ((ctx->opcode >> 6) & 0x3) {
11056 case MOVN_FMT:
11057 FINSN_3ARG_SDPS(MOVN);
11058 break;
11059 case MOVZ_FMT:
11060 FINSN_3ARG_SDPS(MOVZ);
11061 break;
11062 default:
11063 goto pool32f_invalid;
11064 }
11065 break;
11066 do_fpop:
11067 gen_farith(ctx, mips32_op, rt, rs, rd, 0);
11068 break;
11069 default:
11070 pool32f_invalid:
11071 MIPS_INVAL("pool32f");
11072 generate_exception(ctx, EXCP_RI);
11073 break;
11074 }
11075 } else {
11076 generate_exception_err(ctx, EXCP_CpU, 1);
11077 }
11078 break;
11079 case POOL32I:
11080 minor = (ctx->opcode >> 21) & 0x1f;
11081 switch (minor) {
11082 case BLTZ:
11083 mips32_op = OPC_BLTZ;
11084 goto do_branch;
11085 case BLTZAL:
11086 mips32_op = OPC_BLTZAL;
11087 goto do_branch;
11088 case BLTZALS:
11089 mips32_op = OPC_BLTZALS;
11090 goto do_branch;
11091 case BGEZ:
11092 mips32_op = OPC_BGEZ;
11093 goto do_branch;
11094 case BGEZAL:
11095 mips32_op = OPC_BGEZAL;
11096 goto do_branch;
11097 case BGEZALS:
11098 mips32_op = OPC_BGEZALS;
11099 goto do_branch;
11100 case BLEZ:
11101 mips32_op = OPC_BLEZ;
11102 goto do_branch;
11103 case BGTZ:
11104 mips32_op = OPC_BGTZ;
11105 do_branch:
11106 gen_compute_branch(ctx, mips32_op, 4, rs, -1, imm << 1);
11107 *is_branch = 1;
11108 break;
11109
11110 /* Traps */
11111 case TLTI:
11112 mips32_op = OPC_TLTI;
11113 goto do_trapi;
11114 case TGEI:
11115 mips32_op = OPC_TGEI;
11116 goto do_trapi;
11117 case TLTIU:
11118 mips32_op = OPC_TLTIU;
11119 goto do_trapi;
11120 case TGEIU:
11121 mips32_op = OPC_TGEIU;
11122 goto do_trapi;
11123 case TNEI:
11124 mips32_op = OPC_TNEI;
11125 goto do_trapi;
11126 case TEQI:
11127 mips32_op = OPC_TEQI;
11128 do_trapi:
11129 gen_trap(ctx, mips32_op, rs, -1, imm);
11130 break;
11131
11132 case BNEZC:
11133 case BEQZC:
11134 gen_compute_branch(ctx, minor == BNEZC ? OPC_BNE : OPC_BEQ,
11135 4, rs, 0, imm << 1);
11136 /* Compact branches don't have a delay slot, so just let
11137 the normal delay slot handling take us to the branch
11138 target. */
11139 break;
11140 case LUI:
11141 gen_logic_imm(env, OPC_LUI, rs, -1, imm);
11142 break;
11143 case SYNCI:
11144 break;
11145 case BC2F:
11146 case BC2T:
11147 /* COP2: Not implemented. */
11148 generate_exception_err(ctx, EXCP_CpU, 2);
11149 break;
11150 case BC1F:
11151 mips32_op = (ctx->opcode & (1 << 16)) ? OPC_BC1FANY2 : OPC_BC1F;
11152 goto do_cp1branch;
11153 case BC1T:
11154 mips32_op = (ctx->opcode & (1 << 16)) ? OPC_BC1TANY2 : OPC_BC1T;
11155 goto do_cp1branch;
11156 case BC1ANY4F:
11157 mips32_op = OPC_BC1FANY4;
11158 goto do_cp1mips3d;
11159 case BC1ANY4T:
11160 mips32_op = OPC_BC1TANY4;
11161 do_cp1mips3d:
11162 check_cop1x(ctx);
11163 check_insn(env, ctx, ASE_MIPS3D);
11164 /* Fall through */
11165 do_cp1branch:
11166 gen_compute_branch1(env, ctx, mips32_op,
11167 (ctx->opcode >> 18) & 0x7, imm << 1);
11168 *is_branch = 1;
11169 break;
11170 case BPOSGE64:
11171 case BPOSGE32:
11172 /* MIPS DSP: not implemented */
11173 /* Fall through */
11174 default:
11175 MIPS_INVAL("pool32i");
11176 generate_exception(ctx, EXCP_RI);
11177 break;
11178 }
11179 break;
11180 case POOL32C:
11181 minor = (ctx->opcode >> 12) & 0xf;
11182 switch (minor) {
11183 case LWL:
11184 mips32_op = OPC_LWL;
5c13fdfd 11185 goto do_ld_lr;
3c824109
NF
11186 case SWL:
11187 mips32_op = OPC_SWL;
5c13fdfd 11188 goto do_st_lr;
3c824109
NF
11189 case LWR:
11190 mips32_op = OPC_LWR;
5c13fdfd 11191 goto do_ld_lr;
3c824109
NF
11192 case SWR:
11193 mips32_op = OPC_SWR;
5c13fdfd 11194 goto do_st_lr;
3c824109
NF
11195#if defined(TARGET_MIPS64)
11196 case LDL:
11197 mips32_op = OPC_LDL;
5c13fdfd 11198 goto do_ld_lr;
3c824109
NF
11199 case SDL:
11200 mips32_op = OPC_SDL;
5c13fdfd 11201 goto do_st_lr;
3c824109
NF
11202 case LDR:
11203 mips32_op = OPC_LDR;
5c13fdfd 11204 goto do_ld_lr;
3c824109
NF
11205 case SDR:
11206 mips32_op = OPC_SDR;
5c13fdfd 11207 goto do_st_lr;
3c824109
NF
11208 case LWU:
11209 mips32_op = OPC_LWU;
5c13fdfd 11210 goto do_ld_lr;
3c824109
NF
11211 case LLD:
11212 mips32_op = OPC_LLD;
5c13fdfd 11213 goto do_ld_lr;
3c824109
NF
11214#endif
11215 case LL:
11216 mips32_op = OPC_LL;
5c13fdfd
AJ
11217 goto do_ld_lr;
11218 do_ld_lr:
afa88c3a 11219 gen_ld(env, ctx, mips32_op, rt, rs, SIMM(ctx->opcode, 0, 12));
5c13fdfd
AJ
11220 break;
11221 do_st_lr:
11222 gen_st(ctx, mips32_op, rt, rs, SIMM(ctx->opcode, 0, 12));
3c824109
NF
11223 break;
11224 case SC:
11225 gen_st_cond(ctx, OPC_SC, rt, rs, SIMM(ctx->opcode, 0, 12));
11226 break;
11227#if defined(TARGET_MIPS64)
11228 case SCD:
11229 gen_st_cond(ctx, OPC_SCD, rt, rs, SIMM(ctx->opcode, 0, 12));
11230 break;
11231#endif
11232 case PREF:
11233 /* Treat as no-op */
11234 break;
11235 default:
11236 MIPS_INVAL("pool32c");
11237 generate_exception(ctx, EXCP_RI);
11238 break;
11239 }
11240 break;
11241 case ADDI32:
11242 mips32_op = OPC_ADDI;
11243 goto do_addi;
11244 case ADDIU32:
11245 mips32_op = OPC_ADDIU;
11246 do_addi:
11247 gen_arith_imm(env, ctx, mips32_op, rt, rs, imm);
11248 break;
11249
11250 /* Logical operations */
11251 case ORI32:
11252 mips32_op = OPC_ORI;
11253 goto do_logici;
11254 case XORI32:
11255 mips32_op = OPC_XORI;
11256 goto do_logici;
11257 case ANDI32:
11258 mips32_op = OPC_ANDI;
11259 do_logici:
11260 gen_logic_imm(env, mips32_op, rt, rs, imm);
11261 break;
11262
11263 /* Set less than immediate */
11264 case SLTI32:
11265 mips32_op = OPC_SLTI;
11266 goto do_slti;
11267 case SLTIU32:
11268 mips32_op = OPC_SLTIU;
11269 do_slti:
11270 gen_slt_imm(env, mips32_op, rt, rs, imm);
11271 break;
11272 case JALX32:
11273 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2;
11274 gen_compute_branch(ctx, OPC_JALX, 4, rt, rs, offset);
11275 *is_branch = 1;
11276 break;
11277 case JALS32:
11278 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 1;
11279 gen_compute_branch(ctx, OPC_JALS, 4, rt, rs, offset);
11280 *is_branch = 1;
11281 break;
11282 case BEQ32:
11283 gen_compute_branch(ctx, OPC_BEQ, 4, rt, rs, imm << 1);
11284 *is_branch = 1;
11285 break;
11286 case BNE32:
11287 gen_compute_branch(ctx, OPC_BNE, 4, rt, rs, imm << 1);
11288 *is_branch = 1;
11289 break;
11290 case J32:
11291 gen_compute_branch(ctx, OPC_J, 4, rt, rs,
11292 (int32_t)(ctx->opcode & 0x3FFFFFF) << 1);
11293 *is_branch = 1;
11294 break;
11295 case JAL32:
11296 gen_compute_branch(ctx, OPC_JAL, 4, rt, rs,
11297 (int32_t)(ctx->opcode & 0x3FFFFFF) << 1);
11298 *is_branch = 1;
11299 break;
11300 /* Floating point (COP1) */
11301 case LWC132:
11302 mips32_op = OPC_LWC1;
11303 goto do_cop1;
11304 case LDC132:
11305 mips32_op = OPC_LDC1;
11306 goto do_cop1;
11307 case SWC132:
11308 mips32_op = OPC_SWC1;
11309 goto do_cop1;
11310 case SDC132:
11311 mips32_op = OPC_SDC1;
11312 do_cop1:
11313 gen_cop1_ldst(env, ctx, mips32_op, rt, rs, imm);
11314 break;
11315 case ADDIUPC:
11316 {
11317 int reg = mmreg(ZIMM(ctx->opcode, 23, 3));
11318 int offset = SIMM(ctx->opcode, 0, 23) << 2;
11319
11320 gen_addiupc(ctx, reg, offset, 0, 0);
11321 }
11322 break;
11323 /* Loads and stores */
11324 case LB32:
11325 mips32_op = OPC_LB;
5c13fdfd 11326 goto do_ld;
3c824109
NF
11327 case LBU32:
11328 mips32_op = OPC_LBU;
5c13fdfd 11329 goto do_ld;
3c824109
NF
11330 case LH32:
11331 mips32_op = OPC_LH;
5c13fdfd 11332 goto do_ld;
3c824109
NF
11333 case LHU32:
11334 mips32_op = OPC_LHU;
5c13fdfd 11335 goto do_ld;
3c824109
NF
11336 case LW32:
11337 mips32_op = OPC_LW;
5c13fdfd 11338 goto do_ld;
3c824109
NF
11339#ifdef TARGET_MIPS64
11340 case LD32:
11341 mips32_op = OPC_LD;
5c13fdfd 11342 goto do_ld;
3c824109
NF
11343 case SD32:
11344 mips32_op = OPC_SD;
5c13fdfd 11345 goto do_st;
3c824109
NF
11346#endif
11347 case SB32:
11348 mips32_op = OPC_SB;
5c13fdfd 11349 goto do_st;
3c824109
NF
11350 case SH32:
11351 mips32_op = OPC_SH;
5c13fdfd 11352 goto do_st;
3c824109
NF
11353 case SW32:
11354 mips32_op = OPC_SW;
5c13fdfd
AJ
11355 goto do_st;
11356 do_ld:
afa88c3a 11357 gen_ld(env, ctx, mips32_op, rt, rs, imm);
5c13fdfd
AJ
11358 break;
11359 do_st:
11360 gen_st(ctx, mips32_op, rt, rs, imm);
3c824109
NF
11361 break;
11362 default:
11363 generate_exception(ctx, EXCP_RI);
11364 break;
11365 }
11366}
11367
7db13fae 11368static int decode_micromips_opc (CPUMIPSState *env, DisasContext *ctx, int *is_branch)
3c824109
NF
11369{
11370 uint32_t op;
11371
11372 /* make sure instructions are on a halfword boundary */
11373 if (ctx->pc & 0x1) {
11374 env->CP0_BadVAddr = ctx->pc;
11375 generate_exception(ctx, EXCP_AdEL);
11376 ctx->bstate = BS_STOP;
11377 return 2;
11378 }
11379
11380 op = (ctx->opcode >> 10) & 0x3f;
11381 /* Enforce properly-sized instructions in a delay slot */
11382 if (ctx->hflags & MIPS_HFLAG_BMASK) {
11383 int bits = ctx->hflags & MIPS_HFLAG_BMASK_EXT;
11384
11385 switch (op) {
11386 case POOL32A:
11387 case POOL32B:
11388 case POOL32I:
11389 case POOL32C:
11390 case ADDI32:
11391 case ADDIU32:
11392 case ORI32:
11393 case XORI32:
11394 case SLTI32:
11395 case SLTIU32:
11396 case ANDI32:
11397 case JALX32:
11398 case LBU32:
11399 case LHU32:
11400 case POOL32F:
11401 case JALS32:
11402 case BEQ32:
11403 case BNE32:
11404 case J32:
11405 case JAL32:
11406 case SB32:
11407 case SH32:
11408 case POOL32S:
11409 case ADDIUPC:
11410 case SWC132:
11411 case SDC132:
11412 case SD32:
11413 case SW32:
11414 case LB32:
11415 case LH32:
11416 case DADDIU32:
11417 case POOL48A: /* ??? */
11418 case LWC132:
11419 case LDC132:
11420 case LD32:
11421 case LW32:
11422 if (bits & MIPS_HFLAG_BDS16) {
11423 generate_exception(ctx, EXCP_RI);
11424 /* Just stop translation; the user is confused. */
11425 ctx->bstate = BS_STOP;
11426 return 2;
11427 }
11428 break;
11429 case POOL16A:
11430 case POOL16B:
11431 case POOL16C:
11432 case LWGP16:
11433 case POOL16F:
11434 case LBU16:
11435 case LHU16:
11436 case LWSP16:
11437 case LW16:
11438 case SB16:
11439 case SH16:
11440 case SWSP16:
11441 case SW16:
11442 case MOVE16:
11443 case ANDI16:
11444 case POOL16D:
11445 case POOL16E:
11446 case BEQZ16:
11447 case BNEZ16:
11448 case B16:
11449 case LI16:
11450 if (bits & MIPS_HFLAG_BDS32) {
11451 generate_exception(ctx, EXCP_RI);
11452 /* Just stop translation; the user is confused. */
11453 ctx->bstate = BS_STOP;
11454 return 2;
11455 }
11456 break;
11457 default:
11458 break;
11459 }
11460 }
11461 switch (op) {
11462 case POOL16A:
11463 {
11464 int rd = mmreg(uMIPS_RD(ctx->opcode));
11465 int rs1 = mmreg(uMIPS_RS1(ctx->opcode));
11466 int rs2 = mmreg(uMIPS_RS2(ctx->opcode));
11467 uint32_t opc = 0;
11468
11469 switch (ctx->opcode & 0x1) {
11470 case ADDU16:
11471 opc = OPC_ADDU;
11472 break;
11473 case SUBU16:
11474 opc = OPC_SUBU;
11475 break;
11476 }
11477
11478 gen_arith(env, ctx, opc, rd, rs1, rs2);
11479 }
11480 break;
11481 case POOL16B:
11482 {
11483 int rd = mmreg(uMIPS_RD(ctx->opcode));
11484 int rs = mmreg(uMIPS_RS(ctx->opcode));
11485 int amount = (ctx->opcode >> 1) & 0x7;
11486 uint32_t opc = 0;
11487 amount = amount == 0 ? 8 : amount;
11488
11489 switch (ctx->opcode & 0x1) {
11490 case SLL16:
11491 opc = OPC_SLL;
11492 break;
11493 case SRL16:
11494 opc = OPC_SRL;
11495 break;
11496 }
11497
11498 gen_shift_imm(env, ctx, opc, rd, rs, amount);
11499 }
11500 break;
11501 case POOL16C:
11502 gen_pool16c_insn(env, ctx, is_branch);
11503 break;
11504 case LWGP16:
11505 {
11506 int rd = mmreg(uMIPS_RD(ctx->opcode));
11507 int rb = 28; /* GP */
11508 int16_t offset = SIMM(ctx->opcode, 0, 7) << 2;
11509
afa88c3a 11510 gen_ld(env, ctx, OPC_LW, rd, rb, offset);
3c824109
NF
11511 }
11512 break;
11513 case POOL16F:
11514 if (ctx->opcode & 1) {
11515 generate_exception(ctx, EXCP_RI);
11516 } else {
11517 /* MOVEP */
11518 int enc_dest = uMIPS_RD(ctx->opcode);
11519 int enc_rt = uMIPS_RS2(ctx->opcode);
11520 int enc_rs = uMIPS_RS1(ctx->opcode);
11521 int rd, rs, re, rt;
11522 static const int rd_enc[] = { 5, 5, 6, 4, 4, 4, 4, 4 };
11523 static const int re_enc[] = { 6, 7, 7, 21, 22, 5, 6, 7 };
11524 static const int rs_rt_enc[] = { 0, 17, 2, 3, 16, 18, 19, 20 };
11525
11526 rd = rd_enc[enc_dest];
11527 re = re_enc[enc_dest];
11528 rs = rs_rt_enc[enc_rs];
11529 rt = rs_rt_enc[enc_rt];
11530
11531 gen_arith_imm(env, ctx, OPC_ADDIU, rd, rs, 0);
11532 gen_arith_imm(env, ctx, OPC_ADDIU, re, rt, 0);
11533 }
11534 break;
11535 case LBU16:
11536 {
11537 int rd = mmreg(uMIPS_RD(ctx->opcode));
11538 int rb = mmreg(uMIPS_RS(ctx->opcode));
11539 int16_t offset = ZIMM(ctx->opcode, 0, 4);
11540 offset = (offset == 0xf ? -1 : offset);
11541
afa88c3a 11542 gen_ld(env, ctx, OPC_LBU, rd, rb, offset);
3c824109
NF
11543 }
11544 break;
11545 case LHU16:
11546 {
11547 int rd = mmreg(uMIPS_RD(ctx->opcode));
11548 int rb = mmreg(uMIPS_RS(ctx->opcode));
11549 int16_t offset = ZIMM(ctx->opcode, 0, 4) << 1;
11550
afa88c3a 11551 gen_ld(env, ctx, OPC_LHU, rd, rb, offset);
3c824109
NF
11552 }
11553 break;
11554 case LWSP16:
11555 {
11556 int rd = (ctx->opcode >> 5) & 0x1f;
11557 int rb = 29; /* SP */
11558 int16_t offset = ZIMM(ctx->opcode, 0, 5) << 2;
11559
afa88c3a 11560 gen_ld(env, ctx, OPC_LW, rd, rb, offset);
3c824109
NF
11561 }
11562 break;
11563 case LW16:
11564 {
11565 int rd = mmreg(uMIPS_RD(ctx->opcode));
11566 int rb = mmreg(uMIPS_RS(ctx->opcode));
11567 int16_t offset = ZIMM(ctx->opcode, 0, 4) << 2;
11568
afa88c3a 11569 gen_ld(env, ctx, OPC_LW, rd, rb, offset);
3c824109
NF
11570 }
11571 break;
11572 case SB16:
11573 {
11574 int rd = mmreg2(uMIPS_RD(ctx->opcode));
11575 int rb = mmreg(uMIPS_RS(ctx->opcode));
11576 int16_t offset = ZIMM(ctx->opcode, 0, 4);
11577
5c13fdfd 11578 gen_st(ctx, OPC_SB, rd, rb, offset);
3c824109
NF
11579 }
11580 break;
11581 case SH16:
11582 {
11583 int rd = mmreg2(uMIPS_RD(ctx->opcode));
11584 int rb = mmreg(uMIPS_RS(ctx->opcode));
11585 int16_t offset = ZIMM(ctx->opcode, 0, 4) << 1;
11586
5c13fdfd 11587 gen_st(ctx, OPC_SH, rd, rb, offset);
3c824109
NF
11588 }
11589 break;
11590 case SWSP16:
11591 {
11592 int rd = (ctx->opcode >> 5) & 0x1f;
11593 int rb = 29; /* SP */
11594 int16_t offset = ZIMM(ctx->opcode, 0, 5) << 2;
11595
5c13fdfd 11596 gen_st(ctx, OPC_SW, rd, rb, offset);
3c824109
NF
11597 }
11598 break;
11599 case SW16:
11600 {
11601 int rd = mmreg2(uMIPS_RD(ctx->opcode));
11602 int rb = mmreg(uMIPS_RS(ctx->opcode));
11603 int16_t offset = ZIMM(ctx->opcode, 0, 4) << 2;
11604
5c13fdfd 11605 gen_st(ctx, OPC_SW, rd, rb, offset);
3c824109
NF
11606 }
11607 break;
11608 case MOVE16:
11609 {
11610 int rd = uMIPS_RD5(ctx->opcode);
11611 int rs = uMIPS_RS5(ctx->opcode);
11612
11613 gen_arith_imm(env, ctx, OPC_ADDIU, rd, rs, 0);
11614 }
11615 break;
11616 case ANDI16:
11617 gen_andi16(env, ctx);
11618 break;
11619 case POOL16D:
11620 switch (ctx->opcode & 0x1) {
11621 case ADDIUS5:
11622 gen_addius5(env, ctx);
11623 break;
11624 case ADDIUSP:
11625 gen_addiusp(env, ctx);
11626 break;
11627 }
11628 break;
11629 case POOL16E:
11630 switch (ctx->opcode & 0x1) {
11631 case ADDIUR2:
11632 gen_addiur2(env, ctx);
11633 break;
11634 case ADDIUR1SP:
11635 gen_addiur1sp(env, ctx);
11636 break;
11637 }
11638 break;
11639 case B16:
11640 gen_compute_branch(ctx, OPC_BEQ, 2, 0, 0,
11641 SIMM(ctx->opcode, 0, 10) << 1);
11642 *is_branch = 1;
11643 break;
11644 case BNEZ16:
11645 case BEQZ16:
11646 gen_compute_branch(ctx, op == BNEZ16 ? OPC_BNE : OPC_BEQ, 2,
11647 mmreg(uMIPS_RD(ctx->opcode)),
11648 0, SIMM(ctx->opcode, 0, 7) << 1);
11649 *is_branch = 1;
11650 break;
11651 case LI16:
11652 {
11653 int reg = mmreg(uMIPS_RD(ctx->opcode));
11654 int imm = ZIMM(ctx->opcode, 0, 7);
11655
11656 imm = (imm == 0x7f ? -1 : imm);
11657 tcg_gen_movi_tl(cpu_gpr[reg], imm);
11658 }
11659 break;
11660 case RES_20:
11661 case RES_28:
11662 case RES_29:
11663 case RES_30:
11664 case RES_31:
11665 case RES_38:
11666 case RES_39:
11667 generate_exception(ctx, EXCP_RI);
11668 break;
11669 default:
11670 decode_micromips32_opc (env, ctx, op, is_branch);
11671 return 4;
11672 }
11673
11674 return 2;
11675}
11676
11677/* SmartMIPS extension to MIPS32 */
11678
11679#if defined(TARGET_MIPS64)
11680
11681/* MDMX extension to MIPS64 */
11682
11683#endif
11684
7db13fae 11685static void decode_opc (CPUMIPSState *env, DisasContext *ctx, int *is_branch)
3c824109
NF
11686{
11687 int32_t offset;
11688 int rs, rt, rd, sa;
11689 uint32_t op, op1, op2;
11690 int16_t imm;
11691
11692 /* make sure instructions are on a word boundary */
11693 if (ctx->pc & 0x3) {
11694 env->CP0_BadVAddr = ctx->pc;
11695 generate_exception(ctx, EXCP_AdEL);
11696 return;
11697 }
11698
11699 /* Handle blikely not taken case */
11700 if ((ctx->hflags & MIPS_HFLAG_BMASK_BASE) == MIPS_HFLAG_BL) {
11701 int l1 = gen_new_label();
11702
11703 MIPS_DEBUG("blikely condition (" TARGET_FMT_lx ")", ctx->pc + 4);
11704 tcg_gen_brcondi_tl(TCG_COND_NE, bcond, 0, l1);
11705 tcg_gen_movi_i32(hflags, ctx->hflags & ~MIPS_HFLAG_BMASK);
11706 gen_goto_tb(ctx, 1, ctx->pc + 4);
11707 gen_set_label(l1);
11708 }
11709
11710 if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP)))
11711 tcg_gen_debug_insn_start(ctx->pc);
11712
11713 op = MASK_OP_MAJOR(ctx->opcode);
11714 rs = (ctx->opcode >> 21) & 0x1f;
11715 rt = (ctx->opcode >> 16) & 0x1f;
11716 rd = (ctx->opcode >> 11) & 0x1f;
11717 sa = (ctx->opcode >> 6) & 0x1f;
11718 imm = (int16_t)ctx->opcode;
11719 switch (op) {
7a387fff
TS
11720 case OPC_SPECIAL:
11721 op1 = MASK_SPECIAL(ctx->opcode);
6af0bf9c 11722 switch (op1) {
324d9e32
AJ
11723 case OPC_SLL: /* Shift with immediate */
11724 case OPC_SRA:
324d9e32 11725 gen_shift_imm(env, ctx, op1, rd, rt, sa);
7a387fff 11726 break;
ea63e2c3
NF
11727 case OPC_SRL:
11728 switch ((ctx->opcode >> 21) & 0x1f) {
11729 case 1:
11730 /* rotr is decoded as srl on non-R2 CPUs */
11731 if (env->insn_flags & ISA_MIPS32R2) {
11732 op1 = OPC_ROTR;
11733 }
11734 /* Fallthrough */
11735 case 0:
11736 gen_shift_imm(env, ctx, op1, rd, rt, sa);
11737 break;
11738 default:
11739 generate_exception(ctx, EXCP_RI);
11740 break;
11741 }
11742 break;
460f00c4
AJ
11743 case OPC_MOVN: /* Conditional move */
11744 case OPC_MOVZ:
aa8f4009
AJ
11745 check_insn(env, ctx, ISA_MIPS4 | ISA_MIPS32 |
11746 INSN_LOONGSON2E | INSN_LOONGSON2F);
460f00c4
AJ
11747 gen_cond_move(env, op1, rd, rs, rt);
11748 break;
11749 case OPC_ADD ... OPC_SUBU:
e189e748 11750 gen_arith(env, ctx, op1, rd, rs, rt);
7a387fff 11751 break;
460f00c4 11752 case OPC_SLLV: /* Shifts */
460f00c4
AJ
11753 case OPC_SRAV:
11754 gen_shift(env, ctx, op1, rd, rs, rt);
11755 break;
ea63e2c3
NF
11756 case OPC_SRLV:
11757 switch ((ctx->opcode >> 6) & 0x1f) {
11758 case 1:
11759 /* rotrv is decoded as srlv on non-R2 CPUs */
11760 if (env->insn_flags & ISA_MIPS32R2) {
11761 op1 = OPC_ROTRV;
11762 }
11763 /* Fallthrough */
11764 case 0:
11765 gen_shift(env, ctx, op1, rd, rs, rt);
11766 break;
11767 default:
11768 generate_exception(ctx, EXCP_RI);
11769 break;
11770 }
11771 break;
460f00c4
AJ
11772 case OPC_SLT: /* Set on less than */
11773 case OPC_SLTU:
11774 gen_slt(env, op1, rd, rs, rt);
11775 break;
11776 case OPC_AND: /* Logic*/
11777 case OPC_OR:
11778 case OPC_NOR:
11779 case OPC_XOR:
11780 gen_logic(env, op1, rd, rs, rt);
11781 break;
7a387fff 11782 case OPC_MULT ... OPC_DIVU:
e9c71dd1
TS
11783 if (sa) {
11784 check_insn(env, ctx, INSN_VR54XX);
11785 op1 = MASK_MUL_VR54XX(ctx->opcode);
11786 gen_mul_vr54xx(ctx, op1, rd, rs, rt);
11787 } else
11788 gen_muldiv(ctx, op1, rs, rt);
7a387fff
TS
11789 break;
11790 case OPC_JR ... OPC_JALR:
7dca4ad0 11791 gen_compute_branch(ctx, op1, 4, rs, rd, sa);
c9602061
NF
11792 *is_branch = 1;
11793 break;
7a387fff
TS
11794 case OPC_TGE ... OPC_TEQ: /* Traps */
11795 case OPC_TNE:
11796 gen_trap(ctx, op1, rs, rt, -1);
6af0bf9c 11797 break;
7a387fff
TS
11798 case OPC_MFHI: /* Move from HI/LO */
11799 case OPC_MFLO:
11800 gen_HILO(ctx, op1, rd);
6af0bf9c 11801 break;
7a387fff
TS
11802 case OPC_MTHI:
11803 case OPC_MTLO: /* Move to HI/LO */
11804 gen_HILO(ctx, op1, rs);
6af0bf9c 11805 break;
b48cfdff
TS
11806 case OPC_PMON: /* Pmon entry point, also R4010 selsl */
11807#ifdef MIPS_STRICT_STANDARD
11808 MIPS_INVAL("PMON / selsl");
11809 generate_exception(ctx, EXCP_RI);
11810#else
a7812ae4 11811 gen_helper_0i(pmon, sa);
b48cfdff 11812#endif
7a387fff
TS
11813 break;
11814 case OPC_SYSCALL:
6af0bf9c 11815 generate_exception(ctx, EXCP_SYSCALL);
8e0f950d 11816 ctx->bstate = BS_STOP;
6af0bf9c 11817 break;
7a387fff 11818 case OPC_BREAK:
6af0bf9c
FB
11819 generate_exception(ctx, EXCP_BREAK);
11820 break;
b48cfdff
TS
11821 case OPC_SPIM:
11822#ifdef MIPS_STRICT_STANDARD
11823 MIPS_INVAL("SPIM");
11824 generate_exception(ctx, EXCP_RI);
11825#else
7a387fff
TS
11826 /* Implemented as RI exception for now. */
11827 MIPS_INVAL("spim (unofficial)");
11828 generate_exception(ctx, EXCP_RI);
b48cfdff 11829#endif
6af0bf9c 11830 break;
7a387fff 11831 case OPC_SYNC:
ead9360e 11832 /* Treat as NOP. */
6af0bf9c 11833 break;
4ad40f36 11834
7a387fff 11835 case OPC_MOVCI:
e189e748 11836 check_insn(env, ctx, ISA_MIPS4 | ISA_MIPS32);
36d23958 11837 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
5e755519 11838 check_cp1_enabled(ctx);
36d23958
TS
11839 gen_movci(ctx, rd, rs, (ctx->opcode >> 18) & 0x7,
11840 (ctx->opcode >> 16) & 1);
11841 } else {
e397ee33 11842 generate_exception_err(ctx, EXCP_CpU, 1);
36d23958 11843 }
4ad40f36
FB
11844 break;
11845
d26bc211 11846#if defined(TARGET_MIPS64)
7a387fff
TS
11847 /* MIPS64 specific opcodes */
11848 case OPC_DSLL:
324d9e32 11849 case OPC_DSRA:
7a387fff 11850 case OPC_DSLL32:
324d9e32 11851 case OPC_DSRA32:
e189e748
TS
11852 check_insn(env, ctx, ISA_MIPS3);
11853 check_mips_64(ctx);
324d9e32 11854 gen_shift_imm(env, ctx, op1, rd, rt, sa);
7a387fff 11855 break;
ea63e2c3
NF
11856 case OPC_DSRL:
11857 switch ((ctx->opcode >> 21) & 0x1f) {
11858 case 1:
11859 /* drotr is decoded as dsrl on non-R2 CPUs */
11860 if (env->insn_flags & ISA_MIPS32R2) {
11861 op1 = OPC_DROTR;
11862 }
11863 /* Fallthrough */
11864 case 0:
11865 check_insn(env, ctx, ISA_MIPS3);
11866 check_mips_64(ctx);
11867 gen_shift_imm(env, ctx, op1, rd, rt, sa);
11868 break;
11869 default:
11870 generate_exception(ctx, EXCP_RI);
11871 break;
11872 }
11873 break;
11874 case OPC_DSRL32:
11875 switch ((ctx->opcode >> 21) & 0x1f) {
11876 case 1:
11877 /* drotr32 is decoded as dsrl32 on non-R2 CPUs */
11878 if (env->insn_flags & ISA_MIPS32R2) {
11879 op1 = OPC_DROTR32;
11880 }
11881 /* Fallthrough */
11882 case 0:
11883 check_insn(env, ctx, ISA_MIPS3);
11884 check_mips_64(ctx);
11885 gen_shift_imm(env, ctx, op1, rd, rt, sa);
11886 break;
11887 default:
11888 generate_exception(ctx, EXCP_RI);
11889 break;
11890 }
11891 break;
7a387fff 11892 case OPC_DADD ... OPC_DSUBU:
e189e748
TS
11893 check_insn(env, ctx, ISA_MIPS3);
11894 check_mips_64(ctx);
11895 gen_arith(env, ctx, op1, rd, rs, rt);
7a387fff 11896 break;
460f00c4
AJ
11897 case OPC_DSLLV:
11898 case OPC_DSRAV:
460f00c4
AJ
11899 check_insn(env, ctx, ISA_MIPS3);
11900 check_mips_64(ctx);
11901 gen_shift(env, ctx, op1, rd, rs, rt);
11902 break;
ea63e2c3
NF
11903 case OPC_DSRLV:
11904 switch ((ctx->opcode >> 6) & 0x1f) {
11905 case 1:
11906 /* drotrv is decoded as dsrlv on non-R2 CPUs */
11907 if (env->insn_flags & ISA_MIPS32R2) {
11908 op1 = OPC_DROTRV;
11909 }
11910 /* Fallthrough */
11911 case 0:
11912 check_insn(env, ctx, ISA_MIPS3);
11913 check_mips_64(ctx);
11914 gen_shift(env, ctx, op1, rd, rs, rt);
11915 break;
11916 default:
11917 generate_exception(ctx, EXCP_RI);
11918 break;
11919 }
11920 break;
7a387fff 11921 case OPC_DMULT ... OPC_DDIVU:
e189e748
TS
11922 check_insn(env, ctx, ISA_MIPS3);
11923 check_mips_64(ctx);
7a387fff
TS
11924 gen_muldiv(ctx, op1, rs, rt);
11925 break;
6af0bf9c
FB
11926#endif
11927 default: /* Invalid */
11928 MIPS_INVAL("special");
11929 generate_exception(ctx, EXCP_RI);
11930 break;
11931 }
11932 break;
7a387fff
TS
11933 case OPC_SPECIAL2:
11934 op1 = MASK_SPECIAL2(ctx->opcode);
6af0bf9c 11935 switch (op1) {
7a387fff
TS
11936 case OPC_MADD ... OPC_MADDU: /* Multiply and add/sub */
11937 case OPC_MSUB ... OPC_MSUBU:
e189e748 11938 check_insn(env, ctx, ISA_MIPS32);
7a387fff 11939 gen_muldiv(ctx, op1, rs, rt);
6af0bf9c 11940 break;
7a387fff 11941 case OPC_MUL:
e189e748 11942 gen_arith(env, ctx, op1, rd, rs, rt);
6af0bf9c 11943 break;
20e1fb52
AJ
11944 case OPC_CLO:
11945 case OPC_CLZ:
e189e748 11946 check_insn(env, ctx, ISA_MIPS32);
7a387fff 11947 gen_cl(ctx, op1, rd, rs);
6af0bf9c 11948 break;
7a387fff 11949 case OPC_SDBBP:
6af0bf9c
FB
11950 /* XXX: not clear which exception should be raised
11951 * when in debug mode...
11952 */
e189e748 11953 check_insn(env, ctx, ISA_MIPS32);
6af0bf9c
FB
11954 if (!(ctx->hflags & MIPS_HFLAG_DM)) {
11955 generate_exception(ctx, EXCP_DBp);
11956 } else {
11957 generate_exception(ctx, EXCP_DBp);
11958 }
ead9360e 11959 /* Treat as NOP. */
6af0bf9c 11960 break;
161f85e6
AJ
11961 case OPC_DIV_G_2F:
11962 case OPC_DIVU_G_2F:
11963 case OPC_MULT_G_2F:
11964 case OPC_MULTU_G_2F:
11965 case OPC_MOD_G_2F:
11966 case OPC_MODU_G_2F:
11967 check_insn(env, ctx, INSN_LOONGSON2F);
11968 gen_loongson_integer(ctx, op1, rd, rs, rt);
11969 break;
d26bc211 11970#if defined(TARGET_MIPS64)
20e1fb52
AJ
11971 case OPC_DCLO:
11972 case OPC_DCLZ:
e189e748
TS
11973 check_insn(env, ctx, ISA_MIPS64);
11974 check_mips_64(ctx);
7a387fff
TS
11975 gen_cl(ctx, op1, rd, rs);
11976 break;
161f85e6
AJ
11977 case OPC_DMULT_G_2F:
11978 case OPC_DMULTU_G_2F:
11979 case OPC_DDIV_G_2F:
11980 case OPC_DDIVU_G_2F:
11981 case OPC_DMOD_G_2F:
11982 case OPC_DMODU_G_2F:
11983 check_insn(env, ctx, INSN_LOONGSON2F);
11984 gen_loongson_integer(ctx, op1, rd, rs, rt);
11985 break;
7a387fff 11986#endif
6af0bf9c
FB
11987 default: /* Invalid */
11988 MIPS_INVAL("special2");
11989 generate_exception(ctx, EXCP_RI);
11990 break;
11991 }
11992 break;
7a387fff 11993 case OPC_SPECIAL3:
2b0233ab
TS
11994 op1 = MASK_SPECIAL3(ctx->opcode);
11995 switch (op1) {
11996 case OPC_EXT:
11997 case OPC_INS:
11998 check_insn(env, ctx, ISA_MIPS32R2);
11999 gen_bitops(ctx, op1, rt, rs, sa, rd);
12000 break;
12001 case OPC_BSHFL:
12002 check_insn(env, ctx, ISA_MIPS32R2);
12003 op2 = MASK_BSHFL(ctx->opcode);
49bcf33c 12004 gen_bshfl(ctx, op2, rt, rd);
7a387fff 12005 break;
1579a72e 12006 case OPC_RDHWR:
26ebe468 12007 gen_rdhwr(env, ctx, rt, rd);
1579a72e 12008 break;
ead9360e 12009 case OPC_FORK:
7385ac0b 12010 check_insn(env, ctx, ASE_MT);
6c5c1e20 12011 {
35fbce2c
AJ
12012 TCGv t0 = tcg_temp_new();
12013 TCGv t1 = tcg_temp_new();
6c5c1e20
TS
12014
12015 gen_load_gpr(t0, rt);
12016 gen_load_gpr(t1, rs);
a7812ae4 12017 gen_helper_fork(t0, t1);
6c5c1e20
TS
12018 tcg_temp_free(t0);
12019 tcg_temp_free(t1);
12020 }
ead9360e
TS
12021 break;
12022 case OPC_YIELD:
7385ac0b 12023 check_insn(env, ctx, ASE_MT);
6c5c1e20 12024 {
35fbce2c 12025 TCGv t0 = tcg_temp_new();
6c5c1e20 12026
35fbce2c 12027 save_cpu_state(ctx, 1);
6c5c1e20 12028 gen_load_gpr(t0, rs);
a7812ae4 12029 gen_helper_yield(t0, t0);
6c5c1e20
TS
12030 gen_store_gpr(t0, rd);
12031 tcg_temp_free(t0);
12032 }
ead9360e 12033 break;
161f85e6
AJ
12034 case OPC_DIV_G_2E ... OPC_DIVU_G_2E:
12035 case OPC_MULT_G_2E ... OPC_MULTU_G_2E:
12036 case OPC_MOD_G_2E ... OPC_MODU_G_2E:
12037 check_insn(env, ctx, INSN_LOONGSON2E);
12038 gen_loongson_integer(ctx, op1, rd, rs, rt);
12039 break;
d26bc211 12040#if defined(TARGET_MIPS64)
1579a72e
TS
12041 case OPC_DEXTM ... OPC_DEXT:
12042 case OPC_DINSM ... OPC_DINS:
e189e748
TS
12043 check_insn(env, ctx, ISA_MIPS64R2);
12044 check_mips_64(ctx);
1579a72e 12045 gen_bitops(ctx, op1, rt, rs, sa, rd);
7a387fff 12046 break;
1579a72e 12047 case OPC_DBSHFL:
e189e748
TS
12048 check_insn(env, ctx, ISA_MIPS64R2);
12049 check_mips_64(ctx);
1579a72e 12050 op2 = MASK_DBSHFL(ctx->opcode);
49bcf33c 12051 gen_bshfl(ctx, op2, rt, rd);
c6d6dd7c 12052 break;
161f85e6
AJ
12053 case OPC_DDIV_G_2E ... OPC_DDIVU_G_2E:
12054 case OPC_DMULT_G_2E ... OPC_DMULTU_G_2E:
12055 case OPC_DMOD_G_2E ... OPC_DMODU_G_2E:
12056 check_insn(env, ctx, INSN_LOONGSON2E);
12057 gen_loongson_integer(ctx, op1, rd, rs, rt);
12058 break;
7a387fff
TS
12059#endif
12060 default: /* Invalid */
12061 MIPS_INVAL("special3");
12062 generate_exception(ctx, EXCP_RI);
12063 break;
12064 }
12065 break;
12066 case OPC_REGIMM:
12067 op1 = MASK_REGIMM(ctx->opcode);
12068 switch (op1) {
12069 case OPC_BLTZ ... OPC_BGEZL: /* REGIMM branches */
12070 case OPC_BLTZAL ... OPC_BGEZALL:
7dca4ad0 12071 gen_compute_branch(ctx, op1, 4, rs, -1, imm << 2);
c9602061
NF
12072 *is_branch = 1;
12073 break;
7a387fff
TS
12074 case OPC_TGEI ... OPC_TEQI: /* REGIMM traps */
12075 case OPC_TNEI:
12076 gen_trap(ctx, op1, rs, -1, imm);
12077 break;
12078 case OPC_SYNCI:
e189e748 12079 check_insn(env, ctx, ISA_MIPS32R2);
ead9360e 12080 /* Treat as NOP. */
6af0bf9c
FB
12081 break;
12082 default: /* Invalid */
923617a3 12083 MIPS_INVAL("regimm");
6af0bf9c
FB
12084 generate_exception(ctx, EXCP_RI);
12085 break;
12086 }
12087 break;
7a387fff 12088 case OPC_CP0:
387a8fe5 12089 check_cp0_enabled(ctx);
7a387fff 12090 op1 = MASK_CP0(ctx->opcode);
6af0bf9c 12091 switch (op1) {
7a387fff
TS
12092 case OPC_MFC0:
12093 case OPC_MTC0:
ead9360e
TS
12094 case OPC_MFTR:
12095 case OPC_MTTR:
d26bc211 12096#if defined(TARGET_MIPS64)
7a387fff
TS
12097 case OPC_DMFC0:
12098 case OPC_DMTC0:
12099#endif
f1aa6320 12100#ifndef CONFIG_USER_ONLY
932e71cd 12101 gen_cp0(env, ctx, op1, rt, rd);
0eaef5aa 12102#endif /* !CONFIG_USER_ONLY */
7a387fff
TS
12103 break;
12104 case OPC_C0_FIRST ... OPC_C0_LAST:
f1aa6320 12105#ifndef CONFIG_USER_ONLY
932e71cd 12106 gen_cp0(env, ctx, MASK_C0(ctx->opcode), rt, rd);
0eaef5aa 12107#endif /* !CONFIG_USER_ONLY */
7a387fff
TS
12108 break;
12109 case OPC_MFMC0:
8706c382 12110#ifndef CONFIG_USER_ONLY
932e71cd 12111 {
35fbce2c 12112 TCGv t0 = tcg_temp_new();
6c5c1e20 12113
0eaef5aa 12114 op2 = MASK_MFMC0(ctx->opcode);
6c5c1e20
TS
12115 switch (op2) {
12116 case OPC_DMT:
12117 check_insn(env, ctx, ASE_MT);
9ed5726c 12118 gen_helper_dmt(t0);
35fbce2c 12119 gen_store_gpr(t0, rt);
6c5c1e20
TS
12120 break;
12121 case OPC_EMT:
12122 check_insn(env, ctx, ASE_MT);
9ed5726c 12123 gen_helper_emt(t0);
35fbce2c 12124 gen_store_gpr(t0, rt);
da80682b 12125 break;
6c5c1e20
TS
12126 case OPC_DVPE:
12127 check_insn(env, ctx, ASE_MT);
9ed5726c 12128 gen_helper_dvpe(t0);
35fbce2c 12129 gen_store_gpr(t0, rt);
6c5c1e20
TS
12130 break;
12131 case OPC_EVPE:
12132 check_insn(env, ctx, ASE_MT);
9ed5726c 12133 gen_helper_evpe(t0);
35fbce2c 12134 gen_store_gpr(t0, rt);
6c5c1e20
TS
12135 break;
12136 case OPC_DI:
12137 check_insn(env, ctx, ISA_MIPS32R2);
867abc7e 12138 save_cpu_state(ctx, 1);
a7812ae4 12139 gen_helper_di(t0);
35fbce2c 12140 gen_store_gpr(t0, rt);
6c5c1e20
TS
12141 /* Stop translation as we may have switched the execution mode */
12142 ctx->bstate = BS_STOP;
12143 break;
12144 case OPC_EI:
12145 check_insn(env, ctx, ISA_MIPS32R2);
867abc7e 12146 save_cpu_state(ctx, 1);
a7812ae4 12147 gen_helper_ei(t0);
35fbce2c 12148 gen_store_gpr(t0, rt);
6c5c1e20
TS
12149 /* Stop translation as we may have switched the execution mode */
12150 ctx->bstate = BS_STOP;
12151 break;
12152 default: /* Invalid */
12153 MIPS_INVAL("mfmc0");
12154 generate_exception(ctx, EXCP_RI);
12155 break;
12156 }
6c5c1e20 12157 tcg_temp_free(t0);
7a387fff 12158 }
0eaef5aa 12159#endif /* !CONFIG_USER_ONLY */
6af0bf9c 12160 break;
7a387fff 12161 case OPC_RDPGPR:
e189e748 12162 check_insn(env, ctx, ISA_MIPS32R2);
be24bb4f 12163 gen_load_srsgpr(rt, rd);
ead9360e 12164 break;
7a387fff 12165 case OPC_WRPGPR:
e189e748 12166 check_insn(env, ctx, ISA_MIPS32R2);
be24bb4f 12167 gen_store_srsgpr(rt, rd);
38121543 12168 break;
6af0bf9c 12169 default:
923617a3 12170 MIPS_INVAL("cp0");
7a387fff 12171 generate_exception(ctx, EXCP_RI);
6af0bf9c
FB
12172 break;
12173 }
12174 break;
324d9e32
AJ
12175 case OPC_ADDI: /* Arithmetic with immediate opcode */
12176 case OPC_ADDIU:
e189e748 12177 gen_arith_imm(env, ctx, op, rt, rs, imm);
7a387fff 12178 break;
324d9e32
AJ
12179 case OPC_SLTI: /* Set on less than with immediate opcode */
12180 case OPC_SLTIU:
12181 gen_slt_imm(env, op, rt, rs, imm);
12182 break;
12183 case OPC_ANDI: /* Arithmetic with immediate opcode */
12184 case OPC_LUI:
12185 case OPC_ORI:
12186 case OPC_XORI:
12187 gen_logic_imm(env, op, rt, rs, imm);
12188 break;
7a387fff
TS
12189 case OPC_J ... OPC_JAL: /* Jump */
12190 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2;
7dca4ad0 12191 gen_compute_branch(ctx, op, 4, rs, rt, offset);
c9602061
NF
12192 *is_branch = 1;
12193 break;
7a387fff
TS
12194 case OPC_BEQ ... OPC_BGTZ: /* Branch */
12195 case OPC_BEQL ... OPC_BGTZL:
7dca4ad0 12196 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2);
c9602061
NF
12197 *is_branch = 1;
12198 break;
7a387fff 12199 case OPC_LB ... OPC_LWR: /* Load and stores */
5c13fdfd 12200 case OPC_LL:
afa88c3a 12201 gen_ld(env, ctx, op, rt, rs, imm);
5c13fdfd 12202 break;
7a387fff
TS
12203 case OPC_SB ... OPC_SW:
12204 case OPC_SWR:
5c13fdfd 12205 gen_st(ctx, op, rt, rs, imm);
7a387fff 12206 break;
d66c7132
AJ
12207 case OPC_SC:
12208 gen_st_cond(ctx, op, rt, rs, imm);
12209 break;
7a387fff 12210 case OPC_CACHE:
e189e748 12211 check_insn(env, ctx, ISA_MIPS3 | ISA_MIPS32);
ead9360e 12212 /* Treat as NOP. */
34ae7b51 12213 break;
7a387fff 12214 case OPC_PREF:
e189e748 12215 check_insn(env, ctx, ISA_MIPS4 | ISA_MIPS32);
ead9360e 12216 /* Treat as NOP. */
6af0bf9c 12217 break;
4ad40f36 12218
923617a3 12219 /* Floating point (COP1). */
7a387fff
TS
12220 case OPC_LWC1:
12221 case OPC_LDC1:
12222 case OPC_SWC1:
12223 case OPC_SDC1:
26ebe468 12224 gen_cop1_ldst(env, ctx, op, rt, rs, imm);
6ea83fed
FB
12225 break;
12226
7a387fff 12227 case OPC_CP1:
36d23958 12228 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
5e755519 12229 check_cp1_enabled(ctx);
36d23958
TS
12230 op1 = MASK_CP1(ctx->opcode);
12231 switch (op1) {
3a95e3a7
TS
12232 case OPC_MFHC1:
12233 case OPC_MTHC1:
e189e748 12234 check_insn(env, ctx, ISA_MIPS32R2);
36d23958
TS
12235 case OPC_MFC1:
12236 case OPC_CFC1:
12237 case OPC_MTC1:
12238 case OPC_CTC1:
e189e748
TS
12239 gen_cp1(ctx, op1, rt, rd);
12240 break;
d26bc211 12241#if defined(TARGET_MIPS64)
36d23958
TS
12242 case OPC_DMFC1:
12243 case OPC_DMTC1:
e189e748 12244 check_insn(env, ctx, ISA_MIPS3);
36d23958
TS
12245 gen_cp1(ctx, op1, rt, rd);
12246 break;
e189e748 12247#endif
fbcc6828
TS
12248 case OPC_BC1ANY2:
12249 case OPC_BC1ANY4:
b8aa4598 12250 check_cop1x(ctx);
7385ac0b 12251 check_insn(env, ctx, ASE_MIPS3D);
d8a5950a
TS
12252 /* fall through */
12253 case OPC_BC1:
e189e748 12254 gen_compute_branch1(env, ctx, MASK_BC1(ctx->opcode),
5a5012ec 12255 (rt >> 2) & 0x7, imm << 2);
c9602061
NF
12256 *is_branch = 1;
12257 break;
36d23958
TS
12258 case OPC_S_FMT:
12259 case OPC_D_FMT:
12260 case OPC_W_FMT:
12261 case OPC_L_FMT:
5a5012ec 12262 case OPC_PS_FMT:
bf4120ad 12263 gen_farith(ctx, ctx->opcode & FOP(0x3f, 0x1f), rt, rd, sa,
5a5012ec 12264 (imm >> 8) & 0x7);
36d23958
TS
12265 break;
12266 default:
923617a3 12267 MIPS_INVAL("cp1");
e397ee33 12268 generate_exception (ctx, EXCP_RI);
36d23958
TS
12269 break;
12270 }
12271 } else {
12272 generate_exception_err(ctx, EXCP_CpU, 1);
6ea83fed 12273 }
4ad40f36
FB
12274 break;
12275
12276 /* COP2. */
7a387fff
TS
12277 case OPC_LWC2:
12278 case OPC_LDC2:
12279 case OPC_SWC2:
12280 case OPC_SDC2:
12281 case OPC_CP2:
12282 /* COP2: Not implemented. */
4ad40f36
FB
12283 generate_exception_err(ctx, EXCP_CpU, 2);
12284 break;
12285
7a387fff 12286 case OPC_CP3:
36d23958 12287 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
5e755519 12288 check_cp1_enabled(ctx);
36d23958
TS
12289 op1 = MASK_CP3(ctx->opcode);
12290 switch (op1) {
5a5012ec
TS
12291 case OPC_LWXC1:
12292 case OPC_LDXC1:
12293 case OPC_LUXC1:
12294 case OPC_SWXC1:
12295 case OPC_SDXC1:
12296 case OPC_SUXC1:
93b12ccc 12297 gen_flt3_ldst(ctx, op1, sa, rd, rs, rt);
5a5012ec 12298 break;
e0c84da7 12299 case OPC_PREFX:
ead9360e 12300 /* Treat as NOP. */
e0c84da7 12301 break;
5a5012ec
TS
12302 case OPC_ALNV_PS:
12303 case OPC_MADD_S:
12304 case OPC_MADD_D:
12305 case OPC_MADD_PS:
12306 case OPC_MSUB_S:
12307 case OPC_MSUB_D:
12308 case OPC_MSUB_PS:
12309 case OPC_NMADD_S:
12310 case OPC_NMADD_D:
12311 case OPC_NMADD_PS:
12312 case OPC_NMSUB_S:
12313 case OPC_NMSUB_D:
12314 case OPC_NMSUB_PS:
12315 gen_flt3_arith(ctx, op1, sa, rs, rd, rt);
12316 break;
36d23958 12317 default:
923617a3 12318 MIPS_INVAL("cp3");
e397ee33 12319 generate_exception (ctx, EXCP_RI);
36d23958
TS
12320 break;
12321 }
12322 } else {
e397ee33 12323 generate_exception_err(ctx, EXCP_CpU, 1);
7a387fff 12324 }
4ad40f36
FB
12325 break;
12326
d26bc211 12327#if defined(TARGET_MIPS64)
7a387fff
TS
12328 /* MIPS64 opcodes */
12329 case OPC_LWU:
12330 case OPC_LDL ... OPC_LDR:
7a387fff
TS
12331 case OPC_LLD:
12332 case OPC_LD:
5c13fdfd
AJ
12333 check_insn(env, ctx, ISA_MIPS3);
12334 check_mips_64(ctx);
afa88c3a 12335 gen_ld(env, ctx, op, rt, rs, imm);
5c13fdfd
AJ
12336 break;
12337 case OPC_SDL ... OPC_SDR:
7a387fff 12338 case OPC_SD:
e189e748
TS
12339 check_insn(env, ctx, ISA_MIPS3);
12340 check_mips_64(ctx);
5c13fdfd 12341 gen_st(ctx, op, rt, rs, imm);
7a387fff 12342 break;
d66c7132
AJ
12343 case OPC_SCD:
12344 check_insn(env, ctx, ISA_MIPS3);
12345 check_mips_64(ctx);
12346 gen_st_cond(ctx, op, rt, rs, imm);
12347 break;
324d9e32
AJ
12348 case OPC_DADDI:
12349 case OPC_DADDIU:
e189e748
TS
12350 check_insn(env, ctx, ISA_MIPS3);
12351 check_mips_64(ctx);
12352 gen_arith_imm(env, ctx, op, rt, rs, imm);
7a387fff 12353 break;
6af0bf9c 12354#endif
7a387fff 12355 case OPC_JALX:
3c824109 12356 check_insn(env, ctx, ASE_MIPS16 | ASE_MICROMIPS);
364d4831
NF
12357 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2;
12358 gen_compute_branch(ctx, op, 4, rs, rt, offset);
12359 *is_branch = 1;
12360 break;
7a387fff 12361 case OPC_MDMX:
e189e748 12362 check_insn(env, ctx, ASE_MDMX);
7a387fff 12363 /* MDMX: Not implemented. */
6af0bf9c 12364 default: /* Invalid */
923617a3 12365 MIPS_INVAL("major opcode");
6af0bf9c
FB
12366 generate_exception(ctx, EXCP_RI);
12367 break;
12368 }
6af0bf9c
FB
12369}
12370
2cfc5f17 12371static inline void
7db13fae 12372gen_intermediate_code_internal (CPUMIPSState *env, TranslationBlock *tb,
820e00f2 12373 int search_pc)
6af0bf9c 12374{
278d0702 12375 DisasContext ctx;
6af0bf9c
FB
12376 target_ulong pc_start;
12377 uint16_t *gen_opc_end;
a1d1bb31 12378 CPUBreakpoint *bp;
6af0bf9c 12379 int j, lj = -1;
2e70f6ef
PB
12380 int num_insns;
12381 int max_insns;
c9602061
NF
12382 int insn_bytes;
12383 int is_branch;
6af0bf9c 12384
93fcfe39
AL
12385 if (search_pc)
12386 qemu_log("search pc %d\n", search_pc);
4ad40f36 12387
6af0bf9c 12388 pc_start = tb->pc;
d42320c2 12389 gen_opc_end = gen_opc_buf + OPC_MAX_SIZE;
6af0bf9c 12390 ctx.pc = pc_start;
4ad40f36 12391 ctx.saved_pc = -1;
7b270ef2 12392 ctx.singlestep_enabled = env->singlestep_enabled;
6af0bf9c
FB
12393 ctx.tb = tb;
12394 ctx.bstate = BS_NONE;
4ad40f36 12395 /* Restore delay slot state from the tb context. */
c068688b 12396 ctx.hflags = (uint32_t)tb->flags; /* FIXME: maybe use 64 bits here? */
fd4a04eb 12397 restore_cpu_state(env, &ctx);
932e71cd 12398#ifdef CONFIG_USER_ONLY
0eaef5aa 12399 ctx.mem_idx = MIPS_HFLAG_UM;
932e71cd 12400#else
0eaef5aa 12401 ctx.mem_idx = ctx.hflags & MIPS_HFLAG_KSU;
932e71cd 12402#endif
2e70f6ef
PB
12403 num_insns = 0;
12404 max_insns = tb->cflags & CF_COUNT_MASK;
12405 if (max_insns == 0)
12406 max_insns = CF_COUNT_MASK;
d12d51d5 12407 LOG_DISAS("\ntb %p idx %d hflags %04x\n", tb, ctx.mem_idx, ctx.hflags);
2e70f6ef 12408 gen_icount_start();
faf7aaa9 12409 while (ctx.bstate == BS_NONE) {
72cf2d4f
BS
12410 if (unlikely(!QTAILQ_EMPTY(&env->breakpoints))) {
12411 QTAILQ_FOREACH(bp, &env->breakpoints, entry) {
a1d1bb31 12412 if (bp->pc == ctx.pc) {
278d0702 12413 save_cpu_state(&ctx, 1);
4ad40f36 12414 ctx.bstate = BS_BRANCH;
a7812ae4 12415 gen_helper_0i(raise_exception, EXCP_DEBUG);
ce62e5ba
TS
12416 /* Include the breakpoint location or the tb won't
12417 * be flushed when it must be. */
12418 ctx.pc += 4;
4ad40f36
FB
12419 goto done_generating;
12420 }
12421 }
12422 }
12423
6af0bf9c
FB
12424 if (search_pc) {
12425 j = gen_opc_ptr - gen_opc_buf;
6af0bf9c
FB
12426 if (lj < j) {
12427 lj++;
12428 while (lj < j)
12429 gen_opc_instr_start[lj++] = 0;
6af0bf9c 12430 }
4ad40f36
FB
12431 gen_opc_pc[lj] = ctx.pc;
12432 gen_opc_hflags[lj] = ctx.hflags & MIPS_HFLAG_BMASK;
12433 gen_opc_instr_start[lj] = 1;
2e70f6ef 12434 gen_opc_icount[lj] = num_insns;
6af0bf9c 12435 }
2e70f6ef
PB
12436 if (num_insns + 1 == max_insns && (tb->cflags & CF_LAST_IO))
12437 gen_io_start();
c9602061
NF
12438
12439 is_branch = 0;
364d4831 12440 if (!(ctx.hflags & MIPS_HFLAG_M16)) {
c9602061
NF
12441 ctx.opcode = ldl_code(ctx.pc);
12442 insn_bytes = 4;
12443 decode_opc(env, &ctx, &is_branch);
3c824109
NF
12444 } else if (env->insn_flags & ASE_MICROMIPS) {
12445 ctx.opcode = lduw_code(ctx.pc);
12446 insn_bytes = decode_micromips_opc(env, &ctx, &is_branch);
364d4831
NF
12447 } else if (env->insn_flags & ASE_MIPS16) {
12448 ctx.opcode = lduw_code(ctx.pc);
12449 insn_bytes = decode_mips16_opc(env, &ctx, &is_branch);
c9602061
NF
12450 } else {
12451 generate_exception(&ctx, EXCP_RI);
3c824109 12452 ctx.bstate = BS_STOP;
c9602061
NF
12453 break;
12454 }
12455 if (!is_branch) {
12456 handle_delay_slot(env, &ctx, insn_bytes);
12457 }
12458 ctx.pc += insn_bytes;
12459
2e70f6ef 12460 num_insns++;
4ad40f36 12461
7b270ef2
NF
12462 /* Execute a branch and its delay slot as a single instruction.
12463 This is what GDB expects and is consistent with what the
12464 hardware does (e.g. if a delay slot instruction faults, the
12465 reported PC is the PC of the branch). */
12466 if (env->singlestep_enabled && (ctx.hflags & MIPS_HFLAG_BMASK) == 0)
4ad40f36
FB
12467 break;
12468
6af0bf9c
FB
12469 if ((ctx.pc & (TARGET_PAGE_SIZE - 1)) == 0)
12470 break;
4ad40f36 12471
faf7aaa9
TS
12472 if (gen_opc_ptr >= gen_opc_end)
12473 break;
12474
2e70f6ef
PB
12475 if (num_insns >= max_insns)
12476 break;
1b530a6d
AJ
12477
12478 if (singlestep)
12479 break;
6af0bf9c 12480 }
2e70f6ef
PB
12481 if (tb->cflags & CF_LAST_IO)
12482 gen_io_end();
7b270ef2 12483 if (env->singlestep_enabled && ctx.bstate != BS_BRANCH) {
278d0702 12484 save_cpu_state(&ctx, ctx.bstate == BS_NONE);
a7812ae4 12485 gen_helper_0i(raise_exception, EXCP_DEBUG);
16c00cb2 12486 } else {
6958549d 12487 switch (ctx.bstate) {
16c00cb2 12488 case BS_STOP:
df1561e2
TS
12489 gen_goto_tb(&ctx, 0, ctx.pc);
12490 break;
16c00cb2 12491 case BS_NONE:
278d0702 12492 save_cpu_state(&ctx, 0);
16c00cb2
TS
12493 gen_goto_tb(&ctx, 0, ctx.pc);
12494 break;
5a5012ec 12495 case BS_EXCP:
57fec1fe 12496 tcg_gen_exit_tb(0);
16c00cb2 12497 break;
5a5012ec
TS
12498 case BS_BRANCH:
12499 default:
12500 break;
6958549d 12501 }
6af0bf9c 12502 }
4ad40f36 12503done_generating:
2e70f6ef 12504 gen_icount_end(tb, num_insns);
6af0bf9c
FB
12505 *gen_opc_ptr = INDEX_op_end;
12506 if (search_pc) {
12507 j = gen_opc_ptr - gen_opc_buf;
12508 lj++;
12509 while (lj <= j)
12510 gen_opc_instr_start[lj++] = 0;
6af0bf9c
FB
12511 } else {
12512 tb->size = ctx.pc - pc_start;
2e70f6ef 12513 tb->icount = num_insns;
6af0bf9c
FB
12514 }
12515#ifdef DEBUG_DISAS
d12d51d5 12516 LOG_DISAS("\n");
8fec2b8c 12517 if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) {
93fcfe39
AL
12518 qemu_log("IN: %s\n", lookup_symbol(pc_start));
12519 log_target_disas(pc_start, ctx.pc - pc_start, 0);
12520 qemu_log("\n");
6af0bf9c
FB
12521 }
12522#endif
6af0bf9c
FB
12523}
12524
7db13fae 12525void gen_intermediate_code (CPUMIPSState *env, struct TranslationBlock *tb)
6af0bf9c 12526{
2cfc5f17 12527 gen_intermediate_code_internal(env, tb, 0);
6af0bf9c
FB
12528}
12529
7db13fae 12530void gen_intermediate_code_pc (CPUMIPSState *env, struct TranslationBlock *tb)
6af0bf9c 12531{
2cfc5f17 12532 gen_intermediate_code_internal(env, tb, 1);
6af0bf9c
FB
12533}
12534
7db13fae 12535static void fpu_dump_state(CPUMIPSState *env, FILE *f, fprintf_function fpu_fprintf,
8706c382 12536 int flags)
6ea83fed
FB
12537{
12538 int i;
5e755519 12539 int is_fpu64 = !!(env->hflags & MIPS_HFLAG_F64);
5a5012ec 12540
2a5612e6
SW
12541#define printfpr(fp) \
12542 do { \
12543 if (is_fpu64) \
12544 fpu_fprintf(f, "w:%08x d:%016" PRIx64 \
12545 " fd:%13g fs:%13g psu: %13g\n", \
12546 (fp)->w[FP_ENDIAN_IDX], (fp)->d, \
12547 (double)(fp)->fd, \
12548 (double)(fp)->fs[FP_ENDIAN_IDX], \
12549 (double)(fp)->fs[!FP_ENDIAN_IDX]); \
12550 else { \
12551 fpr_t tmp; \
12552 tmp.w[FP_ENDIAN_IDX] = (fp)->w[FP_ENDIAN_IDX]; \
12553 tmp.w[!FP_ENDIAN_IDX] = ((fp) + 1)->w[FP_ENDIAN_IDX]; \
12554 fpu_fprintf(f, "w:%08x d:%016" PRIx64 \
12555 " fd:%13g fs:%13g psu:%13g\n", \
12556 tmp.w[FP_ENDIAN_IDX], tmp.d, \
12557 (double)tmp.fd, \
12558 (double)tmp.fs[FP_ENDIAN_IDX], \
12559 (double)tmp.fs[!FP_ENDIAN_IDX]); \
12560 } \
6ea83fed
FB
12561 } while(0)
12562
5a5012ec 12563
9a78eead
SW
12564 fpu_fprintf(f, "CP1 FCR0 0x%08x FCR31 0x%08x SR.FR %d fp_status 0x%02x\n",
12565 env->active_fpu.fcr0, env->active_fpu.fcr31, is_fpu64,
f01be154 12566 get_float_exception_flags(&env->active_fpu.fp_status));
5a5012ec
TS
12567 for (i = 0; i < 32; (is_fpu64) ? i++ : (i += 2)) {
12568 fpu_fprintf(f, "%3s: ", fregnames[i]);
f01be154 12569 printfpr(&env->active_fpu.fpr[i]);
6ea83fed
FB
12570 }
12571
12572#undef printfpr
12573}
12574
d26bc211 12575#if defined(TARGET_MIPS64) && defined(MIPS_DEBUG_SIGN_EXTENSIONS)
c570fd16 12576/* Debug help: The architecture requires 32bit code to maintain proper
c7e8a937 12577 sign-extended values on 64bit machines. */
c570fd16
TS
12578
12579#define SIGN_EXT_P(val) ((((val) & ~0x7fffffff) == 0) || (((val) & ~0x7fffffff) == ~0x7fffffff))
12580
8706c382 12581static void
7db13fae 12582cpu_mips_check_sign_extensions (CPUMIPSState *env, FILE *f,
9a78eead 12583 fprintf_function cpu_fprintf,
8706c382 12584 int flags)
c570fd16
TS
12585{
12586 int i;
12587
b5dc7732
TS
12588 if (!SIGN_EXT_P(env->active_tc.PC))
12589 cpu_fprintf(f, "BROKEN: pc=0x" TARGET_FMT_lx "\n", env->active_tc.PC);
12590 if (!SIGN_EXT_P(env->active_tc.HI[0]))
12591 cpu_fprintf(f, "BROKEN: HI=0x" TARGET_FMT_lx "\n", env->active_tc.HI[0]);
12592 if (!SIGN_EXT_P(env->active_tc.LO[0]))
12593 cpu_fprintf(f, "BROKEN: LO=0x" TARGET_FMT_lx "\n", env->active_tc.LO[0]);
c570fd16 12594 if (!SIGN_EXT_P(env->btarget))
3594c774 12595 cpu_fprintf(f, "BROKEN: btarget=0x" TARGET_FMT_lx "\n", env->btarget);
c570fd16
TS
12596
12597 for (i = 0; i < 32; i++) {
b5dc7732
TS
12598 if (!SIGN_EXT_P(env->active_tc.gpr[i]))
12599 cpu_fprintf(f, "BROKEN: %s=0x" TARGET_FMT_lx "\n", regnames[i], env->active_tc.gpr[i]);
c570fd16
TS
12600 }
12601
12602 if (!SIGN_EXT_P(env->CP0_EPC))
3594c774 12603 cpu_fprintf(f, "BROKEN: EPC=0x" TARGET_FMT_lx "\n", env->CP0_EPC);
5499b6ff
AJ
12604 if (!SIGN_EXT_P(env->lladdr))
12605 cpu_fprintf(f, "BROKEN: LLAddr=0x" TARGET_FMT_lx "\n", env->lladdr);
c570fd16
TS
12606}
12607#endif
12608
7db13fae 12609void cpu_dump_state (CPUMIPSState *env, FILE *f, fprintf_function cpu_fprintf,
6af0bf9c
FB
12610 int flags)
12611{
12612 int i;
3b46e624 12613
a7200c9f
SW
12614 cpu_fprintf(f, "pc=0x" TARGET_FMT_lx " HI=0x" TARGET_FMT_lx
12615 " LO=0x" TARGET_FMT_lx " ds %04x "
12616 TARGET_FMT_lx " " TARGET_FMT_ld "\n",
3d5be870
TS
12617 env->active_tc.PC, env->active_tc.HI[0], env->active_tc.LO[0],
12618 env->hflags, env->btarget, env->bcond);
6af0bf9c
FB
12619 for (i = 0; i < 32; i++) {
12620 if ((i & 3) == 0)
12621 cpu_fprintf(f, "GPR%02d:", i);
b5dc7732 12622 cpu_fprintf(f, " %s " TARGET_FMT_lx, regnames[i], env->active_tc.gpr[i]);
6af0bf9c
FB
12623 if ((i & 3) == 3)
12624 cpu_fprintf(f, "\n");
12625 }
568b600d 12626
3594c774 12627 cpu_fprintf(f, "CP0 Status 0x%08x Cause 0x%08x EPC 0x" TARGET_FMT_lx "\n",
5e755519 12628 env->CP0_Status, env->CP0_Cause, env->CP0_EPC);
3594c774 12629 cpu_fprintf(f, " Config0 0x%08x Config1 0x%08x LLAddr 0x" TARGET_FMT_lx "\n",
5499b6ff 12630 env->CP0_Config0, env->CP0_Config1, env->lladdr);
5e755519 12631 if (env->hflags & MIPS_HFLAG_FPU)
7a387fff 12632 fpu_dump_state(env, f, cpu_fprintf, flags);
d26bc211 12633#if defined(TARGET_MIPS64) && defined(MIPS_DEBUG_SIGN_EXTENSIONS)
c570fd16
TS
12634 cpu_mips_check_sign_extensions(env, f, cpu_fprintf, flags);
12635#endif
6af0bf9c
FB
12636}
12637
39454628
TS
12638static void mips_tcg_init(void)
12639{
f01be154 12640 int i;
39454628
TS
12641 static int inited;
12642
12643 /* Initialize various static tables. */
12644 if (inited)
6958549d 12645 return;
39454628 12646
a7812ae4 12647 cpu_env = tcg_global_reg_new_ptr(TCG_AREG0, "env");
f2c94b92 12648 TCGV_UNUSED(cpu_gpr[0]);
bb928dbe 12649 for (i = 1; i < 32; i++)
a7812ae4 12650 cpu_gpr[i] = tcg_global_mem_new(TCG_AREG0,
7db13fae 12651 offsetof(CPUMIPSState, active_tc.gpr[i]),
4b2eb8d2 12652 regnames[i]);
a7812ae4 12653 cpu_PC = tcg_global_mem_new(TCG_AREG0,
7db13fae 12654 offsetof(CPUMIPSState, active_tc.PC), "PC");
4b2eb8d2 12655 for (i = 0; i < MIPS_DSP_ACC; i++) {
a7812ae4 12656 cpu_HI[i] = tcg_global_mem_new(TCG_AREG0,
7db13fae 12657 offsetof(CPUMIPSState, active_tc.HI[i]),
4b2eb8d2 12658 regnames_HI[i]);
a7812ae4 12659 cpu_LO[i] = tcg_global_mem_new(TCG_AREG0,
7db13fae 12660 offsetof(CPUMIPSState, active_tc.LO[i]),
4b2eb8d2 12661 regnames_LO[i]);
a7812ae4 12662 cpu_ACX[i] = tcg_global_mem_new(TCG_AREG0,
7db13fae 12663 offsetof(CPUMIPSState, active_tc.ACX[i]),
4b2eb8d2
TS
12664 regnames_ACX[i]);
12665 }
a7812ae4 12666 cpu_dspctrl = tcg_global_mem_new(TCG_AREG0,
7db13fae 12667 offsetof(CPUMIPSState, active_tc.DSPControl),
4b2eb8d2 12668 "DSPControl");
1ba74fb8 12669 bcond = tcg_global_mem_new(TCG_AREG0,
7db13fae 12670 offsetof(CPUMIPSState, bcond), "bcond");
a7812ae4 12671 btarget = tcg_global_mem_new(TCG_AREG0,
7db13fae 12672 offsetof(CPUMIPSState, btarget), "btarget");
41db4607 12673 hflags = tcg_global_mem_new_i32(TCG_AREG0,
7db13fae 12674 offsetof(CPUMIPSState, hflags), "hflags");
41db4607 12675
a7812ae4 12676 fpu_fcr0 = tcg_global_mem_new_i32(TCG_AREG0,
7db13fae 12677 offsetof(CPUMIPSState, active_fpu.fcr0),
a7812ae4
PB
12678 "fcr0");
12679 fpu_fcr31 = tcg_global_mem_new_i32(TCG_AREG0,
7db13fae 12680 offsetof(CPUMIPSState, active_fpu.fcr31),
a7812ae4 12681 "fcr31");
39454628 12682
7dd9e556 12683 /* register helpers */
a7812ae4 12684#define GEN_HELPER 2
7dd9e556
TS
12685#include "helper.h"
12686
39454628
TS
12687 inited = 1;
12688}
12689
aaed909a
FB
12690#include "translate_init.c"
12691
30bf942d 12692MIPSCPU *cpu_mips_init(const char *cpu_model)
6af0bf9c 12693{
0f71a709 12694 MIPSCPU *cpu;
6af0bf9c 12695 CPUMIPSState *env;
c227f099 12696 const mips_def_t *def;
6af0bf9c 12697
aaed909a
FB
12698 def = cpu_mips_find_by_name(cpu_model);
12699 if (!def)
12700 return NULL;
0f71a709
AF
12701 cpu = MIPS_CPU(object_new(TYPE_MIPS_CPU));
12702 env = &cpu->env;
aaed909a 12703 env->cpu_model = def;
51cc2e78 12704 env->cpu_model_str = cpu_model;
aaed909a 12705
51cc2e78
BS
12706#ifndef CONFIG_USER_ONLY
12707 mmu_init(env, def);
12708#endif
12709 fpu_init(env, def);
12710 mvp_init(env, def);
39454628 12711 mips_tcg_init();
3bd4122e 12712 cpu_reset(CPU(cpu));
0bf46a40 12713 qemu_init_vcpu(env);
30bf942d 12714 return cpu;
6ae81775
TS
12715}
12716
1bba0dc9 12717void cpu_state_reset(CPUMIPSState *env)
6ae81775 12718{
eca1bdf4
AL
12719 if (qemu_loglevel_mask(CPU_LOG_RESET)) {
12720 qemu_log("CPU Reset (CPU %d)\n", env->cpu_index);
12721 log_cpu_state(env, 0);
12722 }
12723
6ae81775 12724 memset(env, 0, offsetof(CPUMIPSState, breakpoints));
6af0bf9c 12725 tlb_flush(env, 1);
6ae81775 12726
51cc2e78
BS
12727 /* Reset registers to their default values */
12728 env->CP0_PRid = env->cpu_model->CP0_PRid;
12729 env->CP0_Config0 = env->cpu_model->CP0_Config0;
12730#ifdef TARGET_WORDS_BIGENDIAN
12731 env->CP0_Config0 |= (1 << CP0C0_BE);
12732#endif
12733 env->CP0_Config1 = env->cpu_model->CP0_Config1;
12734 env->CP0_Config2 = env->cpu_model->CP0_Config2;
12735 env->CP0_Config3 = env->cpu_model->CP0_Config3;
12736 env->CP0_Config6 = env->cpu_model->CP0_Config6;
12737 env->CP0_Config7 = env->cpu_model->CP0_Config7;
2a6e32dd
AJ
12738 env->CP0_LLAddr_rw_bitmask = env->cpu_model->CP0_LLAddr_rw_bitmask
12739 << env->cpu_model->CP0_LLAddr_shift;
12740 env->CP0_LLAddr_shift = env->cpu_model->CP0_LLAddr_shift;
51cc2e78
BS
12741 env->SYNCI_Step = env->cpu_model->SYNCI_Step;
12742 env->CCRes = env->cpu_model->CCRes;
12743 env->CP0_Status_rw_bitmask = env->cpu_model->CP0_Status_rw_bitmask;
12744 env->CP0_TCStatus_rw_bitmask = env->cpu_model->CP0_TCStatus_rw_bitmask;
12745 env->CP0_SRSCtl = env->cpu_model->CP0_SRSCtl;
12746 env->current_tc = 0;
12747 env->SEGBITS = env->cpu_model->SEGBITS;
12748 env->SEGMask = (target_ulong)((1ULL << env->cpu_model->SEGBITS) - 1);
12749#if defined(TARGET_MIPS64)
12750 if (env->cpu_model->insn_flags & ISA_MIPS3) {
12751 env->SEGMask |= 3ULL << 62;
12752 }
12753#endif
12754 env->PABITS = env->cpu_model->PABITS;
12755 env->PAMask = (target_ulong)((1ULL << env->cpu_model->PABITS) - 1);
12756 env->CP0_SRSConf0_rw_bitmask = env->cpu_model->CP0_SRSConf0_rw_bitmask;
12757 env->CP0_SRSConf0 = env->cpu_model->CP0_SRSConf0;
12758 env->CP0_SRSConf1_rw_bitmask = env->cpu_model->CP0_SRSConf1_rw_bitmask;
12759 env->CP0_SRSConf1 = env->cpu_model->CP0_SRSConf1;
12760 env->CP0_SRSConf2_rw_bitmask = env->cpu_model->CP0_SRSConf2_rw_bitmask;
12761 env->CP0_SRSConf2 = env->cpu_model->CP0_SRSConf2;
12762 env->CP0_SRSConf3_rw_bitmask = env->cpu_model->CP0_SRSConf3_rw_bitmask;
12763 env->CP0_SRSConf3 = env->cpu_model->CP0_SRSConf3;
12764 env->CP0_SRSConf4_rw_bitmask = env->cpu_model->CP0_SRSConf4_rw_bitmask;
12765 env->CP0_SRSConf4 = env->cpu_model->CP0_SRSConf4;
f1cb0951 12766 env->active_fpu.fcr0 = env->cpu_model->CP1_fcr0;
51cc2e78
BS
12767 env->insn_flags = env->cpu_model->insn_flags;
12768
0eaef5aa 12769#if defined(CONFIG_USER_ONLY)
932e71cd 12770 env->hflags = MIPS_HFLAG_UM;
94159135
MI
12771 /* Enable access to the CPUNum, SYNCI_Step, CC, and CCRes RDHWR
12772 hardware registers. */
12773 env->CP0_HWREna |= 0x0000000F;
91a75935
NF
12774 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
12775 env->hflags |= MIPS_HFLAG_FPU;
12776 }
12777#ifdef TARGET_MIPS64
12778 if (env->active_fpu.fcr0 & (1 << FCR0_F64)) {
12779 env->hflags |= MIPS_HFLAG_F64;
12780 }
12781#endif
932e71cd
AJ
12782#else
12783 if (env->hflags & MIPS_HFLAG_BMASK) {
12784 /* If the exception was raised from a delay slot,
12785 come back to the jump. */
12786 env->CP0_ErrorEPC = env->active_tc.PC - 4;
aa328add 12787 } else {
932e71cd
AJ
12788 env->CP0_ErrorEPC = env->active_tc.PC;
12789 }
12790 env->active_tc.PC = (int32_t)0xBFC00000;
51cc2e78
BS
12791 env->CP0_Random = env->tlb->nb_tlb - 1;
12792 env->tlb->tlb_in_use = env->tlb->nb_tlb;
932e71cd 12793 env->CP0_Wired = 0;
671b0f36 12794 env->CP0_EBase = 0x80000000 | (env->cpu_index & 0x3FF);
932e71cd
AJ
12795 env->CP0_Status = (1 << CP0St_BEV) | (1 << CP0St_ERL);
12796 /* vectored interrupts not implemented, timer on int 7,
12797 no performance counters. */
12798 env->CP0_IntCtl = 0xe0000000;
12799 {
12800 int i;
12801
12802 for (i = 0; i < 7; i++) {
12803 env->CP0_WatchLo[i] = 0;
12804 env->CP0_WatchHi[i] = 0x80000000;
fd88b6ab 12805 }
932e71cd
AJ
12806 env->CP0_WatchLo[7] = 0;
12807 env->CP0_WatchHi[7] = 0;
fd88b6ab 12808 }
932e71cd
AJ
12809 /* Count register increments in debug mode, EJTAG version 1 */
12810 env->CP0_Debug = (1 << CP0DB_CNT) | (0x1 << CP0DB_VER);
12811 env->hflags = MIPS_HFLAG_CP0;
9e56e756
EI
12812
12813 if (env->CP0_Config3 & (1 << CP0C3_MT)) {
12814 int i;
12815
12816 /* Only TC0 on VPE 0 starts as active. */
12817 for (i = 0; i < ARRAY_SIZE(env->tcs); i++) {
12818 env->tcs[i].CP0_TCBind = env->cpu_index << CP0TCBd_CurVPE;
12819 env->tcs[i].CP0_TCHalt = 1;
12820 }
12821 env->active_tc.CP0_TCHalt = 1;
12822 env->halted = 1;
12823
12824 if (!env->cpu_index) {
12825 /* VPE0 starts up enabled. */
12826 env->mvp->CP0_MVPControl |= (1 << CP0MVPCo_EVP);
12827 env->CP0_VPEConf0 |= (1 << CP0VPEC0_MVP) | (1 << CP0VPEC0_VPA);
12828
12829 /* TC0 starts up unhalted. */
12830 env->halted = 0;
12831 env->active_tc.CP0_TCHalt = 0;
12832 env->tcs[0].CP0_TCHalt = 0;
12833 /* With thread 0 active. */
12834 env->active_tc.CP0_TCStatus = (1 << CP0TCSt_A);
12835 env->tcs[0].CP0_TCStatus = (1 << CP0TCSt_A);
12836 }
12837 }
51cc2e78
BS
12838#endif
12839#if defined(TARGET_MIPS64)
12840 if (env->cpu_model->insn_flags & ISA_MIPS3) {
12841 env->hflags |= MIPS_HFLAG_64;
12842 }
932e71cd 12843#endif
6af0bf9c 12844 env->exception_index = EXCP_NONE;
6af0bf9c 12845}
d2856f1a 12846
7db13fae 12847void restore_state_to_opc(CPUMIPSState *env, TranslationBlock *tb, int pc_pos)
d2856f1a 12848{
b5dc7732 12849 env->active_tc.PC = gen_opc_pc[pc_pos];
d2856f1a
AJ
12850 env->hflags &= ~MIPS_HFLAG_BMASK;
12851 env->hflags |= gen_opc_hflags[pc_pos];
12852}