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