blob: 683c936ecd2576d85fb2f551a6bea0946686b275 [file] [log] [blame]
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08001/*
2 * MIPS32 emulation for qemu: main translation routines.
3 *
4 * Copyright (c) 2004-2005 Jocelyn Mayer
5 * Copyright (c) 2006 Marius Groeger (FPU operations)
6 * Copyright (c) 2006 Thiemo Seufer (MIPS32R2 support)
7 *
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2 of the License, or (at your option) any later version.
12 *
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
17 *
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
20 */
21
22#include <stdarg.h>
23#include <stdlib.h>
24#include <stdio.h>
25#include <string.h>
26#include <inttypes.h>
27
28#include "cpu.h"
David 'Digit' Turnercc33b2d2013-12-15 00:09:42 +010029#include "disas/disas.h"
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -080030#include "tcg-op.h"
31#include "qemu-common.h"
32
33#include "helper.h"
34#define GEN_HELPER 1
35#include "helper.h"
36
37//#define MIPS_DEBUG_DISAS
38//#define MIPS_DEBUG_SIGN_EXTENSIONS
39
40/* MIPS major opcodes */
41#define MASK_OP_MAJOR(op) (op & (0x3F << 26))
42
43enum {
44 /* indirect opcode tables */
45 OPC_SPECIAL = (0x00 << 26),
46 OPC_REGIMM = (0x01 << 26),
47 OPC_CP0 = (0x10 << 26),
48 OPC_CP1 = (0x11 << 26),
49 OPC_CP2 = (0x12 << 26),
50 OPC_CP3 = (0x13 << 26),
51 OPC_SPECIAL2 = (0x1C << 26),
52 OPC_SPECIAL3 = (0x1F << 26),
53 /* arithmetic with immediate */
54 OPC_ADDI = (0x08 << 26),
55 OPC_ADDIU = (0x09 << 26),
56 OPC_SLTI = (0x0A << 26),
57 OPC_SLTIU = (0x0B << 26),
58 /* logic with immediate */
59 OPC_ANDI = (0x0C << 26),
60 OPC_ORI = (0x0D << 26),
61 OPC_XORI = (0x0E << 26),
62 OPC_LUI = (0x0F << 26),
63 /* arithmetic with immediate */
64 OPC_DADDI = (0x18 << 26),
65 OPC_DADDIU = (0x19 << 26),
66 /* Jump and branches */
67 OPC_J = (0x02 << 26),
68 OPC_JAL = (0x03 << 26),
69 OPC_BEQ = (0x04 << 26), /* Unconditional if rs = rt = 0 (B) */
70 OPC_BEQL = (0x14 << 26),
71 OPC_BNE = (0x05 << 26),
72 OPC_BNEL = (0x15 << 26),
73 OPC_BLEZ = (0x06 << 26),
74 OPC_BLEZL = (0x16 << 26),
75 OPC_BGTZ = (0x07 << 26),
76 OPC_BGTZL = (0x17 << 26),
77 OPC_JALX = (0x1D << 26), /* MIPS 16 only */
78 /* Load and stores */
79 OPC_LDL = (0x1A << 26),
80 OPC_LDR = (0x1B << 26),
81 OPC_LB = (0x20 << 26),
82 OPC_LH = (0x21 << 26),
83 OPC_LWL = (0x22 << 26),
84 OPC_LW = (0x23 << 26),
85 OPC_LBU = (0x24 << 26),
86 OPC_LHU = (0x25 << 26),
87 OPC_LWR = (0x26 << 26),
88 OPC_LWU = (0x27 << 26),
89 OPC_SB = (0x28 << 26),
90 OPC_SH = (0x29 << 26),
91 OPC_SWL = (0x2A << 26),
92 OPC_SW = (0x2B << 26),
93 OPC_SDL = (0x2C << 26),
94 OPC_SDR = (0x2D << 26),
95 OPC_SWR = (0x2E << 26),
96 OPC_LL = (0x30 << 26),
97 OPC_LLD = (0x34 << 26),
98 OPC_LD = (0x37 << 26),
99 OPC_SC = (0x38 << 26),
100 OPC_SCD = (0x3C << 26),
101 OPC_SD = (0x3F << 26),
102 /* Floating point load/store */
103 OPC_LWC1 = (0x31 << 26),
104 OPC_LWC2 = (0x32 << 26),
105 OPC_LDC1 = (0x35 << 26),
106 OPC_LDC2 = (0x36 << 26),
107 OPC_SWC1 = (0x39 << 26),
108 OPC_SWC2 = (0x3A << 26),
109 OPC_SDC1 = (0x3D << 26),
110 OPC_SDC2 = (0x3E << 26),
111 /* MDMX ASE specific */
112 OPC_MDMX = (0x1E << 26),
113 /* Cache and prefetch */
114 OPC_CACHE = (0x2F << 26),
115 OPC_PREF = (0x33 << 26),
116 /* Reserved major opcode */
117 OPC_MAJOR3B_RESERVED = (0x3B << 26),
118};
119
120/* MIPS special opcodes */
121#define MASK_SPECIAL(op) MASK_OP_MAJOR(op) | (op & 0x3F)
122
123enum {
124 /* Shifts */
125 OPC_SLL = 0x00 | OPC_SPECIAL,
126 /* NOP is SLL r0, r0, 0 */
127 /* SSNOP is SLL r0, r0, 1 */
128 /* EHB is SLL r0, r0, 3 */
129 OPC_SRL = 0x02 | OPC_SPECIAL, /* also ROTR */
130 OPC_SRA = 0x03 | OPC_SPECIAL,
131 OPC_SLLV = 0x04 | OPC_SPECIAL,
132 OPC_SRLV = 0x06 | OPC_SPECIAL, /* also ROTRV */
133 OPC_SRAV = 0x07 | OPC_SPECIAL,
134 OPC_DSLLV = 0x14 | OPC_SPECIAL,
135 OPC_DSRLV = 0x16 | OPC_SPECIAL, /* also DROTRV */
136 OPC_DSRAV = 0x17 | OPC_SPECIAL,
137 OPC_DSLL = 0x38 | OPC_SPECIAL,
138 OPC_DSRL = 0x3A | OPC_SPECIAL, /* also DROTR */
139 OPC_DSRA = 0x3B | OPC_SPECIAL,
140 OPC_DSLL32 = 0x3C | OPC_SPECIAL,
141 OPC_DSRL32 = 0x3E | OPC_SPECIAL, /* also DROTR32 */
142 OPC_DSRA32 = 0x3F | OPC_SPECIAL,
143 /* Multiplication / division */
144 OPC_MULT = 0x18 | OPC_SPECIAL,
145 OPC_MULTU = 0x19 | OPC_SPECIAL,
146 OPC_DIV = 0x1A | OPC_SPECIAL,
147 OPC_DIVU = 0x1B | OPC_SPECIAL,
148 OPC_DMULT = 0x1C | OPC_SPECIAL,
149 OPC_DMULTU = 0x1D | OPC_SPECIAL,
150 OPC_DDIV = 0x1E | OPC_SPECIAL,
151 OPC_DDIVU = 0x1F | OPC_SPECIAL,
152 /* 2 registers arithmetic / logic */
153 OPC_ADD = 0x20 | OPC_SPECIAL,
154 OPC_ADDU = 0x21 | OPC_SPECIAL,
155 OPC_SUB = 0x22 | OPC_SPECIAL,
156 OPC_SUBU = 0x23 | OPC_SPECIAL,
157 OPC_AND = 0x24 | OPC_SPECIAL,
158 OPC_OR = 0x25 | OPC_SPECIAL,
159 OPC_XOR = 0x26 | OPC_SPECIAL,
160 OPC_NOR = 0x27 | OPC_SPECIAL,
161 OPC_SLT = 0x2A | OPC_SPECIAL,
162 OPC_SLTU = 0x2B | OPC_SPECIAL,
163 OPC_DADD = 0x2C | OPC_SPECIAL,
164 OPC_DADDU = 0x2D | OPC_SPECIAL,
165 OPC_DSUB = 0x2E | OPC_SPECIAL,
166 OPC_DSUBU = 0x2F | OPC_SPECIAL,
167 /* Jumps */
168 OPC_JR = 0x08 | OPC_SPECIAL, /* Also JR.HB */
169 OPC_JALR = 0x09 | OPC_SPECIAL, /* Also JALR.HB */
170 /* Traps */
171 OPC_TGE = 0x30 | OPC_SPECIAL,
172 OPC_TGEU = 0x31 | OPC_SPECIAL,
173 OPC_TLT = 0x32 | OPC_SPECIAL,
174 OPC_TLTU = 0x33 | OPC_SPECIAL,
175 OPC_TEQ = 0x34 | OPC_SPECIAL,
176 OPC_TNE = 0x36 | OPC_SPECIAL,
177 /* HI / LO registers load & stores */
178 OPC_MFHI = 0x10 | OPC_SPECIAL,
179 OPC_MTHI = 0x11 | OPC_SPECIAL,
180 OPC_MFLO = 0x12 | OPC_SPECIAL,
181 OPC_MTLO = 0x13 | OPC_SPECIAL,
182 /* Conditional moves */
183 OPC_MOVZ = 0x0A | OPC_SPECIAL,
184 OPC_MOVN = 0x0B | OPC_SPECIAL,
185
186 OPC_MOVCI = 0x01 | OPC_SPECIAL,
187
188 /* Special */
189 OPC_PMON = 0x05 | OPC_SPECIAL, /* unofficial */
190 OPC_SYSCALL = 0x0C | OPC_SPECIAL,
191 OPC_BREAK = 0x0D | OPC_SPECIAL,
192 OPC_SPIM = 0x0E | OPC_SPECIAL, /* unofficial */
193 OPC_SYNC = 0x0F | OPC_SPECIAL,
194
195 OPC_SPECIAL15_RESERVED = 0x15 | OPC_SPECIAL,
196 OPC_SPECIAL28_RESERVED = 0x28 | OPC_SPECIAL,
197 OPC_SPECIAL29_RESERVED = 0x29 | OPC_SPECIAL,
198 OPC_SPECIAL35_RESERVED = 0x35 | OPC_SPECIAL,
199 OPC_SPECIAL37_RESERVED = 0x37 | OPC_SPECIAL,
200 OPC_SPECIAL39_RESERVED = 0x39 | OPC_SPECIAL,
201 OPC_SPECIAL3D_RESERVED = 0x3D | OPC_SPECIAL,
202};
203
204/* Multiplication variants of the vr54xx. */
205#define MASK_MUL_VR54XX(op) MASK_SPECIAL(op) | (op & (0x1F << 6))
206
207enum {
208 OPC_VR54XX_MULS = (0x03 << 6) | OPC_MULT,
209 OPC_VR54XX_MULSU = (0x03 << 6) | OPC_MULTU,
210 OPC_VR54XX_MACC = (0x05 << 6) | OPC_MULT,
211 OPC_VR54XX_MACCU = (0x05 << 6) | OPC_MULTU,
212 OPC_VR54XX_MSAC = (0x07 << 6) | OPC_MULT,
213 OPC_VR54XX_MSACU = (0x07 << 6) | OPC_MULTU,
214 OPC_VR54XX_MULHI = (0x09 << 6) | OPC_MULT,
215 OPC_VR54XX_MULHIU = (0x09 << 6) | OPC_MULTU,
216 OPC_VR54XX_MULSHI = (0x0B << 6) | OPC_MULT,
217 OPC_VR54XX_MULSHIU = (0x0B << 6) | OPC_MULTU,
218 OPC_VR54XX_MACCHI = (0x0D << 6) | OPC_MULT,
219 OPC_VR54XX_MACCHIU = (0x0D << 6) | OPC_MULTU,
220 OPC_VR54XX_MSACHI = (0x0F << 6) | OPC_MULT,
221 OPC_VR54XX_MSACHIU = (0x0F << 6) | OPC_MULTU,
222};
223
224/* REGIMM (rt field) opcodes */
225#define MASK_REGIMM(op) MASK_OP_MAJOR(op) | (op & (0x1F << 16))
226
227enum {
228 OPC_BLTZ = (0x00 << 16) | OPC_REGIMM,
229 OPC_BLTZL = (0x02 << 16) | OPC_REGIMM,
230 OPC_BGEZ = (0x01 << 16) | OPC_REGIMM,
231 OPC_BGEZL = (0x03 << 16) | OPC_REGIMM,
232 OPC_BLTZAL = (0x10 << 16) | OPC_REGIMM,
233 OPC_BLTZALL = (0x12 << 16) | OPC_REGIMM,
234 OPC_BGEZAL = (0x11 << 16) | OPC_REGIMM,
235 OPC_BGEZALL = (0x13 << 16) | OPC_REGIMM,
236 OPC_TGEI = (0x08 << 16) | OPC_REGIMM,
237 OPC_TGEIU = (0x09 << 16) | OPC_REGIMM,
238 OPC_TLTI = (0x0A << 16) | OPC_REGIMM,
239 OPC_TLTIU = (0x0B << 16) | OPC_REGIMM,
240 OPC_TEQI = (0x0C << 16) | OPC_REGIMM,
241 OPC_TNEI = (0x0E << 16) | OPC_REGIMM,
242 OPC_SYNCI = (0x1F << 16) | OPC_REGIMM,
243};
244
245/* Special2 opcodes */
246#define MASK_SPECIAL2(op) MASK_OP_MAJOR(op) | (op & 0x3F)
247
248enum {
249 /* Multiply & xxx operations */
250 OPC_MADD = 0x00 | OPC_SPECIAL2,
251 OPC_MADDU = 0x01 | OPC_SPECIAL2,
252 OPC_MUL = 0x02 | OPC_SPECIAL2,
253 OPC_MSUB = 0x04 | OPC_SPECIAL2,
254 OPC_MSUBU = 0x05 | OPC_SPECIAL2,
255 /* Misc */
256 OPC_CLZ = 0x20 | OPC_SPECIAL2,
257 OPC_CLO = 0x21 | OPC_SPECIAL2,
258 OPC_DCLZ = 0x24 | OPC_SPECIAL2,
259 OPC_DCLO = 0x25 | OPC_SPECIAL2,
260 /* Special */
261 OPC_SDBBP = 0x3F | OPC_SPECIAL2,
262};
263
264/* Special3 opcodes */
265#define MASK_SPECIAL3(op) MASK_OP_MAJOR(op) | (op & 0x3F)
266
267enum {
268 OPC_EXT = 0x00 | OPC_SPECIAL3,
269 OPC_DEXTM = 0x01 | OPC_SPECIAL3,
270 OPC_DEXTU = 0x02 | OPC_SPECIAL3,
271 OPC_DEXT = 0x03 | OPC_SPECIAL3,
272 OPC_INS = 0x04 | OPC_SPECIAL3,
273 OPC_DINSM = 0x05 | OPC_SPECIAL3,
274 OPC_DINSU = 0x06 | OPC_SPECIAL3,
275 OPC_DINS = 0x07 | OPC_SPECIAL3,
276 OPC_FORK = 0x08 | OPC_SPECIAL3,
277 OPC_YIELD = 0x09 | OPC_SPECIAL3,
278 OPC_BSHFL = 0x20 | OPC_SPECIAL3,
279 OPC_DBSHFL = 0x24 | OPC_SPECIAL3,
280 OPC_RDHWR = 0x3B | OPC_SPECIAL3,
281};
282
283/* BSHFL opcodes */
284#define MASK_BSHFL(op) MASK_SPECIAL3(op) | (op & (0x1F << 6))
285
286enum {
287 OPC_WSBH = (0x02 << 6) | OPC_BSHFL,
288 OPC_SEB = (0x10 << 6) | OPC_BSHFL,
289 OPC_SEH = (0x18 << 6) | OPC_BSHFL,
290};
291
292/* DBSHFL opcodes */
293#define MASK_DBSHFL(op) MASK_SPECIAL3(op) | (op & (0x1F << 6))
294
295enum {
296 OPC_DSBH = (0x02 << 6) | OPC_DBSHFL,
297 OPC_DSHD = (0x05 << 6) | OPC_DBSHFL,
298};
299
300/* Coprocessor 0 (rs field) */
301#define MASK_CP0(op) MASK_OP_MAJOR(op) | (op & (0x1F << 21))
302
303enum {
304 OPC_MFC0 = (0x00 << 21) | OPC_CP0,
305 OPC_DMFC0 = (0x01 << 21) | OPC_CP0,
306 OPC_MTC0 = (0x04 << 21) | OPC_CP0,
307 OPC_DMTC0 = (0x05 << 21) | OPC_CP0,
308 OPC_MFTR = (0x08 << 21) | OPC_CP0,
309 OPC_RDPGPR = (0x0A << 21) | OPC_CP0,
310 OPC_MFMC0 = (0x0B << 21) | OPC_CP0,
311 OPC_MTTR = (0x0C << 21) | OPC_CP0,
312 OPC_WRPGPR = (0x0E << 21) | OPC_CP0,
313 OPC_C0 = (0x10 << 21) | OPC_CP0,
314 OPC_C0_FIRST = (0x10 << 21) | OPC_CP0,
315 OPC_C0_LAST = (0x1F << 21) | OPC_CP0,
316};
317
318/* MFMC0 opcodes */
319#define MASK_MFMC0(op) MASK_CP0(op) | (op & 0xFFFF)
320
321enum {
322 OPC_DMT = 0x01 | (0 << 5) | (0x0F << 6) | (0x01 << 11) | OPC_MFMC0,
323 OPC_EMT = 0x01 | (1 << 5) | (0x0F << 6) | (0x01 << 11) | OPC_MFMC0,
324 OPC_DVPE = 0x01 | (0 << 5) | OPC_MFMC0,
325 OPC_EVPE = 0x01 | (1 << 5) | OPC_MFMC0,
326 OPC_DI = (0 << 5) | (0x0C << 11) | OPC_MFMC0,
327 OPC_EI = (1 << 5) | (0x0C << 11) | OPC_MFMC0,
328};
329
330/* Coprocessor 0 (with rs == C0) */
331#define MASK_C0(op) MASK_CP0(op) | (op & 0x3F)
332
333enum {
334 OPC_TLBR = 0x01 | OPC_C0,
335 OPC_TLBWI = 0x02 | OPC_C0,
336 OPC_TLBWR = 0x06 | OPC_C0,
337 OPC_TLBP = 0x08 | OPC_C0,
338 OPC_RFE = 0x10 | OPC_C0,
339 OPC_ERET = 0x18 | OPC_C0,
340 OPC_DERET = 0x1F | OPC_C0,
341 OPC_WAIT = 0x20 | OPC_C0,
342};
343
344/* Coprocessor 1 (rs field) */
345#define MASK_CP1(op) MASK_OP_MAJOR(op) | (op & (0x1F << 21))
346
347enum {
348 OPC_MFC1 = (0x00 << 21) | OPC_CP1,
349 OPC_DMFC1 = (0x01 << 21) | OPC_CP1,
350 OPC_CFC1 = (0x02 << 21) | OPC_CP1,
351 OPC_MFHC1 = (0x03 << 21) | OPC_CP1,
352 OPC_MTC1 = (0x04 << 21) | OPC_CP1,
353 OPC_DMTC1 = (0x05 << 21) | OPC_CP1,
354 OPC_CTC1 = (0x06 << 21) | OPC_CP1,
355 OPC_MTHC1 = (0x07 << 21) | OPC_CP1,
356 OPC_BC1 = (0x08 << 21) | OPC_CP1, /* bc */
357 OPC_BC1ANY2 = (0x09 << 21) | OPC_CP1,
358 OPC_BC1ANY4 = (0x0A << 21) | OPC_CP1,
359 OPC_S_FMT = (0x10 << 21) | OPC_CP1, /* 16: fmt=single fp */
360 OPC_D_FMT = (0x11 << 21) | OPC_CP1, /* 17: fmt=double fp */
361 OPC_E_FMT = (0x12 << 21) | OPC_CP1, /* 18: fmt=extended fp */
362 OPC_Q_FMT = (0x13 << 21) | OPC_CP1, /* 19: fmt=quad fp */
363 OPC_W_FMT = (0x14 << 21) | OPC_CP1, /* 20: fmt=32bit fixed */
364 OPC_L_FMT = (0x15 << 21) | OPC_CP1, /* 21: fmt=64bit fixed */
365 OPC_PS_FMT = (0x16 << 21) | OPC_CP1, /* 22: fmt=paired single fp */
366};
367
368#define MASK_CP1_FUNC(op) MASK_CP1(op) | (op & 0x3F)
369#define MASK_BC1(op) MASK_CP1(op) | (op & (0x3 << 16))
370
371enum {
372 OPC_BC1F = (0x00 << 16) | OPC_BC1,
373 OPC_BC1T = (0x01 << 16) | OPC_BC1,
374 OPC_BC1FL = (0x02 << 16) | OPC_BC1,
375 OPC_BC1TL = (0x03 << 16) | OPC_BC1,
376};
377
378enum {
379 OPC_BC1FANY2 = (0x00 << 16) | OPC_BC1ANY2,
380 OPC_BC1TANY2 = (0x01 << 16) | OPC_BC1ANY2,
381};
382
383enum {
384 OPC_BC1FANY4 = (0x00 << 16) | OPC_BC1ANY4,
385 OPC_BC1TANY4 = (0x01 << 16) | OPC_BC1ANY4,
386};
387
388#define MASK_CP2(op) MASK_OP_MAJOR(op) | (op & (0x1F << 21))
389
390enum {
391 OPC_MFC2 = (0x00 << 21) | OPC_CP2,
392 OPC_DMFC2 = (0x01 << 21) | OPC_CP2,
393 OPC_CFC2 = (0x02 << 21) | OPC_CP2,
394 OPC_MFHC2 = (0x03 << 21) | OPC_CP2,
395 OPC_MTC2 = (0x04 << 21) | OPC_CP2,
396 OPC_DMTC2 = (0x05 << 21) | OPC_CP2,
397 OPC_CTC2 = (0x06 << 21) | OPC_CP2,
398 OPC_MTHC2 = (0x07 << 21) | OPC_CP2,
399 OPC_BC2 = (0x08 << 21) | OPC_CP2,
400};
401
402#define MASK_CP3(op) MASK_OP_MAJOR(op) | (op & 0x3F)
403
404enum {
405 OPC_LWXC1 = 0x00 | OPC_CP3,
406 OPC_LDXC1 = 0x01 | OPC_CP3,
407 OPC_LUXC1 = 0x05 | OPC_CP3,
408 OPC_SWXC1 = 0x08 | OPC_CP3,
409 OPC_SDXC1 = 0x09 | OPC_CP3,
410 OPC_SUXC1 = 0x0D | OPC_CP3,
411 OPC_PREFX = 0x0F | OPC_CP3,
412 OPC_ALNV_PS = 0x1E | OPC_CP3,
413 OPC_MADD_S = 0x20 | OPC_CP3,
414 OPC_MADD_D = 0x21 | OPC_CP3,
415 OPC_MADD_PS = 0x26 | OPC_CP3,
416 OPC_MSUB_S = 0x28 | OPC_CP3,
417 OPC_MSUB_D = 0x29 | OPC_CP3,
418 OPC_MSUB_PS = 0x2E | OPC_CP3,
419 OPC_NMADD_S = 0x30 | OPC_CP3,
420 OPC_NMADD_D = 0x31 | OPC_CP3,
421 OPC_NMADD_PS= 0x36 | OPC_CP3,
422 OPC_NMSUB_S = 0x38 | OPC_CP3,
423 OPC_NMSUB_D = 0x39 | OPC_CP3,
424 OPC_NMSUB_PS= 0x3E | OPC_CP3,
425};
426
427/* global register indices */
428static TCGv_ptr cpu_env;
429static TCGv cpu_gpr[32], cpu_PC;
430static TCGv cpu_HI[MIPS_DSP_ACC], cpu_LO[MIPS_DSP_ACC], cpu_ACX[MIPS_DSP_ACC];
431static TCGv cpu_dspctrl, btarget, bcond;
432static TCGv_i32 hflags;
433static TCGv_i32 fpu_fcr0, fpu_fcr31;
434
David 'Digit' Turner86b1fb02014-03-21 15:20:21 +0100435static uint32_t gen_opc_hflags[OPC_BUF_SIZE];
436
David 'Digit' Turner852088c2013-12-14 23:04:12 +0100437#include "exec/gen-icount.h"
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -0800438
439#define gen_helper_0i(name, arg) do { \
440 TCGv_i32 helper_tmp = tcg_const_i32(arg); \
441 gen_helper_##name(helper_tmp); \
442 tcg_temp_free_i32(helper_tmp); \
443 } while(0)
444
445#define gen_helper_1i(name, arg1, arg2) do { \
446 TCGv_i32 helper_tmp = tcg_const_i32(arg2); \
447 gen_helper_##name(arg1, helper_tmp); \
448 tcg_temp_free_i32(helper_tmp); \
449 } while(0)
450
451#define gen_helper_2i(name, arg1, arg2, arg3) do { \
452 TCGv_i32 helper_tmp = tcg_const_i32(arg3); \
453 gen_helper_##name(arg1, arg2, helper_tmp); \
454 tcg_temp_free_i32(helper_tmp); \
455 } while(0)
456
457#define gen_helper_3i(name, arg1, arg2, arg3, arg4) do { \
458 TCGv_i32 helper_tmp = tcg_const_i32(arg4); \
459 gen_helper_##name(arg1, arg2, arg3, helper_tmp); \
460 tcg_temp_free_i32(helper_tmp); \
461 } while(0)
462
David 'Digit' Turnerd62e5382014-04-03 13:13:04 +0200463#define gen_helper_4i(name, arg1, arg2, arg3, arg4, arg5) do { \
464 TCGv_i32 helper_tmp = tcg_const_i32(arg5); \
465 gen_helper_##name(arg1, arg2, arg3, arg4, helper_tmp); \
466 tcg_temp_free_i32(helper_tmp); \
467 } while(0)
468
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -0800469typedef struct DisasContext {
470 struct TranslationBlock *tb;
471 target_ulong pc, saved_pc;
472 uint32_t opcode;
473 int singlestep_enabled;
474 /* Routine used to access memory */
475 int mem_idx;
476 uint32_t hflags, saved_hflags;
477 int bstate;
478 target_ulong btarget;
479} DisasContext;
480
481enum {
482 BS_NONE = 0, /* We go out of the TB without reaching a branch or an
483 * exception condition */
484 BS_STOP = 1, /* We want to stop translation for any reason */
485 BS_BRANCH = 2, /* We reached a branch condition */
486 BS_EXCP = 3, /* We reached an exception condition */
487};
488
489static const char *regnames[] =
490 { "r0", "at", "v0", "v1", "a0", "a1", "a2", "a3",
491 "t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7",
492 "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7",
493 "t8", "t9", "k0", "k1", "gp", "sp", "s8", "ra", };
494
495static const char *regnames_HI[] =
496 { "HI0", "HI1", "HI2", "HI3", };
497
498static const char *regnames_LO[] =
499 { "LO0", "LO1", "LO2", "LO3", };
500
501static const char *regnames_ACX[] =
502 { "ACX0", "ACX1", "ACX2", "ACX3", };
503
504static const char *fregnames[] =
505 { "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7",
506 "f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15",
507 "f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23",
508 "f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31", };
509
510#ifdef MIPS_DEBUG_DISAS
511#define MIPS_DEBUG(fmt, ...) \
512 qemu_log_mask(CPU_LOG_TB_IN_ASM, \
513 TARGET_FMT_lx ": %08x " fmt "\n", \
514 ctx->pc, ctx->opcode , ## __VA_ARGS__)
515#define LOG_DISAS(...) qemu_log_mask(CPU_LOG_TB_IN_ASM, ## __VA_ARGS__)
516#else
517#define MIPS_DEBUG(fmt, ...) do { } while(0)
518#define LOG_DISAS(...) do { } while (0)
519#endif
520
521#define MIPS_INVAL(op) \
522do { \
523 MIPS_DEBUG("Invalid %s %03x %03x %03x", op, ctx->opcode >> 26, \
524 ctx->opcode & 0x3F, ((ctx->opcode >> 16) & 0x1F)); \
525} while (0)
526
527/* General purpose registers moves. */
528static inline void gen_load_gpr (TCGv t, int reg)
529{
530 if (reg == 0)
531 tcg_gen_movi_tl(t, 0);
532 else
533 tcg_gen_mov_tl(t, cpu_gpr[reg]);
534}
535
536static inline void gen_store_gpr (TCGv t, int reg)
537{
538 if (reg != 0)
539 tcg_gen_mov_tl(cpu_gpr[reg], t);
540}
541
542/* Moves to/from ACX register. */
543static inline void gen_load_ACX (TCGv t, int reg)
544{
545 tcg_gen_mov_tl(t, cpu_ACX[reg]);
546}
547
548static inline void gen_store_ACX (TCGv t, int reg)
549{
550 tcg_gen_mov_tl(cpu_ACX[reg], t);
551}
552
553/* Moves to/from shadow registers. */
554static inline void gen_load_srsgpr (int from, int to)
555{
556 TCGv t0 = tcg_temp_new();
557
558 if (from == 0)
559 tcg_gen_movi_tl(t0, 0);
560 else {
561 TCGv_i32 t2 = tcg_temp_new_i32();
562 TCGv_ptr addr = tcg_temp_new_ptr();
563
David 'Digit' Turnere2678e12014-01-16 15:56:43 +0100564 tcg_gen_ld_i32(t2, cpu_env, offsetof(CPUMIPSState, CP0_SRSCtl));
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -0800565 tcg_gen_shri_i32(t2, t2, CP0SRSCtl_PSS);
566 tcg_gen_andi_i32(t2, t2, 0xf);
567 tcg_gen_muli_i32(t2, t2, sizeof(target_ulong) * 32);
568 tcg_gen_ext_i32_ptr(addr, t2);
569 tcg_gen_add_ptr(addr, cpu_env, addr);
570
571 tcg_gen_ld_tl(t0, addr, sizeof(target_ulong) * from);
572 tcg_temp_free_ptr(addr);
573 tcg_temp_free_i32(t2);
574 }
575 gen_store_gpr(t0, to);
576 tcg_temp_free(t0);
577}
578
579static inline void gen_store_srsgpr (int from, int to)
580{
581 if (to != 0) {
582 TCGv t0 = tcg_temp_new();
583 TCGv_i32 t2 = tcg_temp_new_i32();
584 TCGv_ptr addr = tcg_temp_new_ptr();
585
586 gen_load_gpr(t0, from);
David 'Digit' Turnere2678e12014-01-16 15:56:43 +0100587 tcg_gen_ld_i32(t2, cpu_env, offsetof(CPUMIPSState, CP0_SRSCtl));
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -0800588 tcg_gen_shri_i32(t2, t2, CP0SRSCtl_PSS);
589 tcg_gen_andi_i32(t2, t2, 0xf);
590 tcg_gen_muli_i32(t2, t2, sizeof(target_ulong) * 32);
591 tcg_gen_ext_i32_ptr(addr, t2);
592 tcg_gen_add_ptr(addr, cpu_env, addr);
593
594 tcg_gen_st_tl(t0, addr, sizeof(target_ulong) * to);
595 tcg_temp_free_ptr(addr);
596 tcg_temp_free_i32(t2);
597 tcg_temp_free(t0);
598 }
599}
600
601/* Floating point register moves. */
602static inline void gen_load_fpr32 (TCGv_i32 t, int reg)
603{
David 'Digit' Turnere2678e12014-01-16 15:56:43 +0100604 tcg_gen_ld_i32(t, cpu_env, offsetof(CPUMIPSState, active_fpu.fpr[reg].w[FP_ENDIAN_IDX]));
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -0800605}
606
607static inline void gen_store_fpr32 (TCGv_i32 t, int reg)
608{
David 'Digit' Turnere2678e12014-01-16 15:56:43 +0100609 tcg_gen_st_i32(t, cpu_env, offsetof(CPUMIPSState, active_fpu.fpr[reg].w[FP_ENDIAN_IDX]));
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -0800610}
611
612static inline void gen_load_fpr32h (TCGv_i32 t, int reg)
613{
David 'Digit' Turnere2678e12014-01-16 15:56:43 +0100614 tcg_gen_ld_i32(t, cpu_env, offsetof(CPUMIPSState, active_fpu.fpr[reg].w[!FP_ENDIAN_IDX]));
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -0800615}
616
617static inline void gen_store_fpr32h (TCGv_i32 t, int reg)
618{
David 'Digit' Turnere2678e12014-01-16 15:56:43 +0100619 tcg_gen_st_i32(t, cpu_env, offsetof(CPUMIPSState, active_fpu.fpr[reg].w[!FP_ENDIAN_IDX]));
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -0800620}
621
622static inline void gen_load_fpr64 (DisasContext *ctx, TCGv_i64 t, int reg)
623{
624 if (ctx->hflags & MIPS_HFLAG_F64) {
David 'Digit' Turnere2678e12014-01-16 15:56:43 +0100625 tcg_gen_ld_i64(t, cpu_env, offsetof(CPUMIPSState, active_fpu.fpr[reg].d));
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -0800626 } else {
627 TCGv_i32 t0 = tcg_temp_new_i32();
628 TCGv_i32 t1 = tcg_temp_new_i32();
629 gen_load_fpr32(t0, reg & ~1);
630 gen_load_fpr32(t1, reg | 1);
631 tcg_gen_concat_i32_i64(t, t0, t1);
632 tcg_temp_free_i32(t0);
633 tcg_temp_free_i32(t1);
634 }
635}
636
637static inline void gen_store_fpr64 (DisasContext *ctx, TCGv_i64 t, int reg)
638{
639 if (ctx->hflags & MIPS_HFLAG_F64) {
David 'Digit' Turnere2678e12014-01-16 15:56:43 +0100640 tcg_gen_st_i64(t, cpu_env, offsetof(CPUMIPSState, active_fpu.fpr[reg].d));
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -0800641 } else {
642 TCGv_i64 t0 = tcg_temp_new_i64();
643 TCGv_i32 t1 = tcg_temp_new_i32();
644 tcg_gen_trunc_i64_i32(t1, t);
645 gen_store_fpr32(t1, reg & ~1);
646 tcg_gen_shri_i64(t0, t, 32);
647 tcg_gen_trunc_i64_i32(t1, t0);
648 gen_store_fpr32(t1, reg | 1);
649 tcg_temp_free_i32(t1);
650 tcg_temp_free_i64(t0);
651 }
652}
653
654static inline int get_fp_bit (int cc)
655{
656 if (cc)
657 return 24 + cc;
658 else
659 return 23;
660}
661
662#define FOP_CONDS(type, fmt, bits) \
663static inline void gen_cmp ## type ## _ ## fmt(int n, TCGv_i##bits a, \
664 TCGv_i##bits b, int cc) \
665{ \
666 switch (n) { \
David 'Digit' Turner87350d12014-04-03 15:44:48 +0200667 case 0: gen_helper_3i(cmp ## type ## _ ## fmt ## _f, cpu_env, a, b, cc); break;\
668 case 1: gen_helper_3i(cmp ## type ## _ ## fmt ## _un, cpu_env, a, b, cc); break;\
669 case 2: gen_helper_3i(cmp ## type ## _ ## fmt ## _eq, cpu_env, a, b, cc); break;\
670 case 3: gen_helper_3i(cmp ## type ## _ ## fmt ## _ueq, cpu_env, a, b, cc); break;\
671 case 4: gen_helper_3i(cmp ## type ## _ ## fmt ## _olt, cpu_env, a, b, cc); break;\
672 case 5: gen_helper_3i(cmp ## type ## _ ## fmt ## _ult, cpu_env, a, b, cc); break;\
673 case 6: gen_helper_3i(cmp ## type ## _ ## fmt ## _ole, cpu_env, a, b, cc); break;\
674 case 7: gen_helper_3i(cmp ## type ## _ ## fmt ## _ule, cpu_env, a, b, cc); break;\
675 case 8: gen_helper_3i(cmp ## type ## _ ## fmt ## _sf, cpu_env, a, b, cc); break;\
676 case 9: gen_helper_3i(cmp ## type ## _ ## fmt ## _ngle, cpu_env, a, b, cc); break;\
677 case 10: gen_helper_3i(cmp ## type ## _ ## fmt ## _seq, cpu_env, a, b, cc); break;\
678 case 11: gen_helper_3i(cmp ## type ## _ ## fmt ## _ngl, cpu_env, a, b, cc); break;\
679 case 12: gen_helper_3i(cmp ## type ## _ ## fmt ## _lt, cpu_env, a, b, cc); break;\
680 case 13: gen_helper_3i(cmp ## type ## _ ## fmt ## _nge, cpu_env, a, b, cc); break;\
681 case 14: gen_helper_3i(cmp ## type ## _ ## fmt ## _le, cpu_env, a, b, cc); break;\
682 case 15: gen_helper_3i(cmp ## type ## _ ## fmt ## _ngt, cpu_env, a, b, cc); break;\
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -0800683 default: abort(); \
684 } \
685}
686
687FOP_CONDS(, d, 64)
688FOP_CONDS(abs, d, 64)
689FOP_CONDS(, s, 32)
690FOP_CONDS(abs, s, 32)
691FOP_CONDS(, ps, 64)
692FOP_CONDS(abs, ps, 64)
693#undef FOP_CONDS
694
695/* Tests */
696#define OP_COND(name, cond) \
697static inline void glue(gen_op_, name) (TCGv ret, TCGv t0, TCGv t1) \
698{ \
699 int l1 = gen_new_label(); \
700 int l2 = gen_new_label(); \
701 \
702 tcg_gen_brcond_tl(cond, t0, t1, l1); \
703 tcg_gen_movi_tl(ret, 0); \
704 tcg_gen_br(l2); \
705 gen_set_label(l1); \
706 tcg_gen_movi_tl(ret, 1); \
707 gen_set_label(l2); \
708}
709OP_COND(eq, TCG_COND_EQ);
710OP_COND(ne, TCG_COND_NE);
711OP_COND(ge, TCG_COND_GE);
712OP_COND(geu, TCG_COND_GEU);
713OP_COND(lt, TCG_COND_LT);
714OP_COND(ltu, TCG_COND_LTU);
715#undef OP_COND
716
717#define OP_CONDI(name, cond) \
718static inline void glue(gen_op_, name) (TCGv ret, TCGv t0, target_ulong val) \
719{ \
720 int l1 = gen_new_label(); \
721 int l2 = gen_new_label(); \
722 \
723 tcg_gen_brcondi_tl(cond, t0, val, l1); \
724 tcg_gen_movi_tl(ret, 0); \
725 tcg_gen_br(l2); \
726 gen_set_label(l1); \
727 tcg_gen_movi_tl(ret, 1); \
728 gen_set_label(l2); \
729}
730OP_CONDI(lti, TCG_COND_LT);
731OP_CONDI(ltiu, TCG_COND_LTU);
732#undef OP_CONDI
733
734#define OP_CONDZ(name, cond) \
735static inline void glue(gen_op_, name) (TCGv ret, TCGv t0) \
736{ \
737 int l1 = gen_new_label(); \
738 int l2 = gen_new_label(); \
739 \
740 tcg_gen_brcondi_tl(cond, t0, 0, l1); \
741 tcg_gen_movi_tl(ret, 0); \
742 tcg_gen_br(l2); \
743 gen_set_label(l1); \
744 tcg_gen_movi_tl(ret, 1); \
745 gen_set_label(l2); \
746}
747OP_CONDZ(gez, TCG_COND_GE);
748OP_CONDZ(gtz, TCG_COND_GT);
749OP_CONDZ(lez, TCG_COND_LE);
750OP_CONDZ(ltz, TCG_COND_LT);
751#undef OP_CONDZ
752
753static inline void gen_save_pc(target_ulong pc)
754{
755 tcg_gen_movi_tl(cpu_PC, pc);
756}
757
758static inline void save_cpu_state (DisasContext *ctx, int do_save_pc)
759{
760 LOG_DISAS("hflags %08x saved %08x\n", ctx->hflags, ctx->saved_hflags);
761 if (do_save_pc && ctx->pc != ctx->saved_pc) {
762 gen_save_pc(ctx->pc);
763 ctx->saved_pc = ctx->pc;
764 }
765 if (ctx->hflags != ctx->saved_hflags) {
766 tcg_gen_movi_i32(hflags, ctx->hflags);
767 ctx->saved_hflags = ctx->hflags;
768 switch (ctx->hflags & MIPS_HFLAG_BMASK) {
769 case MIPS_HFLAG_BR:
770 break;
771 case MIPS_HFLAG_BC:
772 case MIPS_HFLAG_BL:
773 case MIPS_HFLAG_B:
774 tcg_gen_movi_tl(btarget, ctx->btarget);
775 break;
776 }
777 }
778}
779
David 'Digit' Turnere2678e12014-01-16 15:56:43 +0100780static inline void restore_cpu_state (CPUMIPSState *env, DisasContext *ctx)
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -0800781{
782 ctx->saved_hflags = ctx->hflags;
783 switch (ctx->hflags & MIPS_HFLAG_BMASK) {
784 case MIPS_HFLAG_BR:
785 break;
786 case MIPS_HFLAG_BC:
787 case MIPS_HFLAG_BL:
788 case MIPS_HFLAG_B:
789 ctx->btarget = env->btarget;
790 break;
791 }
792}
793
794static inline void
795generate_exception_err (DisasContext *ctx, int excp, int err)
796{
797 TCGv_i32 texcp = tcg_const_i32(excp);
798 TCGv_i32 terr = tcg_const_i32(err);
799 save_cpu_state(ctx, 1);
David 'Digit' Turner6480c962014-04-03 12:38:04 +0200800 gen_helper_raise_exception_err(cpu_env, texcp, terr);
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -0800801 tcg_temp_free_i32(terr);
802 tcg_temp_free_i32(texcp);
803}
804
805static inline void
806generate_exception (DisasContext *ctx, int excp)
807{
808 save_cpu_state(ctx, 1);
David 'Digit' Turner6480c962014-04-03 12:38:04 +0200809 gen_helper_1i(raise_exception, cpu_env, excp);
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -0800810}
811
812/* Addresses computation */
813static inline void gen_op_addr_add (DisasContext *ctx, TCGv ret, TCGv arg0, TCGv arg1)
814{
815 tcg_gen_add_tl(ret, arg0, arg1);
816
817#if defined(TARGET_MIPS64)
818 /* For compatibility with 32-bit code, data reference in user mode
819 with Status_UX = 0 should be casted to 32-bit and sign extended.
820 See the MIPS64 PRA manual, section 4.10. */
821 if (((ctx->hflags & MIPS_HFLAG_KSU) == MIPS_HFLAG_UM) &&
822 !(ctx->hflags & MIPS_HFLAG_UX)) {
823 tcg_gen_ext32s_i64(ret, ret);
824 }
825#endif
826}
827
828static inline void check_cp0_enabled(DisasContext *ctx)
829{
830 if (unlikely(!(ctx->hflags & MIPS_HFLAG_CP0)))
831 generate_exception_err(ctx, EXCP_CpU, 0);
832}
833
834static inline void check_cp1_enabled(DisasContext *ctx)
835{
836 if (unlikely(!(ctx->hflags & MIPS_HFLAG_FPU)))
837 generate_exception_err(ctx, EXCP_CpU, 1);
838}
839
840/* Verify that the processor is running with COP1X instructions enabled.
841 This is associated with the nabla symbol in the MIPS32 and MIPS64
842 opcode tables. */
843
844static inline void check_cop1x(DisasContext *ctx)
845{
846 if (unlikely(!(ctx->hflags & MIPS_HFLAG_COP1X)))
847 generate_exception(ctx, EXCP_RI);
848}
849
850/* Verify that the processor is running with 64-bit floating-point
851 operations enabled. */
852
853static inline void check_cp1_64bitmode(DisasContext *ctx)
854{
855 if (unlikely(~ctx->hflags & (MIPS_HFLAG_F64 | MIPS_HFLAG_COP1X)))
856 generate_exception(ctx, EXCP_RI);
857}
858
859/*
860 * Verify if floating point register is valid; an operation is not defined
861 * if bit 0 of any register specification is set and the FR bit in the
862 * Status register equals zero, since the register numbers specify an
863 * even-odd pair of adjacent coprocessor general registers. When the FR bit
864 * in the Status register equals one, both even and odd register numbers
865 * are valid. This limitation exists only for 64 bit wide (d,l,ps) registers.
866 *
867 * Multiple 64 bit wide registers can be checked by calling
868 * gen_op_cp1_registers(freg1 | freg2 | ... | fregN);
869 */
870static inline void check_cp1_registers(DisasContext *ctx, int regs)
871{
872 if (unlikely(!(ctx->hflags & MIPS_HFLAG_F64) && (regs & 1)))
873 generate_exception(ctx, EXCP_RI);
874}
875
876/* This code generates a "reserved instruction" exception if the
877 CPU does not support the instruction set corresponding to flags. */
David 'Digit' Turnere2678e12014-01-16 15:56:43 +0100878static inline void check_insn(CPUMIPSState *env, DisasContext *ctx, int flags)
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -0800879{
880 if (unlikely(!(env->insn_flags & flags)))
881 generate_exception(ctx, EXCP_RI);
882}
883
884/* This code generates a "reserved instruction" exception if 64-bit
885 instructions are not enabled. */
886static inline void check_mips_64(DisasContext *ctx)
887{
888 if (unlikely(!(ctx->hflags & MIPS_HFLAG_64)))
889 generate_exception(ctx, EXCP_RI);
890}
891
892/* load/store instructions. */
893#define OP_LD(insn,fname) \
894static inline void op_ldst_##insn(TCGv ret, TCGv arg1, DisasContext *ctx) \
895{ \
896 tcg_gen_qemu_##fname(ret, arg1, ctx->mem_idx); \
897}
898OP_LD(lb,ld8s);
899OP_LD(lbu,ld8u);
900OP_LD(lh,ld16s);
901OP_LD(lhu,ld16u);
902OP_LD(lw,ld32s);
903#if defined(TARGET_MIPS64)
904OP_LD(lwu,ld32u);
905OP_LD(ld,ld64);
906#endif
907#undef OP_LD
908
909#define OP_ST(insn,fname) \
910static inline void op_ldst_##insn(TCGv arg1, TCGv arg2, DisasContext *ctx) \
911{ \
912 tcg_gen_qemu_##fname(arg1, arg2, ctx->mem_idx); \
913}
914OP_ST(sb,st8);
915OP_ST(sh,st16);
916OP_ST(sw,st32);
917#if defined(TARGET_MIPS64)
918OP_ST(sd,st64);
919#endif
920#undef OP_ST
921
922#ifdef CONFIG_USER_ONLY
923#define OP_LD_ATOMIC(insn,fname) \
924static inline void op_ldst_##insn(TCGv ret, TCGv arg1, DisasContext *ctx) \
925{ \
926 TCGv t0 = tcg_temp_new(); \
927 tcg_gen_mov_tl(t0, arg1); \
928 tcg_gen_qemu_##fname(ret, arg1, ctx->mem_idx); \
David 'Digit' Turnere2678e12014-01-16 15:56:43 +0100929 tcg_gen_st_tl(t0, cpu_env, offsetof(CPUMIPSState, lladdr)); \
930 tcg_gen_st_tl(ret, cpu_env, offsetof(CPUMIPSState, llval)); \
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -0800931 tcg_temp_free(t0); \
932}
933#else
934#define OP_LD_ATOMIC(insn,fname) \
935static inline void op_ldst_##insn(TCGv ret, TCGv arg1, DisasContext *ctx) \
936{ \
David 'Digit' Turnercd35ed22014-04-03 17:23:12 +0200937 gen_helper_3i(insn, ret, cpu_env, arg1, ctx->mem_idx); \
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -0800938}
939#endif
940OP_LD_ATOMIC(ll,ld32s);
941#if defined(TARGET_MIPS64)
942OP_LD_ATOMIC(lld,ld64);
943#endif
944#undef OP_LD_ATOMIC
945
946#ifdef CONFIG_USER_ONLY
947#define OP_ST_ATOMIC(insn,fname,ldname,almask) \
948static inline void op_ldst_##insn(TCGv arg1, TCGv arg2, int rt, DisasContext *ctx) \
949{ \
950 TCGv t0 = tcg_temp_new(); \
951 int l1 = gen_new_label(); \
952 int l2 = gen_new_label(); \
953 \
954 tcg_gen_andi_tl(t0, arg2, almask); \
955 tcg_gen_brcondi_tl(TCG_COND_EQ, t0, 0, l1); \
David 'Digit' Turnere2678e12014-01-16 15:56:43 +0100956 tcg_gen_st_tl(arg2, cpu_env, offsetof(CPUMIPSState, CP0_BadVAddr)); \
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -0800957 generate_exception(ctx, EXCP_AdES); \
958 gen_set_label(l1); \
David 'Digit' Turnere2678e12014-01-16 15:56:43 +0100959 tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUMIPSState, lladdr)); \
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -0800960 tcg_gen_brcond_tl(TCG_COND_NE, arg2, t0, l2); \
961 tcg_gen_movi_tl(t0, rt | ((almask << 3) & 0x20)); \
David 'Digit' Turnere2678e12014-01-16 15:56:43 +0100962 tcg_gen_st_tl(t0, cpu_env, offsetof(CPUMIPSState, llreg)); \
963 tcg_gen_st_tl(arg1, cpu_env, offsetof(CPUMIPSState, llnewval)); \
David 'Digit' Turner6480c962014-04-03 12:38:04 +0200964 gen_helper_1i(raise_exception, cpu_env, EXCP_SC); \
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -0800965 gen_set_label(l2); \
966 tcg_gen_movi_tl(t0, 0); \
967 gen_store_gpr(t0, rt); \
968 tcg_temp_free(t0); \
969}
970#else
971#define OP_ST_ATOMIC(insn,fname,ldname,almask) \
972static inline void op_ldst_##insn(TCGv arg1, TCGv arg2, int rt, DisasContext *ctx) \
973{ \
974 TCGv t0 = tcg_temp_new(); \
David 'Digit' Turnercd35ed22014-04-03 17:23:12 +0200975 gen_helper_4i(insn, t0, cpu_env, arg1, arg2, ctx->mem_idx); \
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -0800976 gen_store_gpr(t0, rt); \
977 tcg_temp_free(t0); \
978}
979#endif
980OP_ST_ATOMIC(sc,st32,ld32s,0x3);
981#if defined(TARGET_MIPS64)
982OP_ST_ATOMIC(scd,st64,ld64,0x7);
983#endif
984#undef OP_ST_ATOMIC
985
986/* Load and store */
987static void gen_ldst (DisasContext *ctx, uint32_t opc, int rt,
988 int base, int16_t offset)
989{
David 'Digit' Turnera2c14f92014-02-04 01:02:30 +0100990 const char * __attribute__((unused)) opn = "ldst";
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -0800991 TCGv t0 = tcg_temp_new();
992 TCGv t1 = tcg_temp_new();
993
994 if (base == 0) {
995 tcg_gen_movi_tl(t0, offset);
996 } else if (offset == 0) {
997 gen_load_gpr(t0, base);
998 } else {
999 tcg_gen_movi_tl(t0, offset);
1000 gen_op_addr_add(ctx, t0, cpu_gpr[base], t0);
1001 }
1002 /* Don't do NOP if destination is zero: we must perform the actual
1003 memory access. */
1004 switch (opc) {
1005#if defined(TARGET_MIPS64)
1006 case OPC_LWU:
1007 save_cpu_state(ctx, 0);
1008 op_ldst_lwu(t0, t0, ctx);
1009 gen_store_gpr(t0, rt);
1010 opn = "lwu";
1011 break;
1012 case OPC_LD:
1013 save_cpu_state(ctx, 0);
1014 op_ldst_ld(t0, t0, ctx);
1015 gen_store_gpr(t0, rt);
1016 opn = "ld";
1017 break;
1018 case OPC_LLD:
1019 save_cpu_state(ctx, 0);
1020 op_ldst_lld(t0, t0, ctx);
1021 gen_store_gpr(t0, rt);
1022 opn = "lld";
1023 break;
1024 case OPC_SD:
1025 save_cpu_state(ctx, 0);
1026 gen_load_gpr(t1, rt);
1027 op_ldst_sd(t1, t0, ctx);
1028 opn = "sd";
1029 break;
1030 case OPC_LDL:
1031 save_cpu_state(ctx, 1);
1032 gen_load_gpr(t1, rt);
David 'Digit' Turnerd62e5382014-04-03 13:13:04 +02001033 gen_helper_4i(ldl, t1, cpu_env, t1, t0, ctx->mem_idx);
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08001034 gen_store_gpr(t1, rt);
1035 opn = "ldl";
1036 break;
1037 case OPC_SDL:
1038 save_cpu_state(ctx, 1);
1039 gen_load_gpr(t1, rt);
David 'Digit' Turnerd62e5382014-04-03 13:13:04 +02001040 gen_helper_3i(sdl, cpu_env, t1, t0, ctx->mem_idx);
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08001041 opn = "sdl";
1042 break;
1043 case OPC_LDR:
1044 save_cpu_state(ctx, 1);
1045 gen_load_gpr(t1, rt);
David 'Digit' Turnerd62e5382014-04-03 13:13:04 +02001046 gen_helper_4i(ldr, t1, cpu_env, t1, t0, ctx->mem_idx);
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08001047 gen_store_gpr(t1, rt);
1048 opn = "ldr";
1049 break;
1050 case OPC_SDR:
1051 save_cpu_state(ctx, 1);
1052 gen_load_gpr(t1, rt);
David 'Digit' Turnerd62e5382014-04-03 13:13:04 +02001053 gen_helper_3i(sdr, cpu_env, t1, t0, ctx->mem_idx);
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08001054 opn = "sdr";
1055 break;
1056#endif
1057 case OPC_LW:
1058 save_cpu_state(ctx, 0);
1059 op_ldst_lw(t0, t0, ctx);
1060 gen_store_gpr(t0, rt);
1061 opn = "lw";
1062 break;
1063 case OPC_SW:
1064 save_cpu_state(ctx, 0);
1065 gen_load_gpr(t1, rt);
1066 op_ldst_sw(t1, t0, ctx);
1067 opn = "sw";
1068 break;
1069 case OPC_LH:
1070 save_cpu_state(ctx, 0);
1071 op_ldst_lh(t0, t0, ctx);
1072 gen_store_gpr(t0, rt);
1073 opn = "lh";
1074 break;
1075 case OPC_SH:
1076 save_cpu_state(ctx, 0);
1077 gen_load_gpr(t1, rt);
1078 op_ldst_sh(t1, t0, ctx);
1079 opn = "sh";
1080 break;
1081 case OPC_LHU:
1082 save_cpu_state(ctx, 0);
1083 op_ldst_lhu(t0, t0, ctx);
1084 gen_store_gpr(t0, rt);
1085 opn = "lhu";
1086 break;
1087 case OPC_LB:
1088 save_cpu_state(ctx, 0);
1089 op_ldst_lb(t0, t0, ctx);
1090 gen_store_gpr(t0, rt);
1091 opn = "lb";
1092 break;
1093 case OPC_SB:
1094 save_cpu_state(ctx, 0);
1095 gen_load_gpr(t1, rt);
1096 op_ldst_sb(t1, t0, ctx);
1097 opn = "sb";
1098 break;
1099 case OPC_LBU:
1100 save_cpu_state(ctx, 0);
1101 op_ldst_lbu(t0, t0, ctx);
1102 gen_store_gpr(t0, rt);
1103 opn = "lbu";
1104 break;
1105 case OPC_LWL:
1106 save_cpu_state(ctx, 1);
1107 gen_load_gpr(t1, rt);
David 'Digit' Turnerd62e5382014-04-03 13:13:04 +02001108 gen_helper_4i(lwl, t1, cpu_env, t1, t0, ctx->mem_idx);
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08001109 gen_store_gpr(t1, rt);
1110 opn = "lwl";
1111 break;
1112 case OPC_SWL:
1113 save_cpu_state(ctx, 1);
1114 gen_load_gpr(t1, rt);
David 'Digit' Turnerd62e5382014-04-03 13:13:04 +02001115 gen_helper_3i(swl, cpu_env, t1, t0, ctx->mem_idx);
1116 opn = "swl";
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08001117 break;
1118 case OPC_LWR:
1119 save_cpu_state(ctx, 1);
1120 gen_load_gpr(t1, rt);
David 'Digit' Turnerd62e5382014-04-03 13:13:04 +02001121 gen_helper_4i(lwr, t1, cpu_env, t1, t0, ctx->mem_idx);
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08001122 gen_store_gpr(t1, rt);
1123 opn = "lwr";
1124 break;
1125 case OPC_SWR:
1126 save_cpu_state(ctx, 1);
1127 gen_load_gpr(t1, rt);
David 'Digit' Turnerd62e5382014-04-03 13:13:04 +02001128 gen_helper_3i(swr, cpu_env, t1, t0, ctx->mem_idx);
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08001129 opn = "swr";
1130 break;
1131 case OPC_LL:
1132 save_cpu_state(ctx, 1);
1133 op_ldst_ll(t0, t0, ctx);
1134 gen_store_gpr(t0, rt);
1135 opn = "ll";
1136 break;
1137 }
1138 MIPS_DEBUG("%s %s, %d(%s)", opn, regnames[rt], offset, regnames[base]);
1139 tcg_temp_free(t0);
1140 tcg_temp_free(t1);
1141}
1142
1143/* Store conditional */
1144static void gen_st_cond (DisasContext *ctx, uint32_t opc, int rt,
1145 int base, int16_t offset)
1146{
David 'Digit' Turnera2c14f92014-02-04 01:02:30 +01001147 const char * __attribute__((unused)) opn = "st_cond";
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08001148 TCGv t0, t1;
1149
1150 t0 = tcg_temp_local_new();
1151
1152 if (base == 0) {
1153 tcg_gen_movi_tl(t0, offset);
1154 } else if (offset == 0) {
1155 gen_load_gpr(t0, base);
1156 } else {
1157 tcg_gen_movi_tl(t0, offset);
1158 gen_op_addr_add(ctx, t0, cpu_gpr[base], t0);
1159 }
1160 /* Don't do NOP if destination is zero: we must perform the actual
1161 memory access. */
1162
1163 t1 = tcg_temp_local_new();
1164 gen_load_gpr(t1, rt);
1165 switch (opc) {
1166#if defined(TARGET_MIPS64)
1167 case OPC_SCD:
1168 save_cpu_state(ctx, 0);
1169 op_ldst_scd(t1, t0, rt, ctx);
1170 opn = "scd";
1171 break;
1172#endif
1173 case OPC_SC:
1174 save_cpu_state(ctx, 1);
1175 op_ldst_sc(t1, t0, rt, ctx);
1176 opn = "sc";
1177 break;
1178 }
1179 MIPS_DEBUG("%s %s, %d(%s)", opn, regnames[rt], offset, regnames[base]);
1180 tcg_temp_free(t1);
1181 tcg_temp_free(t0);
1182}
1183
1184/* Load and store */
1185static void gen_flt_ldst (DisasContext *ctx, uint32_t opc, int ft,
1186 int base, int16_t offset)
1187{
David 'Digit' Turnera2c14f92014-02-04 01:02:30 +01001188 const char * __attribute__((unused)) opn = "flt_ldst";
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08001189 TCGv t0 = tcg_temp_new();
1190
1191 if (base == 0) {
1192 tcg_gen_movi_tl(t0, offset);
1193 } else if (offset == 0) {
1194 gen_load_gpr(t0, base);
1195 } else {
1196 tcg_gen_movi_tl(t0, offset);
1197 gen_op_addr_add(ctx, t0, cpu_gpr[base], t0);
1198 }
1199 /* Don't do NOP if destination is zero: we must perform the actual
1200 memory access. */
1201 switch (opc) {
1202 case OPC_LWC1:
1203 {
1204 TCGv_i32 fp0 = tcg_temp_new_i32();
1205
1206 tcg_gen_qemu_ld32s(t0, t0, ctx->mem_idx);
1207 tcg_gen_trunc_tl_i32(fp0, t0);
1208 gen_store_fpr32(fp0, ft);
1209 tcg_temp_free_i32(fp0);
1210 }
1211 opn = "lwc1";
1212 break;
1213 case OPC_SWC1:
1214 {
1215 TCGv_i32 fp0 = tcg_temp_new_i32();
1216 TCGv t1 = tcg_temp_new();
1217
1218 gen_load_fpr32(fp0, ft);
1219 tcg_gen_extu_i32_tl(t1, fp0);
1220 tcg_gen_qemu_st32(t1, t0, ctx->mem_idx);
1221 tcg_temp_free(t1);
1222 tcg_temp_free_i32(fp0);
1223 }
1224 opn = "swc1";
1225 break;
1226 case OPC_LDC1:
1227 {
1228 TCGv_i64 fp0 = tcg_temp_new_i64();
1229
1230 tcg_gen_qemu_ld64(fp0, t0, ctx->mem_idx);
1231 gen_store_fpr64(ctx, fp0, ft);
1232 tcg_temp_free_i64(fp0);
1233 }
1234 opn = "ldc1";
1235 break;
1236 case OPC_SDC1:
1237 {
1238 TCGv_i64 fp0 = tcg_temp_new_i64();
1239
1240 gen_load_fpr64(ctx, fp0, ft);
1241 tcg_gen_qemu_st64(fp0, t0, ctx->mem_idx);
1242 tcg_temp_free_i64(fp0);
1243 }
1244 opn = "sdc1";
1245 break;
1246 default:
1247 MIPS_INVAL(opn);
1248 generate_exception(ctx, EXCP_RI);
1249 goto out;
1250 }
1251 MIPS_DEBUG("%s %s, %d(%s)", opn, fregnames[ft], offset, regnames[base]);
1252 out:
1253 tcg_temp_free(t0);
1254}
1255
1256/* Arithmetic with immediate operand */
David 'Digit' Turnere2678e12014-01-16 15:56:43 +01001257static void gen_arith_imm (CPUMIPSState *env, DisasContext *ctx, uint32_t opc,
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08001258 int rt, int rs, int16_t imm)
1259{
1260 target_ulong uimm = (target_long)imm; /* Sign extend to 32/64 bits */
David 'Digit' Turnera2c14f92014-02-04 01:02:30 +01001261 const char * __attribute__((unused)) opn = "imm arith";
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08001262
1263 if (rt == 0 && opc != OPC_ADDI && opc != OPC_DADDI) {
1264 /* If no destination, treat it as a NOP.
1265 For addi, we must generate the overflow exception when needed. */
1266 MIPS_DEBUG("NOP");
1267 return;
1268 }
1269 switch (opc) {
1270 case OPC_ADDI:
1271 {
1272 TCGv t0 = tcg_temp_local_new();
1273 TCGv t1 = tcg_temp_new();
1274 TCGv t2 = tcg_temp_new();
1275 int l1 = gen_new_label();
1276
1277 gen_load_gpr(t1, rs);
1278 tcg_gen_addi_tl(t0, t1, uimm);
1279 tcg_gen_ext32s_tl(t0, t0);
1280
1281 tcg_gen_xori_tl(t1, t1, ~uimm);
1282 tcg_gen_xori_tl(t2, t0, uimm);
1283 tcg_gen_and_tl(t1, t1, t2);
1284 tcg_temp_free(t2);
1285 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
1286 tcg_temp_free(t1);
1287 /* operands of same sign, result different sign */
1288 generate_exception(ctx, EXCP_OVERFLOW);
1289 gen_set_label(l1);
1290 tcg_gen_ext32s_tl(t0, t0);
1291 gen_store_gpr(t0, rt);
1292 tcg_temp_free(t0);
1293 }
1294 opn = "addi";
1295 break;
1296 case OPC_ADDIU:
1297 if (rs != 0) {
1298 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
1299 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
1300 } else {
1301 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
1302 }
1303 opn = "addiu";
1304 break;
1305#if defined(TARGET_MIPS64)
1306 case OPC_DADDI:
1307 {
1308 TCGv t0 = tcg_temp_local_new();
1309 TCGv t1 = tcg_temp_new();
1310 TCGv t2 = tcg_temp_new();
1311 int l1 = gen_new_label();
1312
1313 gen_load_gpr(t1, rs);
1314 tcg_gen_addi_tl(t0, t1, uimm);
1315
1316 tcg_gen_xori_tl(t1, t1, ~uimm);
1317 tcg_gen_xori_tl(t2, t0, uimm);
1318 tcg_gen_and_tl(t1, t1, t2);
1319 tcg_temp_free(t2);
1320 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
1321 tcg_temp_free(t1);
1322 /* operands of same sign, result different sign */
1323 generate_exception(ctx, EXCP_OVERFLOW);
1324 gen_set_label(l1);
1325 gen_store_gpr(t0, rt);
1326 tcg_temp_free(t0);
1327 }
1328 opn = "daddi";
1329 break;
1330 case OPC_DADDIU:
1331 if (rs != 0) {
1332 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
1333 } else {
1334 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
1335 }
1336 opn = "daddiu";
1337 break;
1338#endif
1339 }
1340 MIPS_DEBUG("%s %s, %s, " TARGET_FMT_lx, opn, regnames[rt], regnames[rs], uimm);
1341}
1342
1343/* Logic with immediate operand */
David 'Digit' Turnere2678e12014-01-16 15:56:43 +01001344static void gen_logic_imm (CPUMIPSState *env, uint32_t opc, int rt, int rs, int16_t imm)
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08001345{
1346 target_ulong uimm;
David 'Digit' Turnera2c14f92014-02-04 01:02:30 +01001347 const char * __attribute__((unused)) opn = "imm logic";
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08001348
1349 if (rt == 0) {
1350 /* If no destination, treat it as a NOP. */
1351 MIPS_DEBUG("NOP");
1352 return;
1353 }
1354 uimm = (uint16_t)imm;
1355 switch (opc) {
1356 case OPC_ANDI:
1357 if (likely(rs != 0))
1358 tcg_gen_andi_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
1359 else
1360 tcg_gen_movi_tl(cpu_gpr[rt], 0);
1361 opn = "andi";
1362 break;
1363 case OPC_ORI:
1364 if (rs != 0)
1365 tcg_gen_ori_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
1366 else
1367 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
1368 opn = "ori";
1369 break;
1370 case OPC_XORI:
1371 if (likely(rs != 0))
1372 tcg_gen_xori_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
1373 else
1374 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
1375 opn = "xori";
1376 break;
1377 case OPC_LUI:
1378 tcg_gen_movi_tl(cpu_gpr[rt], imm << 16);
1379 opn = "lui";
1380 break;
1381 }
1382 MIPS_DEBUG("%s %s, %s, " TARGET_FMT_lx, opn, regnames[rt], regnames[rs], uimm);
1383}
1384
1385/* Set on less than with immediate operand */
David 'Digit' Turnere2678e12014-01-16 15:56:43 +01001386static void gen_slt_imm (CPUMIPSState *env, uint32_t opc, int rt, int rs, int16_t imm)
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08001387{
1388 target_ulong uimm = (target_long)imm; /* Sign extend to 32/64 bits */
David 'Digit' Turnera2c14f92014-02-04 01:02:30 +01001389 const char * __attribute__((unused)) opn = "imm arith";
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08001390 TCGv t0;
1391
1392 if (rt == 0) {
1393 /* If no destination, treat it as a NOP. */
1394 MIPS_DEBUG("NOP");
1395 return;
1396 }
1397 t0 = tcg_temp_new();
1398 gen_load_gpr(t0, rs);
1399 switch (opc) {
1400 case OPC_SLTI:
1401 gen_op_lti(cpu_gpr[rt], t0, uimm);
1402 opn = "slti";
1403 break;
1404 case OPC_SLTIU:
1405 gen_op_ltiu(cpu_gpr[rt], t0, uimm);
1406 opn = "sltiu";
1407 break;
1408 }
1409 MIPS_DEBUG("%s %s, %s, " TARGET_FMT_lx, opn, regnames[rt], regnames[rs], uimm);
1410 tcg_temp_free(t0);
1411}
1412
1413/* Shifts with immediate operand */
David 'Digit' Turnere2678e12014-01-16 15:56:43 +01001414static void gen_shift_imm(CPUMIPSState *env, DisasContext *ctx, uint32_t opc,
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08001415 int rt, int rs, int16_t imm)
1416{
1417 target_ulong uimm = ((uint16_t)imm) & 0x1f;
David 'Digit' Turnera2c14f92014-02-04 01:02:30 +01001418 const char* __attribute__((unused)) opn = "imm shift";
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08001419 TCGv t0;
1420
1421 if (rt == 0) {
1422 /* If no destination, treat it as a NOP. */
1423 MIPS_DEBUG("NOP");
1424 return;
1425 }
1426
1427 t0 = tcg_temp_new();
1428 gen_load_gpr(t0, rs);
1429 switch (opc) {
1430 case OPC_SLL:
1431 tcg_gen_shli_tl(t0, t0, uimm);
1432 tcg_gen_ext32s_tl(cpu_gpr[rt], t0);
1433 opn = "sll";
1434 break;
1435 case OPC_SRA:
1436 tcg_gen_ext32s_tl(t0, t0);
1437 tcg_gen_sari_tl(cpu_gpr[rt], t0, uimm);
1438 opn = "sra";
1439 break;
1440 case OPC_SRL:
1441 switch ((ctx->opcode >> 21) & 0x1f) {
1442 case 0:
1443 if (uimm != 0) {
1444 tcg_gen_ext32u_tl(t0, t0);
1445 tcg_gen_shri_tl(cpu_gpr[rt], t0, uimm);
1446 } else {
1447 tcg_gen_ext32s_tl(cpu_gpr[rt], t0);
1448 }
1449 opn = "srl";
1450 break;
1451 case 1:
1452 /* rotr is decoded as srl on non-R2 CPUs */
1453 if (env->insn_flags & ISA_MIPS32R2) {
1454 if (uimm != 0) {
1455 TCGv_i32 t1 = tcg_temp_new_i32();
1456
1457 tcg_gen_trunc_tl_i32(t1, t0);
1458 tcg_gen_rotri_i32(t1, t1, uimm);
1459 tcg_gen_ext_i32_tl(cpu_gpr[rt], t1);
1460 tcg_temp_free_i32(t1);
1461 } else {
1462 tcg_gen_ext32s_tl(cpu_gpr[rt], t0);
1463 }
1464 opn = "rotr";
1465 } else {
1466 if (uimm != 0) {
1467 tcg_gen_ext32u_tl(t0, t0);
1468 tcg_gen_shri_tl(cpu_gpr[rt], t0, uimm);
1469 } else {
1470 tcg_gen_ext32s_tl(cpu_gpr[rt], t0);
1471 }
1472 opn = "srl";
1473 }
1474 break;
1475 default:
1476 MIPS_INVAL("invalid srl flag");
1477 generate_exception(ctx, EXCP_RI);
1478 break;
1479 }
1480 break;
1481#if defined(TARGET_MIPS64)
1482 case OPC_DSLL:
1483 tcg_gen_shli_tl(cpu_gpr[rt], t0, uimm);
1484 opn = "dsll";
1485 break;
1486 case OPC_DSRA:
1487 tcg_gen_sari_tl(cpu_gpr[rt], t0, uimm);
1488 opn = "dsra";
1489 break;
1490 case OPC_DSRL:
1491 switch ((ctx->opcode >> 21) & 0x1f) {
1492 case 0:
1493 tcg_gen_shri_tl(cpu_gpr[rt], t0, uimm);
1494 opn = "dsrl";
1495 break;
1496 case 1:
1497 /* drotr is decoded as dsrl on non-R2 CPUs */
1498 if (env->insn_flags & ISA_MIPS32R2) {
1499 if (uimm != 0) {
1500 tcg_gen_rotri_tl(cpu_gpr[rt], t0, uimm);
1501 } else {
1502 tcg_gen_mov_tl(cpu_gpr[rt], t0);
1503 }
1504 opn = "drotr";
1505 } else {
1506 tcg_gen_shri_tl(cpu_gpr[rt], t0, uimm);
1507 opn = "dsrl";
1508 }
1509 break;
1510 default:
1511 MIPS_INVAL("invalid dsrl flag");
1512 generate_exception(ctx, EXCP_RI);
1513 break;
1514 }
1515 break;
1516 case OPC_DSLL32:
1517 tcg_gen_shli_tl(cpu_gpr[rt], t0, uimm + 32);
1518 opn = "dsll32";
1519 break;
1520 case OPC_DSRA32:
1521 tcg_gen_sari_tl(cpu_gpr[rt], t0, uimm + 32);
1522 opn = "dsra32";
1523 break;
1524 case OPC_DSRL32:
1525 switch ((ctx->opcode >> 21) & 0x1f) {
1526 case 0:
1527 tcg_gen_shri_tl(cpu_gpr[rt], t0, uimm + 32);
1528 opn = "dsrl32";
1529 break;
1530 case 1:
1531 /* drotr32 is decoded as dsrl32 on non-R2 CPUs */
1532 if (env->insn_flags & ISA_MIPS32R2) {
1533 tcg_gen_rotri_tl(cpu_gpr[rt], t0, uimm + 32);
1534 opn = "drotr32";
1535 } else {
1536 tcg_gen_shri_tl(cpu_gpr[rt], t0, uimm + 32);
1537 opn = "dsrl32";
1538 }
1539 break;
1540 default:
1541 MIPS_INVAL("invalid dsrl32 flag");
1542 generate_exception(ctx, EXCP_RI);
1543 break;
1544 }
1545 break;
1546#endif
1547 }
1548 MIPS_DEBUG("%s %s, %s, " TARGET_FMT_lx, opn, regnames[rt], regnames[rs], uimm);
1549 tcg_temp_free(t0);
1550}
1551
1552/* Arithmetic */
David 'Digit' Turnere2678e12014-01-16 15:56:43 +01001553static void gen_arith (CPUMIPSState *env, DisasContext *ctx, uint32_t opc,
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08001554 int rd, int rs, int rt)
1555{
David 'Digit' Turnera2c14f92014-02-04 01:02:30 +01001556 const char* __attribute__((unused)) opn = "arith";
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08001557
1558 if (rd == 0 && opc != OPC_ADD && opc != OPC_SUB
1559 && opc != OPC_DADD && opc != OPC_DSUB) {
1560 /* If no destination, treat it as a NOP.
1561 For add & sub, we must generate the overflow exception when needed. */
1562 MIPS_DEBUG("NOP");
1563 return;
1564 }
1565
1566 switch (opc) {
1567 case OPC_ADD:
1568 {
1569 TCGv t0 = tcg_temp_local_new();
1570 TCGv t1 = tcg_temp_new();
1571 TCGv t2 = tcg_temp_new();
1572 int l1 = gen_new_label();
1573
1574 gen_load_gpr(t1, rs);
1575 gen_load_gpr(t2, rt);
1576 tcg_gen_add_tl(t0, t1, t2);
1577 tcg_gen_ext32s_tl(t0, t0);
1578 tcg_gen_xor_tl(t1, t1, t2);
1579 tcg_gen_not_tl(t1, t1);
1580 tcg_gen_xor_tl(t2, t0, t2);
1581 tcg_gen_and_tl(t1, t1, t2);
1582 tcg_temp_free(t2);
1583 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
1584 tcg_temp_free(t1);
1585 /* operands of same sign, result different sign */
1586 generate_exception(ctx, EXCP_OVERFLOW);
1587 gen_set_label(l1);
1588 gen_store_gpr(t0, rd);
1589 tcg_temp_free(t0);
1590 }
1591 opn = "add";
1592 break;
1593 case OPC_ADDU:
1594 if (rs != 0 && rt != 0) {
1595 tcg_gen_add_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
1596 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
1597 } else if (rs == 0 && rt != 0) {
1598 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
1599 } else if (rs != 0 && rt == 0) {
1600 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
1601 } else {
1602 tcg_gen_movi_tl(cpu_gpr[rd], 0);
1603 }
1604 opn = "addu";
1605 break;
1606 case OPC_SUB:
1607 {
1608 TCGv t0 = tcg_temp_local_new();
1609 TCGv t1 = tcg_temp_new();
1610 TCGv t2 = tcg_temp_new();
1611 int l1 = gen_new_label();
1612
1613 gen_load_gpr(t1, rs);
1614 gen_load_gpr(t2, rt);
1615 tcg_gen_sub_tl(t0, t1, t2);
1616 tcg_gen_ext32s_tl(t0, t0);
1617 tcg_gen_xor_tl(t2, t1, t2);
1618 tcg_gen_xor_tl(t1, t0, t1);
1619 tcg_gen_and_tl(t1, t1, t2);
1620 tcg_temp_free(t2);
1621 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
1622 tcg_temp_free(t1);
1623 /* operands of different sign, first operand and result different sign */
1624 generate_exception(ctx, EXCP_OVERFLOW);
1625 gen_set_label(l1);
1626 gen_store_gpr(t0, rd);
1627 tcg_temp_free(t0);
1628 }
1629 opn = "sub";
1630 break;
1631 case OPC_SUBU:
1632 if (rs != 0 && rt != 0) {
1633 tcg_gen_sub_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
1634 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
1635 } else if (rs == 0 && rt != 0) {
1636 tcg_gen_neg_tl(cpu_gpr[rd], cpu_gpr[rt]);
1637 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
1638 } else if (rs != 0 && rt == 0) {
1639 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
1640 } else {
1641 tcg_gen_movi_tl(cpu_gpr[rd], 0);
1642 }
1643 opn = "subu";
1644 break;
1645#if defined(TARGET_MIPS64)
1646 case OPC_DADD:
1647 {
1648 TCGv t0 = tcg_temp_local_new();
1649 TCGv t1 = tcg_temp_new();
1650 TCGv t2 = tcg_temp_new();
1651 int l1 = gen_new_label();
1652
1653 gen_load_gpr(t1, rs);
1654 gen_load_gpr(t2, rt);
1655 tcg_gen_add_tl(t0, t1, t2);
1656 tcg_gen_xor_tl(t1, t1, t2);
1657 tcg_gen_not_tl(t1, t1);
1658 tcg_gen_xor_tl(t2, t0, t2);
1659 tcg_gen_and_tl(t1, t1, t2);
1660 tcg_temp_free(t2);
1661 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
1662 tcg_temp_free(t1);
1663 /* operands of same sign, result different sign */
1664 generate_exception(ctx, EXCP_OVERFLOW);
1665 gen_set_label(l1);
1666 gen_store_gpr(t0, rd);
1667 tcg_temp_free(t0);
1668 }
1669 opn = "dadd";
1670 break;
1671 case OPC_DADDU:
1672 if (rs != 0 && rt != 0) {
1673 tcg_gen_add_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
1674 } else if (rs == 0 && rt != 0) {
1675 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
1676 } else if (rs != 0 && rt == 0) {
1677 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
1678 } else {
1679 tcg_gen_movi_tl(cpu_gpr[rd], 0);
1680 }
1681 opn = "daddu";
1682 break;
1683 case OPC_DSUB:
1684 {
1685 TCGv t0 = tcg_temp_local_new();
1686 TCGv t1 = tcg_temp_new();
1687 TCGv t2 = tcg_temp_new();
1688 int l1 = gen_new_label();
1689
1690 gen_load_gpr(t1, rs);
1691 gen_load_gpr(t2, rt);
1692 tcg_gen_sub_tl(t0, t1, t2);
1693 tcg_gen_xor_tl(t2, t1, t2);
1694 tcg_gen_xor_tl(t1, t0, t1);
1695 tcg_gen_and_tl(t1, t1, t2);
1696 tcg_temp_free(t2);
1697 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
1698 tcg_temp_free(t1);
1699 /* operands of different sign, first operand and result different sign */
1700 generate_exception(ctx, EXCP_OVERFLOW);
1701 gen_set_label(l1);
1702 gen_store_gpr(t0, rd);
1703 tcg_temp_free(t0);
1704 }
1705 opn = "dsub";
1706 break;
1707 case OPC_DSUBU:
1708 if (rs != 0 && rt != 0) {
1709 tcg_gen_sub_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
1710 } else if (rs == 0 && rt != 0) {
1711 tcg_gen_neg_tl(cpu_gpr[rd], cpu_gpr[rt]);
1712 } else if (rs != 0 && rt == 0) {
1713 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
1714 } else {
1715 tcg_gen_movi_tl(cpu_gpr[rd], 0);
1716 }
1717 opn = "dsubu";
1718 break;
1719#endif
1720 case OPC_MUL:
1721 if (likely(rs != 0 && rt != 0)) {
1722 tcg_gen_mul_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
1723 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
1724 } else {
1725 tcg_gen_movi_tl(cpu_gpr[rd], 0);
1726 }
1727 opn = "mul";
1728 break;
1729 }
1730 MIPS_DEBUG("%s %s, %s, %s", opn, regnames[rd], regnames[rs], regnames[rt]);
1731}
1732
1733/* Conditional move */
David 'Digit' Turnere2678e12014-01-16 15:56:43 +01001734static void gen_cond_move (CPUMIPSState *env, uint32_t opc, int rd, int rs, int rt)
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08001735{
David 'Digit' Turnera2c14f92014-02-04 01:02:30 +01001736 const char* __attribute__((unused)) opn = "cond move";
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08001737 int l1;
1738
1739 if (rd == 0) {
1740 /* If no destination, treat it as a NOP.
1741 For add & sub, we must generate the overflow exception when needed. */
1742 MIPS_DEBUG("NOP");
1743 return;
1744 }
1745
1746 l1 = gen_new_label();
1747 switch (opc) {
1748 case OPC_MOVN:
1749 if (likely(rt != 0))
1750 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[rt], 0, l1);
1751 else
1752 tcg_gen_br(l1);
1753 opn = "movn";
1754 break;
1755 case OPC_MOVZ:
1756 if (likely(rt != 0))
1757 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[rt], 0, l1);
1758 opn = "movz";
1759 break;
1760 }
1761 if (rs != 0)
1762 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
1763 else
1764 tcg_gen_movi_tl(cpu_gpr[rd], 0);
1765 gen_set_label(l1);
1766
1767 MIPS_DEBUG("%s %s, %s, %s", opn, regnames[rd], regnames[rs], regnames[rt]);
1768}
1769
1770/* Logic */
David 'Digit' Turnere2678e12014-01-16 15:56:43 +01001771static void gen_logic (CPUMIPSState *env, uint32_t opc, int rd, int rs, int rt)
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08001772{
David 'Digit' Turnera2c14f92014-02-04 01:02:30 +01001773 const char* __attribute__((unused)) opn = "logic";
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08001774
1775 if (rd == 0) {
1776 /* If no destination, treat it as a NOP. */
1777 MIPS_DEBUG("NOP");
1778 return;
1779 }
1780
1781 switch (opc) {
1782 case OPC_AND:
1783 if (likely(rs != 0 && rt != 0)) {
1784 tcg_gen_and_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
1785 } else {
1786 tcg_gen_movi_tl(cpu_gpr[rd], 0);
1787 }
1788 opn = "and";
1789 break;
1790 case OPC_NOR:
1791 if (rs != 0 && rt != 0) {
1792 tcg_gen_nor_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
1793 } else if (rs == 0 && rt != 0) {
1794 tcg_gen_not_tl(cpu_gpr[rd], cpu_gpr[rt]);
1795 } else if (rs != 0 && rt == 0) {
1796 tcg_gen_not_tl(cpu_gpr[rd], cpu_gpr[rs]);
1797 } else {
1798 tcg_gen_movi_tl(cpu_gpr[rd], ~((target_ulong)0));
1799 }
1800 opn = "nor";
1801 break;
1802 case OPC_OR:
1803 if (likely(rs != 0 && rt != 0)) {
1804 tcg_gen_or_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
1805 } else if (rs == 0 && rt != 0) {
1806 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
1807 } else if (rs != 0 && rt == 0) {
1808 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
1809 } else {
1810 tcg_gen_movi_tl(cpu_gpr[rd], 0);
1811 }
1812 opn = "or";
1813 break;
1814 case OPC_XOR:
1815 if (likely(rs != 0 && rt != 0)) {
1816 tcg_gen_xor_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
1817 } else if (rs == 0 && rt != 0) {
1818 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
1819 } else if (rs != 0 && rt == 0) {
1820 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
1821 } else {
1822 tcg_gen_movi_tl(cpu_gpr[rd], 0);
1823 }
1824 opn = "xor";
1825 break;
1826 }
1827 MIPS_DEBUG("%s %s, %s, %s", opn, regnames[rd], regnames[rs], regnames[rt]);
1828}
1829
1830/* Set on lower than */
David 'Digit' Turnere2678e12014-01-16 15:56:43 +01001831static void gen_slt (CPUMIPSState *env, uint32_t opc, int rd, int rs, int rt)
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08001832{
David 'Digit' Turnera2c14f92014-02-04 01:02:30 +01001833 const char* __attribute__((unused)) opn = "slt";
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08001834 TCGv t0, t1;
1835
1836 if (rd == 0) {
1837 /* If no destination, treat it as a NOP. */
1838 MIPS_DEBUG("NOP");
1839 return;
1840 }
1841
1842 t0 = tcg_temp_new();
1843 t1 = tcg_temp_new();
1844 gen_load_gpr(t0, rs);
1845 gen_load_gpr(t1, rt);
1846 switch (opc) {
1847 case OPC_SLT:
1848 gen_op_lt(cpu_gpr[rd], t0, t1);
1849 opn = "slt";
1850 break;
1851 case OPC_SLTU:
1852 gen_op_ltu(cpu_gpr[rd], t0, t1);
1853 opn = "sltu";
1854 break;
1855 }
1856 MIPS_DEBUG("%s %s, %s, %s", opn, regnames[rd], regnames[rs], regnames[rt]);
1857 tcg_temp_free(t0);
1858 tcg_temp_free(t1);
1859}
1860
1861/* Shifts */
David 'Digit' Turnere2678e12014-01-16 15:56:43 +01001862static void gen_shift (CPUMIPSState *env, DisasContext *ctx, uint32_t opc,
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08001863 int rd, int rs, int rt)
1864{
David 'Digit' Turnera2c14f92014-02-04 01:02:30 +01001865 const char* __attribute__((unused)) opn = "shifts";
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08001866 TCGv t0, t1;
1867
1868 if (rd == 0) {
1869 /* If no destination, treat it as a NOP.
1870 For add & sub, we must generate the overflow exception when needed. */
1871 MIPS_DEBUG("NOP");
1872 return;
1873 }
1874
1875 t0 = tcg_temp_new();
1876 t1 = tcg_temp_new();
1877 gen_load_gpr(t0, rs);
1878 gen_load_gpr(t1, rt);
1879 switch (opc) {
1880 case OPC_SLLV:
1881 tcg_gen_andi_tl(t0, t0, 0x1f);
1882 tcg_gen_shl_tl(t0, t1, t0);
1883 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
1884 opn = "sllv";
1885 break;
1886 case OPC_SRAV:
1887 tcg_gen_ext32s_tl(t1, t1);
1888 tcg_gen_andi_tl(t0, t0, 0x1f);
1889 tcg_gen_sar_tl(cpu_gpr[rd], t1, t0);
1890 opn = "srav";
1891 break;
1892 case OPC_SRLV:
1893 switch ((ctx->opcode >> 6) & 0x1f) {
1894 case 0:
1895 tcg_gen_ext32u_tl(t1, t1);
1896 tcg_gen_andi_tl(t0, t0, 0x1f);
1897 tcg_gen_shr_tl(t0, t1, t0);
1898 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
1899 opn = "srlv";
1900 break;
1901 case 1:
1902 /* rotrv is decoded as srlv on non-R2 CPUs */
1903 if (env->insn_flags & ISA_MIPS32R2) {
1904 TCGv_i32 t2 = tcg_temp_new_i32();
1905 TCGv_i32 t3 = tcg_temp_new_i32();
1906
1907 tcg_gen_trunc_tl_i32(t2, t0);
1908 tcg_gen_trunc_tl_i32(t3, t1);
1909 tcg_gen_andi_i32(t2, t2, 0x1f);
1910 tcg_gen_rotr_i32(t2, t3, t2);
1911 tcg_gen_ext_i32_tl(cpu_gpr[rd], t2);
1912 tcg_temp_free_i32(t2);
1913 tcg_temp_free_i32(t3);
1914 opn = "rotrv";
1915 } else {
1916 tcg_gen_ext32u_tl(t1, t1);
1917 tcg_gen_andi_tl(t0, t0, 0x1f);
1918 tcg_gen_shr_tl(t0, t1, t0);
1919 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
1920 opn = "srlv";
1921 }
1922 break;
1923 default:
1924 MIPS_INVAL("invalid srlv flag");
1925 generate_exception(ctx, EXCP_RI);
1926 break;
1927 }
1928 break;
1929#if defined(TARGET_MIPS64)
1930 case OPC_DSLLV:
1931 tcg_gen_andi_tl(t0, t0, 0x3f);
1932 tcg_gen_shl_tl(cpu_gpr[rd], t1, t0);
1933 opn = "dsllv";
1934 break;
1935 case OPC_DSRAV:
1936 tcg_gen_andi_tl(t0, t0, 0x3f);
1937 tcg_gen_sar_tl(cpu_gpr[rd], t1, t0);
1938 opn = "dsrav";
1939 break;
1940 case OPC_DSRLV:
1941 switch ((ctx->opcode >> 6) & 0x1f) {
1942 case 0:
1943 tcg_gen_andi_tl(t0, t0, 0x3f);
1944 tcg_gen_shr_tl(cpu_gpr[rd], t1, t0);
1945 opn = "dsrlv";
1946 break;
1947 case 1:
1948 /* drotrv is decoded as dsrlv on non-R2 CPUs */
1949 if (env->insn_flags & ISA_MIPS32R2) {
1950 tcg_gen_andi_tl(t0, t0, 0x3f);
1951 tcg_gen_rotr_tl(cpu_gpr[rd], t1, t0);
1952 opn = "drotrv";
1953 } else {
1954 tcg_gen_andi_tl(t0, t0, 0x3f);
1955 tcg_gen_shr_tl(t0, t1, t0);
1956 opn = "dsrlv";
1957 }
1958 break;
1959 default:
1960 MIPS_INVAL("invalid dsrlv flag");
1961 generate_exception(ctx, EXCP_RI);
1962 break;
1963 }
1964 break;
1965#endif
1966 }
1967 MIPS_DEBUG("%s %s, %s, %s", opn, regnames[rd], regnames[rs], regnames[rt]);
1968 tcg_temp_free(t0);
1969 tcg_temp_free(t1);
1970}
1971
1972/* Arithmetic on HI/LO registers */
1973static void gen_HILO (DisasContext *ctx, uint32_t opc, int reg)
1974{
David 'Digit' Turnera2c14f92014-02-04 01:02:30 +01001975 const char* __attribute__((unused)) opn = "hilo";
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08001976
1977 if (reg == 0 && (opc == OPC_MFHI || opc == OPC_MFLO)) {
1978 /* Treat as NOP. */
1979 MIPS_DEBUG("NOP");
1980 return;
1981 }
1982 switch (opc) {
1983 case OPC_MFHI:
1984 tcg_gen_mov_tl(cpu_gpr[reg], cpu_HI[0]);
1985 opn = "mfhi";
1986 break;
1987 case OPC_MFLO:
1988 tcg_gen_mov_tl(cpu_gpr[reg], cpu_LO[0]);
1989 opn = "mflo";
1990 break;
1991 case OPC_MTHI:
1992 if (reg != 0)
1993 tcg_gen_mov_tl(cpu_HI[0], cpu_gpr[reg]);
1994 else
1995 tcg_gen_movi_tl(cpu_HI[0], 0);
1996 opn = "mthi";
1997 break;
1998 case OPC_MTLO:
1999 if (reg != 0)
2000 tcg_gen_mov_tl(cpu_LO[0], cpu_gpr[reg]);
2001 else
2002 tcg_gen_movi_tl(cpu_LO[0], 0);
2003 opn = "mtlo";
2004 break;
2005 }
2006 MIPS_DEBUG("%s %s", opn, regnames[reg]);
2007}
2008
2009static void gen_muldiv (DisasContext *ctx, uint32_t opc,
2010 int rs, int rt)
2011{
David 'Digit' Turnera2c14f92014-02-04 01:02:30 +01002012 const char* __attribute__((unused)) opn = "mul/div";
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08002013 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 }
2030
2031 gen_load_gpr(t0, rs);
2032 gen_load_gpr(t1, rt);
2033 switch (opc) {
2034 case OPC_DIV:
2035 {
2036 int l1 = gen_new_label();
2037 int l2 = gen_new_label();
2038
2039 tcg_gen_ext32s_tl(t0, t0);
2040 tcg_gen_ext32s_tl(t1, t1);
2041 tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
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]);
2053 gen_set_label(l1);
2054 }
2055 opn = "div";
2056 break;
2057 case OPC_DIVU:
2058 {
2059 int l1 = gen_new_label();
2060
2061 tcg_gen_ext32u_tl(t0, t0);
2062 tcg_gen_ext32u_tl(t1, t1);
2063 tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
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]);
2068 gen_set_label(l1);
2069 }
2070 opn = "divu";
2071 break;
2072 case OPC_MULT:
2073 {
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);
2085 tcg_gen_ext32s_tl(cpu_LO[0], t0);
2086 tcg_gen_ext32s_tl(cpu_HI[0], t1);
2087 }
2088 opn = "mult";
2089 break;
2090 case OPC_MULTU:
2091 {
2092 TCGv_i64 t2 = tcg_temp_new_i64();
2093 TCGv_i64 t3 = tcg_temp_new_i64();
2094
2095 tcg_gen_ext32u_tl(t0, t0);
2096 tcg_gen_ext32u_tl(t1, t1);
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);
2105 tcg_gen_ext32s_tl(cpu_LO[0], t0);
2106 tcg_gen_ext32s_tl(cpu_HI[0], t1);
2107 }
2108 opn = "multu";
2109 break;
2110#if defined(TARGET_MIPS64)
2111 case OPC_DDIV:
2112 {
2113 int l1 = gen_new_label();
2114 int l2 = gen_new_label();
2115
2116 tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
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);
2125 gen_set_label(l1);
2126 }
2127 opn = "ddiv";
2128 break;
2129 case OPC_DDIVU:
2130 {
2131 int l1 = gen_new_label();
2132
2133 tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
2134 tcg_gen_divu_i64(cpu_LO[0], t0, t1);
2135 tcg_gen_remu_i64(cpu_HI[0], t0, t1);
2136 gen_set_label(l1);
2137 }
2138 opn = "ddivu";
2139 break;
2140 case OPC_DMULT:
2141 gen_helper_dmult(t0, t1);
2142 opn = "dmult";
2143 break;
2144 case OPC_DMULTU:
2145 gen_helper_dmultu(t0, t1);
2146 opn = "dmultu";
2147 break;
2148#endif
2149 case OPC_MADD:
2150 {
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);
2164 tcg_gen_ext32s_tl(cpu_LO[0], t0);
2165 tcg_gen_ext32s_tl(cpu_HI[0], t1);
2166 }
2167 opn = "madd";
2168 break;
2169 case OPC_MADDU:
2170 {
2171 TCGv_i64 t2 = tcg_temp_new_i64();
2172 TCGv_i64 t3 = tcg_temp_new_i64();
2173
2174 tcg_gen_ext32u_tl(t0, t0);
2175 tcg_gen_ext32u_tl(t1, t1);
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);
2186 tcg_gen_ext32s_tl(cpu_LO[0], t0);
2187 tcg_gen_ext32s_tl(cpu_HI[0], t1);
2188 }
2189 opn = "maddu";
2190 break;
2191 case OPC_MSUB:
2192 {
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]);
2200 tcg_gen_sub_i64(t2, t3, t2);
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);
2206 tcg_gen_ext32s_tl(cpu_LO[0], t0);
2207 tcg_gen_ext32s_tl(cpu_HI[0], t1);
2208 }
2209 opn = "msub";
2210 break;
2211 case OPC_MSUBU:
2212 {
2213 TCGv_i64 t2 = tcg_temp_new_i64();
2214 TCGv_i64 t3 = tcg_temp_new_i64();
2215
2216 tcg_gen_ext32u_tl(t0, t0);
2217 tcg_gen_ext32u_tl(t1, t1);
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]);
2222 tcg_gen_sub_i64(t2, t3, t2);
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);
2228 tcg_gen_ext32s_tl(cpu_LO[0], t0);
2229 tcg_gen_ext32s_tl(cpu_HI[0], t1);
2230 }
2231 opn = "msubu";
2232 break;
2233 default:
2234 MIPS_INVAL(opn);
2235 generate_exception(ctx, EXCP_RI);
2236 goto out;
2237 }
2238 MIPS_DEBUG("%s %s %s", opn, regnames[rs], regnames[rt]);
2239 out:
2240 tcg_temp_free(t0);
2241 tcg_temp_free(t1);
2242}
2243
2244static void gen_mul_vr54xx (DisasContext *ctx, uint32_t opc,
2245 int rd, int rs, int rt)
2246{
David 'Digit' Turnera2c14f92014-02-04 01:02:30 +01002247 const char* __attribute__((unused)) opn = "mul vr54xx";
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08002248 TCGv t0 = tcg_temp_new();
2249 TCGv t1 = tcg_temp_new();
2250
2251 gen_load_gpr(t0, rs);
2252 gen_load_gpr(t1, rt);
2253
2254 switch (opc) {
2255 case OPC_VR54XX_MULS:
David 'Digit' Turner5c5a6e12014-04-03 15:48:19 +02002256 gen_helper_muls(t0, cpu_env, t0, t1);
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08002257 opn = "muls";
2258 break;
2259 case OPC_VR54XX_MULSU:
David 'Digit' Turner5c5a6e12014-04-03 15:48:19 +02002260 gen_helper_mulsu(t0, cpu_env, t0, t1);
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08002261 opn = "mulsu";
2262 break;
2263 case OPC_VR54XX_MACC:
David 'Digit' Turner5c5a6e12014-04-03 15:48:19 +02002264 gen_helper_macc(t0, cpu_env, t0, t1);
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08002265 opn = "macc";
2266 break;
2267 case OPC_VR54XX_MACCU:
David 'Digit' Turner5c5a6e12014-04-03 15:48:19 +02002268 gen_helper_maccu(t0, cpu_env, t0, t1);
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08002269 opn = "maccu";
2270 break;
2271 case OPC_VR54XX_MSAC:
David 'Digit' Turner5c5a6e12014-04-03 15:48:19 +02002272 gen_helper_msac(t0, cpu_env, t0, t1);
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08002273 opn = "msac";
2274 break;
2275 case OPC_VR54XX_MSACU:
David 'Digit' Turner5c5a6e12014-04-03 15:48:19 +02002276 gen_helper_msacu(t0, cpu_env, t0, t1);
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08002277 opn = "msacu";
2278 break;
2279 case OPC_VR54XX_MULHI:
David 'Digit' Turner5c5a6e12014-04-03 15:48:19 +02002280 gen_helper_mulhi(t0, cpu_env, t0, t1);
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08002281 opn = "mulhi";
2282 break;
2283 case OPC_VR54XX_MULHIU:
David 'Digit' Turner5c5a6e12014-04-03 15:48:19 +02002284 gen_helper_mulhiu(t0, cpu_env, t0, t1);
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08002285 opn = "mulhiu";
2286 break;
2287 case OPC_VR54XX_MULSHI:
David 'Digit' Turner5c5a6e12014-04-03 15:48:19 +02002288 gen_helper_mulshi(t0, cpu_env, t0, t1);
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08002289 opn = "mulshi";
2290 break;
2291 case OPC_VR54XX_MULSHIU:
David 'Digit' Turner5c5a6e12014-04-03 15:48:19 +02002292 gen_helper_mulshiu(t0, cpu_env, t0, t1);
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08002293 opn = "mulshiu";
2294 break;
2295 case OPC_VR54XX_MACCHI:
David 'Digit' Turner5c5a6e12014-04-03 15:48:19 +02002296 gen_helper_macchi(t0, cpu_env, t0, t1);
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08002297 opn = "macchi";
2298 break;
2299 case OPC_VR54XX_MACCHIU:
David 'Digit' Turner5c5a6e12014-04-03 15:48:19 +02002300 gen_helper_macchiu(t0, cpu_env, t0, t1);
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08002301 opn = "macchiu";
2302 break;
2303 case OPC_VR54XX_MSACHI:
David 'Digit' Turner5c5a6e12014-04-03 15:48:19 +02002304 gen_helper_msachi(t0, cpu_env, t0, t1);
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08002305 opn = "msachi";
2306 break;
2307 case OPC_VR54XX_MSACHIU:
David 'Digit' Turner5c5a6e12014-04-03 15:48:19 +02002308 gen_helper_msachiu(t0, cpu_env, t0, t1);
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08002309 opn = "msachiu";
2310 break;
2311 default:
2312 MIPS_INVAL("mul vr54xx");
2313 generate_exception(ctx, EXCP_RI);
2314 goto out;
2315 }
2316 gen_store_gpr(t0, rd);
2317 MIPS_DEBUG("%s %s, %s, %s", opn, regnames[rd], regnames[rs], regnames[rt]);
2318
2319 out:
2320 tcg_temp_free(t0);
2321 tcg_temp_free(t1);
2322}
2323
2324static void gen_cl (DisasContext *ctx, uint32_t opc,
2325 int rd, int rs)
2326{
David 'Digit' Turnera2c14f92014-02-04 01:02:30 +01002327 const char* __attribute__((unused)) opn = "CLx";
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08002328 TCGv t0;
2329
2330 if (rd == 0) {
2331 /* Treat as NOP. */
2332 MIPS_DEBUG("NOP");
2333 return;
2334 }
2335 t0 = tcg_temp_new();
2336 gen_load_gpr(t0, rs);
2337 switch (opc) {
2338 case OPC_CLO:
2339 gen_helper_clo(cpu_gpr[rd], t0);
2340 opn = "clo";
2341 break;
2342 case OPC_CLZ:
2343 gen_helper_clz(cpu_gpr[rd], t0);
2344 opn = "clz";
2345 break;
2346#if defined(TARGET_MIPS64)
2347 case OPC_DCLO:
2348 gen_helper_dclo(cpu_gpr[rd], t0);
2349 opn = "dclo";
2350 break;
2351 case OPC_DCLZ:
2352 gen_helper_dclz(cpu_gpr[rd], t0);
2353 opn = "dclz";
2354 break;
2355#endif
2356 }
2357 MIPS_DEBUG("%s %s, %s", opn, regnames[rd], regnames[rs]);
2358 tcg_temp_free(t0);
2359}
2360
2361/* Traps */
2362static void gen_trap (DisasContext *ctx, uint32_t opc,
2363 int rs, int rt, int16_t imm)
2364{
2365 int cond;
2366 TCGv t0 = tcg_temp_new();
2367 TCGv t1 = tcg_temp_new();
2368
2369 cond = 0;
2370 /* Load needed operands */
2371 switch (opc) {
2372 case OPC_TEQ:
2373 case OPC_TGE:
2374 case OPC_TGEU:
2375 case OPC_TLT:
2376 case OPC_TLTU:
2377 case OPC_TNE:
2378 /* Compare two registers */
2379 if (rs != rt) {
2380 gen_load_gpr(t0, rs);
2381 gen_load_gpr(t1, rt);
2382 cond = 1;
2383 }
2384 break;
2385 case OPC_TEQI:
2386 case OPC_TGEI:
2387 case OPC_TGEIU:
2388 case OPC_TLTI:
2389 case OPC_TLTIU:
2390 case OPC_TNEI:
2391 /* Compare register to immediate */
2392 if (rs != 0 || imm != 0) {
2393 gen_load_gpr(t0, rs);
2394 tcg_gen_movi_tl(t1, (int32_t)imm);
2395 cond = 1;
2396 }
2397 break;
2398 }
2399 if (cond == 0) {
2400 switch (opc) {
2401 case OPC_TEQ: /* rs == rs */
2402 case OPC_TEQI: /* r0 == 0 */
2403 case OPC_TGE: /* rs >= rs */
2404 case OPC_TGEI: /* r0 >= 0 */
2405 case OPC_TGEU: /* rs >= rs unsigned */
2406 case OPC_TGEIU: /* r0 >= 0 unsigned */
2407 /* Always trap */
2408 generate_exception(ctx, EXCP_TRAP);
2409 break;
2410 case OPC_TLT: /* rs < rs */
2411 case OPC_TLTI: /* r0 < 0 */
2412 case OPC_TLTU: /* rs < rs unsigned */
2413 case OPC_TLTIU: /* r0 < 0 unsigned */
2414 case OPC_TNE: /* rs != rs */
2415 case OPC_TNEI: /* r0 != 0 */
2416 /* Never trap: treat as NOP. */
2417 break;
2418 }
2419 } else {
2420 int l1 = gen_new_label();
2421
2422 switch (opc) {
2423 case OPC_TEQ:
2424 case OPC_TEQI:
2425 tcg_gen_brcond_tl(TCG_COND_NE, t0, t1, l1);
2426 break;
2427 case OPC_TGE:
2428 case OPC_TGEI:
2429 tcg_gen_brcond_tl(TCG_COND_LT, t0, t1, l1);
2430 break;
2431 case OPC_TGEU:
2432 case OPC_TGEIU:
2433 tcg_gen_brcond_tl(TCG_COND_LTU, t0, t1, l1);
2434 break;
2435 case OPC_TLT:
2436 case OPC_TLTI:
2437 tcg_gen_brcond_tl(TCG_COND_GE, t0, t1, l1);
2438 break;
2439 case OPC_TLTU:
2440 case OPC_TLTIU:
2441 tcg_gen_brcond_tl(TCG_COND_GEU, t0, t1, l1);
2442 break;
2443 case OPC_TNE:
2444 case OPC_TNEI:
2445 tcg_gen_brcond_tl(TCG_COND_EQ, t0, t1, l1);
2446 break;
2447 }
2448 generate_exception(ctx, EXCP_TRAP);
2449 gen_set_label(l1);
2450 }
2451 tcg_temp_free(t0);
2452 tcg_temp_free(t1);
2453}
2454
2455static inline void gen_goto_tb(DisasContext *ctx, int n, target_ulong dest)
2456{
2457 TranslationBlock *tb;
2458 tb = ctx->tb;
2459 if ((tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK) &&
2460 likely(!ctx->singlestep_enabled)) {
2461 tcg_gen_goto_tb(n);
2462 gen_save_pc(dest);
2463 tcg_gen_exit_tb((long)tb + n);
2464 } else {
2465 gen_save_pc(dest);
2466 if (ctx->singlestep_enabled) {
2467 save_cpu_state(ctx, 0);
David 'Digit' Turner6480c962014-04-03 12:38:04 +02002468 gen_helper_1i(raise_exception, cpu_env, EXCP_DEBUG);
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08002469 }
2470 tcg_gen_exit_tb(0);
2471 }
2472}
2473
2474/* Branches (before delay slot) */
2475static void gen_compute_branch (DisasContext *ctx, uint32_t opc,
2476 int rs, int rt, int32_t offset)
2477{
2478 target_ulong btgt = -1;
2479 int blink = 0;
2480 int bcond_compute = 0;
2481 TCGv t0 = tcg_temp_new();
2482 TCGv t1 = tcg_temp_new();
2483
2484 if (ctx->hflags & MIPS_HFLAG_BMASK) {
2485#ifdef MIPS_DEBUG_DISAS
2486 LOG_DISAS("Branch in delay slot at PC 0x" TARGET_FMT_lx "\n", ctx->pc);
2487#endif
2488 generate_exception(ctx, EXCP_RI);
2489 goto out;
2490 }
2491
2492 /* Load needed operands */
2493 switch (opc) {
2494 case OPC_BEQ:
2495 case OPC_BEQL:
2496 case OPC_BNE:
2497 case OPC_BNEL:
2498 /* Compare two registers */
2499 if (rs != rt) {
2500 gen_load_gpr(t0, rs);
2501 gen_load_gpr(t1, rt);
2502 bcond_compute = 1;
2503 }
2504 btgt = ctx->pc + 4 + offset;
2505 break;
2506 case OPC_BGEZ:
2507 case OPC_BGEZAL:
2508 case OPC_BGEZALL:
2509 case OPC_BGEZL:
2510 case OPC_BGTZ:
2511 case OPC_BGTZL:
2512 case OPC_BLEZ:
2513 case OPC_BLEZL:
2514 case OPC_BLTZ:
2515 case OPC_BLTZAL:
2516 case OPC_BLTZALL:
2517 case OPC_BLTZL:
2518 /* Compare to zero */
2519 if (rs != 0) {
2520 gen_load_gpr(t0, rs);
2521 bcond_compute = 1;
2522 }
2523 btgt = ctx->pc + 4 + offset;
2524 break;
2525 case OPC_J:
2526 case OPC_JAL:
2527 /* Jump to immediate */
2528 btgt = ((ctx->pc + 4) & (int32_t)0xF0000000) | (uint32_t)offset;
2529 break;
2530 case OPC_JR:
2531 case OPC_JALR:
2532 /* Jump to register */
2533 if (offset != 0 && offset != 16) {
2534 /* Hint = 0 is JR/JALR, hint 16 is JR.HB/JALR.HB, the
2535 others are reserved. */
2536 MIPS_INVAL("jump hint");
2537 generate_exception(ctx, EXCP_RI);
2538 goto out;
2539 }
2540 gen_load_gpr(btarget, rs);
2541 break;
2542 default:
2543 MIPS_INVAL("branch/jump");
2544 generate_exception(ctx, EXCP_RI);
2545 goto out;
2546 }
2547 if (bcond_compute == 0) {
2548 /* No condition to be computed */
2549 switch (opc) {
2550 case OPC_BEQ: /* rx == rx */
2551 case OPC_BEQL: /* rx == rx likely */
2552 case OPC_BGEZ: /* 0 >= 0 */
2553 case OPC_BGEZL: /* 0 >= 0 likely */
2554 case OPC_BLEZ: /* 0 <= 0 */
2555 case OPC_BLEZL: /* 0 <= 0 likely */
2556 /* Always take */
2557 ctx->hflags |= MIPS_HFLAG_B;
2558 MIPS_DEBUG("balways");
2559 break;
2560 case OPC_BGEZAL: /* 0 >= 0 */
2561 case OPC_BGEZALL: /* 0 >= 0 likely */
2562 /* Always take and link */
2563 blink = 31;
2564 ctx->hflags |= MIPS_HFLAG_B;
2565 MIPS_DEBUG("balways and link");
2566 break;
2567 case OPC_BNE: /* rx != rx */
2568 case OPC_BGTZ: /* 0 > 0 */
2569 case OPC_BLTZ: /* 0 < 0 */
2570 /* Treat as NOP. */
2571 MIPS_DEBUG("bnever (NOP)");
2572 goto out;
2573 case OPC_BLTZAL: /* 0 < 0 */
2574 tcg_gen_movi_tl(cpu_gpr[31], ctx->pc + 8);
2575 MIPS_DEBUG("bnever and link");
2576 goto out;
2577 case OPC_BLTZALL: /* 0 < 0 likely */
2578 tcg_gen_movi_tl(cpu_gpr[31], ctx->pc + 8);
2579 /* Skip the instruction in the delay slot */
2580 MIPS_DEBUG("bnever, link and skip");
2581 ctx->pc += 4;
2582 goto out;
2583 case OPC_BNEL: /* rx != rx likely */
2584 case OPC_BGTZL: /* 0 > 0 likely */
2585 case OPC_BLTZL: /* 0 < 0 likely */
2586 /* Skip the instruction in the delay slot */
2587 MIPS_DEBUG("bnever and skip");
2588 ctx->pc += 4;
2589 goto out;
2590 case OPC_J:
2591 ctx->hflags |= MIPS_HFLAG_B;
2592 MIPS_DEBUG("j " TARGET_FMT_lx, btgt);
2593 break;
2594 case OPC_JAL:
2595 blink = 31;
2596 ctx->hflags |= MIPS_HFLAG_B;
2597 MIPS_DEBUG("jal " TARGET_FMT_lx, btgt);
2598 break;
2599 case OPC_JR:
2600 ctx->hflags |= MIPS_HFLAG_BR;
2601 MIPS_DEBUG("jr %s", regnames[rs]);
2602 break;
2603 case OPC_JALR:
2604 blink = rt;
2605 ctx->hflags |= MIPS_HFLAG_BR;
2606 MIPS_DEBUG("jalr %s, %s", regnames[rt], regnames[rs]);
2607 break;
2608 default:
2609 MIPS_INVAL("branch/jump");
2610 generate_exception(ctx, EXCP_RI);
2611 goto out;
2612 }
2613 } else {
2614 switch (opc) {
2615 case OPC_BEQ:
2616 gen_op_eq(bcond, t0, t1);
2617 MIPS_DEBUG("beq %s, %s, " TARGET_FMT_lx,
2618 regnames[rs], regnames[rt], btgt);
2619 goto not_likely;
2620 case OPC_BEQL:
2621 gen_op_eq(bcond, t0, t1);
2622 MIPS_DEBUG("beql %s, %s, " TARGET_FMT_lx,
2623 regnames[rs], regnames[rt], btgt);
2624 goto likely;
2625 case OPC_BNE:
2626 gen_op_ne(bcond, t0, t1);
2627 MIPS_DEBUG("bne %s, %s, " TARGET_FMT_lx,
2628 regnames[rs], regnames[rt], btgt);
2629 goto not_likely;
2630 case OPC_BNEL:
2631 gen_op_ne(bcond, t0, t1);
2632 MIPS_DEBUG("bnel %s, %s, " TARGET_FMT_lx,
2633 regnames[rs], regnames[rt], btgt);
2634 goto likely;
2635 case OPC_BGEZ:
2636 gen_op_gez(bcond, t0);
2637 MIPS_DEBUG("bgez %s, " TARGET_FMT_lx, regnames[rs], btgt);
2638 goto not_likely;
2639 case OPC_BGEZL:
2640 gen_op_gez(bcond, t0);
2641 MIPS_DEBUG("bgezl %s, " TARGET_FMT_lx, regnames[rs], btgt);
2642 goto likely;
2643 case OPC_BGEZAL:
2644 gen_op_gez(bcond, t0);
2645 MIPS_DEBUG("bgezal %s, " TARGET_FMT_lx, regnames[rs], btgt);
2646 blink = 31;
2647 goto not_likely;
2648 case OPC_BGEZALL:
2649 gen_op_gez(bcond, t0);
2650 blink = 31;
2651 MIPS_DEBUG("bgezall %s, " TARGET_FMT_lx, regnames[rs], btgt);
2652 goto likely;
2653 case OPC_BGTZ:
2654 gen_op_gtz(bcond, t0);
2655 MIPS_DEBUG("bgtz %s, " TARGET_FMT_lx, regnames[rs], btgt);
2656 goto not_likely;
2657 case OPC_BGTZL:
2658 gen_op_gtz(bcond, t0);
2659 MIPS_DEBUG("bgtzl %s, " TARGET_FMT_lx, regnames[rs], btgt);
2660 goto likely;
2661 case OPC_BLEZ:
2662 gen_op_lez(bcond, t0);
2663 MIPS_DEBUG("blez %s, " TARGET_FMT_lx, regnames[rs], btgt);
2664 goto not_likely;
2665 case OPC_BLEZL:
2666 gen_op_lez(bcond, t0);
2667 MIPS_DEBUG("blezl %s, " TARGET_FMT_lx, regnames[rs], btgt);
2668 goto likely;
2669 case OPC_BLTZ:
2670 gen_op_ltz(bcond, t0);
2671 MIPS_DEBUG("bltz %s, " TARGET_FMT_lx, regnames[rs], btgt);
2672 goto not_likely;
2673 case OPC_BLTZL:
2674 gen_op_ltz(bcond, t0);
2675 MIPS_DEBUG("bltzl %s, " TARGET_FMT_lx, regnames[rs], btgt);
2676 goto likely;
2677 case OPC_BLTZAL:
2678 gen_op_ltz(bcond, t0);
2679 blink = 31;
2680 MIPS_DEBUG("bltzal %s, " TARGET_FMT_lx, regnames[rs], btgt);
2681 not_likely:
2682 ctx->hflags |= MIPS_HFLAG_BC;
2683 break;
2684 case OPC_BLTZALL:
2685 gen_op_ltz(bcond, t0);
2686 blink = 31;
2687 MIPS_DEBUG("bltzall %s, " TARGET_FMT_lx, regnames[rs], btgt);
2688 likely:
2689 ctx->hflags |= MIPS_HFLAG_BL;
2690 break;
2691 default:
2692 MIPS_INVAL("conditional branch/jump");
2693 generate_exception(ctx, EXCP_RI);
2694 goto out;
2695 }
2696 }
2697 MIPS_DEBUG("enter ds: link %d cond %02x target " TARGET_FMT_lx,
2698 blink, ctx->hflags, btgt);
2699
2700 ctx->btarget = btgt;
2701 if (blink > 0) {
2702 tcg_gen_movi_tl(cpu_gpr[blink], ctx->pc + 8);
2703 }
2704
2705 out:
2706 tcg_temp_free(t0);
2707 tcg_temp_free(t1);
2708}
2709
2710/* special3 bitfield operations */
2711static void gen_bitops (DisasContext *ctx, uint32_t opc, int rt,
2712 int rs, int lsb, int msb)
2713{
2714 TCGv t0 = tcg_temp_new();
2715 TCGv t1 = tcg_temp_new();
2716 target_ulong mask;
2717
2718 gen_load_gpr(t1, rs);
2719 switch (opc) {
2720 case OPC_EXT:
2721 if (lsb + msb > 31)
2722 goto fail;
2723 tcg_gen_shri_tl(t0, t1, lsb);
2724 if (msb != 31) {
2725 tcg_gen_andi_tl(t0, t0, (1 << (msb + 1)) - 1);
2726 } else {
2727 tcg_gen_ext32s_tl(t0, t0);
2728 }
2729 break;
2730#if defined(TARGET_MIPS64)
2731 case OPC_DEXTM:
2732 tcg_gen_shri_tl(t0, t1, lsb);
2733 if (msb != 31) {
2734 tcg_gen_andi_tl(t0, t0, (1ULL << (msb + 1 + 32)) - 1);
2735 }
2736 break;
2737 case OPC_DEXTU:
2738 tcg_gen_shri_tl(t0, t1, lsb + 32);
2739 tcg_gen_andi_tl(t0, t0, (1ULL << (msb + 1)) - 1);
2740 break;
2741 case OPC_DEXT:
2742 tcg_gen_shri_tl(t0, t1, lsb);
2743 tcg_gen_andi_tl(t0, t0, (1ULL << (msb + 1)) - 1);
2744 break;
2745#endif
2746 case OPC_INS:
2747 if (lsb > msb)
2748 goto fail;
2749 mask = ((msb - lsb + 1 < 32) ? ((1 << (msb - lsb + 1)) - 1) : ~0) << lsb;
2750 gen_load_gpr(t0, rt);
2751 tcg_gen_andi_tl(t0, t0, ~mask);
2752 tcg_gen_shli_tl(t1, t1, lsb);
2753 tcg_gen_andi_tl(t1, t1, mask);
2754 tcg_gen_or_tl(t0, t0, t1);
2755 tcg_gen_ext32s_tl(t0, t0);
2756 break;
2757#if defined(TARGET_MIPS64)
2758 case OPC_DINSM:
2759 if (lsb > msb)
2760 goto fail;
2761 mask = ((msb - lsb + 1 + 32 < 64) ? ((1ULL << (msb - lsb + 1 + 32)) - 1) : ~0ULL) << lsb;
2762 gen_load_gpr(t0, rt);
2763 tcg_gen_andi_tl(t0, t0, ~mask);
2764 tcg_gen_shli_tl(t1, t1, lsb);
2765 tcg_gen_andi_tl(t1, t1, mask);
2766 tcg_gen_or_tl(t0, t0, t1);
2767 break;
2768 case OPC_DINSU:
2769 if (lsb > msb)
2770 goto fail;
2771 mask = ((1ULL << (msb - lsb + 1)) - 1) << (lsb + 32);
2772 gen_load_gpr(t0, rt);
2773 tcg_gen_andi_tl(t0, t0, ~mask);
2774 tcg_gen_shli_tl(t1, t1, lsb + 32);
2775 tcg_gen_andi_tl(t1, t1, mask);
2776 tcg_gen_or_tl(t0, t0, t1);
2777 break;
2778 case OPC_DINS:
2779 if (lsb > msb)
2780 goto fail;
2781 gen_load_gpr(t0, rt);
2782 mask = ((1ULL << (msb - lsb + 1)) - 1) << lsb;
2783 gen_load_gpr(t0, rt);
2784 tcg_gen_andi_tl(t0, t0, ~mask);
2785 tcg_gen_shli_tl(t1, t1, lsb);
2786 tcg_gen_andi_tl(t1, t1, mask);
2787 tcg_gen_or_tl(t0, t0, t1);
2788 break;
2789#endif
2790 default:
2791fail:
2792 MIPS_INVAL("bitops");
2793 generate_exception(ctx, EXCP_RI);
2794 tcg_temp_free(t0);
2795 tcg_temp_free(t1);
2796 return;
2797 }
2798 gen_store_gpr(t0, rt);
2799 tcg_temp_free(t0);
2800 tcg_temp_free(t1);
2801}
2802
2803static void gen_bshfl (DisasContext *ctx, uint32_t op2, int rt, int rd)
2804{
2805 TCGv t0;
2806
2807 if (rd == 0) {
2808 /* If no destination, treat it as a NOP. */
2809 MIPS_DEBUG("NOP");
2810 return;
2811 }
2812
2813 t0 = tcg_temp_new();
2814 gen_load_gpr(t0, rt);
2815 switch (op2) {
2816 case OPC_WSBH:
2817 {
2818 TCGv t1 = tcg_temp_new();
2819
2820 tcg_gen_shri_tl(t1, t0, 8);
2821 tcg_gen_andi_tl(t1, t1, 0x00FF00FF);
2822 tcg_gen_shli_tl(t0, t0, 8);
2823 tcg_gen_andi_tl(t0, t0, ~0x00FF00FF);
2824 tcg_gen_or_tl(t0, t0, t1);
2825 tcg_temp_free(t1);
2826 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
2827 }
2828 break;
2829 case OPC_SEB:
2830 tcg_gen_ext8s_tl(cpu_gpr[rd], t0);
2831 break;
2832 case OPC_SEH:
2833 tcg_gen_ext16s_tl(cpu_gpr[rd], t0);
2834 break;
2835#if defined(TARGET_MIPS64)
2836 case OPC_DSBH:
2837 {
2838 TCGv t1 = tcg_temp_new();
2839
2840 tcg_gen_shri_tl(t1, t0, 8);
2841 tcg_gen_andi_tl(t1, t1, 0x00FF00FF00FF00FFULL);
2842 tcg_gen_shli_tl(t0, t0, 8);
2843 tcg_gen_andi_tl(t0, t0, ~0x00FF00FF00FF00FFULL);
2844 tcg_gen_or_tl(cpu_gpr[rd], t0, t1);
2845 tcg_temp_free(t1);
2846 }
2847 break;
2848 case OPC_DSHD:
2849 {
2850 TCGv t1 = tcg_temp_new();
2851
2852 tcg_gen_shri_tl(t1, t0, 16);
2853 tcg_gen_andi_tl(t1, t1, 0x0000FFFF0000FFFFULL);
2854 tcg_gen_shli_tl(t0, t0, 16);
2855 tcg_gen_andi_tl(t0, t0, ~0x0000FFFF0000FFFFULL);
2856 tcg_gen_or_tl(t0, t0, t1);
2857 tcg_gen_shri_tl(t1, t0, 32);
2858 tcg_gen_shli_tl(t0, t0, 32);
2859 tcg_gen_or_tl(cpu_gpr[rd], t0, t1);
2860 tcg_temp_free(t1);
2861 }
2862 break;
2863#endif
2864 default:
2865 MIPS_INVAL("bsfhl");
2866 generate_exception(ctx, EXCP_RI);
2867 tcg_temp_free(t0);
2868 return;
2869 }
2870 tcg_temp_free(t0);
2871}
2872
2873#ifndef CONFIG_USER_ONLY
2874/* CP0 (MMU and control) */
2875static inline void gen_mfc0_load32 (TCGv arg, target_ulong off)
2876{
2877 TCGv_i32 t0 = tcg_temp_new_i32();
2878
2879 tcg_gen_ld_i32(t0, cpu_env, off);
2880 tcg_gen_ext_i32_tl(arg, t0);
2881 tcg_temp_free_i32(t0);
2882}
2883
2884static inline void gen_mfc0_load64 (TCGv arg, target_ulong off)
2885{
2886 tcg_gen_ld_tl(arg, cpu_env, off);
2887 tcg_gen_ext32s_tl(arg, arg);
2888}
2889
2890static inline void gen_mtc0_store32 (TCGv arg, target_ulong off)
2891{
2892 TCGv_i32 t0 = tcg_temp_new_i32();
2893
2894 tcg_gen_trunc_tl_i32(t0, arg);
2895 tcg_gen_st_i32(t0, cpu_env, off);
2896 tcg_temp_free_i32(t0);
2897}
2898
2899static inline void gen_mtc0_store64 (TCGv arg, target_ulong off)
2900{
2901 tcg_gen_ext32s_tl(arg, arg);
2902 tcg_gen_st_tl(arg, cpu_env, off);
2903}
2904
David 'Digit' Turnere2678e12014-01-16 15:56:43 +01002905static void gen_mfc0 (CPUMIPSState *env, DisasContext *ctx, TCGv arg, int reg, int sel)
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08002906{
David 'Digit' Turnera2c14f92014-02-04 01:02:30 +01002907 const char * __attribute__((unused)) rn = "invalid";
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08002908
2909 if (sel != 0)
2910 check_insn(env, ctx, ISA_MIPS32);
2911
2912 switch (reg) {
2913 case 0:
2914 switch (sel) {
2915 case 0:
David 'Digit' Turnere2678e12014-01-16 15:56:43 +01002916 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Index));
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08002917 rn = "Index";
2918 break;
2919 case 1:
2920 check_insn(env, ctx, ASE_MT);
David 'Digit' Turner06978cc2014-04-03 15:55:43 +02002921 gen_helper_mfc0_mvpcontrol(arg, cpu_env);
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08002922 rn = "MVPControl";
2923 break;
2924 case 2:
2925 check_insn(env, ctx, ASE_MT);
David 'Digit' Turner06978cc2014-04-03 15:55:43 +02002926 gen_helper_mfc0_mvpconf0(arg, cpu_env);
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08002927 rn = "MVPConf0";
2928 break;
2929 case 3:
2930 check_insn(env, ctx, ASE_MT);
David 'Digit' Turner06978cc2014-04-03 15:55:43 +02002931 gen_helper_mfc0_mvpconf1(arg, cpu_env);
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08002932 rn = "MVPConf1";
2933 break;
2934 default:
2935 goto die;
2936 }
2937 break;
2938 case 1:
2939 switch (sel) {
2940 case 0:
David 'Digit' Turner06978cc2014-04-03 15:55:43 +02002941 gen_helper_mfc0_random(arg, cpu_env);
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08002942 rn = "Random";
2943 break;
2944 case 1:
2945 check_insn(env, ctx, ASE_MT);
David 'Digit' Turnere2678e12014-01-16 15:56:43 +01002946 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEControl));
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08002947 rn = "VPEControl";
2948 break;
2949 case 2:
2950 check_insn(env, ctx, ASE_MT);
David 'Digit' Turnere2678e12014-01-16 15:56:43 +01002951 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf0));
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08002952 rn = "VPEConf0";
2953 break;
2954 case 3:
2955 check_insn(env, ctx, ASE_MT);
David 'Digit' Turnere2678e12014-01-16 15:56:43 +01002956 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf1));
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08002957 rn = "VPEConf1";
2958 break;
2959 case 4:
2960 check_insn(env, ctx, ASE_MT);
David 'Digit' Turnere2678e12014-01-16 15:56:43 +01002961 gen_mfc0_load64(arg, offsetof(CPUMIPSState, CP0_YQMask));
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08002962 rn = "YQMask";
2963 break;
2964 case 5:
2965 check_insn(env, ctx, ASE_MT);
David 'Digit' Turnere2678e12014-01-16 15:56:43 +01002966 gen_mfc0_load64(arg, offsetof(CPUMIPSState, CP0_VPESchedule));
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08002967 rn = "VPESchedule";
2968 break;
2969 case 6:
2970 check_insn(env, ctx, ASE_MT);
David 'Digit' Turnere2678e12014-01-16 15:56:43 +01002971 gen_mfc0_load64(arg, offsetof(CPUMIPSState, CP0_VPEScheFBack));
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08002972 rn = "VPEScheFBack";
2973 break;
2974 case 7:
2975 check_insn(env, ctx, ASE_MT);
David 'Digit' Turnere2678e12014-01-16 15:56:43 +01002976 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEOpt));
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08002977 rn = "VPEOpt";
2978 break;
2979 default:
2980 goto die;
2981 }
2982 break;
2983 case 2:
2984 switch (sel) {
2985 case 0:
David 'Digit' Turnere2678e12014-01-16 15:56:43 +01002986 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryLo0));
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08002987 tcg_gen_ext32s_tl(arg, arg);
2988 rn = "EntryLo0";
2989 break;
2990 case 1:
2991 check_insn(env, ctx, ASE_MT);
David 'Digit' Turner06978cc2014-04-03 15:55:43 +02002992 gen_helper_mfc0_tcstatus(arg, cpu_env);
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08002993 rn = "TCStatus";
2994 break;
2995 case 2:
2996 check_insn(env, ctx, ASE_MT);
David 'Digit' Turner06978cc2014-04-03 15:55:43 +02002997 gen_helper_mfc0_tcbind(arg, cpu_env);
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08002998 rn = "TCBind";
2999 break;
3000 case 3:
3001 check_insn(env, ctx, ASE_MT);
David 'Digit' Turner06978cc2014-04-03 15:55:43 +02003002 gen_helper_mfc0_tcrestart(arg, cpu_env);
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08003003 rn = "TCRestart";
3004 break;
3005 case 4:
3006 check_insn(env, ctx, ASE_MT);
David 'Digit' Turner06978cc2014-04-03 15:55:43 +02003007 gen_helper_mfc0_tchalt(arg, cpu_env);
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08003008 rn = "TCHalt";
3009 break;
3010 case 5:
3011 check_insn(env, ctx, ASE_MT);
David 'Digit' Turner06978cc2014-04-03 15:55:43 +02003012 gen_helper_mfc0_tccontext(arg, cpu_env);
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08003013 rn = "TCContext";
3014 break;
3015 case 6:
3016 check_insn(env, ctx, ASE_MT);
David 'Digit' Turner06978cc2014-04-03 15:55:43 +02003017 gen_helper_mfc0_tcschedule(arg, cpu_env);
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08003018 rn = "TCSchedule";
3019 break;
3020 case 7:
3021 check_insn(env, ctx, ASE_MT);
David 'Digit' Turner06978cc2014-04-03 15:55:43 +02003022 gen_helper_mfc0_tcschefback(arg, cpu_env);
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08003023 rn = "TCScheFBack";
3024 break;
3025 default:
3026 goto die;
3027 }
3028 break;
3029 case 3:
3030 switch (sel) {
3031 case 0:
David 'Digit' Turnere2678e12014-01-16 15:56:43 +01003032 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryLo1));
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08003033 tcg_gen_ext32s_tl(arg, arg);
3034 rn = "EntryLo1";
3035 break;
3036 default:
3037 goto die;
3038 }
3039 break;
3040 case 4:
3041 switch (sel) {
3042 case 0:
David 'Digit' Turnere2678e12014-01-16 15:56:43 +01003043 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_Context));
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08003044 tcg_gen_ext32s_tl(arg, arg);
3045 rn = "Context";
3046 break;
3047 case 1:
3048// gen_helper_mfc0_contextconfig(arg); /* SmartMIPS ASE */
3049 rn = "ContextConfig";
3050// break;
3051 default:
3052 goto die;
3053 }
3054 break;
3055 case 5:
3056 switch (sel) {
3057 case 0:
David 'Digit' Turnere2678e12014-01-16 15:56:43 +01003058 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageMask));
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08003059 rn = "PageMask";
3060 break;
3061 case 1:
3062 check_insn(env, ctx, ISA_MIPS32R2);
David 'Digit' Turnere2678e12014-01-16 15:56:43 +01003063 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageGrain));
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08003064 rn = "PageGrain";
3065 break;
3066 default:
3067 goto die;
3068 }
3069 break;
3070 case 6:
3071 switch (sel) {
3072 case 0:
David 'Digit' Turnere2678e12014-01-16 15:56:43 +01003073 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Wired));
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08003074 rn = "Wired";
3075 break;
3076 case 1:
3077 check_insn(env, ctx, ISA_MIPS32R2);
David 'Digit' Turnere2678e12014-01-16 15:56:43 +01003078 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf0));
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08003079 rn = "SRSConf0";
3080 break;
3081 case 2:
3082 check_insn(env, ctx, ISA_MIPS32R2);
David 'Digit' Turnere2678e12014-01-16 15:56:43 +01003083 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf1));
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08003084 rn = "SRSConf1";
3085 break;
3086 case 3:
3087 check_insn(env, ctx, ISA_MIPS32R2);
David 'Digit' Turnere2678e12014-01-16 15:56:43 +01003088 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf2));
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08003089 rn = "SRSConf2";
3090 break;
3091 case 4:
3092 check_insn(env, ctx, ISA_MIPS32R2);
David 'Digit' Turnere2678e12014-01-16 15:56:43 +01003093 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf3));
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08003094 rn = "SRSConf3";
3095 break;
3096 case 5:
3097 check_insn(env, ctx, ISA_MIPS32R2);
David 'Digit' Turnere2678e12014-01-16 15:56:43 +01003098 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf4));
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08003099 rn = "SRSConf4";
3100 break;
3101 default:
3102 goto die;
3103 }
3104 break;
3105 case 7:
3106 switch (sel) {
3107 case 0:
3108 check_insn(env, ctx, ISA_MIPS32R2);
David 'Digit' Turnere2678e12014-01-16 15:56:43 +01003109 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_HWREna));
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08003110 rn = "HWREna";
3111 break;
3112 default:
3113 goto die;
3114 }
3115 break;
3116 case 8:
3117 switch (sel) {
3118 case 0:
David 'Digit' Turnere2678e12014-01-16 15:56:43 +01003119 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_BadVAddr));
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08003120 tcg_gen_ext32s_tl(arg, arg);
3121 rn = "BadVAddr";
3122 break;
3123 default:
3124 goto die;
3125 }
3126 break;
3127 case 9:
3128 switch (sel) {
3129 case 0:
3130 /* Mark as an IO operation because we read the time. */
3131 if (use_icount)
3132 gen_io_start();
David 'Digit' Turner06978cc2014-04-03 15:55:43 +02003133 gen_helper_mfc0_count(arg, cpu_env);
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08003134 if (use_icount) {
3135 gen_io_end();
3136 ctx->bstate = BS_STOP;
3137 }
3138 rn = "Count";
3139 break;
3140 /* 6,7 are implementation dependent */
3141 default:
3142 goto die;
3143 }
3144 break;
3145 case 10:
3146 switch (sel) {
3147 case 0:
David 'Digit' Turnere2678e12014-01-16 15:56:43 +01003148 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryHi));
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08003149 tcg_gen_ext32s_tl(arg, arg);
3150 rn = "EntryHi";
3151 break;
3152 default:
3153 goto die;
3154 }
3155 break;
3156 case 11:
3157 switch (sel) {
3158 case 0:
David 'Digit' Turnere2678e12014-01-16 15:56:43 +01003159 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Compare));
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08003160 rn = "Compare";
3161 break;
3162 /* 6,7 are implementation dependent */
3163 default:
3164 goto die;
3165 }
3166 break;
3167 case 12:
3168 switch (sel) {
3169 case 0:
David 'Digit' Turnere2678e12014-01-16 15:56:43 +01003170 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Status));
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08003171 rn = "Status";
3172 break;
3173 case 1:
3174 check_insn(env, ctx, ISA_MIPS32R2);
David 'Digit' Turnere2678e12014-01-16 15:56:43 +01003175 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_IntCtl));
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08003176 rn = "IntCtl";
3177 break;
3178 case 2:
3179 check_insn(env, ctx, ISA_MIPS32R2);
David 'Digit' Turnere2678e12014-01-16 15:56:43 +01003180 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSCtl));
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08003181 rn = "SRSCtl";
3182 break;
3183 case 3:
3184 check_insn(env, ctx, ISA_MIPS32R2);
David 'Digit' Turnere2678e12014-01-16 15:56:43 +01003185 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08003186 rn = "SRSMap";
3187 break;
3188 default:
3189 goto die;
3190 }
3191 break;
3192 case 13:
3193 switch (sel) {
3194 case 0:
David 'Digit' Turnere2678e12014-01-16 15:56:43 +01003195 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Cause));
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08003196 rn = "Cause";
3197 break;
3198 default:
3199 goto die;
3200 }
3201 break;
3202 case 14:
3203 switch (sel) {
3204 case 0:
David 'Digit' Turnere2678e12014-01-16 15:56:43 +01003205 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EPC));
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08003206 tcg_gen_ext32s_tl(arg, arg);
3207 rn = "EPC";
3208 break;
3209 default:
3210 goto die;
3211 }
3212 break;
3213 case 15:
3214 switch (sel) {
3215 case 0:
David 'Digit' Turnere2678e12014-01-16 15:56:43 +01003216 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PRid));
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08003217 rn = "PRid";
3218 break;
3219 case 1:
3220 check_insn(env, ctx, ISA_MIPS32R2);
David 'Digit' Turnere2678e12014-01-16 15:56:43 +01003221 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_EBase));
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08003222 rn = "EBase";
3223 break;
3224 default:
3225 goto die;
3226 }
3227 break;
3228 case 16:
3229 switch (sel) {
3230 case 0:
David 'Digit' Turnere2678e12014-01-16 15:56:43 +01003231 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config0));
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08003232 rn = "Config";
3233 break;
3234 case 1:
David 'Digit' Turnere2678e12014-01-16 15:56:43 +01003235 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config1));
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08003236 rn = "Config1";
3237 break;
3238 case 2:
David 'Digit' Turnere2678e12014-01-16 15:56:43 +01003239 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config2));
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08003240 rn = "Config2";
3241 break;
3242 case 3:
David 'Digit' Turnere2678e12014-01-16 15:56:43 +01003243 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config3));
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08003244 rn = "Config3";
3245 break;
3246 /* 4,5 are reserved */
3247 /* 6,7 are implementation dependent */
3248 case 6:
David 'Digit' Turnere2678e12014-01-16 15:56:43 +01003249 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config6));
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08003250 rn = "Config6";
3251 break;
3252 case 7:
David 'Digit' Turnere2678e12014-01-16 15:56:43 +01003253 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config7));
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08003254 rn = "Config7";
3255 break;
3256 default:
3257 goto die;
3258 }
3259 break;
3260 case 17:
3261 switch (sel) {
3262 case 0:
David 'Digit' Turner06978cc2014-04-03 15:55:43 +02003263 gen_helper_mfc0_lladdr(arg, cpu_env);
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08003264 rn = "LLAddr";
3265 break;
3266 default:
3267 goto die;
3268 }
3269 break;
3270 case 18:
3271 switch (sel) {
3272 case 0 ... 7:
David 'Digit' Turner06978cc2014-04-03 15:55:43 +02003273 gen_helper_2i(mfc0_watchlo, arg, cpu_env, sel);
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08003274 rn = "WatchLo";
3275 break;
3276 default:
3277 goto die;
3278 }
3279 break;
3280 case 19:
3281 switch (sel) {
3282 case 0 ...7:
David 'Digit' Turner06978cc2014-04-03 15:55:43 +02003283 gen_helper_2i(mfc0_watchhi, arg, cpu_env, sel);
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08003284 rn = "WatchHi";
3285 break;
3286 default:
3287 goto die;
3288 }
3289 break;
3290 case 20:
3291 switch (sel) {
3292 case 0:
3293#if defined(TARGET_MIPS64)
3294 check_insn(env, ctx, ISA_MIPS3);
David 'Digit' Turnere2678e12014-01-16 15:56:43 +01003295 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_XContext));
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08003296 tcg_gen_ext32s_tl(arg, arg);
3297 rn = "XContext";
3298 break;
3299#endif
3300 default:
3301 goto die;
3302 }
3303 break;
3304 case 21:
3305 /* Officially reserved, but sel 0 is used for R1x000 framemask */
3306 switch (sel) {
3307 case 0:
David 'Digit' Turnere2678e12014-01-16 15:56:43 +01003308 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Framemask));
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08003309 rn = "Framemask";
3310 break;
3311 default:
3312 goto die;
3313 }
3314 break;
3315 case 22:
3316 tcg_gen_movi_tl(arg, 0); /* unimplemented */
3317 rn = "'Diagnostic"; /* implementation dependent */
3318 break;
3319 case 23:
3320 switch (sel) {
3321 case 0:
David 'Digit' Turner06978cc2014-04-03 15:55:43 +02003322 gen_helper_mfc0_debug(arg, cpu_env); /* EJTAG support */
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08003323 rn = "Debug";
3324 break;
3325 case 1:
3326// gen_helper_mfc0_tracecontrol(arg); /* PDtrace support */
3327 rn = "TraceControl";
3328// break;
3329 case 2:
3330// gen_helper_mfc0_tracecontrol2(arg); /* PDtrace support */
3331 rn = "TraceControl2";
3332// break;
3333 case 3:
3334// gen_helper_mfc0_usertracedata(arg); /* PDtrace support */
3335 rn = "UserTraceData";
3336// break;
3337 case 4:
3338// gen_helper_mfc0_tracebpc(arg); /* PDtrace support */
3339 rn = "TraceBPC";
3340// break;
3341 default:
3342 goto die;
3343 }
3344 break;
3345 case 24:
3346 switch (sel) {
3347 case 0:
3348 /* EJTAG support */
David 'Digit' Turnere2678e12014-01-16 15:56:43 +01003349 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_DEPC));
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08003350 tcg_gen_ext32s_tl(arg, arg);
3351 rn = "DEPC";
3352 break;
3353 default:
3354 goto die;
3355 }
3356 break;
3357 case 25:
3358 switch (sel) {
3359 case 0:
David 'Digit' Turnere2678e12014-01-16 15:56:43 +01003360 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Performance0));
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08003361 rn = "Performance0";
3362 break;
3363 case 1:
3364// gen_helper_mfc0_performance1(arg);
3365 rn = "Performance1";
3366// break;
3367 case 2:
3368// gen_helper_mfc0_performance2(arg);
3369 rn = "Performance2";
3370// break;
3371 case 3:
3372// gen_helper_mfc0_performance3(arg);
3373 rn = "Performance3";
3374// break;
3375 case 4:
3376// gen_helper_mfc0_performance4(arg);
3377 rn = "Performance4";
3378// break;
3379 case 5:
3380// gen_helper_mfc0_performance5(arg);
3381 rn = "Performance5";
3382// break;
3383 case 6:
3384// gen_helper_mfc0_performance6(arg);
3385 rn = "Performance6";
3386// break;
3387 case 7:
3388// gen_helper_mfc0_performance7(arg);
3389 rn = "Performance7";
3390// break;
3391 default:
3392 goto die;
3393 }
3394 break;
3395 case 26:
3396 tcg_gen_movi_tl(arg, 0); /* unimplemented */
3397 rn = "ECC";
3398 break;
3399 case 27:
3400 switch (sel) {
3401 case 0 ... 3:
3402 tcg_gen_movi_tl(arg, 0); /* unimplemented */
3403 rn = "CacheErr";
3404 break;
3405 default:
3406 goto die;
3407 }
3408 break;
3409 case 28:
3410 switch (sel) {
3411 case 0:
3412 case 2:
3413 case 4:
3414 case 6:
David 'Digit' Turnere2678e12014-01-16 15:56:43 +01003415 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_TagLo));
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08003416 rn = "TagLo";
3417 break;
3418 case 1:
3419 case 3:
3420 case 5:
3421 case 7:
David 'Digit' Turnere2678e12014-01-16 15:56:43 +01003422 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataLo));
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08003423 rn = "DataLo";
3424 break;
3425 default:
3426 goto die;
3427 }
3428 break;
3429 case 29:
3430 switch (sel) {
3431 case 0:
3432 case 2:
3433 case 4:
3434 case 6:
David 'Digit' Turnere2678e12014-01-16 15:56:43 +01003435 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_TagHi));
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08003436 rn = "TagHi";
3437 break;
3438 case 1:
3439 case 3:
3440 case 5:
3441 case 7:
David 'Digit' Turnere2678e12014-01-16 15:56:43 +01003442 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataHi));
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08003443 rn = "DataHi";
3444 break;
3445 default:
3446 goto die;
3447 }
3448 break;
3449 case 30:
3450 switch (sel) {
3451 case 0:
David 'Digit' Turnere2678e12014-01-16 15:56:43 +01003452 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_ErrorEPC));
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08003453 tcg_gen_ext32s_tl(arg, arg);
3454 rn = "ErrorEPC";
3455 break;
3456 default:
3457 goto die;
3458 }
3459 break;
3460 case 31:
3461 switch (sel) {
3462 case 0:
3463 /* EJTAG support */
David 'Digit' Turnere2678e12014-01-16 15:56:43 +01003464 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08003465 rn = "DESAVE";
3466 break;
3467 default:
3468 goto die;
3469 }
3470 break;
3471 default:
3472 goto die;
3473 }
3474 LOG_DISAS("mfc0 %s (reg %d sel %d)\n", rn, reg, sel);
3475 return;
3476
3477die:
3478 LOG_DISAS("mfc0 %s (reg %d sel %d)\n", rn, reg, sel);
3479 generate_exception(ctx, EXCP_RI);
3480}
3481
David 'Digit' Turnere2678e12014-01-16 15:56:43 +01003482static void gen_mtc0 (CPUMIPSState *env, DisasContext *ctx, TCGv arg, int reg, int sel)
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08003483{
David 'Digit' Turnera2c14f92014-02-04 01:02:30 +01003484 const char * __attribute__((unused)) rn = "invalid";
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08003485
3486 if (sel != 0)
3487 check_insn(env, ctx, ISA_MIPS32);
3488
3489 if (use_icount)
3490 gen_io_start();
3491
3492 switch (reg) {
3493 case 0:
3494 switch (sel) {
3495 case 0:
David 'Digit' Turner06978cc2014-04-03 15:55:43 +02003496 gen_helper_mtc0_index(cpu_env, arg);
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08003497 rn = "Index";
3498 break;
3499 case 1:
3500 check_insn(env, ctx, ASE_MT);
David 'Digit' Turner06978cc2014-04-03 15:55:43 +02003501 gen_helper_mtc0_mvpcontrol(cpu_env, arg);
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08003502 rn = "MVPControl";
3503 break;
3504 case 2:
3505 check_insn(env, ctx, ASE_MT);
3506 /* ignored */
3507 rn = "MVPConf0";
3508 break;
3509 case 3:
3510 check_insn(env, ctx, ASE_MT);
3511 /* ignored */
3512 rn = "MVPConf1";
3513 break;
3514 default:
3515 goto die;
3516 }
3517 break;
3518 case 1:
3519 switch (sel) {
3520 case 0:
3521 /* ignored */
3522 rn = "Random";
3523 break;
3524 case 1:
3525 check_insn(env, ctx, ASE_MT);
David 'Digit' Turner06978cc2014-04-03 15:55:43 +02003526 gen_helper_mtc0_vpecontrol(cpu_env, arg);
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08003527 rn = "VPEControl";
3528 break;
3529 case 2:
3530 check_insn(env, ctx, ASE_MT);
David 'Digit' Turner06978cc2014-04-03 15:55:43 +02003531 gen_helper_mtc0_vpeconf0(cpu_env, arg);
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08003532 rn = "VPEConf0";
3533 break;
3534 case 3:
3535 check_insn(env, ctx, ASE_MT);
David 'Digit' Turner06978cc2014-04-03 15:55:43 +02003536 gen_helper_mtc0_vpeconf1(cpu_env, arg);
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08003537 rn = "VPEConf1";
3538 break;
3539 case 4:
3540 check_insn(env, ctx, ASE_MT);
David 'Digit' Turner06978cc2014-04-03 15:55:43 +02003541 gen_helper_mtc0_yqmask(cpu_env, arg);
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08003542 rn = "YQMask";
3543 break;
3544 case 5:
3545 check_insn(env, ctx, ASE_MT);
David 'Digit' Turnere2678e12014-01-16 15:56:43 +01003546 gen_mtc0_store64(arg, offsetof(CPUMIPSState, CP0_VPESchedule));
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08003547 rn = "VPESchedule";
3548 break;
3549 case 6:
3550 check_insn(env, ctx, ASE_MT);
David 'Digit' Turnere2678e12014-01-16 15:56:43 +01003551 gen_mtc0_store64(arg, offsetof(CPUMIPSState, CP0_VPEScheFBack));
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08003552 rn = "VPEScheFBack";
3553 break;
3554 case 7:
3555 check_insn(env, ctx, ASE_MT);
David 'Digit' Turner06978cc2014-04-03 15:55:43 +02003556 gen_helper_mtc0_vpeopt(cpu_env, arg);
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08003557 rn = "VPEOpt";
3558 break;
3559 default:
3560 goto die;
3561 }
3562 break;
3563 case 2:
3564 switch (sel) {
3565 case 0:
David 'Digit' Turner06978cc2014-04-03 15:55:43 +02003566 gen_helper_mtc0_entrylo0(cpu_env, arg);
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08003567 rn = "EntryLo0";
3568 break;
3569 case 1:
3570 check_insn(env, ctx, ASE_MT);
David 'Digit' Turner06978cc2014-04-03 15:55:43 +02003571 gen_helper_mtc0_tcstatus(cpu_env, arg);
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08003572 rn = "TCStatus";
3573 break;
3574 case 2:
3575 check_insn(env, ctx, ASE_MT);
David 'Digit' Turner06978cc2014-04-03 15:55:43 +02003576 gen_helper_mtc0_tcbind(cpu_env, arg);
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08003577 rn = "TCBind";
3578 break;
3579 case 3:
3580 check_insn(env, ctx, ASE_MT);
David 'Digit' Turner06978cc2014-04-03 15:55:43 +02003581 gen_helper_mtc0_tcrestart(cpu_env, arg);
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08003582 rn = "TCRestart";
3583 break;
3584 case 4:
3585 check_insn(env, ctx, ASE_MT);
David 'Digit' Turner06978cc2014-04-03 15:55:43 +02003586 gen_helper_mtc0_tchalt(cpu_env, arg);
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08003587 rn = "TCHalt";
3588 break;
3589 case 5:
3590 check_insn(env, ctx, ASE_MT);
David 'Digit' Turner06978cc2014-04-03 15:55:43 +02003591 gen_helper_mtc0_tccontext(cpu_env, arg);
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08003592 rn = "TCContext";
3593 break;
3594 case 6:
3595 check_insn(env, ctx, ASE_MT);
David 'Digit' Turner06978cc2014-04-03 15:55:43 +02003596 gen_helper_mtc0_tcschedule(cpu_env, arg);
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08003597 rn = "TCSchedule";
3598 break;
3599 case 7:
3600 check_insn(env, ctx, ASE_MT);
David 'Digit' Turner06978cc2014-04-03 15:55:43 +02003601 gen_helper_mtc0_tcschefback(cpu_env, arg);
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08003602 rn = "TCScheFBack";
3603 break;
3604 default:
3605 goto die;
3606 }
3607 break;
3608 case 3:
3609 switch (sel) {
3610 case 0:
David 'Digit' Turner06978cc2014-04-03 15:55:43 +02003611 gen_helper_mtc0_entrylo1(cpu_env, arg);
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08003612 rn = "EntryLo1";
3613 break;
3614 default:
3615 goto die;
3616 }
3617 break;
3618 case 4:
3619 switch (sel) {
3620 case 0:
David 'Digit' Turner06978cc2014-04-03 15:55:43 +02003621 gen_helper_mtc0_context(cpu_env, arg);
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08003622 rn = "Context";
3623 break;
3624 case 1:
3625// gen_helper_mtc0_contextconfig(arg); /* SmartMIPS ASE */
3626 rn = "ContextConfig";
3627// break;
3628 default:
3629 goto die;
3630 }
3631 break;
3632 case 5:
3633 switch (sel) {
3634 case 0:
David 'Digit' Turner06978cc2014-04-03 15:55:43 +02003635 gen_helper_mtc0_pagemask(cpu_env, arg);
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08003636 rn = "PageMask";
3637 break;
3638 case 1:
3639 check_insn(env, ctx, ISA_MIPS32R2);
David 'Digit' Turner06978cc2014-04-03 15:55:43 +02003640 gen_helper_mtc0_pagegrain(cpu_env, arg);
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08003641 rn = "PageGrain";
3642 break;
3643 default:
3644 goto die;
3645 }
3646 break;
3647 case 6:
3648 switch (sel) {
3649 case 0:
David 'Digit' Turner06978cc2014-04-03 15:55:43 +02003650 gen_helper_mtc0_wired(cpu_env, arg);
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08003651 rn = "Wired";
3652 break;
3653 case 1:
3654 check_insn(env, ctx, ISA_MIPS32R2);
David 'Digit' Turner06978cc2014-04-03 15:55:43 +02003655 gen_helper_mtc0_srsconf0(cpu_env, arg);
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08003656 rn = "SRSConf0";
3657 break;
3658 case 2:
3659 check_insn(env, ctx, ISA_MIPS32R2);
David 'Digit' Turner06978cc2014-04-03 15:55:43 +02003660 gen_helper_mtc0_srsconf1(cpu_env, arg);
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08003661 rn = "SRSConf1";
3662 break;
3663 case 3:
3664 check_insn(env, ctx, ISA_MIPS32R2);
David 'Digit' Turner06978cc2014-04-03 15:55:43 +02003665 gen_helper_mtc0_srsconf2(cpu_env, arg);
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08003666 rn = "SRSConf2";
3667 break;
3668 case 4:
3669 check_insn(env, ctx, ISA_MIPS32R2);
David 'Digit' Turner06978cc2014-04-03 15:55:43 +02003670 gen_helper_mtc0_srsconf3(cpu_env, arg);
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08003671 rn = "SRSConf3";
3672 break;
3673 case 5:
3674 check_insn(env, ctx, ISA_MIPS32R2);
David 'Digit' Turner06978cc2014-04-03 15:55:43 +02003675 gen_helper_mtc0_srsconf4(cpu_env, arg);
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08003676 rn = "SRSConf4";
3677 break;
3678 default:
3679 goto die;
3680 }
3681 break;
3682 case 7:
3683 switch (sel) {
3684 case 0:
3685 check_insn(env, ctx, ISA_MIPS32R2);
David 'Digit' Turner06978cc2014-04-03 15:55:43 +02003686 gen_helper_mtc0_hwrena(cpu_env, arg);
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08003687 rn = "HWREna";
3688 break;
3689 default:
3690 goto die;
3691 }
3692 break;
3693 case 8:
3694 /* ignored */
3695 rn = "BadVAddr";
3696 break;
3697 case 9:
3698 switch (sel) {
3699 case 0:
David 'Digit' Turner06978cc2014-04-03 15:55:43 +02003700 gen_helper_mtc0_count(cpu_env, arg);
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08003701 rn = "Count";
3702 break;
3703 /* 6,7 are implementation dependent */
3704 default:
3705 goto die;
3706 }
3707 break;
3708 case 10:
3709 switch (sel) {
3710 case 0:
David 'Digit' Turner06978cc2014-04-03 15:55:43 +02003711 gen_helper_mtc0_entryhi(cpu_env, arg);
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08003712 rn = "EntryHi";
3713 break;
3714 default:
3715 goto die;
3716 }
3717 break;
3718 case 11:
3719 switch (sel) {
3720 case 0:
David 'Digit' Turner06978cc2014-04-03 15:55:43 +02003721 gen_helper_mtc0_compare(cpu_env, arg);
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08003722 rn = "Compare";
3723 break;
3724 /* 6,7 are implementation dependent */
3725 default:
3726 goto die;
3727 }
3728 break;
3729 case 12:
3730 switch (sel) {
3731 case 0:
3732 save_cpu_state(ctx, 1);
David 'Digit' Turner06978cc2014-04-03 15:55:43 +02003733 gen_helper_mtc0_status(cpu_env, arg);
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08003734 /* BS_STOP isn't good enough here, hflags may have changed. */
3735 gen_save_pc(ctx->pc + 4);
3736 ctx->bstate = BS_EXCP;
3737 rn = "Status";
3738 break;
3739 case 1:
3740 check_insn(env, ctx, ISA_MIPS32R2);
David 'Digit' Turner06978cc2014-04-03 15:55:43 +02003741 gen_helper_mtc0_intctl(cpu_env, arg);
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08003742 /* Stop translation as we may have switched the execution mode */
3743 ctx->bstate = BS_STOP;
3744 rn = "IntCtl";
3745 break;
3746 case 2:
3747 check_insn(env, ctx, ISA_MIPS32R2);
David 'Digit' Turner06978cc2014-04-03 15:55:43 +02003748 gen_helper_mtc0_srsctl(cpu_env, arg);
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08003749 /* Stop translation as we may have switched the execution mode */
3750 ctx->bstate = BS_STOP;
3751 rn = "SRSCtl";
3752 break;
3753 case 3:
3754 check_insn(env, ctx, ISA_MIPS32R2);
David 'Digit' Turnere2678e12014-01-16 15:56:43 +01003755 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08003756 /* Stop translation as we may have switched the execution mode */
3757 ctx->bstate = BS_STOP;
3758 rn = "SRSMap";
3759 break;
3760 default:
3761 goto die;
3762 }
3763 break;
3764 case 13:
3765 switch (sel) {
3766 case 0:
3767 save_cpu_state(ctx, 1);
David 'Digit' Turner06978cc2014-04-03 15:55:43 +02003768 gen_helper_mtc0_cause(cpu_env, arg);
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08003769 rn = "Cause";
3770 break;
3771 default:
3772 goto die;
3773 }
3774 break;
3775 case 14:
3776 switch (sel) {
3777 case 0:
David 'Digit' Turnere2678e12014-01-16 15:56:43 +01003778 gen_mtc0_store64(arg, offsetof(CPUMIPSState, CP0_EPC));
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08003779 rn = "EPC";
3780 break;
3781 default:
3782 goto die;
3783 }
3784 break;
3785 case 15:
3786 switch (sel) {
3787 case 0:
3788 /* ignored */
3789 rn = "PRid";
3790 break;
3791 case 1:
3792 check_insn(env, ctx, ISA_MIPS32R2);
David 'Digit' Turner06978cc2014-04-03 15:55:43 +02003793 gen_helper_mtc0_ebase(cpu_env, arg);
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08003794 rn = "EBase";
3795 break;
3796 default:
3797 goto die;
3798 }
3799 break;
3800 case 16:
3801 switch (sel) {
3802 case 0:
David 'Digit' Turner06978cc2014-04-03 15:55:43 +02003803 gen_helper_mtc0_config0(cpu_env, arg);
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08003804 rn = "Config";
3805 /* Stop translation as we may have switched the execution mode */
3806 ctx->bstate = BS_STOP;
3807 break;
3808 case 1:
3809 /* ignored, read only */
3810 rn = "Config1";
3811 break;
3812 case 2:
David 'Digit' Turner06978cc2014-04-03 15:55:43 +02003813 gen_helper_mtc0_config2(cpu_env, arg);
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08003814 rn = "Config2";
3815 /* Stop translation as we may have switched the execution mode */
3816 ctx->bstate = BS_STOP;
3817 break;
3818 case 3:
3819 /* ignored, read only */
3820 rn = "Config3";
3821 break;
3822 /* 4,5 are reserved */
3823 /* 6,7 are implementation dependent */
3824 case 6:
3825 /* ignored */
3826 rn = "Config6";
3827 break;
3828 case 7:
3829 /* ignored */
3830 rn = "Config7";
3831 break;
3832 default:
3833 rn = "Invalid config selector";
3834 goto die;
3835 }
3836 break;
3837 case 17:
3838 switch (sel) {
3839 case 0:
David 'Digit' Turner06978cc2014-04-03 15:55:43 +02003840 gen_helper_mtc0_lladdr(cpu_env, arg);
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08003841 rn = "LLAddr";
3842 break;
3843 default:
3844 goto die;
3845 }
3846 break;
3847 case 18:
3848 switch (sel) {
3849 case 0 ... 7:
David 'Digit' Turner06978cc2014-04-03 15:55:43 +02003850 gen_helper_2i(mtc0_watchlo, cpu_env, arg, sel);
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08003851 rn = "WatchLo";
3852 break;
3853 default:
3854 goto die;
3855 }
3856 break;
3857 case 19:
3858 switch (sel) {
3859 case 0 ... 7:
David 'Digit' Turner06978cc2014-04-03 15:55:43 +02003860 gen_helper_2i(mtc0_watchhi, cpu_env, arg, sel);
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08003861 rn = "WatchHi";
3862 break;
3863 default:
3864 goto die;
3865 }
3866 break;
3867 case 20:
3868 switch (sel) {
3869 case 0:
3870#if defined(TARGET_MIPS64)
3871 check_insn(env, ctx, ISA_MIPS3);
David 'Digit' Turner06978cc2014-04-03 15:55:43 +02003872 gen_helper_mtc0_xcontext(cpu_env, arg);
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08003873 rn = "XContext";
3874 break;
3875#endif
3876 default:
3877 goto die;
3878 }
3879 break;
3880 case 21:
3881 /* Officially reserved, but sel 0 is used for R1x000 framemask */
3882 switch (sel) {
3883 case 0:
David 'Digit' Turner06978cc2014-04-03 15:55:43 +02003884 gen_helper_mtc0_framemask(cpu_env, arg);
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08003885 rn = "Framemask";
3886 break;
3887 default:
3888 goto die;
3889 }
3890 break;
3891 case 22:
3892 /* ignored */
3893 rn = "Diagnostic"; /* implementation dependent */
3894 break;
3895 case 23:
3896 switch (sel) {
3897 case 0:
David 'Digit' Turner06978cc2014-04-03 15:55:43 +02003898 gen_helper_mtc0_debug(cpu_env, arg); /* EJTAG support */
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08003899 /* BS_STOP isn't good enough here, hflags may have changed. */
3900 gen_save_pc(ctx->pc + 4);
3901 ctx->bstate = BS_EXCP;
3902 rn = "Debug";
3903 break;
3904 case 1:
3905// gen_helper_mtc0_tracecontrol(arg); /* PDtrace support */
3906 rn = "TraceControl";
3907 /* Stop translation as we may have switched the execution mode */
3908 ctx->bstate = BS_STOP;
3909// break;
3910 case 2:
3911// gen_helper_mtc0_tracecontrol2(arg); /* PDtrace support */
3912 rn = "TraceControl2";
3913 /* Stop translation as we may have switched the execution mode */
3914 ctx->bstate = BS_STOP;
3915// break;
3916 case 3:
3917 /* Stop translation as we may have switched the execution mode */
3918 ctx->bstate = BS_STOP;
3919// gen_helper_mtc0_usertracedata(arg); /* PDtrace support */
3920 rn = "UserTraceData";
3921 /* Stop translation as we may have switched the execution mode */
3922 ctx->bstate = BS_STOP;
3923// break;
3924 case 4:
3925// gen_helper_mtc0_tracebpc(arg); /* PDtrace support */
3926 /* Stop translation as we may have switched the execution mode */
3927 ctx->bstate = BS_STOP;
3928 rn = "TraceBPC";
3929// break;
3930 default:
3931 goto die;
3932 }
3933 break;
3934 case 24:
3935 switch (sel) {
3936 case 0:
3937 /* EJTAG support */
David 'Digit' Turnere2678e12014-01-16 15:56:43 +01003938 gen_mtc0_store64(arg, offsetof(CPUMIPSState, CP0_DEPC));
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08003939 rn = "DEPC";
3940 break;
3941 default:
3942 goto die;
3943 }
3944 break;
3945 case 25:
3946 switch (sel) {
3947 case 0:
David 'Digit' Turner06978cc2014-04-03 15:55:43 +02003948 gen_helper_mtc0_performance0(cpu_env, arg);
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08003949 rn = "Performance0";
3950 break;
3951 case 1:
David 'Digit' Turner06978cc2014-04-03 15:55:43 +02003952// gen_helper_mtc0_performance1(cpu_env, arg);
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08003953 rn = "Performance1";
3954// break;
3955 case 2:
David 'Digit' Turner06978cc2014-04-03 15:55:43 +02003956// gen_helper_mtc0_performance2(cpu_env, arg);
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08003957 rn = "Performance2";
3958// break;
3959 case 3:
David 'Digit' Turner06978cc2014-04-03 15:55:43 +02003960// gen_helper_mtc0_performance3(cpu_env, arg);
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08003961 rn = "Performance3";
3962// break;
3963 case 4:
David 'Digit' Turner06978cc2014-04-03 15:55:43 +02003964// gen_helper_mtc0_performance4(cpu_env, arg);
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08003965 rn = "Performance4";
3966// break;
3967 case 5:
David 'Digit' Turner06978cc2014-04-03 15:55:43 +02003968// gen_helper_mtc0_performance5(cpu_env, arg);
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08003969 rn = "Performance5";
3970// break;
3971 case 6:
David 'Digit' Turner06978cc2014-04-03 15:55:43 +02003972// gen_helper_mtc0_performance6(cpu_env, arg);
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08003973 rn = "Performance6";
3974// break;
3975 case 7:
David 'Digit' Turner06978cc2014-04-03 15:55:43 +02003976// gen_helper_mtc0_performance7(cpu_env, arg);
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08003977 rn = "Performance7";
3978// break;
3979 default:
3980 goto die;
3981 }
3982 break;
3983 case 26:
3984 /* ignored */
3985 rn = "ECC";
3986 break;
3987 case 27:
3988 switch (sel) {
3989 case 0 ... 3:
3990 /* ignored */
3991 rn = "CacheErr";
3992 break;
3993 default:
3994 goto die;
3995 }
3996 break;
3997 case 28:
3998 switch (sel) {
3999 case 0:
4000 case 2:
4001 case 4:
4002 case 6:
David 'Digit' Turner06978cc2014-04-03 15:55:43 +02004003 gen_helper_mtc0_taglo(cpu_env, arg);
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08004004 rn = "TagLo";
4005 break;
4006 case 1:
4007 case 3:
4008 case 5:
4009 case 7:
David 'Digit' Turner06978cc2014-04-03 15:55:43 +02004010 gen_helper_mtc0_datalo(cpu_env, arg);
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08004011 rn = "DataLo";
4012 break;
4013 default:
4014 goto die;
4015 }
4016 break;
4017 case 29:
4018 switch (sel) {
4019 case 0:
4020 case 2:
4021 case 4:
4022 case 6:
David 'Digit' Turner06978cc2014-04-03 15:55:43 +02004023 gen_helper_mtc0_taghi(cpu_env, arg);
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08004024 rn = "TagHi";
4025 break;
4026 case 1:
4027 case 3:
4028 case 5:
4029 case 7:
David 'Digit' Turner06978cc2014-04-03 15:55:43 +02004030 gen_helper_mtc0_datahi(cpu_env, arg);
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08004031 rn = "DataHi";
4032 break;
4033 default:
4034 rn = "invalid sel";
4035 goto die;
4036 }
4037 break;
4038 case 30:
4039 switch (sel) {
4040 case 0:
David 'Digit' Turnere2678e12014-01-16 15:56:43 +01004041 gen_mtc0_store64(arg, offsetof(CPUMIPSState, CP0_ErrorEPC));
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08004042 rn = "ErrorEPC";
4043 break;
4044 default:
4045 goto die;
4046 }
4047 break;
4048 case 31:
4049 switch (sel) {
4050 case 0:
4051 /* EJTAG support */
David 'Digit' Turnere2678e12014-01-16 15:56:43 +01004052 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08004053 rn = "DESAVE";
4054 break;
4055 default:
4056 goto die;
4057 }
4058 /* Stop translation as we may have switched the execution mode */
4059 ctx->bstate = BS_STOP;
4060 break;
4061 default:
4062 goto die;
4063 }
4064 LOG_DISAS("mtc0 %s (reg %d sel %d)\n", rn, reg, sel);
4065 /* For simplicity assume that all writes can cause interrupts. */
4066 if (use_icount) {
4067 gen_io_end();
4068 ctx->bstate = BS_STOP;
4069 }
4070 return;
4071
4072die:
4073 LOG_DISAS("mtc0 %s (reg %d sel %d)\n", rn, reg, sel);
4074 generate_exception(ctx, EXCP_RI);
4075}
4076
4077#if defined(TARGET_MIPS64)
David 'Digit' Turnere2678e12014-01-16 15:56:43 +01004078static void gen_dmfc0 (CPUMIPSState *env, DisasContext *ctx, TCGv arg, int reg, int sel)
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08004079{
4080 const char *rn = "invalid";
4081
4082 if (sel != 0)
4083 check_insn(env, ctx, ISA_MIPS64);
4084
4085 switch (reg) {
4086 case 0:
4087 switch (sel) {
4088 case 0:
David 'Digit' Turnere2678e12014-01-16 15:56:43 +01004089 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Index));
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08004090 rn = "Index";
4091 break;
4092 case 1:
4093 check_insn(env, ctx, ASE_MT);
4094 gen_helper_mfc0_mvpcontrol(arg);
4095 rn = "MVPControl";
4096 break;
4097 case 2:
4098 check_insn(env, ctx, ASE_MT);
4099 gen_helper_mfc0_mvpconf0(arg);
4100 rn = "MVPConf0";
4101 break;
4102 case 3:
4103 check_insn(env, ctx, ASE_MT);
4104 gen_helper_mfc0_mvpconf1(arg);
4105 rn = "MVPConf1";
4106 break;
4107 default:
4108 goto die;
4109 }
4110 break;
4111 case 1:
4112 switch (sel) {
4113 case 0:
4114 gen_helper_mfc0_random(arg);
4115 rn = "Random";
4116 break;
4117 case 1:
4118 check_insn(env, ctx, ASE_MT);
David 'Digit' Turnere2678e12014-01-16 15:56:43 +01004119 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEControl));
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08004120 rn = "VPEControl";
4121 break;
4122 case 2:
4123 check_insn(env, ctx, ASE_MT);
David 'Digit' Turnere2678e12014-01-16 15:56:43 +01004124 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf0));
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08004125 rn = "VPEConf0";
4126 break;
4127 case 3:
4128 check_insn(env, ctx, ASE_MT);
David 'Digit' Turnere2678e12014-01-16 15:56:43 +01004129 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf1));
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08004130 rn = "VPEConf1";
4131 break;
4132 case 4:
4133 check_insn(env, ctx, ASE_MT);
David 'Digit' Turnere2678e12014-01-16 15:56:43 +01004134 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_YQMask));
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08004135 rn = "YQMask";
4136 break;
4137 case 5:
4138 check_insn(env, ctx, ASE_MT);
David 'Digit' Turnere2678e12014-01-16 15:56:43 +01004139 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_VPESchedule));
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08004140 rn = "VPESchedule";
4141 break;
4142 case 6:
4143 check_insn(env, ctx, ASE_MT);
David 'Digit' Turnere2678e12014-01-16 15:56:43 +01004144 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_VPEScheFBack));
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08004145 rn = "VPEScheFBack";
4146 break;
4147 case 7:
4148 check_insn(env, ctx, ASE_MT);
David 'Digit' Turnere2678e12014-01-16 15:56:43 +01004149 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEOpt));
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08004150 rn = "VPEOpt";
4151 break;
4152 default:
4153 goto die;
4154 }
4155 break;
4156 case 2:
4157 switch (sel) {
4158 case 0:
David 'Digit' Turnere2678e12014-01-16 15:56:43 +01004159 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryLo0));
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08004160 rn = "EntryLo0";
4161 break;
4162 case 1:
4163 check_insn(env, ctx, ASE_MT);
4164 gen_helper_mfc0_tcstatus(arg);
4165 rn = "TCStatus";
4166 break;
4167 case 2:
4168 check_insn(env, ctx, ASE_MT);
4169 gen_helper_mfc0_tcbind(arg);
4170 rn = "TCBind";
4171 break;
4172 case 3:
4173 check_insn(env, ctx, ASE_MT);
David 'Digit' Turner06978cc2014-04-03 15:55:43 +02004174 gen_helper_dmfc0_tcrestart(arg, cpu_env);
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08004175 rn = "TCRestart";
4176 break;
4177 case 4:
4178 check_insn(env, ctx, ASE_MT);
David 'Digit' Turner06978cc2014-04-03 15:55:43 +02004179 gen_helper_dmfc0_tchalt(arg, cpu_env);
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08004180 rn = "TCHalt";
4181 break;
4182 case 5:
4183 check_insn(env, ctx, ASE_MT);
David 'Digit' Turner06978cc2014-04-03 15:55:43 +02004184 gen_helper_dmfc0_tccontext(arg, cpu_env);
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08004185 rn = "TCContext";
4186 break;
4187 case 6:
4188 check_insn(env, ctx, ASE_MT);
David 'Digit' Turner06978cc2014-04-03 15:55:43 +02004189 gen_helper_dmfc0_tcschedule(arg, cpu_env);
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08004190 rn = "TCSchedule";
4191 break;
4192 case 7:
4193 check_insn(env, ctx, ASE_MT);
David 'Digit' Turner06978cc2014-04-03 15:55:43 +02004194 gen_helper_dmfc0_tcschefback(arg, cpu_env);
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08004195 rn = "TCScheFBack";
4196 break;
4197 default:
4198 goto die;
4199 }
4200 break;
4201 case 3:
4202 switch (sel) {
4203 case 0:
David 'Digit' Turnere2678e12014-01-16 15:56:43 +01004204 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryLo1));
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08004205 rn = "EntryLo1";
4206 break;
4207 default:
4208 goto die;
4209 }
4210 break;
4211 case 4:
4212 switch (sel) {
4213 case 0:
David 'Digit' Turnere2678e12014-01-16 15:56:43 +01004214 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_Context));
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08004215 rn = "Context";
4216 break;
4217 case 1:
4218// gen_helper_dmfc0_contextconfig(arg); /* SmartMIPS ASE */
4219 rn = "ContextConfig";
4220// break;
4221 default:
4222 goto die;
4223 }
4224 break;
4225 case 5:
4226 switch (sel) {
4227 case 0:
David 'Digit' Turnere2678e12014-01-16 15:56:43 +01004228 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageMask));
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08004229 rn = "PageMask";
4230 break;
4231 case 1:
4232 check_insn(env, ctx, ISA_MIPS32R2);
David 'Digit' Turnere2678e12014-01-16 15:56:43 +01004233 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageGrain));
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08004234 rn = "PageGrain";
4235 break;
4236 default:
4237 goto die;
4238 }
4239 break;
4240 case 6:
4241 switch (sel) {
4242 case 0:
David 'Digit' Turnere2678e12014-01-16 15:56:43 +01004243 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Wired));
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08004244 rn = "Wired";
4245 break;
4246 case 1:
4247 check_insn(env, ctx, ISA_MIPS32R2);
David 'Digit' Turnere2678e12014-01-16 15:56:43 +01004248 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf0));
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08004249 rn = "SRSConf0";
4250 break;
4251 case 2:
4252 check_insn(env, ctx, ISA_MIPS32R2);
David 'Digit' Turnere2678e12014-01-16 15:56:43 +01004253 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf1));
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08004254 rn = "SRSConf1";
4255 break;
4256 case 3:
4257 check_insn(env, ctx, ISA_MIPS32R2);
David 'Digit' Turnere2678e12014-01-16 15:56:43 +01004258 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf2));
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08004259 rn = "SRSConf2";
4260 break;
4261 case 4:
4262 check_insn(env, ctx, ISA_MIPS32R2);
David 'Digit' Turnere2678e12014-01-16 15:56:43 +01004263 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf3));
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08004264 rn = "SRSConf3";
4265 break;
4266 case 5:
4267 check_insn(env, ctx, ISA_MIPS32R2);
David 'Digit' Turnere2678e12014-01-16 15:56:43 +01004268 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf4));
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08004269 rn = "SRSConf4";
4270 break;
4271 default:
4272 goto die;
4273 }
4274 break;
4275 case 7:
4276 switch (sel) {
4277 case 0:
4278 check_insn(env, ctx, ISA_MIPS32R2);
David 'Digit' Turnere2678e12014-01-16 15:56:43 +01004279 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_HWREna));
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08004280 rn = "HWREna";
4281 break;
4282 default:
4283 goto die;
4284 }
4285 break;
4286 case 8:
4287 switch (sel) {
4288 case 0:
David 'Digit' Turnere2678e12014-01-16 15:56:43 +01004289 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_BadVAddr));
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08004290 rn = "BadVAddr";
4291 break;
4292 default:
4293 goto die;
4294 }
4295 break;
4296 case 9:
4297 switch (sel) {
4298 case 0:
4299 /* Mark as an IO operation because we read the time. */
4300 if (use_icount)
4301 gen_io_start();
4302 gen_helper_mfc0_count(arg);
4303 if (use_icount) {
4304 gen_io_end();
4305 ctx->bstate = BS_STOP;
4306 }
4307 rn = "Count";
4308 break;
4309 /* 6,7 are implementation dependent */
4310 default:
4311 goto die;
4312 }
4313 break;
4314 case 10:
4315 switch (sel) {
4316 case 0:
David 'Digit' Turnere2678e12014-01-16 15:56:43 +01004317 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryHi));
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08004318 rn = "EntryHi";
4319 break;
4320 default:
4321 goto die;
4322 }
4323 break;
4324 case 11:
4325 switch (sel) {
4326 case 0:
David 'Digit' Turnere2678e12014-01-16 15:56:43 +01004327 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Compare));
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08004328 rn = "Compare";
4329 break;
4330 /* 6,7 are implementation dependent */
4331 default:
4332 goto die;
4333 }
4334 break;
4335 case 12:
4336 switch (sel) {
4337 case 0:
David 'Digit' Turnere2678e12014-01-16 15:56:43 +01004338 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Status));
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08004339 rn = "Status";
4340 break;
4341 case 1:
4342 check_insn(env, ctx, ISA_MIPS32R2);
David 'Digit' Turnere2678e12014-01-16 15:56:43 +01004343 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_IntCtl));
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08004344 rn = "IntCtl";
4345 break;
4346 case 2:
4347 check_insn(env, ctx, ISA_MIPS32R2);
David 'Digit' Turnere2678e12014-01-16 15:56:43 +01004348 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSCtl));
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08004349 rn = "SRSCtl";
4350 break;
4351 case 3:
4352 check_insn(env, ctx, ISA_MIPS32R2);
David 'Digit' Turnere2678e12014-01-16 15:56:43 +01004353 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08004354 rn = "SRSMap";
4355 break;
4356 default:
4357 goto die;
4358 }
4359 break;
4360 case 13:
4361 switch (sel) {
4362 case 0:
David 'Digit' Turnere2678e12014-01-16 15:56:43 +01004363 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Cause));
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08004364 rn = "Cause";
4365 break;
4366 default:
4367 goto die;
4368 }
4369 break;
4370 case 14:
4371 switch (sel) {
4372 case 0:
David 'Digit' Turnere2678e12014-01-16 15:56:43 +01004373 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EPC));
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08004374 rn = "EPC";
4375 break;
4376 default:
4377 goto die;
4378 }
4379 break;
4380 case 15:
4381 switch (sel) {
4382 case 0:
David 'Digit' Turnere2678e12014-01-16 15:56:43 +01004383 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PRid));
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08004384 rn = "PRid";
4385 break;
4386 case 1:
4387 check_insn(env, ctx, ISA_MIPS32R2);
David 'Digit' Turnere2678e12014-01-16 15:56:43 +01004388 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_EBase));
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08004389 rn = "EBase";
4390 break;
4391 default:
4392 goto die;
4393 }
4394 break;
4395 case 16:
4396 switch (sel) {
4397 case 0:
David 'Digit' Turnere2678e12014-01-16 15:56:43 +01004398 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config0));
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08004399 rn = "Config";
4400 break;
4401 case 1:
David 'Digit' Turnere2678e12014-01-16 15:56:43 +01004402 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config1));
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08004403 rn = "Config1";
4404 break;
4405 case 2:
David 'Digit' Turnere2678e12014-01-16 15:56:43 +01004406 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config2));
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08004407 rn = "Config2";
4408 break;
4409 case 3:
David 'Digit' Turnere2678e12014-01-16 15:56:43 +01004410 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config3));
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08004411 rn = "Config3";
4412 break;
4413 /* 6,7 are implementation dependent */
4414 case 6:
David 'Digit' Turnere2678e12014-01-16 15:56:43 +01004415 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config6));
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08004416 rn = "Config6";
4417 break;
4418 case 7:
David 'Digit' Turnere2678e12014-01-16 15:56:43 +01004419 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config7));
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08004420 rn = "Config7";
4421 break;
4422 default:
4423 goto die;
4424 }
4425 break;
4426 case 17:
4427 switch (sel) {
4428 case 0:
David 'Digit' Turner06978cc2014-04-03 15:55:43 +02004429 gen_helper_dmfc0_lladdr(arg, cpu_env);
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08004430 rn = "LLAddr";
4431 break;
4432 default:
4433 goto die;
4434 }
4435 break;
4436 case 18:
4437 switch (sel) {
4438 case 0 ... 7:
4439 gen_helper_1i(dmfc0_watchlo, arg, sel);
4440 rn = "WatchLo";
4441 break;
4442 default:
4443 goto die;
4444 }
4445 break;
4446 case 19:
4447 switch (sel) {
4448 case 0 ... 7:
4449 gen_helper_1i(mfc0_watchhi, arg, sel);
4450 rn = "WatchHi";
4451 break;
4452 default:
4453 goto die;
4454 }
4455 break;
4456 case 20:
4457 switch (sel) {
4458 case 0:
4459 check_insn(env, ctx, ISA_MIPS3);
David 'Digit' Turnere2678e12014-01-16 15:56:43 +01004460 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_XContext));
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08004461 rn = "XContext";
4462 break;
4463 default:
4464 goto die;
4465 }
4466 break;
4467 case 21:
4468 /* Officially reserved, but sel 0 is used for R1x000 framemask */
4469 switch (sel) {
4470 case 0:
David 'Digit' Turnere2678e12014-01-16 15:56:43 +01004471 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Framemask));
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08004472 rn = "Framemask";
4473 break;
4474 default:
4475 goto die;
4476 }
4477 break;
4478 case 22:
4479 tcg_gen_movi_tl(arg, 0); /* unimplemented */
4480 rn = "'Diagnostic"; /* implementation dependent */
4481 break;
4482 case 23:
4483 switch (sel) {
4484 case 0:
David 'Digit' Turner06978cc2014-04-03 15:55:43 +02004485 gen_helper_mfc0_debug(arg, cpu_env); /* EJTAG support */
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08004486 rn = "Debug";
4487 break;
4488 case 1:
4489// gen_helper_dmfc0_tracecontrol(arg); /* PDtrace support */
4490 rn = "TraceControl";
4491// break;
4492 case 2:
4493// gen_helper_dmfc0_tracecontrol2(arg); /* PDtrace support */
4494 rn = "TraceControl2";
4495// break;
4496 case 3:
4497// gen_helper_dmfc0_usertracedata(arg); /* PDtrace support */
4498 rn = "UserTraceData";
4499// break;
4500 case 4:
4501// gen_helper_dmfc0_tracebpc(arg); /* PDtrace support */
4502 rn = "TraceBPC";
4503// break;
4504 default:
4505 goto die;
4506 }
4507 break;
4508 case 24:
4509 switch (sel) {
4510 case 0:
4511 /* EJTAG support */
David 'Digit' Turnere2678e12014-01-16 15:56:43 +01004512 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_DEPC));
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08004513 rn = "DEPC";
4514 break;
4515 default:
4516 goto die;
4517 }
4518 break;
4519 case 25:
4520 switch (sel) {
4521 case 0:
David 'Digit' Turnere2678e12014-01-16 15:56:43 +01004522 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Performance0));
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08004523 rn = "Performance0";
4524 break;
4525 case 1:
4526// gen_helper_dmfc0_performance1(arg);
4527 rn = "Performance1";
4528// break;
4529 case 2:
4530// gen_helper_dmfc0_performance2(arg);
4531 rn = "Performance2";
4532// break;
4533 case 3:
4534// gen_helper_dmfc0_performance3(arg);
4535 rn = "Performance3";
4536// break;
4537 case 4:
4538// gen_helper_dmfc0_performance4(arg);
4539 rn = "Performance4";
4540// break;
4541 case 5:
4542// gen_helper_dmfc0_performance5(arg);
4543 rn = "Performance5";
4544// break;
4545 case 6:
4546// gen_helper_dmfc0_performance6(arg);
4547 rn = "Performance6";
4548// break;
4549 case 7:
4550// gen_helper_dmfc0_performance7(arg);
4551 rn = "Performance7";
4552// break;
4553 default:
4554 goto die;
4555 }
4556 break;
4557 case 26:
4558 tcg_gen_movi_tl(arg, 0); /* unimplemented */
4559 rn = "ECC";
4560 break;
4561 case 27:
4562 switch (sel) {
4563 /* ignored */
4564 case 0 ... 3:
4565 tcg_gen_movi_tl(arg, 0); /* unimplemented */
4566 rn = "CacheErr";
4567 break;
4568 default:
4569 goto die;
4570 }
4571 break;
4572 case 28:
4573 switch (sel) {
4574 case 0:
4575 case 2:
4576 case 4:
4577 case 6:
David 'Digit' Turnere2678e12014-01-16 15:56:43 +01004578 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_TagLo));
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08004579 rn = "TagLo";
4580 break;
4581 case 1:
4582 case 3:
4583 case 5:
4584 case 7:
David 'Digit' Turnere2678e12014-01-16 15:56:43 +01004585 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataLo));
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08004586 rn = "DataLo";
4587 break;
4588 default:
4589 goto die;
4590 }
4591 break;
4592 case 29:
4593 switch (sel) {
4594 case 0:
4595 case 2:
4596 case 4:
4597 case 6:
David 'Digit' Turnere2678e12014-01-16 15:56:43 +01004598 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_TagHi));
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08004599 rn = "TagHi";
4600 break;
4601 case 1:
4602 case 3:
4603 case 5:
4604 case 7:
David 'Digit' Turnere2678e12014-01-16 15:56:43 +01004605 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataHi));
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08004606 rn = "DataHi";
4607 break;
4608 default:
4609 goto die;
4610 }
4611 break;
4612 case 30:
4613 switch (sel) {
4614 case 0:
David 'Digit' Turnere2678e12014-01-16 15:56:43 +01004615 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_ErrorEPC));
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08004616 rn = "ErrorEPC";
4617 break;
4618 default:
4619 goto die;
4620 }
4621 break;
4622 case 31:
4623 switch (sel) {
4624 case 0:
4625 /* EJTAG support */
David 'Digit' Turnere2678e12014-01-16 15:56:43 +01004626 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08004627 rn = "DESAVE";
4628 break;
4629 default:
4630 goto die;
4631 }
4632 break;
4633 default:
4634 goto die;
4635 }
4636 LOG_DISAS("dmfc0 %s (reg %d sel %d)\n", rn, reg, sel);
4637 return;
4638
4639die:
4640 LOG_DISAS("dmfc0 %s (reg %d sel %d)\n", rn, reg, sel);
4641 generate_exception(ctx, EXCP_RI);
4642}
4643
David 'Digit' Turnere2678e12014-01-16 15:56:43 +01004644static void gen_dmtc0 (CPUMIPSState *env, DisasContext *ctx, TCGv arg, int reg, int sel)
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08004645{
4646 const char *rn = "invalid";
4647
4648 if (sel != 0)
4649 check_insn(env, ctx, ISA_MIPS64);
4650
4651 if (use_icount)
4652 gen_io_start();
4653
4654 switch (reg) {
4655 case 0:
4656 switch (sel) {
4657 case 0:
David 'Digit' Turner06978cc2014-04-03 15:55:43 +02004658 gen_helper_mtc0_index(cpu_env, arg);
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08004659 rn = "Index";
4660 break;
4661 case 1:
4662 check_insn(env, ctx, ASE_MT);
David 'Digit' Turner06978cc2014-04-03 15:55:43 +02004663 gen_helper_mtc0_mvpcontrol(cpu_env, arg);
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08004664 rn = "MVPControl";
4665 break;
4666 case 2:
4667 check_insn(env, ctx, ASE_MT);
4668 /* ignored */
4669 rn = "MVPConf0";
4670 break;
4671 case 3:
4672 check_insn(env, ctx, ASE_MT);
4673 /* ignored */
4674 rn = "MVPConf1";
4675 break;
4676 default:
4677 goto die;
4678 }
4679 break;
4680 case 1:
4681 switch (sel) {
4682 case 0:
4683 /* ignored */
4684 rn = "Random";
4685 break;
4686 case 1:
4687 check_insn(env, ctx, ASE_MT);
David 'Digit' Turner06978cc2014-04-03 15:55:43 +02004688 gen_helper_mtc0_vpecontrol(cpu_env, arg);
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08004689 rn = "VPEControl";
4690 break;
4691 case 2:
4692 check_insn(env, ctx, ASE_MT);
David 'Digit' Turner06978cc2014-04-03 15:55:43 +02004693 gen_helper_mtc0_vpeconf0(cpu_env, arg);
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08004694 rn = "VPEConf0";
4695 break;
4696 case 3:
4697 check_insn(env, ctx, ASE_MT);
David 'Digit' Turner06978cc2014-04-03 15:55:43 +02004698 gen_helper_mtc0_vpeconf1(cpu_env, arg);
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08004699 rn = "VPEConf1";
4700 break;
4701 case 4:
4702 check_insn(env, ctx, ASE_MT);
David 'Digit' Turner06978cc2014-04-03 15:55:43 +02004703 gen_helper_mtc0_yqmask(cpu_env, arg);
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08004704 rn = "YQMask";
4705 break;
4706 case 5:
4707 check_insn(env, ctx, ASE_MT);
David 'Digit' Turnere2678e12014-01-16 15:56:43 +01004708 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_VPESchedule));
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08004709 rn = "VPESchedule";
4710 break;
4711 case 6:
4712 check_insn(env, ctx, ASE_MT);
David 'Digit' Turnere2678e12014-01-16 15:56:43 +01004713 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_VPEScheFBack));
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08004714 rn = "VPEScheFBack";
4715 break;
4716 case 7:
4717 check_insn(env, ctx, ASE_MT);
David 'Digit' Turner06978cc2014-04-03 15:55:43 +02004718 gen_helper_mtc0_vpeopt(cpu_env, arg);
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08004719 rn = "VPEOpt";
4720 break;
4721 default:
4722 goto die;
4723 }
4724 break;
4725 case 2:
4726 switch (sel) {
4727 case 0:
David 'Digit' Turner06978cc2014-04-03 15:55:43 +02004728 gen_helper_mtc0_entrylo0(cpu_env, arg);
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08004729 rn = "EntryLo0";
4730 break;
4731 case 1:
4732 check_insn(env, ctx, ASE_MT);
David 'Digit' Turner06978cc2014-04-03 15:55:43 +02004733 gen_helper_mtc0_tcstatus(cpu_env, arg);
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08004734 rn = "TCStatus";
4735 break;
4736 case 2:
4737 check_insn(env, ctx, ASE_MT);
David 'Digit' Turner06978cc2014-04-03 15:55:43 +02004738 gen_helper_mtc0_tcbind(cpu_env, arg);
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08004739 rn = "TCBind";
4740 break;
4741 case 3:
4742 check_insn(env, ctx, ASE_MT);
David 'Digit' Turner06978cc2014-04-03 15:55:43 +02004743 gen_helper_mtc0_tcrestart(cpu_env, arg);
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08004744 rn = "TCRestart";
4745 break;
4746 case 4:
4747 check_insn(env, ctx, ASE_MT);
David 'Digit' Turner06978cc2014-04-03 15:55:43 +02004748 gen_helper_mtc0_tchalt(cpu_env, arg);
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08004749 rn = "TCHalt";
4750 break;
4751 case 5:
4752 check_insn(env, ctx, ASE_MT);
David 'Digit' Turner06978cc2014-04-03 15:55:43 +02004753 gen_helper_mtc0_tccontext(cpu_env, arg);
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08004754 rn = "TCContext";
4755 break;
4756 case 6:
4757 check_insn(env, ctx, ASE_MT);
David 'Digit' Turner06978cc2014-04-03 15:55:43 +02004758 gen_helper_mtc0_tcschedule(cpu_env, arg);
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08004759 rn = "TCSchedule";
4760 break;
4761 case 7:
4762 check_insn(env, ctx, ASE_MT);
David 'Digit' Turner06978cc2014-04-03 15:55:43 +02004763 gen_helper_mtc0_tcschefback(cpu_env, arg);
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08004764 rn = "TCScheFBack";
4765 break;
4766 default:
4767 goto die;
4768 }
4769 break;
4770 case 3:
4771 switch (sel) {
4772 case 0:
David 'Digit' Turner06978cc2014-04-03 15:55:43 +02004773 gen_helper_mtc0_entrylo1(cpu_env, arg);
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08004774 rn = "EntryLo1";
4775 break;
4776 default:
4777 goto die;
4778 }
4779 break;
4780 case 4:
4781 switch (sel) {
4782 case 0:
David 'Digit' Turner06978cc2014-04-03 15:55:43 +02004783 gen_helper_mtc0_context(cpu_env, arg);
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08004784 rn = "Context";
4785 break;
4786 case 1:
4787// gen_helper_mtc0_contextconfig(arg); /* SmartMIPS ASE */
4788 rn = "ContextConfig";
4789// break;
4790 default:
4791 goto die;
4792 }
4793 break;
4794 case 5:
4795 switch (sel) {
4796 case 0:
David 'Digit' Turner06978cc2014-04-03 15:55:43 +02004797 gen_helper_mtc0_pagemask(cpu_env, arg);
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08004798 rn = "PageMask";
4799 break;
4800 case 1:
4801 check_insn(env, ctx, ISA_MIPS32R2);
David 'Digit' Turner06978cc2014-04-03 15:55:43 +02004802 gen_helper_mtc0_pagegrain(cpu_env, arg);
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08004803 rn = "PageGrain";
4804 break;
4805 default:
4806 goto die;
4807 }
4808 break;
4809 case 6:
4810 switch (sel) {
4811 case 0:
David 'Digit' Turner06978cc2014-04-03 15:55:43 +02004812 gen_helper_mtc0_wired(cpu_env, arg);
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08004813 rn = "Wired";
4814 break;
4815 case 1:
4816 check_insn(env, ctx, ISA_MIPS32R2);
David 'Digit' Turner06978cc2014-04-03 15:55:43 +02004817 gen_helper_mtc0_srsconf0(cpu_env, arg);
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08004818 rn = "SRSConf0";
4819 break;
4820 case 2:
4821 check_insn(env, ctx, ISA_MIPS32R2);
David 'Digit' Turner06978cc2014-04-03 15:55:43 +02004822 gen_helper_mtc0_srsconf1(cpu_env, arg);
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08004823 rn = "SRSConf1";
4824 break;
4825 case 3:
4826 check_insn(env, ctx, ISA_MIPS32R2);
David 'Digit' Turner06978cc2014-04-03 15:55:43 +02004827 gen_helper_mtc0_srsconf2(cpu_env, arg);
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08004828 rn = "SRSConf2";
4829 break;
4830 case 4:
4831 check_insn(env, ctx, ISA_MIPS32R2);
David 'Digit' Turner06978cc2014-04-03 15:55:43 +02004832 gen_helper_mtc0_srsconf3(cpu_env, arg);
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08004833 rn = "SRSConf3";
4834 break;
4835 case 5:
4836 check_insn(env, ctx, ISA_MIPS32R2);
David 'Digit' Turner06978cc2014-04-03 15:55:43 +02004837 gen_helper_mtc0_srsconf4(cpu_env, arg);
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08004838 rn = "SRSConf4";
4839 break;
4840 default:
4841 goto die;
4842 }
4843 break;
4844 case 7:
4845 switch (sel) {
4846 case 0:
4847 check_insn(env, ctx, ISA_MIPS32R2);
David 'Digit' Turner06978cc2014-04-03 15:55:43 +02004848 gen_helper_mtc0_hwrena(cpu_env, arg);
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08004849 rn = "HWREna";
4850 break;
4851 default:
4852 goto die;
4853 }
4854 break;
4855 case 8:
4856 /* ignored */
4857 rn = "BadVAddr";
4858 break;
4859 case 9:
4860 switch (sel) {
4861 case 0:
David 'Digit' Turner06978cc2014-04-03 15:55:43 +02004862 gen_helper_mtc0_count(cpu_env, arg);
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08004863 rn = "Count";
4864 break;
4865 /* 6,7 are implementation dependent */
4866 default:
4867 goto die;
4868 }
4869 /* Stop translation as we may have switched the execution mode */
4870 ctx->bstate = BS_STOP;
4871 break;
4872 case 10:
4873 switch (sel) {
4874 case 0:
David 'Digit' Turner06978cc2014-04-03 15:55:43 +02004875 gen_helper_mtc0_entryhi(cpu_env, arg);
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08004876 rn = "EntryHi";
4877 break;
4878 default:
4879 goto die;
4880 }
4881 break;
4882 case 11:
4883 switch (sel) {
4884 case 0:
David 'Digit' Turner06978cc2014-04-03 15:55:43 +02004885 gen_helper_mtc0_compare(cpu_env, arg);
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08004886 rn = "Compare";
4887 break;
4888 /* 6,7 are implementation dependent */
4889 default:
4890 goto die;
4891 }
4892 /* Stop translation as we may have switched the execution mode */
4893 ctx->bstate = BS_STOP;
4894 break;
4895 case 12:
4896 switch (sel) {
4897 case 0:
4898 save_cpu_state(ctx, 1);
David 'Digit' Turner06978cc2014-04-03 15:55:43 +02004899 gen_helper_mtc0_status(cpu_env, arg);
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08004900 /* BS_STOP isn't good enough here, hflags may have changed. */
4901 gen_save_pc(ctx->pc + 4);
4902 ctx->bstate = BS_EXCP;
4903 rn = "Status";
4904 break;
4905 case 1:
4906 check_insn(env, ctx, ISA_MIPS32R2);
David 'Digit' Turner06978cc2014-04-03 15:55:43 +02004907 gen_helper_mtc0_intctl(cpu_env, arg);
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08004908 /* Stop translation as we may have switched the execution mode */
4909 ctx->bstate = BS_STOP;
4910 rn = "IntCtl";
4911 break;
4912 case 2:
4913 check_insn(env, ctx, ISA_MIPS32R2);
David 'Digit' Turner06978cc2014-04-03 15:55:43 +02004914 gen_helper_mtc0_srsctl(cpu_env, arg);
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08004915 /* Stop translation as we may have switched the execution mode */
4916 ctx->bstate = BS_STOP;
4917 rn = "SRSCtl";
4918 break;
4919 case 3:
4920 check_insn(env, ctx, ISA_MIPS32R2);
David 'Digit' Turnere2678e12014-01-16 15:56:43 +01004921 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08004922 /* Stop translation as we may have switched the execution mode */
4923 ctx->bstate = BS_STOP;
4924 rn = "SRSMap";
4925 break;
4926 default:
4927 goto die;
4928 }
4929 break;
4930 case 13:
4931 switch (sel) {
4932 case 0:
4933 save_cpu_state(ctx, 1);
David 'Digit' Turner06978cc2014-04-03 15:55:43 +02004934 gen_helper_mtc0_cause(cpu_env, arg);
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08004935 rn = "Cause";
4936 break;
4937 default:
4938 goto die;
4939 }
4940 break;
4941 case 14:
4942 switch (sel) {
4943 case 0:
David 'Digit' Turnere2678e12014-01-16 15:56:43 +01004944 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EPC));
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08004945 rn = "EPC";
4946 break;
4947 default:
4948 goto die;
4949 }
4950 break;
4951 case 15:
4952 switch (sel) {
4953 case 0:
4954 /* ignored */
4955 rn = "PRid";
4956 break;
4957 case 1:
4958 check_insn(env, ctx, ISA_MIPS32R2);
David 'Digit' Turner06978cc2014-04-03 15:55:43 +02004959 gen_helper_mtc0_ebase(cpu_env, arg);
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08004960 rn = "EBase";
4961 break;
4962 default:
4963 goto die;
4964 }
4965 break;
4966 case 16:
4967 switch (sel) {
4968 case 0:
David 'Digit' Turner06978cc2014-04-03 15:55:43 +02004969 gen_helper_mtc0_config0(cpu_env, arg);
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08004970 rn = "Config";
4971 /* Stop translation as we may have switched the execution mode */
4972 ctx->bstate = BS_STOP;
4973 break;
4974 case 1:
4975 /* ignored, read only */
4976 rn = "Config1";
4977 break;
4978 case 2:
David 'Digit' Turner06978cc2014-04-03 15:55:43 +02004979 gen_helper_mtc0_config2(cpu_env, arg);
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08004980 rn = "Config2";
4981 /* Stop translation as we may have switched the execution mode */
4982 ctx->bstate = BS_STOP;
4983 break;
4984 case 3:
4985 /* ignored */
4986 rn = "Config3";
4987 break;
4988 /* 6,7 are implementation dependent */
4989 default:
4990 rn = "Invalid config selector";
4991 goto die;
4992 }
4993 break;
4994 case 17:
4995 switch (sel) {
4996 case 0:
David 'Digit' Turner06978cc2014-04-03 15:55:43 +02004997 gen_helper_mtc0_lladdr(cpu_env, arg);
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08004998 rn = "LLAddr";
4999 break;
5000 default:
5001 goto die;
5002 }
5003 break;
5004 case 18:
5005 switch (sel) {
5006 case 0 ... 7:
David 'Digit' Turner06978cc2014-04-03 15:55:43 +02005007 gen_helper_2i(mtc0_watchlo, cpu_env, arg, sel);
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08005008 rn = "WatchLo";
5009 break;
5010 default:
5011 goto die;
5012 }
5013 break;
5014 case 19:
5015 switch (sel) {
5016 case 0 ... 7:
David 'Digit' Turner06978cc2014-04-03 15:55:43 +02005017 gen_helper_2i(mtc0_watchhi, cpu_env, arg, sel);
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08005018 rn = "WatchHi";
5019 break;
5020 default:
5021 goto die;
5022 }
5023 break;
5024 case 20:
5025 switch (sel) {
5026 case 0:
5027 check_insn(env, ctx, ISA_MIPS3);
David 'Digit' Turner06978cc2014-04-03 15:55:43 +02005028 gen_helper_mtc0_xcontext(cpu_env, arg);
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08005029 rn = "XContext";
5030 break;
5031 default:
5032 goto die;
5033 }
5034 break;
5035 case 21:
5036 /* Officially reserved, but sel 0 is used for R1x000 framemask */
5037 switch (sel) {
5038 case 0:
David 'Digit' Turner06978cc2014-04-03 15:55:43 +02005039 gen_helper_mtc0_framemask(cpu_env, arg);
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08005040 rn = "Framemask";
5041 break;
5042 default:
5043 goto die;
5044 }
5045 break;
5046 case 22:
5047 /* ignored */
5048 rn = "Diagnostic"; /* implementation dependent */
5049 break;
5050 case 23:
5051 switch (sel) {
5052 case 0:
David 'Digit' Turner06978cc2014-04-03 15:55:43 +02005053 gen_helper_mtc0_debug(cpu_env, arg); /* EJTAG support */
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08005054 /* BS_STOP isn't good enough here, hflags may have changed. */
5055 gen_save_pc(ctx->pc + 4);
5056 ctx->bstate = BS_EXCP;
5057 rn = "Debug";
5058 break;
5059 case 1:
5060// gen_helper_mtc0_tracecontrol(arg); /* PDtrace support */
5061 /* Stop translation as we may have switched the execution mode */
5062 ctx->bstate = BS_STOP;
5063 rn = "TraceControl";
5064// break;
5065 case 2:
5066// gen_helper_mtc0_tracecontrol2(arg); /* PDtrace support */
5067 /* Stop translation as we may have switched the execution mode */
5068 ctx->bstate = BS_STOP;
5069 rn = "TraceControl2";
5070// break;
5071 case 3:
5072// gen_helper_mtc0_usertracedata(arg); /* PDtrace support */
5073 /* Stop translation as we may have switched the execution mode */
5074 ctx->bstate = BS_STOP;
5075 rn = "UserTraceData";
5076// break;
5077 case 4:
5078// gen_helper_mtc0_tracebpc(arg); /* PDtrace support */
5079 /* Stop translation as we may have switched the execution mode */
5080 ctx->bstate = BS_STOP;
5081 rn = "TraceBPC";
5082// break;
5083 default:
5084 goto die;
5085 }
5086 break;
5087 case 24:
5088 switch (sel) {
5089 case 0:
5090 /* EJTAG support */
David 'Digit' Turnere2678e12014-01-16 15:56:43 +01005091 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_DEPC));
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08005092 rn = "DEPC";
5093 break;
5094 default:
5095 goto die;
5096 }
5097 break;
5098 case 25:
5099 switch (sel) {
5100 case 0:
David 'Digit' Turner06978cc2014-04-03 15:55:43 +02005101 gen_helper_mtc0_performance0(cpu_env, arg);
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08005102 rn = "Performance0";
5103 break;
5104 case 1:
David 'Digit' Turner06978cc2014-04-03 15:55:43 +02005105// gen_helper_mtc0_performance1(cpu_env, arg);
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08005106 rn = "Performance1";
5107// break;
5108 case 2:
David 'Digit' Turner06978cc2014-04-03 15:55:43 +02005109// gen_helper_mtc0_performance2(cpu_env, arg);
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08005110 rn = "Performance2";
5111// break;
5112 case 3:
David 'Digit' Turner06978cc2014-04-03 15:55:43 +02005113// gen_helper_mtc0_performance3(cpu_env, arg);
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08005114 rn = "Performance3";
5115// break;
5116 case 4:
David 'Digit' Turner06978cc2014-04-03 15:55:43 +02005117// gen_helper_mtc0_performance4(cpu_env, arg);
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08005118 rn = "Performance4";
5119// break;
5120 case 5:
David 'Digit' Turner06978cc2014-04-03 15:55:43 +02005121// gen_helper_mtc0_performance5(cpu_env, arg);
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08005122 rn = "Performance5";
5123// break;
5124 case 6:
David 'Digit' Turner06978cc2014-04-03 15:55:43 +02005125// gen_helper_mtc0_performance6(cpu_env, arg);
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08005126 rn = "Performance6";
5127// break;
5128 case 7:
David 'Digit' Turner06978cc2014-04-03 15:55:43 +02005129// gen_helper_mtc0_performance7(cpu_env, arg);
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08005130 rn = "Performance7";
5131// break;
5132 default:
5133 goto die;
5134 }
5135 break;
5136 case 26:
5137 /* ignored */
5138 rn = "ECC";
5139 break;
5140 case 27:
5141 switch (sel) {
5142 case 0 ... 3:
5143 /* ignored */
5144 rn = "CacheErr";
5145 break;
5146 default:
5147 goto die;
5148 }
5149 break;
5150 case 28:
5151 switch (sel) {
5152 case 0:
5153 case 2:
5154 case 4:
5155 case 6:
David 'Digit' Turner06978cc2014-04-03 15:55:43 +02005156 gen_helper_mtc0_taglo(cpu_env, arg);
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08005157 rn = "TagLo";
5158 break;
5159 case 1:
5160 case 3:
5161 case 5:
5162 case 7:
David 'Digit' Turner06978cc2014-04-03 15:55:43 +02005163 gen_helper_mtc0_datalo(cpu_env, arg);
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08005164 rn = "DataLo";
5165 break;
5166 default:
5167 goto die;
5168 }
5169 break;
5170 case 29:
5171 switch (sel) {
5172 case 0:
5173 case 2:
5174 case 4:
5175 case 6:
David 'Digit' Turner06978cc2014-04-03 15:55:43 +02005176 gen_helper_mtc0_taghi(cpu_env, arg);
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08005177 rn = "TagHi";
5178 break;
5179 case 1:
5180 case 3:
5181 case 5:
5182 case 7:
David 'Digit' Turner06978cc2014-04-03 15:55:43 +02005183 gen_helper_mtc0_datahi(cpu_env, arg);
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08005184 rn = "DataHi";
5185 break;
5186 default:
5187 rn = "invalid sel";
5188 goto die;
5189 }
5190 break;
5191 case 30:
5192 switch (sel) {
5193 case 0:
David 'Digit' Turnere2678e12014-01-16 15:56:43 +01005194 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_ErrorEPC));
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08005195 rn = "ErrorEPC";
5196 break;
5197 default:
5198 goto die;
5199 }
5200 break;
5201 case 31:
5202 switch (sel) {
5203 case 0:
5204 /* EJTAG support */
David 'Digit' Turnere2678e12014-01-16 15:56:43 +01005205 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08005206 rn = "DESAVE";
5207 break;
5208 default:
5209 goto die;
5210 }
5211 /* Stop translation as we may have switched the execution mode */
5212 ctx->bstate = BS_STOP;
5213 break;
5214 default:
5215 goto die;
5216 }
5217 LOG_DISAS("dmtc0 %s (reg %d sel %d)\n", rn, reg, sel);
5218 /* For simplicity assume that all writes can cause interrupts. */
5219 if (use_icount) {
5220 gen_io_end();
5221 ctx->bstate = BS_STOP;
5222 }
5223 return;
5224
5225die:
5226 LOG_DISAS("dmtc0 %s (reg %d sel %d)\n", rn, reg, sel);
5227 generate_exception(ctx, EXCP_RI);
5228}
5229#endif /* TARGET_MIPS64 */
5230
David 'Digit' Turnere2678e12014-01-16 15:56:43 +01005231static void gen_mftr(CPUMIPSState *env, DisasContext *ctx, int rt, int rd,
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08005232 int u, int sel, int h)
5233{
5234 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
5235 TCGv t0 = tcg_temp_local_new();
5236
5237 if ((env->CP0_VPEConf0 & (1 << CP0VPEC0_MVP)) == 0 &&
5238 ((env->tcs[other_tc].CP0_TCBind & (0xf << CP0TCBd_CurVPE)) !=
5239 (env->active_tc.CP0_TCBind & (0xf << CP0TCBd_CurVPE))))
5240 tcg_gen_movi_tl(t0, -1);
5241 else if ((env->CP0_VPEControl & (0xff << CP0VPECo_TargTC)) >
5242 (env->mvp->CP0_MVPConf0 & (0xff << CP0MVPC0_PTC)))
5243 tcg_gen_movi_tl(t0, -1);
5244 else if (u == 0) {
5245 switch (rt) {
5246 case 2:
5247 switch (sel) {
5248 case 1:
David 'Digit' Turner06978cc2014-04-03 15:55:43 +02005249 gen_helper_mftc0_tcstatus(t0, cpu_env);
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08005250 break;
5251 case 2:
David 'Digit' Turner06978cc2014-04-03 15:55:43 +02005252 gen_helper_mftc0_tcbind(t0, cpu_env);
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08005253 break;
5254 case 3:
David 'Digit' Turner06978cc2014-04-03 15:55:43 +02005255 gen_helper_mftc0_tcrestart(t0, cpu_env);
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08005256 break;
5257 case 4:
David 'Digit' Turner06978cc2014-04-03 15:55:43 +02005258 gen_helper_mftc0_tchalt(t0, cpu_env);
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08005259 break;
5260 case 5:
David 'Digit' Turner06978cc2014-04-03 15:55:43 +02005261 gen_helper_mftc0_tccontext(t0, cpu_env);
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08005262 break;
5263 case 6:
David 'Digit' Turner06978cc2014-04-03 15:55:43 +02005264 gen_helper_mftc0_tcschedule(t0, cpu_env);
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08005265 break;
5266 case 7:
David 'Digit' Turner06978cc2014-04-03 15:55:43 +02005267 gen_helper_mftc0_tcschefback(t0, cpu_env);
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08005268 break;
5269 default:
5270 gen_mfc0(env, ctx, t0, rt, sel);
5271 break;
5272 }
5273 break;
5274 case 10:
5275 switch (sel) {
5276 case 0:
David 'Digit' Turner06978cc2014-04-03 15:55:43 +02005277 gen_helper_mftc0_entryhi(t0, cpu_env);
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08005278 break;
5279 default:
5280 gen_mfc0(env, ctx, t0, rt, sel);
5281 break;
5282 }
5283 case 12:
5284 switch (sel) {
5285 case 0:
David 'Digit' Turner06978cc2014-04-03 15:55:43 +02005286 gen_helper_mftc0_status(t0, cpu_env);
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08005287 break;
5288 default:
5289 gen_mfc0(env, ctx, t0, rt, sel);
5290 break;
5291 }
5292 case 23:
5293 switch (sel) {
5294 case 0:
David 'Digit' Turner06978cc2014-04-03 15:55:43 +02005295 gen_helper_mftc0_debug(t0, cpu_env);
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08005296 break;
5297 default:
5298 gen_mfc0(env, ctx, t0, rt, sel);
5299 break;
5300 }
5301 break;
5302 default:
5303 gen_mfc0(env, ctx, t0, rt, sel);
5304 }
5305 } else switch (sel) {
5306 /* GPR registers. */
5307 case 0:
David 'Digit' Turner26efe752014-04-03 15:59:28 +02005308 gen_helper_2i(mftgpr, t0, cpu_env, rt);
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08005309 break;
5310 /* Auxiliary CPU registers */
5311 case 1:
5312 switch (rt) {
5313 case 0:
David 'Digit' Turner26efe752014-04-03 15:59:28 +02005314 gen_helper_2i(mftlo, t0, cpu_env, 0);
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08005315 break;
5316 case 1:
David 'Digit' Turner26efe752014-04-03 15:59:28 +02005317 gen_helper_2i(mfthi, t0, cpu_env, 0);
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08005318 break;
5319 case 2:
David 'Digit' Turner26efe752014-04-03 15:59:28 +02005320 gen_helper_2i(mftacx, t0, cpu_env, 0);
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08005321 break;
5322 case 4:
David 'Digit' Turner26efe752014-04-03 15:59:28 +02005323 gen_helper_2i(mftlo, t0, cpu_env, 1);
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08005324 break;
5325 case 5:
David 'Digit' Turner26efe752014-04-03 15:59:28 +02005326 gen_helper_2i(mfthi, t0, cpu_env, 1);
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08005327 break;
5328 case 6:
David 'Digit' Turner26efe752014-04-03 15:59:28 +02005329 gen_helper_2i(mftacx, t0, cpu_env, 1);
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08005330 break;
5331 case 8:
David 'Digit' Turner26efe752014-04-03 15:59:28 +02005332 gen_helper_2i(mftlo, t0, cpu_env, 2);
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08005333 break;
5334 case 9:
David 'Digit' Turner26efe752014-04-03 15:59:28 +02005335 gen_helper_2i(mfthi, t0, cpu_env, 2);
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08005336 break;
5337 case 10:
David 'Digit' Turner26efe752014-04-03 15:59:28 +02005338 gen_helper_2i(mftacx, t0, cpu_env, 2);
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08005339 break;
5340 case 12:
David 'Digit' Turner26efe752014-04-03 15:59:28 +02005341 gen_helper_2i(mftlo, t0, cpu_env, 3);
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08005342 break;
5343 case 13:
David 'Digit' Turner26efe752014-04-03 15:59:28 +02005344 gen_helper_2i(mfthi, t0, cpu_env, 3);
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08005345 break;
5346 case 14:
David 'Digit' Turner26efe752014-04-03 15:59:28 +02005347 gen_helper_2i(mftacx, t0, cpu_env, 3);
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08005348 break;
5349 case 16:
David 'Digit' Turner26efe752014-04-03 15:59:28 +02005350 gen_helper_mftdsp(t0, cpu_env);
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08005351 break;
5352 default:
5353 goto die;
5354 }
5355 break;
5356 /* Floating point (COP1). */
5357 case 2:
5358 /* XXX: For now we support only a single FPU context. */
5359 if (h == 0) {
5360 TCGv_i32 fp0 = tcg_temp_new_i32();
5361
5362 gen_load_fpr32(fp0, rt);
5363 tcg_gen_ext_i32_tl(t0, fp0);
5364 tcg_temp_free_i32(fp0);
5365 } else {
5366 TCGv_i32 fp0 = tcg_temp_new_i32();
5367
5368 gen_load_fpr32h(fp0, rt);
5369 tcg_gen_ext_i32_tl(t0, fp0);
5370 tcg_temp_free_i32(fp0);
5371 }
5372 break;
5373 case 3:
5374 /* XXX: For now we support only a single FPU context. */
David 'Digit' Turner87350d12014-04-03 15:44:48 +02005375 gen_helper_2i(cfc1, t0, cpu_env, rt);
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08005376 break;
5377 /* COP2: Not implemented. */
5378 case 4:
5379 case 5:
5380 /* fall through */
5381 default:
5382 goto die;
5383 }
5384 LOG_DISAS("mftr (reg %d u %d sel %d h %d)\n", rt, u, sel, h);
5385 gen_store_gpr(t0, rd);
5386 tcg_temp_free(t0);
5387 return;
5388
5389die:
5390 tcg_temp_free(t0);
5391 LOG_DISAS("mftr (reg %d u %d sel %d h %d)\n", rt, u, sel, h);
5392 generate_exception(ctx, EXCP_RI);
5393}
5394
David 'Digit' Turnere2678e12014-01-16 15:56:43 +01005395static void gen_mttr(CPUMIPSState *env, DisasContext *ctx, int rd, int rt,
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08005396 int u, int sel, int h)
5397{
5398 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
5399 TCGv t0 = tcg_temp_local_new();
5400
5401 gen_load_gpr(t0, rt);
5402 if ((env->CP0_VPEConf0 & (1 << CP0VPEC0_MVP)) == 0 &&
5403 ((env->tcs[other_tc].CP0_TCBind & (0xf << CP0TCBd_CurVPE)) !=
5404 (env->active_tc.CP0_TCBind & (0xf << CP0TCBd_CurVPE))))
5405 /* NOP */ ;
5406 else if ((env->CP0_VPEControl & (0xff << CP0VPECo_TargTC)) >
5407 (env->mvp->CP0_MVPConf0 & (0xff << CP0MVPC0_PTC)))
5408 /* NOP */ ;
5409 else if (u == 0) {
5410 switch (rd) {
5411 case 2:
5412 switch (sel) {
5413 case 1:
David 'Digit' Turner06978cc2014-04-03 15:55:43 +02005414 gen_helper_mttc0_tcstatus(cpu_env, t0);
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08005415 break;
5416 case 2:
David 'Digit' Turner06978cc2014-04-03 15:55:43 +02005417 gen_helper_mttc0_tcbind(cpu_env, t0);
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08005418 break;
5419 case 3:
David 'Digit' Turner06978cc2014-04-03 15:55:43 +02005420 gen_helper_mttc0_tcrestart(cpu_env, t0);
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08005421 break;
5422 case 4:
David 'Digit' Turner06978cc2014-04-03 15:55:43 +02005423 gen_helper_mttc0_tchalt(cpu_env, t0);
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08005424 break;
5425 case 5:
David 'Digit' Turner06978cc2014-04-03 15:55:43 +02005426 gen_helper_mttc0_tccontext(cpu_env, t0);
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08005427 break;
5428 case 6:
David 'Digit' Turner06978cc2014-04-03 15:55:43 +02005429 gen_helper_mttc0_tcschedule(cpu_env, t0);
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08005430 break;
5431 case 7:
David 'Digit' Turner06978cc2014-04-03 15:55:43 +02005432 gen_helper_mttc0_tcschefback(cpu_env, t0);
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08005433 break;
5434 default:
5435 gen_mtc0(env, ctx, t0, rd, sel);
5436 break;
5437 }
5438 break;
5439 case 10:
5440 switch (sel) {
5441 case 0:
David 'Digit' Turner06978cc2014-04-03 15:55:43 +02005442 gen_helper_mttc0_entryhi(cpu_env, t0);
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08005443 break;
5444 default:
5445 gen_mtc0(env, ctx, t0, rd, sel);
5446 break;
5447 }
5448 case 12:
5449 switch (sel) {
5450 case 0:
David 'Digit' Turner06978cc2014-04-03 15:55:43 +02005451 gen_helper_mttc0_status(cpu_env, t0);
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08005452 break;
5453 default:
5454 gen_mtc0(env, ctx, t0, rd, sel);
5455 break;
5456 }
5457 case 23:
5458 switch (sel) {
5459 case 0:
David 'Digit' Turner06978cc2014-04-03 15:55:43 +02005460 gen_helper_mttc0_debug(cpu_env, t0);
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08005461 break;
5462 default:
5463 gen_mtc0(env, ctx, t0, rd, sel);
5464 break;
5465 }
5466 break;
5467 default:
5468 gen_mtc0(env, ctx, t0, rd, sel);
5469 }
5470 } else switch (sel) {
5471 /* GPR registers. */
5472 case 0:
David 'Digit' Turner26efe752014-04-03 15:59:28 +02005473 gen_helper_2i(mttgpr, cpu_env, t0, rd);
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08005474 break;
5475 /* Auxiliary CPU registers */
5476 case 1:
5477 switch (rd) {
5478 case 0:
David 'Digit' Turner26efe752014-04-03 15:59:28 +02005479 gen_helper_2i(mttlo, cpu_env, t0, 0);
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08005480 break;
5481 case 1:
David 'Digit' Turner26efe752014-04-03 15:59:28 +02005482 gen_helper_2i(mtthi, cpu_env, t0, 0);
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08005483 break;
5484 case 2:
David 'Digit' Turner26efe752014-04-03 15:59:28 +02005485 gen_helper_2i(mttacx, cpu_env, t0, 0);
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08005486 break;
5487 case 4:
David 'Digit' Turner26efe752014-04-03 15:59:28 +02005488 gen_helper_2i(mttlo, cpu_env, t0, 1);
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08005489 break;
5490 case 5:
David 'Digit' Turner26efe752014-04-03 15:59:28 +02005491 gen_helper_2i(mtthi, cpu_env, t0, 1);
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08005492 break;
5493 case 6:
David 'Digit' Turner26efe752014-04-03 15:59:28 +02005494 gen_helper_2i(mttacx, cpu_env, t0, 1);
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08005495 break;
5496 case 8:
David 'Digit' Turner26efe752014-04-03 15:59:28 +02005497 gen_helper_2i(mttlo, cpu_env, t0, 2);
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08005498 break;
5499 case 9:
David 'Digit' Turner26efe752014-04-03 15:59:28 +02005500 gen_helper_2i(mtthi, cpu_env, t0, 2);
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08005501 break;
5502 case 10:
David 'Digit' Turner26efe752014-04-03 15:59:28 +02005503 gen_helper_2i(mttacx, cpu_env, t0, 2);
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08005504 break;
5505 case 12:
David 'Digit' Turner26efe752014-04-03 15:59:28 +02005506 gen_helper_2i(mttlo, cpu_env, t0, 3);
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08005507 break;
5508 case 13:
David 'Digit' Turner26efe752014-04-03 15:59:28 +02005509 gen_helper_2i(mtthi, cpu_env, t0, 3);
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08005510 break;
5511 case 14:
David 'Digit' Turner26efe752014-04-03 15:59:28 +02005512 gen_helper_2i(mttacx, cpu_env, t0, 3);
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08005513 break;
5514 case 16:
David 'Digit' Turner26efe752014-04-03 15:59:28 +02005515 gen_helper_mttdsp(cpu_env, t0);
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08005516 break;
5517 default:
5518 goto die;
5519 }
5520 break;
5521 /* Floating point (COP1). */
5522 case 2:
5523 /* XXX: For now we support only a single FPU context. */
5524 if (h == 0) {
5525 TCGv_i32 fp0 = tcg_temp_new_i32();
5526
5527 tcg_gen_trunc_tl_i32(fp0, t0);
5528 gen_store_fpr32(fp0, rd);
5529 tcg_temp_free_i32(fp0);
5530 } else {
5531 TCGv_i32 fp0 = tcg_temp_new_i32();
5532
5533 tcg_gen_trunc_tl_i32(fp0, t0);
5534 gen_store_fpr32h(fp0, rd);
5535 tcg_temp_free_i32(fp0);
5536 }
5537 break;
5538 case 3:
5539 /* XXX: For now we support only a single FPU context. */
David 'Digit' Turner87350d12014-04-03 15:44:48 +02005540 gen_helper_2i(ctc1, cpu_env, t0, rd);
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08005541 break;
5542 /* COP2: Not implemented. */
5543 case 4:
5544 case 5:
5545 /* fall through */
5546 default:
5547 goto die;
5548 }
5549 LOG_DISAS("mttr (reg %d u %d sel %d h %d)\n", rd, u, sel, h);
5550 tcg_temp_free(t0);
5551 return;
5552
5553die:
5554 tcg_temp_free(t0);
5555 LOG_DISAS("mttr (reg %d u %d sel %d h %d)\n", rd, u, sel, h);
5556 generate_exception(ctx, EXCP_RI);
5557}
5558
David 'Digit' Turnere2678e12014-01-16 15:56:43 +01005559static void gen_cp0 (CPUMIPSState *env, DisasContext *ctx, uint32_t opc, int rt, int rd)
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08005560{
David 'Digit' Turnera2c14f92014-02-04 01:02:30 +01005561 const char* __attribute__((unused)) opn = "ldst";
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08005562
5563 switch (opc) {
5564 case OPC_MFC0:
5565 if (rt == 0) {
5566 /* Treat as NOP. */
5567 return;
5568 }
5569 gen_mfc0(env, ctx, cpu_gpr[rt], rd, ctx->opcode & 0x7);
5570 opn = "mfc0";
5571 break;
5572 case OPC_MTC0:
5573 {
5574 TCGv t0 = tcg_temp_new();
5575
5576 gen_load_gpr(t0, rt);
5577 gen_mtc0(env, ctx, t0, rd, ctx->opcode & 0x7);
5578 tcg_temp_free(t0);
5579 }
5580 opn = "mtc0";
5581 break;
5582#if defined(TARGET_MIPS64)
5583 case OPC_DMFC0:
5584 check_insn(env, ctx, ISA_MIPS3);
5585 if (rt == 0) {
5586 /* Treat as NOP. */
5587 return;
5588 }
5589 gen_dmfc0(env, ctx, cpu_gpr[rt], rd, ctx->opcode & 0x7);
5590 opn = "dmfc0";
5591 break;
5592 case OPC_DMTC0:
5593 check_insn(env, ctx, ISA_MIPS3);
5594 {
5595 TCGv t0 = tcg_temp_new();
5596
5597 gen_load_gpr(t0, rt);
5598 gen_dmtc0(env, ctx, t0, rd, ctx->opcode & 0x7);
5599 tcg_temp_free(t0);
5600 }
5601 opn = "dmtc0";
5602 break;
5603#endif
5604 case OPC_MFTR:
5605 check_insn(env, ctx, ASE_MT);
5606 if (rd == 0) {
5607 /* Treat as NOP. */
5608 return;
5609 }
5610 gen_mftr(env, ctx, rt, rd, (ctx->opcode >> 5) & 1,
5611 ctx->opcode & 0x7, (ctx->opcode >> 4) & 1);
5612 opn = "mftr";
5613 break;
5614 case OPC_MTTR:
5615 check_insn(env, ctx, ASE_MT);
5616 gen_mttr(env, ctx, rd, rt, (ctx->opcode >> 5) & 1,
5617 ctx->opcode & 0x7, (ctx->opcode >> 4) & 1);
5618 opn = "mttr";
5619 break;
5620 case OPC_TLBWI:
5621 opn = "tlbwi";
5622 if (!env->tlb->helper_tlbwi)
5623 goto die;
David 'Digit' Turner758fa082014-04-03 12:29:21 +02005624 gen_helper_tlbwi(cpu_env);
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08005625 break;
5626 case OPC_TLBWR:
5627 opn = "tlbwr";
5628 if (!env->tlb->helper_tlbwr)
5629 goto die;
David 'Digit' Turner758fa082014-04-03 12:29:21 +02005630 gen_helper_tlbwr(cpu_env);
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08005631 break;
5632 case OPC_TLBP:
5633 opn = "tlbp";
5634 if (!env->tlb->helper_tlbp)
5635 goto die;
David 'Digit' Turner758fa082014-04-03 12:29:21 +02005636 gen_helper_tlbp(cpu_env);
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08005637 break;
5638 case OPC_TLBR:
5639 opn = "tlbr";
5640 if (!env->tlb->helper_tlbr)
5641 goto die;
David 'Digit' Turner758fa082014-04-03 12:29:21 +02005642 gen_helper_tlbr(cpu_env);
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08005643 break;
5644 case OPC_ERET:
5645 opn = "eret";
5646 check_insn(env, ctx, ISA_MIPS2);
David 'Digit' Turner6480c962014-04-03 12:38:04 +02005647 gen_helper_eret(cpu_env);
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08005648 ctx->bstate = BS_EXCP;
5649 break;
5650 case OPC_DERET:
5651 opn = "deret";
5652 check_insn(env, ctx, ISA_MIPS32);
5653 if (!(ctx->hflags & MIPS_HFLAG_DM)) {
5654 MIPS_INVAL(opn);
5655 generate_exception(ctx, EXCP_RI);
5656 } else {
David 'Digit' Turner6480c962014-04-03 12:38:04 +02005657 gen_helper_deret(cpu_env);
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08005658 ctx->bstate = BS_EXCP;
5659 }
5660 break;
5661 case OPC_WAIT:
5662 opn = "wait";
5663 check_insn(env, ctx, ISA_MIPS3 | ISA_MIPS32);
5664 /* If we get an exception, we want to restart at next instruction */
5665 ctx->pc += 4;
5666 save_cpu_state(ctx, 1);
5667 ctx->pc -= 4;
David 'Digit' Turnerd5b76c62014-04-03 12:40:54 +02005668 gen_helper_wait(cpu_env);
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08005669 ctx->bstate = BS_EXCP;
5670 break;
5671 default:
5672 die:
5673 MIPS_INVAL(opn);
5674 generate_exception(ctx, EXCP_RI);
5675 return;
5676 }
5677 MIPS_DEBUG("%s %s %d", opn, regnames[rt], rd);
5678}
5679#endif /* !CONFIG_USER_ONLY */
5680
5681/* CP1 Branches (before delay slot) */
David 'Digit' Turnere2678e12014-01-16 15:56:43 +01005682static void gen_compute_branch1 (CPUMIPSState *env, DisasContext *ctx, uint32_t op,
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08005683 int32_t cc, int32_t offset)
5684{
5685 target_ulong btarget;
David 'Digit' Turnera2c14f92014-02-04 01:02:30 +01005686 const char* __attribute__((unused)) opn = "cp1 cond branch";
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08005687 TCGv_i32 t0 = tcg_temp_new_i32();
5688
5689 if (cc != 0)
5690 check_insn(env, ctx, ISA_MIPS4 | ISA_MIPS32);
5691
5692 btarget = ctx->pc + 4 + offset;
5693
5694 switch (op) {
5695 case OPC_BC1F:
5696 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
5697 tcg_gen_not_i32(t0, t0);
5698 tcg_gen_andi_i32(t0, t0, 1);
5699 tcg_gen_extu_i32_tl(bcond, t0);
5700 opn = "bc1f";
5701 goto not_likely;
5702 case OPC_BC1FL:
5703 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
5704 tcg_gen_not_i32(t0, t0);
5705 tcg_gen_andi_i32(t0, t0, 1);
5706 tcg_gen_extu_i32_tl(bcond, t0);
5707 opn = "bc1fl";
5708 goto likely;
5709 case OPC_BC1T:
5710 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
5711 tcg_gen_andi_i32(t0, t0, 1);
5712 tcg_gen_extu_i32_tl(bcond, t0);
5713 opn = "bc1t";
5714 goto not_likely;
5715 case OPC_BC1TL:
5716 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
5717 tcg_gen_andi_i32(t0, t0, 1);
5718 tcg_gen_extu_i32_tl(bcond, t0);
5719 opn = "bc1tl";
5720 likely:
5721 ctx->hflags |= MIPS_HFLAG_BL;
5722 break;
5723 case OPC_BC1FANY2:
5724 {
5725 TCGv_i32 t1 = tcg_temp_new_i32();
5726 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
5727 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+1));
5728 tcg_gen_or_i32(t0, t0, t1);
5729 tcg_temp_free_i32(t1);
5730 tcg_gen_not_i32(t0, t0);
5731 tcg_gen_andi_i32(t0, t0, 1);
5732 tcg_gen_extu_i32_tl(bcond, t0);
5733 }
5734 opn = "bc1any2f";
5735 goto not_likely;
5736 case OPC_BC1TANY2:
5737 {
5738 TCGv_i32 t1 = tcg_temp_new_i32();
5739 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
5740 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+1));
5741 tcg_gen_or_i32(t0, t0, t1);
5742 tcg_temp_free_i32(t1);
5743 tcg_gen_andi_i32(t0, t0, 1);
5744 tcg_gen_extu_i32_tl(bcond, t0);
5745 }
5746 opn = "bc1any2t";
5747 goto not_likely;
5748 case OPC_BC1FANY4:
5749 {
5750 TCGv_i32 t1 = tcg_temp_new_i32();
5751 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
5752 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+1));
5753 tcg_gen_or_i32(t0, t0, t1);
5754 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+2));
5755 tcg_gen_or_i32(t0, t0, t1);
5756 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+3));
5757 tcg_gen_or_i32(t0, t0, t1);
5758 tcg_temp_free_i32(t1);
5759 tcg_gen_not_i32(t0, t0);
5760 tcg_gen_andi_i32(t0, t0, 1);
5761 tcg_gen_extu_i32_tl(bcond, t0);
5762 }
5763 opn = "bc1any4f";
5764 goto not_likely;
5765 case OPC_BC1TANY4:
5766 {
5767 TCGv_i32 t1 = tcg_temp_new_i32();
5768 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
5769 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+1));
5770 tcg_gen_or_i32(t0, t0, t1);
5771 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+2));
5772 tcg_gen_or_i32(t0, t0, t1);
5773 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+3));
5774 tcg_gen_or_i32(t0, t0, t1);
5775 tcg_temp_free_i32(t1);
5776 tcg_gen_andi_i32(t0, t0, 1);
5777 tcg_gen_extu_i32_tl(bcond, t0);
5778 }
5779 opn = "bc1any4t";
5780 not_likely:
5781 ctx->hflags |= MIPS_HFLAG_BC;
5782 break;
5783 default:
5784 MIPS_INVAL(opn);
5785 generate_exception (ctx, EXCP_RI);
5786 goto out;
5787 }
5788 MIPS_DEBUG("%s: cond %02x target " TARGET_FMT_lx, opn,
5789 ctx->hflags, btarget);
5790 ctx->btarget = btarget;
5791
5792 out:
5793 tcg_temp_free_i32(t0);
5794}
5795
5796/* Coprocessor 1 (FPU) */
5797
5798#define FOP(func, fmt) (((fmt) << 21) | (func))
5799
5800static void gen_cp1 (DisasContext *ctx, uint32_t opc, int rt, int fs)
5801{
David 'Digit' Turnera2c14f92014-02-04 01:02:30 +01005802 const char* __attribute__((unused)) opn = "cp1 move";
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08005803 TCGv t0 = tcg_temp_new();
5804
5805 switch (opc) {
5806 case OPC_MFC1:
5807 {
5808 TCGv_i32 fp0 = tcg_temp_new_i32();
5809
5810 gen_load_fpr32(fp0, fs);
5811 tcg_gen_ext_i32_tl(t0, fp0);
5812 tcg_temp_free_i32(fp0);
5813 }
5814 gen_store_gpr(t0, rt);
5815 opn = "mfc1";
5816 break;
5817 case OPC_MTC1:
5818 gen_load_gpr(t0, rt);
5819 {
5820 TCGv_i32 fp0 = tcg_temp_new_i32();
5821
5822 tcg_gen_trunc_tl_i32(fp0, t0);
5823 gen_store_fpr32(fp0, fs);
5824 tcg_temp_free_i32(fp0);
5825 }
5826 opn = "mtc1";
5827 break;
5828 case OPC_CFC1:
David 'Digit' Turner87350d12014-04-03 15:44:48 +02005829 gen_helper_2i(cfc1, t0, cpu_env, fs);
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08005830 gen_store_gpr(t0, rt);
5831 opn = "cfc1";
5832 break;
5833 case OPC_CTC1:
5834 gen_load_gpr(t0, rt);
David 'Digit' Turner87350d12014-04-03 15:44:48 +02005835 gen_helper_2i(ctc1, cpu_env, t0, fs);
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08005836 opn = "ctc1";
5837 break;
5838#if defined(TARGET_MIPS64)
5839 case OPC_DMFC1:
5840 gen_load_fpr64(ctx, t0, fs);
5841 gen_store_gpr(t0, rt);
5842 opn = "dmfc1";
5843 break;
5844 case OPC_DMTC1:
5845 gen_load_gpr(t0, rt);
5846 gen_store_fpr64(ctx, t0, fs);
5847 opn = "dmtc1";
5848 break;
5849#endif
5850 case OPC_MFHC1:
5851 {
5852 TCGv_i32 fp0 = tcg_temp_new_i32();
5853
5854 gen_load_fpr32h(fp0, fs);
5855 tcg_gen_ext_i32_tl(t0, fp0);
5856 tcg_temp_free_i32(fp0);
5857 }
5858 gen_store_gpr(t0, rt);
5859 opn = "mfhc1";
5860 break;
5861 case OPC_MTHC1:
5862 gen_load_gpr(t0, rt);
5863 {
5864 TCGv_i32 fp0 = tcg_temp_new_i32();
5865
5866 tcg_gen_trunc_tl_i32(fp0, t0);
5867 gen_store_fpr32h(fp0, fs);
5868 tcg_temp_free_i32(fp0);
5869 }
5870 opn = "mthc1";
5871 break;
5872 default:
5873 MIPS_INVAL(opn);
5874 generate_exception (ctx, EXCP_RI);
5875 goto out;
5876 }
5877 MIPS_DEBUG("%s %s %s", opn, regnames[rt], fregnames[fs]);
5878
5879 out:
5880 tcg_temp_free(t0);
5881}
5882
5883static void gen_movci (DisasContext *ctx, int rd, int rs, int cc, int tf)
5884{
5885 int l1;
5886 TCGCond cond;
5887 TCGv_i32 t0;
5888
5889 if (rd == 0) {
5890 /* Treat as NOP. */
5891 return;
5892 }
5893
5894 if (tf)
5895 cond = TCG_COND_EQ;
5896 else
5897 cond = TCG_COND_NE;
5898
5899 l1 = gen_new_label();
5900 t0 = tcg_temp_new_i32();
5901 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
5902 tcg_gen_brcondi_i32(cond, t0, 0, l1);
5903 tcg_temp_free_i32(t0);
5904 if (rs == 0) {
5905 tcg_gen_movi_tl(cpu_gpr[rd], 0);
5906 } else {
5907 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
5908 }
5909 gen_set_label(l1);
5910}
5911
5912static inline void gen_movcf_s (int fs, int fd, int cc, int tf)
5913{
5914 int cond;
5915 TCGv_i32 t0 = tcg_temp_new_i32();
5916 int l1 = gen_new_label();
5917
5918 if (tf)
5919 cond = TCG_COND_EQ;
5920 else
5921 cond = TCG_COND_NE;
5922
5923 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
5924 tcg_gen_brcondi_i32(cond, t0, 0, l1);
5925 gen_load_fpr32(t0, fs);
5926 gen_store_fpr32(t0, fd);
5927 gen_set_label(l1);
5928 tcg_temp_free_i32(t0);
5929}
5930
5931static inline void gen_movcf_d (DisasContext *ctx, int fs, int fd, int cc, int tf)
5932{
5933 int cond;
5934 TCGv_i32 t0 = tcg_temp_new_i32();
5935 TCGv_i64 fp0;
5936 int l1 = gen_new_label();
5937
5938 if (tf)
5939 cond = TCG_COND_EQ;
5940 else
5941 cond = TCG_COND_NE;
5942
5943 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
5944 tcg_gen_brcondi_i32(cond, t0, 0, l1);
5945 tcg_temp_free_i32(t0);
5946 fp0 = tcg_temp_new_i64();
5947 gen_load_fpr64(ctx, fp0, fs);
5948 gen_store_fpr64(ctx, fp0, fd);
5949 tcg_temp_free_i64(fp0);
5950 gen_set_label(l1);
5951}
5952
5953static inline void gen_movcf_ps (int fs, int fd, int cc, int tf)
5954{
5955 int cond;
5956 TCGv_i32 t0 = tcg_temp_new_i32();
5957 int l1 = gen_new_label();
5958 int l2 = gen_new_label();
5959
5960 if (tf)
5961 cond = TCG_COND_EQ;
5962 else
5963 cond = TCG_COND_NE;
5964
5965 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
5966 tcg_gen_brcondi_i32(cond, t0, 0, l1);
5967 gen_load_fpr32(t0, fs);
5968 gen_store_fpr32(t0, fd);
5969 gen_set_label(l1);
5970
5971 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc+1));
5972 tcg_gen_brcondi_i32(cond, t0, 0, l2);
5973 gen_load_fpr32h(t0, fs);
5974 gen_store_fpr32h(t0, fd);
5975 tcg_temp_free_i32(t0);
5976 gen_set_label(l2);
5977}
5978
5979
5980static void gen_farith (DisasContext *ctx, uint32_t op1,
5981 int ft, int fs, int fd, int cc)
5982{
David 'Digit' Turnera2c14f92014-02-04 01:02:30 +01005983 const char* __attribute__((unused)) opn = "farith";
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08005984 const char *condnames[] = {
5985 "c.f",
5986 "c.un",
5987 "c.eq",
5988 "c.ueq",
5989 "c.olt",
5990 "c.ult",
5991 "c.ole",
5992 "c.ule",
5993 "c.sf",
5994 "c.ngle",
5995 "c.seq",
5996 "c.ngl",
5997 "c.lt",
5998 "c.nge",
5999 "c.le",
6000 "c.ngt",
6001 };
6002 const char *condnames_abs[] = {
6003 "cabs.f",
6004 "cabs.un",
6005 "cabs.eq",
6006 "cabs.ueq",
6007 "cabs.olt",
6008 "cabs.ult",
6009 "cabs.ole",
6010 "cabs.ule",
6011 "cabs.sf",
6012 "cabs.ngle",
6013 "cabs.seq",
6014 "cabs.ngl",
6015 "cabs.lt",
6016 "cabs.nge",
6017 "cabs.le",
6018 "cabs.ngt",
6019 };
6020 enum { BINOP, CMPOP, OTHEROP } optype = OTHEROP;
6021 uint32_t func = ctx->opcode & 0x3f;
6022
6023 switch (ctx->opcode & FOP(0x3f, 0x1f)) {
6024 case FOP(0, 16):
6025 {
6026 TCGv_i32 fp0 = tcg_temp_new_i32();
6027 TCGv_i32 fp1 = tcg_temp_new_i32();
6028
6029 gen_load_fpr32(fp0, fs);
6030 gen_load_fpr32(fp1, ft);
David 'Digit' Turner87350d12014-04-03 15:44:48 +02006031 gen_helper_float_add_s(fp0, cpu_env, fp0, fp1);
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08006032 tcg_temp_free_i32(fp1);
6033 gen_store_fpr32(fp0, fd);
6034 tcg_temp_free_i32(fp0);
6035 }
6036 opn = "add.s";
6037 optype = BINOP;
6038 break;
6039 case FOP(1, 16):
6040 {
6041 TCGv_i32 fp0 = tcg_temp_new_i32();
6042 TCGv_i32 fp1 = tcg_temp_new_i32();
6043
6044 gen_load_fpr32(fp0, fs);
6045 gen_load_fpr32(fp1, ft);
David 'Digit' Turner87350d12014-04-03 15:44:48 +02006046 gen_helper_float_sub_s(fp0, cpu_env, fp0, fp1);
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08006047 tcg_temp_free_i32(fp1);
6048 gen_store_fpr32(fp0, fd);
6049 tcg_temp_free_i32(fp0);
6050 }
6051 opn = "sub.s";
6052 optype = BINOP;
6053 break;
6054 case FOP(2, 16):
6055 {
6056 TCGv_i32 fp0 = tcg_temp_new_i32();
6057 TCGv_i32 fp1 = tcg_temp_new_i32();
6058
6059 gen_load_fpr32(fp0, fs);
6060 gen_load_fpr32(fp1, ft);
David 'Digit' Turner87350d12014-04-03 15:44:48 +02006061 gen_helper_float_mul_s(fp0, cpu_env, fp0, fp1);
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08006062 tcg_temp_free_i32(fp1);
6063 gen_store_fpr32(fp0, fd);
6064 tcg_temp_free_i32(fp0);
6065 }
6066 opn = "mul.s";
6067 optype = BINOP;
6068 break;
6069 case FOP(3, 16):
6070 {
6071 TCGv_i32 fp0 = tcg_temp_new_i32();
6072 TCGv_i32 fp1 = tcg_temp_new_i32();
6073
6074 gen_load_fpr32(fp0, fs);
6075 gen_load_fpr32(fp1, ft);
David 'Digit' Turner87350d12014-04-03 15:44:48 +02006076 gen_helper_float_div_s(fp0, cpu_env, fp0, fp1);
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08006077 tcg_temp_free_i32(fp1);
6078 gen_store_fpr32(fp0, fd);
6079 tcg_temp_free_i32(fp0);
6080 }
6081 opn = "div.s";
6082 optype = BINOP;
6083 break;
6084 case FOP(4, 16):
6085 {
6086 TCGv_i32 fp0 = tcg_temp_new_i32();
6087
6088 gen_load_fpr32(fp0, fs);
David 'Digit' Turner87350d12014-04-03 15:44:48 +02006089 gen_helper_float_sqrt_s(fp0, cpu_env, fp0);
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08006090 gen_store_fpr32(fp0, fd);
6091 tcg_temp_free_i32(fp0);
6092 }
6093 opn = "sqrt.s";
6094 break;
6095 case FOP(5, 16):
6096 {
6097 TCGv_i32 fp0 = tcg_temp_new_i32();
6098
6099 gen_load_fpr32(fp0, fs);
6100 gen_helper_float_abs_s(fp0, fp0);
6101 gen_store_fpr32(fp0, fd);
6102 tcg_temp_free_i32(fp0);
6103 }
6104 opn = "abs.s";
6105 break;
6106 case FOP(6, 16):
6107 {
6108 TCGv_i32 fp0 = tcg_temp_new_i32();
6109
6110 gen_load_fpr32(fp0, fs);
6111 gen_store_fpr32(fp0, fd);
6112 tcg_temp_free_i32(fp0);
6113 }
6114 opn = "mov.s";
6115 break;
6116 case FOP(7, 16):
6117 {
6118 TCGv_i32 fp0 = tcg_temp_new_i32();
6119
6120 gen_load_fpr32(fp0, fs);
6121 gen_helper_float_chs_s(fp0, fp0);
6122 gen_store_fpr32(fp0, fd);
6123 tcg_temp_free_i32(fp0);
6124 }
6125 opn = "neg.s";
6126 break;
6127 case FOP(8, 16):
6128 check_cp1_64bitmode(ctx);
6129 {
6130 TCGv_i32 fp32 = tcg_temp_new_i32();
6131 TCGv_i64 fp64 = tcg_temp_new_i64();
6132
6133 gen_load_fpr32(fp32, fs);
David 'Digit' Turner87350d12014-04-03 15:44:48 +02006134 gen_helper_float_roundl_s(fp64, cpu_env, fp32);
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08006135 tcg_temp_free_i32(fp32);
6136 gen_store_fpr64(ctx, fp64, fd);
6137 tcg_temp_free_i64(fp64);
6138 }
6139 opn = "round.l.s";
6140 break;
6141 case FOP(9, 16):
6142 check_cp1_64bitmode(ctx);
6143 {
6144 TCGv_i32 fp32 = tcg_temp_new_i32();
6145 TCGv_i64 fp64 = tcg_temp_new_i64();
6146
6147 gen_load_fpr32(fp32, fs);
David 'Digit' Turner87350d12014-04-03 15:44:48 +02006148 gen_helper_float_truncl_s(fp64, cpu_env, fp32);
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08006149 tcg_temp_free_i32(fp32);
6150 gen_store_fpr64(ctx, fp64, fd);
6151 tcg_temp_free_i64(fp64);
6152 }
6153 opn = "trunc.l.s";
6154 break;
6155 case FOP(10, 16):
6156 check_cp1_64bitmode(ctx);
6157 {
6158 TCGv_i32 fp32 = tcg_temp_new_i32();
6159 TCGv_i64 fp64 = tcg_temp_new_i64();
6160
6161 gen_load_fpr32(fp32, fs);
David 'Digit' Turner87350d12014-04-03 15:44:48 +02006162 gen_helper_float_ceill_s(fp64, cpu_env, fp32);
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08006163 tcg_temp_free_i32(fp32);
6164 gen_store_fpr64(ctx, fp64, fd);
6165 tcg_temp_free_i64(fp64);
6166 }
6167 opn = "ceil.l.s";
6168 break;
6169 case FOP(11, 16):
6170 check_cp1_64bitmode(ctx);
6171 {
6172 TCGv_i32 fp32 = tcg_temp_new_i32();
6173 TCGv_i64 fp64 = tcg_temp_new_i64();
6174
6175 gen_load_fpr32(fp32, fs);
David 'Digit' Turner87350d12014-04-03 15:44:48 +02006176 gen_helper_float_floorl_s(fp64, cpu_env, fp32);
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08006177 tcg_temp_free_i32(fp32);
6178 gen_store_fpr64(ctx, fp64, fd);
6179 tcg_temp_free_i64(fp64);
6180 }
6181 opn = "floor.l.s";
6182 break;
6183 case FOP(12, 16):
6184 {
6185 TCGv_i32 fp0 = tcg_temp_new_i32();
6186
6187 gen_load_fpr32(fp0, fs);
David 'Digit' Turner87350d12014-04-03 15:44:48 +02006188 gen_helper_float_roundw_s(fp0, cpu_env, fp0);
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08006189 gen_store_fpr32(fp0, fd);
6190 tcg_temp_free_i32(fp0);
6191 }
6192 opn = "round.w.s";
6193 break;
6194 case FOP(13, 16):
6195 {
6196 TCGv_i32 fp0 = tcg_temp_new_i32();
6197
6198 gen_load_fpr32(fp0, fs);
David 'Digit' Turner87350d12014-04-03 15:44:48 +02006199 gen_helper_float_truncw_s(fp0, cpu_env, fp0);
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08006200 gen_store_fpr32(fp0, fd);
6201 tcg_temp_free_i32(fp0);
6202 }
6203 opn = "trunc.w.s";
6204 break;
6205 case FOP(14, 16):
6206 {
6207 TCGv_i32 fp0 = tcg_temp_new_i32();
6208
6209 gen_load_fpr32(fp0, fs);
David 'Digit' Turner87350d12014-04-03 15:44:48 +02006210 gen_helper_float_ceilw_s(fp0, cpu_env, fp0);
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08006211 gen_store_fpr32(fp0, fd);
6212 tcg_temp_free_i32(fp0);
6213 }
6214 opn = "ceil.w.s";
6215 break;
6216 case FOP(15, 16):
6217 {
6218 TCGv_i32 fp0 = tcg_temp_new_i32();
6219
6220 gen_load_fpr32(fp0, fs);
David 'Digit' Turner87350d12014-04-03 15:44:48 +02006221 gen_helper_float_floorw_s(fp0, cpu_env, fp0);
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08006222 gen_store_fpr32(fp0, fd);
6223 tcg_temp_free_i32(fp0);
6224 }
6225 opn = "floor.w.s";
6226 break;
6227 case FOP(17, 16):
6228 gen_movcf_s(fs, fd, (ft >> 2) & 0x7, ft & 0x1);
6229 opn = "movcf.s";
6230 break;
6231 case FOP(18, 16):
6232 {
6233 int l1 = gen_new_label();
6234 TCGv_i32 fp0;
6235
6236 if (ft != 0) {
6237 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[ft], 0, l1);
6238 }
6239 fp0 = tcg_temp_new_i32();
6240 gen_load_fpr32(fp0, fs);
6241 gen_store_fpr32(fp0, fd);
6242 tcg_temp_free_i32(fp0);
6243 gen_set_label(l1);
6244 }
6245 opn = "movz.s";
6246 break;
6247 case FOP(19, 16):
6248 {
6249 int l1 = gen_new_label();
6250 TCGv_i32 fp0;
6251
6252 if (ft != 0) {
6253 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[ft], 0, l1);
6254 fp0 = tcg_temp_new_i32();
6255 gen_load_fpr32(fp0, fs);
6256 gen_store_fpr32(fp0, fd);
6257 tcg_temp_free_i32(fp0);
6258 gen_set_label(l1);
6259 }
6260 }
6261 opn = "movn.s";
6262 break;
6263 case FOP(21, 16):
6264 check_cop1x(ctx);
6265 {
6266 TCGv_i32 fp0 = tcg_temp_new_i32();
6267
6268 gen_load_fpr32(fp0, fs);
David 'Digit' Turner87350d12014-04-03 15:44:48 +02006269 gen_helper_float_recip_s(fp0, cpu_env, fp0);
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08006270 gen_store_fpr32(fp0, fd);
6271 tcg_temp_free_i32(fp0);
6272 }
6273 opn = "recip.s";
6274 break;
6275 case FOP(22, 16):
6276 check_cop1x(ctx);
6277 {
6278 TCGv_i32 fp0 = tcg_temp_new_i32();
6279
6280 gen_load_fpr32(fp0, fs);
David 'Digit' Turner87350d12014-04-03 15:44:48 +02006281 gen_helper_float_rsqrt_s(fp0, cpu_env, fp0);
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08006282 gen_store_fpr32(fp0, fd);
6283 tcg_temp_free_i32(fp0);
6284 }
6285 opn = "rsqrt.s";
6286 break;
6287 case FOP(28, 16):
6288 check_cp1_64bitmode(ctx);
6289 {
6290 TCGv_i32 fp0 = tcg_temp_new_i32();
6291 TCGv_i32 fp1 = tcg_temp_new_i32();
6292
6293 gen_load_fpr32(fp0, fs);
6294 gen_load_fpr32(fp1, fd);
David 'Digit' Turner87350d12014-04-03 15:44:48 +02006295 gen_helper_float_recip2_s(fp0, cpu_env, fp0, fp1);
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08006296 tcg_temp_free_i32(fp1);
6297 gen_store_fpr32(fp0, fd);
6298 tcg_temp_free_i32(fp0);
6299 }
6300 opn = "recip2.s";
6301 break;
6302 case FOP(29, 16):
6303 check_cp1_64bitmode(ctx);
6304 {
6305 TCGv_i32 fp0 = tcg_temp_new_i32();
6306
6307 gen_load_fpr32(fp0, fs);
David 'Digit' Turner87350d12014-04-03 15:44:48 +02006308 gen_helper_float_recip1_s(fp0, cpu_env, fp0);
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08006309 gen_store_fpr32(fp0, fd);
6310 tcg_temp_free_i32(fp0);
6311 }
6312 opn = "recip1.s";
6313 break;
6314 case FOP(30, 16):
6315 check_cp1_64bitmode(ctx);
6316 {
6317 TCGv_i32 fp0 = tcg_temp_new_i32();
6318
6319 gen_load_fpr32(fp0, fs);
David 'Digit' Turner87350d12014-04-03 15:44:48 +02006320 gen_helper_float_rsqrt1_s(fp0, cpu_env, fp0);
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08006321 gen_store_fpr32(fp0, fd);
6322 tcg_temp_free_i32(fp0);
6323 }
6324 opn = "rsqrt1.s";
6325 break;
6326 case FOP(31, 16):
6327 check_cp1_64bitmode(ctx);
6328 {
6329 TCGv_i32 fp0 = tcg_temp_new_i32();
6330 TCGv_i32 fp1 = tcg_temp_new_i32();
6331
6332 gen_load_fpr32(fp0, fs);
6333 gen_load_fpr32(fp1, ft);
David 'Digit' Turner87350d12014-04-03 15:44:48 +02006334 gen_helper_float_rsqrt2_s(fp0, cpu_env, fp0, fp1);
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08006335 tcg_temp_free_i32(fp1);
6336 gen_store_fpr32(fp0, fd);
6337 tcg_temp_free_i32(fp0);
6338 }
6339 opn = "rsqrt2.s";
6340 break;
6341 case FOP(33, 16):
6342 check_cp1_registers(ctx, fd);
6343 {
6344 TCGv_i32 fp32 = tcg_temp_new_i32();
6345 TCGv_i64 fp64 = tcg_temp_new_i64();
6346
6347 gen_load_fpr32(fp32, fs);
David 'Digit' Turner87350d12014-04-03 15:44:48 +02006348 gen_helper_float_cvtd_s(fp64, cpu_env, fp32);
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08006349 tcg_temp_free_i32(fp32);
6350 gen_store_fpr64(ctx, fp64, fd);
6351 tcg_temp_free_i64(fp64);
6352 }
6353 opn = "cvt.d.s";
6354 break;
6355 case FOP(36, 16):
6356 {
6357 TCGv_i32 fp0 = tcg_temp_new_i32();
6358
6359 gen_load_fpr32(fp0, fs);
David 'Digit' Turner87350d12014-04-03 15:44:48 +02006360 gen_helper_float_cvtw_s(fp0, cpu_env, fp0);
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08006361 gen_store_fpr32(fp0, fd);
6362 tcg_temp_free_i32(fp0);
6363 }
6364 opn = "cvt.w.s";
6365 break;
6366 case FOP(37, 16):
6367 check_cp1_64bitmode(ctx);
6368 {
6369 TCGv_i32 fp32 = tcg_temp_new_i32();
6370 TCGv_i64 fp64 = tcg_temp_new_i64();
6371
6372 gen_load_fpr32(fp32, fs);
David 'Digit' Turner87350d12014-04-03 15:44:48 +02006373 gen_helper_float_cvtl_s(fp64, cpu_env, fp32);
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08006374 tcg_temp_free_i32(fp32);
6375 gen_store_fpr64(ctx, fp64, fd);
6376 tcg_temp_free_i64(fp64);
6377 }
6378 opn = "cvt.l.s";
6379 break;
6380 case FOP(38, 16):
6381 check_cp1_64bitmode(ctx);
6382 {
6383 TCGv_i64 fp64 = tcg_temp_new_i64();
6384 TCGv_i32 fp32_0 = tcg_temp_new_i32();
6385 TCGv_i32 fp32_1 = tcg_temp_new_i32();
6386
6387 gen_load_fpr32(fp32_0, fs);
6388 gen_load_fpr32(fp32_1, ft);
6389 tcg_gen_concat_i32_i64(fp64, fp32_0, fp32_1);
6390 tcg_temp_free_i32(fp32_1);
6391 tcg_temp_free_i32(fp32_0);
6392 gen_store_fpr64(ctx, fp64, fd);
6393 tcg_temp_free_i64(fp64);
6394 }
6395 opn = "cvt.ps.s";
6396 break;
6397 case FOP(48, 16):
6398 case FOP(49, 16):
6399 case FOP(50, 16):
6400 case FOP(51, 16):
6401 case FOP(52, 16):
6402 case FOP(53, 16):
6403 case FOP(54, 16):
6404 case FOP(55, 16):
6405 case FOP(56, 16):
6406 case FOP(57, 16):
6407 case FOP(58, 16):
6408 case FOP(59, 16):
6409 case FOP(60, 16):
6410 case FOP(61, 16):
6411 case FOP(62, 16):
6412 case FOP(63, 16):
6413 {
6414 TCGv_i32 fp0 = tcg_temp_new_i32();
6415 TCGv_i32 fp1 = tcg_temp_new_i32();
6416
6417 gen_load_fpr32(fp0, fs);
6418 gen_load_fpr32(fp1, ft);
6419 if (ctx->opcode & (1 << 6)) {
6420 check_cop1x(ctx);
6421 gen_cmpabs_s(func-48, fp0, fp1, cc);
6422 opn = condnames_abs[func-48];
6423 } else {
6424 gen_cmp_s(func-48, fp0, fp1, cc);
6425 opn = condnames[func-48];
6426 }
6427 tcg_temp_free_i32(fp0);
6428 tcg_temp_free_i32(fp1);
6429 }
6430 break;
6431 case FOP(0, 17):
6432 check_cp1_registers(ctx, fs | ft | fd);
6433 {
6434 TCGv_i64 fp0 = tcg_temp_new_i64();
6435 TCGv_i64 fp1 = tcg_temp_new_i64();
6436
6437 gen_load_fpr64(ctx, fp0, fs);
6438 gen_load_fpr64(ctx, fp1, ft);
David 'Digit' Turner87350d12014-04-03 15:44:48 +02006439 gen_helper_float_add_d(fp0, cpu_env, fp0, fp1);
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08006440 tcg_temp_free_i64(fp1);
6441 gen_store_fpr64(ctx, fp0, fd);
6442 tcg_temp_free_i64(fp0);
6443 }
6444 opn = "add.d";
6445 optype = BINOP;
6446 break;
6447 case FOP(1, 17):
6448 check_cp1_registers(ctx, fs | ft | fd);
6449 {
6450 TCGv_i64 fp0 = tcg_temp_new_i64();
6451 TCGv_i64 fp1 = tcg_temp_new_i64();
6452
6453 gen_load_fpr64(ctx, fp0, fs);
6454 gen_load_fpr64(ctx, fp1, ft);
David 'Digit' Turner87350d12014-04-03 15:44:48 +02006455 gen_helper_float_sub_d(fp0, cpu_env, fp0, fp1);
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08006456 tcg_temp_free_i64(fp1);
6457 gen_store_fpr64(ctx, fp0, fd);
6458 tcg_temp_free_i64(fp0);
6459 }
6460 opn = "sub.d";
6461 optype = BINOP;
6462 break;
6463 case FOP(2, 17):
6464 check_cp1_registers(ctx, fs | ft | fd);
6465 {
6466 TCGv_i64 fp0 = tcg_temp_new_i64();
6467 TCGv_i64 fp1 = tcg_temp_new_i64();
6468
6469 gen_load_fpr64(ctx, fp0, fs);
6470 gen_load_fpr64(ctx, fp1, ft);
David 'Digit' Turner87350d12014-04-03 15:44:48 +02006471 gen_helper_float_mul_d(fp0, cpu_env, fp0, fp1);
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08006472 tcg_temp_free_i64(fp1);
6473 gen_store_fpr64(ctx, fp0, fd);
6474 tcg_temp_free_i64(fp0);
6475 }
6476 opn = "mul.d";
6477 optype = BINOP;
6478 break;
6479 case FOP(3, 17):
6480 check_cp1_registers(ctx, fs | ft | fd);
6481 {
6482 TCGv_i64 fp0 = tcg_temp_new_i64();
6483 TCGv_i64 fp1 = tcg_temp_new_i64();
6484
6485 gen_load_fpr64(ctx, fp0, fs);
6486 gen_load_fpr64(ctx, fp1, ft);
David 'Digit' Turner87350d12014-04-03 15:44:48 +02006487 gen_helper_float_div_d(fp0, cpu_env, fp0, fp1);
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08006488 tcg_temp_free_i64(fp1);
6489 gen_store_fpr64(ctx, fp0, fd);
6490 tcg_temp_free_i64(fp0);
6491 }
6492 opn = "div.d";
6493 optype = BINOP;
6494 break;
6495 case FOP(4, 17):
6496 check_cp1_registers(ctx, fs | fd);
6497 {
6498 TCGv_i64 fp0 = tcg_temp_new_i64();
6499
6500 gen_load_fpr64(ctx, fp0, fs);
David 'Digit' Turner87350d12014-04-03 15:44:48 +02006501 gen_helper_float_sqrt_d(fp0, cpu_env, fp0);
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08006502 gen_store_fpr64(ctx, fp0, fd);
6503 tcg_temp_free_i64(fp0);
6504 }
6505 opn = "sqrt.d";
6506 break;
6507 case FOP(5, 17):
6508 check_cp1_registers(ctx, fs | fd);
6509 {
6510 TCGv_i64 fp0 = tcg_temp_new_i64();
6511
6512 gen_load_fpr64(ctx, fp0, fs);
6513 gen_helper_float_abs_d(fp0, fp0);
6514 gen_store_fpr64(ctx, fp0, fd);
6515 tcg_temp_free_i64(fp0);
6516 }
6517 opn = "abs.d";
6518 break;
6519 case FOP(6, 17):
6520 check_cp1_registers(ctx, fs | fd);
6521 {
6522 TCGv_i64 fp0 = tcg_temp_new_i64();
6523
6524 gen_load_fpr64(ctx, fp0, fs);
6525 gen_store_fpr64(ctx, fp0, fd);
6526 tcg_temp_free_i64(fp0);
6527 }
6528 opn = "mov.d";
6529 break;
6530 case FOP(7, 17):
6531 check_cp1_registers(ctx, fs | fd);
6532 {
6533 TCGv_i64 fp0 = tcg_temp_new_i64();
6534
6535 gen_load_fpr64(ctx, fp0, fs);
6536 gen_helper_float_chs_d(fp0, fp0);
6537 gen_store_fpr64(ctx, fp0, fd);
6538 tcg_temp_free_i64(fp0);
6539 }
6540 opn = "neg.d";
6541 break;
6542 case FOP(8, 17):
6543 check_cp1_64bitmode(ctx);
6544 {
6545 TCGv_i64 fp0 = tcg_temp_new_i64();
6546
6547 gen_load_fpr64(ctx, fp0, fs);
David 'Digit' Turner87350d12014-04-03 15:44:48 +02006548 gen_helper_float_roundl_d(fp0, cpu_env, fp0);
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08006549 gen_store_fpr64(ctx, fp0, fd);
6550 tcg_temp_free_i64(fp0);
6551 }
6552 opn = "round.l.d";
6553 break;
6554 case FOP(9, 17):
6555 check_cp1_64bitmode(ctx);
6556 {
6557 TCGv_i64 fp0 = tcg_temp_new_i64();
6558
6559 gen_load_fpr64(ctx, fp0, fs);
David 'Digit' Turner87350d12014-04-03 15:44:48 +02006560 gen_helper_float_truncl_d(fp0, cpu_env, fp0);
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08006561 gen_store_fpr64(ctx, fp0, fd);
6562 tcg_temp_free_i64(fp0);
6563 }
6564 opn = "trunc.l.d";
6565 break;
6566 case FOP(10, 17):
6567 check_cp1_64bitmode(ctx);
6568 {
6569 TCGv_i64 fp0 = tcg_temp_new_i64();
6570
6571 gen_load_fpr64(ctx, fp0, fs);
David 'Digit' Turner87350d12014-04-03 15:44:48 +02006572 gen_helper_float_ceill_d(fp0, cpu_env, fp0);
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08006573 gen_store_fpr64(ctx, fp0, fd);
6574 tcg_temp_free_i64(fp0);
6575 }
6576 opn = "ceil.l.d";
6577 break;
6578 case FOP(11, 17):
6579 check_cp1_64bitmode(ctx);
6580 {
6581 TCGv_i64 fp0 = tcg_temp_new_i64();
6582
6583 gen_load_fpr64(ctx, fp0, fs);
David 'Digit' Turner87350d12014-04-03 15:44:48 +02006584 gen_helper_float_floorl_d(fp0, cpu_env, fp0);
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08006585 gen_store_fpr64(ctx, fp0, fd);
6586 tcg_temp_free_i64(fp0);
6587 }
6588 opn = "floor.l.d";
6589 break;
6590 case FOP(12, 17):
6591 check_cp1_registers(ctx, fs);
6592 {
6593 TCGv_i32 fp32 = tcg_temp_new_i32();
6594 TCGv_i64 fp64 = tcg_temp_new_i64();
6595
6596 gen_load_fpr64(ctx, fp64, fs);
David 'Digit' Turner87350d12014-04-03 15:44:48 +02006597 gen_helper_float_roundw_d(fp32, cpu_env, fp64);
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08006598 tcg_temp_free_i64(fp64);
6599 gen_store_fpr32(fp32, fd);
6600 tcg_temp_free_i32(fp32);
6601 }
6602 opn = "round.w.d";
6603 break;
6604 case FOP(13, 17):
6605 check_cp1_registers(ctx, fs);
6606 {
6607 TCGv_i32 fp32 = tcg_temp_new_i32();
6608 TCGv_i64 fp64 = tcg_temp_new_i64();
6609
6610 gen_load_fpr64(ctx, fp64, fs);
David 'Digit' Turner87350d12014-04-03 15:44:48 +02006611 gen_helper_float_truncw_d(fp32, cpu_env, fp64);
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08006612 tcg_temp_free_i64(fp64);
6613 gen_store_fpr32(fp32, fd);
6614 tcg_temp_free_i32(fp32);
6615 }
6616 opn = "trunc.w.d";
6617 break;
6618 case FOP(14, 17):
6619 check_cp1_registers(ctx, fs);
6620 {
6621 TCGv_i32 fp32 = tcg_temp_new_i32();
6622 TCGv_i64 fp64 = tcg_temp_new_i64();
6623
6624 gen_load_fpr64(ctx, fp64, fs);
David 'Digit' Turner87350d12014-04-03 15:44:48 +02006625 gen_helper_float_ceilw_d(fp32, cpu_env, fp64);
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08006626 tcg_temp_free_i64(fp64);
6627 gen_store_fpr32(fp32, fd);
6628 tcg_temp_free_i32(fp32);
6629 }
6630 opn = "ceil.w.d";
6631 break;
6632 case FOP(15, 17):
6633 check_cp1_registers(ctx, fs);
6634 {
6635 TCGv_i32 fp32 = tcg_temp_new_i32();
6636 TCGv_i64 fp64 = tcg_temp_new_i64();
6637
6638 gen_load_fpr64(ctx, fp64, fs);
David 'Digit' Turner87350d12014-04-03 15:44:48 +02006639 gen_helper_float_floorw_d(fp32, cpu_env, fp64);
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08006640 tcg_temp_free_i64(fp64);
6641 gen_store_fpr32(fp32, fd);
6642 tcg_temp_free_i32(fp32);
6643 }
6644 opn = "floor.w.d";
6645 break;
6646 case FOP(17, 17):
6647 gen_movcf_d(ctx, fs, fd, (ft >> 2) & 0x7, ft & 0x1);
6648 opn = "movcf.d";
6649 break;
6650 case FOP(18, 17):
6651 {
6652 int l1 = gen_new_label();
6653 TCGv_i64 fp0;
6654
6655 if (ft != 0) {
6656 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[ft], 0, l1);
6657 }
6658 fp0 = tcg_temp_new_i64();
6659 gen_load_fpr64(ctx, fp0, fs);
6660 gen_store_fpr64(ctx, fp0, fd);
6661 tcg_temp_free_i64(fp0);
6662 gen_set_label(l1);
6663 }
6664 opn = "movz.d";
6665 break;
6666 case FOP(19, 17):
6667 {
6668 int l1 = gen_new_label();
6669 TCGv_i64 fp0;
6670
6671 if (ft != 0) {
6672 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[ft], 0, l1);
6673 fp0 = tcg_temp_new_i64();
6674 gen_load_fpr64(ctx, fp0, fs);
6675 gen_store_fpr64(ctx, fp0, fd);
6676 tcg_temp_free_i64(fp0);
6677 gen_set_label(l1);
6678 }
6679 }
6680 opn = "movn.d";
6681 break;
6682 case FOP(21, 17):
6683 check_cp1_64bitmode(ctx);
6684 {
6685 TCGv_i64 fp0 = tcg_temp_new_i64();
6686
6687 gen_load_fpr64(ctx, fp0, fs);
David 'Digit' Turner87350d12014-04-03 15:44:48 +02006688 gen_helper_float_recip_d(fp0, cpu_env, fp0);
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08006689 gen_store_fpr64(ctx, fp0, fd);
6690 tcg_temp_free_i64(fp0);
6691 }
6692 opn = "recip.d";
6693 break;
6694 case FOP(22, 17):
6695 check_cp1_64bitmode(ctx);
6696 {
6697 TCGv_i64 fp0 = tcg_temp_new_i64();
6698
6699 gen_load_fpr64(ctx, fp0, fs);
David 'Digit' Turner87350d12014-04-03 15:44:48 +02006700 gen_helper_float_rsqrt_d(fp0, cpu_env, fp0);
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08006701 gen_store_fpr64(ctx, fp0, fd);
6702 tcg_temp_free_i64(fp0);
6703 }
6704 opn = "rsqrt.d";
6705 break;
6706 case FOP(28, 17):
6707 check_cp1_64bitmode(ctx);
6708 {
6709 TCGv_i64 fp0 = tcg_temp_new_i64();
6710 TCGv_i64 fp1 = tcg_temp_new_i64();
6711
6712 gen_load_fpr64(ctx, fp0, fs);
6713 gen_load_fpr64(ctx, fp1, ft);
David 'Digit' Turner87350d12014-04-03 15:44:48 +02006714 gen_helper_float_recip2_d(fp0, cpu_env, fp0, fp1);
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08006715 tcg_temp_free_i64(fp1);
6716 gen_store_fpr64(ctx, fp0, fd);
6717 tcg_temp_free_i64(fp0);
6718 }
6719 opn = "recip2.d";
6720 break;
6721 case FOP(29, 17):
6722 check_cp1_64bitmode(ctx);
6723 {
6724 TCGv_i64 fp0 = tcg_temp_new_i64();
6725
6726 gen_load_fpr64(ctx, fp0, fs);
David 'Digit' Turner87350d12014-04-03 15:44:48 +02006727 gen_helper_float_recip1_d(fp0, cpu_env, fp0);
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08006728 gen_store_fpr64(ctx, fp0, fd);
6729 tcg_temp_free_i64(fp0);
6730 }
6731 opn = "recip1.d";
6732 break;
6733 case FOP(30, 17):
6734 check_cp1_64bitmode(ctx);
6735 {
6736 TCGv_i64 fp0 = tcg_temp_new_i64();
6737
6738 gen_load_fpr64(ctx, fp0, fs);
David 'Digit' Turner87350d12014-04-03 15:44:48 +02006739 gen_helper_float_rsqrt1_d(fp0, cpu_env, fp0);
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08006740 gen_store_fpr64(ctx, fp0, fd);
6741 tcg_temp_free_i64(fp0);
6742 }
6743 opn = "rsqrt1.d";
6744 break;
6745 case FOP(31, 17):
6746 check_cp1_64bitmode(ctx);
6747 {
6748 TCGv_i64 fp0 = tcg_temp_new_i64();
6749 TCGv_i64 fp1 = tcg_temp_new_i64();
6750
6751 gen_load_fpr64(ctx, fp0, fs);
6752 gen_load_fpr64(ctx, fp1, ft);
David 'Digit' Turner87350d12014-04-03 15:44:48 +02006753 gen_helper_float_rsqrt2_d(fp0, cpu_env, fp0, fp1);
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08006754 tcg_temp_free_i64(fp1);
6755 gen_store_fpr64(ctx, fp0, fd);
6756 tcg_temp_free_i64(fp0);
6757 }
6758 opn = "rsqrt2.d";
6759 break;
6760 case FOP(48, 17):
6761 case FOP(49, 17):
6762 case FOP(50, 17):
6763 case FOP(51, 17):
6764 case FOP(52, 17):
6765 case FOP(53, 17):
6766 case FOP(54, 17):
6767 case FOP(55, 17):
6768 case FOP(56, 17):
6769 case FOP(57, 17):
6770 case FOP(58, 17):
6771 case FOP(59, 17):
6772 case FOP(60, 17):
6773 case FOP(61, 17):
6774 case FOP(62, 17):
6775 case FOP(63, 17):
6776 {
6777 TCGv_i64 fp0 = tcg_temp_new_i64();
6778 TCGv_i64 fp1 = tcg_temp_new_i64();
6779
6780 gen_load_fpr64(ctx, fp0, fs);
6781 gen_load_fpr64(ctx, fp1, ft);
6782 if (ctx->opcode & (1 << 6)) {
6783 check_cop1x(ctx);
6784 check_cp1_registers(ctx, fs | ft);
6785 gen_cmpabs_d(func-48, fp0, fp1, cc);
6786 opn = condnames_abs[func-48];
6787 } else {
6788 check_cp1_registers(ctx, fs | ft);
6789 gen_cmp_d(func-48, fp0, fp1, cc);
6790 opn = condnames[func-48];
6791 }
6792 tcg_temp_free_i64(fp0);
6793 tcg_temp_free_i64(fp1);
6794 }
6795 break;
6796 case FOP(32, 17):
6797 check_cp1_registers(ctx, fs);
6798 {
6799 TCGv_i32 fp32 = tcg_temp_new_i32();
6800 TCGv_i64 fp64 = tcg_temp_new_i64();
6801
6802 gen_load_fpr64(ctx, fp64, fs);
David 'Digit' Turner87350d12014-04-03 15:44:48 +02006803 gen_helper_float_cvts_d(fp32, cpu_env, fp64);
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08006804 tcg_temp_free_i64(fp64);
6805 gen_store_fpr32(fp32, fd);
6806 tcg_temp_free_i32(fp32);
6807 }
6808 opn = "cvt.s.d";
6809 break;
6810 case FOP(36, 17):
6811 check_cp1_registers(ctx, fs);
6812 {
6813 TCGv_i32 fp32 = tcg_temp_new_i32();
6814 TCGv_i64 fp64 = tcg_temp_new_i64();
6815
6816 gen_load_fpr64(ctx, fp64, fs);
David 'Digit' Turner87350d12014-04-03 15:44:48 +02006817 gen_helper_float_cvtw_d(fp32, cpu_env, fp64);
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08006818 tcg_temp_free_i64(fp64);
6819 gen_store_fpr32(fp32, fd);
6820 tcg_temp_free_i32(fp32);
6821 }
6822 opn = "cvt.w.d";
6823 break;
6824 case FOP(37, 17):
6825 check_cp1_64bitmode(ctx);
6826 {
6827 TCGv_i64 fp0 = tcg_temp_new_i64();
6828
6829 gen_load_fpr64(ctx, fp0, fs);
David 'Digit' Turner87350d12014-04-03 15:44:48 +02006830 gen_helper_float_cvtl_d(fp0, cpu_env, fp0);
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08006831 gen_store_fpr64(ctx, fp0, fd);
6832 tcg_temp_free_i64(fp0);
6833 }
6834 opn = "cvt.l.d";
6835 break;
6836 case FOP(32, 20):
6837 {
6838 TCGv_i32 fp0 = tcg_temp_new_i32();
6839
6840 gen_load_fpr32(fp0, fs);
David 'Digit' Turner87350d12014-04-03 15:44:48 +02006841 gen_helper_float_cvts_w(fp0, cpu_env, fp0);
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08006842 gen_store_fpr32(fp0, fd);
6843 tcg_temp_free_i32(fp0);
6844 }
6845 opn = "cvt.s.w";
6846 break;
6847 case FOP(33, 20):
6848 check_cp1_registers(ctx, fd);
6849 {
6850 TCGv_i32 fp32 = tcg_temp_new_i32();
6851 TCGv_i64 fp64 = tcg_temp_new_i64();
6852
6853 gen_load_fpr32(fp32, fs);
David 'Digit' Turner87350d12014-04-03 15:44:48 +02006854 gen_helper_float_cvtd_w(fp64, cpu_env, fp32);
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08006855 tcg_temp_free_i32(fp32);
6856 gen_store_fpr64(ctx, fp64, fd);
6857 tcg_temp_free_i64(fp64);
6858 }
6859 opn = "cvt.d.w";
6860 break;
6861 case FOP(32, 21):
6862 check_cp1_64bitmode(ctx);
6863 {
6864 TCGv_i32 fp32 = tcg_temp_new_i32();
6865 TCGv_i64 fp64 = tcg_temp_new_i64();
6866
6867 gen_load_fpr64(ctx, fp64, fs);
David 'Digit' Turner87350d12014-04-03 15:44:48 +02006868 gen_helper_float_cvts_l(fp32, cpu_env, fp64);
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08006869 tcg_temp_free_i64(fp64);
6870 gen_store_fpr32(fp32, fd);
6871 tcg_temp_free_i32(fp32);
6872 }
6873 opn = "cvt.s.l";
6874 break;
6875 case FOP(33, 21):
6876 check_cp1_64bitmode(ctx);
6877 {
6878 TCGv_i64 fp0 = tcg_temp_new_i64();
6879
6880 gen_load_fpr64(ctx, fp0, fs);
David 'Digit' Turner87350d12014-04-03 15:44:48 +02006881 gen_helper_float_cvtd_l(fp0, cpu_env, fp0);
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08006882 gen_store_fpr64(ctx, fp0, fd);
6883 tcg_temp_free_i64(fp0);
6884 }
6885 opn = "cvt.d.l";
6886 break;
6887 case FOP(38, 20):
6888 check_cp1_64bitmode(ctx);
6889 {
6890 TCGv_i64 fp0 = tcg_temp_new_i64();
6891
6892 gen_load_fpr64(ctx, fp0, fs);
David 'Digit' Turner87350d12014-04-03 15:44:48 +02006893 gen_helper_float_cvtps_pw(fp0, cpu_env, fp0);
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08006894 gen_store_fpr64(ctx, fp0, fd);
6895 tcg_temp_free_i64(fp0);
6896 }
6897 opn = "cvt.ps.pw";
6898 break;
6899 case FOP(0, 22):
6900 check_cp1_64bitmode(ctx);
6901 {
6902 TCGv_i64 fp0 = tcg_temp_new_i64();
6903 TCGv_i64 fp1 = tcg_temp_new_i64();
6904
6905 gen_load_fpr64(ctx, fp0, fs);
6906 gen_load_fpr64(ctx, fp1, ft);
David 'Digit' Turner87350d12014-04-03 15:44:48 +02006907 gen_helper_float_add_ps(fp0, cpu_env, fp0, fp1);
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08006908 tcg_temp_free_i64(fp1);
6909 gen_store_fpr64(ctx, fp0, fd);
6910 tcg_temp_free_i64(fp0);
6911 }
6912 opn = "add.ps";
6913 break;
6914 case FOP(1, 22):
6915 check_cp1_64bitmode(ctx);
6916 {
6917 TCGv_i64 fp0 = tcg_temp_new_i64();
6918 TCGv_i64 fp1 = tcg_temp_new_i64();
6919
6920 gen_load_fpr64(ctx, fp0, fs);
6921 gen_load_fpr64(ctx, fp1, ft);
David 'Digit' Turner87350d12014-04-03 15:44:48 +02006922 gen_helper_float_sub_ps(fp0, cpu_env, fp0, fp1);
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08006923 tcg_temp_free_i64(fp1);
6924 gen_store_fpr64(ctx, fp0, fd);
6925 tcg_temp_free_i64(fp0);
6926 }
6927 opn = "sub.ps";
6928 break;
6929 case FOP(2, 22):
6930 check_cp1_64bitmode(ctx);
6931 {
6932 TCGv_i64 fp0 = tcg_temp_new_i64();
6933 TCGv_i64 fp1 = tcg_temp_new_i64();
6934
6935 gen_load_fpr64(ctx, fp0, fs);
6936 gen_load_fpr64(ctx, fp1, ft);
David 'Digit' Turner87350d12014-04-03 15:44:48 +02006937 gen_helper_float_mul_ps(fp0, cpu_env, fp0, fp1);
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08006938 tcg_temp_free_i64(fp1);
6939 gen_store_fpr64(ctx, fp0, fd);
6940 tcg_temp_free_i64(fp0);
6941 }
6942 opn = "mul.ps";
6943 break;
6944 case FOP(5, 22):
6945 check_cp1_64bitmode(ctx);
6946 {
6947 TCGv_i64 fp0 = tcg_temp_new_i64();
6948
6949 gen_load_fpr64(ctx, fp0, fs);
6950 gen_helper_float_abs_ps(fp0, fp0);
6951 gen_store_fpr64(ctx, fp0, fd);
6952 tcg_temp_free_i64(fp0);
6953 }
6954 opn = "abs.ps";
6955 break;
6956 case FOP(6, 22):
6957 check_cp1_64bitmode(ctx);
6958 {
6959 TCGv_i64 fp0 = tcg_temp_new_i64();
6960
6961 gen_load_fpr64(ctx, fp0, fs);
6962 gen_store_fpr64(ctx, fp0, fd);
6963 tcg_temp_free_i64(fp0);
6964 }
6965 opn = "mov.ps";
6966 break;
6967 case FOP(7, 22):
6968 check_cp1_64bitmode(ctx);
6969 {
6970 TCGv_i64 fp0 = tcg_temp_new_i64();
6971
6972 gen_load_fpr64(ctx, fp0, fs);
6973 gen_helper_float_chs_ps(fp0, fp0);
6974 gen_store_fpr64(ctx, fp0, fd);
6975 tcg_temp_free_i64(fp0);
6976 }
6977 opn = "neg.ps";
6978 break;
6979 case FOP(17, 22):
6980 check_cp1_64bitmode(ctx);
6981 gen_movcf_ps(fs, fd, (ft >> 2) & 0x7, ft & 0x1);
6982 opn = "movcf.ps";
6983 break;
6984 case FOP(18, 22):
6985 check_cp1_64bitmode(ctx);
6986 {
6987 int l1 = gen_new_label();
6988 TCGv_i64 fp0;
6989
6990 if (ft != 0)
6991 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[ft], 0, l1);
6992 fp0 = tcg_temp_new_i64();
6993 gen_load_fpr64(ctx, fp0, fs);
6994 gen_store_fpr64(ctx, fp0, fd);
6995 tcg_temp_free_i64(fp0);
6996 gen_set_label(l1);
6997 }
6998 opn = "movz.ps";
6999 break;
7000 case FOP(19, 22):
7001 check_cp1_64bitmode(ctx);
7002 {
7003 int l1 = gen_new_label();
7004 TCGv_i64 fp0;
7005
7006 if (ft != 0) {
7007 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[ft], 0, l1);
7008 fp0 = tcg_temp_new_i64();
7009 gen_load_fpr64(ctx, fp0, fs);
7010 gen_store_fpr64(ctx, fp0, fd);
7011 tcg_temp_free_i64(fp0);
7012 gen_set_label(l1);
7013 }
7014 }
7015 opn = "movn.ps";
7016 break;
7017 case FOP(24, 22):
7018 check_cp1_64bitmode(ctx);
7019 {
7020 TCGv_i64 fp0 = tcg_temp_new_i64();
7021 TCGv_i64 fp1 = tcg_temp_new_i64();
7022
7023 gen_load_fpr64(ctx, fp0, ft);
7024 gen_load_fpr64(ctx, fp1, fs);
David 'Digit' Turner87350d12014-04-03 15:44:48 +02007025 gen_helper_float_addr_ps(fp0, cpu_env, fp0, fp1);
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08007026 tcg_temp_free_i64(fp1);
7027 gen_store_fpr64(ctx, fp0, fd);
7028 tcg_temp_free_i64(fp0);
7029 }
7030 opn = "addr.ps";
7031 break;
7032 case FOP(26, 22):
7033 check_cp1_64bitmode(ctx);
7034 {
7035 TCGv_i64 fp0 = tcg_temp_new_i64();
7036 TCGv_i64 fp1 = tcg_temp_new_i64();
7037
7038 gen_load_fpr64(ctx, fp0, ft);
7039 gen_load_fpr64(ctx, fp1, fs);
David 'Digit' Turner87350d12014-04-03 15:44:48 +02007040 gen_helper_float_mulr_ps(fp0, cpu_env, fp0, fp1);
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08007041 tcg_temp_free_i64(fp1);
7042 gen_store_fpr64(ctx, fp0, fd);
7043 tcg_temp_free_i64(fp0);
7044 }
7045 opn = "mulr.ps";
7046 break;
7047 case FOP(28, 22):
7048 check_cp1_64bitmode(ctx);
7049 {
7050 TCGv_i64 fp0 = tcg_temp_new_i64();
7051 TCGv_i64 fp1 = tcg_temp_new_i64();
7052
7053 gen_load_fpr64(ctx, fp0, fs);
7054 gen_load_fpr64(ctx, fp1, fd);
David 'Digit' Turner87350d12014-04-03 15:44:48 +02007055 gen_helper_float_recip2_ps(fp0, cpu_env, fp0, fp1);
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08007056 tcg_temp_free_i64(fp1);
7057 gen_store_fpr64(ctx, fp0, fd);
7058 tcg_temp_free_i64(fp0);
7059 }
7060 opn = "recip2.ps";
7061 break;
7062 case FOP(29, 22):
7063 check_cp1_64bitmode(ctx);
7064 {
7065 TCGv_i64 fp0 = tcg_temp_new_i64();
7066
7067 gen_load_fpr64(ctx, fp0, fs);
David 'Digit' Turner87350d12014-04-03 15:44:48 +02007068 gen_helper_float_recip1_ps(fp0, cpu_env, fp0);
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08007069 gen_store_fpr64(ctx, fp0, fd);
7070 tcg_temp_free_i64(fp0);
7071 }
7072 opn = "recip1.ps";
7073 break;
7074 case FOP(30, 22):
7075 check_cp1_64bitmode(ctx);
7076 {
7077 TCGv_i64 fp0 = tcg_temp_new_i64();
7078
7079 gen_load_fpr64(ctx, fp0, fs);
David 'Digit' Turner87350d12014-04-03 15:44:48 +02007080 gen_helper_float_rsqrt1_ps(fp0, cpu_env, fp0);
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08007081 gen_store_fpr64(ctx, fp0, fd);
7082 tcg_temp_free_i64(fp0);
7083 }
7084 opn = "rsqrt1.ps";
7085 break;
7086 case FOP(31, 22):
7087 check_cp1_64bitmode(ctx);
7088 {
7089 TCGv_i64 fp0 = tcg_temp_new_i64();
7090 TCGv_i64 fp1 = tcg_temp_new_i64();
7091
7092 gen_load_fpr64(ctx, fp0, fs);
7093 gen_load_fpr64(ctx, fp1, ft);
David 'Digit' Turner87350d12014-04-03 15:44:48 +02007094 gen_helper_float_rsqrt2_ps(fp0, cpu_env, fp0, fp1);
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08007095 tcg_temp_free_i64(fp1);
7096 gen_store_fpr64(ctx, fp0, fd);
7097 tcg_temp_free_i64(fp0);
7098 }
7099 opn = "rsqrt2.ps";
7100 break;
7101 case FOP(32, 22):
7102 check_cp1_64bitmode(ctx);
7103 {
7104 TCGv_i32 fp0 = tcg_temp_new_i32();
7105
7106 gen_load_fpr32h(fp0, fs);
David 'Digit' Turner87350d12014-04-03 15:44:48 +02007107 gen_helper_float_cvts_pu(fp0, cpu_env, fp0);
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08007108 gen_store_fpr32(fp0, fd);
7109 tcg_temp_free_i32(fp0);
7110 }
7111 opn = "cvt.s.pu";
7112 break;
7113 case FOP(36, 22):
7114 check_cp1_64bitmode(ctx);
7115 {
7116 TCGv_i64 fp0 = tcg_temp_new_i64();
7117
7118 gen_load_fpr64(ctx, fp0, fs);
David 'Digit' Turner87350d12014-04-03 15:44:48 +02007119 gen_helper_float_cvtpw_ps(fp0, cpu_env, fp0);
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08007120 gen_store_fpr64(ctx, fp0, fd);
7121 tcg_temp_free_i64(fp0);
7122 }
7123 opn = "cvt.pw.ps";
7124 break;
7125 case FOP(40, 22):
7126 check_cp1_64bitmode(ctx);
7127 {
7128 TCGv_i32 fp0 = tcg_temp_new_i32();
7129
7130 gen_load_fpr32(fp0, fs);
David 'Digit' Turner87350d12014-04-03 15:44:48 +02007131 gen_helper_float_cvts_pl(fp0, cpu_env, fp0);
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08007132 gen_store_fpr32(fp0, fd);
7133 tcg_temp_free_i32(fp0);
7134 }
7135 opn = "cvt.s.pl";
7136 break;
7137 case FOP(44, 22):
7138 check_cp1_64bitmode(ctx);
7139 {
7140 TCGv_i32 fp0 = tcg_temp_new_i32();
7141 TCGv_i32 fp1 = tcg_temp_new_i32();
7142
7143 gen_load_fpr32(fp0, fs);
7144 gen_load_fpr32(fp1, ft);
7145 gen_store_fpr32h(fp0, fd);
7146 gen_store_fpr32(fp1, fd);
7147 tcg_temp_free_i32(fp0);
7148 tcg_temp_free_i32(fp1);
7149 }
7150 opn = "pll.ps";
7151 break;
7152 case FOP(45, 22):
7153 check_cp1_64bitmode(ctx);
7154 {
7155 TCGv_i32 fp0 = tcg_temp_new_i32();
7156 TCGv_i32 fp1 = tcg_temp_new_i32();
7157
7158 gen_load_fpr32(fp0, fs);
7159 gen_load_fpr32h(fp1, ft);
7160 gen_store_fpr32(fp1, fd);
7161 gen_store_fpr32h(fp0, fd);
7162 tcg_temp_free_i32(fp0);
7163 tcg_temp_free_i32(fp1);
7164 }
7165 opn = "plu.ps";
7166 break;
7167 case FOP(46, 22):
7168 check_cp1_64bitmode(ctx);
7169 {
7170 TCGv_i32 fp0 = tcg_temp_new_i32();
7171 TCGv_i32 fp1 = tcg_temp_new_i32();
7172
7173 gen_load_fpr32h(fp0, fs);
7174 gen_load_fpr32(fp1, ft);
7175 gen_store_fpr32(fp1, fd);
7176 gen_store_fpr32h(fp0, fd);
7177 tcg_temp_free_i32(fp0);
7178 tcg_temp_free_i32(fp1);
7179 }
7180 opn = "pul.ps";
7181 break;
7182 case FOP(47, 22):
7183 check_cp1_64bitmode(ctx);
7184 {
7185 TCGv_i32 fp0 = tcg_temp_new_i32();
7186 TCGv_i32 fp1 = tcg_temp_new_i32();
7187
7188 gen_load_fpr32h(fp0, fs);
7189 gen_load_fpr32h(fp1, ft);
7190 gen_store_fpr32(fp1, fd);
7191 gen_store_fpr32h(fp0, fd);
7192 tcg_temp_free_i32(fp0);
7193 tcg_temp_free_i32(fp1);
7194 }
7195 opn = "puu.ps";
7196 break;
7197 case FOP(48, 22):
7198 case FOP(49, 22):
7199 case FOP(50, 22):
7200 case FOP(51, 22):
7201 case FOP(52, 22):
7202 case FOP(53, 22):
7203 case FOP(54, 22):
7204 case FOP(55, 22):
7205 case FOP(56, 22):
7206 case FOP(57, 22):
7207 case FOP(58, 22):
7208 case FOP(59, 22):
7209 case FOP(60, 22):
7210 case FOP(61, 22):
7211 case FOP(62, 22):
7212 case FOP(63, 22):
7213 check_cp1_64bitmode(ctx);
7214 {
7215 TCGv_i64 fp0 = tcg_temp_new_i64();
7216 TCGv_i64 fp1 = tcg_temp_new_i64();
7217
7218 gen_load_fpr64(ctx, fp0, fs);
7219 gen_load_fpr64(ctx, fp1, ft);
7220 if (ctx->opcode & (1 << 6)) {
7221 gen_cmpabs_ps(func-48, fp0, fp1, cc);
7222 opn = condnames_abs[func-48];
7223 } else {
7224 gen_cmp_ps(func-48, fp0, fp1, cc);
7225 opn = condnames[func-48];
7226 }
7227 tcg_temp_free_i64(fp0);
7228 tcg_temp_free_i64(fp1);
7229 }
7230 break;
7231 default:
7232 MIPS_INVAL(opn);
7233 generate_exception (ctx, EXCP_RI);
7234 return;
7235 }
7236 switch (optype) {
7237 case BINOP:
7238 MIPS_DEBUG("%s %s, %s, %s", opn, fregnames[fd], fregnames[fs], fregnames[ft]);
7239 break;
7240 case CMPOP:
7241 MIPS_DEBUG("%s %s,%s", opn, fregnames[fs], fregnames[ft]);
7242 break;
7243 default:
7244 MIPS_DEBUG("%s %s,%s", opn, fregnames[fd], fregnames[fs]);
7245 break;
7246 }
7247}
7248
7249/* Coprocessor 3 (FPU) */
7250static void gen_flt3_ldst (DisasContext *ctx, uint32_t opc,
7251 int fd, int fs, int base, int index)
7252{
David 'Digit' Turnera2c14f92014-02-04 01:02:30 +01007253 const char* __attribute__((unused)) opn = "extended float load/store";
7254 int __attribute__((unused)) store = 0;
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08007255 TCGv t0 = tcg_temp_new();
7256
7257 if (base == 0) {
7258 gen_load_gpr(t0, index);
7259 } else if (index == 0) {
7260 gen_load_gpr(t0, base);
7261 } else {
7262 gen_load_gpr(t0, index);
7263 gen_op_addr_add(ctx, t0, cpu_gpr[base], t0);
7264 }
7265 /* Don't do NOP if destination is zero: we must perform the actual
7266 memory access. */
7267 save_cpu_state(ctx, 0);
7268 switch (opc) {
7269 case OPC_LWXC1:
7270 check_cop1x(ctx);
7271 {
7272 TCGv_i32 fp0 = tcg_temp_new_i32();
7273
7274 tcg_gen_qemu_ld32s(t0, t0, ctx->mem_idx);
7275 tcg_gen_trunc_tl_i32(fp0, t0);
7276 gen_store_fpr32(fp0, fd);
7277 tcg_temp_free_i32(fp0);
7278 }
7279 opn = "lwxc1";
7280 break;
7281 case OPC_LDXC1:
7282 check_cop1x(ctx);
7283 check_cp1_registers(ctx, fd);
7284 {
7285 TCGv_i64 fp0 = tcg_temp_new_i64();
7286
7287 tcg_gen_qemu_ld64(fp0, t0, ctx->mem_idx);
7288 gen_store_fpr64(ctx, fp0, fd);
7289 tcg_temp_free_i64(fp0);
7290 }
7291 opn = "ldxc1";
7292 break;
7293 case OPC_LUXC1:
7294 check_cp1_64bitmode(ctx);
7295 tcg_gen_andi_tl(t0, t0, ~0x7);
7296 {
7297 TCGv_i64 fp0 = tcg_temp_new_i64();
7298
7299 tcg_gen_qemu_ld64(fp0, t0, ctx->mem_idx);
7300 gen_store_fpr64(ctx, fp0, fd);
7301 tcg_temp_free_i64(fp0);
7302 }
7303 opn = "luxc1";
7304 break;
7305 case OPC_SWXC1:
7306 check_cop1x(ctx);
7307 {
7308 TCGv_i32 fp0 = tcg_temp_new_i32();
7309 TCGv t1 = tcg_temp_new();
7310
7311 gen_load_fpr32(fp0, fs);
7312 tcg_gen_extu_i32_tl(t1, fp0);
7313 tcg_gen_qemu_st32(t1, t0, ctx->mem_idx);
7314 tcg_temp_free_i32(fp0);
7315 tcg_temp_free(t1);
7316 }
7317 opn = "swxc1";
7318 store = 1;
7319 break;
7320 case OPC_SDXC1:
7321 check_cop1x(ctx);
7322 check_cp1_registers(ctx, fs);
7323 {
7324 TCGv_i64 fp0 = tcg_temp_new_i64();
7325
7326 gen_load_fpr64(ctx, fp0, fs);
7327 tcg_gen_qemu_st64(fp0, t0, ctx->mem_idx);
7328 tcg_temp_free_i64(fp0);
7329 }
7330 opn = "sdxc1";
7331 store = 1;
7332 break;
7333 case OPC_SUXC1:
7334 check_cp1_64bitmode(ctx);
7335 tcg_gen_andi_tl(t0, t0, ~0x7);
7336 {
7337 TCGv_i64 fp0 = tcg_temp_new_i64();
7338
7339 gen_load_fpr64(ctx, fp0, fs);
7340 tcg_gen_qemu_st64(fp0, t0, ctx->mem_idx);
7341 tcg_temp_free_i64(fp0);
7342 }
7343 opn = "suxc1";
7344 store = 1;
7345 break;
7346 }
7347 tcg_temp_free(t0);
7348 MIPS_DEBUG("%s %s, %s(%s)", opn, fregnames[store ? fs : fd],
7349 regnames[index], regnames[base]);
7350}
7351
7352static void gen_flt3_arith (DisasContext *ctx, uint32_t opc,
7353 int fd, int fr, int fs, int ft)
7354{
David 'Digit' Turnera2c14f92014-02-04 01:02:30 +01007355 const char* __attribute__((unused)) opn = "flt3_arith";
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08007356
7357 switch (opc) {
7358 case OPC_ALNV_PS:
7359 check_cp1_64bitmode(ctx);
7360 {
7361 TCGv t0 = tcg_temp_local_new();
7362 TCGv_i32 fp = tcg_temp_new_i32();
7363 TCGv_i32 fph = tcg_temp_new_i32();
7364 int l1 = gen_new_label();
7365 int l2 = gen_new_label();
7366
7367 gen_load_gpr(t0, fr);
7368 tcg_gen_andi_tl(t0, t0, 0x7);
7369
7370 tcg_gen_brcondi_tl(TCG_COND_NE, t0, 0, l1);
7371 gen_load_fpr32(fp, fs);
7372 gen_load_fpr32h(fph, fs);
7373 gen_store_fpr32(fp, fd);
7374 gen_store_fpr32h(fph, fd);
7375 tcg_gen_br(l2);
7376 gen_set_label(l1);
7377 tcg_gen_brcondi_tl(TCG_COND_NE, t0, 4, l2);
7378 tcg_temp_free(t0);
7379#ifdef TARGET_WORDS_BIGENDIAN
7380 gen_load_fpr32(fp, fs);
7381 gen_load_fpr32h(fph, ft);
7382 gen_store_fpr32h(fp, fd);
7383 gen_store_fpr32(fph, fd);
7384#else
7385 gen_load_fpr32h(fph, fs);
7386 gen_load_fpr32(fp, ft);
7387 gen_store_fpr32(fph, fd);
7388 gen_store_fpr32h(fp, fd);
7389#endif
7390 gen_set_label(l2);
7391 tcg_temp_free_i32(fp);
7392 tcg_temp_free_i32(fph);
7393 }
7394 opn = "alnv.ps";
7395 break;
7396 case OPC_MADD_S:
7397 check_cop1x(ctx);
7398 {
7399 TCGv_i32 fp0 = tcg_temp_new_i32();
7400 TCGv_i32 fp1 = tcg_temp_new_i32();
7401 TCGv_i32 fp2 = tcg_temp_new_i32();
7402
7403 gen_load_fpr32(fp0, fs);
7404 gen_load_fpr32(fp1, ft);
7405 gen_load_fpr32(fp2, fr);
David 'Digit' Turner87350d12014-04-03 15:44:48 +02007406 gen_helper_float_muladd_s(fp2, cpu_env, fp0, fp1, fp2);
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08007407 tcg_temp_free_i32(fp0);
7408 tcg_temp_free_i32(fp1);
7409 gen_store_fpr32(fp2, fd);
7410 tcg_temp_free_i32(fp2);
7411 }
7412 opn = "madd.s";
7413 break;
7414 case OPC_MADD_D:
7415 check_cop1x(ctx);
7416 check_cp1_registers(ctx, fd | fs | ft | fr);
7417 {
7418 TCGv_i64 fp0 = tcg_temp_new_i64();
7419 TCGv_i64 fp1 = tcg_temp_new_i64();
7420 TCGv_i64 fp2 = tcg_temp_new_i64();
7421
7422 gen_load_fpr64(ctx, fp0, fs);
7423 gen_load_fpr64(ctx, fp1, ft);
7424 gen_load_fpr64(ctx, fp2, fr);
David 'Digit' Turner87350d12014-04-03 15:44:48 +02007425 gen_helper_float_muladd_d(fp2, cpu_env, fp0, fp1, fp2);
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08007426 tcg_temp_free_i64(fp0);
7427 tcg_temp_free_i64(fp1);
7428 gen_store_fpr64(ctx, fp2, fd);
7429 tcg_temp_free_i64(fp2);
7430 }
7431 opn = "madd.d";
7432 break;
7433 case OPC_MADD_PS:
7434 check_cp1_64bitmode(ctx);
7435 {
7436 TCGv_i64 fp0 = tcg_temp_new_i64();
7437 TCGv_i64 fp1 = tcg_temp_new_i64();
7438 TCGv_i64 fp2 = tcg_temp_new_i64();
7439
7440 gen_load_fpr64(ctx, fp0, fs);
7441 gen_load_fpr64(ctx, fp1, ft);
7442 gen_load_fpr64(ctx, fp2, fr);
David 'Digit' Turner87350d12014-04-03 15:44:48 +02007443 gen_helper_float_muladd_ps(fp2, cpu_env, fp0, fp1, fp2);
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08007444 tcg_temp_free_i64(fp0);
7445 tcg_temp_free_i64(fp1);
7446 gen_store_fpr64(ctx, fp2, fd);
7447 tcg_temp_free_i64(fp2);
7448 }
7449 opn = "madd.ps";
7450 break;
7451 case OPC_MSUB_S:
7452 check_cop1x(ctx);
7453 {
7454 TCGv_i32 fp0 = tcg_temp_new_i32();
7455 TCGv_i32 fp1 = tcg_temp_new_i32();
7456 TCGv_i32 fp2 = tcg_temp_new_i32();
7457
7458 gen_load_fpr32(fp0, fs);
7459 gen_load_fpr32(fp1, ft);
7460 gen_load_fpr32(fp2, fr);
David 'Digit' Turner87350d12014-04-03 15:44:48 +02007461 gen_helper_float_mulsub_s(fp2, cpu_env, fp0, fp1, fp2);
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08007462 tcg_temp_free_i32(fp0);
7463 tcg_temp_free_i32(fp1);
7464 gen_store_fpr32(fp2, fd);
7465 tcg_temp_free_i32(fp2);
7466 }
7467 opn = "msub.s";
7468 break;
7469 case OPC_MSUB_D:
7470 check_cop1x(ctx);
7471 check_cp1_registers(ctx, fd | fs | ft | fr);
7472 {
7473 TCGv_i64 fp0 = tcg_temp_new_i64();
7474 TCGv_i64 fp1 = tcg_temp_new_i64();
7475 TCGv_i64 fp2 = tcg_temp_new_i64();
7476
7477 gen_load_fpr64(ctx, fp0, fs);
7478 gen_load_fpr64(ctx, fp1, ft);
7479 gen_load_fpr64(ctx, fp2, fr);
David 'Digit' Turner87350d12014-04-03 15:44:48 +02007480 gen_helper_float_mulsub_d(fp2, cpu_env, fp0, fp1, fp2);
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08007481 tcg_temp_free_i64(fp0);
7482 tcg_temp_free_i64(fp1);
7483 gen_store_fpr64(ctx, fp2, fd);
7484 tcg_temp_free_i64(fp2);
7485 }
7486 opn = "msub.d";
7487 break;
7488 case OPC_MSUB_PS:
7489 check_cp1_64bitmode(ctx);
7490 {
7491 TCGv_i64 fp0 = tcg_temp_new_i64();
7492 TCGv_i64 fp1 = tcg_temp_new_i64();
7493 TCGv_i64 fp2 = tcg_temp_new_i64();
7494
7495 gen_load_fpr64(ctx, fp0, fs);
7496 gen_load_fpr64(ctx, fp1, ft);
7497 gen_load_fpr64(ctx, fp2, fr);
David 'Digit' Turner87350d12014-04-03 15:44:48 +02007498 gen_helper_float_mulsub_ps(fp2, cpu_env, fp0, fp1, fp2);
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08007499 tcg_temp_free_i64(fp0);
7500 tcg_temp_free_i64(fp1);
7501 gen_store_fpr64(ctx, fp2, fd);
7502 tcg_temp_free_i64(fp2);
7503 }
7504 opn = "msub.ps";
7505 break;
7506 case OPC_NMADD_S:
7507 check_cop1x(ctx);
7508 {
7509 TCGv_i32 fp0 = tcg_temp_new_i32();
7510 TCGv_i32 fp1 = tcg_temp_new_i32();
7511 TCGv_i32 fp2 = tcg_temp_new_i32();
7512
7513 gen_load_fpr32(fp0, fs);
7514 gen_load_fpr32(fp1, ft);
7515 gen_load_fpr32(fp2, fr);
David 'Digit' Turner87350d12014-04-03 15:44:48 +02007516 gen_helper_float_nmuladd_s(fp2, cpu_env, fp0, fp1, fp2);
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08007517 tcg_temp_free_i32(fp0);
7518 tcg_temp_free_i32(fp1);
7519 gen_store_fpr32(fp2, fd);
7520 tcg_temp_free_i32(fp2);
7521 }
7522 opn = "nmadd.s";
7523 break;
7524 case OPC_NMADD_D:
7525 check_cop1x(ctx);
7526 check_cp1_registers(ctx, fd | fs | ft | fr);
7527 {
7528 TCGv_i64 fp0 = tcg_temp_new_i64();
7529 TCGv_i64 fp1 = tcg_temp_new_i64();
7530 TCGv_i64 fp2 = tcg_temp_new_i64();
7531
7532 gen_load_fpr64(ctx, fp0, fs);
7533 gen_load_fpr64(ctx, fp1, ft);
7534 gen_load_fpr64(ctx, fp2, fr);
David 'Digit' Turner87350d12014-04-03 15:44:48 +02007535 gen_helper_float_nmuladd_d(fp2, cpu_env, fp0, fp1, fp2);
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08007536 tcg_temp_free_i64(fp0);
7537 tcg_temp_free_i64(fp1);
7538 gen_store_fpr64(ctx, fp2, fd);
7539 tcg_temp_free_i64(fp2);
7540 }
7541 opn = "nmadd.d";
7542 break;
7543 case OPC_NMADD_PS:
7544 check_cp1_64bitmode(ctx);
7545 {
7546 TCGv_i64 fp0 = tcg_temp_new_i64();
7547 TCGv_i64 fp1 = tcg_temp_new_i64();
7548 TCGv_i64 fp2 = tcg_temp_new_i64();
7549
7550 gen_load_fpr64(ctx, fp0, fs);
7551 gen_load_fpr64(ctx, fp1, ft);
7552 gen_load_fpr64(ctx, fp2, fr);
David 'Digit' Turner87350d12014-04-03 15:44:48 +02007553 gen_helper_float_nmuladd_ps(fp2, cpu_env, fp0, fp1, fp2);
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08007554 tcg_temp_free_i64(fp0);
7555 tcg_temp_free_i64(fp1);
7556 gen_store_fpr64(ctx, fp2, fd);
7557 tcg_temp_free_i64(fp2);
7558 }
7559 opn = "nmadd.ps";
7560 break;
7561 case OPC_NMSUB_S:
7562 check_cop1x(ctx);
7563 {
7564 TCGv_i32 fp0 = tcg_temp_new_i32();
7565 TCGv_i32 fp1 = tcg_temp_new_i32();
7566 TCGv_i32 fp2 = tcg_temp_new_i32();
7567
7568 gen_load_fpr32(fp0, fs);
7569 gen_load_fpr32(fp1, ft);
7570 gen_load_fpr32(fp2, fr);
David 'Digit' Turner87350d12014-04-03 15:44:48 +02007571 gen_helper_float_nmulsub_s(fp2, cpu_env, fp0, fp1, fp2);
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08007572 tcg_temp_free_i32(fp0);
7573 tcg_temp_free_i32(fp1);
7574 gen_store_fpr32(fp2, fd);
7575 tcg_temp_free_i32(fp2);
7576 }
7577 opn = "nmsub.s";
7578 break;
7579 case OPC_NMSUB_D:
7580 check_cop1x(ctx);
7581 check_cp1_registers(ctx, fd | fs | ft | fr);
7582 {
7583 TCGv_i64 fp0 = tcg_temp_new_i64();
7584 TCGv_i64 fp1 = tcg_temp_new_i64();
7585 TCGv_i64 fp2 = tcg_temp_new_i64();
7586
7587 gen_load_fpr64(ctx, fp0, fs);
7588 gen_load_fpr64(ctx, fp1, ft);
7589 gen_load_fpr64(ctx, fp2, fr);
David 'Digit' Turner87350d12014-04-03 15:44:48 +02007590 gen_helper_float_nmulsub_d(fp2, cpu_env, fp0, fp1, fp2);
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08007591 tcg_temp_free_i64(fp0);
7592 tcg_temp_free_i64(fp1);
7593 gen_store_fpr64(ctx, fp2, fd);
7594 tcg_temp_free_i64(fp2);
7595 }
7596 opn = "nmsub.d";
7597 break;
7598 case OPC_NMSUB_PS:
7599 check_cp1_64bitmode(ctx);
7600 {
7601 TCGv_i64 fp0 = tcg_temp_new_i64();
7602 TCGv_i64 fp1 = tcg_temp_new_i64();
7603 TCGv_i64 fp2 = tcg_temp_new_i64();
7604
7605 gen_load_fpr64(ctx, fp0, fs);
7606 gen_load_fpr64(ctx, fp1, ft);
7607 gen_load_fpr64(ctx, fp2, fr);
David 'Digit' Turner87350d12014-04-03 15:44:48 +02007608 gen_helper_float_nmulsub_ps(fp2, cpu_env, fp0, fp1, fp2);
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08007609 tcg_temp_free_i64(fp0);
7610 tcg_temp_free_i64(fp1);
7611 gen_store_fpr64(ctx, fp2, fd);
7612 tcg_temp_free_i64(fp2);
7613 }
7614 opn = "nmsub.ps";
7615 break;
7616 default:
7617 MIPS_INVAL(opn);
7618 generate_exception (ctx, EXCP_RI);
7619 return;
7620 }
7621 MIPS_DEBUG("%s %s, %s, %s, %s", opn, fregnames[fd], fregnames[fr],
7622 fregnames[fs], fregnames[ft]);
7623}
7624
7625/* ISA extensions (ASEs) */
7626/* MIPS16 extension to MIPS32 */
7627/* SmartMIPS extension to MIPS32 */
7628
7629#if defined(TARGET_MIPS64)
7630
7631/* MDMX extension to MIPS64 */
7632
7633#endif
7634
David 'Digit' Turnere2678e12014-01-16 15:56:43 +01007635static void decode_opc (CPUMIPSState *env, DisasContext *ctx)
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08007636{
7637 int32_t offset;
7638 int rs, rt, rd, sa;
7639 uint32_t op, op1, op2;
7640 int16_t imm;
7641
7642 /* make sure instructions are on a word boundary */
7643 if (ctx->pc & 0x3) {
7644 env->CP0_BadVAddr = ctx->pc;
7645 generate_exception(ctx, EXCP_AdEL);
7646 return;
7647 }
7648
7649 /* Handle blikely not taken case */
7650 if ((ctx->hflags & MIPS_HFLAG_BMASK) == MIPS_HFLAG_BL) {
7651 int l1 = gen_new_label();
7652
7653 MIPS_DEBUG("blikely condition (" TARGET_FMT_lx ")", ctx->pc + 4);
7654 tcg_gen_brcondi_tl(TCG_COND_NE, bcond, 0, l1);
7655 tcg_gen_movi_i32(hflags, ctx->hflags & ~MIPS_HFLAG_BMASK);
7656 gen_goto_tb(ctx, 1, ctx->pc + 4);
7657 gen_set_label(l1);
7658 }
7659
7660 if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP)))
7661 tcg_gen_debug_insn_start(ctx->pc);
7662
7663 op = MASK_OP_MAJOR(ctx->opcode);
7664 rs = (ctx->opcode >> 21) & 0x1f;
7665 rt = (ctx->opcode >> 16) & 0x1f;
7666 rd = (ctx->opcode >> 11) & 0x1f;
7667 sa = (ctx->opcode >> 6) & 0x1f;
7668 imm = (int16_t)ctx->opcode;
7669 switch (op) {
7670 case OPC_SPECIAL:
7671 op1 = MASK_SPECIAL(ctx->opcode);
7672 switch (op1) {
7673 case OPC_SLL: /* Shift with immediate */
7674 case OPC_SRA:
7675 case OPC_SRL:
7676 gen_shift_imm(env, ctx, op1, rd, rt, sa);
7677 break;
7678 case OPC_MOVN: /* Conditional move */
7679 case OPC_MOVZ:
7680 check_insn(env, ctx, ISA_MIPS4 | ISA_MIPS32);
7681 gen_cond_move(env, op1, rd, rs, rt);
7682 break;
7683 case OPC_ADD ... OPC_SUBU:
7684 gen_arith(env, ctx, op1, rd, rs, rt);
7685 break;
7686 case OPC_SLLV: /* Shifts */
7687 case OPC_SRLV:
7688 case OPC_SRAV:
7689 gen_shift(env, ctx, op1, rd, rs, rt);
7690 break;
7691 case OPC_SLT: /* Set on less than */
7692 case OPC_SLTU:
7693 gen_slt(env, op1, rd, rs, rt);
7694 break;
7695 case OPC_AND: /* Logic*/
7696 case OPC_OR:
7697 case OPC_NOR:
7698 case OPC_XOR:
7699 gen_logic(env, op1, rd, rs, rt);
7700 break;
7701 case OPC_MULT ... OPC_DIVU:
7702 if (sa) {
7703 check_insn(env, ctx, INSN_VR54XX);
7704 op1 = MASK_MUL_VR54XX(ctx->opcode);
7705 gen_mul_vr54xx(ctx, op1, rd, rs, rt);
7706 } else
7707 gen_muldiv(ctx, op1, rs, rt);
7708 break;
7709 case OPC_JR ... OPC_JALR:
7710 gen_compute_branch(ctx, op1, rs, rd, sa);
7711 return;
7712 case OPC_TGE ... OPC_TEQ: /* Traps */
7713 case OPC_TNE:
7714 gen_trap(ctx, op1, rs, rt, -1);
7715 break;
7716 case OPC_MFHI: /* Move from HI/LO */
7717 case OPC_MFLO:
7718 gen_HILO(ctx, op1, rd);
7719 break;
7720 case OPC_MTHI:
7721 case OPC_MTLO: /* Move to HI/LO */
7722 gen_HILO(ctx, op1, rs);
7723 break;
7724 case OPC_PMON: /* Pmon entry point, also R4010 selsl */
7725#ifdef MIPS_STRICT_STANDARD
7726 MIPS_INVAL("PMON / selsl");
7727 generate_exception(ctx, EXCP_RI);
7728#else
David 'Digit' Turnerd5b76c62014-04-03 12:40:54 +02007729 gen_helper_1i(pmon, cpu_env, sa);
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08007730#endif
7731 break;
7732 case OPC_SYSCALL:
7733 generate_exception(ctx, EXCP_SYSCALL);
7734 ctx->bstate = BS_STOP;
7735 break;
7736 case OPC_BREAK:
7737 generate_exception(ctx, EXCP_BREAK);
7738 break;
7739 case OPC_SPIM:
7740#ifdef MIPS_STRICT_STANDARD
7741 MIPS_INVAL("SPIM");
7742 generate_exception(ctx, EXCP_RI);
7743#else
7744 /* Implemented as RI exception for now. */
7745 MIPS_INVAL("spim (unofficial)");
7746 generate_exception(ctx, EXCP_RI);
7747#endif
7748 break;
7749 case OPC_SYNC:
7750 /* Treat as NOP. */
7751 break;
7752
7753 case OPC_MOVCI:
7754 check_insn(env, ctx, ISA_MIPS4 | ISA_MIPS32);
7755 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
7756 check_cp1_enabled(ctx);
7757 gen_movci(ctx, rd, rs, (ctx->opcode >> 18) & 0x7,
7758 (ctx->opcode >> 16) & 1);
7759 } else {
7760 generate_exception_err(ctx, EXCP_CpU, 1);
7761 }
7762 break;
7763
7764#if defined(TARGET_MIPS64)
7765 /* MIPS64 specific opcodes */
7766 case OPC_DSLL:
7767 case OPC_DSRA:
7768 case OPC_DSRL:
7769 case OPC_DSLL32:
7770 case OPC_DSRA32:
7771 case OPC_DSRL32:
7772 check_insn(env, ctx, ISA_MIPS3);
7773 check_mips_64(ctx);
7774 gen_shift_imm(env, ctx, op1, rd, rt, sa);
7775 break;
7776 case OPC_DADD ... OPC_DSUBU:
7777 check_insn(env, ctx, ISA_MIPS3);
7778 check_mips_64(ctx);
7779 gen_arith(env, ctx, op1, rd, rs, rt);
7780 break;
7781 case OPC_DSLLV:
7782 case OPC_DSRAV:
7783 case OPC_DSRLV:
7784 check_insn(env, ctx, ISA_MIPS3);
7785 check_mips_64(ctx);
7786 gen_shift(env, ctx, op1, rd, rs, rt);
7787 break;
7788 case OPC_DMULT ... OPC_DDIVU:
7789 check_insn(env, ctx, ISA_MIPS3);
7790 check_mips_64(ctx);
7791 gen_muldiv(ctx, op1, rs, rt);
7792 break;
7793#endif
7794 default: /* Invalid */
7795 MIPS_INVAL("special");
7796 generate_exception(ctx, EXCP_RI);
7797 break;
7798 }
7799 break;
7800 case OPC_SPECIAL2:
7801 op1 = MASK_SPECIAL2(ctx->opcode);
7802 switch (op1) {
7803 case OPC_MADD ... OPC_MADDU: /* Multiply and add/sub */
7804 case OPC_MSUB ... OPC_MSUBU:
7805 check_insn(env, ctx, ISA_MIPS32);
7806 gen_muldiv(ctx, op1, rs, rt);
7807 break;
7808 case OPC_MUL:
7809 gen_arith(env, ctx, op1, rd, rs, rt);
7810 break;
7811 case OPC_CLO:
7812 case OPC_CLZ:
7813 check_insn(env, ctx, ISA_MIPS32);
7814 gen_cl(ctx, op1, rd, rs);
7815 break;
7816 case OPC_SDBBP:
7817 /* XXX: not clear which exception should be raised
7818 * when in debug mode...
7819 */
7820 check_insn(env, ctx, ISA_MIPS32);
7821 if (!(ctx->hflags & MIPS_HFLAG_DM)) {
7822 generate_exception(ctx, EXCP_DBp);
7823 } else {
7824 generate_exception(ctx, EXCP_DBp);
7825 }
7826 /* Treat as NOP. */
7827 break;
7828#if defined(TARGET_MIPS64)
7829 case OPC_DCLO:
7830 case OPC_DCLZ:
7831 check_insn(env, ctx, ISA_MIPS64);
7832 check_mips_64(ctx);
7833 gen_cl(ctx, op1, rd, rs);
7834 break;
7835#endif
7836 default: /* Invalid */
7837 MIPS_INVAL("special2");
7838 generate_exception(ctx, EXCP_RI);
7839 break;
7840 }
7841 break;
7842 case OPC_SPECIAL3:
7843 op1 = MASK_SPECIAL3(ctx->opcode);
7844 switch (op1) {
7845 case OPC_EXT:
7846 case OPC_INS:
7847 check_insn(env, ctx, ISA_MIPS32R2);
7848 gen_bitops(ctx, op1, rt, rs, sa, rd);
7849 break;
7850 case OPC_BSHFL:
7851 check_insn(env, ctx, ISA_MIPS32R2);
7852 op2 = MASK_BSHFL(ctx->opcode);
7853 gen_bshfl(ctx, op2, rt, rd);
7854 break;
7855 case OPC_RDHWR:
7856 check_insn(env, ctx, ISA_MIPS32R2);
7857 {
7858 TCGv t0 = tcg_temp_new();
7859
7860 switch (rd) {
7861 case 0:
7862 save_cpu_state(ctx, 1);
David 'Digit' Turnerd5b76c62014-04-03 12:40:54 +02007863 gen_helper_rdhwr_cpunum(t0, cpu_env);
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08007864 gen_store_gpr(t0, rt);
7865 break;
7866 case 1:
7867 save_cpu_state(ctx, 1);
David 'Digit' Turnerd5b76c62014-04-03 12:40:54 +02007868 gen_helper_rdhwr_synci_step(t0, cpu_env);
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08007869 gen_store_gpr(t0, rt);
7870 break;
7871 case 2:
7872 save_cpu_state(ctx, 1);
David 'Digit' Turnerd5b76c62014-04-03 12:40:54 +02007873 gen_helper_rdhwr_cc(t0, cpu_env);
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08007874 gen_store_gpr(t0, rt);
7875 break;
7876 case 3:
7877 save_cpu_state(ctx, 1);
David 'Digit' Turnerd5b76c62014-04-03 12:40:54 +02007878 gen_helper_rdhwr_ccres(t0, cpu_env);
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08007879 gen_store_gpr(t0, rt);
7880 break;
7881 case 29:
7882#if defined(CONFIG_USER_ONLY)
David 'Digit' Turnere2678e12014-01-16 15:56:43 +01007883 tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUMIPSState, tls_value));
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08007884 gen_store_gpr(t0, rt);
7885 break;
7886#else
7887 /* XXX: Some CPUs implement this in hardware.
7888 Not supported yet. */
7889#endif
7890 default: /* Invalid */
7891 MIPS_INVAL("rdhwr");
7892 generate_exception(ctx, EXCP_RI);
7893 break;
7894 }
7895 tcg_temp_free(t0);
7896 }
7897 break;
7898 case OPC_FORK:
7899 check_insn(env, ctx, ASE_MT);
7900 {
7901 TCGv t0 = tcg_temp_new();
7902 TCGv t1 = tcg_temp_new();
7903
7904 gen_load_gpr(t0, rt);
7905 gen_load_gpr(t1, rs);
7906 gen_helper_fork(t0, t1);
7907 tcg_temp_free(t0);
7908 tcg_temp_free(t1);
7909 }
7910 break;
7911 case OPC_YIELD:
7912 check_insn(env, ctx, ASE_MT);
7913 {
7914 TCGv t0 = tcg_temp_new();
7915
7916 save_cpu_state(ctx, 1);
7917 gen_load_gpr(t0, rs);
David 'Digit' Turner26efe752014-04-03 15:59:28 +02007918 gen_helper_yield(t0, cpu_env, t0);
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08007919 gen_store_gpr(t0, rd);
7920 tcg_temp_free(t0);
7921 }
7922 break;
7923#if defined(TARGET_MIPS64)
7924 case OPC_DEXTM ... OPC_DEXT:
7925 case OPC_DINSM ... OPC_DINS:
7926 check_insn(env, ctx, ISA_MIPS64R2);
7927 check_mips_64(ctx);
7928 gen_bitops(ctx, op1, rt, rs, sa, rd);
7929 break;
7930 case OPC_DBSHFL:
7931 check_insn(env, ctx, ISA_MIPS64R2);
7932 check_mips_64(ctx);
7933 op2 = MASK_DBSHFL(ctx->opcode);
7934 gen_bshfl(ctx, op2, rt, rd);
7935 break;
7936#endif
7937 default: /* Invalid */
7938 MIPS_INVAL("special3");
7939 generate_exception(ctx, EXCP_RI);
7940 break;
7941 }
7942 break;
7943 case OPC_REGIMM:
7944 op1 = MASK_REGIMM(ctx->opcode);
7945 switch (op1) {
7946 case OPC_BLTZ ... OPC_BGEZL: /* REGIMM branches */
7947 case OPC_BLTZAL ... OPC_BGEZALL:
7948 gen_compute_branch(ctx, op1, rs, -1, imm << 2);
7949 return;
7950 case OPC_TGEI ... OPC_TEQI: /* REGIMM traps */
7951 case OPC_TNEI:
7952 gen_trap(ctx, op1, rs, -1, imm);
7953 break;
7954 case OPC_SYNCI:
7955 check_insn(env, ctx, ISA_MIPS32R2);
7956 /* Treat as NOP. */
7957 break;
7958 default: /* Invalid */
7959 MIPS_INVAL("regimm");
7960 generate_exception(ctx, EXCP_RI);
7961 break;
7962 }
7963 break;
7964 case OPC_CP0:
7965 check_cp0_enabled(ctx);
7966 op1 = MASK_CP0(ctx->opcode);
7967 switch (op1) {
7968 case OPC_MFC0:
7969 case OPC_MTC0:
7970 case OPC_MFTR:
7971 case OPC_MTTR:
7972#if defined(TARGET_MIPS64)
7973 case OPC_DMFC0:
7974 case OPC_DMTC0:
7975#endif
7976#ifndef CONFIG_USER_ONLY
7977 gen_cp0(env, ctx, op1, rt, rd);
7978#endif /* !CONFIG_USER_ONLY */
7979 break;
7980 case OPC_C0_FIRST ... OPC_C0_LAST:
7981#ifndef CONFIG_USER_ONLY
7982 gen_cp0(env, ctx, MASK_C0(ctx->opcode), rt, rd);
7983#endif /* !CONFIG_USER_ONLY */
7984 break;
7985 case OPC_MFMC0:
7986#ifndef CONFIG_USER_ONLY
7987 {
7988 TCGv t0 = tcg_temp_new();
7989
7990 op2 = MASK_MFMC0(ctx->opcode);
7991 switch (op2) {
7992 case OPC_DMT:
7993 check_insn(env, ctx, ASE_MT);
David 'Digit' Turner26efe752014-04-03 15:59:28 +02007994 gen_helper_dmt(t0);
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08007995 gen_store_gpr(t0, rt);
7996 break;
7997 case OPC_EMT:
7998 check_insn(env, ctx, ASE_MT);
David 'Digit' Turner26efe752014-04-03 15:59:28 +02007999 gen_helper_emt(t0);
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08008000 gen_store_gpr(t0, rt);
8001 break;
8002 case OPC_DVPE:
8003 check_insn(env, ctx, ASE_MT);
David 'Digit' Turner26efe752014-04-03 15:59:28 +02008004 gen_helper_dvpe(t0, cpu_env);
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08008005 gen_store_gpr(t0, rt);
8006 break;
8007 case OPC_EVPE:
8008 check_insn(env, ctx, ASE_MT);
David 'Digit' Turner26efe752014-04-03 15:59:28 +02008009 gen_helper_evpe(t0, cpu_env);
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08008010 gen_store_gpr(t0, rt);
8011 break;
8012 case OPC_DI:
8013 check_insn(env, ctx, ISA_MIPS32R2);
8014 save_cpu_state(ctx, 1);
David 'Digit' Turner6480c962014-04-03 12:38:04 +02008015 gen_helper_di(t0, cpu_env);
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08008016 gen_store_gpr(t0, rt);
8017 /* Stop translation as we may have switched the execution mode */
8018 ctx->bstate = BS_STOP;
8019 break;
8020 case OPC_EI:
8021 check_insn(env, ctx, ISA_MIPS32R2);
8022 save_cpu_state(ctx, 1);
David 'Digit' Turner6480c962014-04-03 12:38:04 +02008023 gen_helper_ei(t0, cpu_env);
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08008024 gen_store_gpr(t0, rt);
8025 /* Stop translation as we may have switched the execution mode */
8026 ctx->bstate = BS_STOP;
8027 break;
8028 default: /* Invalid */
8029 MIPS_INVAL("mfmc0");
8030 generate_exception(ctx, EXCP_RI);
8031 break;
8032 }
8033 tcg_temp_free(t0);
8034 }
8035#endif /* !CONFIG_USER_ONLY */
8036 break;
8037 case OPC_RDPGPR:
8038 check_insn(env, ctx, ISA_MIPS32R2);
8039 gen_load_srsgpr(rt, rd);
8040 break;
8041 case OPC_WRPGPR:
8042 check_insn(env, ctx, ISA_MIPS32R2);
8043 gen_store_srsgpr(rt, rd);
8044 break;
8045 default:
8046 MIPS_INVAL("cp0");
8047 generate_exception(ctx, EXCP_RI);
8048 break;
8049 }
8050 break;
8051 case OPC_ADDI: /* Arithmetic with immediate opcode */
8052 case OPC_ADDIU:
8053 gen_arith_imm(env, ctx, op, rt, rs, imm);
8054 break;
8055 case OPC_SLTI: /* Set on less than with immediate opcode */
8056 case OPC_SLTIU:
8057 gen_slt_imm(env, op, rt, rs, imm);
8058 break;
8059 case OPC_ANDI: /* Arithmetic with immediate opcode */
8060 case OPC_LUI:
8061 case OPC_ORI:
8062 case OPC_XORI:
8063 gen_logic_imm(env, op, rt, rs, imm);
8064 break;
8065 case OPC_J ... OPC_JAL: /* Jump */
8066 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2;
8067 gen_compute_branch(ctx, op, rs, rt, offset);
8068 return;
8069 case OPC_BEQ ... OPC_BGTZ: /* Branch */
8070 case OPC_BEQL ... OPC_BGTZL:
8071 gen_compute_branch(ctx, op, rs, rt, imm << 2);
8072 return;
8073 case OPC_LB ... OPC_LWR: /* Load and stores */
8074 case OPC_SB ... OPC_SW:
8075 case OPC_SWR:
8076 case OPC_LL:
8077 gen_ldst(ctx, op, rt, rs, imm);
8078 break;
8079 case OPC_SC:
8080 gen_st_cond(ctx, op, rt, rs, imm);
8081 break;
8082 case OPC_CACHE:
8083 check_insn(env, ctx, ISA_MIPS3 | ISA_MIPS32);
8084 /* Treat as NOP. */
8085 break;
8086 case OPC_PREF:
8087 check_insn(env, ctx, ISA_MIPS4 | ISA_MIPS32);
8088 /* Treat as NOP. */
8089 break;
8090
8091 /* Floating point (COP1). */
8092 case OPC_LWC1:
8093 case OPC_LDC1:
8094 case OPC_SWC1:
8095 case OPC_SDC1:
8096 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
8097 check_cp1_enabled(ctx);
8098 gen_flt_ldst(ctx, op, rt, rs, imm);
8099 } else {
8100 generate_exception_err(ctx, EXCP_CpU, 1);
8101 }
8102 break;
8103
8104 case OPC_CP1:
8105 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
8106 check_cp1_enabled(ctx);
8107 op1 = MASK_CP1(ctx->opcode);
8108 switch (op1) {
8109 case OPC_MFHC1:
8110 case OPC_MTHC1:
8111 check_insn(env, ctx, ISA_MIPS32R2);
8112 case OPC_MFC1:
8113 case OPC_CFC1:
8114 case OPC_MTC1:
8115 case OPC_CTC1:
8116 gen_cp1(ctx, op1, rt, rd);
8117 break;
8118#if defined(TARGET_MIPS64)
8119 case OPC_DMFC1:
8120 case OPC_DMTC1:
8121 check_insn(env, ctx, ISA_MIPS3);
8122 gen_cp1(ctx, op1, rt, rd);
8123 break;
8124#endif
8125 case OPC_BC1ANY2:
8126 case OPC_BC1ANY4:
8127 check_cop1x(ctx);
8128 check_insn(env, ctx, ASE_MIPS3D);
8129 /* fall through */
8130 case OPC_BC1:
8131 gen_compute_branch1(env, ctx, MASK_BC1(ctx->opcode),
8132 (rt >> 2) & 0x7, imm << 2);
8133 return;
8134 case OPC_S_FMT:
8135 case OPC_D_FMT:
8136 case OPC_W_FMT:
8137 case OPC_L_FMT:
8138 case OPC_PS_FMT:
8139 gen_farith(ctx, MASK_CP1_FUNC(ctx->opcode), rt, rd, sa,
8140 (imm >> 8) & 0x7);
8141 break;
8142 default:
8143 MIPS_INVAL("cp1");
8144 generate_exception (ctx, EXCP_RI);
8145 break;
8146 }
8147 } else {
8148 generate_exception_err(ctx, EXCP_CpU, 1);
8149 }
8150 break;
8151
8152 /* COP2. */
8153 case OPC_LWC2:
8154 case OPC_LDC2:
8155 case OPC_SWC2:
8156 case OPC_SDC2:
8157 case OPC_CP2:
8158 /* COP2: Not implemented. */
8159 generate_exception_err(ctx, EXCP_CpU, 2);
8160 break;
8161
8162 case OPC_CP3:
8163 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
8164 check_cp1_enabled(ctx);
8165 op1 = MASK_CP3(ctx->opcode);
8166 switch (op1) {
8167 case OPC_LWXC1:
8168 case OPC_LDXC1:
8169 case OPC_LUXC1:
8170 case OPC_SWXC1:
8171 case OPC_SDXC1:
8172 case OPC_SUXC1:
8173 gen_flt3_ldst(ctx, op1, sa, rd, rs, rt);
8174 break;
8175 case OPC_PREFX:
8176 /* Treat as NOP. */
8177 break;
8178 case OPC_ALNV_PS:
8179 case OPC_MADD_S:
8180 case OPC_MADD_D:
8181 case OPC_MADD_PS:
8182 case OPC_MSUB_S:
8183 case OPC_MSUB_D:
8184 case OPC_MSUB_PS:
8185 case OPC_NMADD_S:
8186 case OPC_NMADD_D:
8187 case OPC_NMADD_PS:
8188 case OPC_NMSUB_S:
8189 case OPC_NMSUB_D:
8190 case OPC_NMSUB_PS:
8191 gen_flt3_arith(ctx, op1, sa, rs, rd, rt);
8192 break;
8193 default:
8194 MIPS_INVAL("cp3");
8195 generate_exception (ctx, EXCP_RI);
8196 break;
8197 }
8198 } else {
8199 generate_exception_err(ctx, EXCP_CpU, 1);
8200 }
8201 break;
8202
8203#if defined(TARGET_MIPS64)
8204 /* MIPS64 opcodes */
8205 case OPC_LWU:
8206 case OPC_LDL ... OPC_LDR:
8207 case OPC_SDL ... OPC_SDR:
8208 case OPC_LLD:
8209 case OPC_LD:
8210 case OPC_SD:
8211 check_insn(env, ctx, ISA_MIPS3);
8212 check_mips_64(ctx);
8213 gen_ldst(ctx, op, rt, rs, imm);
8214 break;
8215 case OPC_SCD:
8216 check_insn(env, ctx, ISA_MIPS3);
8217 check_mips_64(ctx);
8218 gen_st_cond(ctx, op, rt, rs, imm);
8219 break;
8220 case OPC_DADDI:
8221 case OPC_DADDIU:
8222 check_insn(env, ctx, ISA_MIPS3);
8223 check_mips_64(ctx);
8224 gen_arith_imm(env, ctx, op, rt, rs, imm);
8225 break;
8226#endif
8227 case OPC_JALX:
8228 check_insn(env, ctx, ASE_MIPS16);
8229 /* MIPS16: Not implemented. */
8230 case OPC_MDMX:
8231 check_insn(env, ctx, ASE_MDMX);
8232 /* MDMX: Not implemented. */
8233 default: /* Invalid */
8234 MIPS_INVAL("major opcode");
8235 generate_exception(ctx, EXCP_RI);
8236 break;
8237 }
8238 if (ctx->hflags & MIPS_HFLAG_BMASK) {
8239 int hflags = ctx->hflags & MIPS_HFLAG_BMASK;
8240 /* Branches completion */
8241 ctx->hflags &= ~MIPS_HFLAG_BMASK;
8242 ctx->bstate = BS_BRANCH;
8243 save_cpu_state(ctx, 0);
8244 /* FIXME: Need to clear can_do_io. */
8245 switch (hflags) {
8246 case MIPS_HFLAG_B:
8247 /* unconditional branch */
8248 MIPS_DEBUG("unconditional branch");
8249 gen_goto_tb(ctx, 0, ctx->btarget);
8250 break;
8251 case MIPS_HFLAG_BL:
8252 /* blikely taken case */
8253 MIPS_DEBUG("blikely branch taken");
8254 gen_goto_tb(ctx, 0, ctx->btarget);
8255 break;
8256 case MIPS_HFLAG_BC:
8257 /* Conditional branch */
8258 MIPS_DEBUG("conditional branch");
8259 {
8260 int l1 = gen_new_label();
8261
8262 tcg_gen_brcondi_tl(TCG_COND_NE, bcond, 0, l1);
8263 gen_goto_tb(ctx, 1, ctx->pc + 4);
8264 gen_set_label(l1);
8265 gen_goto_tb(ctx, 0, ctx->btarget);
8266 }
8267 break;
8268 case MIPS_HFLAG_BR:
8269 /* unconditional branch to register */
8270 MIPS_DEBUG("branch to register");
8271 tcg_gen_mov_tl(cpu_PC, btarget);
8272 if (ctx->singlestep_enabled) {
8273 save_cpu_state(ctx, 0);
David 'Digit' Turner6480c962014-04-03 12:38:04 +02008274 gen_helper_1i(raise_exception, cpu_env, EXCP_DEBUG);
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08008275 }
8276 tcg_gen_exit_tb(0);
8277 break;
8278 default:
8279 MIPS_DEBUG("unknown branch");
8280 break;
8281 }
8282 }
8283}
8284
8285static inline void
David 'Digit' Turnere2678e12014-01-16 15:56:43 +01008286gen_intermediate_code_internal (CPUMIPSState *env, TranslationBlock *tb,
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08008287 int search_pc)
8288{
8289 DisasContext ctx;
8290 target_ulong pc_start;
8291 uint16_t *gen_opc_end;
8292 CPUBreakpoint *bp;
8293 int j, lj = -1;
8294 int num_insns;
8295 int max_insns;
8296
8297 if (search_pc)
8298 qemu_log("search pc %d\n", search_pc);
8299
8300 pc_start = tb->pc;
David 'Digit' Turner975bba82014-02-17 23:33:29 +01008301 gen_opc_end = tcg_ctx.gen_opc_buf + OPC_MAX_SIZE;
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08008302 ctx.pc = pc_start;
8303 ctx.saved_pc = -1;
David 'Digit' Turnerfed223d2014-03-24 17:42:47 +01008304 ctx.singlestep_enabled = ENV_GET_CPU(env)->singlestep_enabled;
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08008305 ctx.tb = tb;
8306 ctx.bstate = BS_NONE;
8307 /* Restore delay slot state from the tb context. */
8308 ctx.hflags = (uint32_t)tb->flags; /* FIXME: maybe use 64 bits here? */
8309 restore_cpu_state(env, &ctx);
8310#ifdef CONFIG_USER_ONLY
8311 ctx.mem_idx = MIPS_HFLAG_UM;
8312#else
8313 ctx.mem_idx = ctx.hflags & MIPS_HFLAG_KSU;
8314#endif
8315 num_insns = 0;
8316 max_insns = tb->cflags & CF_COUNT_MASK;
8317 if (max_insns == 0)
8318 max_insns = CF_COUNT_MASK;
8319#ifdef DEBUG_DISAS
8320 qemu_log_mask(CPU_LOG_TB_CPU, "------------------------------------------------\n");
8321 /* FIXME: This may print out stale hflags from env... */
David 'Digit' Turnerbf7a22f2014-03-25 16:36:03 +01008322 log_cpu_state_mask(CPU_LOG_TB_CPU, ENV_GET_CPU(env), 0);
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08008323#endif
8324 LOG_DISAS("\ntb %p idx %d hflags %04x\n", tb, ctx.mem_idx, ctx.hflags);
8325 gen_icount_start();
8326 while (ctx.bstate == BS_NONE) {
8327 if (unlikely(!QTAILQ_EMPTY(&env->breakpoints))) {
8328 QTAILQ_FOREACH(bp, &env->breakpoints, entry) {
8329 if (bp->pc == ctx.pc) {
8330 save_cpu_state(&ctx, 1);
8331 ctx.bstate = BS_BRANCH;
David 'Digit' Turner6480c962014-04-03 12:38:04 +02008332 gen_helper_1i(raise_exception, cpu_env, EXCP_DEBUG);
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08008333 /* Include the breakpoint location or the tb won't
8334 * be flushed when it must be. */
8335 ctx.pc += 4;
8336 goto done_generating;
8337 }
8338 }
8339 }
8340
8341 if (search_pc) {
David 'Digit' Turner975bba82014-02-17 23:33:29 +01008342 j = tcg_ctx.gen_opc_ptr - tcg_ctx.gen_opc_buf;
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08008343 if (lj < j) {
8344 lj++;
8345 while (lj < j)
David 'Digit' Turner975bba82014-02-17 23:33:29 +01008346 tcg_ctx.gen_opc_instr_start[lj++] = 0;
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08008347 }
David 'Digit' Turner975bba82014-02-17 23:33:29 +01008348 tcg_ctx.gen_opc_pc[lj] = ctx.pc;
David 'Digit' Turner86b1fb02014-03-21 15:20:21 +01008349 gen_opc_hflags[lj] = ctx.hflags & MIPS_HFLAG_BMASK;
David 'Digit' Turner975bba82014-02-17 23:33:29 +01008350 tcg_ctx.gen_opc_instr_start[lj] = 1;
8351 tcg_ctx.gen_opc_icount[lj] = num_insns;
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08008352 }
8353 if (num_insns + 1 == max_insns && (tb->cflags & CF_LAST_IO))
8354 gen_io_start();
David 'Digit' Turnereca7bc22014-03-14 23:58:39 +01008355 ctx.opcode = cpu_ldl_code(env, ctx.pc);
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08008356 decode_opc(env, &ctx);
8357 ctx.pc += 4;
8358 num_insns++;
8359
8360 /* Execute a branch and its delay slot as a single instruction.
8361 This is what GDB expects and is consistent with what the
8362 hardware does (e.g. if a delay slot instruction faults, the
8363 reported PC is the PC of the branch). */
David 'Digit' Turnerfed223d2014-03-24 17:42:47 +01008364 if (ENV_GET_CPU(env)->singlestep_enabled && (ctx.hflags & MIPS_HFLAG_BMASK) == 0)
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08008365 break;
8366
Dusan Milosavljevic3d781242012-09-22 09:58:45 -07008367 /* Do not split a branch instruction and its delay slot into two
8368 TB's when a page boundary is crossed. This causes TB's to be
8369 invalidated incorrectly if branch target is patched. */
8370 if ((ctx.pc & (TARGET_PAGE_SIZE - 1)) == 0 && (ctx.hflags & MIPS_HFLAG_BMASK) == 0)
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08008371 break;
8372
David 'Digit' Turner975bba82014-02-17 23:33:29 +01008373 if (tcg_ctx.gen_opc_ptr >= gen_opc_end)
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08008374 break;
8375
8376 if (num_insns >= max_insns)
8377 break;
8378
8379 if (singlestep)
8380 break;
8381 }
8382 if (tb->cflags & CF_LAST_IO)
8383 gen_io_end();
David 'Digit' Turnerfed223d2014-03-24 17:42:47 +01008384 if (ENV_GET_CPU(env)->singlestep_enabled && ctx.bstate != BS_BRANCH) {
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08008385 save_cpu_state(&ctx, ctx.bstate == BS_NONE);
David 'Digit' Turner6480c962014-04-03 12:38:04 +02008386 gen_helper_1i(raise_exception, cpu_env, EXCP_DEBUG);
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08008387 } else {
8388 switch (ctx.bstate) {
8389 case BS_STOP:
David 'Digit' Turner6480c962014-04-03 12:38:04 +02008390 gen_helper_interrupt_restart(cpu_env);
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08008391 gen_goto_tb(&ctx, 0, ctx.pc);
8392 break;
8393 case BS_NONE:
8394 save_cpu_state(&ctx, 0);
8395 gen_goto_tb(&ctx, 0, ctx.pc);
8396 break;
8397 case BS_EXCP:
David 'Digit' Turner6480c962014-04-03 12:38:04 +02008398 gen_helper_interrupt_restart(cpu_env);
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08008399 tcg_gen_exit_tb(0);
8400 break;
8401 case BS_BRANCH:
8402 default:
8403 break;
8404 }
8405 }
8406done_generating:
8407 gen_icount_end(tb, num_insns);
David 'Digit' Turner975bba82014-02-17 23:33:29 +01008408 *tcg_ctx.gen_opc_ptr = INDEX_op_end;
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08008409 if (search_pc) {
David 'Digit' Turner975bba82014-02-17 23:33:29 +01008410 j = tcg_ctx.gen_opc_ptr - tcg_ctx.gen_opc_buf;
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08008411 lj++;
8412 while (lj <= j)
David 'Digit' Turner975bba82014-02-17 23:33:29 +01008413 tcg_ctx.gen_opc_instr_start[lj++] = 0;
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08008414 } else {
8415 tb->size = ctx.pc - pc_start;
8416 tb->icount = num_insns;
8417 }
8418#ifdef DEBUG_DISAS
8419 LOG_DISAS("\n");
8420 if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) {
8421 qemu_log("IN: %s\n", lookup_symbol(pc_start));
David 'Digit' Turner0dc43a92014-01-16 15:43:33 +01008422 log_target_disas(env, pc_start, ctx.pc - pc_start, 0);
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08008423 qemu_log("\n");
8424 }
8425 qemu_log_mask(CPU_LOG_TB_CPU, "---------------- %d %08x\n", ctx.bstate, ctx.hflags);
8426#endif
8427}
8428
David 'Digit' Turnere2678e12014-01-16 15:56:43 +01008429void gen_intermediate_code (CPUMIPSState *env, struct TranslationBlock *tb)
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08008430{
8431 gen_intermediate_code_internal(env, tb, 0);
8432}
8433
David 'Digit' Turnere2678e12014-01-16 15:56:43 +01008434void gen_intermediate_code_pc (CPUMIPSState *env, struct TranslationBlock *tb)
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08008435{
8436 gen_intermediate_code_internal(env, tb, 1);
8437}
8438
David 'Digit' Turnere2678e12014-01-16 15:56:43 +01008439static void fpu_dump_state(CPUMIPSState *env, FILE *f,
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08008440 int (*fpu_fprintf)(FILE *f, const char *fmt, ...),
8441 int flags)
8442{
8443 int i;
8444 int is_fpu64 = !!(env->hflags & MIPS_HFLAG_F64);
8445
8446#define printfpr(fp) \
8447 do { \
8448 if (is_fpu64) \
8449 fpu_fprintf(f, "w:%08x d:%016lx fd:%13g fs:%13g psu: %13g\n", \
8450 (fp)->w[FP_ENDIAN_IDX], (fp)->d, (fp)->fd, \
8451 (fp)->fs[FP_ENDIAN_IDX], (fp)->fs[!FP_ENDIAN_IDX]); \
8452 else { \
8453 fpr_t tmp; \
8454 tmp.w[FP_ENDIAN_IDX] = (fp)->w[FP_ENDIAN_IDX]; \
8455 tmp.w[!FP_ENDIAN_IDX] = ((fp) + 1)->w[FP_ENDIAN_IDX]; \
8456 fpu_fprintf(f, "w:%08x d:%016lx fd:%13g fs:%13g psu:%13g\n", \
8457 tmp.w[FP_ENDIAN_IDX], tmp.d, tmp.fd, \
8458 tmp.fs[FP_ENDIAN_IDX], tmp.fs[!FP_ENDIAN_IDX]); \
8459 } \
8460 } while(0)
8461
8462
8463 fpu_fprintf(f, "CP1 FCR0 0x%08x FCR31 0x%08x SR.FR %d fp_status 0x%08x(0x%02x)\n",
8464 env->active_fpu.fcr0, env->active_fpu.fcr31, is_fpu64, env->active_fpu.fp_status,
8465 get_float_exception_flags(&env->active_fpu.fp_status));
8466 for (i = 0; i < 32; (is_fpu64) ? i++ : (i += 2)) {
8467 fpu_fprintf(f, "%3s: ", fregnames[i]);
8468 printfpr(&env->active_fpu.fpr[i]);
8469 }
8470
8471#undef printfpr
8472}
8473
8474#if defined(TARGET_MIPS64) && defined(MIPS_DEBUG_SIGN_EXTENSIONS)
8475/* Debug help: The architecture requires 32bit code to maintain proper
8476 sign-extended values on 64bit machines. */
8477
8478#define SIGN_EXT_P(val) ((((val) & ~0x7fffffff) == 0) || (((val) & ~0x7fffffff) == ~0x7fffffff))
8479
8480static void
David 'Digit' Turnere2678e12014-01-16 15:56:43 +01008481cpu_mips_check_sign_extensions (CPUMIPSState *env, FILE *f,
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08008482 int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
8483 int flags)
8484{
8485 int i;
8486
8487 if (!SIGN_EXT_P(env->active_tc.PC))
8488 cpu_fprintf(f, "BROKEN: pc=0x" TARGET_FMT_lx "\n", env->active_tc.PC);
8489 if (!SIGN_EXT_P(env->active_tc.HI[0]))
8490 cpu_fprintf(f, "BROKEN: HI=0x" TARGET_FMT_lx "\n", env->active_tc.HI[0]);
8491 if (!SIGN_EXT_P(env->active_tc.LO[0]))
8492 cpu_fprintf(f, "BROKEN: LO=0x" TARGET_FMT_lx "\n", env->active_tc.LO[0]);
8493 if (!SIGN_EXT_P(env->btarget))
8494 cpu_fprintf(f, "BROKEN: btarget=0x" TARGET_FMT_lx "\n", env->btarget);
8495
8496 for (i = 0; i < 32; i++) {
8497 if (!SIGN_EXT_P(env->active_tc.gpr[i]))
8498 cpu_fprintf(f, "BROKEN: %s=0x" TARGET_FMT_lx "\n", regnames[i], env->active_tc.gpr[i]);
8499 }
8500
8501 if (!SIGN_EXT_P(env->CP0_EPC))
8502 cpu_fprintf(f, "BROKEN: EPC=0x" TARGET_FMT_lx "\n", env->CP0_EPC);
8503 if (!SIGN_EXT_P(env->lladdr))
8504 cpu_fprintf(f, "BROKEN: LLAddr=0x" TARGET_FMT_lx "\n", env->lladdr);
8505}
8506#endif
8507
David 'Digit' Turnerbf7a22f2014-03-25 16:36:03 +01008508void cpu_dump_state (CPUState *cpu, FILE *f,
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08008509 int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
8510 int flags)
8511{
David 'Digit' Turnerbf7a22f2014-03-25 16:36:03 +01008512 CPUMIPSState *env = cpu->env_ptr;
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08008513 int i;
8514
8515 cpu_fprintf(f, "pc=0x" TARGET_FMT_lx " HI=0x" TARGET_FMT_lx " LO=0x" TARGET_FMT_lx " ds %04x " TARGET_FMT_lx " %d\n",
8516 env->active_tc.PC, env->active_tc.HI[0], env->active_tc.LO[0],
8517 env->hflags, env->btarget, env->bcond);
8518 for (i = 0; i < 32; i++) {
8519 if ((i & 3) == 0)
8520 cpu_fprintf(f, "GPR%02d:", i);
8521 cpu_fprintf(f, " %s " TARGET_FMT_lx, regnames[i], env->active_tc.gpr[i]);
8522 if ((i & 3) == 3)
8523 cpu_fprintf(f, "\n");
8524 }
8525
8526 cpu_fprintf(f, "CP0 Status 0x%08x Cause 0x%08x EPC 0x" TARGET_FMT_lx "\n",
8527 env->CP0_Status, env->CP0_Cause, env->CP0_EPC);
8528 cpu_fprintf(f, " Config0 0x%08x Config1 0x%08x LLAddr 0x" TARGET_FMT_lx "\n",
8529 env->CP0_Config0, env->CP0_Config1, env->lladdr);
8530 if (env->hflags & MIPS_HFLAG_FPU)
8531 fpu_dump_state(env, f, cpu_fprintf, flags);
8532#if defined(TARGET_MIPS64) && defined(MIPS_DEBUG_SIGN_EXTENSIONS)
8533 cpu_mips_check_sign_extensions(env, f, cpu_fprintf, flags);
8534#endif
8535}
8536
8537static void mips_tcg_init(void)
8538{
8539 int i;
8540 static int inited;
8541
8542 /* Initialize various static tables. */
8543 if (inited)
8544 return;
8545
8546 cpu_env = tcg_global_reg_new_ptr(TCG_AREG0, "env");
8547 TCGV_UNUSED(cpu_gpr[0]);
8548 for (i = 1; i < 32; i++)
8549 cpu_gpr[i] = tcg_global_mem_new(TCG_AREG0,
David 'Digit' Turnere2678e12014-01-16 15:56:43 +01008550 offsetof(CPUMIPSState, active_tc.gpr[i]),
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08008551 regnames[i]);
8552 cpu_PC = tcg_global_mem_new(TCG_AREG0,
David 'Digit' Turnere2678e12014-01-16 15:56:43 +01008553 offsetof(CPUMIPSState, active_tc.PC), "PC");
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08008554 for (i = 0; i < MIPS_DSP_ACC; i++) {
8555 cpu_HI[i] = tcg_global_mem_new(TCG_AREG0,
David 'Digit' Turnere2678e12014-01-16 15:56:43 +01008556 offsetof(CPUMIPSState, active_tc.HI[i]),
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08008557 regnames_HI[i]);
8558 cpu_LO[i] = tcg_global_mem_new(TCG_AREG0,
David 'Digit' Turnere2678e12014-01-16 15:56:43 +01008559 offsetof(CPUMIPSState, active_tc.LO[i]),
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08008560 regnames_LO[i]);
8561 cpu_ACX[i] = tcg_global_mem_new(TCG_AREG0,
David 'Digit' Turnere2678e12014-01-16 15:56:43 +01008562 offsetof(CPUMIPSState, active_tc.ACX[i]),
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08008563 regnames_ACX[i]);
8564 }
8565 cpu_dspctrl = tcg_global_mem_new(TCG_AREG0,
David 'Digit' Turnere2678e12014-01-16 15:56:43 +01008566 offsetof(CPUMIPSState, active_tc.DSPControl),
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08008567 "DSPControl");
8568 bcond = tcg_global_mem_new(TCG_AREG0,
David 'Digit' Turnere2678e12014-01-16 15:56:43 +01008569 offsetof(CPUMIPSState, bcond), "bcond");
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08008570 btarget = tcg_global_mem_new(TCG_AREG0,
David 'Digit' Turnere2678e12014-01-16 15:56:43 +01008571 offsetof(CPUMIPSState, btarget), "btarget");
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08008572 hflags = tcg_global_mem_new_i32(TCG_AREG0,
David 'Digit' Turnere2678e12014-01-16 15:56:43 +01008573 offsetof(CPUMIPSState, hflags), "hflags");
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08008574
8575 fpu_fcr0 = tcg_global_mem_new_i32(TCG_AREG0,
David 'Digit' Turnere2678e12014-01-16 15:56:43 +01008576 offsetof(CPUMIPSState, active_fpu.fcr0),
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08008577 "fcr0");
8578 fpu_fcr31 = tcg_global_mem_new_i32(TCG_AREG0,
David 'Digit' Turnere2678e12014-01-16 15:56:43 +01008579 offsetof(CPUMIPSState, active_fpu.fcr31),
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08008580 "fcr31");
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08008581 inited = 1;
8582}
8583
8584#include "translate_init.c"
8585
8586CPUMIPSState *cpu_mips_init (const char *cpu_model)
8587{
David 'Digit' Turner66576782014-03-24 16:57:57 +01008588 MIPSCPU *mips_cpu;
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08008589 CPUMIPSState *env;
David 'Digit' Turner66576782014-03-24 16:57:57 +01008590 CPUState *cpu;
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08008591 const mips_def_t *def;
8592
8593 def = cpu_mips_find_by_name(cpu_model);
8594 if (!def)
8595 return NULL;
David 'Digit' Turner66576782014-03-24 16:57:57 +01008596 mips_cpu = g_malloc0(sizeof(MIPSCPU));
8597 env = &mips_cpu->env;
8598 ENV_GET_CPU(env)->env_ptr = env;
8599
8600 cpu = ENV_GET_CPU(env);
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08008601 env->cpu_model = def;
David 'Digit' Turner66576782014-03-24 16:57:57 +01008602 cpu->cpu_model_str = cpu_model;
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08008603
8604 cpu_exec_init(env);
8605#ifndef CONFIG_USER_ONLY
8606 mmu_init(env, def);
8607#endif
8608 mvp_init(env, def);
8609 mips_tcg_init();
David 'Digit' Turnerbf7a22f2014-03-25 16:36:03 +01008610 cpu_reset(cpu);
8611 qemu_init_vcpu(cpu);
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08008612 return env;
8613}
8614
David 'Digit' Turnerbf7a22f2014-03-25 16:36:03 +01008615void cpu_reset(CPUState *cpu)
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08008616{
David 'Digit' Turnerbf7a22f2014-03-25 16:36:03 +01008617 CPUMIPSState *env = cpu->env_ptr;
8618
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08008619 if (qemu_loglevel_mask(CPU_LOG_RESET)) {
David 'Digit' Turnerbf7a22f2014-03-25 16:36:03 +01008620 qemu_log("CPU Reset (CPU %d)\n", cpu->cpu_index);
8621 log_cpu_state(cpu, 0);
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08008622 }
8623
8624 memset(env, 0, offsetof(CPUMIPSState, breakpoints));
8625 tlb_flush(env, 1);
8626
8627 /* Reset registers to their default values */
8628 env->CP0_PRid = env->cpu_model->CP0_PRid;
8629 env->CP0_Config0 = env->cpu_model->CP0_Config0;
8630#ifdef TARGET_WORDS_BIGENDIAN
8631 env->CP0_Config0 |= (1 << CP0C0_BE);
8632#endif
8633 env->CP0_Config1 = env->cpu_model->CP0_Config1;
8634 env->CP0_Config2 = env->cpu_model->CP0_Config2;
8635 env->CP0_Config3 = env->cpu_model->CP0_Config3;
8636 env->CP0_Config6 = env->cpu_model->CP0_Config6;
8637 env->CP0_Config7 = env->cpu_model->CP0_Config7;
8638 env->CP0_LLAddr_rw_bitmask = env->cpu_model->CP0_LLAddr_rw_bitmask
8639 << env->cpu_model->CP0_LLAddr_shift;
8640 env->CP0_LLAddr_shift = env->cpu_model->CP0_LLAddr_shift;
8641 env->SYNCI_Step = env->cpu_model->SYNCI_Step;
8642 env->CCRes = env->cpu_model->CCRes;
8643 env->CP0_Status_rw_bitmask = env->cpu_model->CP0_Status_rw_bitmask;
8644 env->CP0_TCStatus_rw_bitmask = env->cpu_model->CP0_TCStatus_rw_bitmask;
8645 env->CP0_SRSCtl = env->cpu_model->CP0_SRSCtl;
8646 env->current_tc = 0;
8647 env->SEGBITS = env->cpu_model->SEGBITS;
8648 env->SEGMask = (target_ulong)((1ULL << env->cpu_model->SEGBITS) - 1);
8649#if defined(TARGET_MIPS64)
8650 if (env->cpu_model->insn_flags & ISA_MIPS3) {
8651 env->SEGMask |= 3ULL << 62;
8652 }
8653#endif
8654 env->PABITS = env->cpu_model->PABITS;
8655 env->PAMask = (target_ulong)((1ULL << env->cpu_model->PABITS) - 1);
8656 env->CP0_SRSConf0_rw_bitmask = env->cpu_model->CP0_SRSConf0_rw_bitmask;
8657 env->CP0_SRSConf0 = env->cpu_model->CP0_SRSConf0;
8658 env->CP0_SRSConf1_rw_bitmask = env->cpu_model->CP0_SRSConf1_rw_bitmask;
8659 env->CP0_SRSConf1 = env->cpu_model->CP0_SRSConf1;
8660 env->CP0_SRSConf2_rw_bitmask = env->cpu_model->CP0_SRSConf2_rw_bitmask;
8661 env->CP0_SRSConf2 = env->cpu_model->CP0_SRSConf2;
8662 env->CP0_SRSConf3_rw_bitmask = env->cpu_model->CP0_SRSConf3_rw_bitmask;
8663 env->CP0_SRSConf3 = env->cpu_model->CP0_SRSConf3;
8664 env->CP0_SRSConf4_rw_bitmask = env->cpu_model->CP0_SRSConf4_rw_bitmask;
8665 env->CP0_SRSConf4 = env->cpu_model->CP0_SRSConf4;
8666 env->insn_flags = env->cpu_model->insn_flags;
8667
8668 fpu_init(env, env->cpu_model);
8669
8670#if defined(CONFIG_USER_ONLY)
8671 env->hflags = MIPS_HFLAG_UM;
8672 /* Enable access to the SYNCI_Step register. */
8673 env->CP0_HWREna |= (1 << 1);
8674 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
8675 env->hflags |= MIPS_HFLAG_FPU;
8676 }
8677#ifdef TARGET_MIPS64
8678 if (env->active_fpu.fcr0 & (1 << FCR0_F64)) {
8679 env->hflags |= MIPS_HFLAG_F64;
8680 }
8681#endif
8682#else
8683 if (env->hflags & MIPS_HFLAG_BMASK) {
8684 /* If the exception was raised from a delay slot,
8685 come back to the jump. */
8686 env->CP0_ErrorEPC = env->active_tc.PC - 4;
8687 } else {
8688 env->CP0_ErrorEPC = env->active_tc.PC;
8689 }
8690 env->active_tc.PC = (int32_t)0xBFC00000;
8691 env->CP0_Random = env->tlb->nb_tlb - 1;
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08008692 env->CP0_Wired = 0;
8693 /* SMP not implemented */
8694 env->CP0_EBase = 0x80000000;
8695 env->CP0_Status = (1 << CP0St_BEV) | (1 << CP0St_ERL);
8696 /* vectored interrupts not implemented, timer on int 7,
8697 no performance counters. */
8698 env->CP0_IntCtl = 0xe0000000;
8699 {
8700 int i;
8701
8702 for (i = 0; i < 7; i++) {
8703 env->CP0_WatchLo[i] = 0;
8704 env->CP0_WatchHi[i] = 0x80000000;
8705 }
8706 env->CP0_WatchLo[7] = 0;
8707 env->CP0_WatchHi[7] = 0;
8708 }
8709 /* Count register increments in debug mode, EJTAG version 1 */
8710 env->CP0_Debug = (1 << CP0DB_CNT) | (0x1 << CP0DB_VER);
8711 env->hflags = MIPS_HFLAG_CP0;
8712#endif
8713#if defined(TARGET_MIPS64)
8714 if (env->cpu_model->insn_flags & ISA_MIPS3) {
8715 env->hflags |= MIPS_HFLAG_64;
8716 }
8717#endif
8718 env->exception_index = EXCP_NONE;
8719}
8720
David 'Digit' Turnere2678e12014-01-16 15:56:43 +01008721void restore_state_to_opc(CPUMIPSState *env, TranslationBlock *tb, int pc_pos)
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08008722{
David 'Digit' Turner975bba82014-02-17 23:33:29 +01008723 env->active_tc.PC = tcg_ctx.gen_opc_pc[pc_pos];
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08008724 env->hflags &= ~MIPS_HFLAG_BMASK;
David 'Digit' Turner86b1fb02014-03-21 15:20:21 +01008725 env->hflags |= gen_opc_hflags[pc_pos];
Bhanu Chetlapalli409c7b62012-01-31 16:25:04 -08008726}