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