block: Free iovec arrays allocated by multiwrite_merge()
[qemu/stefanha.git] / target-mips / translate.c
blob7cb539d407bb6d7f64466a0d32ff9a0171a22ae3
1 /*
2 * MIPS32 emulation for qemu: main translation routines.
4 * Copyright (c) 2004-2005 Jocelyn Mayer
5 * Copyright (c) 2006 Marius Groeger (FPU operations)
6 * Copyright (c) 2006 Thiemo Seufer (MIPS32R2 support)
7 * Copyright (c) 2009 CodeSourcery (MIPS16 support)
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation; either
12 * version 2 of the License, or (at your option) any later version.
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
23 #include <stdarg.h>
24 #include <stdlib.h>
25 #include <stdio.h>
26 #include <string.h>
27 #include <inttypes.h>
29 #include "cpu.h"
30 #include "exec-all.h"
31 #include "disas.h"
32 #include "tcg-op.h"
33 #include "qemu-common.h"
35 #include "helper.h"
36 #define GEN_HELPER 1
37 #include "helper.h"
39 //#define MIPS_DEBUG_DISAS
40 //#define MIPS_DEBUG_SIGN_EXTENSIONS
42 /* MIPS major opcodes */
43 #define MASK_OP_MAJOR(op) (op & (0x3F << 26))
45 enum {
46 /* indirect opcode tables */
47 OPC_SPECIAL = (0x00 << 26),
48 OPC_REGIMM = (0x01 << 26),
49 OPC_CP0 = (0x10 << 26),
50 OPC_CP1 = (0x11 << 26),
51 OPC_CP2 = (0x12 << 26),
52 OPC_CP3 = (0x13 << 26),
53 OPC_SPECIAL2 = (0x1C << 26),
54 OPC_SPECIAL3 = (0x1F << 26),
55 /* arithmetic with immediate */
56 OPC_ADDI = (0x08 << 26),
57 OPC_ADDIU = (0x09 << 26),
58 OPC_SLTI = (0x0A << 26),
59 OPC_SLTIU = (0x0B << 26),
60 /* logic with immediate */
61 OPC_ANDI = (0x0C << 26),
62 OPC_ORI = (0x0D << 26),
63 OPC_XORI = (0x0E << 26),
64 OPC_LUI = (0x0F << 26),
65 /* arithmetic with immediate */
66 OPC_DADDI = (0x18 << 26),
67 OPC_DADDIU = (0x19 << 26),
68 /* Jump and branches */
69 OPC_J = (0x02 << 26),
70 OPC_JAL = (0x03 << 26),
71 OPC_BEQ = (0x04 << 26), /* Unconditional if rs = rt = 0 (B) */
72 OPC_BEQL = (0x14 << 26),
73 OPC_BNE = (0x05 << 26),
74 OPC_BNEL = (0x15 << 26),
75 OPC_BLEZ = (0x06 << 26),
76 OPC_BLEZL = (0x16 << 26),
77 OPC_BGTZ = (0x07 << 26),
78 OPC_BGTZL = (0x17 << 26),
79 OPC_JALX = (0x1D << 26), /* MIPS 16 only */
80 /* Load and stores */
81 OPC_LDL = (0x1A << 26),
82 OPC_LDR = (0x1B << 26),
83 OPC_LB = (0x20 << 26),
84 OPC_LH = (0x21 << 26),
85 OPC_LWL = (0x22 << 26),
86 OPC_LW = (0x23 << 26),
87 OPC_LWPC = OPC_LW | 0x5,
88 OPC_LBU = (0x24 << 26),
89 OPC_LHU = (0x25 << 26),
90 OPC_LWR = (0x26 << 26),
91 OPC_LWU = (0x27 << 26),
92 OPC_SB = (0x28 << 26),
93 OPC_SH = (0x29 << 26),
94 OPC_SWL = (0x2A << 26),
95 OPC_SW = (0x2B << 26),
96 OPC_SDL = (0x2C << 26),
97 OPC_SDR = (0x2D << 26),
98 OPC_SWR = (0x2E << 26),
99 OPC_LL = (0x30 << 26),
100 OPC_LLD = (0x34 << 26),
101 OPC_LD = (0x37 << 26),
102 OPC_LDPC = OPC_LD | 0x5,
103 OPC_SC = (0x38 << 26),
104 OPC_SCD = (0x3C << 26),
105 OPC_SD = (0x3F << 26),
106 /* Floating point load/store */
107 OPC_LWC1 = (0x31 << 26),
108 OPC_LWC2 = (0x32 << 26),
109 OPC_LDC1 = (0x35 << 26),
110 OPC_LDC2 = (0x36 << 26),
111 OPC_SWC1 = (0x39 << 26),
112 OPC_SWC2 = (0x3A << 26),
113 OPC_SDC1 = (0x3D << 26),
114 OPC_SDC2 = (0x3E << 26),
115 /* MDMX ASE specific */
116 OPC_MDMX = (0x1E << 26),
117 /* Cache and prefetch */
118 OPC_CACHE = (0x2F << 26),
119 OPC_PREF = (0x33 << 26),
120 /* Reserved major opcode */
121 OPC_MAJOR3B_RESERVED = (0x3B << 26),
124 /* MIPS special opcodes */
125 #define MASK_SPECIAL(op) MASK_OP_MAJOR(op) | (op & 0x3F)
127 enum {
128 /* Shifts */
129 OPC_SLL = 0x00 | OPC_SPECIAL,
130 /* NOP is SLL r0, r0, 0 */
131 /* SSNOP is SLL r0, r0, 1 */
132 /* EHB is SLL r0, r0, 3 */
133 OPC_SRL = 0x02 | OPC_SPECIAL, /* also ROTR */
134 OPC_ROTR = OPC_SRL | (1 << 21),
135 OPC_SRA = 0x03 | OPC_SPECIAL,
136 OPC_SLLV = 0x04 | OPC_SPECIAL,
137 OPC_SRLV = 0x06 | OPC_SPECIAL, /* also ROTRV */
138 OPC_ROTRV = OPC_SRLV | (1 << 6),
139 OPC_SRAV = 0x07 | OPC_SPECIAL,
140 OPC_DSLLV = 0x14 | OPC_SPECIAL,
141 OPC_DSRLV = 0x16 | OPC_SPECIAL, /* also DROTRV */
142 OPC_DROTRV = OPC_DSRLV | (1 << 6),
143 OPC_DSRAV = 0x17 | OPC_SPECIAL,
144 OPC_DSLL = 0x38 | OPC_SPECIAL,
145 OPC_DSRL = 0x3A | OPC_SPECIAL, /* also DROTR */
146 OPC_DROTR = OPC_DSRL | (1 << 21),
147 OPC_DSRA = 0x3B | OPC_SPECIAL,
148 OPC_DSLL32 = 0x3C | OPC_SPECIAL,
149 OPC_DSRL32 = 0x3E | OPC_SPECIAL, /* also DROTR32 */
150 OPC_DROTR32 = OPC_DSRL32 | (1 << 21),
151 OPC_DSRA32 = 0x3F | OPC_SPECIAL,
152 /* Multiplication / division */
153 OPC_MULT = 0x18 | OPC_SPECIAL,
154 OPC_MULTU = 0x19 | OPC_SPECIAL,
155 OPC_DIV = 0x1A | OPC_SPECIAL,
156 OPC_DIVU = 0x1B | OPC_SPECIAL,
157 OPC_DMULT = 0x1C | OPC_SPECIAL,
158 OPC_DMULTU = 0x1D | OPC_SPECIAL,
159 OPC_DDIV = 0x1E | OPC_SPECIAL,
160 OPC_DDIVU = 0x1F | OPC_SPECIAL,
161 /* 2 registers arithmetic / logic */
162 OPC_ADD = 0x20 | OPC_SPECIAL,
163 OPC_ADDU = 0x21 | OPC_SPECIAL,
164 OPC_SUB = 0x22 | OPC_SPECIAL,
165 OPC_SUBU = 0x23 | OPC_SPECIAL,
166 OPC_AND = 0x24 | OPC_SPECIAL,
167 OPC_OR = 0x25 | OPC_SPECIAL,
168 OPC_XOR = 0x26 | OPC_SPECIAL,
169 OPC_NOR = 0x27 | OPC_SPECIAL,
170 OPC_SLT = 0x2A | OPC_SPECIAL,
171 OPC_SLTU = 0x2B | OPC_SPECIAL,
172 OPC_DADD = 0x2C | OPC_SPECIAL,
173 OPC_DADDU = 0x2D | OPC_SPECIAL,
174 OPC_DSUB = 0x2E | OPC_SPECIAL,
175 OPC_DSUBU = 0x2F | OPC_SPECIAL,
176 /* Jumps */
177 OPC_JR = 0x08 | OPC_SPECIAL, /* Also JR.HB */
178 OPC_JALR = 0x09 | OPC_SPECIAL, /* Also JALR.HB */
179 OPC_JALRC = OPC_JALR | (0x5 << 6),
180 /* Traps */
181 OPC_TGE = 0x30 | OPC_SPECIAL,
182 OPC_TGEU = 0x31 | OPC_SPECIAL,
183 OPC_TLT = 0x32 | OPC_SPECIAL,
184 OPC_TLTU = 0x33 | OPC_SPECIAL,
185 OPC_TEQ = 0x34 | OPC_SPECIAL,
186 OPC_TNE = 0x36 | OPC_SPECIAL,
187 /* HI / LO registers load & stores */
188 OPC_MFHI = 0x10 | OPC_SPECIAL,
189 OPC_MTHI = 0x11 | OPC_SPECIAL,
190 OPC_MFLO = 0x12 | OPC_SPECIAL,
191 OPC_MTLO = 0x13 | OPC_SPECIAL,
192 /* Conditional moves */
193 OPC_MOVZ = 0x0A | OPC_SPECIAL,
194 OPC_MOVN = 0x0B | OPC_SPECIAL,
196 OPC_MOVCI = 0x01 | OPC_SPECIAL,
198 /* Special */
199 OPC_PMON = 0x05 | OPC_SPECIAL, /* unofficial */
200 OPC_SYSCALL = 0x0C | OPC_SPECIAL,
201 OPC_BREAK = 0x0D | OPC_SPECIAL,
202 OPC_SPIM = 0x0E | OPC_SPECIAL, /* unofficial */
203 OPC_SYNC = 0x0F | OPC_SPECIAL,
205 OPC_SPECIAL15_RESERVED = 0x15 | OPC_SPECIAL,
206 OPC_SPECIAL28_RESERVED = 0x28 | OPC_SPECIAL,
207 OPC_SPECIAL29_RESERVED = 0x29 | OPC_SPECIAL,
208 OPC_SPECIAL35_RESERVED = 0x35 | OPC_SPECIAL,
209 OPC_SPECIAL37_RESERVED = 0x37 | OPC_SPECIAL,
210 OPC_SPECIAL39_RESERVED = 0x39 | OPC_SPECIAL,
211 OPC_SPECIAL3D_RESERVED = 0x3D | OPC_SPECIAL,
214 /* Multiplication variants of the vr54xx. */
215 #define MASK_MUL_VR54XX(op) MASK_SPECIAL(op) | (op & (0x1F << 6))
217 enum {
218 OPC_VR54XX_MULS = (0x03 << 6) | OPC_MULT,
219 OPC_VR54XX_MULSU = (0x03 << 6) | OPC_MULTU,
220 OPC_VR54XX_MACC = (0x05 << 6) | OPC_MULT,
221 OPC_VR54XX_MACCU = (0x05 << 6) | OPC_MULTU,
222 OPC_VR54XX_MSAC = (0x07 << 6) | OPC_MULT,
223 OPC_VR54XX_MSACU = (0x07 << 6) | OPC_MULTU,
224 OPC_VR54XX_MULHI = (0x09 << 6) | OPC_MULT,
225 OPC_VR54XX_MULHIU = (0x09 << 6) | OPC_MULTU,
226 OPC_VR54XX_MULSHI = (0x0B << 6) | OPC_MULT,
227 OPC_VR54XX_MULSHIU = (0x0B << 6) | OPC_MULTU,
228 OPC_VR54XX_MACCHI = (0x0D << 6) | OPC_MULT,
229 OPC_VR54XX_MACCHIU = (0x0D << 6) | OPC_MULTU,
230 OPC_VR54XX_MSACHI = (0x0F << 6) | OPC_MULT,
231 OPC_VR54XX_MSACHIU = (0x0F << 6) | OPC_MULTU,
234 /* REGIMM (rt field) opcodes */
235 #define MASK_REGIMM(op) MASK_OP_MAJOR(op) | (op & (0x1F << 16))
237 enum {
238 OPC_BLTZ = (0x00 << 16) | OPC_REGIMM,
239 OPC_BLTZL = (0x02 << 16) | OPC_REGIMM,
240 OPC_BGEZ = (0x01 << 16) | OPC_REGIMM,
241 OPC_BGEZL = (0x03 << 16) | OPC_REGIMM,
242 OPC_BLTZAL = (0x10 << 16) | OPC_REGIMM,
243 OPC_BLTZALL = (0x12 << 16) | OPC_REGIMM,
244 OPC_BGEZAL = (0x11 << 16) | OPC_REGIMM,
245 OPC_BGEZALL = (0x13 << 16) | OPC_REGIMM,
246 OPC_TGEI = (0x08 << 16) | OPC_REGIMM,
247 OPC_TGEIU = (0x09 << 16) | OPC_REGIMM,
248 OPC_TLTI = (0x0A << 16) | OPC_REGIMM,
249 OPC_TLTIU = (0x0B << 16) | OPC_REGIMM,
250 OPC_TEQI = (0x0C << 16) | OPC_REGIMM,
251 OPC_TNEI = (0x0E << 16) | OPC_REGIMM,
252 OPC_SYNCI = (0x1F << 16) | OPC_REGIMM,
255 /* Special2 opcodes */
256 #define MASK_SPECIAL2(op) MASK_OP_MAJOR(op) | (op & 0x3F)
258 enum {
259 /* Multiply & xxx operations */
260 OPC_MADD = 0x00 | OPC_SPECIAL2,
261 OPC_MADDU = 0x01 | OPC_SPECIAL2,
262 OPC_MUL = 0x02 | OPC_SPECIAL2,
263 OPC_MSUB = 0x04 | OPC_SPECIAL2,
264 OPC_MSUBU = 0x05 | OPC_SPECIAL2,
265 /* Misc */
266 OPC_CLZ = 0x20 | OPC_SPECIAL2,
267 OPC_CLO = 0x21 | OPC_SPECIAL2,
268 OPC_DCLZ = 0x24 | OPC_SPECIAL2,
269 OPC_DCLO = 0x25 | OPC_SPECIAL2,
270 /* Special */
271 OPC_SDBBP = 0x3F | OPC_SPECIAL2,
274 /* Special3 opcodes */
275 #define MASK_SPECIAL3(op) MASK_OP_MAJOR(op) | (op & 0x3F)
277 enum {
278 OPC_EXT = 0x00 | OPC_SPECIAL3,
279 OPC_DEXTM = 0x01 | OPC_SPECIAL3,
280 OPC_DEXTU = 0x02 | OPC_SPECIAL3,
281 OPC_DEXT = 0x03 | OPC_SPECIAL3,
282 OPC_INS = 0x04 | OPC_SPECIAL3,
283 OPC_DINSM = 0x05 | OPC_SPECIAL3,
284 OPC_DINSU = 0x06 | OPC_SPECIAL3,
285 OPC_DINS = 0x07 | OPC_SPECIAL3,
286 OPC_FORK = 0x08 | OPC_SPECIAL3,
287 OPC_YIELD = 0x09 | OPC_SPECIAL3,
288 OPC_BSHFL = 0x20 | OPC_SPECIAL3,
289 OPC_DBSHFL = 0x24 | OPC_SPECIAL3,
290 OPC_RDHWR = 0x3B | OPC_SPECIAL3,
293 /* BSHFL opcodes */
294 #define MASK_BSHFL(op) MASK_SPECIAL3(op) | (op & (0x1F << 6))
296 enum {
297 OPC_WSBH = (0x02 << 6) | OPC_BSHFL,
298 OPC_SEB = (0x10 << 6) | OPC_BSHFL,
299 OPC_SEH = (0x18 << 6) | OPC_BSHFL,
302 /* DBSHFL opcodes */
303 #define MASK_DBSHFL(op) MASK_SPECIAL3(op) | (op & (0x1F << 6))
305 enum {
306 OPC_DSBH = (0x02 << 6) | OPC_DBSHFL,
307 OPC_DSHD = (0x05 << 6) | OPC_DBSHFL,
310 /* Coprocessor 0 (rs field) */
311 #define MASK_CP0(op) MASK_OP_MAJOR(op) | (op & (0x1F << 21))
313 enum {
314 OPC_MFC0 = (0x00 << 21) | OPC_CP0,
315 OPC_DMFC0 = (0x01 << 21) | OPC_CP0,
316 OPC_MTC0 = (0x04 << 21) | OPC_CP0,
317 OPC_DMTC0 = (0x05 << 21) | OPC_CP0,
318 OPC_MFTR = (0x08 << 21) | OPC_CP0,
319 OPC_RDPGPR = (0x0A << 21) | OPC_CP0,
320 OPC_MFMC0 = (0x0B << 21) | OPC_CP0,
321 OPC_MTTR = (0x0C << 21) | OPC_CP0,
322 OPC_WRPGPR = (0x0E << 21) | OPC_CP0,
323 OPC_C0 = (0x10 << 21) | OPC_CP0,
324 OPC_C0_FIRST = (0x10 << 21) | OPC_CP0,
325 OPC_C0_LAST = (0x1F << 21) | OPC_CP0,
328 /* MFMC0 opcodes */
329 #define MASK_MFMC0(op) MASK_CP0(op) | (op & 0xFFFF)
331 enum {
332 OPC_DMT = 0x01 | (0 << 5) | (0x0F << 6) | (0x01 << 11) | OPC_MFMC0,
333 OPC_EMT = 0x01 | (1 << 5) | (0x0F << 6) | (0x01 << 11) | OPC_MFMC0,
334 OPC_DVPE = 0x01 | (0 << 5) | OPC_MFMC0,
335 OPC_EVPE = 0x01 | (1 << 5) | OPC_MFMC0,
336 OPC_DI = (0 << 5) | (0x0C << 11) | OPC_MFMC0,
337 OPC_EI = (1 << 5) | (0x0C << 11) | OPC_MFMC0,
340 /* Coprocessor 0 (with rs == C0) */
341 #define MASK_C0(op) MASK_CP0(op) | (op & 0x3F)
343 enum {
344 OPC_TLBR = 0x01 | OPC_C0,
345 OPC_TLBWI = 0x02 | OPC_C0,
346 OPC_TLBWR = 0x06 | OPC_C0,
347 OPC_TLBP = 0x08 | OPC_C0,
348 OPC_RFE = 0x10 | OPC_C0,
349 OPC_ERET = 0x18 | OPC_C0,
350 OPC_DERET = 0x1F | OPC_C0,
351 OPC_WAIT = 0x20 | OPC_C0,
354 /* Coprocessor 1 (rs field) */
355 #define MASK_CP1(op) MASK_OP_MAJOR(op) | (op & (0x1F << 21))
357 enum {
358 OPC_MFC1 = (0x00 << 21) | OPC_CP1,
359 OPC_DMFC1 = (0x01 << 21) | OPC_CP1,
360 OPC_CFC1 = (0x02 << 21) | OPC_CP1,
361 OPC_MFHC1 = (0x03 << 21) | OPC_CP1,
362 OPC_MTC1 = (0x04 << 21) | OPC_CP1,
363 OPC_DMTC1 = (0x05 << 21) | OPC_CP1,
364 OPC_CTC1 = (0x06 << 21) | OPC_CP1,
365 OPC_MTHC1 = (0x07 << 21) | OPC_CP1,
366 OPC_BC1 = (0x08 << 21) | OPC_CP1, /* bc */
367 OPC_BC1ANY2 = (0x09 << 21) | OPC_CP1,
368 OPC_BC1ANY4 = (0x0A << 21) | OPC_CP1,
369 OPC_S_FMT = (0x10 << 21) | OPC_CP1, /* 16: fmt=single fp */
370 OPC_D_FMT = (0x11 << 21) | OPC_CP1, /* 17: fmt=double fp */
371 OPC_E_FMT = (0x12 << 21) | OPC_CP1, /* 18: fmt=extended fp */
372 OPC_Q_FMT = (0x13 << 21) | OPC_CP1, /* 19: fmt=quad fp */
373 OPC_W_FMT = (0x14 << 21) | OPC_CP1, /* 20: fmt=32bit fixed */
374 OPC_L_FMT = (0x15 << 21) | OPC_CP1, /* 21: fmt=64bit fixed */
375 OPC_PS_FMT = (0x16 << 21) | OPC_CP1, /* 22: fmt=paired single fp */
378 #define MASK_CP1_FUNC(op) MASK_CP1(op) | (op & 0x3F)
379 #define MASK_BC1(op) MASK_CP1(op) | (op & (0x3 << 16))
381 enum {
382 OPC_BC1F = (0x00 << 16) | OPC_BC1,
383 OPC_BC1T = (0x01 << 16) | OPC_BC1,
384 OPC_BC1FL = (0x02 << 16) | OPC_BC1,
385 OPC_BC1TL = (0x03 << 16) | OPC_BC1,
388 enum {
389 OPC_BC1FANY2 = (0x00 << 16) | OPC_BC1ANY2,
390 OPC_BC1TANY2 = (0x01 << 16) | OPC_BC1ANY2,
393 enum {
394 OPC_BC1FANY4 = (0x00 << 16) | OPC_BC1ANY4,
395 OPC_BC1TANY4 = (0x01 << 16) | OPC_BC1ANY4,
398 #define MASK_CP2(op) MASK_OP_MAJOR(op) | (op & (0x1F << 21))
400 enum {
401 OPC_MFC2 = (0x00 << 21) | OPC_CP2,
402 OPC_DMFC2 = (0x01 << 21) | OPC_CP2,
403 OPC_CFC2 = (0x02 << 21) | OPC_CP2,
404 OPC_MFHC2 = (0x03 << 21) | OPC_CP2,
405 OPC_MTC2 = (0x04 << 21) | OPC_CP2,
406 OPC_DMTC2 = (0x05 << 21) | OPC_CP2,
407 OPC_CTC2 = (0x06 << 21) | OPC_CP2,
408 OPC_MTHC2 = (0x07 << 21) | OPC_CP2,
409 OPC_BC2 = (0x08 << 21) | OPC_CP2,
412 #define MASK_CP3(op) MASK_OP_MAJOR(op) | (op & 0x3F)
414 enum {
415 OPC_LWXC1 = 0x00 | OPC_CP3,
416 OPC_LDXC1 = 0x01 | OPC_CP3,
417 OPC_LUXC1 = 0x05 | OPC_CP3,
418 OPC_SWXC1 = 0x08 | OPC_CP3,
419 OPC_SDXC1 = 0x09 | OPC_CP3,
420 OPC_SUXC1 = 0x0D | OPC_CP3,
421 OPC_PREFX = 0x0F | OPC_CP3,
422 OPC_ALNV_PS = 0x1E | OPC_CP3,
423 OPC_MADD_S = 0x20 | OPC_CP3,
424 OPC_MADD_D = 0x21 | OPC_CP3,
425 OPC_MADD_PS = 0x26 | OPC_CP3,
426 OPC_MSUB_S = 0x28 | OPC_CP3,
427 OPC_MSUB_D = 0x29 | OPC_CP3,
428 OPC_MSUB_PS = 0x2E | OPC_CP3,
429 OPC_NMADD_S = 0x30 | OPC_CP3,
430 OPC_NMADD_D = 0x31 | OPC_CP3,
431 OPC_NMADD_PS= 0x36 | OPC_CP3,
432 OPC_NMSUB_S = 0x38 | OPC_CP3,
433 OPC_NMSUB_D = 0x39 | OPC_CP3,
434 OPC_NMSUB_PS= 0x3E | OPC_CP3,
437 /* global register indices */
438 static TCGv_ptr cpu_env;
439 static TCGv cpu_gpr[32], cpu_PC;
440 static TCGv cpu_HI[MIPS_DSP_ACC], cpu_LO[MIPS_DSP_ACC], cpu_ACX[MIPS_DSP_ACC];
441 static TCGv cpu_dspctrl, btarget, bcond;
442 static TCGv_i32 hflags;
443 static TCGv_i32 fpu_fcr0, fpu_fcr31;
445 static uint32_t gen_opc_hflags[OPC_BUF_SIZE];
447 #include "gen-icount.h"
449 #define gen_helper_0i(name, arg) do { \
450 TCGv_i32 helper_tmp = tcg_const_i32(arg); \
451 gen_helper_##name(helper_tmp); \
452 tcg_temp_free_i32(helper_tmp); \
453 } while(0)
455 #define gen_helper_1i(name, arg1, arg2) do { \
456 TCGv_i32 helper_tmp = tcg_const_i32(arg2); \
457 gen_helper_##name(arg1, helper_tmp); \
458 tcg_temp_free_i32(helper_tmp); \
459 } while(0)
461 #define gen_helper_2i(name, arg1, arg2, arg3) do { \
462 TCGv_i32 helper_tmp = tcg_const_i32(arg3); \
463 gen_helper_##name(arg1, arg2, helper_tmp); \
464 tcg_temp_free_i32(helper_tmp); \
465 } while(0)
467 #define gen_helper_3i(name, arg1, arg2, arg3, arg4) do { \
468 TCGv_i32 helper_tmp = tcg_const_i32(arg4); \
469 gen_helper_##name(arg1, arg2, arg3, helper_tmp); \
470 tcg_temp_free_i32(helper_tmp); \
471 } while(0)
473 typedef struct DisasContext {
474 struct TranslationBlock *tb;
475 target_ulong pc, saved_pc;
476 uint32_t opcode;
477 int singlestep_enabled;
478 /* Routine used to access memory */
479 int mem_idx;
480 uint32_t hflags, saved_hflags;
481 int bstate;
482 target_ulong btarget;
483 } DisasContext;
485 enum {
486 BS_NONE = 0, /* We go out of the TB without reaching a branch or an
487 * exception condition */
488 BS_STOP = 1, /* We want to stop translation for any reason */
489 BS_BRANCH = 2, /* We reached a branch condition */
490 BS_EXCP = 3, /* We reached an exception condition */
493 static const char *regnames[] =
494 { "r0", "at", "v0", "v1", "a0", "a1", "a2", "a3",
495 "t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7",
496 "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7",
497 "t8", "t9", "k0", "k1", "gp", "sp", "s8", "ra", };
499 static const char *regnames_HI[] =
500 { "HI0", "HI1", "HI2", "HI3", };
502 static const char *regnames_LO[] =
503 { "LO0", "LO1", "LO2", "LO3", };
505 static const char *regnames_ACX[] =
506 { "ACX0", "ACX1", "ACX2", "ACX3", };
508 static const char *fregnames[] =
509 { "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7",
510 "f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15",
511 "f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23",
512 "f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31", };
514 #ifdef MIPS_DEBUG_DISAS
515 #define MIPS_DEBUG(fmt, ...) \
516 qemu_log_mask(CPU_LOG_TB_IN_ASM, \
517 TARGET_FMT_lx ": %08x " fmt "\n", \
518 ctx->pc, ctx->opcode , ## __VA_ARGS__)
519 #define LOG_DISAS(...) qemu_log_mask(CPU_LOG_TB_IN_ASM, ## __VA_ARGS__)
520 #else
521 #define MIPS_DEBUG(fmt, ...) do { } while(0)
522 #define LOG_DISAS(...) do { } while (0)
523 #endif
525 #define MIPS_INVAL(op) \
526 do { \
527 MIPS_DEBUG("Invalid %s %03x %03x %03x", op, ctx->opcode >> 26, \
528 ctx->opcode & 0x3F, ((ctx->opcode >> 16) & 0x1F)); \
529 } while (0)
531 /* General purpose registers moves. */
532 static inline void gen_load_gpr (TCGv t, int reg)
534 if (reg == 0)
535 tcg_gen_movi_tl(t, 0);
536 else
537 tcg_gen_mov_tl(t, cpu_gpr[reg]);
540 static inline void gen_store_gpr (TCGv t, int reg)
542 if (reg != 0)
543 tcg_gen_mov_tl(cpu_gpr[reg], t);
546 /* Moves to/from ACX register. */
547 static inline void gen_load_ACX (TCGv t, int reg)
549 tcg_gen_mov_tl(t, cpu_ACX[reg]);
552 static inline void gen_store_ACX (TCGv t, int reg)
554 tcg_gen_mov_tl(cpu_ACX[reg], t);
557 /* Moves to/from shadow registers. */
558 static inline void gen_load_srsgpr (int from, int to)
560 TCGv t0 = tcg_temp_new();
562 if (from == 0)
563 tcg_gen_movi_tl(t0, 0);
564 else {
565 TCGv_i32 t2 = tcg_temp_new_i32();
566 TCGv_ptr addr = tcg_temp_new_ptr();
568 tcg_gen_ld_i32(t2, cpu_env, offsetof(CPUState, CP0_SRSCtl));
569 tcg_gen_shri_i32(t2, t2, CP0SRSCtl_PSS);
570 tcg_gen_andi_i32(t2, t2, 0xf);
571 tcg_gen_muli_i32(t2, t2, sizeof(target_ulong) * 32);
572 tcg_gen_ext_i32_ptr(addr, t2);
573 tcg_gen_add_ptr(addr, cpu_env, addr);
575 tcg_gen_ld_tl(t0, addr, sizeof(target_ulong) * from);
576 tcg_temp_free_ptr(addr);
577 tcg_temp_free_i32(t2);
579 gen_store_gpr(t0, to);
580 tcg_temp_free(t0);
583 static inline void gen_store_srsgpr (int from, int to)
585 if (to != 0) {
586 TCGv t0 = tcg_temp_new();
587 TCGv_i32 t2 = tcg_temp_new_i32();
588 TCGv_ptr addr = tcg_temp_new_ptr();
590 gen_load_gpr(t0, from);
591 tcg_gen_ld_i32(t2, cpu_env, offsetof(CPUState, CP0_SRSCtl));
592 tcg_gen_shri_i32(t2, t2, CP0SRSCtl_PSS);
593 tcg_gen_andi_i32(t2, t2, 0xf);
594 tcg_gen_muli_i32(t2, t2, sizeof(target_ulong) * 32);
595 tcg_gen_ext_i32_ptr(addr, t2);
596 tcg_gen_add_ptr(addr, cpu_env, addr);
598 tcg_gen_st_tl(t0, addr, sizeof(target_ulong) * to);
599 tcg_temp_free_ptr(addr);
600 tcg_temp_free_i32(t2);
601 tcg_temp_free(t0);
605 /* Floating point register moves. */
606 static inline void gen_load_fpr32 (TCGv_i32 t, int reg)
608 tcg_gen_ld_i32(t, cpu_env, offsetof(CPUState, active_fpu.fpr[reg].w[FP_ENDIAN_IDX]));
611 static inline void gen_store_fpr32 (TCGv_i32 t, int reg)
613 tcg_gen_st_i32(t, cpu_env, offsetof(CPUState, active_fpu.fpr[reg].w[FP_ENDIAN_IDX]));
616 static inline void gen_load_fpr32h (TCGv_i32 t, int reg)
618 tcg_gen_ld_i32(t, cpu_env, offsetof(CPUState, active_fpu.fpr[reg].w[!FP_ENDIAN_IDX]));
621 static inline void gen_store_fpr32h (TCGv_i32 t, int reg)
623 tcg_gen_st_i32(t, cpu_env, offsetof(CPUState, active_fpu.fpr[reg].w[!FP_ENDIAN_IDX]));
626 static inline void gen_load_fpr64 (DisasContext *ctx, TCGv_i64 t, int reg)
628 if (ctx->hflags & MIPS_HFLAG_F64) {
629 tcg_gen_ld_i64(t, cpu_env, offsetof(CPUState, active_fpu.fpr[reg].d));
630 } else {
631 TCGv_i32 t0 = tcg_temp_new_i32();
632 TCGv_i32 t1 = tcg_temp_new_i32();
633 gen_load_fpr32(t0, reg & ~1);
634 gen_load_fpr32(t1, reg | 1);
635 tcg_gen_concat_i32_i64(t, t0, t1);
636 tcg_temp_free_i32(t0);
637 tcg_temp_free_i32(t1);
641 static inline void gen_store_fpr64 (DisasContext *ctx, TCGv_i64 t, int reg)
643 if (ctx->hflags & MIPS_HFLAG_F64) {
644 tcg_gen_st_i64(t, cpu_env, offsetof(CPUState, active_fpu.fpr[reg].d));
645 } else {
646 TCGv_i64 t0 = tcg_temp_new_i64();
647 TCGv_i32 t1 = tcg_temp_new_i32();
648 tcg_gen_trunc_i64_i32(t1, t);
649 gen_store_fpr32(t1, reg & ~1);
650 tcg_gen_shri_i64(t0, t, 32);
651 tcg_gen_trunc_i64_i32(t1, t0);
652 gen_store_fpr32(t1, reg | 1);
653 tcg_temp_free_i32(t1);
654 tcg_temp_free_i64(t0);
658 static inline int get_fp_bit (int cc)
660 if (cc)
661 return 24 + cc;
662 else
663 return 23;
666 #define FOP_CONDS(type, fmt, bits) \
667 static inline void gen_cmp ## type ## _ ## fmt(int n, TCGv_i##bits a, \
668 TCGv_i##bits b, int cc) \
670 switch (n) { \
671 case 0: gen_helper_2i(cmp ## type ## _ ## fmt ## _f, a, b, cc); break;\
672 case 1: gen_helper_2i(cmp ## type ## _ ## fmt ## _un, a, b, cc); break;\
673 case 2: gen_helper_2i(cmp ## type ## _ ## fmt ## _eq, a, b, cc); break;\
674 case 3: gen_helper_2i(cmp ## type ## _ ## fmt ## _ueq, a, b, cc); break;\
675 case 4: gen_helper_2i(cmp ## type ## _ ## fmt ## _olt, a, b, cc); break;\
676 case 5: gen_helper_2i(cmp ## type ## _ ## fmt ## _ult, a, b, cc); break;\
677 case 6: gen_helper_2i(cmp ## type ## _ ## fmt ## _ole, a, b, cc); break;\
678 case 7: gen_helper_2i(cmp ## type ## _ ## fmt ## _ule, a, b, cc); break;\
679 case 8: gen_helper_2i(cmp ## type ## _ ## fmt ## _sf, a, b, cc); break;\
680 case 9: gen_helper_2i(cmp ## type ## _ ## fmt ## _ngle, a, b, cc); break;\
681 case 10: gen_helper_2i(cmp ## type ## _ ## fmt ## _seq, a, b, cc); break;\
682 case 11: gen_helper_2i(cmp ## type ## _ ## fmt ## _ngl, a, b, cc); break;\
683 case 12: gen_helper_2i(cmp ## type ## _ ## fmt ## _lt, a, b, cc); break;\
684 case 13: gen_helper_2i(cmp ## type ## _ ## fmt ## _nge, a, b, cc); break;\
685 case 14: gen_helper_2i(cmp ## type ## _ ## fmt ## _le, a, b, cc); break;\
686 case 15: gen_helper_2i(cmp ## type ## _ ## fmt ## _ngt, a, b, cc); break;\
687 default: abort(); \
691 FOP_CONDS(, d, 64)
692 FOP_CONDS(abs, d, 64)
693 FOP_CONDS(, s, 32)
694 FOP_CONDS(abs, s, 32)
695 FOP_CONDS(, ps, 64)
696 FOP_CONDS(abs, ps, 64)
697 #undef FOP_CONDS
699 /* Tests */
700 static inline void gen_save_pc(target_ulong pc)
702 tcg_gen_movi_tl(cpu_PC, pc);
705 static inline void save_cpu_state (DisasContext *ctx, int do_save_pc)
707 LOG_DISAS("hflags %08x saved %08x\n", ctx->hflags, ctx->saved_hflags);
708 if (do_save_pc && ctx->pc != ctx->saved_pc) {
709 gen_save_pc(ctx->pc);
710 ctx->saved_pc = ctx->pc;
712 if (ctx->hflags != ctx->saved_hflags) {
713 tcg_gen_movi_i32(hflags, ctx->hflags);
714 ctx->saved_hflags = ctx->hflags;
715 switch (ctx->hflags & MIPS_HFLAG_BMASK_BASE) {
716 case MIPS_HFLAG_BR:
717 break;
718 case MIPS_HFLAG_BC:
719 case MIPS_HFLAG_BL:
720 case MIPS_HFLAG_B:
721 tcg_gen_movi_tl(btarget, ctx->btarget);
722 break;
727 static inline void restore_cpu_state (CPUState *env, DisasContext *ctx)
729 ctx->saved_hflags = ctx->hflags;
730 switch (ctx->hflags & MIPS_HFLAG_BMASK_BASE) {
731 case MIPS_HFLAG_BR:
732 break;
733 case MIPS_HFLAG_BC:
734 case MIPS_HFLAG_BL:
735 case MIPS_HFLAG_B:
736 ctx->btarget = env->btarget;
737 break;
741 static inline void
742 generate_exception_err (DisasContext *ctx, int excp, int err)
744 TCGv_i32 texcp = tcg_const_i32(excp);
745 TCGv_i32 terr = tcg_const_i32(err);
746 save_cpu_state(ctx, 1);
747 gen_helper_raise_exception_err(texcp, terr);
748 tcg_temp_free_i32(terr);
749 tcg_temp_free_i32(texcp);
752 static inline void
753 generate_exception (DisasContext *ctx, int excp)
755 save_cpu_state(ctx, 1);
756 gen_helper_0i(raise_exception, excp);
759 /* Addresses computation */
760 static inline void gen_op_addr_add (DisasContext *ctx, TCGv ret, TCGv arg0, TCGv arg1)
762 tcg_gen_add_tl(ret, arg0, arg1);
764 #if defined(TARGET_MIPS64)
765 /* For compatibility with 32-bit code, data reference in user mode
766 with Status_UX = 0 should be casted to 32-bit and sign extended.
767 See the MIPS64 PRA manual, section 4.10. */
768 if (((ctx->hflags & MIPS_HFLAG_KSU) == MIPS_HFLAG_UM) &&
769 !(ctx->hflags & MIPS_HFLAG_UX)) {
770 tcg_gen_ext32s_i64(ret, ret);
772 #endif
775 static inline void check_cp0_enabled(DisasContext *ctx)
777 if (unlikely(!(ctx->hflags & MIPS_HFLAG_CP0)))
778 generate_exception_err(ctx, EXCP_CpU, 0);
781 static inline void check_cp1_enabled(DisasContext *ctx)
783 if (unlikely(!(ctx->hflags & MIPS_HFLAG_FPU)))
784 generate_exception_err(ctx, EXCP_CpU, 1);
787 /* Verify that the processor is running with COP1X instructions enabled.
788 This is associated with the nabla symbol in the MIPS32 and MIPS64
789 opcode tables. */
791 static inline void check_cop1x(DisasContext *ctx)
793 if (unlikely(!(ctx->hflags & MIPS_HFLAG_COP1X)))
794 generate_exception(ctx, EXCP_RI);
797 /* Verify that the processor is running with 64-bit floating-point
798 operations enabled. */
800 static inline void check_cp1_64bitmode(DisasContext *ctx)
802 if (unlikely(~ctx->hflags & (MIPS_HFLAG_F64 | MIPS_HFLAG_COP1X)))
803 generate_exception(ctx, EXCP_RI);
807 * Verify if floating point register is valid; an operation is not defined
808 * if bit 0 of any register specification is set and the FR bit in the
809 * Status register equals zero, since the register numbers specify an
810 * even-odd pair of adjacent coprocessor general registers. When the FR bit
811 * in the Status register equals one, both even and odd register numbers
812 * are valid. This limitation exists only for 64 bit wide (d,l,ps) registers.
814 * Multiple 64 bit wide registers can be checked by calling
815 * gen_op_cp1_registers(freg1 | freg2 | ... | fregN);
817 static inline void check_cp1_registers(DisasContext *ctx, int regs)
819 if (unlikely(!(ctx->hflags & MIPS_HFLAG_F64) && (regs & 1)))
820 generate_exception(ctx, EXCP_RI);
823 /* This code generates a "reserved instruction" exception if the
824 CPU does not support the instruction set corresponding to flags. */
825 static inline void check_insn(CPUState *env, DisasContext *ctx, int flags)
827 if (unlikely(!(env->insn_flags & flags)))
828 generate_exception(ctx, EXCP_RI);
831 /* This code generates a "reserved instruction" exception if 64-bit
832 instructions are not enabled. */
833 static inline void check_mips_64(DisasContext *ctx)
835 if (unlikely(!(ctx->hflags & MIPS_HFLAG_64)))
836 generate_exception(ctx, EXCP_RI);
839 /* load/store instructions. */
840 #define OP_LD(insn,fname) \
841 static inline void op_ldst_##insn(TCGv ret, TCGv arg1, DisasContext *ctx) \
843 tcg_gen_qemu_##fname(ret, arg1, ctx->mem_idx); \
845 OP_LD(lb,ld8s);
846 OP_LD(lbu,ld8u);
847 OP_LD(lh,ld16s);
848 OP_LD(lhu,ld16u);
849 OP_LD(lw,ld32s);
850 #if defined(TARGET_MIPS64)
851 OP_LD(lwu,ld32u);
852 OP_LD(ld,ld64);
853 #endif
854 #undef OP_LD
856 #define OP_ST(insn,fname) \
857 static inline void op_ldst_##insn(TCGv arg1, TCGv arg2, DisasContext *ctx) \
859 tcg_gen_qemu_##fname(arg1, arg2, ctx->mem_idx); \
861 OP_ST(sb,st8);
862 OP_ST(sh,st16);
863 OP_ST(sw,st32);
864 #if defined(TARGET_MIPS64)
865 OP_ST(sd,st64);
866 #endif
867 #undef OP_ST
869 #ifdef CONFIG_USER_ONLY
870 #define OP_LD_ATOMIC(insn,fname) \
871 static inline void op_ldst_##insn(TCGv ret, TCGv arg1, DisasContext *ctx) \
873 TCGv t0 = tcg_temp_new(); \
874 tcg_gen_mov_tl(t0, arg1); \
875 tcg_gen_qemu_##fname(ret, arg1, ctx->mem_idx); \
876 tcg_gen_st_tl(t0, cpu_env, offsetof(CPUState, lladdr)); \
877 tcg_gen_st_tl(ret, cpu_env, offsetof(CPUState, llval)); \
878 tcg_temp_free(t0); \
880 #else
881 #define OP_LD_ATOMIC(insn,fname) \
882 static inline void op_ldst_##insn(TCGv ret, TCGv arg1, DisasContext *ctx) \
884 gen_helper_2i(insn, ret, arg1, ctx->mem_idx); \
886 #endif
887 OP_LD_ATOMIC(ll,ld32s);
888 #if defined(TARGET_MIPS64)
889 OP_LD_ATOMIC(lld,ld64);
890 #endif
891 #undef OP_LD_ATOMIC
893 #ifdef CONFIG_USER_ONLY
894 #define OP_ST_ATOMIC(insn,fname,ldname,almask) \
895 static inline void op_ldst_##insn(TCGv arg1, TCGv arg2, int rt, DisasContext *ctx) \
897 TCGv t0 = tcg_temp_new(); \
898 int l1 = gen_new_label(); \
899 int l2 = gen_new_label(); \
901 tcg_gen_andi_tl(t0, arg2, almask); \
902 tcg_gen_brcondi_tl(TCG_COND_EQ, t0, 0, l1); \
903 tcg_gen_st_tl(arg2, cpu_env, offsetof(CPUState, CP0_BadVAddr)); \
904 generate_exception(ctx, EXCP_AdES); \
905 gen_set_label(l1); \
906 tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUState, lladdr)); \
907 tcg_gen_brcond_tl(TCG_COND_NE, arg2, t0, l2); \
908 tcg_gen_movi_tl(t0, rt | ((almask << 3) & 0x20)); \
909 tcg_gen_st_tl(t0, cpu_env, offsetof(CPUState, llreg)); \
910 tcg_gen_st_tl(arg1, cpu_env, offsetof(CPUState, llnewval)); \
911 gen_helper_0i(raise_exception, EXCP_SC); \
912 gen_set_label(l2); \
913 tcg_gen_movi_tl(t0, 0); \
914 gen_store_gpr(t0, rt); \
915 tcg_temp_free(t0); \
917 #else
918 #define OP_ST_ATOMIC(insn,fname,ldname,almask) \
919 static inline void op_ldst_##insn(TCGv arg1, TCGv arg2, int rt, DisasContext *ctx) \
921 TCGv t0 = tcg_temp_new(); \
922 gen_helper_3i(insn, t0, arg1, arg2, ctx->mem_idx); \
923 gen_store_gpr(t0, rt); \
924 tcg_temp_free(t0); \
926 #endif
927 OP_ST_ATOMIC(sc,st32,ld32s,0x3);
928 #if defined(TARGET_MIPS64)
929 OP_ST_ATOMIC(scd,st64,ld64,0x7);
930 #endif
931 #undef OP_ST_ATOMIC
933 static void gen_base_offset_addr (DisasContext *ctx, TCGv addr,
934 int base, int16_t offset)
936 if (base == 0) {
937 tcg_gen_movi_tl(addr, offset);
938 } else if (offset == 0) {
939 gen_load_gpr(addr, base);
940 } else {
941 tcg_gen_movi_tl(addr, offset);
942 gen_op_addr_add(ctx, addr, cpu_gpr[base], addr);
946 static target_ulong pc_relative_pc (DisasContext *ctx)
948 target_ulong pc = ctx->pc;
950 if (ctx->hflags & MIPS_HFLAG_BMASK) {
951 int branch_bytes = ctx->hflags & MIPS_HFLAG_BDS16 ? 2 : 4;
953 pc -= branch_bytes;
956 pc &= ~(target_ulong)3;
957 return pc;
960 /* Load and store */
961 static void gen_ldst (DisasContext *ctx, uint32_t opc, int rt,
962 int base, int16_t offset)
964 const char *opn = "ldst";
965 TCGv t0 = tcg_temp_new();
966 TCGv t1 = tcg_temp_new();
968 gen_base_offset_addr(ctx, t0, base, offset);
969 /* Don't do NOP if destination is zero: we must perform the actual
970 memory access. */
971 switch (opc) {
972 #if defined(TARGET_MIPS64)
973 case OPC_LWU:
974 save_cpu_state(ctx, 0);
975 op_ldst_lwu(t0, t0, ctx);
976 gen_store_gpr(t0, rt);
977 opn = "lwu";
978 break;
979 case OPC_LD:
980 save_cpu_state(ctx, 0);
981 op_ldst_ld(t0, t0, ctx);
982 gen_store_gpr(t0, rt);
983 opn = "ld";
984 break;
985 case OPC_LLD:
986 save_cpu_state(ctx, 0);
987 op_ldst_lld(t0, t0, ctx);
988 gen_store_gpr(t0, rt);
989 opn = "lld";
990 break;
991 case OPC_SD:
992 save_cpu_state(ctx, 0);
993 gen_load_gpr(t1, rt);
994 op_ldst_sd(t1, t0, ctx);
995 opn = "sd";
996 break;
997 case OPC_LDL:
998 save_cpu_state(ctx, 1);
999 gen_load_gpr(t1, rt);
1000 gen_helper_3i(ldl, t1, t1, t0, ctx->mem_idx);
1001 gen_store_gpr(t1, rt);
1002 opn = "ldl";
1003 break;
1004 case OPC_SDL:
1005 save_cpu_state(ctx, 1);
1006 gen_load_gpr(t1, rt);
1007 gen_helper_2i(sdl, t1, t0, ctx->mem_idx);
1008 opn = "sdl";
1009 break;
1010 case OPC_LDR:
1011 save_cpu_state(ctx, 1);
1012 gen_load_gpr(t1, rt);
1013 gen_helper_3i(ldr, t1, t1, t0, ctx->mem_idx);
1014 gen_store_gpr(t1, rt);
1015 opn = "ldr";
1016 break;
1017 case OPC_SDR:
1018 save_cpu_state(ctx, 1);
1019 gen_load_gpr(t1, rt);
1020 gen_helper_2i(sdr, t1, t0, ctx->mem_idx);
1021 opn = "sdr";
1022 break;
1023 case OPC_LDPC:
1024 save_cpu_state(ctx, 1);
1025 tcg_gen_movi_tl(t1, pc_relative_pc(ctx));
1026 gen_op_addr_add(ctx, t0, t0, t1);
1027 op_ldst_ld(t0, t0, ctx);
1028 gen_store_gpr(t0, rt);
1029 break;
1030 #endif
1031 case OPC_LWPC:
1032 save_cpu_state(ctx, 1);
1033 tcg_gen_movi_tl(t1, pc_relative_pc(ctx));
1034 gen_op_addr_add(ctx, t0, t0, t1);
1035 op_ldst_lw(t0, t0, ctx);
1036 gen_store_gpr(t0, rt);
1037 break;
1038 case OPC_LW:
1039 save_cpu_state(ctx, 0);
1040 op_ldst_lw(t0, t0, ctx);
1041 gen_store_gpr(t0, rt);
1042 opn = "lw";
1043 break;
1044 case OPC_SW:
1045 save_cpu_state(ctx, 0);
1046 gen_load_gpr(t1, rt);
1047 op_ldst_sw(t1, t0, ctx);
1048 opn = "sw";
1049 break;
1050 case OPC_LH:
1051 save_cpu_state(ctx, 0);
1052 op_ldst_lh(t0, t0, ctx);
1053 gen_store_gpr(t0, rt);
1054 opn = "lh";
1055 break;
1056 case OPC_SH:
1057 save_cpu_state(ctx, 0);
1058 gen_load_gpr(t1, rt);
1059 op_ldst_sh(t1, t0, ctx);
1060 opn = "sh";
1061 break;
1062 case OPC_LHU:
1063 save_cpu_state(ctx, 0);
1064 op_ldst_lhu(t0, t0, ctx);
1065 gen_store_gpr(t0, rt);
1066 opn = "lhu";
1067 break;
1068 case OPC_LB:
1069 save_cpu_state(ctx, 0);
1070 op_ldst_lb(t0, t0, ctx);
1071 gen_store_gpr(t0, rt);
1072 opn = "lb";
1073 break;
1074 case OPC_SB:
1075 save_cpu_state(ctx, 0);
1076 gen_load_gpr(t1, rt);
1077 op_ldst_sb(t1, t0, ctx);
1078 opn = "sb";
1079 break;
1080 case OPC_LBU:
1081 save_cpu_state(ctx, 0);
1082 op_ldst_lbu(t0, t0, ctx);
1083 gen_store_gpr(t0, rt);
1084 opn = "lbu";
1085 break;
1086 case OPC_LWL:
1087 save_cpu_state(ctx, 1);
1088 gen_load_gpr(t1, rt);
1089 gen_helper_3i(lwl, t1, t1, t0, ctx->mem_idx);
1090 gen_store_gpr(t1, rt);
1091 opn = "lwl";
1092 break;
1093 case OPC_SWL:
1094 save_cpu_state(ctx, 1);
1095 gen_load_gpr(t1, rt);
1096 gen_helper_2i(swl, t1, t0, ctx->mem_idx);
1097 opn = "swr";
1098 break;
1099 case OPC_LWR:
1100 save_cpu_state(ctx, 1);
1101 gen_load_gpr(t1, rt);
1102 gen_helper_3i(lwr, t1, t1, t0, ctx->mem_idx);
1103 gen_store_gpr(t1, rt);
1104 opn = "lwr";
1105 break;
1106 case OPC_SWR:
1107 save_cpu_state(ctx, 1);
1108 gen_load_gpr(t1, rt);
1109 gen_helper_2i(swr, t1, t0, ctx->mem_idx);
1110 opn = "swr";
1111 break;
1112 case OPC_LL:
1113 save_cpu_state(ctx, 1);
1114 op_ldst_ll(t0, t0, ctx);
1115 gen_store_gpr(t0, rt);
1116 opn = "ll";
1117 break;
1119 MIPS_DEBUG("%s %s, %d(%s)", opn, regnames[rt], offset, regnames[base]);
1120 tcg_temp_free(t0);
1121 tcg_temp_free(t1);
1124 /* Store conditional */
1125 static void gen_st_cond (DisasContext *ctx, uint32_t opc, int rt,
1126 int base, int16_t offset)
1128 const char *opn = "st_cond";
1129 TCGv t0, t1;
1131 t0 = tcg_temp_local_new();
1133 gen_base_offset_addr(ctx, t0, base, offset);
1134 /* Don't do NOP if destination is zero: we must perform the actual
1135 memory access. */
1137 t1 = tcg_temp_local_new();
1138 gen_load_gpr(t1, rt);
1139 switch (opc) {
1140 #if defined(TARGET_MIPS64)
1141 case OPC_SCD:
1142 save_cpu_state(ctx, 0);
1143 op_ldst_scd(t1, t0, rt, ctx);
1144 opn = "scd";
1145 break;
1146 #endif
1147 case OPC_SC:
1148 save_cpu_state(ctx, 1);
1149 op_ldst_sc(t1, t0, rt, ctx);
1150 opn = "sc";
1151 break;
1153 MIPS_DEBUG("%s %s, %d(%s)", opn, regnames[rt], offset, regnames[base]);
1154 tcg_temp_free(t1);
1155 tcg_temp_free(t0);
1158 /* Load and store */
1159 static void gen_flt_ldst (DisasContext *ctx, uint32_t opc, int ft,
1160 int base, int16_t offset)
1162 const char *opn = "flt_ldst";
1163 TCGv t0 = tcg_temp_new();
1165 gen_base_offset_addr(ctx, t0, base, offset);
1166 /* Don't do NOP if destination is zero: we must perform the actual
1167 memory access. */
1168 switch (opc) {
1169 case OPC_LWC1:
1171 TCGv_i32 fp0 = tcg_temp_new_i32();
1173 tcg_gen_qemu_ld32s(t0, t0, ctx->mem_idx);
1174 tcg_gen_trunc_tl_i32(fp0, t0);
1175 gen_store_fpr32(fp0, ft);
1176 tcg_temp_free_i32(fp0);
1178 opn = "lwc1";
1179 break;
1180 case OPC_SWC1:
1182 TCGv_i32 fp0 = tcg_temp_new_i32();
1183 TCGv t1 = tcg_temp_new();
1185 gen_load_fpr32(fp0, ft);
1186 tcg_gen_extu_i32_tl(t1, fp0);
1187 tcg_gen_qemu_st32(t1, t0, ctx->mem_idx);
1188 tcg_temp_free(t1);
1189 tcg_temp_free_i32(fp0);
1191 opn = "swc1";
1192 break;
1193 case OPC_LDC1:
1195 TCGv_i64 fp0 = tcg_temp_new_i64();
1197 tcg_gen_qemu_ld64(fp0, t0, ctx->mem_idx);
1198 gen_store_fpr64(ctx, fp0, ft);
1199 tcg_temp_free_i64(fp0);
1201 opn = "ldc1";
1202 break;
1203 case OPC_SDC1:
1205 TCGv_i64 fp0 = tcg_temp_new_i64();
1207 gen_load_fpr64(ctx, fp0, ft);
1208 tcg_gen_qemu_st64(fp0, t0, ctx->mem_idx);
1209 tcg_temp_free_i64(fp0);
1211 opn = "sdc1";
1212 break;
1213 default:
1214 MIPS_INVAL(opn);
1215 generate_exception(ctx, EXCP_RI);
1216 goto out;
1218 MIPS_DEBUG("%s %s, %d(%s)", opn, fregnames[ft], offset, regnames[base]);
1219 out:
1220 tcg_temp_free(t0);
1223 /* Arithmetic with immediate operand */
1224 static void gen_arith_imm (CPUState *env, DisasContext *ctx, uint32_t opc,
1225 int rt, int rs, int16_t imm)
1227 target_ulong uimm = (target_long)imm; /* Sign extend to 32/64 bits */
1228 const char *opn = "imm arith";
1230 if (rt == 0 && opc != OPC_ADDI && opc != OPC_DADDI) {
1231 /* If no destination, treat it as a NOP.
1232 For addi, we must generate the overflow exception when needed. */
1233 MIPS_DEBUG("NOP");
1234 return;
1236 switch (opc) {
1237 case OPC_ADDI:
1239 TCGv t0 = tcg_temp_local_new();
1240 TCGv t1 = tcg_temp_new();
1241 TCGv t2 = tcg_temp_new();
1242 int l1 = gen_new_label();
1244 gen_load_gpr(t1, rs);
1245 tcg_gen_addi_tl(t0, t1, uimm);
1246 tcg_gen_ext32s_tl(t0, t0);
1248 tcg_gen_xori_tl(t1, t1, ~uimm);
1249 tcg_gen_xori_tl(t2, t0, uimm);
1250 tcg_gen_and_tl(t1, t1, t2);
1251 tcg_temp_free(t2);
1252 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
1253 tcg_temp_free(t1);
1254 /* operands of same sign, result different sign */
1255 generate_exception(ctx, EXCP_OVERFLOW);
1256 gen_set_label(l1);
1257 tcg_gen_ext32s_tl(t0, t0);
1258 gen_store_gpr(t0, rt);
1259 tcg_temp_free(t0);
1261 opn = "addi";
1262 break;
1263 case OPC_ADDIU:
1264 if (rs != 0) {
1265 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
1266 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
1267 } else {
1268 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
1270 opn = "addiu";
1271 break;
1272 #if defined(TARGET_MIPS64)
1273 case OPC_DADDI:
1275 TCGv t0 = tcg_temp_local_new();
1276 TCGv t1 = tcg_temp_new();
1277 TCGv t2 = tcg_temp_new();
1278 int l1 = gen_new_label();
1280 gen_load_gpr(t1, rs);
1281 tcg_gen_addi_tl(t0, t1, uimm);
1283 tcg_gen_xori_tl(t1, t1, ~uimm);
1284 tcg_gen_xori_tl(t2, t0, uimm);
1285 tcg_gen_and_tl(t1, t1, t2);
1286 tcg_temp_free(t2);
1287 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
1288 tcg_temp_free(t1);
1289 /* operands of same sign, result different sign */
1290 generate_exception(ctx, EXCP_OVERFLOW);
1291 gen_set_label(l1);
1292 gen_store_gpr(t0, rt);
1293 tcg_temp_free(t0);
1295 opn = "daddi";
1296 break;
1297 case OPC_DADDIU:
1298 if (rs != 0) {
1299 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
1300 } else {
1301 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
1303 opn = "daddiu";
1304 break;
1305 #endif
1307 MIPS_DEBUG("%s %s, %s, " TARGET_FMT_lx, opn, regnames[rt], regnames[rs], uimm);
1310 /* Logic with immediate operand */
1311 static void gen_logic_imm (CPUState *env, uint32_t opc, int rt, int rs, int16_t imm)
1313 target_ulong uimm;
1314 const char *opn = "imm logic";
1316 if (rt == 0) {
1317 /* If no destination, treat it as a NOP. */
1318 MIPS_DEBUG("NOP");
1319 return;
1321 uimm = (uint16_t)imm;
1322 switch (opc) {
1323 case OPC_ANDI:
1324 if (likely(rs != 0))
1325 tcg_gen_andi_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
1326 else
1327 tcg_gen_movi_tl(cpu_gpr[rt], 0);
1328 opn = "andi";
1329 break;
1330 case OPC_ORI:
1331 if (rs != 0)
1332 tcg_gen_ori_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
1333 else
1334 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
1335 opn = "ori";
1336 break;
1337 case OPC_XORI:
1338 if (likely(rs != 0))
1339 tcg_gen_xori_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
1340 else
1341 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
1342 opn = "xori";
1343 break;
1344 case OPC_LUI:
1345 tcg_gen_movi_tl(cpu_gpr[rt], imm << 16);
1346 opn = "lui";
1347 break;
1349 MIPS_DEBUG("%s %s, %s, " TARGET_FMT_lx, opn, regnames[rt], regnames[rs], uimm);
1352 /* Set on less than with immediate operand */
1353 static void gen_slt_imm (CPUState *env, uint32_t opc, int rt, int rs, int16_t imm)
1355 target_ulong uimm = (target_long)imm; /* Sign extend to 32/64 bits */
1356 const char *opn = "imm arith";
1357 TCGv t0;
1359 if (rt == 0) {
1360 /* If no destination, treat it as a NOP. */
1361 MIPS_DEBUG("NOP");
1362 return;
1364 t0 = tcg_temp_new();
1365 gen_load_gpr(t0, rs);
1366 switch (opc) {
1367 case OPC_SLTI:
1368 tcg_gen_setcondi_tl(TCG_COND_LT, cpu_gpr[rt], t0, uimm);
1369 opn = "slti";
1370 break;
1371 case OPC_SLTIU:
1372 tcg_gen_setcondi_tl(TCG_COND_LTU, cpu_gpr[rt], t0, uimm);
1373 opn = "sltiu";
1374 break;
1376 MIPS_DEBUG("%s %s, %s, " TARGET_FMT_lx, opn, regnames[rt], regnames[rs], uimm);
1377 tcg_temp_free(t0);
1380 /* Shifts with immediate operand */
1381 static void gen_shift_imm(CPUState *env, DisasContext *ctx, uint32_t opc,
1382 int rt, int rs, int16_t imm)
1384 target_ulong uimm = ((uint16_t)imm) & 0x1f;
1385 const char *opn = "imm shift";
1386 TCGv t0;
1388 if (rt == 0) {
1389 /* If no destination, treat it as a NOP. */
1390 MIPS_DEBUG("NOP");
1391 return;
1394 t0 = tcg_temp_new();
1395 gen_load_gpr(t0, rs);
1396 switch (opc) {
1397 case OPC_SLL:
1398 tcg_gen_shli_tl(t0, t0, uimm);
1399 tcg_gen_ext32s_tl(cpu_gpr[rt], t0);
1400 opn = "sll";
1401 break;
1402 case OPC_SRA:
1403 tcg_gen_sari_tl(cpu_gpr[rt], t0, uimm);
1404 opn = "sra";
1405 break;
1406 case OPC_SRL:
1407 if (uimm != 0) {
1408 tcg_gen_ext32u_tl(t0, t0);
1409 tcg_gen_shri_tl(cpu_gpr[rt], t0, uimm);
1410 } else {
1411 tcg_gen_ext32s_tl(cpu_gpr[rt], t0);
1413 opn = "srl";
1414 break;
1415 case OPC_ROTR:
1416 if (uimm != 0) {
1417 TCGv_i32 t1 = tcg_temp_new_i32();
1419 tcg_gen_trunc_tl_i32(t1, t0);
1420 tcg_gen_rotri_i32(t1, t1, uimm);
1421 tcg_gen_ext_i32_tl(cpu_gpr[rt], t1);
1422 tcg_temp_free_i32(t1);
1423 } else {
1424 tcg_gen_ext32s_tl(cpu_gpr[rt], t0);
1426 opn = "rotr";
1427 break;
1428 #if defined(TARGET_MIPS64)
1429 case OPC_DSLL:
1430 tcg_gen_shli_tl(cpu_gpr[rt], t0, uimm);
1431 opn = "dsll";
1432 break;
1433 case OPC_DSRA:
1434 tcg_gen_sari_tl(cpu_gpr[rt], t0, uimm);
1435 opn = "dsra";
1436 break;
1437 case OPC_DSRL:
1438 tcg_gen_shri_tl(cpu_gpr[rt], t0, uimm);
1439 opn = "dsrl";
1440 break;
1441 case OPC_DROTR:
1442 if (uimm != 0) {
1443 tcg_gen_rotri_tl(cpu_gpr[rt], t0, uimm);
1444 } else {
1445 tcg_gen_mov_tl(cpu_gpr[rt], t0);
1447 opn = "drotr";
1448 break;
1449 case OPC_DSLL32:
1450 tcg_gen_shli_tl(cpu_gpr[rt], t0, uimm + 32);
1451 opn = "dsll32";
1452 break;
1453 case OPC_DSRA32:
1454 tcg_gen_sari_tl(cpu_gpr[rt], t0, uimm + 32);
1455 opn = "dsra32";
1456 break;
1457 case OPC_DSRL32:
1458 tcg_gen_shri_tl(cpu_gpr[rt], t0, uimm + 32);
1459 opn = "dsrl32";
1460 break;
1461 case OPC_DROTR32:
1462 tcg_gen_rotri_tl(cpu_gpr[rt], t0, uimm + 32);
1463 opn = "drotr32";
1464 break;
1465 #endif
1467 MIPS_DEBUG("%s %s, %s, " TARGET_FMT_lx, opn, regnames[rt], regnames[rs], uimm);
1468 tcg_temp_free(t0);
1471 /* Arithmetic */
1472 static void gen_arith (CPUState *env, DisasContext *ctx, uint32_t opc,
1473 int rd, int rs, int rt)
1475 const char *opn = "arith";
1477 if (rd == 0 && opc != OPC_ADD && opc != OPC_SUB
1478 && opc != OPC_DADD && opc != OPC_DSUB) {
1479 /* If no destination, treat it as a NOP.
1480 For add & sub, we must generate the overflow exception when needed. */
1481 MIPS_DEBUG("NOP");
1482 return;
1485 switch (opc) {
1486 case OPC_ADD:
1488 TCGv t0 = tcg_temp_local_new();
1489 TCGv t1 = tcg_temp_new();
1490 TCGv t2 = tcg_temp_new();
1491 int l1 = gen_new_label();
1493 gen_load_gpr(t1, rs);
1494 gen_load_gpr(t2, rt);
1495 tcg_gen_add_tl(t0, t1, t2);
1496 tcg_gen_ext32s_tl(t0, t0);
1497 tcg_gen_xor_tl(t1, t1, t2);
1498 tcg_gen_xor_tl(t2, t0, t2);
1499 tcg_gen_andc_tl(t1, t2, t1);
1500 tcg_temp_free(t2);
1501 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
1502 tcg_temp_free(t1);
1503 /* operands of same sign, result different sign */
1504 generate_exception(ctx, EXCP_OVERFLOW);
1505 gen_set_label(l1);
1506 gen_store_gpr(t0, rd);
1507 tcg_temp_free(t0);
1509 opn = "add";
1510 break;
1511 case OPC_ADDU:
1512 if (rs != 0 && rt != 0) {
1513 tcg_gen_add_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
1514 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
1515 } else if (rs == 0 && rt != 0) {
1516 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
1517 } else if (rs != 0 && rt == 0) {
1518 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
1519 } else {
1520 tcg_gen_movi_tl(cpu_gpr[rd], 0);
1522 opn = "addu";
1523 break;
1524 case OPC_SUB:
1526 TCGv t0 = tcg_temp_local_new();
1527 TCGv t1 = tcg_temp_new();
1528 TCGv t2 = tcg_temp_new();
1529 int l1 = gen_new_label();
1531 gen_load_gpr(t1, rs);
1532 gen_load_gpr(t2, rt);
1533 tcg_gen_sub_tl(t0, t1, t2);
1534 tcg_gen_ext32s_tl(t0, t0);
1535 tcg_gen_xor_tl(t2, t1, t2);
1536 tcg_gen_xor_tl(t1, t0, t1);
1537 tcg_gen_and_tl(t1, t1, t2);
1538 tcg_temp_free(t2);
1539 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
1540 tcg_temp_free(t1);
1541 /* operands of different sign, first operand and result different sign */
1542 generate_exception(ctx, EXCP_OVERFLOW);
1543 gen_set_label(l1);
1544 gen_store_gpr(t0, rd);
1545 tcg_temp_free(t0);
1547 opn = "sub";
1548 break;
1549 case OPC_SUBU:
1550 if (rs != 0 && rt != 0) {
1551 tcg_gen_sub_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
1552 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
1553 } else if (rs == 0 && rt != 0) {
1554 tcg_gen_neg_tl(cpu_gpr[rd], cpu_gpr[rt]);
1555 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
1556 } else if (rs != 0 && rt == 0) {
1557 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
1558 } else {
1559 tcg_gen_movi_tl(cpu_gpr[rd], 0);
1561 opn = "subu";
1562 break;
1563 #if defined(TARGET_MIPS64)
1564 case OPC_DADD:
1566 TCGv t0 = tcg_temp_local_new();
1567 TCGv t1 = tcg_temp_new();
1568 TCGv t2 = tcg_temp_new();
1569 int l1 = gen_new_label();
1571 gen_load_gpr(t1, rs);
1572 gen_load_gpr(t2, rt);
1573 tcg_gen_add_tl(t0, t1, t2);
1574 tcg_gen_xor_tl(t1, t1, t2);
1575 tcg_gen_xor_tl(t2, t0, t2);
1576 tcg_gen_andc_tl(t1, t2, t1);
1577 tcg_temp_free(t2);
1578 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
1579 tcg_temp_free(t1);
1580 /* operands of same sign, result different sign */
1581 generate_exception(ctx, EXCP_OVERFLOW);
1582 gen_set_label(l1);
1583 gen_store_gpr(t0, rd);
1584 tcg_temp_free(t0);
1586 opn = "dadd";
1587 break;
1588 case OPC_DADDU:
1589 if (rs != 0 && rt != 0) {
1590 tcg_gen_add_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
1591 } else if (rs == 0 && rt != 0) {
1592 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
1593 } else if (rs != 0 && rt == 0) {
1594 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
1595 } else {
1596 tcg_gen_movi_tl(cpu_gpr[rd], 0);
1598 opn = "daddu";
1599 break;
1600 case OPC_DSUB:
1602 TCGv t0 = tcg_temp_local_new();
1603 TCGv t1 = tcg_temp_new();
1604 TCGv t2 = tcg_temp_new();
1605 int l1 = gen_new_label();
1607 gen_load_gpr(t1, rs);
1608 gen_load_gpr(t2, rt);
1609 tcg_gen_sub_tl(t0, t1, t2);
1610 tcg_gen_xor_tl(t2, t1, t2);
1611 tcg_gen_xor_tl(t1, t0, t1);
1612 tcg_gen_and_tl(t1, t1, t2);
1613 tcg_temp_free(t2);
1614 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
1615 tcg_temp_free(t1);
1616 /* operands of different sign, first operand and result different sign */
1617 generate_exception(ctx, EXCP_OVERFLOW);
1618 gen_set_label(l1);
1619 gen_store_gpr(t0, rd);
1620 tcg_temp_free(t0);
1622 opn = "dsub";
1623 break;
1624 case OPC_DSUBU:
1625 if (rs != 0 && rt != 0) {
1626 tcg_gen_sub_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
1627 } else if (rs == 0 && rt != 0) {
1628 tcg_gen_neg_tl(cpu_gpr[rd], cpu_gpr[rt]);
1629 } else if (rs != 0 && rt == 0) {
1630 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
1631 } else {
1632 tcg_gen_movi_tl(cpu_gpr[rd], 0);
1634 opn = "dsubu";
1635 break;
1636 #endif
1637 case OPC_MUL:
1638 if (likely(rs != 0 && rt != 0)) {
1639 tcg_gen_mul_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
1640 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
1641 } else {
1642 tcg_gen_movi_tl(cpu_gpr[rd], 0);
1644 opn = "mul";
1645 break;
1647 MIPS_DEBUG("%s %s, %s, %s", opn, regnames[rd], regnames[rs], regnames[rt]);
1650 /* Conditional move */
1651 static void gen_cond_move (CPUState *env, uint32_t opc, int rd, int rs, int rt)
1653 const char *opn = "cond move";
1654 int l1;
1656 if (rd == 0) {
1657 /* If no destination, treat it as a NOP.
1658 For add & sub, we must generate the overflow exception when needed. */
1659 MIPS_DEBUG("NOP");
1660 return;
1663 l1 = gen_new_label();
1664 switch (opc) {
1665 case OPC_MOVN:
1666 if (likely(rt != 0))
1667 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[rt], 0, l1);
1668 else
1669 tcg_gen_br(l1);
1670 opn = "movn";
1671 break;
1672 case OPC_MOVZ:
1673 if (likely(rt != 0))
1674 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[rt], 0, l1);
1675 opn = "movz";
1676 break;
1678 if (rs != 0)
1679 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
1680 else
1681 tcg_gen_movi_tl(cpu_gpr[rd], 0);
1682 gen_set_label(l1);
1684 MIPS_DEBUG("%s %s, %s, %s", opn, regnames[rd], regnames[rs], regnames[rt]);
1687 /* Logic */
1688 static void gen_logic (CPUState *env, uint32_t opc, int rd, int rs, int rt)
1690 const char *opn = "logic";
1692 if (rd == 0) {
1693 /* If no destination, treat it as a NOP. */
1694 MIPS_DEBUG("NOP");
1695 return;
1698 switch (opc) {
1699 case OPC_AND:
1700 if (likely(rs != 0 && rt != 0)) {
1701 tcg_gen_and_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
1702 } else {
1703 tcg_gen_movi_tl(cpu_gpr[rd], 0);
1705 opn = "and";
1706 break;
1707 case OPC_NOR:
1708 if (rs != 0 && rt != 0) {
1709 tcg_gen_nor_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
1710 } else if (rs == 0 && rt != 0) {
1711 tcg_gen_not_tl(cpu_gpr[rd], cpu_gpr[rt]);
1712 } else if (rs != 0 && rt == 0) {
1713 tcg_gen_not_tl(cpu_gpr[rd], cpu_gpr[rs]);
1714 } else {
1715 tcg_gen_movi_tl(cpu_gpr[rd], ~((target_ulong)0));
1717 opn = "nor";
1718 break;
1719 case OPC_OR:
1720 if (likely(rs != 0 && rt != 0)) {
1721 tcg_gen_or_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
1722 } else if (rs == 0 && rt != 0) {
1723 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
1724 } else if (rs != 0 && rt == 0) {
1725 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
1726 } else {
1727 tcg_gen_movi_tl(cpu_gpr[rd], 0);
1729 opn = "or";
1730 break;
1731 case OPC_XOR:
1732 if (likely(rs != 0 && rt != 0)) {
1733 tcg_gen_xor_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
1734 } else if (rs == 0 && rt != 0) {
1735 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
1736 } else if (rs != 0 && rt == 0) {
1737 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
1738 } else {
1739 tcg_gen_movi_tl(cpu_gpr[rd], 0);
1741 opn = "xor";
1742 break;
1744 MIPS_DEBUG("%s %s, %s, %s", opn, regnames[rd], regnames[rs], regnames[rt]);
1747 /* Set on lower than */
1748 static void gen_slt (CPUState *env, uint32_t opc, int rd, int rs, int rt)
1750 const char *opn = "slt";
1751 TCGv t0, t1;
1753 if (rd == 0) {
1754 /* If no destination, treat it as a NOP. */
1755 MIPS_DEBUG("NOP");
1756 return;
1759 t0 = tcg_temp_new();
1760 t1 = tcg_temp_new();
1761 gen_load_gpr(t0, rs);
1762 gen_load_gpr(t1, rt);
1763 switch (opc) {
1764 case OPC_SLT:
1765 tcg_gen_setcond_tl(TCG_COND_LT, cpu_gpr[rd], t0, t1);
1766 opn = "slt";
1767 break;
1768 case OPC_SLTU:
1769 tcg_gen_setcond_tl(TCG_COND_LTU, cpu_gpr[rd], t0, t1);
1770 opn = "sltu";
1771 break;
1773 MIPS_DEBUG("%s %s, %s, %s", opn, regnames[rd], regnames[rs], regnames[rt]);
1774 tcg_temp_free(t0);
1775 tcg_temp_free(t1);
1778 /* Shifts */
1779 static void gen_shift (CPUState *env, DisasContext *ctx, uint32_t opc,
1780 int rd, int rs, int rt)
1782 const char *opn = "shifts";
1783 TCGv t0, t1;
1785 if (rd == 0) {
1786 /* If no destination, treat it as a NOP.
1787 For add & sub, we must generate the overflow exception when needed. */
1788 MIPS_DEBUG("NOP");
1789 return;
1792 t0 = tcg_temp_new();
1793 t1 = tcg_temp_new();
1794 gen_load_gpr(t0, rs);
1795 gen_load_gpr(t1, rt);
1796 switch (opc) {
1797 case OPC_SLLV:
1798 tcg_gen_andi_tl(t0, t0, 0x1f);
1799 tcg_gen_shl_tl(t0, t1, t0);
1800 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
1801 opn = "sllv";
1802 break;
1803 case OPC_SRAV:
1804 tcg_gen_andi_tl(t0, t0, 0x1f);
1805 tcg_gen_sar_tl(cpu_gpr[rd], t1, t0);
1806 opn = "srav";
1807 break;
1808 case OPC_SRLV:
1809 tcg_gen_ext32u_tl(t1, t1);
1810 tcg_gen_andi_tl(t0, t0, 0x1f);
1811 tcg_gen_shr_tl(t0, t1, t0);
1812 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
1813 opn = "srlv";
1814 break;
1815 case OPC_ROTRV:
1817 TCGv_i32 t2 = tcg_temp_new_i32();
1818 TCGv_i32 t3 = tcg_temp_new_i32();
1820 tcg_gen_trunc_tl_i32(t2, t0);
1821 tcg_gen_trunc_tl_i32(t3, t1);
1822 tcg_gen_andi_i32(t2, t2, 0x1f);
1823 tcg_gen_rotr_i32(t2, t3, t2);
1824 tcg_gen_ext_i32_tl(cpu_gpr[rd], t2);
1825 tcg_temp_free_i32(t2);
1826 tcg_temp_free_i32(t3);
1827 opn = "rotrv";
1829 break;
1830 #if defined(TARGET_MIPS64)
1831 case OPC_DSLLV:
1832 tcg_gen_andi_tl(t0, t0, 0x3f);
1833 tcg_gen_shl_tl(cpu_gpr[rd], t1, t0);
1834 opn = "dsllv";
1835 break;
1836 case OPC_DSRAV:
1837 tcg_gen_andi_tl(t0, t0, 0x3f);
1838 tcg_gen_sar_tl(cpu_gpr[rd], t1, t0);
1839 opn = "dsrav";
1840 break;
1841 case OPC_DSRLV:
1842 tcg_gen_andi_tl(t0, t0, 0x3f);
1843 tcg_gen_shr_tl(cpu_gpr[rd], t1, t0);
1844 opn = "dsrlv";
1845 break;
1846 case OPC_DROTRV:
1847 tcg_gen_andi_tl(t0, t0, 0x3f);
1848 tcg_gen_rotr_tl(cpu_gpr[rd], t1, t0);
1849 opn = "drotrv";
1850 break;
1851 #endif
1853 MIPS_DEBUG("%s %s, %s, %s", opn, regnames[rd], regnames[rs], regnames[rt]);
1854 tcg_temp_free(t0);
1855 tcg_temp_free(t1);
1858 /* Arithmetic on HI/LO registers */
1859 static void gen_HILO (DisasContext *ctx, uint32_t opc, int reg)
1861 const char *opn = "hilo";
1863 if (reg == 0 && (opc == OPC_MFHI || opc == OPC_MFLO)) {
1864 /* Treat as NOP. */
1865 MIPS_DEBUG("NOP");
1866 return;
1868 switch (opc) {
1869 case OPC_MFHI:
1870 tcg_gen_mov_tl(cpu_gpr[reg], cpu_HI[0]);
1871 opn = "mfhi";
1872 break;
1873 case OPC_MFLO:
1874 tcg_gen_mov_tl(cpu_gpr[reg], cpu_LO[0]);
1875 opn = "mflo";
1876 break;
1877 case OPC_MTHI:
1878 if (reg != 0)
1879 tcg_gen_mov_tl(cpu_HI[0], cpu_gpr[reg]);
1880 else
1881 tcg_gen_movi_tl(cpu_HI[0], 0);
1882 opn = "mthi";
1883 break;
1884 case OPC_MTLO:
1885 if (reg != 0)
1886 tcg_gen_mov_tl(cpu_LO[0], cpu_gpr[reg]);
1887 else
1888 tcg_gen_movi_tl(cpu_LO[0], 0);
1889 opn = "mtlo";
1890 break;
1892 MIPS_DEBUG("%s %s", opn, regnames[reg]);
1895 static void gen_muldiv (DisasContext *ctx, uint32_t opc,
1896 int rs, int rt)
1898 const char *opn = "mul/div";
1899 TCGv t0, t1;
1901 switch (opc) {
1902 case OPC_DIV:
1903 case OPC_DIVU:
1904 #if defined(TARGET_MIPS64)
1905 case OPC_DDIV:
1906 case OPC_DDIVU:
1907 #endif
1908 t0 = tcg_temp_local_new();
1909 t1 = tcg_temp_local_new();
1910 break;
1911 default:
1912 t0 = tcg_temp_new();
1913 t1 = tcg_temp_new();
1914 break;
1917 gen_load_gpr(t0, rs);
1918 gen_load_gpr(t1, rt);
1919 switch (opc) {
1920 case OPC_DIV:
1922 int l1 = gen_new_label();
1923 int l2 = gen_new_label();
1925 tcg_gen_ext32s_tl(t0, t0);
1926 tcg_gen_ext32s_tl(t1, t1);
1927 tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
1928 tcg_gen_brcondi_tl(TCG_COND_NE, t0, INT_MIN, l2);
1929 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1, l2);
1931 tcg_gen_mov_tl(cpu_LO[0], t0);
1932 tcg_gen_movi_tl(cpu_HI[0], 0);
1933 tcg_gen_br(l1);
1934 gen_set_label(l2);
1935 tcg_gen_div_tl(cpu_LO[0], t0, t1);
1936 tcg_gen_rem_tl(cpu_HI[0], t0, t1);
1937 tcg_gen_ext32s_tl(cpu_LO[0], cpu_LO[0]);
1938 tcg_gen_ext32s_tl(cpu_HI[0], cpu_HI[0]);
1939 gen_set_label(l1);
1941 opn = "div";
1942 break;
1943 case OPC_DIVU:
1945 int l1 = gen_new_label();
1947 tcg_gen_ext32u_tl(t0, t0);
1948 tcg_gen_ext32u_tl(t1, t1);
1949 tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
1950 tcg_gen_divu_tl(cpu_LO[0], t0, t1);
1951 tcg_gen_remu_tl(cpu_HI[0], t0, t1);
1952 tcg_gen_ext32s_tl(cpu_LO[0], cpu_LO[0]);
1953 tcg_gen_ext32s_tl(cpu_HI[0], cpu_HI[0]);
1954 gen_set_label(l1);
1956 opn = "divu";
1957 break;
1958 case OPC_MULT:
1960 TCGv_i64 t2 = tcg_temp_new_i64();
1961 TCGv_i64 t3 = tcg_temp_new_i64();
1963 tcg_gen_ext_tl_i64(t2, t0);
1964 tcg_gen_ext_tl_i64(t3, t1);
1965 tcg_gen_mul_i64(t2, t2, t3);
1966 tcg_temp_free_i64(t3);
1967 tcg_gen_trunc_i64_tl(t0, t2);
1968 tcg_gen_shri_i64(t2, t2, 32);
1969 tcg_gen_trunc_i64_tl(t1, t2);
1970 tcg_temp_free_i64(t2);
1971 tcg_gen_ext32s_tl(cpu_LO[0], t0);
1972 tcg_gen_ext32s_tl(cpu_HI[0], t1);
1974 opn = "mult";
1975 break;
1976 case OPC_MULTU:
1978 TCGv_i64 t2 = tcg_temp_new_i64();
1979 TCGv_i64 t3 = tcg_temp_new_i64();
1981 tcg_gen_ext32u_tl(t0, t0);
1982 tcg_gen_ext32u_tl(t1, t1);
1983 tcg_gen_extu_tl_i64(t2, t0);
1984 tcg_gen_extu_tl_i64(t3, t1);
1985 tcg_gen_mul_i64(t2, t2, t3);
1986 tcg_temp_free_i64(t3);
1987 tcg_gen_trunc_i64_tl(t0, t2);
1988 tcg_gen_shri_i64(t2, t2, 32);
1989 tcg_gen_trunc_i64_tl(t1, t2);
1990 tcg_temp_free_i64(t2);
1991 tcg_gen_ext32s_tl(cpu_LO[0], t0);
1992 tcg_gen_ext32s_tl(cpu_HI[0], t1);
1994 opn = "multu";
1995 break;
1996 #if defined(TARGET_MIPS64)
1997 case OPC_DDIV:
1999 int l1 = gen_new_label();
2000 int l2 = gen_new_label();
2002 tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
2003 tcg_gen_brcondi_tl(TCG_COND_NE, t0, -1LL << 63, l2);
2004 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1LL, l2);
2005 tcg_gen_mov_tl(cpu_LO[0], t0);
2006 tcg_gen_movi_tl(cpu_HI[0], 0);
2007 tcg_gen_br(l1);
2008 gen_set_label(l2);
2009 tcg_gen_div_i64(cpu_LO[0], t0, t1);
2010 tcg_gen_rem_i64(cpu_HI[0], t0, t1);
2011 gen_set_label(l1);
2013 opn = "ddiv";
2014 break;
2015 case OPC_DDIVU:
2017 int l1 = gen_new_label();
2019 tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
2020 tcg_gen_divu_i64(cpu_LO[0], t0, t1);
2021 tcg_gen_remu_i64(cpu_HI[0], t0, t1);
2022 gen_set_label(l1);
2024 opn = "ddivu";
2025 break;
2026 case OPC_DMULT:
2027 gen_helper_dmult(t0, t1);
2028 opn = "dmult";
2029 break;
2030 case OPC_DMULTU:
2031 gen_helper_dmultu(t0, t1);
2032 opn = "dmultu";
2033 break;
2034 #endif
2035 case OPC_MADD:
2037 TCGv_i64 t2 = tcg_temp_new_i64();
2038 TCGv_i64 t3 = tcg_temp_new_i64();
2040 tcg_gen_ext_tl_i64(t2, t0);
2041 tcg_gen_ext_tl_i64(t3, t1);
2042 tcg_gen_mul_i64(t2, t2, t3);
2043 tcg_gen_concat_tl_i64(t3, cpu_LO[0], cpu_HI[0]);
2044 tcg_gen_add_i64(t2, t2, t3);
2045 tcg_temp_free_i64(t3);
2046 tcg_gen_trunc_i64_tl(t0, t2);
2047 tcg_gen_shri_i64(t2, t2, 32);
2048 tcg_gen_trunc_i64_tl(t1, t2);
2049 tcg_temp_free_i64(t2);
2050 tcg_gen_ext32s_tl(cpu_LO[0], t0);
2051 tcg_gen_ext32s_tl(cpu_HI[0], t1);
2053 opn = "madd";
2054 break;
2055 case OPC_MADDU:
2057 TCGv_i64 t2 = tcg_temp_new_i64();
2058 TCGv_i64 t3 = tcg_temp_new_i64();
2060 tcg_gen_ext32u_tl(t0, t0);
2061 tcg_gen_ext32u_tl(t1, t1);
2062 tcg_gen_extu_tl_i64(t2, t0);
2063 tcg_gen_extu_tl_i64(t3, t1);
2064 tcg_gen_mul_i64(t2, t2, t3);
2065 tcg_gen_concat_tl_i64(t3, cpu_LO[0], cpu_HI[0]);
2066 tcg_gen_add_i64(t2, t2, t3);
2067 tcg_temp_free_i64(t3);
2068 tcg_gen_trunc_i64_tl(t0, t2);
2069 tcg_gen_shri_i64(t2, t2, 32);
2070 tcg_gen_trunc_i64_tl(t1, t2);
2071 tcg_temp_free_i64(t2);
2072 tcg_gen_ext32s_tl(cpu_LO[0], t0);
2073 tcg_gen_ext32s_tl(cpu_HI[0], t1);
2075 opn = "maddu";
2076 break;
2077 case OPC_MSUB:
2079 TCGv_i64 t2 = tcg_temp_new_i64();
2080 TCGv_i64 t3 = tcg_temp_new_i64();
2082 tcg_gen_ext_tl_i64(t2, t0);
2083 tcg_gen_ext_tl_i64(t3, t1);
2084 tcg_gen_mul_i64(t2, t2, t3);
2085 tcg_gen_concat_tl_i64(t3, cpu_LO[0], cpu_HI[0]);
2086 tcg_gen_sub_i64(t2, t3, t2);
2087 tcg_temp_free_i64(t3);
2088 tcg_gen_trunc_i64_tl(t0, t2);
2089 tcg_gen_shri_i64(t2, t2, 32);
2090 tcg_gen_trunc_i64_tl(t1, t2);
2091 tcg_temp_free_i64(t2);
2092 tcg_gen_ext32s_tl(cpu_LO[0], t0);
2093 tcg_gen_ext32s_tl(cpu_HI[0], t1);
2095 opn = "msub";
2096 break;
2097 case OPC_MSUBU:
2099 TCGv_i64 t2 = tcg_temp_new_i64();
2100 TCGv_i64 t3 = tcg_temp_new_i64();
2102 tcg_gen_ext32u_tl(t0, t0);
2103 tcg_gen_ext32u_tl(t1, t1);
2104 tcg_gen_extu_tl_i64(t2, t0);
2105 tcg_gen_extu_tl_i64(t3, t1);
2106 tcg_gen_mul_i64(t2, t2, t3);
2107 tcg_gen_concat_tl_i64(t3, cpu_LO[0], cpu_HI[0]);
2108 tcg_gen_sub_i64(t2, t3, t2);
2109 tcg_temp_free_i64(t3);
2110 tcg_gen_trunc_i64_tl(t0, t2);
2111 tcg_gen_shri_i64(t2, t2, 32);
2112 tcg_gen_trunc_i64_tl(t1, t2);
2113 tcg_temp_free_i64(t2);
2114 tcg_gen_ext32s_tl(cpu_LO[0], t0);
2115 tcg_gen_ext32s_tl(cpu_HI[0], t1);
2117 opn = "msubu";
2118 break;
2119 default:
2120 MIPS_INVAL(opn);
2121 generate_exception(ctx, EXCP_RI);
2122 goto out;
2124 MIPS_DEBUG("%s %s %s", opn, regnames[rs], regnames[rt]);
2125 out:
2126 tcg_temp_free(t0);
2127 tcg_temp_free(t1);
2130 static void gen_mul_vr54xx (DisasContext *ctx, uint32_t opc,
2131 int rd, int rs, int rt)
2133 const char *opn = "mul vr54xx";
2134 TCGv t0 = tcg_temp_new();
2135 TCGv t1 = tcg_temp_new();
2137 gen_load_gpr(t0, rs);
2138 gen_load_gpr(t1, rt);
2140 switch (opc) {
2141 case OPC_VR54XX_MULS:
2142 gen_helper_muls(t0, t0, t1);
2143 opn = "muls";
2144 break;
2145 case OPC_VR54XX_MULSU:
2146 gen_helper_mulsu(t0, t0, t1);
2147 opn = "mulsu";
2148 break;
2149 case OPC_VR54XX_MACC:
2150 gen_helper_macc(t0, t0, t1);
2151 opn = "macc";
2152 break;
2153 case OPC_VR54XX_MACCU:
2154 gen_helper_maccu(t0, t0, t1);
2155 opn = "maccu";
2156 break;
2157 case OPC_VR54XX_MSAC:
2158 gen_helper_msac(t0, t0, t1);
2159 opn = "msac";
2160 break;
2161 case OPC_VR54XX_MSACU:
2162 gen_helper_msacu(t0, t0, t1);
2163 opn = "msacu";
2164 break;
2165 case OPC_VR54XX_MULHI:
2166 gen_helper_mulhi(t0, t0, t1);
2167 opn = "mulhi";
2168 break;
2169 case OPC_VR54XX_MULHIU:
2170 gen_helper_mulhiu(t0, t0, t1);
2171 opn = "mulhiu";
2172 break;
2173 case OPC_VR54XX_MULSHI:
2174 gen_helper_mulshi(t0, t0, t1);
2175 opn = "mulshi";
2176 break;
2177 case OPC_VR54XX_MULSHIU:
2178 gen_helper_mulshiu(t0, t0, t1);
2179 opn = "mulshiu";
2180 break;
2181 case OPC_VR54XX_MACCHI:
2182 gen_helper_macchi(t0, t0, t1);
2183 opn = "macchi";
2184 break;
2185 case OPC_VR54XX_MACCHIU:
2186 gen_helper_macchiu(t0, t0, t1);
2187 opn = "macchiu";
2188 break;
2189 case OPC_VR54XX_MSACHI:
2190 gen_helper_msachi(t0, t0, t1);
2191 opn = "msachi";
2192 break;
2193 case OPC_VR54XX_MSACHIU:
2194 gen_helper_msachiu(t0, t0, t1);
2195 opn = "msachiu";
2196 break;
2197 default:
2198 MIPS_INVAL("mul vr54xx");
2199 generate_exception(ctx, EXCP_RI);
2200 goto out;
2202 gen_store_gpr(t0, rd);
2203 MIPS_DEBUG("%s %s, %s, %s", opn, regnames[rd], regnames[rs], regnames[rt]);
2205 out:
2206 tcg_temp_free(t0);
2207 tcg_temp_free(t1);
2210 static void gen_cl (DisasContext *ctx, uint32_t opc,
2211 int rd, int rs)
2213 const char *opn = "CLx";
2214 TCGv t0;
2216 if (rd == 0) {
2217 /* Treat as NOP. */
2218 MIPS_DEBUG("NOP");
2219 return;
2221 t0 = tcg_temp_new();
2222 gen_load_gpr(t0, rs);
2223 switch (opc) {
2224 case OPC_CLO:
2225 gen_helper_clo(cpu_gpr[rd], t0);
2226 opn = "clo";
2227 break;
2228 case OPC_CLZ:
2229 gen_helper_clz(cpu_gpr[rd], t0);
2230 opn = "clz";
2231 break;
2232 #if defined(TARGET_MIPS64)
2233 case OPC_DCLO:
2234 gen_helper_dclo(cpu_gpr[rd], t0);
2235 opn = "dclo";
2236 break;
2237 case OPC_DCLZ:
2238 gen_helper_dclz(cpu_gpr[rd], t0);
2239 opn = "dclz";
2240 break;
2241 #endif
2243 MIPS_DEBUG("%s %s, %s", opn, regnames[rd], regnames[rs]);
2244 tcg_temp_free(t0);
2247 /* Traps */
2248 static void gen_trap (DisasContext *ctx, uint32_t opc,
2249 int rs, int rt, int16_t imm)
2251 int cond;
2252 TCGv t0 = tcg_temp_new();
2253 TCGv t1 = tcg_temp_new();
2255 cond = 0;
2256 /* Load needed operands */
2257 switch (opc) {
2258 case OPC_TEQ:
2259 case OPC_TGE:
2260 case OPC_TGEU:
2261 case OPC_TLT:
2262 case OPC_TLTU:
2263 case OPC_TNE:
2264 /* Compare two registers */
2265 if (rs != rt) {
2266 gen_load_gpr(t0, rs);
2267 gen_load_gpr(t1, rt);
2268 cond = 1;
2270 break;
2271 case OPC_TEQI:
2272 case OPC_TGEI:
2273 case OPC_TGEIU:
2274 case OPC_TLTI:
2275 case OPC_TLTIU:
2276 case OPC_TNEI:
2277 /* Compare register to immediate */
2278 if (rs != 0 || imm != 0) {
2279 gen_load_gpr(t0, rs);
2280 tcg_gen_movi_tl(t1, (int32_t)imm);
2281 cond = 1;
2283 break;
2285 if (cond == 0) {
2286 switch (opc) {
2287 case OPC_TEQ: /* rs == rs */
2288 case OPC_TEQI: /* r0 == 0 */
2289 case OPC_TGE: /* rs >= rs */
2290 case OPC_TGEI: /* r0 >= 0 */
2291 case OPC_TGEU: /* rs >= rs unsigned */
2292 case OPC_TGEIU: /* r0 >= 0 unsigned */
2293 /* Always trap */
2294 generate_exception(ctx, EXCP_TRAP);
2295 break;
2296 case OPC_TLT: /* rs < rs */
2297 case OPC_TLTI: /* r0 < 0 */
2298 case OPC_TLTU: /* rs < rs unsigned */
2299 case OPC_TLTIU: /* r0 < 0 unsigned */
2300 case OPC_TNE: /* rs != rs */
2301 case OPC_TNEI: /* r0 != 0 */
2302 /* Never trap: treat as NOP. */
2303 break;
2305 } else {
2306 int l1 = gen_new_label();
2308 switch (opc) {
2309 case OPC_TEQ:
2310 case OPC_TEQI:
2311 tcg_gen_brcond_tl(TCG_COND_NE, t0, t1, l1);
2312 break;
2313 case OPC_TGE:
2314 case OPC_TGEI:
2315 tcg_gen_brcond_tl(TCG_COND_LT, t0, t1, l1);
2316 break;
2317 case OPC_TGEU:
2318 case OPC_TGEIU:
2319 tcg_gen_brcond_tl(TCG_COND_LTU, t0, t1, l1);
2320 break;
2321 case OPC_TLT:
2322 case OPC_TLTI:
2323 tcg_gen_brcond_tl(TCG_COND_GE, t0, t1, l1);
2324 break;
2325 case OPC_TLTU:
2326 case OPC_TLTIU:
2327 tcg_gen_brcond_tl(TCG_COND_GEU, t0, t1, l1);
2328 break;
2329 case OPC_TNE:
2330 case OPC_TNEI:
2331 tcg_gen_brcond_tl(TCG_COND_EQ, t0, t1, l1);
2332 break;
2334 generate_exception(ctx, EXCP_TRAP);
2335 gen_set_label(l1);
2337 tcg_temp_free(t0);
2338 tcg_temp_free(t1);
2341 static inline void gen_goto_tb(DisasContext *ctx, int n, target_ulong dest)
2343 TranslationBlock *tb;
2344 tb = ctx->tb;
2345 if ((tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK) &&
2346 likely(!ctx->singlestep_enabled)) {
2347 tcg_gen_goto_tb(n);
2348 gen_save_pc(dest);
2349 tcg_gen_exit_tb((long)tb + n);
2350 } else {
2351 gen_save_pc(dest);
2352 if (ctx->singlestep_enabled) {
2353 save_cpu_state(ctx, 0);
2354 gen_helper_0i(raise_exception, EXCP_DEBUG);
2356 tcg_gen_exit_tb(0);
2360 /* Branches (before delay slot) */
2361 static void gen_compute_branch (DisasContext *ctx, uint32_t opc,
2362 int insn_bytes,
2363 int rs, int rt, int32_t offset)
2365 target_ulong btgt = -1;
2366 int blink = 0;
2367 int bcond_compute = 0;
2368 TCGv t0 = tcg_temp_new();
2369 TCGv t1 = tcg_temp_new();
2371 if (ctx->hflags & MIPS_HFLAG_BMASK) {
2372 #ifdef MIPS_DEBUG_DISAS
2373 LOG_DISAS("Branch in delay slot at PC 0x" TARGET_FMT_lx "\n", ctx->pc);
2374 #endif
2375 generate_exception(ctx, EXCP_RI);
2376 goto out;
2379 /* Load needed operands */
2380 switch (opc) {
2381 case OPC_BEQ:
2382 case OPC_BEQL:
2383 case OPC_BNE:
2384 case OPC_BNEL:
2385 /* Compare two registers */
2386 if (rs != rt) {
2387 gen_load_gpr(t0, rs);
2388 gen_load_gpr(t1, rt);
2389 bcond_compute = 1;
2391 btgt = ctx->pc + insn_bytes + offset;
2392 break;
2393 case OPC_BGEZ:
2394 case OPC_BGEZAL:
2395 case OPC_BGEZALL:
2396 case OPC_BGEZL:
2397 case OPC_BGTZ:
2398 case OPC_BGTZL:
2399 case OPC_BLEZ:
2400 case OPC_BLEZL:
2401 case OPC_BLTZ:
2402 case OPC_BLTZAL:
2403 case OPC_BLTZALL:
2404 case OPC_BLTZL:
2405 /* Compare to zero */
2406 if (rs != 0) {
2407 gen_load_gpr(t0, rs);
2408 bcond_compute = 1;
2410 btgt = ctx->pc + insn_bytes + offset;
2411 break;
2412 case OPC_J:
2413 case OPC_JAL:
2414 case OPC_JALX:
2415 /* Jump to immediate */
2416 btgt = ((ctx->pc + insn_bytes) & (int32_t)0xF0000000) | (uint32_t)offset;
2417 break;
2418 case OPC_JR:
2419 case OPC_JALR:
2420 case OPC_JALRC:
2421 /* Jump to register */
2422 if (offset != 0 && offset != 16) {
2423 /* Hint = 0 is JR/JALR, hint 16 is JR.HB/JALR.HB, the
2424 others are reserved. */
2425 MIPS_INVAL("jump hint");
2426 generate_exception(ctx, EXCP_RI);
2427 goto out;
2429 gen_load_gpr(btarget, rs);
2430 break;
2431 default:
2432 MIPS_INVAL("branch/jump");
2433 generate_exception(ctx, EXCP_RI);
2434 goto out;
2436 if (bcond_compute == 0) {
2437 /* No condition to be computed */
2438 switch (opc) {
2439 case OPC_BEQ: /* rx == rx */
2440 case OPC_BEQL: /* rx == rx likely */
2441 case OPC_BGEZ: /* 0 >= 0 */
2442 case OPC_BGEZL: /* 0 >= 0 likely */
2443 case OPC_BLEZ: /* 0 <= 0 */
2444 case OPC_BLEZL: /* 0 <= 0 likely */
2445 /* Always take */
2446 ctx->hflags |= MIPS_HFLAG_B;
2447 MIPS_DEBUG("balways");
2448 break;
2449 case OPC_BGEZAL: /* 0 >= 0 */
2450 case OPC_BGEZALL: /* 0 >= 0 likely */
2451 /* Always take and link */
2452 blink = 31;
2453 ctx->hflags |= MIPS_HFLAG_B;
2454 MIPS_DEBUG("balways and link");
2455 break;
2456 case OPC_BNE: /* rx != rx */
2457 case OPC_BGTZ: /* 0 > 0 */
2458 case OPC_BLTZ: /* 0 < 0 */
2459 /* Treat as NOP. */
2460 MIPS_DEBUG("bnever (NOP)");
2461 goto out;
2462 case OPC_BLTZAL: /* 0 < 0 */
2463 tcg_gen_movi_tl(cpu_gpr[31], ctx->pc + 8);
2464 MIPS_DEBUG("bnever and link");
2465 goto out;
2466 case OPC_BLTZALL: /* 0 < 0 likely */
2467 tcg_gen_movi_tl(cpu_gpr[31], ctx->pc + 8);
2468 /* Skip the instruction in the delay slot */
2469 MIPS_DEBUG("bnever, link and skip");
2470 ctx->pc += 4;
2471 goto out;
2472 case OPC_BNEL: /* rx != rx likely */
2473 case OPC_BGTZL: /* 0 > 0 likely */
2474 case OPC_BLTZL: /* 0 < 0 likely */
2475 /* Skip the instruction in the delay slot */
2476 MIPS_DEBUG("bnever and skip");
2477 ctx->pc += 4;
2478 goto out;
2479 case OPC_J:
2480 ctx->hflags |= MIPS_HFLAG_B;
2481 MIPS_DEBUG("j " TARGET_FMT_lx, btgt);
2482 break;
2483 case OPC_JALX:
2484 ctx->hflags |= MIPS_HFLAG_BX;
2485 /* Fallthrough */
2486 case OPC_JAL:
2487 blink = 31;
2488 ctx->hflags |= MIPS_HFLAG_B;
2489 ctx->hflags |= (ctx->hflags & MIPS_HFLAG_M16
2490 ? MIPS_HFLAG_BDS16
2491 : MIPS_HFLAG_BDS32);
2492 MIPS_DEBUG("jal " TARGET_FMT_lx, btgt);
2493 break;
2494 case OPC_JR:
2495 ctx->hflags |= MIPS_HFLAG_BR;
2496 if (ctx->hflags & MIPS_HFLAG_M16)
2497 ctx->hflags |= MIPS_HFLAG_BDS16;
2498 MIPS_DEBUG("jr %s", regnames[rs]);
2499 break;
2500 case OPC_JALR:
2501 case OPC_JALRC:
2502 blink = rt;
2503 ctx->hflags |= MIPS_HFLAG_BR;
2504 if (ctx->hflags & MIPS_HFLAG_M16)
2505 ctx->hflags |= MIPS_HFLAG_BDS16;
2506 MIPS_DEBUG("jalr %s, %s", regnames[rt], regnames[rs]);
2507 break;
2508 default:
2509 MIPS_INVAL("branch/jump");
2510 generate_exception(ctx, EXCP_RI);
2511 goto out;
2513 } else {
2514 switch (opc) {
2515 case OPC_BEQ:
2516 tcg_gen_setcond_tl(TCG_COND_EQ, bcond, t0, t1);
2517 MIPS_DEBUG("beq %s, %s, " TARGET_FMT_lx,
2518 regnames[rs], regnames[rt], btgt);
2519 goto not_likely;
2520 case OPC_BEQL:
2521 tcg_gen_setcond_tl(TCG_COND_EQ, bcond, t0, t1);
2522 MIPS_DEBUG("beql %s, %s, " TARGET_FMT_lx,
2523 regnames[rs], regnames[rt], btgt);
2524 goto likely;
2525 case OPC_BNE:
2526 tcg_gen_setcond_tl(TCG_COND_NE, bcond, t0, t1);
2527 MIPS_DEBUG("bne %s, %s, " TARGET_FMT_lx,
2528 regnames[rs], regnames[rt], btgt);
2529 goto not_likely;
2530 case OPC_BNEL:
2531 tcg_gen_setcond_tl(TCG_COND_NE, bcond, t0, t1);
2532 MIPS_DEBUG("bnel %s, %s, " TARGET_FMT_lx,
2533 regnames[rs], regnames[rt], btgt);
2534 goto likely;
2535 case OPC_BGEZ:
2536 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
2537 MIPS_DEBUG("bgez %s, " TARGET_FMT_lx, regnames[rs], btgt);
2538 goto not_likely;
2539 case OPC_BGEZL:
2540 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
2541 MIPS_DEBUG("bgezl %s, " TARGET_FMT_lx, regnames[rs], btgt);
2542 goto likely;
2543 case OPC_BGEZAL:
2544 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
2545 MIPS_DEBUG("bgezal %s, " TARGET_FMT_lx, regnames[rs], btgt);
2546 blink = 31;
2547 goto not_likely;
2548 case OPC_BGEZALL:
2549 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
2550 blink = 31;
2551 MIPS_DEBUG("bgezall %s, " TARGET_FMT_lx, regnames[rs], btgt);
2552 goto likely;
2553 case OPC_BGTZ:
2554 tcg_gen_setcondi_tl(TCG_COND_GT, bcond, t0, 0);
2555 MIPS_DEBUG("bgtz %s, " TARGET_FMT_lx, regnames[rs], btgt);
2556 goto not_likely;
2557 case OPC_BGTZL:
2558 tcg_gen_setcondi_tl(TCG_COND_GT, bcond, t0, 0);
2559 MIPS_DEBUG("bgtzl %s, " TARGET_FMT_lx, regnames[rs], btgt);
2560 goto likely;
2561 case OPC_BLEZ:
2562 tcg_gen_setcondi_tl(TCG_COND_LE, bcond, t0, 0);
2563 MIPS_DEBUG("blez %s, " TARGET_FMT_lx, regnames[rs], btgt);
2564 goto not_likely;
2565 case OPC_BLEZL:
2566 tcg_gen_setcondi_tl(TCG_COND_LE, bcond, t0, 0);
2567 MIPS_DEBUG("blezl %s, " TARGET_FMT_lx, regnames[rs], btgt);
2568 goto likely;
2569 case OPC_BLTZ:
2570 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
2571 MIPS_DEBUG("bltz %s, " TARGET_FMT_lx, regnames[rs], btgt);
2572 goto not_likely;
2573 case OPC_BLTZL:
2574 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
2575 MIPS_DEBUG("bltzl %s, " TARGET_FMT_lx, regnames[rs], btgt);
2576 goto likely;
2577 case OPC_BLTZAL:
2578 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
2579 blink = 31;
2580 MIPS_DEBUG("bltzal %s, " TARGET_FMT_lx, regnames[rs], btgt);
2581 not_likely:
2582 ctx->hflags |= MIPS_HFLAG_BC;
2583 break;
2584 case OPC_BLTZALL:
2585 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
2586 blink = 31;
2587 MIPS_DEBUG("bltzall %s, " TARGET_FMT_lx, regnames[rs], btgt);
2588 likely:
2589 ctx->hflags |= MIPS_HFLAG_BL;
2590 break;
2591 default:
2592 MIPS_INVAL("conditional branch/jump");
2593 generate_exception(ctx, EXCP_RI);
2594 goto out;
2597 MIPS_DEBUG("enter ds: link %d cond %02x target " TARGET_FMT_lx,
2598 blink, ctx->hflags, btgt);
2600 ctx->btarget = btgt;
2601 if (blink > 0) {
2602 int post_delay = insn_bytes;
2603 int lowbit = !!(ctx->hflags & MIPS_HFLAG_M16);
2605 if (opc != OPC_JALRC)
2606 post_delay += ((ctx->hflags & MIPS_HFLAG_BDS16) ? 2 : 4);
2608 tcg_gen_movi_tl(cpu_gpr[blink], ctx->pc + post_delay + lowbit);
2611 out:
2612 if (insn_bytes == 2)
2613 ctx->hflags |= MIPS_HFLAG_B16;
2614 tcg_temp_free(t0);
2615 tcg_temp_free(t1);
2618 /* special3 bitfield operations */
2619 static void gen_bitops (DisasContext *ctx, uint32_t opc, int rt,
2620 int rs, int lsb, int msb)
2622 TCGv t0 = tcg_temp_new();
2623 TCGv t1 = tcg_temp_new();
2624 target_ulong mask;
2626 gen_load_gpr(t1, rs);
2627 switch (opc) {
2628 case OPC_EXT:
2629 if (lsb + msb > 31)
2630 goto fail;
2631 tcg_gen_shri_tl(t0, t1, lsb);
2632 if (msb != 31) {
2633 tcg_gen_andi_tl(t0, t0, (1 << (msb + 1)) - 1);
2634 } else {
2635 tcg_gen_ext32s_tl(t0, t0);
2637 break;
2638 #if defined(TARGET_MIPS64)
2639 case OPC_DEXTM:
2640 tcg_gen_shri_tl(t0, t1, lsb);
2641 if (msb != 31) {
2642 tcg_gen_andi_tl(t0, t0, (1ULL << (msb + 1 + 32)) - 1);
2644 break;
2645 case OPC_DEXTU:
2646 tcg_gen_shri_tl(t0, t1, lsb + 32);
2647 tcg_gen_andi_tl(t0, t0, (1ULL << (msb + 1)) - 1);
2648 break;
2649 case OPC_DEXT:
2650 tcg_gen_shri_tl(t0, t1, lsb);
2651 tcg_gen_andi_tl(t0, t0, (1ULL << (msb + 1)) - 1);
2652 break;
2653 #endif
2654 case OPC_INS:
2655 if (lsb > msb)
2656 goto fail;
2657 mask = ((msb - lsb + 1 < 32) ? ((1 << (msb - lsb + 1)) - 1) : ~0) << lsb;
2658 gen_load_gpr(t0, rt);
2659 tcg_gen_andi_tl(t0, t0, ~mask);
2660 tcg_gen_shli_tl(t1, t1, lsb);
2661 tcg_gen_andi_tl(t1, t1, mask);
2662 tcg_gen_or_tl(t0, t0, t1);
2663 tcg_gen_ext32s_tl(t0, t0);
2664 break;
2665 #if defined(TARGET_MIPS64)
2666 case OPC_DINSM:
2667 if (lsb > msb)
2668 goto fail;
2669 mask = ((msb - lsb + 1 + 32 < 64) ? ((1ULL << (msb - lsb + 1 + 32)) - 1) : ~0ULL) << lsb;
2670 gen_load_gpr(t0, rt);
2671 tcg_gen_andi_tl(t0, t0, ~mask);
2672 tcg_gen_shli_tl(t1, t1, lsb);
2673 tcg_gen_andi_tl(t1, t1, mask);
2674 tcg_gen_or_tl(t0, t0, t1);
2675 break;
2676 case OPC_DINSU:
2677 if (lsb > msb)
2678 goto fail;
2679 mask = ((1ULL << (msb - lsb + 1)) - 1) << lsb;
2680 gen_load_gpr(t0, rt);
2681 tcg_gen_andi_tl(t0, t0, ~mask);
2682 tcg_gen_shli_tl(t1, t1, lsb + 32);
2683 tcg_gen_andi_tl(t1, t1, mask);
2684 tcg_gen_or_tl(t0, t0, t1);
2685 break;
2686 case OPC_DINS:
2687 if (lsb > msb)
2688 goto fail;
2689 gen_load_gpr(t0, rt);
2690 mask = ((1ULL << (msb - lsb + 1)) - 1) << lsb;
2691 gen_load_gpr(t0, rt);
2692 tcg_gen_andi_tl(t0, t0, ~mask);
2693 tcg_gen_shli_tl(t1, t1, lsb);
2694 tcg_gen_andi_tl(t1, t1, mask);
2695 tcg_gen_or_tl(t0, t0, t1);
2696 break;
2697 #endif
2698 default:
2699 fail:
2700 MIPS_INVAL("bitops");
2701 generate_exception(ctx, EXCP_RI);
2702 tcg_temp_free(t0);
2703 tcg_temp_free(t1);
2704 return;
2706 gen_store_gpr(t0, rt);
2707 tcg_temp_free(t0);
2708 tcg_temp_free(t1);
2711 static void gen_bshfl (DisasContext *ctx, uint32_t op2, int rt, int rd)
2713 TCGv t0;
2715 if (rd == 0) {
2716 /* If no destination, treat it as a NOP. */
2717 MIPS_DEBUG("NOP");
2718 return;
2721 t0 = tcg_temp_new();
2722 gen_load_gpr(t0, rt);
2723 switch (op2) {
2724 case OPC_WSBH:
2726 TCGv t1 = tcg_temp_new();
2728 tcg_gen_shri_tl(t1, t0, 8);
2729 tcg_gen_andi_tl(t1, t1, 0x00FF00FF);
2730 tcg_gen_shli_tl(t0, t0, 8);
2731 tcg_gen_andi_tl(t0, t0, ~0x00FF00FF);
2732 tcg_gen_or_tl(t0, t0, t1);
2733 tcg_temp_free(t1);
2734 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
2736 break;
2737 case OPC_SEB:
2738 tcg_gen_ext8s_tl(cpu_gpr[rd], t0);
2739 break;
2740 case OPC_SEH:
2741 tcg_gen_ext16s_tl(cpu_gpr[rd], t0);
2742 break;
2743 #if defined(TARGET_MIPS64)
2744 case OPC_DSBH:
2746 TCGv t1 = tcg_temp_new();
2748 tcg_gen_shri_tl(t1, t0, 8);
2749 tcg_gen_andi_tl(t1, t1, 0x00FF00FF00FF00FFULL);
2750 tcg_gen_shli_tl(t0, t0, 8);
2751 tcg_gen_andi_tl(t0, t0, ~0x00FF00FF00FF00FFULL);
2752 tcg_gen_or_tl(cpu_gpr[rd], t0, t1);
2753 tcg_temp_free(t1);
2755 break;
2756 case OPC_DSHD:
2758 TCGv t1 = tcg_temp_new();
2760 tcg_gen_shri_tl(t1, t0, 16);
2761 tcg_gen_andi_tl(t1, t1, 0x0000FFFF0000FFFFULL);
2762 tcg_gen_shli_tl(t0, t0, 16);
2763 tcg_gen_andi_tl(t0, t0, ~0x0000FFFF0000FFFFULL);
2764 tcg_gen_or_tl(t0, t0, t1);
2765 tcg_gen_shri_tl(t1, t0, 32);
2766 tcg_gen_shli_tl(t0, t0, 32);
2767 tcg_gen_or_tl(cpu_gpr[rd], t0, t1);
2768 tcg_temp_free(t1);
2770 break;
2771 #endif
2772 default:
2773 MIPS_INVAL("bsfhl");
2774 generate_exception(ctx, EXCP_RI);
2775 tcg_temp_free(t0);
2776 return;
2778 tcg_temp_free(t0);
2781 #ifndef CONFIG_USER_ONLY
2782 /* CP0 (MMU and control) */
2783 static inline void gen_mfc0_load32 (TCGv arg, target_ulong off)
2785 TCGv_i32 t0 = tcg_temp_new_i32();
2787 tcg_gen_ld_i32(t0, cpu_env, off);
2788 tcg_gen_ext_i32_tl(arg, t0);
2789 tcg_temp_free_i32(t0);
2792 static inline void gen_mfc0_load64 (TCGv arg, target_ulong off)
2794 tcg_gen_ld_tl(arg, cpu_env, off);
2795 tcg_gen_ext32s_tl(arg, arg);
2798 static inline void gen_mtc0_store32 (TCGv arg, target_ulong off)
2800 TCGv_i32 t0 = tcg_temp_new_i32();
2802 tcg_gen_trunc_tl_i32(t0, arg);
2803 tcg_gen_st_i32(t0, cpu_env, off);
2804 tcg_temp_free_i32(t0);
2807 static inline void gen_mtc0_store64 (TCGv arg, target_ulong off)
2809 tcg_gen_ext32s_tl(arg, arg);
2810 tcg_gen_st_tl(arg, cpu_env, off);
2813 static void gen_mfc0 (CPUState *env, DisasContext *ctx, TCGv arg, int reg, int sel)
2815 const char *rn = "invalid";
2817 if (sel != 0)
2818 check_insn(env, ctx, ISA_MIPS32);
2820 switch (reg) {
2821 case 0:
2822 switch (sel) {
2823 case 0:
2824 gen_mfc0_load32(arg, offsetof(CPUState, CP0_Index));
2825 rn = "Index";
2826 break;
2827 case 1:
2828 check_insn(env, ctx, ASE_MT);
2829 gen_helper_mfc0_mvpcontrol(arg);
2830 rn = "MVPControl";
2831 break;
2832 case 2:
2833 check_insn(env, ctx, ASE_MT);
2834 gen_helper_mfc0_mvpconf0(arg);
2835 rn = "MVPConf0";
2836 break;
2837 case 3:
2838 check_insn(env, ctx, ASE_MT);
2839 gen_helper_mfc0_mvpconf1(arg);
2840 rn = "MVPConf1";
2841 break;
2842 default:
2843 goto die;
2845 break;
2846 case 1:
2847 switch (sel) {
2848 case 0:
2849 gen_helper_mfc0_random(arg);
2850 rn = "Random";
2851 break;
2852 case 1:
2853 check_insn(env, ctx, ASE_MT);
2854 gen_mfc0_load32(arg, offsetof(CPUState, CP0_VPEControl));
2855 rn = "VPEControl";
2856 break;
2857 case 2:
2858 check_insn(env, ctx, ASE_MT);
2859 gen_mfc0_load32(arg, offsetof(CPUState, CP0_VPEConf0));
2860 rn = "VPEConf0";
2861 break;
2862 case 3:
2863 check_insn(env, ctx, ASE_MT);
2864 gen_mfc0_load32(arg, offsetof(CPUState, CP0_VPEConf1));
2865 rn = "VPEConf1";
2866 break;
2867 case 4:
2868 check_insn(env, ctx, ASE_MT);
2869 gen_mfc0_load64(arg, offsetof(CPUState, CP0_YQMask));
2870 rn = "YQMask";
2871 break;
2872 case 5:
2873 check_insn(env, ctx, ASE_MT);
2874 gen_mfc0_load64(arg, offsetof(CPUState, CP0_VPESchedule));
2875 rn = "VPESchedule";
2876 break;
2877 case 6:
2878 check_insn(env, ctx, ASE_MT);
2879 gen_mfc0_load64(arg, offsetof(CPUState, CP0_VPEScheFBack));
2880 rn = "VPEScheFBack";
2881 break;
2882 case 7:
2883 check_insn(env, ctx, ASE_MT);
2884 gen_mfc0_load32(arg, offsetof(CPUState, CP0_VPEOpt));
2885 rn = "VPEOpt";
2886 break;
2887 default:
2888 goto die;
2890 break;
2891 case 2:
2892 switch (sel) {
2893 case 0:
2894 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_EntryLo0));
2895 tcg_gen_ext32s_tl(arg, arg);
2896 rn = "EntryLo0";
2897 break;
2898 case 1:
2899 check_insn(env, ctx, ASE_MT);
2900 gen_helper_mfc0_tcstatus(arg);
2901 rn = "TCStatus";
2902 break;
2903 case 2:
2904 check_insn(env, ctx, ASE_MT);
2905 gen_helper_mfc0_tcbind(arg);
2906 rn = "TCBind";
2907 break;
2908 case 3:
2909 check_insn(env, ctx, ASE_MT);
2910 gen_helper_mfc0_tcrestart(arg);
2911 rn = "TCRestart";
2912 break;
2913 case 4:
2914 check_insn(env, ctx, ASE_MT);
2915 gen_helper_mfc0_tchalt(arg);
2916 rn = "TCHalt";
2917 break;
2918 case 5:
2919 check_insn(env, ctx, ASE_MT);
2920 gen_helper_mfc0_tccontext(arg);
2921 rn = "TCContext";
2922 break;
2923 case 6:
2924 check_insn(env, ctx, ASE_MT);
2925 gen_helper_mfc0_tcschedule(arg);
2926 rn = "TCSchedule";
2927 break;
2928 case 7:
2929 check_insn(env, ctx, ASE_MT);
2930 gen_helper_mfc0_tcschefback(arg);
2931 rn = "TCScheFBack";
2932 break;
2933 default:
2934 goto die;
2936 break;
2937 case 3:
2938 switch (sel) {
2939 case 0:
2940 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_EntryLo1));
2941 tcg_gen_ext32s_tl(arg, arg);
2942 rn = "EntryLo1";
2943 break;
2944 default:
2945 goto die;
2947 break;
2948 case 4:
2949 switch (sel) {
2950 case 0:
2951 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_Context));
2952 tcg_gen_ext32s_tl(arg, arg);
2953 rn = "Context";
2954 break;
2955 case 1:
2956 // gen_helper_mfc0_contextconfig(arg); /* SmartMIPS ASE */
2957 rn = "ContextConfig";
2958 // break;
2959 default:
2960 goto die;
2962 break;
2963 case 5:
2964 switch (sel) {
2965 case 0:
2966 gen_mfc0_load32(arg, offsetof(CPUState, CP0_PageMask));
2967 rn = "PageMask";
2968 break;
2969 case 1:
2970 check_insn(env, ctx, ISA_MIPS32R2);
2971 gen_mfc0_load32(arg, offsetof(CPUState, CP0_PageGrain));
2972 rn = "PageGrain";
2973 break;
2974 default:
2975 goto die;
2977 break;
2978 case 6:
2979 switch (sel) {
2980 case 0:
2981 gen_mfc0_load32(arg, offsetof(CPUState, CP0_Wired));
2982 rn = "Wired";
2983 break;
2984 case 1:
2985 check_insn(env, ctx, ISA_MIPS32R2);
2986 gen_mfc0_load32(arg, offsetof(CPUState, CP0_SRSConf0));
2987 rn = "SRSConf0";
2988 break;
2989 case 2:
2990 check_insn(env, ctx, ISA_MIPS32R2);
2991 gen_mfc0_load32(arg, offsetof(CPUState, CP0_SRSConf1));
2992 rn = "SRSConf1";
2993 break;
2994 case 3:
2995 check_insn(env, ctx, ISA_MIPS32R2);
2996 gen_mfc0_load32(arg, offsetof(CPUState, CP0_SRSConf2));
2997 rn = "SRSConf2";
2998 break;
2999 case 4:
3000 check_insn(env, ctx, ISA_MIPS32R2);
3001 gen_mfc0_load32(arg, offsetof(CPUState, CP0_SRSConf3));
3002 rn = "SRSConf3";
3003 break;
3004 case 5:
3005 check_insn(env, ctx, ISA_MIPS32R2);
3006 gen_mfc0_load32(arg, offsetof(CPUState, CP0_SRSConf4));
3007 rn = "SRSConf4";
3008 break;
3009 default:
3010 goto die;
3012 break;
3013 case 7:
3014 switch (sel) {
3015 case 0:
3016 check_insn(env, ctx, ISA_MIPS32R2);
3017 gen_mfc0_load32(arg, offsetof(CPUState, CP0_HWREna));
3018 rn = "HWREna";
3019 break;
3020 default:
3021 goto die;
3023 break;
3024 case 8:
3025 switch (sel) {
3026 case 0:
3027 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_BadVAddr));
3028 tcg_gen_ext32s_tl(arg, arg);
3029 rn = "BadVAddr";
3030 break;
3031 default:
3032 goto die;
3034 break;
3035 case 9:
3036 switch (sel) {
3037 case 0:
3038 /* Mark as an IO operation because we read the time. */
3039 if (use_icount)
3040 gen_io_start();
3041 gen_helper_mfc0_count(arg);
3042 if (use_icount) {
3043 gen_io_end();
3044 ctx->bstate = BS_STOP;
3046 rn = "Count";
3047 break;
3048 /* 6,7 are implementation dependent */
3049 default:
3050 goto die;
3052 break;
3053 case 10:
3054 switch (sel) {
3055 case 0:
3056 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_EntryHi));
3057 tcg_gen_ext32s_tl(arg, arg);
3058 rn = "EntryHi";
3059 break;
3060 default:
3061 goto die;
3063 break;
3064 case 11:
3065 switch (sel) {
3066 case 0:
3067 gen_mfc0_load32(arg, offsetof(CPUState, CP0_Compare));
3068 rn = "Compare";
3069 break;
3070 /* 6,7 are implementation dependent */
3071 default:
3072 goto die;
3074 break;
3075 case 12:
3076 switch (sel) {
3077 case 0:
3078 gen_mfc0_load32(arg, offsetof(CPUState, CP0_Status));
3079 rn = "Status";
3080 break;
3081 case 1:
3082 check_insn(env, ctx, ISA_MIPS32R2);
3083 gen_mfc0_load32(arg, offsetof(CPUState, CP0_IntCtl));
3084 rn = "IntCtl";
3085 break;
3086 case 2:
3087 check_insn(env, ctx, ISA_MIPS32R2);
3088 gen_mfc0_load32(arg, offsetof(CPUState, CP0_SRSCtl));
3089 rn = "SRSCtl";
3090 break;
3091 case 3:
3092 check_insn(env, ctx, ISA_MIPS32R2);
3093 gen_mfc0_load32(arg, offsetof(CPUState, CP0_SRSMap));
3094 rn = "SRSMap";
3095 break;
3096 default:
3097 goto die;
3099 break;
3100 case 13:
3101 switch (sel) {
3102 case 0:
3103 gen_mfc0_load32(arg, offsetof(CPUState, CP0_Cause));
3104 rn = "Cause";
3105 break;
3106 default:
3107 goto die;
3109 break;
3110 case 14:
3111 switch (sel) {
3112 case 0:
3113 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_EPC));
3114 tcg_gen_ext32s_tl(arg, arg);
3115 rn = "EPC";
3116 break;
3117 default:
3118 goto die;
3120 break;
3121 case 15:
3122 switch (sel) {
3123 case 0:
3124 gen_mfc0_load32(arg, offsetof(CPUState, CP0_PRid));
3125 rn = "PRid";
3126 break;
3127 case 1:
3128 check_insn(env, ctx, ISA_MIPS32R2);
3129 gen_mfc0_load32(arg, offsetof(CPUState, CP0_EBase));
3130 rn = "EBase";
3131 break;
3132 default:
3133 goto die;
3135 break;
3136 case 16:
3137 switch (sel) {
3138 case 0:
3139 gen_mfc0_load32(arg, offsetof(CPUState, CP0_Config0));
3140 rn = "Config";
3141 break;
3142 case 1:
3143 gen_mfc0_load32(arg, offsetof(CPUState, CP0_Config1));
3144 rn = "Config1";
3145 break;
3146 case 2:
3147 gen_mfc0_load32(arg, offsetof(CPUState, CP0_Config2));
3148 rn = "Config2";
3149 break;
3150 case 3:
3151 gen_mfc0_load32(arg, offsetof(CPUState, CP0_Config3));
3152 rn = "Config3";
3153 break;
3154 /* 4,5 are reserved */
3155 /* 6,7 are implementation dependent */
3156 case 6:
3157 gen_mfc0_load32(arg, offsetof(CPUState, CP0_Config6));
3158 rn = "Config6";
3159 break;
3160 case 7:
3161 gen_mfc0_load32(arg, offsetof(CPUState, CP0_Config7));
3162 rn = "Config7";
3163 break;
3164 default:
3165 goto die;
3167 break;
3168 case 17:
3169 switch (sel) {
3170 case 0:
3171 gen_helper_mfc0_lladdr(arg);
3172 rn = "LLAddr";
3173 break;
3174 default:
3175 goto die;
3177 break;
3178 case 18:
3179 switch (sel) {
3180 case 0 ... 7:
3181 gen_helper_1i(mfc0_watchlo, arg, sel);
3182 rn = "WatchLo";
3183 break;
3184 default:
3185 goto die;
3187 break;
3188 case 19:
3189 switch (sel) {
3190 case 0 ...7:
3191 gen_helper_1i(mfc0_watchhi, arg, sel);
3192 rn = "WatchHi";
3193 break;
3194 default:
3195 goto die;
3197 break;
3198 case 20:
3199 switch (sel) {
3200 case 0:
3201 #if defined(TARGET_MIPS64)
3202 check_insn(env, ctx, ISA_MIPS3);
3203 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_XContext));
3204 tcg_gen_ext32s_tl(arg, arg);
3205 rn = "XContext";
3206 break;
3207 #endif
3208 default:
3209 goto die;
3211 break;
3212 case 21:
3213 /* Officially reserved, but sel 0 is used for R1x000 framemask */
3214 switch (sel) {
3215 case 0:
3216 gen_mfc0_load32(arg, offsetof(CPUState, CP0_Framemask));
3217 rn = "Framemask";
3218 break;
3219 default:
3220 goto die;
3222 break;
3223 case 22:
3224 tcg_gen_movi_tl(arg, 0); /* unimplemented */
3225 rn = "'Diagnostic"; /* implementation dependent */
3226 break;
3227 case 23:
3228 switch (sel) {
3229 case 0:
3230 gen_helper_mfc0_debug(arg); /* EJTAG support */
3231 rn = "Debug";
3232 break;
3233 case 1:
3234 // gen_helper_mfc0_tracecontrol(arg); /* PDtrace support */
3235 rn = "TraceControl";
3236 // break;
3237 case 2:
3238 // gen_helper_mfc0_tracecontrol2(arg); /* PDtrace support */
3239 rn = "TraceControl2";
3240 // break;
3241 case 3:
3242 // gen_helper_mfc0_usertracedata(arg); /* PDtrace support */
3243 rn = "UserTraceData";
3244 // break;
3245 case 4:
3246 // gen_helper_mfc0_tracebpc(arg); /* PDtrace support */
3247 rn = "TraceBPC";
3248 // break;
3249 default:
3250 goto die;
3252 break;
3253 case 24:
3254 switch (sel) {
3255 case 0:
3256 /* EJTAG support */
3257 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_DEPC));
3258 tcg_gen_ext32s_tl(arg, arg);
3259 rn = "DEPC";
3260 break;
3261 default:
3262 goto die;
3264 break;
3265 case 25:
3266 switch (sel) {
3267 case 0:
3268 gen_mfc0_load32(arg, offsetof(CPUState, CP0_Performance0));
3269 rn = "Performance0";
3270 break;
3271 case 1:
3272 // gen_helper_mfc0_performance1(arg);
3273 rn = "Performance1";
3274 // break;
3275 case 2:
3276 // gen_helper_mfc0_performance2(arg);
3277 rn = "Performance2";
3278 // break;
3279 case 3:
3280 // gen_helper_mfc0_performance3(arg);
3281 rn = "Performance3";
3282 // break;
3283 case 4:
3284 // gen_helper_mfc0_performance4(arg);
3285 rn = "Performance4";
3286 // break;
3287 case 5:
3288 // gen_helper_mfc0_performance5(arg);
3289 rn = "Performance5";
3290 // break;
3291 case 6:
3292 // gen_helper_mfc0_performance6(arg);
3293 rn = "Performance6";
3294 // break;
3295 case 7:
3296 // gen_helper_mfc0_performance7(arg);
3297 rn = "Performance7";
3298 // break;
3299 default:
3300 goto die;
3302 break;
3303 case 26:
3304 tcg_gen_movi_tl(arg, 0); /* unimplemented */
3305 rn = "ECC";
3306 break;
3307 case 27:
3308 switch (sel) {
3309 case 0 ... 3:
3310 tcg_gen_movi_tl(arg, 0); /* unimplemented */
3311 rn = "CacheErr";
3312 break;
3313 default:
3314 goto die;
3316 break;
3317 case 28:
3318 switch (sel) {
3319 case 0:
3320 case 2:
3321 case 4:
3322 case 6:
3323 gen_mfc0_load32(arg, offsetof(CPUState, CP0_TagLo));
3324 rn = "TagLo";
3325 break;
3326 case 1:
3327 case 3:
3328 case 5:
3329 case 7:
3330 gen_mfc0_load32(arg, offsetof(CPUState, CP0_DataLo));
3331 rn = "DataLo";
3332 break;
3333 default:
3334 goto die;
3336 break;
3337 case 29:
3338 switch (sel) {
3339 case 0:
3340 case 2:
3341 case 4:
3342 case 6:
3343 gen_mfc0_load32(arg, offsetof(CPUState, CP0_TagHi));
3344 rn = "TagHi";
3345 break;
3346 case 1:
3347 case 3:
3348 case 5:
3349 case 7:
3350 gen_mfc0_load32(arg, offsetof(CPUState, CP0_DataHi));
3351 rn = "DataHi";
3352 break;
3353 default:
3354 goto die;
3356 break;
3357 case 30:
3358 switch (sel) {
3359 case 0:
3360 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_ErrorEPC));
3361 tcg_gen_ext32s_tl(arg, arg);
3362 rn = "ErrorEPC";
3363 break;
3364 default:
3365 goto die;
3367 break;
3368 case 31:
3369 switch (sel) {
3370 case 0:
3371 /* EJTAG support */
3372 gen_mfc0_load32(arg, offsetof(CPUState, CP0_DESAVE));
3373 rn = "DESAVE";
3374 break;
3375 default:
3376 goto die;
3378 break;
3379 default:
3380 goto die;
3382 LOG_DISAS("mfc0 %s (reg %d sel %d)\n", rn, reg, sel);
3383 return;
3385 die:
3386 LOG_DISAS("mfc0 %s (reg %d sel %d)\n", rn, reg, sel);
3387 generate_exception(ctx, EXCP_RI);
3390 static void gen_mtc0 (CPUState *env, DisasContext *ctx, TCGv arg, int reg, int sel)
3392 const char *rn = "invalid";
3394 if (sel != 0)
3395 check_insn(env, ctx, ISA_MIPS32);
3397 if (use_icount)
3398 gen_io_start();
3400 switch (reg) {
3401 case 0:
3402 switch (sel) {
3403 case 0:
3404 gen_helper_mtc0_index(arg);
3405 rn = "Index";
3406 break;
3407 case 1:
3408 check_insn(env, ctx, ASE_MT);
3409 gen_helper_mtc0_mvpcontrol(arg);
3410 rn = "MVPControl";
3411 break;
3412 case 2:
3413 check_insn(env, ctx, ASE_MT);
3414 /* ignored */
3415 rn = "MVPConf0";
3416 break;
3417 case 3:
3418 check_insn(env, ctx, ASE_MT);
3419 /* ignored */
3420 rn = "MVPConf1";
3421 break;
3422 default:
3423 goto die;
3425 break;
3426 case 1:
3427 switch (sel) {
3428 case 0:
3429 /* ignored */
3430 rn = "Random";
3431 break;
3432 case 1:
3433 check_insn(env, ctx, ASE_MT);
3434 gen_helper_mtc0_vpecontrol(arg);
3435 rn = "VPEControl";
3436 break;
3437 case 2:
3438 check_insn(env, ctx, ASE_MT);
3439 gen_helper_mtc0_vpeconf0(arg);
3440 rn = "VPEConf0";
3441 break;
3442 case 3:
3443 check_insn(env, ctx, ASE_MT);
3444 gen_helper_mtc0_vpeconf1(arg);
3445 rn = "VPEConf1";
3446 break;
3447 case 4:
3448 check_insn(env, ctx, ASE_MT);
3449 gen_helper_mtc0_yqmask(arg);
3450 rn = "YQMask";
3451 break;
3452 case 5:
3453 check_insn(env, ctx, ASE_MT);
3454 gen_mtc0_store64(arg, offsetof(CPUState, CP0_VPESchedule));
3455 rn = "VPESchedule";
3456 break;
3457 case 6:
3458 check_insn(env, ctx, ASE_MT);
3459 gen_mtc0_store64(arg, offsetof(CPUState, CP0_VPEScheFBack));
3460 rn = "VPEScheFBack";
3461 break;
3462 case 7:
3463 check_insn(env, ctx, ASE_MT);
3464 gen_helper_mtc0_vpeopt(arg);
3465 rn = "VPEOpt";
3466 break;
3467 default:
3468 goto die;
3470 break;
3471 case 2:
3472 switch (sel) {
3473 case 0:
3474 gen_helper_mtc0_entrylo0(arg);
3475 rn = "EntryLo0";
3476 break;
3477 case 1:
3478 check_insn(env, ctx, ASE_MT);
3479 gen_helper_mtc0_tcstatus(arg);
3480 rn = "TCStatus";
3481 break;
3482 case 2:
3483 check_insn(env, ctx, ASE_MT);
3484 gen_helper_mtc0_tcbind(arg);
3485 rn = "TCBind";
3486 break;
3487 case 3:
3488 check_insn(env, ctx, ASE_MT);
3489 gen_helper_mtc0_tcrestart(arg);
3490 rn = "TCRestart";
3491 break;
3492 case 4:
3493 check_insn(env, ctx, ASE_MT);
3494 gen_helper_mtc0_tchalt(arg);
3495 rn = "TCHalt";
3496 break;
3497 case 5:
3498 check_insn(env, ctx, ASE_MT);
3499 gen_helper_mtc0_tccontext(arg);
3500 rn = "TCContext";
3501 break;
3502 case 6:
3503 check_insn(env, ctx, ASE_MT);
3504 gen_helper_mtc0_tcschedule(arg);
3505 rn = "TCSchedule";
3506 break;
3507 case 7:
3508 check_insn(env, ctx, ASE_MT);
3509 gen_helper_mtc0_tcschefback(arg);
3510 rn = "TCScheFBack";
3511 break;
3512 default:
3513 goto die;
3515 break;
3516 case 3:
3517 switch (sel) {
3518 case 0:
3519 gen_helper_mtc0_entrylo1(arg);
3520 rn = "EntryLo1";
3521 break;
3522 default:
3523 goto die;
3525 break;
3526 case 4:
3527 switch (sel) {
3528 case 0:
3529 gen_helper_mtc0_context(arg);
3530 rn = "Context";
3531 break;
3532 case 1:
3533 // gen_helper_mtc0_contextconfig(arg); /* SmartMIPS ASE */
3534 rn = "ContextConfig";
3535 // break;
3536 default:
3537 goto die;
3539 break;
3540 case 5:
3541 switch (sel) {
3542 case 0:
3543 gen_helper_mtc0_pagemask(arg);
3544 rn = "PageMask";
3545 break;
3546 case 1:
3547 check_insn(env, ctx, ISA_MIPS32R2);
3548 gen_helper_mtc0_pagegrain(arg);
3549 rn = "PageGrain";
3550 break;
3551 default:
3552 goto die;
3554 break;
3555 case 6:
3556 switch (sel) {
3557 case 0:
3558 gen_helper_mtc0_wired(arg);
3559 rn = "Wired";
3560 break;
3561 case 1:
3562 check_insn(env, ctx, ISA_MIPS32R2);
3563 gen_helper_mtc0_srsconf0(arg);
3564 rn = "SRSConf0";
3565 break;
3566 case 2:
3567 check_insn(env, ctx, ISA_MIPS32R2);
3568 gen_helper_mtc0_srsconf1(arg);
3569 rn = "SRSConf1";
3570 break;
3571 case 3:
3572 check_insn(env, ctx, ISA_MIPS32R2);
3573 gen_helper_mtc0_srsconf2(arg);
3574 rn = "SRSConf2";
3575 break;
3576 case 4:
3577 check_insn(env, ctx, ISA_MIPS32R2);
3578 gen_helper_mtc0_srsconf3(arg);
3579 rn = "SRSConf3";
3580 break;
3581 case 5:
3582 check_insn(env, ctx, ISA_MIPS32R2);
3583 gen_helper_mtc0_srsconf4(arg);
3584 rn = "SRSConf4";
3585 break;
3586 default:
3587 goto die;
3589 break;
3590 case 7:
3591 switch (sel) {
3592 case 0:
3593 check_insn(env, ctx, ISA_MIPS32R2);
3594 gen_helper_mtc0_hwrena(arg);
3595 rn = "HWREna";
3596 break;
3597 default:
3598 goto die;
3600 break;
3601 case 8:
3602 /* ignored */
3603 rn = "BadVAddr";
3604 break;
3605 case 9:
3606 switch (sel) {
3607 case 0:
3608 gen_helper_mtc0_count(arg);
3609 rn = "Count";
3610 break;
3611 /* 6,7 are implementation dependent */
3612 default:
3613 goto die;
3615 break;
3616 case 10:
3617 switch (sel) {
3618 case 0:
3619 gen_helper_mtc0_entryhi(arg);
3620 rn = "EntryHi";
3621 break;
3622 default:
3623 goto die;
3625 break;
3626 case 11:
3627 switch (sel) {
3628 case 0:
3629 gen_helper_mtc0_compare(arg);
3630 rn = "Compare";
3631 break;
3632 /* 6,7 are implementation dependent */
3633 default:
3634 goto die;
3636 break;
3637 case 12:
3638 switch (sel) {
3639 case 0:
3640 save_cpu_state(ctx, 1);
3641 gen_helper_mtc0_status(arg);
3642 /* BS_STOP isn't good enough here, hflags may have changed. */
3643 gen_save_pc(ctx->pc + 4);
3644 ctx->bstate = BS_EXCP;
3645 rn = "Status";
3646 break;
3647 case 1:
3648 check_insn(env, ctx, ISA_MIPS32R2);
3649 gen_helper_mtc0_intctl(arg);
3650 /* Stop translation as we may have switched the execution mode */
3651 ctx->bstate = BS_STOP;
3652 rn = "IntCtl";
3653 break;
3654 case 2:
3655 check_insn(env, ctx, ISA_MIPS32R2);
3656 gen_helper_mtc0_srsctl(arg);
3657 /* Stop translation as we may have switched the execution mode */
3658 ctx->bstate = BS_STOP;
3659 rn = "SRSCtl";
3660 break;
3661 case 3:
3662 check_insn(env, ctx, ISA_MIPS32R2);
3663 gen_mtc0_store32(arg, offsetof(CPUState, CP0_SRSMap));
3664 /* Stop translation as we may have switched the execution mode */
3665 ctx->bstate = BS_STOP;
3666 rn = "SRSMap";
3667 break;
3668 default:
3669 goto die;
3671 break;
3672 case 13:
3673 switch (sel) {
3674 case 0:
3675 save_cpu_state(ctx, 1);
3676 gen_helper_mtc0_cause(arg);
3677 rn = "Cause";
3678 break;
3679 default:
3680 goto die;
3682 break;
3683 case 14:
3684 switch (sel) {
3685 case 0:
3686 gen_mtc0_store64(arg, offsetof(CPUState, CP0_EPC));
3687 rn = "EPC";
3688 break;
3689 default:
3690 goto die;
3692 break;
3693 case 15:
3694 switch (sel) {
3695 case 0:
3696 /* ignored */
3697 rn = "PRid";
3698 break;
3699 case 1:
3700 check_insn(env, ctx, ISA_MIPS32R2);
3701 gen_helper_mtc0_ebase(arg);
3702 rn = "EBase";
3703 break;
3704 default:
3705 goto die;
3707 break;
3708 case 16:
3709 switch (sel) {
3710 case 0:
3711 gen_helper_mtc0_config0(arg);
3712 rn = "Config";
3713 /* Stop translation as we may have switched the execution mode */
3714 ctx->bstate = BS_STOP;
3715 break;
3716 case 1:
3717 /* ignored, read only */
3718 rn = "Config1";
3719 break;
3720 case 2:
3721 gen_helper_mtc0_config2(arg);
3722 rn = "Config2";
3723 /* Stop translation as we may have switched the execution mode */
3724 ctx->bstate = BS_STOP;
3725 break;
3726 case 3:
3727 /* ignored, read only */
3728 rn = "Config3";
3729 break;
3730 /* 4,5 are reserved */
3731 /* 6,7 are implementation dependent */
3732 case 6:
3733 /* ignored */
3734 rn = "Config6";
3735 break;
3736 case 7:
3737 /* ignored */
3738 rn = "Config7";
3739 break;
3740 default:
3741 rn = "Invalid config selector";
3742 goto die;
3744 break;
3745 case 17:
3746 switch (sel) {
3747 case 0:
3748 gen_helper_mtc0_lladdr(arg);
3749 rn = "LLAddr";
3750 break;
3751 default:
3752 goto die;
3754 break;
3755 case 18:
3756 switch (sel) {
3757 case 0 ... 7:
3758 gen_helper_1i(mtc0_watchlo, arg, sel);
3759 rn = "WatchLo";
3760 break;
3761 default:
3762 goto die;
3764 break;
3765 case 19:
3766 switch (sel) {
3767 case 0 ... 7:
3768 gen_helper_1i(mtc0_watchhi, arg, sel);
3769 rn = "WatchHi";
3770 break;
3771 default:
3772 goto die;
3774 break;
3775 case 20:
3776 switch (sel) {
3777 case 0:
3778 #if defined(TARGET_MIPS64)
3779 check_insn(env, ctx, ISA_MIPS3);
3780 gen_helper_mtc0_xcontext(arg);
3781 rn = "XContext";
3782 break;
3783 #endif
3784 default:
3785 goto die;
3787 break;
3788 case 21:
3789 /* Officially reserved, but sel 0 is used for R1x000 framemask */
3790 switch (sel) {
3791 case 0:
3792 gen_helper_mtc0_framemask(arg);
3793 rn = "Framemask";
3794 break;
3795 default:
3796 goto die;
3798 break;
3799 case 22:
3800 /* ignored */
3801 rn = "Diagnostic"; /* implementation dependent */
3802 break;
3803 case 23:
3804 switch (sel) {
3805 case 0:
3806 gen_helper_mtc0_debug(arg); /* EJTAG support */
3807 /* BS_STOP isn't good enough here, hflags may have changed. */
3808 gen_save_pc(ctx->pc + 4);
3809 ctx->bstate = BS_EXCP;
3810 rn = "Debug";
3811 break;
3812 case 1:
3813 // gen_helper_mtc0_tracecontrol(arg); /* PDtrace support */
3814 rn = "TraceControl";
3815 /* Stop translation as we may have switched the execution mode */
3816 ctx->bstate = BS_STOP;
3817 // break;
3818 case 2:
3819 // gen_helper_mtc0_tracecontrol2(arg); /* PDtrace support */
3820 rn = "TraceControl2";
3821 /* Stop translation as we may have switched the execution mode */
3822 ctx->bstate = BS_STOP;
3823 // break;
3824 case 3:
3825 /* Stop translation as we may have switched the execution mode */
3826 ctx->bstate = BS_STOP;
3827 // gen_helper_mtc0_usertracedata(arg); /* PDtrace support */
3828 rn = "UserTraceData";
3829 /* Stop translation as we may have switched the execution mode */
3830 ctx->bstate = BS_STOP;
3831 // break;
3832 case 4:
3833 // gen_helper_mtc0_tracebpc(arg); /* PDtrace support */
3834 /* Stop translation as we may have switched the execution mode */
3835 ctx->bstate = BS_STOP;
3836 rn = "TraceBPC";
3837 // break;
3838 default:
3839 goto die;
3841 break;
3842 case 24:
3843 switch (sel) {
3844 case 0:
3845 /* EJTAG support */
3846 gen_mtc0_store64(arg, offsetof(CPUState, CP0_DEPC));
3847 rn = "DEPC";
3848 break;
3849 default:
3850 goto die;
3852 break;
3853 case 25:
3854 switch (sel) {
3855 case 0:
3856 gen_helper_mtc0_performance0(arg);
3857 rn = "Performance0";
3858 break;
3859 case 1:
3860 // gen_helper_mtc0_performance1(arg);
3861 rn = "Performance1";
3862 // break;
3863 case 2:
3864 // gen_helper_mtc0_performance2(arg);
3865 rn = "Performance2";
3866 // break;
3867 case 3:
3868 // gen_helper_mtc0_performance3(arg);
3869 rn = "Performance3";
3870 // break;
3871 case 4:
3872 // gen_helper_mtc0_performance4(arg);
3873 rn = "Performance4";
3874 // break;
3875 case 5:
3876 // gen_helper_mtc0_performance5(arg);
3877 rn = "Performance5";
3878 // break;
3879 case 6:
3880 // gen_helper_mtc0_performance6(arg);
3881 rn = "Performance6";
3882 // break;
3883 case 7:
3884 // gen_helper_mtc0_performance7(arg);
3885 rn = "Performance7";
3886 // break;
3887 default:
3888 goto die;
3890 break;
3891 case 26:
3892 /* ignored */
3893 rn = "ECC";
3894 break;
3895 case 27:
3896 switch (sel) {
3897 case 0 ... 3:
3898 /* ignored */
3899 rn = "CacheErr";
3900 break;
3901 default:
3902 goto die;
3904 break;
3905 case 28:
3906 switch (sel) {
3907 case 0:
3908 case 2:
3909 case 4:
3910 case 6:
3911 gen_helper_mtc0_taglo(arg);
3912 rn = "TagLo";
3913 break;
3914 case 1:
3915 case 3:
3916 case 5:
3917 case 7:
3918 gen_helper_mtc0_datalo(arg);
3919 rn = "DataLo";
3920 break;
3921 default:
3922 goto die;
3924 break;
3925 case 29:
3926 switch (sel) {
3927 case 0:
3928 case 2:
3929 case 4:
3930 case 6:
3931 gen_helper_mtc0_taghi(arg);
3932 rn = "TagHi";
3933 break;
3934 case 1:
3935 case 3:
3936 case 5:
3937 case 7:
3938 gen_helper_mtc0_datahi(arg);
3939 rn = "DataHi";
3940 break;
3941 default:
3942 rn = "invalid sel";
3943 goto die;
3945 break;
3946 case 30:
3947 switch (sel) {
3948 case 0:
3949 gen_mtc0_store64(arg, offsetof(CPUState, CP0_ErrorEPC));
3950 rn = "ErrorEPC";
3951 break;
3952 default:
3953 goto die;
3955 break;
3956 case 31:
3957 switch (sel) {
3958 case 0:
3959 /* EJTAG support */
3960 gen_mtc0_store32(arg, offsetof(CPUState, CP0_DESAVE));
3961 rn = "DESAVE";
3962 break;
3963 default:
3964 goto die;
3966 /* Stop translation as we may have switched the execution mode */
3967 ctx->bstate = BS_STOP;
3968 break;
3969 default:
3970 goto die;
3972 LOG_DISAS("mtc0 %s (reg %d sel %d)\n", rn, reg, sel);
3973 /* For simplicity assume that all writes can cause interrupts. */
3974 if (use_icount) {
3975 gen_io_end();
3976 ctx->bstate = BS_STOP;
3978 return;
3980 die:
3981 LOG_DISAS("mtc0 %s (reg %d sel %d)\n", rn, reg, sel);
3982 generate_exception(ctx, EXCP_RI);
3985 #if defined(TARGET_MIPS64)
3986 static void gen_dmfc0 (CPUState *env, DisasContext *ctx, TCGv arg, int reg, int sel)
3988 const char *rn = "invalid";
3990 if (sel != 0)
3991 check_insn(env, ctx, ISA_MIPS64);
3993 switch (reg) {
3994 case 0:
3995 switch (sel) {
3996 case 0:
3997 gen_mfc0_load32(arg, offsetof(CPUState, CP0_Index));
3998 rn = "Index";
3999 break;
4000 case 1:
4001 check_insn(env, ctx, ASE_MT);
4002 gen_helper_mfc0_mvpcontrol(arg);
4003 rn = "MVPControl";
4004 break;
4005 case 2:
4006 check_insn(env, ctx, ASE_MT);
4007 gen_helper_mfc0_mvpconf0(arg);
4008 rn = "MVPConf0";
4009 break;
4010 case 3:
4011 check_insn(env, ctx, ASE_MT);
4012 gen_helper_mfc0_mvpconf1(arg);
4013 rn = "MVPConf1";
4014 break;
4015 default:
4016 goto die;
4018 break;
4019 case 1:
4020 switch (sel) {
4021 case 0:
4022 gen_helper_mfc0_random(arg);
4023 rn = "Random";
4024 break;
4025 case 1:
4026 check_insn(env, ctx, ASE_MT);
4027 gen_mfc0_load32(arg, offsetof(CPUState, CP0_VPEControl));
4028 rn = "VPEControl";
4029 break;
4030 case 2:
4031 check_insn(env, ctx, ASE_MT);
4032 gen_mfc0_load32(arg, offsetof(CPUState, CP0_VPEConf0));
4033 rn = "VPEConf0";
4034 break;
4035 case 3:
4036 check_insn(env, ctx, ASE_MT);
4037 gen_mfc0_load32(arg, offsetof(CPUState, CP0_VPEConf1));
4038 rn = "VPEConf1";
4039 break;
4040 case 4:
4041 check_insn(env, ctx, ASE_MT);
4042 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_YQMask));
4043 rn = "YQMask";
4044 break;
4045 case 5:
4046 check_insn(env, ctx, ASE_MT);
4047 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_VPESchedule));
4048 rn = "VPESchedule";
4049 break;
4050 case 6:
4051 check_insn(env, ctx, ASE_MT);
4052 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_VPEScheFBack));
4053 rn = "VPEScheFBack";
4054 break;
4055 case 7:
4056 check_insn(env, ctx, ASE_MT);
4057 gen_mfc0_load32(arg, offsetof(CPUState, CP0_VPEOpt));
4058 rn = "VPEOpt";
4059 break;
4060 default:
4061 goto die;
4063 break;
4064 case 2:
4065 switch (sel) {
4066 case 0:
4067 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_EntryLo0));
4068 rn = "EntryLo0";
4069 break;
4070 case 1:
4071 check_insn(env, ctx, ASE_MT);
4072 gen_helper_mfc0_tcstatus(arg);
4073 rn = "TCStatus";
4074 break;
4075 case 2:
4076 check_insn(env, ctx, ASE_MT);
4077 gen_helper_mfc0_tcbind(arg);
4078 rn = "TCBind";
4079 break;
4080 case 3:
4081 check_insn(env, ctx, ASE_MT);
4082 gen_helper_dmfc0_tcrestart(arg);
4083 rn = "TCRestart";
4084 break;
4085 case 4:
4086 check_insn(env, ctx, ASE_MT);
4087 gen_helper_dmfc0_tchalt(arg);
4088 rn = "TCHalt";
4089 break;
4090 case 5:
4091 check_insn(env, ctx, ASE_MT);
4092 gen_helper_dmfc0_tccontext(arg);
4093 rn = "TCContext";
4094 break;
4095 case 6:
4096 check_insn(env, ctx, ASE_MT);
4097 gen_helper_dmfc0_tcschedule(arg);
4098 rn = "TCSchedule";
4099 break;
4100 case 7:
4101 check_insn(env, ctx, ASE_MT);
4102 gen_helper_dmfc0_tcschefback(arg);
4103 rn = "TCScheFBack";
4104 break;
4105 default:
4106 goto die;
4108 break;
4109 case 3:
4110 switch (sel) {
4111 case 0:
4112 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_EntryLo1));
4113 rn = "EntryLo1";
4114 break;
4115 default:
4116 goto die;
4118 break;
4119 case 4:
4120 switch (sel) {
4121 case 0:
4122 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_Context));
4123 rn = "Context";
4124 break;
4125 case 1:
4126 // gen_helper_dmfc0_contextconfig(arg); /* SmartMIPS ASE */
4127 rn = "ContextConfig";
4128 // break;
4129 default:
4130 goto die;
4132 break;
4133 case 5:
4134 switch (sel) {
4135 case 0:
4136 gen_mfc0_load32(arg, offsetof(CPUState, CP0_PageMask));
4137 rn = "PageMask";
4138 break;
4139 case 1:
4140 check_insn(env, ctx, ISA_MIPS32R2);
4141 gen_mfc0_load32(arg, offsetof(CPUState, CP0_PageGrain));
4142 rn = "PageGrain";
4143 break;
4144 default:
4145 goto die;
4147 break;
4148 case 6:
4149 switch (sel) {
4150 case 0:
4151 gen_mfc0_load32(arg, offsetof(CPUState, CP0_Wired));
4152 rn = "Wired";
4153 break;
4154 case 1:
4155 check_insn(env, ctx, ISA_MIPS32R2);
4156 gen_mfc0_load32(arg, offsetof(CPUState, CP0_SRSConf0));
4157 rn = "SRSConf0";
4158 break;
4159 case 2:
4160 check_insn(env, ctx, ISA_MIPS32R2);
4161 gen_mfc0_load32(arg, offsetof(CPUState, CP0_SRSConf1));
4162 rn = "SRSConf1";
4163 break;
4164 case 3:
4165 check_insn(env, ctx, ISA_MIPS32R2);
4166 gen_mfc0_load32(arg, offsetof(CPUState, CP0_SRSConf2));
4167 rn = "SRSConf2";
4168 break;
4169 case 4:
4170 check_insn(env, ctx, ISA_MIPS32R2);
4171 gen_mfc0_load32(arg, offsetof(CPUState, CP0_SRSConf3));
4172 rn = "SRSConf3";
4173 break;
4174 case 5:
4175 check_insn(env, ctx, ISA_MIPS32R2);
4176 gen_mfc0_load32(arg, offsetof(CPUState, CP0_SRSConf4));
4177 rn = "SRSConf4";
4178 break;
4179 default:
4180 goto die;
4182 break;
4183 case 7:
4184 switch (sel) {
4185 case 0:
4186 check_insn(env, ctx, ISA_MIPS32R2);
4187 gen_mfc0_load32(arg, offsetof(CPUState, CP0_HWREna));
4188 rn = "HWREna";
4189 break;
4190 default:
4191 goto die;
4193 break;
4194 case 8:
4195 switch (sel) {
4196 case 0:
4197 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_BadVAddr));
4198 rn = "BadVAddr";
4199 break;
4200 default:
4201 goto die;
4203 break;
4204 case 9:
4205 switch (sel) {
4206 case 0:
4207 /* Mark as an IO operation because we read the time. */
4208 if (use_icount)
4209 gen_io_start();
4210 gen_helper_mfc0_count(arg);
4211 if (use_icount) {
4212 gen_io_end();
4213 ctx->bstate = BS_STOP;
4215 rn = "Count";
4216 break;
4217 /* 6,7 are implementation dependent */
4218 default:
4219 goto die;
4221 break;
4222 case 10:
4223 switch (sel) {
4224 case 0:
4225 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_EntryHi));
4226 rn = "EntryHi";
4227 break;
4228 default:
4229 goto die;
4231 break;
4232 case 11:
4233 switch (sel) {
4234 case 0:
4235 gen_mfc0_load32(arg, offsetof(CPUState, CP0_Compare));
4236 rn = "Compare";
4237 break;
4238 /* 6,7 are implementation dependent */
4239 default:
4240 goto die;
4242 break;
4243 case 12:
4244 switch (sel) {
4245 case 0:
4246 gen_mfc0_load32(arg, offsetof(CPUState, CP0_Status));
4247 rn = "Status";
4248 break;
4249 case 1:
4250 check_insn(env, ctx, ISA_MIPS32R2);
4251 gen_mfc0_load32(arg, offsetof(CPUState, CP0_IntCtl));
4252 rn = "IntCtl";
4253 break;
4254 case 2:
4255 check_insn(env, ctx, ISA_MIPS32R2);
4256 gen_mfc0_load32(arg, offsetof(CPUState, CP0_SRSCtl));
4257 rn = "SRSCtl";
4258 break;
4259 case 3:
4260 check_insn(env, ctx, ISA_MIPS32R2);
4261 gen_mfc0_load32(arg, offsetof(CPUState, CP0_SRSMap));
4262 rn = "SRSMap";
4263 break;
4264 default:
4265 goto die;
4267 break;
4268 case 13:
4269 switch (sel) {
4270 case 0:
4271 gen_mfc0_load32(arg, offsetof(CPUState, CP0_Cause));
4272 rn = "Cause";
4273 break;
4274 default:
4275 goto die;
4277 break;
4278 case 14:
4279 switch (sel) {
4280 case 0:
4281 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_EPC));
4282 rn = "EPC";
4283 break;
4284 default:
4285 goto die;
4287 break;
4288 case 15:
4289 switch (sel) {
4290 case 0:
4291 gen_mfc0_load32(arg, offsetof(CPUState, CP0_PRid));
4292 rn = "PRid";
4293 break;
4294 case 1:
4295 check_insn(env, ctx, ISA_MIPS32R2);
4296 gen_mfc0_load32(arg, offsetof(CPUState, CP0_EBase));
4297 rn = "EBase";
4298 break;
4299 default:
4300 goto die;
4302 break;
4303 case 16:
4304 switch (sel) {
4305 case 0:
4306 gen_mfc0_load32(arg, offsetof(CPUState, CP0_Config0));
4307 rn = "Config";
4308 break;
4309 case 1:
4310 gen_mfc0_load32(arg, offsetof(CPUState, CP0_Config1));
4311 rn = "Config1";
4312 break;
4313 case 2:
4314 gen_mfc0_load32(arg, offsetof(CPUState, CP0_Config2));
4315 rn = "Config2";
4316 break;
4317 case 3:
4318 gen_mfc0_load32(arg, offsetof(CPUState, CP0_Config3));
4319 rn = "Config3";
4320 break;
4321 /* 6,7 are implementation dependent */
4322 case 6:
4323 gen_mfc0_load32(arg, offsetof(CPUState, CP0_Config6));
4324 rn = "Config6";
4325 break;
4326 case 7:
4327 gen_mfc0_load32(arg, offsetof(CPUState, CP0_Config7));
4328 rn = "Config7";
4329 break;
4330 default:
4331 goto die;
4333 break;
4334 case 17:
4335 switch (sel) {
4336 case 0:
4337 gen_helper_dmfc0_lladdr(arg);
4338 rn = "LLAddr";
4339 break;
4340 default:
4341 goto die;
4343 break;
4344 case 18:
4345 switch (sel) {
4346 case 0 ... 7:
4347 gen_helper_1i(dmfc0_watchlo, arg, sel);
4348 rn = "WatchLo";
4349 break;
4350 default:
4351 goto die;
4353 break;
4354 case 19:
4355 switch (sel) {
4356 case 0 ... 7:
4357 gen_helper_1i(mfc0_watchhi, arg, sel);
4358 rn = "WatchHi";
4359 break;
4360 default:
4361 goto die;
4363 break;
4364 case 20:
4365 switch (sel) {
4366 case 0:
4367 check_insn(env, ctx, ISA_MIPS3);
4368 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_XContext));
4369 rn = "XContext";
4370 break;
4371 default:
4372 goto die;
4374 break;
4375 case 21:
4376 /* Officially reserved, but sel 0 is used for R1x000 framemask */
4377 switch (sel) {
4378 case 0:
4379 gen_mfc0_load32(arg, offsetof(CPUState, CP0_Framemask));
4380 rn = "Framemask";
4381 break;
4382 default:
4383 goto die;
4385 break;
4386 case 22:
4387 tcg_gen_movi_tl(arg, 0); /* unimplemented */
4388 rn = "'Diagnostic"; /* implementation dependent */
4389 break;
4390 case 23:
4391 switch (sel) {
4392 case 0:
4393 gen_helper_mfc0_debug(arg); /* EJTAG support */
4394 rn = "Debug";
4395 break;
4396 case 1:
4397 // gen_helper_dmfc0_tracecontrol(arg); /* PDtrace support */
4398 rn = "TraceControl";
4399 // break;
4400 case 2:
4401 // gen_helper_dmfc0_tracecontrol2(arg); /* PDtrace support */
4402 rn = "TraceControl2";
4403 // break;
4404 case 3:
4405 // gen_helper_dmfc0_usertracedata(arg); /* PDtrace support */
4406 rn = "UserTraceData";
4407 // break;
4408 case 4:
4409 // gen_helper_dmfc0_tracebpc(arg); /* PDtrace support */
4410 rn = "TraceBPC";
4411 // break;
4412 default:
4413 goto die;
4415 break;
4416 case 24:
4417 switch (sel) {
4418 case 0:
4419 /* EJTAG support */
4420 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_DEPC));
4421 rn = "DEPC";
4422 break;
4423 default:
4424 goto die;
4426 break;
4427 case 25:
4428 switch (sel) {
4429 case 0:
4430 gen_mfc0_load32(arg, offsetof(CPUState, CP0_Performance0));
4431 rn = "Performance0";
4432 break;
4433 case 1:
4434 // gen_helper_dmfc0_performance1(arg);
4435 rn = "Performance1";
4436 // break;
4437 case 2:
4438 // gen_helper_dmfc0_performance2(arg);
4439 rn = "Performance2";
4440 // break;
4441 case 3:
4442 // gen_helper_dmfc0_performance3(arg);
4443 rn = "Performance3";
4444 // break;
4445 case 4:
4446 // gen_helper_dmfc0_performance4(arg);
4447 rn = "Performance4";
4448 // break;
4449 case 5:
4450 // gen_helper_dmfc0_performance5(arg);
4451 rn = "Performance5";
4452 // break;
4453 case 6:
4454 // gen_helper_dmfc0_performance6(arg);
4455 rn = "Performance6";
4456 // break;
4457 case 7:
4458 // gen_helper_dmfc0_performance7(arg);
4459 rn = "Performance7";
4460 // break;
4461 default:
4462 goto die;
4464 break;
4465 case 26:
4466 tcg_gen_movi_tl(arg, 0); /* unimplemented */
4467 rn = "ECC";
4468 break;
4469 case 27:
4470 switch (sel) {
4471 /* ignored */
4472 case 0 ... 3:
4473 tcg_gen_movi_tl(arg, 0); /* unimplemented */
4474 rn = "CacheErr";
4475 break;
4476 default:
4477 goto die;
4479 break;
4480 case 28:
4481 switch (sel) {
4482 case 0:
4483 case 2:
4484 case 4:
4485 case 6:
4486 gen_mfc0_load32(arg, offsetof(CPUState, CP0_TagLo));
4487 rn = "TagLo";
4488 break;
4489 case 1:
4490 case 3:
4491 case 5:
4492 case 7:
4493 gen_mfc0_load32(arg, offsetof(CPUState, CP0_DataLo));
4494 rn = "DataLo";
4495 break;
4496 default:
4497 goto die;
4499 break;
4500 case 29:
4501 switch (sel) {
4502 case 0:
4503 case 2:
4504 case 4:
4505 case 6:
4506 gen_mfc0_load32(arg, offsetof(CPUState, CP0_TagHi));
4507 rn = "TagHi";
4508 break;
4509 case 1:
4510 case 3:
4511 case 5:
4512 case 7:
4513 gen_mfc0_load32(arg, offsetof(CPUState, CP0_DataHi));
4514 rn = "DataHi";
4515 break;
4516 default:
4517 goto die;
4519 break;
4520 case 30:
4521 switch (sel) {
4522 case 0:
4523 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_ErrorEPC));
4524 rn = "ErrorEPC";
4525 break;
4526 default:
4527 goto die;
4529 break;
4530 case 31:
4531 switch (sel) {
4532 case 0:
4533 /* EJTAG support */
4534 gen_mfc0_load32(arg, offsetof(CPUState, CP0_DESAVE));
4535 rn = "DESAVE";
4536 break;
4537 default:
4538 goto die;
4540 break;
4541 default:
4542 goto die;
4544 LOG_DISAS("dmfc0 %s (reg %d sel %d)\n", rn, reg, sel);
4545 return;
4547 die:
4548 LOG_DISAS("dmfc0 %s (reg %d sel %d)\n", rn, reg, sel);
4549 generate_exception(ctx, EXCP_RI);
4552 static void gen_dmtc0 (CPUState *env, DisasContext *ctx, TCGv arg, int reg, int sel)
4554 const char *rn = "invalid";
4556 if (sel != 0)
4557 check_insn(env, ctx, ISA_MIPS64);
4559 if (use_icount)
4560 gen_io_start();
4562 switch (reg) {
4563 case 0:
4564 switch (sel) {
4565 case 0:
4566 gen_helper_mtc0_index(arg);
4567 rn = "Index";
4568 break;
4569 case 1:
4570 check_insn(env, ctx, ASE_MT);
4571 gen_helper_mtc0_mvpcontrol(arg);
4572 rn = "MVPControl";
4573 break;
4574 case 2:
4575 check_insn(env, ctx, ASE_MT);
4576 /* ignored */
4577 rn = "MVPConf0";
4578 break;
4579 case 3:
4580 check_insn(env, ctx, ASE_MT);
4581 /* ignored */
4582 rn = "MVPConf1";
4583 break;
4584 default:
4585 goto die;
4587 break;
4588 case 1:
4589 switch (sel) {
4590 case 0:
4591 /* ignored */
4592 rn = "Random";
4593 break;
4594 case 1:
4595 check_insn(env, ctx, ASE_MT);
4596 gen_helper_mtc0_vpecontrol(arg);
4597 rn = "VPEControl";
4598 break;
4599 case 2:
4600 check_insn(env, ctx, ASE_MT);
4601 gen_helper_mtc0_vpeconf0(arg);
4602 rn = "VPEConf0";
4603 break;
4604 case 3:
4605 check_insn(env, ctx, ASE_MT);
4606 gen_helper_mtc0_vpeconf1(arg);
4607 rn = "VPEConf1";
4608 break;
4609 case 4:
4610 check_insn(env, ctx, ASE_MT);
4611 gen_helper_mtc0_yqmask(arg);
4612 rn = "YQMask";
4613 break;
4614 case 5:
4615 check_insn(env, ctx, ASE_MT);
4616 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUState, CP0_VPESchedule));
4617 rn = "VPESchedule";
4618 break;
4619 case 6:
4620 check_insn(env, ctx, ASE_MT);
4621 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUState, CP0_VPEScheFBack));
4622 rn = "VPEScheFBack";
4623 break;
4624 case 7:
4625 check_insn(env, ctx, ASE_MT);
4626 gen_helper_mtc0_vpeopt(arg);
4627 rn = "VPEOpt";
4628 break;
4629 default:
4630 goto die;
4632 break;
4633 case 2:
4634 switch (sel) {
4635 case 0:
4636 gen_helper_mtc0_entrylo0(arg);
4637 rn = "EntryLo0";
4638 break;
4639 case 1:
4640 check_insn(env, ctx, ASE_MT);
4641 gen_helper_mtc0_tcstatus(arg);
4642 rn = "TCStatus";
4643 break;
4644 case 2:
4645 check_insn(env, ctx, ASE_MT);
4646 gen_helper_mtc0_tcbind(arg);
4647 rn = "TCBind";
4648 break;
4649 case 3:
4650 check_insn(env, ctx, ASE_MT);
4651 gen_helper_mtc0_tcrestart(arg);
4652 rn = "TCRestart";
4653 break;
4654 case 4:
4655 check_insn(env, ctx, ASE_MT);
4656 gen_helper_mtc0_tchalt(arg);
4657 rn = "TCHalt";
4658 break;
4659 case 5:
4660 check_insn(env, ctx, ASE_MT);
4661 gen_helper_mtc0_tccontext(arg);
4662 rn = "TCContext";
4663 break;
4664 case 6:
4665 check_insn(env, ctx, ASE_MT);
4666 gen_helper_mtc0_tcschedule(arg);
4667 rn = "TCSchedule";
4668 break;
4669 case 7:
4670 check_insn(env, ctx, ASE_MT);
4671 gen_helper_mtc0_tcschefback(arg);
4672 rn = "TCScheFBack";
4673 break;
4674 default:
4675 goto die;
4677 break;
4678 case 3:
4679 switch (sel) {
4680 case 0:
4681 gen_helper_mtc0_entrylo1(arg);
4682 rn = "EntryLo1";
4683 break;
4684 default:
4685 goto die;
4687 break;
4688 case 4:
4689 switch (sel) {
4690 case 0:
4691 gen_helper_mtc0_context(arg);
4692 rn = "Context";
4693 break;
4694 case 1:
4695 // gen_helper_mtc0_contextconfig(arg); /* SmartMIPS ASE */
4696 rn = "ContextConfig";
4697 // break;
4698 default:
4699 goto die;
4701 break;
4702 case 5:
4703 switch (sel) {
4704 case 0:
4705 gen_helper_mtc0_pagemask(arg);
4706 rn = "PageMask";
4707 break;
4708 case 1:
4709 check_insn(env, ctx, ISA_MIPS32R2);
4710 gen_helper_mtc0_pagegrain(arg);
4711 rn = "PageGrain";
4712 break;
4713 default:
4714 goto die;
4716 break;
4717 case 6:
4718 switch (sel) {
4719 case 0:
4720 gen_helper_mtc0_wired(arg);
4721 rn = "Wired";
4722 break;
4723 case 1:
4724 check_insn(env, ctx, ISA_MIPS32R2);
4725 gen_helper_mtc0_srsconf0(arg);
4726 rn = "SRSConf0";
4727 break;
4728 case 2:
4729 check_insn(env, ctx, ISA_MIPS32R2);
4730 gen_helper_mtc0_srsconf1(arg);
4731 rn = "SRSConf1";
4732 break;
4733 case 3:
4734 check_insn(env, ctx, ISA_MIPS32R2);
4735 gen_helper_mtc0_srsconf2(arg);
4736 rn = "SRSConf2";
4737 break;
4738 case 4:
4739 check_insn(env, ctx, ISA_MIPS32R2);
4740 gen_helper_mtc0_srsconf3(arg);
4741 rn = "SRSConf3";
4742 break;
4743 case 5:
4744 check_insn(env, ctx, ISA_MIPS32R2);
4745 gen_helper_mtc0_srsconf4(arg);
4746 rn = "SRSConf4";
4747 break;
4748 default:
4749 goto die;
4751 break;
4752 case 7:
4753 switch (sel) {
4754 case 0:
4755 check_insn(env, ctx, ISA_MIPS32R2);
4756 gen_helper_mtc0_hwrena(arg);
4757 rn = "HWREna";
4758 break;
4759 default:
4760 goto die;
4762 break;
4763 case 8:
4764 /* ignored */
4765 rn = "BadVAddr";
4766 break;
4767 case 9:
4768 switch (sel) {
4769 case 0:
4770 gen_helper_mtc0_count(arg);
4771 rn = "Count";
4772 break;
4773 /* 6,7 are implementation dependent */
4774 default:
4775 goto die;
4777 /* Stop translation as we may have switched the execution mode */
4778 ctx->bstate = BS_STOP;
4779 break;
4780 case 10:
4781 switch (sel) {
4782 case 0:
4783 gen_helper_mtc0_entryhi(arg);
4784 rn = "EntryHi";
4785 break;
4786 default:
4787 goto die;
4789 break;
4790 case 11:
4791 switch (sel) {
4792 case 0:
4793 gen_helper_mtc0_compare(arg);
4794 rn = "Compare";
4795 break;
4796 /* 6,7 are implementation dependent */
4797 default:
4798 goto die;
4800 /* Stop translation as we may have switched the execution mode */
4801 ctx->bstate = BS_STOP;
4802 break;
4803 case 12:
4804 switch (sel) {
4805 case 0:
4806 save_cpu_state(ctx, 1);
4807 gen_helper_mtc0_status(arg);
4808 /* BS_STOP isn't good enough here, hflags may have changed. */
4809 gen_save_pc(ctx->pc + 4);
4810 ctx->bstate = BS_EXCP;
4811 rn = "Status";
4812 break;
4813 case 1:
4814 check_insn(env, ctx, ISA_MIPS32R2);
4815 gen_helper_mtc0_intctl(arg);
4816 /* Stop translation as we may have switched the execution mode */
4817 ctx->bstate = BS_STOP;
4818 rn = "IntCtl";
4819 break;
4820 case 2:
4821 check_insn(env, ctx, ISA_MIPS32R2);
4822 gen_helper_mtc0_srsctl(arg);
4823 /* Stop translation as we may have switched the execution mode */
4824 ctx->bstate = BS_STOP;
4825 rn = "SRSCtl";
4826 break;
4827 case 3:
4828 check_insn(env, ctx, ISA_MIPS32R2);
4829 gen_mtc0_store32(arg, offsetof(CPUState, CP0_SRSMap));
4830 /* Stop translation as we may have switched the execution mode */
4831 ctx->bstate = BS_STOP;
4832 rn = "SRSMap";
4833 break;
4834 default:
4835 goto die;
4837 break;
4838 case 13:
4839 switch (sel) {
4840 case 0:
4841 save_cpu_state(ctx, 1);
4842 gen_helper_mtc0_cause(arg);
4843 rn = "Cause";
4844 break;
4845 default:
4846 goto die;
4848 break;
4849 case 14:
4850 switch (sel) {
4851 case 0:
4852 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUState, CP0_EPC));
4853 rn = "EPC";
4854 break;
4855 default:
4856 goto die;
4858 break;
4859 case 15:
4860 switch (sel) {
4861 case 0:
4862 /* ignored */
4863 rn = "PRid";
4864 break;
4865 case 1:
4866 check_insn(env, ctx, ISA_MIPS32R2);
4867 gen_helper_mtc0_ebase(arg);
4868 rn = "EBase";
4869 break;
4870 default:
4871 goto die;
4873 break;
4874 case 16:
4875 switch (sel) {
4876 case 0:
4877 gen_helper_mtc0_config0(arg);
4878 rn = "Config";
4879 /* Stop translation as we may have switched the execution mode */
4880 ctx->bstate = BS_STOP;
4881 break;
4882 case 1:
4883 /* ignored, read only */
4884 rn = "Config1";
4885 break;
4886 case 2:
4887 gen_helper_mtc0_config2(arg);
4888 rn = "Config2";
4889 /* Stop translation as we may have switched the execution mode */
4890 ctx->bstate = BS_STOP;
4891 break;
4892 case 3:
4893 /* ignored */
4894 rn = "Config3";
4895 break;
4896 /* 6,7 are implementation dependent */
4897 default:
4898 rn = "Invalid config selector";
4899 goto die;
4901 break;
4902 case 17:
4903 switch (sel) {
4904 case 0:
4905 gen_helper_mtc0_lladdr(arg);
4906 rn = "LLAddr";
4907 break;
4908 default:
4909 goto die;
4911 break;
4912 case 18:
4913 switch (sel) {
4914 case 0 ... 7:
4915 gen_helper_1i(mtc0_watchlo, arg, sel);
4916 rn = "WatchLo";
4917 break;
4918 default:
4919 goto die;
4921 break;
4922 case 19:
4923 switch (sel) {
4924 case 0 ... 7:
4925 gen_helper_1i(mtc0_watchhi, arg, sel);
4926 rn = "WatchHi";
4927 break;
4928 default:
4929 goto die;
4931 break;
4932 case 20:
4933 switch (sel) {
4934 case 0:
4935 check_insn(env, ctx, ISA_MIPS3);
4936 gen_helper_mtc0_xcontext(arg);
4937 rn = "XContext";
4938 break;
4939 default:
4940 goto die;
4942 break;
4943 case 21:
4944 /* Officially reserved, but sel 0 is used for R1x000 framemask */
4945 switch (sel) {
4946 case 0:
4947 gen_helper_mtc0_framemask(arg);
4948 rn = "Framemask";
4949 break;
4950 default:
4951 goto die;
4953 break;
4954 case 22:
4955 /* ignored */
4956 rn = "Diagnostic"; /* implementation dependent */
4957 break;
4958 case 23:
4959 switch (sel) {
4960 case 0:
4961 gen_helper_mtc0_debug(arg); /* EJTAG support */
4962 /* BS_STOP isn't good enough here, hflags may have changed. */
4963 gen_save_pc(ctx->pc + 4);
4964 ctx->bstate = BS_EXCP;
4965 rn = "Debug";
4966 break;
4967 case 1:
4968 // gen_helper_mtc0_tracecontrol(arg); /* PDtrace support */
4969 /* Stop translation as we may have switched the execution mode */
4970 ctx->bstate = BS_STOP;
4971 rn = "TraceControl";
4972 // break;
4973 case 2:
4974 // gen_helper_mtc0_tracecontrol2(arg); /* PDtrace support */
4975 /* Stop translation as we may have switched the execution mode */
4976 ctx->bstate = BS_STOP;
4977 rn = "TraceControl2";
4978 // break;
4979 case 3:
4980 // gen_helper_mtc0_usertracedata(arg); /* PDtrace support */
4981 /* Stop translation as we may have switched the execution mode */
4982 ctx->bstate = BS_STOP;
4983 rn = "UserTraceData";
4984 // break;
4985 case 4:
4986 // gen_helper_mtc0_tracebpc(arg); /* PDtrace support */
4987 /* Stop translation as we may have switched the execution mode */
4988 ctx->bstate = BS_STOP;
4989 rn = "TraceBPC";
4990 // break;
4991 default:
4992 goto die;
4994 break;
4995 case 24:
4996 switch (sel) {
4997 case 0:
4998 /* EJTAG support */
4999 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUState, CP0_DEPC));
5000 rn = "DEPC";
5001 break;
5002 default:
5003 goto die;
5005 break;
5006 case 25:
5007 switch (sel) {
5008 case 0:
5009 gen_helper_mtc0_performance0(arg);
5010 rn = "Performance0";
5011 break;
5012 case 1:
5013 // gen_helper_mtc0_performance1(arg);
5014 rn = "Performance1";
5015 // break;
5016 case 2:
5017 // gen_helper_mtc0_performance2(arg);
5018 rn = "Performance2";
5019 // break;
5020 case 3:
5021 // gen_helper_mtc0_performance3(arg);
5022 rn = "Performance3";
5023 // break;
5024 case 4:
5025 // gen_helper_mtc0_performance4(arg);
5026 rn = "Performance4";
5027 // break;
5028 case 5:
5029 // gen_helper_mtc0_performance5(arg);
5030 rn = "Performance5";
5031 // break;
5032 case 6:
5033 // gen_helper_mtc0_performance6(arg);
5034 rn = "Performance6";
5035 // break;
5036 case 7:
5037 // gen_helper_mtc0_performance7(arg);
5038 rn = "Performance7";
5039 // break;
5040 default:
5041 goto die;
5043 break;
5044 case 26:
5045 /* ignored */
5046 rn = "ECC";
5047 break;
5048 case 27:
5049 switch (sel) {
5050 case 0 ... 3:
5051 /* ignored */
5052 rn = "CacheErr";
5053 break;
5054 default:
5055 goto die;
5057 break;
5058 case 28:
5059 switch (sel) {
5060 case 0:
5061 case 2:
5062 case 4:
5063 case 6:
5064 gen_helper_mtc0_taglo(arg);
5065 rn = "TagLo";
5066 break;
5067 case 1:
5068 case 3:
5069 case 5:
5070 case 7:
5071 gen_helper_mtc0_datalo(arg);
5072 rn = "DataLo";
5073 break;
5074 default:
5075 goto die;
5077 break;
5078 case 29:
5079 switch (sel) {
5080 case 0:
5081 case 2:
5082 case 4:
5083 case 6:
5084 gen_helper_mtc0_taghi(arg);
5085 rn = "TagHi";
5086 break;
5087 case 1:
5088 case 3:
5089 case 5:
5090 case 7:
5091 gen_helper_mtc0_datahi(arg);
5092 rn = "DataHi";
5093 break;
5094 default:
5095 rn = "invalid sel";
5096 goto die;
5098 break;
5099 case 30:
5100 switch (sel) {
5101 case 0:
5102 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUState, CP0_ErrorEPC));
5103 rn = "ErrorEPC";
5104 break;
5105 default:
5106 goto die;
5108 break;
5109 case 31:
5110 switch (sel) {
5111 case 0:
5112 /* EJTAG support */
5113 gen_mtc0_store32(arg, offsetof(CPUState, CP0_DESAVE));
5114 rn = "DESAVE";
5115 break;
5116 default:
5117 goto die;
5119 /* Stop translation as we may have switched the execution mode */
5120 ctx->bstate = BS_STOP;
5121 break;
5122 default:
5123 goto die;
5125 LOG_DISAS("dmtc0 %s (reg %d sel %d)\n", rn, reg, sel);
5126 /* For simplicity assume that all writes can cause interrupts. */
5127 if (use_icount) {
5128 gen_io_end();
5129 ctx->bstate = BS_STOP;
5131 return;
5133 die:
5134 LOG_DISAS("dmtc0 %s (reg %d sel %d)\n", rn, reg, sel);
5135 generate_exception(ctx, EXCP_RI);
5137 #endif /* TARGET_MIPS64 */
5139 static void gen_mftr(CPUState *env, DisasContext *ctx, int rt, int rd,
5140 int u, int sel, int h)
5142 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
5143 TCGv t0 = tcg_temp_local_new();
5145 if ((env->CP0_VPEConf0 & (1 << CP0VPEC0_MVP)) == 0 &&
5146 ((env->tcs[other_tc].CP0_TCBind & (0xf << CP0TCBd_CurVPE)) !=
5147 (env->active_tc.CP0_TCBind & (0xf << CP0TCBd_CurVPE))))
5148 tcg_gen_movi_tl(t0, -1);
5149 else if ((env->CP0_VPEControl & (0xff << CP0VPECo_TargTC)) >
5150 (env->mvp->CP0_MVPConf0 & (0xff << CP0MVPC0_PTC)))
5151 tcg_gen_movi_tl(t0, -1);
5152 else if (u == 0) {
5153 switch (rt) {
5154 case 2:
5155 switch (sel) {
5156 case 1:
5157 gen_helper_mftc0_tcstatus(t0);
5158 break;
5159 case 2:
5160 gen_helper_mftc0_tcbind(t0);
5161 break;
5162 case 3:
5163 gen_helper_mftc0_tcrestart(t0);
5164 break;
5165 case 4:
5166 gen_helper_mftc0_tchalt(t0);
5167 break;
5168 case 5:
5169 gen_helper_mftc0_tccontext(t0);
5170 break;
5171 case 6:
5172 gen_helper_mftc0_tcschedule(t0);
5173 break;
5174 case 7:
5175 gen_helper_mftc0_tcschefback(t0);
5176 break;
5177 default:
5178 gen_mfc0(env, ctx, t0, rt, sel);
5179 break;
5181 break;
5182 case 10:
5183 switch (sel) {
5184 case 0:
5185 gen_helper_mftc0_entryhi(t0);
5186 break;
5187 default:
5188 gen_mfc0(env, ctx, t0, rt, sel);
5189 break;
5191 case 12:
5192 switch (sel) {
5193 case 0:
5194 gen_helper_mftc0_status(t0);
5195 break;
5196 default:
5197 gen_mfc0(env, ctx, t0, rt, sel);
5198 break;
5200 case 23:
5201 switch (sel) {
5202 case 0:
5203 gen_helper_mftc0_debug(t0);
5204 break;
5205 default:
5206 gen_mfc0(env, ctx, t0, rt, sel);
5207 break;
5209 break;
5210 default:
5211 gen_mfc0(env, ctx, t0, rt, sel);
5213 } else switch (sel) {
5214 /* GPR registers. */
5215 case 0:
5216 gen_helper_1i(mftgpr, t0, rt);
5217 break;
5218 /* Auxiliary CPU registers */
5219 case 1:
5220 switch (rt) {
5221 case 0:
5222 gen_helper_1i(mftlo, t0, 0);
5223 break;
5224 case 1:
5225 gen_helper_1i(mfthi, t0, 0);
5226 break;
5227 case 2:
5228 gen_helper_1i(mftacx, t0, 0);
5229 break;
5230 case 4:
5231 gen_helper_1i(mftlo, t0, 1);
5232 break;
5233 case 5:
5234 gen_helper_1i(mfthi, t0, 1);
5235 break;
5236 case 6:
5237 gen_helper_1i(mftacx, t0, 1);
5238 break;
5239 case 8:
5240 gen_helper_1i(mftlo, t0, 2);
5241 break;
5242 case 9:
5243 gen_helper_1i(mfthi, t0, 2);
5244 break;
5245 case 10:
5246 gen_helper_1i(mftacx, t0, 2);
5247 break;
5248 case 12:
5249 gen_helper_1i(mftlo, t0, 3);
5250 break;
5251 case 13:
5252 gen_helper_1i(mfthi, t0, 3);
5253 break;
5254 case 14:
5255 gen_helper_1i(mftacx, t0, 3);
5256 break;
5257 case 16:
5258 gen_helper_mftdsp(t0);
5259 break;
5260 default:
5261 goto die;
5263 break;
5264 /* Floating point (COP1). */
5265 case 2:
5266 /* XXX: For now we support only a single FPU context. */
5267 if (h == 0) {
5268 TCGv_i32 fp0 = tcg_temp_new_i32();
5270 gen_load_fpr32(fp0, rt);
5271 tcg_gen_ext_i32_tl(t0, fp0);
5272 tcg_temp_free_i32(fp0);
5273 } else {
5274 TCGv_i32 fp0 = tcg_temp_new_i32();
5276 gen_load_fpr32h(fp0, rt);
5277 tcg_gen_ext_i32_tl(t0, fp0);
5278 tcg_temp_free_i32(fp0);
5280 break;
5281 case 3:
5282 /* XXX: For now we support only a single FPU context. */
5283 gen_helper_1i(cfc1, t0, rt);
5284 break;
5285 /* COP2: Not implemented. */
5286 case 4:
5287 case 5:
5288 /* fall through */
5289 default:
5290 goto die;
5292 LOG_DISAS("mftr (reg %d u %d sel %d h %d)\n", rt, u, sel, h);
5293 gen_store_gpr(t0, rd);
5294 tcg_temp_free(t0);
5295 return;
5297 die:
5298 tcg_temp_free(t0);
5299 LOG_DISAS("mftr (reg %d u %d sel %d h %d)\n", rt, u, sel, h);
5300 generate_exception(ctx, EXCP_RI);
5303 static void gen_mttr(CPUState *env, DisasContext *ctx, int rd, int rt,
5304 int u, int sel, int h)
5306 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
5307 TCGv t0 = tcg_temp_local_new();
5309 gen_load_gpr(t0, rt);
5310 if ((env->CP0_VPEConf0 & (1 << CP0VPEC0_MVP)) == 0 &&
5311 ((env->tcs[other_tc].CP0_TCBind & (0xf << CP0TCBd_CurVPE)) !=
5312 (env->active_tc.CP0_TCBind & (0xf << CP0TCBd_CurVPE))))
5313 /* NOP */ ;
5314 else if ((env->CP0_VPEControl & (0xff << CP0VPECo_TargTC)) >
5315 (env->mvp->CP0_MVPConf0 & (0xff << CP0MVPC0_PTC)))
5316 /* NOP */ ;
5317 else if (u == 0) {
5318 switch (rd) {
5319 case 2:
5320 switch (sel) {
5321 case 1:
5322 gen_helper_mttc0_tcstatus(t0);
5323 break;
5324 case 2:
5325 gen_helper_mttc0_tcbind(t0);
5326 break;
5327 case 3:
5328 gen_helper_mttc0_tcrestart(t0);
5329 break;
5330 case 4:
5331 gen_helper_mttc0_tchalt(t0);
5332 break;
5333 case 5:
5334 gen_helper_mttc0_tccontext(t0);
5335 break;
5336 case 6:
5337 gen_helper_mttc0_tcschedule(t0);
5338 break;
5339 case 7:
5340 gen_helper_mttc0_tcschefback(t0);
5341 break;
5342 default:
5343 gen_mtc0(env, ctx, t0, rd, sel);
5344 break;
5346 break;
5347 case 10:
5348 switch (sel) {
5349 case 0:
5350 gen_helper_mttc0_entryhi(t0);
5351 break;
5352 default:
5353 gen_mtc0(env, ctx, t0, rd, sel);
5354 break;
5356 case 12:
5357 switch (sel) {
5358 case 0:
5359 gen_helper_mttc0_status(t0);
5360 break;
5361 default:
5362 gen_mtc0(env, ctx, t0, rd, sel);
5363 break;
5365 case 23:
5366 switch (sel) {
5367 case 0:
5368 gen_helper_mttc0_debug(t0);
5369 break;
5370 default:
5371 gen_mtc0(env, ctx, t0, rd, sel);
5372 break;
5374 break;
5375 default:
5376 gen_mtc0(env, ctx, t0, rd, sel);
5378 } else switch (sel) {
5379 /* GPR registers. */
5380 case 0:
5381 gen_helper_1i(mttgpr, t0, rd);
5382 break;
5383 /* Auxiliary CPU registers */
5384 case 1:
5385 switch (rd) {
5386 case 0:
5387 gen_helper_1i(mttlo, t0, 0);
5388 break;
5389 case 1:
5390 gen_helper_1i(mtthi, t0, 0);
5391 break;
5392 case 2:
5393 gen_helper_1i(mttacx, t0, 0);
5394 break;
5395 case 4:
5396 gen_helper_1i(mttlo, t0, 1);
5397 break;
5398 case 5:
5399 gen_helper_1i(mtthi, t0, 1);
5400 break;
5401 case 6:
5402 gen_helper_1i(mttacx, t0, 1);
5403 break;
5404 case 8:
5405 gen_helper_1i(mttlo, t0, 2);
5406 break;
5407 case 9:
5408 gen_helper_1i(mtthi, t0, 2);
5409 break;
5410 case 10:
5411 gen_helper_1i(mttacx, t0, 2);
5412 break;
5413 case 12:
5414 gen_helper_1i(mttlo, t0, 3);
5415 break;
5416 case 13:
5417 gen_helper_1i(mtthi, t0, 3);
5418 break;
5419 case 14:
5420 gen_helper_1i(mttacx, t0, 3);
5421 break;
5422 case 16:
5423 gen_helper_mttdsp(t0);
5424 break;
5425 default:
5426 goto die;
5428 break;
5429 /* Floating point (COP1). */
5430 case 2:
5431 /* XXX: For now we support only a single FPU context. */
5432 if (h == 0) {
5433 TCGv_i32 fp0 = tcg_temp_new_i32();
5435 tcg_gen_trunc_tl_i32(fp0, t0);
5436 gen_store_fpr32(fp0, rd);
5437 tcg_temp_free_i32(fp0);
5438 } else {
5439 TCGv_i32 fp0 = tcg_temp_new_i32();
5441 tcg_gen_trunc_tl_i32(fp0, t0);
5442 gen_store_fpr32h(fp0, rd);
5443 tcg_temp_free_i32(fp0);
5445 break;
5446 case 3:
5447 /* XXX: For now we support only a single FPU context. */
5448 gen_helper_1i(ctc1, t0, rd);
5449 break;
5450 /* COP2: Not implemented. */
5451 case 4:
5452 case 5:
5453 /* fall through */
5454 default:
5455 goto die;
5457 LOG_DISAS("mttr (reg %d u %d sel %d h %d)\n", rd, u, sel, h);
5458 tcg_temp_free(t0);
5459 return;
5461 die:
5462 tcg_temp_free(t0);
5463 LOG_DISAS("mttr (reg %d u %d sel %d h %d)\n", rd, u, sel, h);
5464 generate_exception(ctx, EXCP_RI);
5467 static void gen_cp0 (CPUState *env, DisasContext *ctx, uint32_t opc, int rt, int rd)
5469 const char *opn = "ldst";
5471 switch (opc) {
5472 case OPC_MFC0:
5473 if (rt == 0) {
5474 /* Treat as NOP. */
5475 return;
5477 gen_mfc0(env, ctx, cpu_gpr[rt], rd, ctx->opcode & 0x7);
5478 opn = "mfc0";
5479 break;
5480 case OPC_MTC0:
5482 TCGv t0 = tcg_temp_new();
5484 gen_load_gpr(t0, rt);
5485 gen_mtc0(env, ctx, t0, rd, ctx->opcode & 0x7);
5486 tcg_temp_free(t0);
5488 opn = "mtc0";
5489 break;
5490 #if defined(TARGET_MIPS64)
5491 case OPC_DMFC0:
5492 check_insn(env, ctx, ISA_MIPS3);
5493 if (rt == 0) {
5494 /* Treat as NOP. */
5495 return;
5497 gen_dmfc0(env, ctx, cpu_gpr[rt], rd, ctx->opcode & 0x7);
5498 opn = "dmfc0";
5499 break;
5500 case OPC_DMTC0:
5501 check_insn(env, ctx, ISA_MIPS3);
5503 TCGv t0 = tcg_temp_new();
5505 gen_load_gpr(t0, rt);
5506 gen_dmtc0(env, ctx, t0, rd, ctx->opcode & 0x7);
5507 tcg_temp_free(t0);
5509 opn = "dmtc0";
5510 break;
5511 #endif
5512 case OPC_MFTR:
5513 check_insn(env, ctx, ASE_MT);
5514 if (rd == 0) {
5515 /* Treat as NOP. */
5516 return;
5518 gen_mftr(env, ctx, rt, rd, (ctx->opcode >> 5) & 1,
5519 ctx->opcode & 0x7, (ctx->opcode >> 4) & 1);
5520 opn = "mftr";
5521 break;
5522 case OPC_MTTR:
5523 check_insn(env, ctx, ASE_MT);
5524 gen_mttr(env, ctx, rd, rt, (ctx->opcode >> 5) & 1,
5525 ctx->opcode & 0x7, (ctx->opcode >> 4) & 1);
5526 opn = "mttr";
5527 break;
5528 case OPC_TLBWI:
5529 opn = "tlbwi";
5530 if (!env->tlb->helper_tlbwi)
5531 goto die;
5532 gen_helper_tlbwi();
5533 break;
5534 case OPC_TLBWR:
5535 opn = "tlbwr";
5536 if (!env->tlb->helper_tlbwr)
5537 goto die;
5538 gen_helper_tlbwr();
5539 break;
5540 case OPC_TLBP:
5541 opn = "tlbp";
5542 if (!env->tlb->helper_tlbp)
5543 goto die;
5544 gen_helper_tlbp();
5545 break;
5546 case OPC_TLBR:
5547 opn = "tlbr";
5548 if (!env->tlb->helper_tlbr)
5549 goto die;
5550 gen_helper_tlbr();
5551 break;
5552 case OPC_ERET:
5553 opn = "eret";
5554 check_insn(env, ctx, ISA_MIPS2);
5555 gen_helper_eret();
5556 ctx->bstate = BS_EXCP;
5557 break;
5558 case OPC_DERET:
5559 opn = "deret";
5560 check_insn(env, ctx, ISA_MIPS32);
5561 if (!(ctx->hflags & MIPS_HFLAG_DM)) {
5562 MIPS_INVAL(opn);
5563 generate_exception(ctx, EXCP_RI);
5564 } else {
5565 gen_helper_deret();
5566 ctx->bstate = BS_EXCP;
5568 break;
5569 case OPC_WAIT:
5570 opn = "wait";
5571 check_insn(env, ctx, ISA_MIPS3 | ISA_MIPS32);
5572 /* If we get an exception, we want to restart at next instruction */
5573 ctx->pc += 4;
5574 save_cpu_state(ctx, 1);
5575 ctx->pc -= 4;
5576 gen_helper_wait();
5577 ctx->bstate = BS_EXCP;
5578 break;
5579 default:
5580 die:
5581 MIPS_INVAL(opn);
5582 generate_exception(ctx, EXCP_RI);
5583 return;
5585 MIPS_DEBUG("%s %s %d", opn, regnames[rt], rd);
5587 #endif /* !CONFIG_USER_ONLY */
5589 /* CP1 Branches (before delay slot) */
5590 static void gen_compute_branch1 (CPUState *env, DisasContext *ctx, uint32_t op,
5591 int32_t cc, int32_t offset)
5593 target_ulong btarget;
5594 const char *opn = "cp1 cond branch";
5595 TCGv_i32 t0 = tcg_temp_new_i32();
5597 if (cc != 0)
5598 check_insn(env, ctx, ISA_MIPS4 | ISA_MIPS32);
5600 btarget = ctx->pc + 4 + offset;
5602 switch (op) {
5603 case OPC_BC1F:
5604 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
5605 tcg_gen_not_i32(t0, t0);
5606 tcg_gen_andi_i32(t0, t0, 1);
5607 tcg_gen_extu_i32_tl(bcond, t0);
5608 opn = "bc1f";
5609 goto not_likely;
5610 case OPC_BC1FL:
5611 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
5612 tcg_gen_not_i32(t0, t0);
5613 tcg_gen_andi_i32(t0, t0, 1);
5614 tcg_gen_extu_i32_tl(bcond, t0);
5615 opn = "bc1fl";
5616 goto likely;
5617 case OPC_BC1T:
5618 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
5619 tcg_gen_andi_i32(t0, t0, 1);
5620 tcg_gen_extu_i32_tl(bcond, t0);
5621 opn = "bc1t";
5622 goto not_likely;
5623 case OPC_BC1TL:
5624 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
5625 tcg_gen_andi_i32(t0, t0, 1);
5626 tcg_gen_extu_i32_tl(bcond, t0);
5627 opn = "bc1tl";
5628 likely:
5629 ctx->hflags |= MIPS_HFLAG_BL;
5630 break;
5631 case OPC_BC1FANY2:
5633 TCGv_i32 t1 = tcg_temp_new_i32();
5634 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
5635 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+1));
5636 tcg_gen_nor_i32(t0, t0, t1);
5637 tcg_temp_free_i32(t1);
5638 tcg_gen_andi_i32(t0, t0, 1);
5639 tcg_gen_extu_i32_tl(bcond, t0);
5641 opn = "bc1any2f";
5642 goto not_likely;
5643 case OPC_BC1TANY2:
5645 TCGv_i32 t1 = tcg_temp_new_i32();
5646 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
5647 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+1));
5648 tcg_gen_or_i32(t0, t0, t1);
5649 tcg_temp_free_i32(t1);
5650 tcg_gen_andi_i32(t0, t0, 1);
5651 tcg_gen_extu_i32_tl(bcond, t0);
5653 opn = "bc1any2t";
5654 goto not_likely;
5655 case OPC_BC1FANY4:
5657 TCGv_i32 t1 = tcg_temp_new_i32();
5658 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
5659 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+1));
5660 tcg_gen_or_i32(t0, t0, t1);
5661 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+2));
5662 tcg_gen_or_i32(t0, t0, t1);
5663 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+3));
5664 tcg_gen_nor_i32(t0, t0, t1);
5665 tcg_temp_free_i32(t1);
5666 tcg_gen_andi_i32(t0, t0, 1);
5667 tcg_gen_extu_i32_tl(bcond, t0);
5669 opn = "bc1any4f";
5670 goto not_likely;
5671 case OPC_BC1TANY4:
5673 TCGv_i32 t1 = tcg_temp_new_i32();
5674 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
5675 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+1));
5676 tcg_gen_or_i32(t0, t0, t1);
5677 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+2));
5678 tcg_gen_or_i32(t0, t0, t1);
5679 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+3));
5680 tcg_gen_or_i32(t0, t0, t1);
5681 tcg_temp_free_i32(t1);
5682 tcg_gen_andi_i32(t0, t0, 1);
5683 tcg_gen_extu_i32_tl(bcond, t0);
5685 opn = "bc1any4t";
5686 not_likely:
5687 ctx->hflags |= MIPS_HFLAG_BC;
5688 break;
5689 default:
5690 MIPS_INVAL(opn);
5691 generate_exception (ctx, EXCP_RI);
5692 goto out;
5694 MIPS_DEBUG("%s: cond %02x target " TARGET_FMT_lx, opn,
5695 ctx->hflags, btarget);
5696 ctx->btarget = btarget;
5698 out:
5699 tcg_temp_free_i32(t0);
5702 /* Coprocessor 1 (FPU) */
5704 #define FOP(func, fmt) (((fmt) << 21) | (func))
5706 static void gen_cp1 (DisasContext *ctx, uint32_t opc, int rt, int fs)
5708 const char *opn = "cp1 move";
5709 TCGv t0 = tcg_temp_new();
5711 switch (opc) {
5712 case OPC_MFC1:
5714 TCGv_i32 fp0 = tcg_temp_new_i32();
5716 gen_load_fpr32(fp0, fs);
5717 tcg_gen_ext_i32_tl(t0, fp0);
5718 tcg_temp_free_i32(fp0);
5720 gen_store_gpr(t0, rt);
5721 opn = "mfc1";
5722 break;
5723 case OPC_MTC1:
5724 gen_load_gpr(t0, rt);
5726 TCGv_i32 fp0 = tcg_temp_new_i32();
5728 tcg_gen_trunc_tl_i32(fp0, t0);
5729 gen_store_fpr32(fp0, fs);
5730 tcg_temp_free_i32(fp0);
5732 opn = "mtc1";
5733 break;
5734 case OPC_CFC1:
5735 gen_helper_1i(cfc1, t0, fs);
5736 gen_store_gpr(t0, rt);
5737 opn = "cfc1";
5738 break;
5739 case OPC_CTC1:
5740 gen_load_gpr(t0, rt);
5741 gen_helper_1i(ctc1, t0, fs);
5742 opn = "ctc1";
5743 break;
5744 #if defined(TARGET_MIPS64)
5745 case OPC_DMFC1:
5746 gen_load_fpr64(ctx, t0, fs);
5747 gen_store_gpr(t0, rt);
5748 opn = "dmfc1";
5749 break;
5750 case OPC_DMTC1:
5751 gen_load_gpr(t0, rt);
5752 gen_store_fpr64(ctx, t0, fs);
5753 opn = "dmtc1";
5754 break;
5755 #endif
5756 case OPC_MFHC1:
5758 TCGv_i32 fp0 = tcg_temp_new_i32();
5760 gen_load_fpr32h(fp0, fs);
5761 tcg_gen_ext_i32_tl(t0, fp0);
5762 tcg_temp_free_i32(fp0);
5764 gen_store_gpr(t0, rt);
5765 opn = "mfhc1";
5766 break;
5767 case OPC_MTHC1:
5768 gen_load_gpr(t0, rt);
5770 TCGv_i32 fp0 = tcg_temp_new_i32();
5772 tcg_gen_trunc_tl_i32(fp0, t0);
5773 gen_store_fpr32h(fp0, fs);
5774 tcg_temp_free_i32(fp0);
5776 opn = "mthc1";
5777 break;
5778 default:
5779 MIPS_INVAL(opn);
5780 generate_exception (ctx, EXCP_RI);
5781 goto out;
5783 MIPS_DEBUG("%s %s %s", opn, regnames[rt], fregnames[fs]);
5785 out:
5786 tcg_temp_free(t0);
5789 static void gen_movci (DisasContext *ctx, int rd, int rs, int cc, int tf)
5791 int l1;
5792 TCGCond cond;
5793 TCGv_i32 t0;
5795 if (rd == 0) {
5796 /* Treat as NOP. */
5797 return;
5800 if (tf)
5801 cond = TCG_COND_EQ;
5802 else
5803 cond = TCG_COND_NE;
5805 l1 = gen_new_label();
5806 t0 = tcg_temp_new_i32();
5807 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
5808 tcg_gen_brcondi_i32(cond, t0, 0, l1);
5809 tcg_temp_free_i32(t0);
5810 if (rs == 0) {
5811 tcg_gen_movi_tl(cpu_gpr[rd], 0);
5812 } else {
5813 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
5815 gen_set_label(l1);
5818 static inline void gen_movcf_s (int fs, int fd, int cc, int tf)
5820 int cond;
5821 TCGv_i32 t0 = tcg_temp_new_i32();
5822 int l1 = gen_new_label();
5824 if (tf)
5825 cond = TCG_COND_EQ;
5826 else
5827 cond = TCG_COND_NE;
5829 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
5830 tcg_gen_brcondi_i32(cond, t0, 0, l1);
5831 gen_load_fpr32(t0, fs);
5832 gen_store_fpr32(t0, fd);
5833 gen_set_label(l1);
5834 tcg_temp_free_i32(t0);
5837 static inline void gen_movcf_d (DisasContext *ctx, int fs, int fd, int cc, int tf)
5839 int cond;
5840 TCGv_i32 t0 = tcg_temp_new_i32();
5841 TCGv_i64 fp0;
5842 int l1 = gen_new_label();
5844 if (tf)
5845 cond = TCG_COND_EQ;
5846 else
5847 cond = TCG_COND_NE;
5849 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
5850 tcg_gen_brcondi_i32(cond, t0, 0, l1);
5851 tcg_temp_free_i32(t0);
5852 fp0 = tcg_temp_new_i64();
5853 gen_load_fpr64(ctx, fp0, fs);
5854 gen_store_fpr64(ctx, fp0, fd);
5855 tcg_temp_free_i64(fp0);
5856 gen_set_label(l1);
5859 static inline void gen_movcf_ps (int fs, int fd, int cc, int tf)
5861 int cond;
5862 TCGv_i32 t0 = tcg_temp_new_i32();
5863 int l1 = gen_new_label();
5864 int l2 = gen_new_label();
5866 if (tf)
5867 cond = TCG_COND_EQ;
5868 else
5869 cond = TCG_COND_NE;
5871 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
5872 tcg_gen_brcondi_i32(cond, t0, 0, l1);
5873 gen_load_fpr32(t0, fs);
5874 gen_store_fpr32(t0, fd);
5875 gen_set_label(l1);
5877 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc+1));
5878 tcg_gen_brcondi_i32(cond, t0, 0, l2);
5879 gen_load_fpr32h(t0, fs);
5880 gen_store_fpr32h(t0, fd);
5881 tcg_temp_free_i32(t0);
5882 gen_set_label(l2);
5886 static void gen_farith (DisasContext *ctx, uint32_t op1,
5887 int ft, int fs, int fd, int cc)
5889 const char *opn = "farith";
5890 const char *condnames[] = {
5891 "c.f",
5892 "c.un",
5893 "c.eq",
5894 "c.ueq",
5895 "c.olt",
5896 "c.ult",
5897 "c.ole",
5898 "c.ule",
5899 "c.sf",
5900 "c.ngle",
5901 "c.seq",
5902 "c.ngl",
5903 "c.lt",
5904 "c.nge",
5905 "c.le",
5906 "c.ngt",
5908 const char *condnames_abs[] = {
5909 "cabs.f",
5910 "cabs.un",
5911 "cabs.eq",
5912 "cabs.ueq",
5913 "cabs.olt",
5914 "cabs.ult",
5915 "cabs.ole",
5916 "cabs.ule",
5917 "cabs.sf",
5918 "cabs.ngle",
5919 "cabs.seq",
5920 "cabs.ngl",
5921 "cabs.lt",
5922 "cabs.nge",
5923 "cabs.le",
5924 "cabs.ngt",
5926 enum { BINOP, CMPOP, OTHEROP } optype = OTHEROP;
5927 uint32_t func = ctx->opcode & 0x3f;
5929 switch (ctx->opcode & FOP(0x3f, 0x1f)) {
5930 case FOP(0, 16):
5932 TCGv_i32 fp0 = tcg_temp_new_i32();
5933 TCGv_i32 fp1 = tcg_temp_new_i32();
5935 gen_load_fpr32(fp0, fs);
5936 gen_load_fpr32(fp1, ft);
5937 gen_helper_float_add_s(fp0, fp0, fp1);
5938 tcg_temp_free_i32(fp1);
5939 gen_store_fpr32(fp0, fd);
5940 tcg_temp_free_i32(fp0);
5942 opn = "add.s";
5943 optype = BINOP;
5944 break;
5945 case FOP(1, 16):
5947 TCGv_i32 fp0 = tcg_temp_new_i32();
5948 TCGv_i32 fp1 = tcg_temp_new_i32();
5950 gen_load_fpr32(fp0, fs);
5951 gen_load_fpr32(fp1, ft);
5952 gen_helper_float_sub_s(fp0, fp0, fp1);
5953 tcg_temp_free_i32(fp1);
5954 gen_store_fpr32(fp0, fd);
5955 tcg_temp_free_i32(fp0);
5957 opn = "sub.s";
5958 optype = BINOP;
5959 break;
5960 case FOP(2, 16):
5962 TCGv_i32 fp0 = tcg_temp_new_i32();
5963 TCGv_i32 fp1 = tcg_temp_new_i32();
5965 gen_load_fpr32(fp0, fs);
5966 gen_load_fpr32(fp1, ft);
5967 gen_helper_float_mul_s(fp0, fp0, fp1);
5968 tcg_temp_free_i32(fp1);
5969 gen_store_fpr32(fp0, fd);
5970 tcg_temp_free_i32(fp0);
5972 opn = "mul.s";
5973 optype = BINOP;
5974 break;
5975 case FOP(3, 16):
5977 TCGv_i32 fp0 = tcg_temp_new_i32();
5978 TCGv_i32 fp1 = tcg_temp_new_i32();
5980 gen_load_fpr32(fp0, fs);
5981 gen_load_fpr32(fp1, ft);
5982 gen_helper_float_div_s(fp0, fp0, fp1);
5983 tcg_temp_free_i32(fp1);
5984 gen_store_fpr32(fp0, fd);
5985 tcg_temp_free_i32(fp0);
5987 opn = "div.s";
5988 optype = BINOP;
5989 break;
5990 case FOP(4, 16):
5992 TCGv_i32 fp0 = tcg_temp_new_i32();
5994 gen_load_fpr32(fp0, fs);
5995 gen_helper_float_sqrt_s(fp0, fp0);
5996 gen_store_fpr32(fp0, fd);
5997 tcg_temp_free_i32(fp0);
5999 opn = "sqrt.s";
6000 break;
6001 case FOP(5, 16):
6003 TCGv_i32 fp0 = tcg_temp_new_i32();
6005 gen_load_fpr32(fp0, fs);
6006 gen_helper_float_abs_s(fp0, fp0);
6007 gen_store_fpr32(fp0, fd);
6008 tcg_temp_free_i32(fp0);
6010 opn = "abs.s";
6011 break;
6012 case FOP(6, 16):
6014 TCGv_i32 fp0 = tcg_temp_new_i32();
6016 gen_load_fpr32(fp0, fs);
6017 gen_store_fpr32(fp0, fd);
6018 tcg_temp_free_i32(fp0);
6020 opn = "mov.s";
6021 break;
6022 case FOP(7, 16):
6024 TCGv_i32 fp0 = tcg_temp_new_i32();
6026 gen_load_fpr32(fp0, fs);
6027 gen_helper_float_chs_s(fp0, fp0);
6028 gen_store_fpr32(fp0, fd);
6029 tcg_temp_free_i32(fp0);
6031 opn = "neg.s";
6032 break;
6033 case FOP(8, 16):
6034 check_cp1_64bitmode(ctx);
6036 TCGv_i32 fp32 = tcg_temp_new_i32();
6037 TCGv_i64 fp64 = tcg_temp_new_i64();
6039 gen_load_fpr32(fp32, fs);
6040 gen_helper_float_roundl_s(fp64, fp32);
6041 tcg_temp_free_i32(fp32);
6042 gen_store_fpr64(ctx, fp64, fd);
6043 tcg_temp_free_i64(fp64);
6045 opn = "round.l.s";
6046 break;
6047 case FOP(9, 16):
6048 check_cp1_64bitmode(ctx);
6050 TCGv_i32 fp32 = tcg_temp_new_i32();
6051 TCGv_i64 fp64 = tcg_temp_new_i64();
6053 gen_load_fpr32(fp32, fs);
6054 gen_helper_float_truncl_s(fp64, fp32);
6055 tcg_temp_free_i32(fp32);
6056 gen_store_fpr64(ctx, fp64, fd);
6057 tcg_temp_free_i64(fp64);
6059 opn = "trunc.l.s";
6060 break;
6061 case FOP(10, 16):
6062 check_cp1_64bitmode(ctx);
6064 TCGv_i32 fp32 = tcg_temp_new_i32();
6065 TCGv_i64 fp64 = tcg_temp_new_i64();
6067 gen_load_fpr32(fp32, fs);
6068 gen_helper_float_ceill_s(fp64, fp32);
6069 tcg_temp_free_i32(fp32);
6070 gen_store_fpr64(ctx, fp64, fd);
6071 tcg_temp_free_i64(fp64);
6073 opn = "ceil.l.s";
6074 break;
6075 case FOP(11, 16):
6076 check_cp1_64bitmode(ctx);
6078 TCGv_i32 fp32 = tcg_temp_new_i32();
6079 TCGv_i64 fp64 = tcg_temp_new_i64();
6081 gen_load_fpr32(fp32, fs);
6082 gen_helper_float_floorl_s(fp64, fp32);
6083 tcg_temp_free_i32(fp32);
6084 gen_store_fpr64(ctx, fp64, fd);
6085 tcg_temp_free_i64(fp64);
6087 opn = "floor.l.s";
6088 break;
6089 case FOP(12, 16):
6091 TCGv_i32 fp0 = tcg_temp_new_i32();
6093 gen_load_fpr32(fp0, fs);
6094 gen_helper_float_roundw_s(fp0, fp0);
6095 gen_store_fpr32(fp0, fd);
6096 tcg_temp_free_i32(fp0);
6098 opn = "round.w.s";
6099 break;
6100 case FOP(13, 16):
6102 TCGv_i32 fp0 = tcg_temp_new_i32();
6104 gen_load_fpr32(fp0, fs);
6105 gen_helper_float_truncw_s(fp0, fp0);
6106 gen_store_fpr32(fp0, fd);
6107 tcg_temp_free_i32(fp0);
6109 opn = "trunc.w.s";
6110 break;
6111 case FOP(14, 16):
6113 TCGv_i32 fp0 = tcg_temp_new_i32();
6115 gen_load_fpr32(fp0, fs);
6116 gen_helper_float_ceilw_s(fp0, fp0);
6117 gen_store_fpr32(fp0, fd);
6118 tcg_temp_free_i32(fp0);
6120 opn = "ceil.w.s";
6121 break;
6122 case FOP(15, 16):
6124 TCGv_i32 fp0 = tcg_temp_new_i32();
6126 gen_load_fpr32(fp0, fs);
6127 gen_helper_float_floorw_s(fp0, fp0);
6128 gen_store_fpr32(fp0, fd);
6129 tcg_temp_free_i32(fp0);
6131 opn = "floor.w.s";
6132 break;
6133 case FOP(17, 16):
6134 gen_movcf_s(fs, fd, (ft >> 2) & 0x7, ft & 0x1);
6135 opn = "movcf.s";
6136 break;
6137 case FOP(18, 16):
6139 int l1 = gen_new_label();
6140 TCGv_i32 fp0;
6142 if (ft != 0) {
6143 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[ft], 0, l1);
6145 fp0 = tcg_temp_new_i32();
6146 gen_load_fpr32(fp0, fs);
6147 gen_store_fpr32(fp0, fd);
6148 tcg_temp_free_i32(fp0);
6149 gen_set_label(l1);
6151 opn = "movz.s";
6152 break;
6153 case FOP(19, 16):
6155 int l1 = gen_new_label();
6156 TCGv_i32 fp0;
6158 if (ft != 0) {
6159 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[ft], 0, l1);
6160 fp0 = tcg_temp_new_i32();
6161 gen_load_fpr32(fp0, fs);
6162 gen_store_fpr32(fp0, fd);
6163 tcg_temp_free_i32(fp0);
6164 gen_set_label(l1);
6167 opn = "movn.s";
6168 break;
6169 case FOP(21, 16):
6170 check_cop1x(ctx);
6172 TCGv_i32 fp0 = tcg_temp_new_i32();
6174 gen_load_fpr32(fp0, fs);
6175 gen_helper_float_recip_s(fp0, fp0);
6176 gen_store_fpr32(fp0, fd);
6177 tcg_temp_free_i32(fp0);
6179 opn = "recip.s";
6180 break;
6181 case FOP(22, 16):
6182 check_cop1x(ctx);
6184 TCGv_i32 fp0 = tcg_temp_new_i32();
6186 gen_load_fpr32(fp0, fs);
6187 gen_helper_float_rsqrt_s(fp0, fp0);
6188 gen_store_fpr32(fp0, fd);
6189 tcg_temp_free_i32(fp0);
6191 opn = "rsqrt.s";
6192 break;
6193 case FOP(28, 16):
6194 check_cp1_64bitmode(ctx);
6196 TCGv_i32 fp0 = tcg_temp_new_i32();
6197 TCGv_i32 fp1 = tcg_temp_new_i32();
6199 gen_load_fpr32(fp0, fs);
6200 gen_load_fpr32(fp1, fd);
6201 gen_helper_float_recip2_s(fp0, fp0, fp1);
6202 tcg_temp_free_i32(fp1);
6203 gen_store_fpr32(fp0, fd);
6204 tcg_temp_free_i32(fp0);
6206 opn = "recip2.s";
6207 break;
6208 case FOP(29, 16):
6209 check_cp1_64bitmode(ctx);
6211 TCGv_i32 fp0 = tcg_temp_new_i32();
6213 gen_load_fpr32(fp0, fs);
6214 gen_helper_float_recip1_s(fp0, fp0);
6215 gen_store_fpr32(fp0, fd);
6216 tcg_temp_free_i32(fp0);
6218 opn = "recip1.s";
6219 break;
6220 case FOP(30, 16):
6221 check_cp1_64bitmode(ctx);
6223 TCGv_i32 fp0 = tcg_temp_new_i32();
6225 gen_load_fpr32(fp0, fs);
6226 gen_helper_float_rsqrt1_s(fp0, fp0);
6227 gen_store_fpr32(fp0, fd);
6228 tcg_temp_free_i32(fp0);
6230 opn = "rsqrt1.s";
6231 break;
6232 case FOP(31, 16):
6233 check_cp1_64bitmode(ctx);
6235 TCGv_i32 fp0 = tcg_temp_new_i32();
6236 TCGv_i32 fp1 = tcg_temp_new_i32();
6238 gen_load_fpr32(fp0, fs);
6239 gen_load_fpr32(fp1, ft);
6240 gen_helper_float_rsqrt2_s(fp0, fp0, fp1);
6241 tcg_temp_free_i32(fp1);
6242 gen_store_fpr32(fp0, fd);
6243 tcg_temp_free_i32(fp0);
6245 opn = "rsqrt2.s";
6246 break;
6247 case FOP(33, 16):
6248 check_cp1_registers(ctx, fd);
6250 TCGv_i32 fp32 = tcg_temp_new_i32();
6251 TCGv_i64 fp64 = tcg_temp_new_i64();
6253 gen_load_fpr32(fp32, fs);
6254 gen_helper_float_cvtd_s(fp64, fp32);
6255 tcg_temp_free_i32(fp32);
6256 gen_store_fpr64(ctx, fp64, fd);
6257 tcg_temp_free_i64(fp64);
6259 opn = "cvt.d.s";
6260 break;
6261 case FOP(36, 16):
6263 TCGv_i32 fp0 = tcg_temp_new_i32();
6265 gen_load_fpr32(fp0, fs);
6266 gen_helper_float_cvtw_s(fp0, fp0);
6267 gen_store_fpr32(fp0, fd);
6268 tcg_temp_free_i32(fp0);
6270 opn = "cvt.w.s";
6271 break;
6272 case FOP(37, 16):
6273 check_cp1_64bitmode(ctx);
6275 TCGv_i32 fp32 = tcg_temp_new_i32();
6276 TCGv_i64 fp64 = tcg_temp_new_i64();
6278 gen_load_fpr32(fp32, fs);
6279 gen_helper_float_cvtl_s(fp64, fp32);
6280 tcg_temp_free_i32(fp32);
6281 gen_store_fpr64(ctx, fp64, fd);
6282 tcg_temp_free_i64(fp64);
6284 opn = "cvt.l.s";
6285 break;
6286 case FOP(38, 16):
6287 check_cp1_64bitmode(ctx);
6289 TCGv_i64 fp64 = tcg_temp_new_i64();
6290 TCGv_i32 fp32_0 = tcg_temp_new_i32();
6291 TCGv_i32 fp32_1 = tcg_temp_new_i32();
6293 gen_load_fpr32(fp32_0, fs);
6294 gen_load_fpr32(fp32_1, ft);
6295 tcg_gen_concat_i32_i64(fp64, fp32_0, fp32_1);
6296 tcg_temp_free_i32(fp32_1);
6297 tcg_temp_free_i32(fp32_0);
6298 gen_store_fpr64(ctx, fp64, fd);
6299 tcg_temp_free_i64(fp64);
6301 opn = "cvt.ps.s";
6302 break;
6303 case FOP(48, 16):
6304 case FOP(49, 16):
6305 case FOP(50, 16):
6306 case FOP(51, 16):
6307 case FOP(52, 16):
6308 case FOP(53, 16):
6309 case FOP(54, 16):
6310 case FOP(55, 16):
6311 case FOP(56, 16):
6312 case FOP(57, 16):
6313 case FOP(58, 16):
6314 case FOP(59, 16):
6315 case FOP(60, 16):
6316 case FOP(61, 16):
6317 case FOP(62, 16):
6318 case FOP(63, 16):
6320 TCGv_i32 fp0 = tcg_temp_new_i32();
6321 TCGv_i32 fp1 = tcg_temp_new_i32();
6323 gen_load_fpr32(fp0, fs);
6324 gen_load_fpr32(fp1, ft);
6325 if (ctx->opcode & (1 << 6)) {
6326 check_cop1x(ctx);
6327 gen_cmpabs_s(func-48, fp0, fp1, cc);
6328 opn = condnames_abs[func-48];
6329 } else {
6330 gen_cmp_s(func-48, fp0, fp1, cc);
6331 opn = condnames[func-48];
6333 tcg_temp_free_i32(fp0);
6334 tcg_temp_free_i32(fp1);
6336 break;
6337 case FOP(0, 17):
6338 check_cp1_registers(ctx, fs | ft | fd);
6340 TCGv_i64 fp0 = tcg_temp_new_i64();
6341 TCGv_i64 fp1 = tcg_temp_new_i64();
6343 gen_load_fpr64(ctx, fp0, fs);
6344 gen_load_fpr64(ctx, fp1, ft);
6345 gen_helper_float_add_d(fp0, fp0, fp1);
6346 tcg_temp_free_i64(fp1);
6347 gen_store_fpr64(ctx, fp0, fd);
6348 tcg_temp_free_i64(fp0);
6350 opn = "add.d";
6351 optype = BINOP;
6352 break;
6353 case FOP(1, 17):
6354 check_cp1_registers(ctx, fs | ft | fd);
6356 TCGv_i64 fp0 = tcg_temp_new_i64();
6357 TCGv_i64 fp1 = tcg_temp_new_i64();
6359 gen_load_fpr64(ctx, fp0, fs);
6360 gen_load_fpr64(ctx, fp1, ft);
6361 gen_helper_float_sub_d(fp0, fp0, fp1);
6362 tcg_temp_free_i64(fp1);
6363 gen_store_fpr64(ctx, fp0, fd);
6364 tcg_temp_free_i64(fp0);
6366 opn = "sub.d";
6367 optype = BINOP;
6368 break;
6369 case FOP(2, 17):
6370 check_cp1_registers(ctx, fs | ft | fd);
6372 TCGv_i64 fp0 = tcg_temp_new_i64();
6373 TCGv_i64 fp1 = tcg_temp_new_i64();
6375 gen_load_fpr64(ctx, fp0, fs);
6376 gen_load_fpr64(ctx, fp1, ft);
6377 gen_helper_float_mul_d(fp0, fp0, fp1);
6378 tcg_temp_free_i64(fp1);
6379 gen_store_fpr64(ctx, fp0, fd);
6380 tcg_temp_free_i64(fp0);
6382 opn = "mul.d";
6383 optype = BINOP;
6384 break;
6385 case FOP(3, 17):
6386 check_cp1_registers(ctx, fs | ft | fd);
6388 TCGv_i64 fp0 = tcg_temp_new_i64();
6389 TCGv_i64 fp1 = tcg_temp_new_i64();
6391 gen_load_fpr64(ctx, fp0, fs);
6392 gen_load_fpr64(ctx, fp1, ft);
6393 gen_helper_float_div_d(fp0, fp0, fp1);
6394 tcg_temp_free_i64(fp1);
6395 gen_store_fpr64(ctx, fp0, fd);
6396 tcg_temp_free_i64(fp0);
6398 opn = "div.d";
6399 optype = BINOP;
6400 break;
6401 case FOP(4, 17):
6402 check_cp1_registers(ctx, fs | fd);
6404 TCGv_i64 fp0 = tcg_temp_new_i64();
6406 gen_load_fpr64(ctx, fp0, fs);
6407 gen_helper_float_sqrt_d(fp0, fp0);
6408 gen_store_fpr64(ctx, fp0, fd);
6409 tcg_temp_free_i64(fp0);
6411 opn = "sqrt.d";
6412 break;
6413 case FOP(5, 17):
6414 check_cp1_registers(ctx, fs | fd);
6416 TCGv_i64 fp0 = tcg_temp_new_i64();
6418 gen_load_fpr64(ctx, fp0, fs);
6419 gen_helper_float_abs_d(fp0, fp0);
6420 gen_store_fpr64(ctx, fp0, fd);
6421 tcg_temp_free_i64(fp0);
6423 opn = "abs.d";
6424 break;
6425 case FOP(6, 17):
6426 check_cp1_registers(ctx, fs | fd);
6428 TCGv_i64 fp0 = tcg_temp_new_i64();
6430 gen_load_fpr64(ctx, fp0, fs);
6431 gen_store_fpr64(ctx, fp0, fd);
6432 tcg_temp_free_i64(fp0);
6434 opn = "mov.d";
6435 break;
6436 case FOP(7, 17):
6437 check_cp1_registers(ctx, fs | fd);
6439 TCGv_i64 fp0 = tcg_temp_new_i64();
6441 gen_load_fpr64(ctx, fp0, fs);
6442 gen_helper_float_chs_d(fp0, fp0);
6443 gen_store_fpr64(ctx, fp0, fd);
6444 tcg_temp_free_i64(fp0);
6446 opn = "neg.d";
6447 break;
6448 case FOP(8, 17):
6449 check_cp1_64bitmode(ctx);
6451 TCGv_i64 fp0 = tcg_temp_new_i64();
6453 gen_load_fpr64(ctx, fp0, fs);
6454 gen_helper_float_roundl_d(fp0, fp0);
6455 gen_store_fpr64(ctx, fp0, fd);
6456 tcg_temp_free_i64(fp0);
6458 opn = "round.l.d";
6459 break;
6460 case FOP(9, 17):
6461 check_cp1_64bitmode(ctx);
6463 TCGv_i64 fp0 = tcg_temp_new_i64();
6465 gen_load_fpr64(ctx, fp0, fs);
6466 gen_helper_float_truncl_d(fp0, fp0);
6467 gen_store_fpr64(ctx, fp0, fd);
6468 tcg_temp_free_i64(fp0);
6470 opn = "trunc.l.d";
6471 break;
6472 case FOP(10, 17):
6473 check_cp1_64bitmode(ctx);
6475 TCGv_i64 fp0 = tcg_temp_new_i64();
6477 gen_load_fpr64(ctx, fp0, fs);
6478 gen_helper_float_ceill_d(fp0, fp0);
6479 gen_store_fpr64(ctx, fp0, fd);
6480 tcg_temp_free_i64(fp0);
6482 opn = "ceil.l.d";
6483 break;
6484 case FOP(11, 17):
6485 check_cp1_64bitmode(ctx);
6487 TCGv_i64 fp0 = tcg_temp_new_i64();
6489 gen_load_fpr64(ctx, fp0, fs);
6490 gen_helper_float_floorl_d(fp0, fp0);
6491 gen_store_fpr64(ctx, fp0, fd);
6492 tcg_temp_free_i64(fp0);
6494 opn = "floor.l.d";
6495 break;
6496 case FOP(12, 17):
6497 check_cp1_registers(ctx, fs);
6499 TCGv_i32 fp32 = tcg_temp_new_i32();
6500 TCGv_i64 fp64 = tcg_temp_new_i64();
6502 gen_load_fpr64(ctx, fp64, fs);
6503 gen_helper_float_roundw_d(fp32, fp64);
6504 tcg_temp_free_i64(fp64);
6505 gen_store_fpr32(fp32, fd);
6506 tcg_temp_free_i32(fp32);
6508 opn = "round.w.d";
6509 break;
6510 case FOP(13, 17):
6511 check_cp1_registers(ctx, fs);
6513 TCGv_i32 fp32 = tcg_temp_new_i32();
6514 TCGv_i64 fp64 = tcg_temp_new_i64();
6516 gen_load_fpr64(ctx, fp64, fs);
6517 gen_helper_float_truncw_d(fp32, fp64);
6518 tcg_temp_free_i64(fp64);
6519 gen_store_fpr32(fp32, fd);
6520 tcg_temp_free_i32(fp32);
6522 opn = "trunc.w.d";
6523 break;
6524 case FOP(14, 17):
6525 check_cp1_registers(ctx, fs);
6527 TCGv_i32 fp32 = tcg_temp_new_i32();
6528 TCGv_i64 fp64 = tcg_temp_new_i64();
6530 gen_load_fpr64(ctx, fp64, fs);
6531 gen_helper_float_ceilw_d(fp32, fp64);
6532 tcg_temp_free_i64(fp64);
6533 gen_store_fpr32(fp32, fd);
6534 tcg_temp_free_i32(fp32);
6536 opn = "ceil.w.d";
6537 break;
6538 case FOP(15, 17):
6539 check_cp1_registers(ctx, fs);
6541 TCGv_i32 fp32 = tcg_temp_new_i32();
6542 TCGv_i64 fp64 = tcg_temp_new_i64();
6544 gen_load_fpr64(ctx, fp64, fs);
6545 gen_helper_float_floorw_d(fp32, fp64);
6546 tcg_temp_free_i64(fp64);
6547 gen_store_fpr32(fp32, fd);
6548 tcg_temp_free_i32(fp32);
6550 opn = "floor.w.d";
6551 break;
6552 case FOP(17, 17):
6553 gen_movcf_d(ctx, fs, fd, (ft >> 2) & 0x7, ft & 0x1);
6554 opn = "movcf.d";
6555 break;
6556 case FOP(18, 17):
6558 int l1 = gen_new_label();
6559 TCGv_i64 fp0;
6561 if (ft != 0) {
6562 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[ft], 0, l1);
6564 fp0 = tcg_temp_new_i64();
6565 gen_load_fpr64(ctx, fp0, fs);
6566 gen_store_fpr64(ctx, fp0, fd);
6567 tcg_temp_free_i64(fp0);
6568 gen_set_label(l1);
6570 opn = "movz.d";
6571 break;
6572 case FOP(19, 17):
6574 int l1 = gen_new_label();
6575 TCGv_i64 fp0;
6577 if (ft != 0) {
6578 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[ft], 0, l1);
6579 fp0 = tcg_temp_new_i64();
6580 gen_load_fpr64(ctx, fp0, fs);
6581 gen_store_fpr64(ctx, fp0, fd);
6582 tcg_temp_free_i64(fp0);
6583 gen_set_label(l1);
6586 opn = "movn.d";
6587 break;
6588 case FOP(21, 17):
6589 check_cp1_64bitmode(ctx);
6591 TCGv_i64 fp0 = tcg_temp_new_i64();
6593 gen_load_fpr64(ctx, fp0, fs);
6594 gen_helper_float_recip_d(fp0, fp0);
6595 gen_store_fpr64(ctx, fp0, fd);
6596 tcg_temp_free_i64(fp0);
6598 opn = "recip.d";
6599 break;
6600 case FOP(22, 17):
6601 check_cp1_64bitmode(ctx);
6603 TCGv_i64 fp0 = tcg_temp_new_i64();
6605 gen_load_fpr64(ctx, fp0, fs);
6606 gen_helper_float_rsqrt_d(fp0, fp0);
6607 gen_store_fpr64(ctx, fp0, fd);
6608 tcg_temp_free_i64(fp0);
6610 opn = "rsqrt.d";
6611 break;
6612 case FOP(28, 17):
6613 check_cp1_64bitmode(ctx);
6615 TCGv_i64 fp0 = tcg_temp_new_i64();
6616 TCGv_i64 fp1 = tcg_temp_new_i64();
6618 gen_load_fpr64(ctx, fp0, fs);
6619 gen_load_fpr64(ctx, fp1, ft);
6620 gen_helper_float_recip2_d(fp0, fp0, fp1);
6621 tcg_temp_free_i64(fp1);
6622 gen_store_fpr64(ctx, fp0, fd);
6623 tcg_temp_free_i64(fp0);
6625 opn = "recip2.d";
6626 break;
6627 case FOP(29, 17):
6628 check_cp1_64bitmode(ctx);
6630 TCGv_i64 fp0 = tcg_temp_new_i64();
6632 gen_load_fpr64(ctx, fp0, fs);
6633 gen_helper_float_recip1_d(fp0, fp0);
6634 gen_store_fpr64(ctx, fp0, fd);
6635 tcg_temp_free_i64(fp0);
6637 opn = "recip1.d";
6638 break;
6639 case FOP(30, 17):
6640 check_cp1_64bitmode(ctx);
6642 TCGv_i64 fp0 = tcg_temp_new_i64();
6644 gen_load_fpr64(ctx, fp0, fs);
6645 gen_helper_float_rsqrt1_d(fp0, fp0);
6646 gen_store_fpr64(ctx, fp0, fd);
6647 tcg_temp_free_i64(fp0);
6649 opn = "rsqrt1.d";
6650 break;
6651 case FOP(31, 17):
6652 check_cp1_64bitmode(ctx);
6654 TCGv_i64 fp0 = tcg_temp_new_i64();
6655 TCGv_i64 fp1 = tcg_temp_new_i64();
6657 gen_load_fpr64(ctx, fp0, fs);
6658 gen_load_fpr64(ctx, fp1, ft);
6659 gen_helper_float_rsqrt2_d(fp0, fp0, fp1);
6660 tcg_temp_free_i64(fp1);
6661 gen_store_fpr64(ctx, fp0, fd);
6662 tcg_temp_free_i64(fp0);
6664 opn = "rsqrt2.d";
6665 break;
6666 case FOP(48, 17):
6667 case FOP(49, 17):
6668 case FOP(50, 17):
6669 case FOP(51, 17):
6670 case FOP(52, 17):
6671 case FOP(53, 17):
6672 case FOP(54, 17):
6673 case FOP(55, 17):
6674 case FOP(56, 17):
6675 case FOP(57, 17):
6676 case FOP(58, 17):
6677 case FOP(59, 17):
6678 case FOP(60, 17):
6679 case FOP(61, 17):
6680 case FOP(62, 17):
6681 case FOP(63, 17):
6683 TCGv_i64 fp0 = tcg_temp_new_i64();
6684 TCGv_i64 fp1 = tcg_temp_new_i64();
6686 gen_load_fpr64(ctx, fp0, fs);
6687 gen_load_fpr64(ctx, fp1, ft);
6688 if (ctx->opcode & (1 << 6)) {
6689 check_cop1x(ctx);
6690 check_cp1_registers(ctx, fs | ft);
6691 gen_cmpabs_d(func-48, fp0, fp1, cc);
6692 opn = condnames_abs[func-48];
6693 } else {
6694 check_cp1_registers(ctx, fs | ft);
6695 gen_cmp_d(func-48, fp0, fp1, cc);
6696 opn = condnames[func-48];
6698 tcg_temp_free_i64(fp0);
6699 tcg_temp_free_i64(fp1);
6701 break;
6702 case FOP(32, 17):
6703 check_cp1_registers(ctx, fs);
6705 TCGv_i32 fp32 = tcg_temp_new_i32();
6706 TCGv_i64 fp64 = tcg_temp_new_i64();
6708 gen_load_fpr64(ctx, fp64, fs);
6709 gen_helper_float_cvts_d(fp32, fp64);
6710 tcg_temp_free_i64(fp64);
6711 gen_store_fpr32(fp32, fd);
6712 tcg_temp_free_i32(fp32);
6714 opn = "cvt.s.d";
6715 break;
6716 case FOP(36, 17):
6717 check_cp1_registers(ctx, fs);
6719 TCGv_i32 fp32 = tcg_temp_new_i32();
6720 TCGv_i64 fp64 = tcg_temp_new_i64();
6722 gen_load_fpr64(ctx, fp64, fs);
6723 gen_helper_float_cvtw_d(fp32, fp64);
6724 tcg_temp_free_i64(fp64);
6725 gen_store_fpr32(fp32, fd);
6726 tcg_temp_free_i32(fp32);
6728 opn = "cvt.w.d";
6729 break;
6730 case FOP(37, 17):
6731 check_cp1_64bitmode(ctx);
6733 TCGv_i64 fp0 = tcg_temp_new_i64();
6735 gen_load_fpr64(ctx, fp0, fs);
6736 gen_helper_float_cvtl_d(fp0, fp0);
6737 gen_store_fpr64(ctx, fp0, fd);
6738 tcg_temp_free_i64(fp0);
6740 opn = "cvt.l.d";
6741 break;
6742 case FOP(32, 20):
6744 TCGv_i32 fp0 = tcg_temp_new_i32();
6746 gen_load_fpr32(fp0, fs);
6747 gen_helper_float_cvts_w(fp0, fp0);
6748 gen_store_fpr32(fp0, fd);
6749 tcg_temp_free_i32(fp0);
6751 opn = "cvt.s.w";
6752 break;
6753 case FOP(33, 20):
6754 check_cp1_registers(ctx, fd);
6756 TCGv_i32 fp32 = tcg_temp_new_i32();
6757 TCGv_i64 fp64 = tcg_temp_new_i64();
6759 gen_load_fpr32(fp32, fs);
6760 gen_helper_float_cvtd_w(fp64, fp32);
6761 tcg_temp_free_i32(fp32);
6762 gen_store_fpr64(ctx, fp64, fd);
6763 tcg_temp_free_i64(fp64);
6765 opn = "cvt.d.w";
6766 break;
6767 case FOP(32, 21):
6768 check_cp1_64bitmode(ctx);
6770 TCGv_i32 fp32 = tcg_temp_new_i32();
6771 TCGv_i64 fp64 = tcg_temp_new_i64();
6773 gen_load_fpr64(ctx, fp64, fs);
6774 gen_helper_float_cvts_l(fp32, fp64);
6775 tcg_temp_free_i64(fp64);
6776 gen_store_fpr32(fp32, fd);
6777 tcg_temp_free_i32(fp32);
6779 opn = "cvt.s.l";
6780 break;
6781 case FOP(33, 21):
6782 check_cp1_64bitmode(ctx);
6784 TCGv_i64 fp0 = tcg_temp_new_i64();
6786 gen_load_fpr64(ctx, fp0, fs);
6787 gen_helper_float_cvtd_l(fp0, fp0);
6788 gen_store_fpr64(ctx, fp0, fd);
6789 tcg_temp_free_i64(fp0);
6791 opn = "cvt.d.l";
6792 break;
6793 case FOP(38, 20):
6794 check_cp1_64bitmode(ctx);
6796 TCGv_i64 fp0 = tcg_temp_new_i64();
6798 gen_load_fpr64(ctx, fp0, fs);
6799 gen_helper_float_cvtps_pw(fp0, fp0);
6800 gen_store_fpr64(ctx, fp0, fd);
6801 tcg_temp_free_i64(fp0);
6803 opn = "cvt.ps.pw";
6804 break;
6805 case FOP(0, 22):
6806 check_cp1_64bitmode(ctx);
6808 TCGv_i64 fp0 = tcg_temp_new_i64();
6809 TCGv_i64 fp1 = tcg_temp_new_i64();
6811 gen_load_fpr64(ctx, fp0, fs);
6812 gen_load_fpr64(ctx, fp1, ft);
6813 gen_helper_float_add_ps(fp0, fp0, fp1);
6814 tcg_temp_free_i64(fp1);
6815 gen_store_fpr64(ctx, fp0, fd);
6816 tcg_temp_free_i64(fp0);
6818 opn = "add.ps";
6819 break;
6820 case FOP(1, 22):
6821 check_cp1_64bitmode(ctx);
6823 TCGv_i64 fp0 = tcg_temp_new_i64();
6824 TCGv_i64 fp1 = tcg_temp_new_i64();
6826 gen_load_fpr64(ctx, fp0, fs);
6827 gen_load_fpr64(ctx, fp1, ft);
6828 gen_helper_float_sub_ps(fp0, fp0, fp1);
6829 tcg_temp_free_i64(fp1);
6830 gen_store_fpr64(ctx, fp0, fd);
6831 tcg_temp_free_i64(fp0);
6833 opn = "sub.ps";
6834 break;
6835 case FOP(2, 22):
6836 check_cp1_64bitmode(ctx);
6838 TCGv_i64 fp0 = tcg_temp_new_i64();
6839 TCGv_i64 fp1 = tcg_temp_new_i64();
6841 gen_load_fpr64(ctx, fp0, fs);
6842 gen_load_fpr64(ctx, fp1, ft);
6843 gen_helper_float_mul_ps(fp0, fp0, fp1);
6844 tcg_temp_free_i64(fp1);
6845 gen_store_fpr64(ctx, fp0, fd);
6846 tcg_temp_free_i64(fp0);
6848 opn = "mul.ps";
6849 break;
6850 case FOP(5, 22):
6851 check_cp1_64bitmode(ctx);
6853 TCGv_i64 fp0 = tcg_temp_new_i64();
6855 gen_load_fpr64(ctx, fp0, fs);
6856 gen_helper_float_abs_ps(fp0, fp0);
6857 gen_store_fpr64(ctx, fp0, fd);
6858 tcg_temp_free_i64(fp0);
6860 opn = "abs.ps";
6861 break;
6862 case FOP(6, 22):
6863 check_cp1_64bitmode(ctx);
6865 TCGv_i64 fp0 = tcg_temp_new_i64();
6867 gen_load_fpr64(ctx, fp0, fs);
6868 gen_store_fpr64(ctx, fp0, fd);
6869 tcg_temp_free_i64(fp0);
6871 opn = "mov.ps";
6872 break;
6873 case FOP(7, 22):
6874 check_cp1_64bitmode(ctx);
6876 TCGv_i64 fp0 = tcg_temp_new_i64();
6878 gen_load_fpr64(ctx, fp0, fs);
6879 gen_helper_float_chs_ps(fp0, fp0);
6880 gen_store_fpr64(ctx, fp0, fd);
6881 tcg_temp_free_i64(fp0);
6883 opn = "neg.ps";
6884 break;
6885 case FOP(17, 22):
6886 check_cp1_64bitmode(ctx);
6887 gen_movcf_ps(fs, fd, (ft >> 2) & 0x7, ft & 0x1);
6888 opn = "movcf.ps";
6889 break;
6890 case FOP(18, 22):
6891 check_cp1_64bitmode(ctx);
6893 int l1 = gen_new_label();
6894 TCGv_i64 fp0;
6896 if (ft != 0)
6897 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[ft], 0, l1);
6898 fp0 = tcg_temp_new_i64();
6899 gen_load_fpr64(ctx, fp0, fs);
6900 gen_store_fpr64(ctx, fp0, fd);
6901 tcg_temp_free_i64(fp0);
6902 gen_set_label(l1);
6904 opn = "movz.ps";
6905 break;
6906 case FOP(19, 22):
6907 check_cp1_64bitmode(ctx);
6909 int l1 = gen_new_label();
6910 TCGv_i64 fp0;
6912 if (ft != 0) {
6913 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[ft], 0, l1);
6914 fp0 = tcg_temp_new_i64();
6915 gen_load_fpr64(ctx, fp0, fs);
6916 gen_store_fpr64(ctx, fp0, fd);
6917 tcg_temp_free_i64(fp0);
6918 gen_set_label(l1);
6921 opn = "movn.ps";
6922 break;
6923 case FOP(24, 22):
6924 check_cp1_64bitmode(ctx);
6926 TCGv_i64 fp0 = tcg_temp_new_i64();
6927 TCGv_i64 fp1 = tcg_temp_new_i64();
6929 gen_load_fpr64(ctx, fp0, ft);
6930 gen_load_fpr64(ctx, fp1, fs);
6931 gen_helper_float_addr_ps(fp0, fp0, fp1);
6932 tcg_temp_free_i64(fp1);
6933 gen_store_fpr64(ctx, fp0, fd);
6934 tcg_temp_free_i64(fp0);
6936 opn = "addr.ps";
6937 break;
6938 case FOP(26, 22):
6939 check_cp1_64bitmode(ctx);
6941 TCGv_i64 fp0 = tcg_temp_new_i64();
6942 TCGv_i64 fp1 = tcg_temp_new_i64();
6944 gen_load_fpr64(ctx, fp0, ft);
6945 gen_load_fpr64(ctx, fp1, fs);
6946 gen_helper_float_mulr_ps(fp0, fp0, fp1);
6947 tcg_temp_free_i64(fp1);
6948 gen_store_fpr64(ctx, fp0, fd);
6949 tcg_temp_free_i64(fp0);
6951 opn = "mulr.ps";
6952 break;
6953 case FOP(28, 22):
6954 check_cp1_64bitmode(ctx);
6956 TCGv_i64 fp0 = tcg_temp_new_i64();
6957 TCGv_i64 fp1 = tcg_temp_new_i64();
6959 gen_load_fpr64(ctx, fp0, fs);
6960 gen_load_fpr64(ctx, fp1, fd);
6961 gen_helper_float_recip2_ps(fp0, fp0, fp1);
6962 tcg_temp_free_i64(fp1);
6963 gen_store_fpr64(ctx, fp0, fd);
6964 tcg_temp_free_i64(fp0);
6966 opn = "recip2.ps";
6967 break;
6968 case FOP(29, 22):
6969 check_cp1_64bitmode(ctx);
6971 TCGv_i64 fp0 = tcg_temp_new_i64();
6973 gen_load_fpr64(ctx, fp0, fs);
6974 gen_helper_float_recip1_ps(fp0, fp0);
6975 gen_store_fpr64(ctx, fp0, fd);
6976 tcg_temp_free_i64(fp0);
6978 opn = "recip1.ps";
6979 break;
6980 case FOP(30, 22):
6981 check_cp1_64bitmode(ctx);
6983 TCGv_i64 fp0 = tcg_temp_new_i64();
6985 gen_load_fpr64(ctx, fp0, fs);
6986 gen_helper_float_rsqrt1_ps(fp0, fp0);
6987 gen_store_fpr64(ctx, fp0, fd);
6988 tcg_temp_free_i64(fp0);
6990 opn = "rsqrt1.ps";
6991 break;
6992 case FOP(31, 22):
6993 check_cp1_64bitmode(ctx);
6995 TCGv_i64 fp0 = tcg_temp_new_i64();
6996 TCGv_i64 fp1 = tcg_temp_new_i64();
6998 gen_load_fpr64(ctx, fp0, fs);
6999 gen_load_fpr64(ctx, fp1, ft);
7000 gen_helper_float_rsqrt2_ps(fp0, fp0, fp1);
7001 tcg_temp_free_i64(fp1);
7002 gen_store_fpr64(ctx, fp0, fd);
7003 tcg_temp_free_i64(fp0);
7005 opn = "rsqrt2.ps";
7006 break;
7007 case FOP(32, 22):
7008 check_cp1_64bitmode(ctx);
7010 TCGv_i32 fp0 = tcg_temp_new_i32();
7012 gen_load_fpr32h(fp0, fs);
7013 gen_helper_float_cvts_pu(fp0, fp0);
7014 gen_store_fpr32(fp0, fd);
7015 tcg_temp_free_i32(fp0);
7017 opn = "cvt.s.pu";
7018 break;
7019 case FOP(36, 22):
7020 check_cp1_64bitmode(ctx);
7022 TCGv_i64 fp0 = tcg_temp_new_i64();
7024 gen_load_fpr64(ctx, fp0, fs);
7025 gen_helper_float_cvtpw_ps(fp0, fp0);
7026 gen_store_fpr64(ctx, fp0, fd);
7027 tcg_temp_free_i64(fp0);
7029 opn = "cvt.pw.ps";
7030 break;
7031 case FOP(40, 22):
7032 check_cp1_64bitmode(ctx);
7034 TCGv_i32 fp0 = tcg_temp_new_i32();
7036 gen_load_fpr32(fp0, fs);
7037 gen_helper_float_cvts_pl(fp0, fp0);
7038 gen_store_fpr32(fp0, fd);
7039 tcg_temp_free_i32(fp0);
7041 opn = "cvt.s.pl";
7042 break;
7043 case FOP(44, 22):
7044 check_cp1_64bitmode(ctx);
7046 TCGv_i32 fp0 = tcg_temp_new_i32();
7047 TCGv_i32 fp1 = tcg_temp_new_i32();
7049 gen_load_fpr32(fp0, fs);
7050 gen_load_fpr32(fp1, ft);
7051 gen_store_fpr32h(fp0, fd);
7052 gen_store_fpr32(fp1, fd);
7053 tcg_temp_free_i32(fp0);
7054 tcg_temp_free_i32(fp1);
7056 opn = "pll.ps";
7057 break;
7058 case FOP(45, 22):
7059 check_cp1_64bitmode(ctx);
7061 TCGv_i32 fp0 = tcg_temp_new_i32();
7062 TCGv_i32 fp1 = tcg_temp_new_i32();
7064 gen_load_fpr32(fp0, fs);
7065 gen_load_fpr32h(fp1, ft);
7066 gen_store_fpr32(fp1, fd);
7067 gen_store_fpr32h(fp0, fd);
7068 tcg_temp_free_i32(fp0);
7069 tcg_temp_free_i32(fp1);
7071 opn = "plu.ps";
7072 break;
7073 case FOP(46, 22):
7074 check_cp1_64bitmode(ctx);
7076 TCGv_i32 fp0 = tcg_temp_new_i32();
7077 TCGv_i32 fp1 = tcg_temp_new_i32();
7079 gen_load_fpr32h(fp0, fs);
7080 gen_load_fpr32(fp1, ft);
7081 gen_store_fpr32(fp1, fd);
7082 gen_store_fpr32h(fp0, fd);
7083 tcg_temp_free_i32(fp0);
7084 tcg_temp_free_i32(fp1);
7086 opn = "pul.ps";
7087 break;
7088 case FOP(47, 22):
7089 check_cp1_64bitmode(ctx);
7091 TCGv_i32 fp0 = tcg_temp_new_i32();
7092 TCGv_i32 fp1 = tcg_temp_new_i32();
7094 gen_load_fpr32h(fp0, fs);
7095 gen_load_fpr32h(fp1, ft);
7096 gen_store_fpr32(fp1, fd);
7097 gen_store_fpr32h(fp0, fd);
7098 tcg_temp_free_i32(fp0);
7099 tcg_temp_free_i32(fp1);
7101 opn = "puu.ps";
7102 break;
7103 case FOP(48, 22):
7104 case FOP(49, 22):
7105 case FOP(50, 22):
7106 case FOP(51, 22):
7107 case FOP(52, 22):
7108 case FOP(53, 22):
7109 case FOP(54, 22):
7110 case FOP(55, 22):
7111 case FOP(56, 22):
7112 case FOP(57, 22):
7113 case FOP(58, 22):
7114 case FOP(59, 22):
7115 case FOP(60, 22):
7116 case FOP(61, 22):
7117 case FOP(62, 22):
7118 case FOP(63, 22):
7119 check_cp1_64bitmode(ctx);
7121 TCGv_i64 fp0 = tcg_temp_new_i64();
7122 TCGv_i64 fp1 = tcg_temp_new_i64();
7124 gen_load_fpr64(ctx, fp0, fs);
7125 gen_load_fpr64(ctx, fp1, ft);
7126 if (ctx->opcode & (1 << 6)) {
7127 gen_cmpabs_ps(func-48, fp0, fp1, cc);
7128 opn = condnames_abs[func-48];
7129 } else {
7130 gen_cmp_ps(func-48, fp0, fp1, cc);
7131 opn = condnames[func-48];
7133 tcg_temp_free_i64(fp0);
7134 tcg_temp_free_i64(fp1);
7136 break;
7137 default:
7138 MIPS_INVAL(opn);
7139 generate_exception (ctx, EXCP_RI);
7140 return;
7142 switch (optype) {
7143 case BINOP:
7144 MIPS_DEBUG("%s %s, %s, %s", opn, fregnames[fd], fregnames[fs], fregnames[ft]);
7145 break;
7146 case CMPOP:
7147 MIPS_DEBUG("%s %s,%s", opn, fregnames[fs], fregnames[ft]);
7148 break;
7149 default:
7150 MIPS_DEBUG("%s %s,%s", opn, fregnames[fd], fregnames[fs]);
7151 break;
7155 /* Coprocessor 3 (FPU) */
7156 static void gen_flt3_ldst (DisasContext *ctx, uint32_t opc,
7157 int fd, int fs, int base, int index)
7159 const char *opn = "extended float load/store";
7160 int store = 0;
7161 TCGv t0 = tcg_temp_new();
7163 if (base == 0) {
7164 gen_load_gpr(t0, index);
7165 } else if (index == 0) {
7166 gen_load_gpr(t0, base);
7167 } else {
7168 gen_load_gpr(t0, index);
7169 gen_op_addr_add(ctx, t0, cpu_gpr[base], t0);
7171 /* Don't do NOP if destination is zero: we must perform the actual
7172 memory access. */
7173 save_cpu_state(ctx, 0);
7174 switch (opc) {
7175 case OPC_LWXC1:
7176 check_cop1x(ctx);
7178 TCGv_i32 fp0 = tcg_temp_new_i32();
7180 tcg_gen_qemu_ld32s(t0, t0, ctx->mem_idx);
7181 tcg_gen_trunc_tl_i32(fp0, t0);
7182 gen_store_fpr32(fp0, fd);
7183 tcg_temp_free_i32(fp0);
7185 opn = "lwxc1";
7186 break;
7187 case OPC_LDXC1:
7188 check_cop1x(ctx);
7189 check_cp1_registers(ctx, fd);
7191 TCGv_i64 fp0 = tcg_temp_new_i64();
7193 tcg_gen_qemu_ld64(fp0, t0, ctx->mem_idx);
7194 gen_store_fpr64(ctx, fp0, fd);
7195 tcg_temp_free_i64(fp0);
7197 opn = "ldxc1";
7198 break;
7199 case OPC_LUXC1:
7200 check_cp1_64bitmode(ctx);
7201 tcg_gen_andi_tl(t0, t0, ~0x7);
7203 TCGv_i64 fp0 = tcg_temp_new_i64();
7205 tcg_gen_qemu_ld64(fp0, t0, ctx->mem_idx);
7206 gen_store_fpr64(ctx, fp0, fd);
7207 tcg_temp_free_i64(fp0);
7209 opn = "luxc1";
7210 break;
7211 case OPC_SWXC1:
7212 check_cop1x(ctx);
7214 TCGv_i32 fp0 = tcg_temp_new_i32();
7215 TCGv t1 = tcg_temp_new();
7217 gen_load_fpr32(fp0, fs);
7218 tcg_gen_extu_i32_tl(t1, fp0);
7219 tcg_gen_qemu_st32(t1, t0, ctx->mem_idx);
7220 tcg_temp_free_i32(fp0);
7221 tcg_temp_free(t1);
7223 opn = "swxc1";
7224 store = 1;
7225 break;
7226 case OPC_SDXC1:
7227 check_cop1x(ctx);
7228 check_cp1_registers(ctx, fs);
7230 TCGv_i64 fp0 = tcg_temp_new_i64();
7232 gen_load_fpr64(ctx, fp0, fs);
7233 tcg_gen_qemu_st64(fp0, t0, ctx->mem_idx);
7234 tcg_temp_free_i64(fp0);
7236 opn = "sdxc1";
7237 store = 1;
7238 break;
7239 case OPC_SUXC1:
7240 check_cp1_64bitmode(ctx);
7241 tcg_gen_andi_tl(t0, t0, ~0x7);
7243 TCGv_i64 fp0 = tcg_temp_new_i64();
7245 gen_load_fpr64(ctx, fp0, fs);
7246 tcg_gen_qemu_st64(fp0, t0, ctx->mem_idx);
7247 tcg_temp_free_i64(fp0);
7249 opn = "suxc1";
7250 store = 1;
7251 break;
7253 tcg_temp_free(t0);
7254 MIPS_DEBUG("%s %s, %s(%s)", opn, fregnames[store ? fs : fd],
7255 regnames[index], regnames[base]);
7258 static void gen_flt3_arith (DisasContext *ctx, uint32_t opc,
7259 int fd, int fr, int fs, int ft)
7261 const char *opn = "flt3_arith";
7263 switch (opc) {
7264 case OPC_ALNV_PS:
7265 check_cp1_64bitmode(ctx);
7267 TCGv t0 = tcg_temp_local_new();
7268 TCGv_i32 fp = tcg_temp_new_i32();
7269 TCGv_i32 fph = tcg_temp_new_i32();
7270 int l1 = gen_new_label();
7271 int l2 = gen_new_label();
7273 gen_load_gpr(t0, fr);
7274 tcg_gen_andi_tl(t0, t0, 0x7);
7276 tcg_gen_brcondi_tl(TCG_COND_NE, t0, 0, l1);
7277 gen_load_fpr32(fp, fs);
7278 gen_load_fpr32h(fph, fs);
7279 gen_store_fpr32(fp, fd);
7280 gen_store_fpr32h(fph, fd);
7281 tcg_gen_br(l2);
7282 gen_set_label(l1);
7283 tcg_gen_brcondi_tl(TCG_COND_NE, t0, 4, l2);
7284 tcg_temp_free(t0);
7285 #ifdef TARGET_WORDS_BIGENDIAN
7286 gen_load_fpr32(fp, fs);
7287 gen_load_fpr32h(fph, ft);
7288 gen_store_fpr32h(fp, fd);
7289 gen_store_fpr32(fph, fd);
7290 #else
7291 gen_load_fpr32h(fph, fs);
7292 gen_load_fpr32(fp, ft);
7293 gen_store_fpr32(fph, fd);
7294 gen_store_fpr32h(fp, fd);
7295 #endif
7296 gen_set_label(l2);
7297 tcg_temp_free_i32(fp);
7298 tcg_temp_free_i32(fph);
7300 opn = "alnv.ps";
7301 break;
7302 case OPC_MADD_S:
7303 check_cop1x(ctx);
7305 TCGv_i32 fp0 = tcg_temp_new_i32();
7306 TCGv_i32 fp1 = tcg_temp_new_i32();
7307 TCGv_i32 fp2 = tcg_temp_new_i32();
7309 gen_load_fpr32(fp0, fs);
7310 gen_load_fpr32(fp1, ft);
7311 gen_load_fpr32(fp2, fr);
7312 gen_helper_float_muladd_s(fp2, fp0, fp1, fp2);
7313 tcg_temp_free_i32(fp0);
7314 tcg_temp_free_i32(fp1);
7315 gen_store_fpr32(fp2, fd);
7316 tcg_temp_free_i32(fp2);
7318 opn = "madd.s";
7319 break;
7320 case OPC_MADD_D:
7321 check_cop1x(ctx);
7322 check_cp1_registers(ctx, fd | fs | ft | fr);
7324 TCGv_i64 fp0 = tcg_temp_new_i64();
7325 TCGv_i64 fp1 = tcg_temp_new_i64();
7326 TCGv_i64 fp2 = tcg_temp_new_i64();
7328 gen_load_fpr64(ctx, fp0, fs);
7329 gen_load_fpr64(ctx, fp1, ft);
7330 gen_load_fpr64(ctx, fp2, fr);
7331 gen_helper_float_muladd_d(fp2, fp0, fp1, fp2);
7332 tcg_temp_free_i64(fp0);
7333 tcg_temp_free_i64(fp1);
7334 gen_store_fpr64(ctx, fp2, fd);
7335 tcg_temp_free_i64(fp2);
7337 opn = "madd.d";
7338 break;
7339 case OPC_MADD_PS:
7340 check_cp1_64bitmode(ctx);
7342 TCGv_i64 fp0 = tcg_temp_new_i64();
7343 TCGv_i64 fp1 = tcg_temp_new_i64();
7344 TCGv_i64 fp2 = tcg_temp_new_i64();
7346 gen_load_fpr64(ctx, fp0, fs);
7347 gen_load_fpr64(ctx, fp1, ft);
7348 gen_load_fpr64(ctx, fp2, fr);
7349 gen_helper_float_muladd_ps(fp2, fp0, fp1, fp2);
7350 tcg_temp_free_i64(fp0);
7351 tcg_temp_free_i64(fp1);
7352 gen_store_fpr64(ctx, fp2, fd);
7353 tcg_temp_free_i64(fp2);
7355 opn = "madd.ps";
7356 break;
7357 case OPC_MSUB_S:
7358 check_cop1x(ctx);
7360 TCGv_i32 fp0 = tcg_temp_new_i32();
7361 TCGv_i32 fp1 = tcg_temp_new_i32();
7362 TCGv_i32 fp2 = tcg_temp_new_i32();
7364 gen_load_fpr32(fp0, fs);
7365 gen_load_fpr32(fp1, ft);
7366 gen_load_fpr32(fp2, fr);
7367 gen_helper_float_mulsub_s(fp2, fp0, fp1, fp2);
7368 tcg_temp_free_i32(fp0);
7369 tcg_temp_free_i32(fp1);
7370 gen_store_fpr32(fp2, fd);
7371 tcg_temp_free_i32(fp2);
7373 opn = "msub.s";
7374 break;
7375 case OPC_MSUB_D:
7376 check_cop1x(ctx);
7377 check_cp1_registers(ctx, fd | fs | ft | fr);
7379 TCGv_i64 fp0 = tcg_temp_new_i64();
7380 TCGv_i64 fp1 = tcg_temp_new_i64();
7381 TCGv_i64 fp2 = tcg_temp_new_i64();
7383 gen_load_fpr64(ctx, fp0, fs);
7384 gen_load_fpr64(ctx, fp1, ft);
7385 gen_load_fpr64(ctx, fp2, fr);
7386 gen_helper_float_mulsub_d(fp2, fp0, fp1, fp2);
7387 tcg_temp_free_i64(fp0);
7388 tcg_temp_free_i64(fp1);
7389 gen_store_fpr64(ctx, fp2, fd);
7390 tcg_temp_free_i64(fp2);
7392 opn = "msub.d";
7393 break;
7394 case OPC_MSUB_PS:
7395 check_cp1_64bitmode(ctx);
7397 TCGv_i64 fp0 = tcg_temp_new_i64();
7398 TCGv_i64 fp1 = tcg_temp_new_i64();
7399 TCGv_i64 fp2 = tcg_temp_new_i64();
7401 gen_load_fpr64(ctx, fp0, fs);
7402 gen_load_fpr64(ctx, fp1, ft);
7403 gen_load_fpr64(ctx, fp2, fr);
7404 gen_helper_float_mulsub_ps(fp2, fp0, fp1, fp2);
7405 tcg_temp_free_i64(fp0);
7406 tcg_temp_free_i64(fp1);
7407 gen_store_fpr64(ctx, fp2, fd);
7408 tcg_temp_free_i64(fp2);
7410 opn = "msub.ps";
7411 break;
7412 case OPC_NMADD_S:
7413 check_cop1x(ctx);
7415 TCGv_i32 fp0 = tcg_temp_new_i32();
7416 TCGv_i32 fp1 = tcg_temp_new_i32();
7417 TCGv_i32 fp2 = tcg_temp_new_i32();
7419 gen_load_fpr32(fp0, fs);
7420 gen_load_fpr32(fp1, ft);
7421 gen_load_fpr32(fp2, fr);
7422 gen_helper_float_nmuladd_s(fp2, fp0, fp1, fp2);
7423 tcg_temp_free_i32(fp0);
7424 tcg_temp_free_i32(fp1);
7425 gen_store_fpr32(fp2, fd);
7426 tcg_temp_free_i32(fp2);
7428 opn = "nmadd.s";
7429 break;
7430 case OPC_NMADD_D:
7431 check_cop1x(ctx);
7432 check_cp1_registers(ctx, fd | fs | ft | fr);
7434 TCGv_i64 fp0 = tcg_temp_new_i64();
7435 TCGv_i64 fp1 = tcg_temp_new_i64();
7436 TCGv_i64 fp2 = tcg_temp_new_i64();
7438 gen_load_fpr64(ctx, fp0, fs);
7439 gen_load_fpr64(ctx, fp1, ft);
7440 gen_load_fpr64(ctx, fp2, fr);
7441 gen_helper_float_nmuladd_d(fp2, fp0, fp1, fp2);
7442 tcg_temp_free_i64(fp0);
7443 tcg_temp_free_i64(fp1);
7444 gen_store_fpr64(ctx, fp2, fd);
7445 tcg_temp_free_i64(fp2);
7447 opn = "nmadd.d";
7448 break;
7449 case OPC_NMADD_PS:
7450 check_cp1_64bitmode(ctx);
7452 TCGv_i64 fp0 = tcg_temp_new_i64();
7453 TCGv_i64 fp1 = tcg_temp_new_i64();
7454 TCGv_i64 fp2 = tcg_temp_new_i64();
7456 gen_load_fpr64(ctx, fp0, fs);
7457 gen_load_fpr64(ctx, fp1, ft);
7458 gen_load_fpr64(ctx, fp2, fr);
7459 gen_helper_float_nmuladd_ps(fp2, fp0, fp1, fp2);
7460 tcg_temp_free_i64(fp0);
7461 tcg_temp_free_i64(fp1);
7462 gen_store_fpr64(ctx, fp2, fd);
7463 tcg_temp_free_i64(fp2);
7465 opn = "nmadd.ps";
7466 break;
7467 case OPC_NMSUB_S:
7468 check_cop1x(ctx);
7470 TCGv_i32 fp0 = tcg_temp_new_i32();
7471 TCGv_i32 fp1 = tcg_temp_new_i32();
7472 TCGv_i32 fp2 = tcg_temp_new_i32();
7474 gen_load_fpr32(fp0, fs);
7475 gen_load_fpr32(fp1, ft);
7476 gen_load_fpr32(fp2, fr);
7477 gen_helper_float_nmulsub_s(fp2, fp0, fp1, fp2);
7478 tcg_temp_free_i32(fp0);
7479 tcg_temp_free_i32(fp1);
7480 gen_store_fpr32(fp2, fd);
7481 tcg_temp_free_i32(fp2);
7483 opn = "nmsub.s";
7484 break;
7485 case OPC_NMSUB_D:
7486 check_cop1x(ctx);
7487 check_cp1_registers(ctx, fd | fs | ft | fr);
7489 TCGv_i64 fp0 = tcg_temp_new_i64();
7490 TCGv_i64 fp1 = tcg_temp_new_i64();
7491 TCGv_i64 fp2 = tcg_temp_new_i64();
7493 gen_load_fpr64(ctx, fp0, fs);
7494 gen_load_fpr64(ctx, fp1, ft);
7495 gen_load_fpr64(ctx, fp2, fr);
7496 gen_helper_float_nmulsub_d(fp2, fp0, fp1, fp2);
7497 tcg_temp_free_i64(fp0);
7498 tcg_temp_free_i64(fp1);
7499 gen_store_fpr64(ctx, fp2, fd);
7500 tcg_temp_free_i64(fp2);
7502 opn = "nmsub.d";
7503 break;
7504 case OPC_NMSUB_PS:
7505 check_cp1_64bitmode(ctx);
7507 TCGv_i64 fp0 = tcg_temp_new_i64();
7508 TCGv_i64 fp1 = tcg_temp_new_i64();
7509 TCGv_i64 fp2 = tcg_temp_new_i64();
7511 gen_load_fpr64(ctx, fp0, fs);
7512 gen_load_fpr64(ctx, fp1, ft);
7513 gen_load_fpr64(ctx, fp2, fr);
7514 gen_helper_float_nmulsub_ps(fp2, fp0, fp1, fp2);
7515 tcg_temp_free_i64(fp0);
7516 tcg_temp_free_i64(fp1);
7517 gen_store_fpr64(ctx, fp2, fd);
7518 tcg_temp_free_i64(fp2);
7520 opn = "nmsub.ps";
7521 break;
7522 default:
7523 MIPS_INVAL(opn);
7524 generate_exception (ctx, EXCP_RI);
7525 return;
7527 MIPS_DEBUG("%s %s, %s, %s, %s", opn, fregnames[fd], fregnames[fr],
7528 fregnames[fs], fregnames[ft]);
7531 static void handle_delay_slot (CPUState *env, DisasContext *ctx,
7532 int insn_bytes)
7534 if (ctx->hflags & MIPS_HFLAG_BMASK) {
7535 int proc_hflags = ctx->hflags & MIPS_HFLAG_BMASK;
7536 /* Branches completion */
7537 ctx->hflags &= ~MIPS_HFLAG_BMASK;
7538 ctx->bstate = BS_BRANCH;
7539 save_cpu_state(ctx, 0);
7540 /* FIXME: Need to clear can_do_io. */
7541 switch (proc_hflags & MIPS_HFLAG_BMASK_BASE) {
7542 case MIPS_HFLAG_B:
7543 /* unconditional branch */
7544 MIPS_DEBUG("unconditional branch");
7545 if (proc_hflags & MIPS_HFLAG_BX) {
7546 tcg_gen_xori_i32(hflags, hflags, MIPS_HFLAG_M16);
7548 gen_goto_tb(ctx, 0, ctx->btarget);
7549 break;
7550 case MIPS_HFLAG_BL:
7551 /* blikely taken case */
7552 MIPS_DEBUG("blikely branch taken");
7553 gen_goto_tb(ctx, 0, ctx->btarget);
7554 break;
7555 case MIPS_HFLAG_BC:
7556 /* Conditional branch */
7557 MIPS_DEBUG("conditional branch");
7559 int l1 = gen_new_label();
7561 tcg_gen_brcondi_tl(TCG_COND_NE, bcond, 0, l1);
7562 gen_goto_tb(ctx, 1, ctx->pc + insn_bytes);
7563 gen_set_label(l1);
7564 gen_goto_tb(ctx, 0, ctx->btarget);
7566 break;
7567 case MIPS_HFLAG_BR:
7568 /* unconditional branch to register */
7569 MIPS_DEBUG("branch to register");
7570 if (env->insn_flags & ASE_MIPS16) {
7571 TCGv t0 = tcg_temp_new();
7572 TCGv_i32 t1 = tcg_temp_new_i32();
7574 tcg_gen_andi_tl(t0, btarget, 0x1);
7575 tcg_gen_trunc_tl_i32(t1, t0);
7576 tcg_temp_free(t0);
7577 tcg_gen_andi_i32(hflags, hflags, ~(uint32_t)MIPS_HFLAG_M16);
7578 tcg_gen_shli_i32(t1, t1, MIPS_HFLAG_M16_SHIFT);
7579 tcg_gen_or_i32(hflags, hflags, t1);
7580 tcg_temp_free_i32(t1);
7582 tcg_gen_andi_tl(cpu_PC, btarget, ~(target_ulong)0x1);
7583 } else {
7584 tcg_gen_mov_tl(cpu_PC, btarget);
7586 if (ctx->singlestep_enabled) {
7587 save_cpu_state(ctx, 0);
7588 gen_helper_0i(raise_exception, EXCP_DEBUG);
7590 tcg_gen_exit_tb(0);
7591 break;
7592 default:
7593 MIPS_DEBUG("unknown branch");
7594 break;
7599 /* ISA extensions (ASEs) */
7600 /* MIPS16 extension to MIPS32 */
7602 /* MIPS16 major opcodes */
7603 enum {
7604 M16_OPC_ADDIUSP = 0x00,
7605 M16_OPC_ADDIUPC = 0x01,
7606 M16_OPC_B = 0x02,
7607 M16_OPC_JAL = 0x03,
7608 M16_OPC_BEQZ = 0x04,
7609 M16_OPC_BNEQZ = 0x05,
7610 M16_OPC_SHIFT = 0x06,
7611 M16_OPC_LD = 0x07,
7612 M16_OPC_RRIA = 0x08,
7613 M16_OPC_ADDIU8 = 0x09,
7614 M16_OPC_SLTI = 0x0a,
7615 M16_OPC_SLTIU = 0x0b,
7616 M16_OPC_I8 = 0x0c,
7617 M16_OPC_LI = 0x0d,
7618 M16_OPC_CMPI = 0x0e,
7619 M16_OPC_SD = 0x0f,
7620 M16_OPC_LB = 0x10,
7621 M16_OPC_LH = 0x11,
7622 M16_OPC_LWSP = 0x12,
7623 M16_OPC_LW = 0x13,
7624 M16_OPC_LBU = 0x14,
7625 M16_OPC_LHU = 0x15,
7626 M16_OPC_LWPC = 0x16,
7627 M16_OPC_LWU = 0x17,
7628 M16_OPC_SB = 0x18,
7629 M16_OPC_SH = 0x19,
7630 M16_OPC_SWSP = 0x1a,
7631 M16_OPC_SW = 0x1b,
7632 M16_OPC_RRR = 0x1c,
7633 M16_OPC_RR = 0x1d,
7634 M16_OPC_EXTEND = 0x1e,
7635 M16_OPC_I64 = 0x1f
7638 /* I8 funct field */
7639 enum {
7640 I8_BTEQZ = 0x0,
7641 I8_BTNEZ = 0x1,
7642 I8_SWRASP = 0x2,
7643 I8_ADJSP = 0x3,
7644 I8_SVRS = 0x4,
7645 I8_MOV32R = 0x5,
7646 I8_MOVR32 = 0x7
7649 /* RRR f field */
7650 enum {
7651 RRR_DADDU = 0x0,
7652 RRR_ADDU = 0x1,
7653 RRR_DSUBU = 0x2,
7654 RRR_SUBU = 0x3
7657 /* RR funct field */
7658 enum {
7659 RR_JR = 0x00,
7660 RR_SDBBP = 0x01,
7661 RR_SLT = 0x02,
7662 RR_SLTU = 0x03,
7663 RR_SLLV = 0x04,
7664 RR_BREAK = 0x05,
7665 RR_SRLV = 0x06,
7666 RR_SRAV = 0x07,
7667 RR_DSRL = 0x08,
7668 RR_CMP = 0x0a,
7669 RR_NEG = 0x0b,
7670 RR_AND = 0x0c,
7671 RR_OR = 0x0d,
7672 RR_XOR = 0x0e,
7673 RR_NOT = 0x0f,
7674 RR_MFHI = 0x10,
7675 RR_CNVT = 0x11,
7676 RR_MFLO = 0x12,
7677 RR_DSRA = 0x13,
7678 RR_DSLLV = 0x14,
7679 RR_DSRLV = 0x16,
7680 RR_DSRAV = 0x17,
7681 RR_MULT = 0x18,
7682 RR_MULTU = 0x19,
7683 RR_DIV = 0x1a,
7684 RR_DIVU = 0x1b,
7685 RR_DMULT = 0x1c,
7686 RR_DMULTU = 0x1d,
7687 RR_DDIV = 0x1e,
7688 RR_DDIVU = 0x1f
7691 /* I64 funct field */
7692 enum {
7693 I64_LDSP = 0x0,
7694 I64_SDSP = 0x1,
7695 I64_SDRASP = 0x2,
7696 I64_DADJSP = 0x3,
7697 I64_LDPC = 0x4,
7698 I64_DADDIU5 = 0x5,
7699 I64_DADDIUPC = 0x6,
7700 I64_DADDIUSP = 0x7
7703 /* RR ry field for CNVT */
7704 enum {
7705 RR_RY_CNVT_ZEB = 0x0,
7706 RR_RY_CNVT_ZEH = 0x1,
7707 RR_RY_CNVT_ZEW = 0x2,
7708 RR_RY_CNVT_SEB = 0x4,
7709 RR_RY_CNVT_SEH = 0x5,
7710 RR_RY_CNVT_SEW = 0x6,
7713 static int xlat (int r)
7715 static int map[] = { 16, 17, 2, 3, 4, 5, 6, 7 };
7717 return map[r];
7720 static void gen_mips16_save (DisasContext *ctx,
7721 int xsregs, int aregs,
7722 int do_ra, int do_s0, int do_s1,
7723 int framesize)
7725 TCGv t0 = tcg_temp_new();
7726 TCGv t1 = tcg_temp_new();
7727 int args, astatic;
7729 switch (aregs) {
7730 case 0:
7731 case 1:
7732 case 2:
7733 case 3:
7734 case 11:
7735 args = 0;
7736 break;
7737 case 4:
7738 case 5:
7739 case 6:
7740 case 7:
7741 args = 1;
7742 break;
7743 case 8:
7744 case 9:
7745 case 10:
7746 args = 2;
7747 break;
7748 case 12:
7749 case 13:
7750 args = 3;
7751 break;
7752 case 14:
7753 args = 4;
7754 break;
7755 default:
7756 generate_exception(ctx, EXCP_RI);
7757 return;
7760 switch (args) {
7761 case 4:
7762 gen_base_offset_addr(ctx, t0, 29, 12);
7763 gen_load_gpr(t1, 7);
7764 op_ldst_sw(t1, t0, ctx);
7765 /* Fall through */
7766 case 3:
7767 gen_base_offset_addr(ctx, t0, 29, 8);
7768 gen_load_gpr(t1, 6);
7769 op_ldst_sw(t1, t0, ctx);
7770 /* Fall through */
7771 case 2:
7772 gen_base_offset_addr(ctx, t0, 29, 4);
7773 gen_load_gpr(t1, 5);
7774 op_ldst_sw(t1, t0, ctx);
7775 /* Fall through */
7776 case 1:
7777 gen_base_offset_addr(ctx, t0, 29, 0);
7778 gen_load_gpr(t1, 4);
7779 op_ldst_sw(t1, t0, ctx);
7782 gen_load_gpr(t0, 29);
7784 #define DECR_AND_STORE(reg) do { \
7785 tcg_gen_subi_tl(t0, t0, 4); \
7786 gen_load_gpr(t1, reg); \
7787 op_ldst_sw(t1, t0, ctx); \
7788 } while (0)
7790 if (do_ra) {
7791 DECR_AND_STORE(31);
7794 switch (xsregs) {
7795 case 7:
7796 DECR_AND_STORE(30);
7797 /* Fall through */
7798 case 6:
7799 DECR_AND_STORE(23);
7800 /* Fall through */
7801 case 5:
7802 DECR_AND_STORE(22);
7803 /* Fall through */
7804 case 4:
7805 DECR_AND_STORE(21);
7806 /* Fall through */
7807 case 3:
7808 DECR_AND_STORE(20);
7809 /* Fall through */
7810 case 2:
7811 DECR_AND_STORE(19);
7812 /* Fall through */
7813 case 1:
7814 DECR_AND_STORE(18);
7817 if (do_s1) {
7818 DECR_AND_STORE(17);
7820 if (do_s0) {
7821 DECR_AND_STORE(16);
7824 switch (aregs) {
7825 case 0:
7826 case 4:
7827 case 8:
7828 case 12:
7829 case 14:
7830 astatic = 0;
7831 break;
7832 case 1:
7833 case 5:
7834 case 9:
7835 case 13:
7836 astatic = 1;
7837 break;
7838 case 2:
7839 case 6:
7840 case 10:
7841 astatic = 2;
7842 break;
7843 case 3:
7844 case 7:
7845 astatic = 3;
7846 break;
7847 case 11:
7848 astatic = 4;
7849 break;
7850 default:
7851 generate_exception(ctx, EXCP_RI);
7852 return;
7855 if (astatic > 0) {
7856 DECR_AND_STORE(7);
7857 if (astatic > 1) {
7858 DECR_AND_STORE(6);
7859 if (astatic > 2) {
7860 DECR_AND_STORE(5);
7861 if (astatic > 3) {
7862 DECR_AND_STORE(4);
7867 #undef DECR_AND_STORE
7869 tcg_gen_subi_tl(cpu_gpr[29], cpu_gpr[29], framesize);
7870 tcg_temp_free(t0);
7871 tcg_temp_free(t1);
7874 static void gen_mips16_restore (DisasContext *ctx,
7875 int xsregs, int aregs,
7876 int do_ra, int do_s0, int do_s1,
7877 int framesize)
7879 int astatic;
7880 TCGv t0 = tcg_temp_new();
7881 TCGv t1 = tcg_temp_new();
7883 tcg_gen_addi_tl(t0, cpu_gpr[29], framesize);
7885 #define DECR_AND_LOAD(reg) do { \
7886 tcg_gen_subi_tl(t0, t0, 4); \
7887 op_ldst_lw(t1, t0, ctx); \
7888 gen_store_gpr(t1, reg); \
7889 } while (0)
7891 if (do_ra) {
7892 DECR_AND_LOAD(31);
7895 switch (xsregs) {
7896 case 7:
7897 DECR_AND_LOAD(30);
7898 /* Fall through */
7899 case 6:
7900 DECR_AND_LOAD(23);
7901 /* Fall through */
7902 case 5:
7903 DECR_AND_LOAD(22);
7904 /* Fall through */
7905 case 4:
7906 DECR_AND_LOAD(21);
7907 /* Fall through */
7908 case 3:
7909 DECR_AND_LOAD(20);
7910 /* Fall through */
7911 case 2:
7912 DECR_AND_LOAD(19);
7913 /* Fall through */
7914 case 1:
7915 DECR_AND_LOAD(18);
7918 if (do_s1) {
7919 DECR_AND_LOAD(17);
7921 if (do_s0) {
7922 DECR_AND_LOAD(16);
7925 switch (aregs) {
7926 case 0:
7927 case 4:
7928 case 8:
7929 case 12:
7930 case 14:
7931 astatic = 0;
7932 break;
7933 case 1:
7934 case 5:
7935 case 9:
7936 case 13:
7937 astatic = 1;
7938 break;
7939 case 2:
7940 case 6:
7941 case 10:
7942 astatic = 2;
7943 break;
7944 case 3:
7945 case 7:
7946 astatic = 3;
7947 break;
7948 case 11:
7949 astatic = 4;
7950 break;
7951 default:
7952 generate_exception(ctx, EXCP_RI);
7953 return;
7956 if (astatic > 0) {
7957 DECR_AND_LOAD(7);
7958 if (astatic > 1) {
7959 DECR_AND_LOAD(6);
7960 if (astatic > 2) {
7961 DECR_AND_LOAD(5);
7962 if (astatic > 3) {
7963 DECR_AND_LOAD(4);
7968 #undef DECR_AND_LOAD
7970 tcg_gen_addi_tl(cpu_gpr[29], cpu_gpr[29], framesize);
7971 tcg_temp_free(t0);
7972 tcg_temp_free(t1);
7975 static void gen_addiupc (DisasContext *ctx, int rx, int imm,
7976 int is_64_bit, int extended)
7978 TCGv t0;
7980 if (extended && (ctx->hflags & MIPS_HFLAG_BMASK)) {
7981 generate_exception(ctx, EXCP_RI);
7982 return;
7985 t0 = tcg_temp_new();
7987 tcg_gen_movi_tl(t0, pc_relative_pc(ctx));
7988 tcg_gen_addi_tl(cpu_gpr[rx], t0, imm);
7989 if (!is_64_bit) {
7990 tcg_gen_ext32s_tl(cpu_gpr[rx], cpu_gpr[rx]);
7993 tcg_temp_free(t0);
7996 #if defined(TARGET_MIPS64)
7997 static void decode_i64_mips16 (CPUState *env, DisasContext *ctx,
7998 int ry, int funct, int16_t offset,
7999 int extended)
8001 switch (funct) {
8002 case I64_LDSP:
8003 check_mips_64(ctx);
8004 offset = extended ? offset : offset << 3;
8005 gen_ldst(ctx, OPC_LD, ry, 29, offset);
8006 break;
8007 case I64_SDSP:
8008 check_mips_64(ctx);
8009 offset = extended ? offset : offset << 3;
8010 gen_ldst(ctx, OPC_SD, ry, 29, offset);
8011 break;
8012 case I64_SDRASP:
8013 check_mips_64(ctx);
8014 offset = extended ? offset : (ctx->opcode & 0xff) << 3;
8015 gen_ldst(ctx, OPC_SD, 31, 29, offset);
8016 break;
8017 case I64_DADJSP:
8018 check_mips_64(ctx);
8019 offset = extended ? offset : ((int8_t)ctx->opcode) << 3;
8020 gen_arith_imm(env, ctx, OPC_DADDIU, 29, 29, offset);
8021 break;
8022 case I64_LDPC:
8023 if (extended && (ctx->hflags & MIPS_HFLAG_BMASK)) {
8024 generate_exception(ctx, EXCP_RI);
8025 } else {
8026 offset = extended ? offset : offset << 3;
8027 gen_ldst(ctx, OPC_LDPC, ry, 0, offset);
8029 break;
8030 case I64_DADDIU5:
8031 check_mips_64(ctx);
8032 offset = extended ? offset : ((int8_t)(offset << 3)) >> 3;
8033 gen_arith_imm(env, ctx, OPC_DADDIU, ry, ry, offset);
8034 break;
8035 case I64_DADDIUPC:
8036 check_mips_64(ctx);
8037 offset = extended ? offset : offset << 2;
8038 gen_addiupc(ctx, ry, offset, 1, extended);
8039 break;
8040 case I64_DADDIUSP:
8041 check_mips_64(ctx);
8042 offset = extended ? offset : offset << 2;
8043 gen_arith_imm(env, ctx, OPC_DADDIU, ry, 29, offset);
8044 break;
8047 #endif
8049 static int decode_extended_mips16_opc (CPUState *env, DisasContext *ctx,
8050 int *is_branch)
8052 int extend = lduw_code(ctx->pc + 2);
8053 int op, rx, ry, funct, sa;
8054 int16_t imm, offset;
8056 ctx->opcode = (ctx->opcode << 16) | extend;
8057 op = (ctx->opcode >> 11) & 0x1f;
8058 sa = (ctx->opcode >> 22) & 0x1f;
8059 funct = (ctx->opcode >> 8) & 0x7;
8060 rx = xlat((ctx->opcode >> 8) & 0x7);
8061 ry = xlat((ctx->opcode >> 5) & 0x7);
8062 offset = imm = (int16_t) (((ctx->opcode >> 16) & 0x1f) << 11
8063 | ((ctx->opcode >> 21) & 0x3f) << 5
8064 | (ctx->opcode & 0x1f));
8066 /* The extended opcodes cleverly reuse the opcodes from their 16-bit
8067 counterparts. */
8068 switch (op) {
8069 case M16_OPC_ADDIUSP:
8070 gen_arith_imm(env, ctx, OPC_ADDIU, rx, 29, imm);
8071 break;
8072 case M16_OPC_ADDIUPC:
8073 gen_addiupc(ctx, rx, imm, 0, 1);
8074 break;
8075 case M16_OPC_B:
8076 gen_compute_branch(ctx, OPC_BEQ, 4, 0, 0, offset << 1);
8077 /* No delay slot, so just process as a normal instruction */
8078 break;
8079 case M16_OPC_BEQZ:
8080 gen_compute_branch(ctx, OPC_BEQ, 4, rx, 0, offset << 1);
8081 /* No delay slot, so just process as a normal instruction */
8082 break;
8083 case M16_OPC_BNEQZ:
8084 gen_compute_branch(ctx, OPC_BNE, 4, rx, 0, offset << 1);
8085 /* No delay slot, so just process as a normal instruction */
8086 break;
8087 case M16_OPC_SHIFT:
8088 switch (ctx->opcode & 0x3) {
8089 case 0x0:
8090 gen_shift_imm(env, ctx, OPC_SLL, rx, ry, sa);
8091 break;
8092 case 0x1:
8093 #if defined(TARGET_MIPS64)
8094 check_mips_64(ctx);
8095 gen_shift_imm(env, ctx, OPC_DSLL, rx, ry, sa);
8096 #else
8097 generate_exception(ctx, EXCP_RI);
8098 #endif
8099 break;
8100 case 0x2:
8101 gen_shift_imm(env, ctx, OPC_SRL, rx, ry, sa);
8102 break;
8103 case 0x3:
8104 gen_shift_imm(env, ctx, OPC_SRA, rx, ry, sa);
8105 break;
8107 break;
8108 #if defined(TARGET_MIPS64)
8109 case M16_OPC_LD:
8110 check_mips_64(ctx);
8111 gen_ldst(ctx, OPC_LD, ry, rx, offset);
8112 break;
8113 #endif
8114 case M16_OPC_RRIA:
8115 imm = ctx->opcode & 0xf;
8116 imm = imm | ((ctx->opcode >> 20) & 0x7f) << 4;
8117 imm = imm | ((ctx->opcode >> 16) & 0xf) << 11;
8118 imm = (int16_t) (imm << 1) >> 1;
8119 if ((ctx->opcode >> 4) & 0x1) {
8120 #if defined(TARGET_MIPS64)
8121 check_mips_64(ctx);
8122 gen_arith_imm(env, ctx, OPC_DADDIU, ry, rx, imm);
8123 #else
8124 generate_exception(ctx, EXCP_RI);
8125 #endif
8126 } else {
8127 gen_arith_imm(env, ctx, OPC_ADDIU, ry, rx, imm);
8129 break;
8130 case M16_OPC_ADDIU8:
8131 gen_arith_imm(env, ctx, OPC_ADDIU, rx, rx, imm);
8132 break;
8133 case M16_OPC_SLTI:
8134 gen_slt_imm(env, OPC_SLTI, 24, rx, imm);
8135 break;
8136 case M16_OPC_SLTIU:
8137 gen_slt_imm(env, OPC_SLTIU, 24, rx, imm);
8138 break;
8139 case M16_OPC_I8:
8140 switch (funct) {
8141 case I8_BTEQZ:
8142 gen_compute_branch(ctx, OPC_BEQ, 4, 24, 0, offset << 1);
8143 break;
8144 case I8_BTNEZ:
8145 gen_compute_branch(ctx, OPC_BNE, 4, 24, 0, offset << 1);
8146 break;
8147 case I8_SWRASP:
8148 gen_ldst(ctx, OPC_SW, 31, 29, imm);
8149 break;
8150 case I8_ADJSP:
8151 gen_arith_imm(env, ctx, OPC_ADDIU, 29, 29, imm);
8152 break;
8153 case I8_SVRS:
8155 int xsregs = (ctx->opcode >> 24) & 0x7;
8156 int aregs = (ctx->opcode >> 16) & 0xf;
8157 int do_ra = (ctx->opcode >> 6) & 0x1;
8158 int do_s0 = (ctx->opcode >> 5) & 0x1;
8159 int do_s1 = (ctx->opcode >> 4) & 0x1;
8160 int framesize = (((ctx->opcode >> 20) & 0xf) << 4
8161 | (ctx->opcode & 0xf)) << 3;
8163 if (ctx->opcode & (1 << 7)) {
8164 gen_mips16_save(ctx, xsregs, aregs,
8165 do_ra, do_s0, do_s1,
8166 framesize);
8167 } else {
8168 gen_mips16_restore(ctx, xsregs, aregs,
8169 do_ra, do_s0, do_s1,
8170 framesize);
8173 break;
8174 default:
8175 generate_exception(ctx, EXCP_RI);
8176 break;
8178 break;
8179 case M16_OPC_LI:
8180 tcg_gen_movi_tl(cpu_gpr[rx], (uint16_t) imm);
8181 break;
8182 case M16_OPC_CMPI:
8183 tcg_gen_xori_tl(cpu_gpr[24], cpu_gpr[rx], (uint16_t) imm);
8184 break;
8185 #if defined(TARGET_MIPS64)
8186 case M16_OPC_SD:
8187 gen_ldst(ctx, OPC_SD, ry, rx, offset);
8188 break;
8189 #endif
8190 case M16_OPC_LB:
8191 gen_ldst(ctx, OPC_LB, ry, rx, offset);
8192 break;
8193 case M16_OPC_LH:
8194 gen_ldst(ctx, OPC_LH, ry, rx, offset);
8195 break;
8196 case M16_OPC_LWSP:
8197 gen_ldst(ctx, OPC_LW, rx, 29, offset);
8198 break;
8199 case M16_OPC_LW:
8200 gen_ldst(ctx, OPC_LW, ry, rx, offset);
8201 break;
8202 case M16_OPC_LBU:
8203 gen_ldst(ctx, OPC_LBU, ry, rx, offset);
8204 break;
8205 case M16_OPC_LHU:
8206 gen_ldst(ctx, OPC_LHU, ry, rx, offset);
8207 break;
8208 case M16_OPC_LWPC:
8209 gen_ldst(ctx, OPC_LWPC, rx, 0, offset);
8210 break;
8211 #if defined(TARGET_MIPS64)
8212 case M16_OPC_LWU:
8213 gen_ldst(ctx, OPC_LWU, ry, rx, offset);
8214 break;
8215 #endif
8216 case M16_OPC_SB:
8217 gen_ldst(ctx, OPC_SB, ry, rx, offset);
8218 break;
8219 case M16_OPC_SH:
8220 gen_ldst(ctx, OPC_SH, ry, rx, offset);
8221 break;
8222 case M16_OPC_SWSP:
8223 gen_ldst(ctx, OPC_SW, rx, 29, offset);
8224 break;
8225 case M16_OPC_SW:
8226 gen_ldst(ctx, OPC_SW, ry, rx, offset);
8227 break;
8228 #if defined(TARGET_MIPS64)
8229 case M16_OPC_I64:
8230 decode_i64_mips16(env, ctx, ry, funct, offset, 1);
8231 break;
8232 #endif
8233 default:
8234 generate_exception(ctx, EXCP_RI);
8235 break;
8238 return 4;
8241 static int decode_mips16_opc (CPUState *env, DisasContext *ctx,
8242 int *is_branch)
8244 int rx, ry;
8245 int sa;
8246 int op, cnvt_op, op1, offset;
8247 int funct;
8248 int n_bytes;
8250 op = (ctx->opcode >> 11) & 0x1f;
8251 sa = (ctx->opcode >> 2) & 0x7;
8252 sa = sa == 0 ? 8 : sa;
8253 rx = xlat((ctx->opcode >> 8) & 0x7);
8254 cnvt_op = (ctx->opcode >> 5) & 0x7;
8255 ry = xlat((ctx->opcode >> 5) & 0x7);
8256 op1 = offset = ctx->opcode & 0x1f;
8258 n_bytes = 2;
8260 switch (op) {
8261 case M16_OPC_ADDIUSP:
8263 int16_t imm = ((uint8_t) ctx->opcode) << 2;
8265 gen_arith_imm(env, ctx, OPC_ADDIU, rx, 29, imm);
8267 break;
8268 case M16_OPC_ADDIUPC:
8269 gen_addiupc(ctx, rx, ((uint8_t) ctx->opcode) << 2, 0, 0);
8270 break;
8271 case M16_OPC_B:
8272 offset = (ctx->opcode & 0x7ff) << 1;
8273 offset = (int16_t)(offset << 4) >> 4;
8274 gen_compute_branch(ctx, OPC_BEQ, 2, 0, 0, offset);
8275 /* No delay slot, so just process as a normal instruction */
8276 break;
8277 case M16_OPC_JAL:
8278 offset = lduw_code(ctx->pc + 2);
8279 offset = (((ctx->opcode & 0x1f) << 21)
8280 | ((ctx->opcode >> 5) & 0x1f) << 16
8281 | offset) << 2;
8282 op = ((ctx->opcode >> 10) & 0x1) ? OPC_JALX : OPC_JAL;
8283 gen_compute_branch(ctx, op, 4, rx, ry, offset);
8284 n_bytes = 4;
8285 *is_branch = 1;
8286 break;
8287 case M16_OPC_BEQZ:
8288 gen_compute_branch(ctx, OPC_BEQ, 2, rx, 0, ((int8_t)ctx->opcode) << 1);
8289 /* No delay slot, so just process as a normal instruction */
8290 break;
8291 case M16_OPC_BNEQZ:
8292 gen_compute_branch(ctx, OPC_BNE, 2, rx, 0, ((int8_t)ctx->opcode) << 1);
8293 /* No delay slot, so just process as a normal instruction */
8294 break;
8295 case M16_OPC_SHIFT:
8296 switch (ctx->opcode & 0x3) {
8297 case 0x0:
8298 gen_shift_imm(env, ctx, OPC_SLL, rx, ry, sa);
8299 break;
8300 case 0x1:
8301 #if defined(TARGET_MIPS64)
8302 check_mips_64(ctx);
8303 gen_shift_imm(env, ctx, OPC_DSLL, rx, ry, sa);
8304 #else
8305 generate_exception(ctx, EXCP_RI);
8306 #endif
8307 break;
8308 case 0x2:
8309 gen_shift_imm(env, ctx, OPC_SRL, rx, ry, sa);
8310 break;
8311 case 0x3:
8312 gen_shift_imm(env, ctx, OPC_SRA, rx, ry, sa);
8313 break;
8315 break;
8316 #if defined(TARGET_MIPS64)
8317 case M16_OPC_LD:
8318 check_mips_64(ctx);
8319 gen_ldst(ctx, OPC_LD, ry, rx, offset << 3);
8320 break;
8321 #endif
8322 case M16_OPC_RRIA:
8324 int16_t imm = (int8_t)((ctx->opcode & 0xf) << 4) >> 4;
8326 if ((ctx->opcode >> 4) & 1) {
8327 #if defined(TARGET_MIPS64)
8328 check_mips_64(ctx);
8329 gen_arith_imm(env, ctx, OPC_DADDIU, ry, rx, imm);
8330 #else
8331 generate_exception(ctx, EXCP_RI);
8332 #endif
8333 } else {
8334 gen_arith_imm(env, ctx, OPC_ADDIU, ry, rx, imm);
8337 break;
8338 case M16_OPC_ADDIU8:
8340 int16_t imm = (int8_t) ctx->opcode;
8342 gen_arith_imm(env, ctx, OPC_ADDIU, rx, rx, imm);
8344 break;
8345 case M16_OPC_SLTI:
8347 int16_t imm = (uint8_t) ctx->opcode;
8349 gen_slt_imm(env, OPC_SLTI, 24, rx, imm);
8351 break;
8352 case M16_OPC_SLTIU:
8354 int16_t imm = (uint8_t) ctx->opcode;
8356 gen_slt_imm(env, OPC_SLTIU, 24, rx, imm);
8358 break;
8359 case M16_OPC_I8:
8361 int reg32;
8363 funct = (ctx->opcode >> 8) & 0x7;
8364 switch (funct) {
8365 case I8_BTEQZ:
8366 gen_compute_branch(ctx, OPC_BEQ, 2, 24, 0,
8367 ((int8_t)ctx->opcode) << 1);
8368 break;
8369 case I8_BTNEZ:
8370 gen_compute_branch(ctx, OPC_BNE, 2, 24, 0,
8371 ((int8_t)ctx->opcode) << 1);
8372 break;
8373 case I8_SWRASP:
8374 gen_ldst(ctx, OPC_SW, 31, 29, (ctx->opcode & 0xff) << 2);
8375 break;
8376 case I8_ADJSP:
8377 gen_arith_imm(env, ctx, OPC_ADDIU, 29, 29,
8378 ((int8_t)ctx->opcode) << 3);
8379 break;
8380 case I8_SVRS:
8382 int do_ra = ctx->opcode & (1 << 6);
8383 int do_s0 = ctx->opcode & (1 << 5);
8384 int do_s1 = ctx->opcode & (1 << 4);
8385 int framesize = ctx->opcode & 0xf;
8387 if (framesize == 0) {
8388 framesize = 128;
8389 } else {
8390 framesize = framesize << 3;
8393 if (ctx->opcode & (1 << 7)) {
8394 gen_mips16_save(ctx, 0, 0,
8395 do_ra, do_s0, do_s1, framesize);
8396 } else {
8397 gen_mips16_restore(ctx, 0, 0,
8398 do_ra, do_s0, do_s1, framesize);
8401 break;
8402 case I8_MOV32R:
8404 int rz = xlat(ctx->opcode & 0x7);
8406 reg32 = (((ctx->opcode >> 3) & 0x3) << 3) |
8407 ((ctx->opcode >> 5) & 0x7);
8408 gen_arith(env, ctx, OPC_ADDU, reg32, rz, 0);
8410 break;
8411 case I8_MOVR32:
8412 reg32 = ctx->opcode & 0x1f;
8413 gen_arith(env, ctx, OPC_ADDU, ry, reg32, 0);
8414 break;
8415 default:
8416 generate_exception(ctx, EXCP_RI);
8417 break;
8420 break;
8421 case M16_OPC_LI:
8423 int16_t imm = (uint8_t) ctx->opcode;
8425 gen_arith_imm(env, ctx, OPC_ADDIU, rx, 0, imm);
8427 break;
8428 case M16_OPC_CMPI:
8430 int16_t imm = (uint8_t) ctx->opcode;
8432 gen_logic_imm(env, OPC_XORI, 24, rx, imm);
8434 break;
8435 #if defined(TARGET_MIPS64)
8436 case M16_OPC_SD:
8437 check_mips_64(ctx);
8438 gen_ldst(ctx, OPC_SD, ry, rx, offset << 3);
8439 break;
8440 #endif
8441 case M16_OPC_LB:
8442 gen_ldst(ctx, OPC_LB, ry, rx, offset);
8443 break;
8444 case M16_OPC_LH:
8445 gen_ldst(ctx, OPC_LH, ry, rx, offset << 1);
8446 break;
8447 case M16_OPC_LWSP:
8448 gen_ldst(ctx, OPC_LW, rx, 29, ((uint8_t)ctx->opcode) << 2);
8449 break;
8450 case M16_OPC_LW:
8451 gen_ldst(ctx, OPC_LW, ry, rx, offset << 2);
8452 break;
8453 case M16_OPC_LBU:
8454 gen_ldst(ctx, OPC_LBU, ry, rx, offset);
8455 break;
8456 case M16_OPC_LHU:
8457 gen_ldst(ctx, OPC_LHU, ry, rx, offset << 1);
8458 break;
8459 case M16_OPC_LWPC:
8460 gen_ldst(ctx, OPC_LWPC, rx, 0, ((uint8_t)ctx->opcode) << 2);
8461 break;
8462 #if defined (TARGET_MIPS64)
8463 case M16_OPC_LWU:
8464 check_mips_64(ctx);
8465 gen_ldst(ctx, OPC_LWU, ry, rx, offset << 2);
8466 break;
8467 #endif
8468 case M16_OPC_SB:
8469 gen_ldst(ctx, OPC_SB, ry, rx, offset);
8470 break;
8471 case M16_OPC_SH:
8472 gen_ldst(ctx, OPC_SH, ry, rx, offset << 1);
8473 break;
8474 case M16_OPC_SWSP:
8475 gen_ldst(ctx, OPC_SW, rx, 29, ((uint8_t)ctx->opcode) << 2);
8476 break;
8477 case M16_OPC_SW:
8478 gen_ldst(ctx, OPC_SW, ry, rx, offset << 2);
8479 break;
8480 case M16_OPC_RRR:
8482 int rz = xlat((ctx->opcode >> 2) & 0x7);
8483 int mips32_op;
8485 switch (ctx->opcode & 0x3) {
8486 case RRR_ADDU:
8487 mips32_op = OPC_ADDU;
8488 break;
8489 case RRR_SUBU:
8490 mips32_op = OPC_SUBU;
8491 break;
8492 #if defined(TARGET_MIPS64)
8493 case RRR_DADDU:
8494 mips32_op = OPC_DADDU;
8495 check_mips_64(ctx);
8496 break;
8497 case RRR_DSUBU:
8498 mips32_op = OPC_DSUBU;
8499 check_mips_64(ctx);
8500 break;
8501 #endif
8502 default:
8503 generate_exception(ctx, EXCP_RI);
8504 goto done;
8507 gen_arith(env, ctx, mips32_op, rz, rx, ry);
8508 done:
8511 break;
8512 case M16_OPC_RR:
8513 switch (op1) {
8514 case RR_JR:
8516 int nd = (ctx->opcode >> 7) & 0x1;
8517 int link = (ctx->opcode >> 6) & 0x1;
8518 int ra = (ctx->opcode >> 5) & 0x1;
8520 if (link) {
8521 op = nd ? OPC_JALRC : OPC_JALR;
8522 } else {
8523 op = OPC_JR;
8526 gen_compute_branch(ctx, op, 2, ra ? 31 : rx, 31, 0);
8527 if (!nd) {
8528 *is_branch = 1;
8531 break;
8532 case RR_SDBBP:
8533 /* XXX: not clear which exception should be raised
8534 * when in debug mode...
8536 check_insn(env, ctx, ISA_MIPS32);
8537 if (!(ctx->hflags & MIPS_HFLAG_DM)) {
8538 generate_exception(ctx, EXCP_DBp);
8539 } else {
8540 generate_exception(ctx, EXCP_DBp);
8542 break;
8543 case RR_SLT:
8544 gen_slt(env, OPC_SLT, 24, rx, ry);
8545 break;
8546 case RR_SLTU:
8547 gen_slt(env, OPC_SLTU, 24, rx, ry);
8548 break;
8549 case RR_BREAK:
8550 generate_exception(ctx, EXCP_BREAK);
8551 break;
8552 case RR_SLLV:
8553 gen_shift(env, ctx, OPC_SLLV, ry, rx, ry);
8554 break;
8555 case RR_SRLV:
8556 gen_shift(env, ctx, OPC_SRLV, ry, rx, ry);
8557 break;
8558 case RR_SRAV:
8559 gen_shift(env, ctx, OPC_SRAV, ry, rx, ry);
8560 break;
8561 #if defined (TARGET_MIPS64)
8562 case RR_DSRL:
8563 check_mips_64(ctx);
8564 gen_shift_imm(env, ctx, OPC_DSRL, ry, ry, sa);
8565 break;
8566 #endif
8567 case RR_CMP:
8568 gen_logic(env, OPC_XOR, 24, rx, ry);
8569 break;
8570 case RR_NEG:
8571 gen_arith(env, ctx, OPC_SUBU, rx, 0, ry);
8572 break;
8573 case RR_AND:
8574 gen_logic(env, OPC_AND, rx, rx, ry);
8575 break;
8576 case RR_OR:
8577 gen_logic(env, OPC_OR, rx, rx, ry);
8578 break;
8579 case RR_XOR:
8580 gen_logic(env, OPC_XOR, rx, rx, ry);
8581 break;
8582 case RR_NOT:
8583 gen_logic(env, OPC_NOR, rx, ry, 0);
8584 break;
8585 case RR_MFHI:
8586 gen_HILO(ctx, OPC_MFHI, rx);
8587 break;
8588 case RR_CNVT:
8589 switch (cnvt_op) {
8590 case RR_RY_CNVT_ZEB:
8591 tcg_gen_ext8u_tl(cpu_gpr[rx], cpu_gpr[rx]);
8592 break;
8593 case RR_RY_CNVT_ZEH:
8594 tcg_gen_ext16u_tl(cpu_gpr[rx], cpu_gpr[rx]);
8595 break;
8596 case RR_RY_CNVT_SEB:
8597 tcg_gen_ext8s_tl(cpu_gpr[rx], cpu_gpr[rx]);
8598 break;
8599 case RR_RY_CNVT_SEH:
8600 tcg_gen_ext16s_tl(cpu_gpr[rx], cpu_gpr[rx]);
8601 break;
8602 #if defined (TARGET_MIPS64)
8603 case RR_RY_CNVT_ZEW:
8604 check_mips_64(ctx);
8605 tcg_gen_ext32u_tl(cpu_gpr[rx], cpu_gpr[rx]);
8606 break;
8607 case RR_RY_CNVT_SEW:
8608 check_mips_64(ctx);
8609 tcg_gen_ext32s_tl(cpu_gpr[rx], cpu_gpr[rx]);
8610 break;
8611 #endif
8612 default:
8613 generate_exception(ctx, EXCP_RI);
8614 break;
8616 break;
8617 case RR_MFLO:
8618 gen_HILO(ctx, OPC_MFLO, rx);
8619 break;
8620 #if defined (TARGET_MIPS64)
8621 case RR_DSRA:
8622 check_mips_64(ctx);
8623 gen_shift_imm(env, ctx, OPC_DSRA, ry, ry, sa);
8624 break;
8625 case RR_DSLLV:
8626 check_mips_64(ctx);
8627 gen_shift(env, ctx, OPC_DSLLV, ry, rx, ry);
8628 break;
8629 case RR_DSRLV:
8630 check_mips_64(ctx);
8631 gen_shift(env, ctx, OPC_DSRLV, ry, rx, ry);
8632 break;
8633 case RR_DSRAV:
8634 check_mips_64(ctx);
8635 gen_shift(env, ctx, OPC_DSRAV, ry, rx, ry);
8636 break;
8637 #endif
8638 case RR_MULT:
8639 gen_muldiv(ctx, OPC_MULT, rx, ry);
8640 break;
8641 case RR_MULTU:
8642 gen_muldiv(ctx, OPC_MULTU, rx, ry);
8643 break;
8644 case RR_DIV:
8645 gen_muldiv(ctx, OPC_DIV, rx, ry);
8646 break;
8647 case RR_DIVU:
8648 gen_muldiv(ctx, OPC_DIVU, rx, ry);
8649 break;
8650 #if defined (TARGET_MIPS64)
8651 case RR_DMULT:
8652 check_mips_64(ctx);
8653 gen_muldiv(ctx, OPC_DMULT, rx, ry);
8654 break;
8655 case RR_DMULTU:
8656 check_mips_64(ctx);
8657 gen_muldiv(ctx, OPC_DMULTU, rx, ry);
8658 break;
8659 case RR_DDIV:
8660 check_mips_64(ctx);
8661 gen_muldiv(ctx, OPC_DDIV, rx, ry);
8662 break;
8663 case RR_DDIVU:
8664 check_mips_64(ctx);
8665 gen_muldiv(ctx, OPC_DDIVU, rx, ry);
8666 break;
8667 #endif
8668 default:
8669 generate_exception(ctx, EXCP_RI);
8670 break;
8672 break;
8673 case M16_OPC_EXTEND:
8674 decode_extended_mips16_opc(env, ctx, is_branch);
8675 n_bytes = 4;
8676 break;
8677 #if defined(TARGET_MIPS64)
8678 case M16_OPC_I64:
8679 funct = (ctx->opcode >> 8) & 0x7;
8680 decode_i64_mips16(env, ctx, ry, funct, offset, 0);
8681 break;
8682 #endif
8683 default:
8684 generate_exception(ctx, EXCP_RI);
8685 break;
8688 return n_bytes;
8691 /* SmartMIPS extension to MIPS32 */
8693 #if defined(TARGET_MIPS64)
8695 /* MDMX extension to MIPS64 */
8697 #endif
8699 static void decode_opc (CPUState *env, DisasContext *ctx, int *is_branch)
8701 int32_t offset;
8702 int rs, rt, rd, sa;
8703 uint32_t op, op1, op2;
8704 int16_t imm;
8706 /* make sure instructions are on a word boundary */
8707 if (ctx->pc & 0x3) {
8708 env->CP0_BadVAddr = ctx->pc;
8709 generate_exception(ctx, EXCP_AdEL);
8710 return;
8713 /* Handle blikely not taken case */
8714 if ((ctx->hflags & MIPS_HFLAG_BMASK_BASE) == MIPS_HFLAG_BL) {
8715 int l1 = gen_new_label();
8717 MIPS_DEBUG("blikely condition (" TARGET_FMT_lx ")", ctx->pc + 4);
8718 tcg_gen_brcondi_tl(TCG_COND_NE, bcond, 0, l1);
8719 tcg_gen_movi_i32(hflags, ctx->hflags & ~MIPS_HFLAG_BMASK);
8720 gen_goto_tb(ctx, 1, ctx->pc + 4);
8721 gen_set_label(l1);
8724 if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP)))
8725 tcg_gen_debug_insn_start(ctx->pc);
8727 op = MASK_OP_MAJOR(ctx->opcode);
8728 rs = (ctx->opcode >> 21) & 0x1f;
8729 rt = (ctx->opcode >> 16) & 0x1f;
8730 rd = (ctx->opcode >> 11) & 0x1f;
8731 sa = (ctx->opcode >> 6) & 0x1f;
8732 imm = (int16_t)ctx->opcode;
8733 switch (op) {
8734 case OPC_SPECIAL:
8735 op1 = MASK_SPECIAL(ctx->opcode);
8736 switch (op1) {
8737 case OPC_SLL: /* Shift with immediate */
8738 case OPC_SRA:
8739 gen_shift_imm(env, ctx, op1, rd, rt, sa);
8740 break;
8741 case OPC_SRL:
8742 switch ((ctx->opcode >> 21) & 0x1f) {
8743 case 1:
8744 /* rotr is decoded as srl on non-R2 CPUs */
8745 if (env->insn_flags & ISA_MIPS32R2) {
8746 op1 = OPC_ROTR;
8748 /* Fallthrough */
8749 case 0:
8750 gen_shift_imm(env, ctx, op1, rd, rt, sa);
8751 break;
8752 default:
8753 generate_exception(ctx, EXCP_RI);
8754 break;
8756 break;
8757 case OPC_MOVN: /* Conditional move */
8758 case OPC_MOVZ:
8759 check_insn(env, ctx, ISA_MIPS4 | ISA_MIPS32);
8760 gen_cond_move(env, op1, rd, rs, rt);
8761 break;
8762 case OPC_ADD ... OPC_SUBU:
8763 gen_arith(env, ctx, op1, rd, rs, rt);
8764 break;
8765 case OPC_SLLV: /* Shifts */
8766 case OPC_SRAV:
8767 gen_shift(env, ctx, op1, rd, rs, rt);
8768 break;
8769 case OPC_SRLV:
8770 switch ((ctx->opcode >> 6) & 0x1f) {
8771 case 1:
8772 /* rotrv is decoded as srlv on non-R2 CPUs */
8773 if (env->insn_flags & ISA_MIPS32R2) {
8774 op1 = OPC_ROTRV;
8776 /* Fallthrough */
8777 case 0:
8778 gen_shift(env, ctx, op1, rd, rs, rt);
8779 break;
8780 default:
8781 generate_exception(ctx, EXCP_RI);
8782 break;
8784 break;
8785 case OPC_SLT: /* Set on less than */
8786 case OPC_SLTU:
8787 gen_slt(env, op1, rd, rs, rt);
8788 break;
8789 case OPC_AND: /* Logic*/
8790 case OPC_OR:
8791 case OPC_NOR:
8792 case OPC_XOR:
8793 gen_logic(env, op1, rd, rs, rt);
8794 break;
8795 case OPC_MULT ... OPC_DIVU:
8796 if (sa) {
8797 check_insn(env, ctx, INSN_VR54XX);
8798 op1 = MASK_MUL_VR54XX(ctx->opcode);
8799 gen_mul_vr54xx(ctx, op1, rd, rs, rt);
8800 } else
8801 gen_muldiv(ctx, op1, rs, rt);
8802 break;
8803 case OPC_JR ... OPC_JALR:
8804 gen_compute_branch(ctx, op1, 4, rs, rd, sa);
8805 *is_branch = 1;
8806 break;
8807 case OPC_TGE ... OPC_TEQ: /* Traps */
8808 case OPC_TNE:
8809 gen_trap(ctx, op1, rs, rt, -1);
8810 break;
8811 case OPC_MFHI: /* Move from HI/LO */
8812 case OPC_MFLO:
8813 gen_HILO(ctx, op1, rd);
8814 break;
8815 case OPC_MTHI:
8816 case OPC_MTLO: /* Move to HI/LO */
8817 gen_HILO(ctx, op1, rs);
8818 break;
8819 case OPC_PMON: /* Pmon entry point, also R4010 selsl */
8820 #ifdef MIPS_STRICT_STANDARD
8821 MIPS_INVAL("PMON / selsl");
8822 generate_exception(ctx, EXCP_RI);
8823 #else
8824 gen_helper_0i(pmon, sa);
8825 #endif
8826 break;
8827 case OPC_SYSCALL:
8828 generate_exception(ctx, EXCP_SYSCALL);
8829 ctx->bstate = BS_STOP;
8830 break;
8831 case OPC_BREAK:
8832 generate_exception(ctx, EXCP_BREAK);
8833 break;
8834 case OPC_SPIM:
8835 #ifdef MIPS_STRICT_STANDARD
8836 MIPS_INVAL("SPIM");
8837 generate_exception(ctx, EXCP_RI);
8838 #else
8839 /* Implemented as RI exception for now. */
8840 MIPS_INVAL("spim (unofficial)");
8841 generate_exception(ctx, EXCP_RI);
8842 #endif
8843 break;
8844 case OPC_SYNC:
8845 /* Treat as NOP. */
8846 break;
8848 case OPC_MOVCI:
8849 check_insn(env, ctx, ISA_MIPS4 | ISA_MIPS32);
8850 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
8851 check_cp1_enabled(ctx);
8852 gen_movci(ctx, rd, rs, (ctx->opcode >> 18) & 0x7,
8853 (ctx->opcode >> 16) & 1);
8854 } else {
8855 generate_exception_err(ctx, EXCP_CpU, 1);
8857 break;
8859 #if defined(TARGET_MIPS64)
8860 /* MIPS64 specific opcodes */
8861 case OPC_DSLL:
8862 case OPC_DSRA:
8863 case OPC_DSLL32:
8864 case OPC_DSRA32:
8865 check_insn(env, ctx, ISA_MIPS3);
8866 check_mips_64(ctx);
8867 gen_shift_imm(env, ctx, op1, rd, rt, sa);
8868 break;
8869 case OPC_DSRL:
8870 switch ((ctx->opcode >> 21) & 0x1f) {
8871 case 1:
8872 /* drotr is decoded as dsrl on non-R2 CPUs */
8873 if (env->insn_flags & ISA_MIPS32R2) {
8874 op1 = OPC_DROTR;
8876 /* Fallthrough */
8877 case 0:
8878 check_insn(env, ctx, ISA_MIPS3);
8879 check_mips_64(ctx);
8880 gen_shift_imm(env, ctx, op1, rd, rt, sa);
8881 break;
8882 default:
8883 generate_exception(ctx, EXCP_RI);
8884 break;
8886 break;
8887 case OPC_DSRL32:
8888 switch ((ctx->opcode >> 21) & 0x1f) {
8889 case 1:
8890 /* drotr32 is decoded as dsrl32 on non-R2 CPUs */
8891 if (env->insn_flags & ISA_MIPS32R2) {
8892 op1 = OPC_DROTR32;
8894 /* Fallthrough */
8895 case 0:
8896 check_insn(env, ctx, ISA_MIPS3);
8897 check_mips_64(ctx);
8898 gen_shift_imm(env, ctx, op1, rd, rt, sa);
8899 break;
8900 default:
8901 generate_exception(ctx, EXCP_RI);
8902 break;
8904 break;
8905 case OPC_DADD ... OPC_DSUBU:
8906 check_insn(env, ctx, ISA_MIPS3);
8907 check_mips_64(ctx);
8908 gen_arith(env, ctx, op1, rd, rs, rt);
8909 break;
8910 case OPC_DSLLV:
8911 case OPC_DSRAV:
8912 check_insn(env, ctx, ISA_MIPS3);
8913 check_mips_64(ctx);
8914 gen_shift(env, ctx, op1, rd, rs, rt);
8915 break;
8916 case OPC_DSRLV:
8917 switch ((ctx->opcode >> 6) & 0x1f) {
8918 case 1:
8919 /* drotrv is decoded as dsrlv on non-R2 CPUs */
8920 if (env->insn_flags & ISA_MIPS32R2) {
8921 op1 = OPC_DROTRV;
8923 /* Fallthrough */
8924 case 0:
8925 check_insn(env, ctx, ISA_MIPS3);
8926 check_mips_64(ctx);
8927 gen_shift(env, ctx, op1, rd, rs, rt);
8928 break;
8929 default:
8930 generate_exception(ctx, EXCP_RI);
8931 break;
8933 break;
8934 case OPC_DMULT ... OPC_DDIVU:
8935 check_insn(env, ctx, ISA_MIPS3);
8936 check_mips_64(ctx);
8937 gen_muldiv(ctx, op1, rs, rt);
8938 break;
8939 #endif
8940 default: /* Invalid */
8941 MIPS_INVAL("special");
8942 generate_exception(ctx, EXCP_RI);
8943 break;
8945 break;
8946 case OPC_SPECIAL2:
8947 op1 = MASK_SPECIAL2(ctx->opcode);
8948 switch (op1) {
8949 case OPC_MADD ... OPC_MADDU: /* Multiply and add/sub */
8950 case OPC_MSUB ... OPC_MSUBU:
8951 check_insn(env, ctx, ISA_MIPS32);
8952 gen_muldiv(ctx, op1, rs, rt);
8953 break;
8954 case OPC_MUL:
8955 gen_arith(env, ctx, op1, rd, rs, rt);
8956 break;
8957 case OPC_CLO:
8958 case OPC_CLZ:
8959 check_insn(env, ctx, ISA_MIPS32);
8960 gen_cl(ctx, op1, rd, rs);
8961 break;
8962 case OPC_SDBBP:
8963 /* XXX: not clear which exception should be raised
8964 * when in debug mode...
8966 check_insn(env, ctx, ISA_MIPS32);
8967 if (!(ctx->hflags & MIPS_HFLAG_DM)) {
8968 generate_exception(ctx, EXCP_DBp);
8969 } else {
8970 generate_exception(ctx, EXCP_DBp);
8972 /* Treat as NOP. */
8973 break;
8974 #if defined(TARGET_MIPS64)
8975 case OPC_DCLO:
8976 case OPC_DCLZ:
8977 check_insn(env, ctx, ISA_MIPS64);
8978 check_mips_64(ctx);
8979 gen_cl(ctx, op1, rd, rs);
8980 break;
8981 #endif
8982 default: /* Invalid */
8983 MIPS_INVAL("special2");
8984 generate_exception(ctx, EXCP_RI);
8985 break;
8987 break;
8988 case OPC_SPECIAL3:
8989 op1 = MASK_SPECIAL3(ctx->opcode);
8990 switch (op1) {
8991 case OPC_EXT:
8992 case OPC_INS:
8993 check_insn(env, ctx, ISA_MIPS32R2);
8994 gen_bitops(ctx, op1, rt, rs, sa, rd);
8995 break;
8996 case OPC_BSHFL:
8997 check_insn(env, ctx, ISA_MIPS32R2);
8998 op2 = MASK_BSHFL(ctx->opcode);
8999 gen_bshfl(ctx, op2, rt, rd);
9000 break;
9001 case OPC_RDHWR:
9002 check_insn(env, ctx, ISA_MIPS32R2);
9004 TCGv t0 = tcg_temp_new();
9006 switch (rd) {
9007 case 0:
9008 save_cpu_state(ctx, 1);
9009 gen_helper_rdhwr_cpunum(t0);
9010 gen_store_gpr(t0, rt);
9011 break;
9012 case 1:
9013 save_cpu_state(ctx, 1);
9014 gen_helper_rdhwr_synci_step(t0);
9015 gen_store_gpr(t0, rt);
9016 break;
9017 case 2:
9018 save_cpu_state(ctx, 1);
9019 gen_helper_rdhwr_cc(t0);
9020 gen_store_gpr(t0, rt);
9021 break;
9022 case 3:
9023 save_cpu_state(ctx, 1);
9024 gen_helper_rdhwr_ccres(t0);
9025 gen_store_gpr(t0, rt);
9026 break;
9027 case 29:
9028 #if defined(CONFIG_USER_ONLY)
9029 tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUState, tls_value));
9030 gen_store_gpr(t0, rt);
9031 break;
9032 #else
9033 /* XXX: Some CPUs implement this in hardware.
9034 Not supported yet. */
9035 #endif
9036 default: /* Invalid */
9037 MIPS_INVAL("rdhwr");
9038 generate_exception(ctx, EXCP_RI);
9039 break;
9041 tcg_temp_free(t0);
9043 break;
9044 case OPC_FORK:
9045 check_insn(env, ctx, ASE_MT);
9047 TCGv t0 = tcg_temp_new();
9048 TCGv t1 = tcg_temp_new();
9050 gen_load_gpr(t0, rt);
9051 gen_load_gpr(t1, rs);
9052 gen_helper_fork(t0, t1);
9053 tcg_temp_free(t0);
9054 tcg_temp_free(t1);
9056 break;
9057 case OPC_YIELD:
9058 check_insn(env, ctx, ASE_MT);
9060 TCGv t0 = tcg_temp_new();
9062 save_cpu_state(ctx, 1);
9063 gen_load_gpr(t0, rs);
9064 gen_helper_yield(t0, t0);
9065 gen_store_gpr(t0, rd);
9066 tcg_temp_free(t0);
9068 break;
9069 #if defined(TARGET_MIPS64)
9070 case OPC_DEXTM ... OPC_DEXT:
9071 case OPC_DINSM ... OPC_DINS:
9072 check_insn(env, ctx, ISA_MIPS64R2);
9073 check_mips_64(ctx);
9074 gen_bitops(ctx, op1, rt, rs, sa, rd);
9075 break;
9076 case OPC_DBSHFL:
9077 check_insn(env, ctx, ISA_MIPS64R2);
9078 check_mips_64(ctx);
9079 op2 = MASK_DBSHFL(ctx->opcode);
9080 gen_bshfl(ctx, op2, rt, rd);
9081 break;
9082 #endif
9083 default: /* Invalid */
9084 MIPS_INVAL("special3");
9085 generate_exception(ctx, EXCP_RI);
9086 break;
9088 break;
9089 case OPC_REGIMM:
9090 op1 = MASK_REGIMM(ctx->opcode);
9091 switch (op1) {
9092 case OPC_BLTZ ... OPC_BGEZL: /* REGIMM branches */
9093 case OPC_BLTZAL ... OPC_BGEZALL:
9094 gen_compute_branch(ctx, op1, 4, rs, -1, imm << 2);
9095 *is_branch = 1;
9096 break;
9097 case OPC_TGEI ... OPC_TEQI: /* REGIMM traps */
9098 case OPC_TNEI:
9099 gen_trap(ctx, op1, rs, -1, imm);
9100 break;
9101 case OPC_SYNCI:
9102 check_insn(env, ctx, ISA_MIPS32R2);
9103 /* Treat as NOP. */
9104 break;
9105 default: /* Invalid */
9106 MIPS_INVAL("regimm");
9107 generate_exception(ctx, EXCP_RI);
9108 break;
9110 break;
9111 case OPC_CP0:
9112 check_cp0_enabled(ctx);
9113 op1 = MASK_CP0(ctx->opcode);
9114 switch (op1) {
9115 case OPC_MFC0:
9116 case OPC_MTC0:
9117 case OPC_MFTR:
9118 case OPC_MTTR:
9119 #if defined(TARGET_MIPS64)
9120 case OPC_DMFC0:
9121 case OPC_DMTC0:
9122 #endif
9123 #ifndef CONFIG_USER_ONLY
9124 gen_cp0(env, ctx, op1, rt, rd);
9125 #endif /* !CONFIG_USER_ONLY */
9126 break;
9127 case OPC_C0_FIRST ... OPC_C0_LAST:
9128 #ifndef CONFIG_USER_ONLY
9129 gen_cp0(env, ctx, MASK_C0(ctx->opcode), rt, rd);
9130 #endif /* !CONFIG_USER_ONLY */
9131 break;
9132 case OPC_MFMC0:
9133 #ifndef CONFIG_USER_ONLY
9135 TCGv t0 = tcg_temp_new();
9137 op2 = MASK_MFMC0(ctx->opcode);
9138 switch (op2) {
9139 case OPC_DMT:
9140 check_insn(env, ctx, ASE_MT);
9141 gen_helper_dmt(t0, t0);
9142 gen_store_gpr(t0, rt);
9143 break;
9144 case OPC_EMT:
9145 check_insn(env, ctx, ASE_MT);
9146 gen_helper_emt(t0, t0);
9147 gen_store_gpr(t0, rt);
9148 break;
9149 case OPC_DVPE:
9150 check_insn(env, ctx, ASE_MT);
9151 gen_helper_dvpe(t0, t0);
9152 gen_store_gpr(t0, rt);
9153 break;
9154 case OPC_EVPE:
9155 check_insn(env, ctx, ASE_MT);
9156 gen_helper_evpe(t0, t0);
9157 gen_store_gpr(t0, rt);
9158 break;
9159 case OPC_DI:
9160 check_insn(env, ctx, ISA_MIPS32R2);
9161 save_cpu_state(ctx, 1);
9162 gen_helper_di(t0);
9163 gen_store_gpr(t0, rt);
9164 /* Stop translation as we may have switched the execution mode */
9165 ctx->bstate = BS_STOP;
9166 break;
9167 case OPC_EI:
9168 check_insn(env, ctx, ISA_MIPS32R2);
9169 save_cpu_state(ctx, 1);
9170 gen_helper_ei(t0);
9171 gen_store_gpr(t0, rt);
9172 /* Stop translation as we may have switched the execution mode */
9173 ctx->bstate = BS_STOP;
9174 break;
9175 default: /* Invalid */
9176 MIPS_INVAL("mfmc0");
9177 generate_exception(ctx, EXCP_RI);
9178 break;
9180 tcg_temp_free(t0);
9182 #endif /* !CONFIG_USER_ONLY */
9183 break;
9184 case OPC_RDPGPR:
9185 check_insn(env, ctx, ISA_MIPS32R2);
9186 gen_load_srsgpr(rt, rd);
9187 break;
9188 case OPC_WRPGPR:
9189 check_insn(env, ctx, ISA_MIPS32R2);
9190 gen_store_srsgpr(rt, rd);
9191 break;
9192 default:
9193 MIPS_INVAL("cp0");
9194 generate_exception(ctx, EXCP_RI);
9195 break;
9197 break;
9198 case OPC_ADDI: /* Arithmetic with immediate opcode */
9199 case OPC_ADDIU:
9200 gen_arith_imm(env, ctx, op, rt, rs, imm);
9201 break;
9202 case OPC_SLTI: /* Set on less than with immediate opcode */
9203 case OPC_SLTIU:
9204 gen_slt_imm(env, op, rt, rs, imm);
9205 break;
9206 case OPC_ANDI: /* Arithmetic with immediate opcode */
9207 case OPC_LUI:
9208 case OPC_ORI:
9209 case OPC_XORI:
9210 gen_logic_imm(env, op, rt, rs, imm);
9211 break;
9212 case OPC_J ... OPC_JAL: /* Jump */
9213 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2;
9214 gen_compute_branch(ctx, op, 4, rs, rt, offset);
9215 *is_branch = 1;
9216 break;
9217 case OPC_BEQ ... OPC_BGTZ: /* Branch */
9218 case OPC_BEQL ... OPC_BGTZL:
9219 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2);
9220 *is_branch = 1;
9221 break;
9222 case OPC_LB ... OPC_LWR: /* Load and stores */
9223 case OPC_SB ... OPC_SW:
9224 case OPC_SWR:
9225 case OPC_LL:
9226 gen_ldst(ctx, op, rt, rs, imm);
9227 break;
9228 case OPC_SC:
9229 gen_st_cond(ctx, op, rt, rs, imm);
9230 break;
9231 case OPC_CACHE:
9232 check_insn(env, ctx, ISA_MIPS3 | ISA_MIPS32);
9233 /* Treat as NOP. */
9234 break;
9235 case OPC_PREF:
9236 check_insn(env, ctx, ISA_MIPS4 | ISA_MIPS32);
9237 /* Treat as NOP. */
9238 break;
9240 /* Floating point (COP1). */
9241 case OPC_LWC1:
9242 case OPC_LDC1:
9243 case OPC_SWC1:
9244 case OPC_SDC1:
9245 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
9246 check_cp1_enabled(ctx);
9247 gen_flt_ldst(ctx, op, rt, rs, imm);
9248 } else {
9249 generate_exception_err(ctx, EXCP_CpU, 1);
9251 break;
9253 case OPC_CP1:
9254 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
9255 check_cp1_enabled(ctx);
9256 op1 = MASK_CP1(ctx->opcode);
9257 switch (op1) {
9258 case OPC_MFHC1:
9259 case OPC_MTHC1:
9260 check_insn(env, ctx, ISA_MIPS32R2);
9261 case OPC_MFC1:
9262 case OPC_CFC1:
9263 case OPC_MTC1:
9264 case OPC_CTC1:
9265 gen_cp1(ctx, op1, rt, rd);
9266 break;
9267 #if defined(TARGET_MIPS64)
9268 case OPC_DMFC1:
9269 case OPC_DMTC1:
9270 check_insn(env, ctx, ISA_MIPS3);
9271 gen_cp1(ctx, op1, rt, rd);
9272 break;
9273 #endif
9274 case OPC_BC1ANY2:
9275 case OPC_BC1ANY4:
9276 check_cop1x(ctx);
9277 check_insn(env, ctx, ASE_MIPS3D);
9278 /* fall through */
9279 case OPC_BC1:
9280 gen_compute_branch1(env, ctx, MASK_BC1(ctx->opcode),
9281 (rt >> 2) & 0x7, imm << 2);
9282 *is_branch = 1;
9283 break;
9284 case OPC_S_FMT:
9285 case OPC_D_FMT:
9286 case OPC_W_FMT:
9287 case OPC_L_FMT:
9288 case OPC_PS_FMT:
9289 gen_farith(ctx, MASK_CP1_FUNC(ctx->opcode), rt, rd, sa,
9290 (imm >> 8) & 0x7);
9291 break;
9292 default:
9293 MIPS_INVAL("cp1");
9294 generate_exception (ctx, EXCP_RI);
9295 break;
9297 } else {
9298 generate_exception_err(ctx, EXCP_CpU, 1);
9300 break;
9302 /* COP2. */
9303 case OPC_LWC2:
9304 case OPC_LDC2:
9305 case OPC_SWC2:
9306 case OPC_SDC2:
9307 case OPC_CP2:
9308 /* COP2: Not implemented. */
9309 generate_exception_err(ctx, EXCP_CpU, 2);
9310 break;
9312 case OPC_CP3:
9313 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
9314 check_cp1_enabled(ctx);
9315 op1 = MASK_CP3(ctx->opcode);
9316 switch (op1) {
9317 case OPC_LWXC1:
9318 case OPC_LDXC1:
9319 case OPC_LUXC1:
9320 case OPC_SWXC1:
9321 case OPC_SDXC1:
9322 case OPC_SUXC1:
9323 gen_flt3_ldst(ctx, op1, sa, rd, rs, rt);
9324 break;
9325 case OPC_PREFX:
9326 /* Treat as NOP. */
9327 break;
9328 case OPC_ALNV_PS:
9329 case OPC_MADD_S:
9330 case OPC_MADD_D:
9331 case OPC_MADD_PS:
9332 case OPC_MSUB_S:
9333 case OPC_MSUB_D:
9334 case OPC_MSUB_PS:
9335 case OPC_NMADD_S:
9336 case OPC_NMADD_D:
9337 case OPC_NMADD_PS:
9338 case OPC_NMSUB_S:
9339 case OPC_NMSUB_D:
9340 case OPC_NMSUB_PS:
9341 gen_flt3_arith(ctx, op1, sa, rs, rd, rt);
9342 break;
9343 default:
9344 MIPS_INVAL("cp3");
9345 generate_exception (ctx, EXCP_RI);
9346 break;
9348 } else {
9349 generate_exception_err(ctx, EXCP_CpU, 1);
9351 break;
9353 #if defined(TARGET_MIPS64)
9354 /* MIPS64 opcodes */
9355 case OPC_LWU:
9356 case OPC_LDL ... OPC_LDR:
9357 case OPC_SDL ... OPC_SDR:
9358 case OPC_LLD:
9359 case OPC_LD:
9360 case OPC_SD:
9361 check_insn(env, ctx, ISA_MIPS3);
9362 check_mips_64(ctx);
9363 gen_ldst(ctx, op, rt, rs, imm);
9364 break;
9365 case OPC_SCD:
9366 check_insn(env, ctx, ISA_MIPS3);
9367 check_mips_64(ctx);
9368 gen_st_cond(ctx, op, rt, rs, imm);
9369 break;
9370 case OPC_DADDI:
9371 case OPC_DADDIU:
9372 check_insn(env, ctx, ISA_MIPS3);
9373 check_mips_64(ctx);
9374 gen_arith_imm(env, ctx, op, rt, rs, imm);
9375 break;
9376 #endif
9377 case OPC_JALX:
9378 check_insn(env, ctx, ASE_MIPS16);
9379 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2;
9380 gen_compute_branch(ctx, op, 4, rs, rt, offset);
9381 *is_branch = 1;
9382 break;
9383 case OPC_MDMX:
9384 check_insn(env, ctx, ASE_MDMX);
9385 /* MDMX: Not implemented. */
9386 default: /* Invalid */
9387 MIPS_INVAL("major opcode");
9388 generate_exception(ctx, EXCP_RI);
9389 break;
9393 static inline void
9394 gen_intermediate_code_internal (CPUState *env, TranslationBlock *tb,
9395 int search_pc)
9397 DisasContext ctx;
9398 target_ulong pc_start;
9399 uint16_t *gen_opc_end;
9400 CPUBreakpoint *bp;
9401 int j, lj = -1;
9402 int num_insns;
9403 int max_insns;
9404 int insn_bytes;
9405 int is_branch;
9407 if (search_pc)
9408 qemu_log("search pc %d\n", search_pc);
9410 pc_start = tb->pc;
9411 gen_opc_end = gen_opc_buf + OPC_MAX_SIZE;
9412 ctx.pc = pc_start;
9413 ctx.saved_pc = -1;
9414 ctx.singlestep_enabled = env->singlestep_enabled;
9415 ctx.tb = tb;
9416 ctx.bstate = BS_NONE;
9417 /* Restore delay slot state from the tb context. */
9418 ctx.hflags = (uint32_t)tb->flags; /* FIXME: maybe use 64 bits here? */
9419 restore_cpu_state(env, &ctx);
9420 #ifdef CONFIG_USER_ONLY
9421 ctx.mem_idx = MIPS_HFLAG_UM;
9422 #else
9423 ctx.mem_idx = ctx.hflags & MIPS_HFLAG_KSU;
9424 #endif
9425 num_insns = 0;
9426 max_insns = tb->cflags & CF_COUNT_MASK;
9427 if (max_insns == 0)
9428 max_insns = CF_COUNT_MASK;
9429 #ifdef DEBUG_DISAS
9430 qemu_log_mask(CPU_LOG_TB_CPU, "------------------------------------------------\n");
9431 /* FIXME: This may print out stale hflags from env... */
9432 log_cpu_state_mask(CPU_LOG_TB_CPU, env, 0);
9433 #endif
9434 LOG_DISAS("\ntb %p idx %d hflags %04x\n", tb, ctx.mem_idx, ctx.hflags);
9435 gen_icount_start();
9436 while (ctx.bstate == BS_NONE) {
9437 if (unlikely(!QTAILQ_EMPTY(&env->breakpoints))) {
9438 QTAILQ_FOREACH(bp, &env->breakpoints, entry) {
9439 if (bp->pc == ctx.pc) {
9440 save_cpu_state(&ctx, 1);
9441 ctx.bstate = BS_BRANCH;
9442 gen_helper_0i(raise_exception, EXCP_DEBUG);
9443 /* Include the breakpoint location or the tb won't
9444 * be flushed when it must be. */
9445 ctx.pc += 4;
9446 goto done_generating;
9451 if (search_pc) {
9452 j = gen_opc_ptr - gen_opc_buf;
9453 if (lj < j) {
9454 lj++;
9455 while (lj < j)
9456 gen_opc_instr_start[lj++] = 0;
9458 gen_opc_pc[lj] = ctx.pc;
9459 gen_opc_hflags[lj] = ctx.hflags & MIPS_HFLAG_BMASK;
9460 gen_opc_instr_start[lj] = 1;
9461 gen_opc_icount[lj] = num_insns;
9463 if (num_insns + 1 == max_insns && (tb->cflags & CF_LAST_IO))
9464 gen_io_start();
9466 is_branch = 0;
9467 if (!(ctx.hflags & MIPS_HFLAG_M16)) {
9468 ctx.opcode = ldl_code(ctx.pc);
9469 insn_bytes = 4;
9470 decode_opc(env, &ctx, &is_branch);
9471 } else if (env->insn_flags & ASE_MIPS16) {
9472 ctx.opcode = lduw_code(ctx.pc);
9473 insn_bytes = decode_mips16_opc(env, &ctx, &is_branch);
9474 } else {
9475 generate_exception(&ctx, EXCP_RI);
9476 break;
9478 if (!is_branch) {
9479 handle_delay_slot(env, &ctx, insn_bytes);
9481 ctx.pc += insn_bytes;
9483 num_insns++;
9485 /* Execute a branch and its delay slot as a single instruction.
9486 This is what GDB expects and is consistent with what the
9487 hardware does (e.g. if a delay slot instruction faults, the
9488 reported PC is the PC of the branch). */
9489 if (env->singlestep_enabled && (ctx.hflags & MIPS_HFLAG_BMASK) == 0)
9490 break;
9492 if ((ctx.pc & (TARGET_PAGE_SIZE - 1)) == 0)
9493 break;
9495 if (gen_opc_ptr >= gen_opc_end)
9496 break;
9498 if (num_insns >= max_insns)
9499 break;
9501 if (singlestep)
9502 break;
9504 if (tb->cflags & CF_LAST_IO)
9505 gen_io_end();
9506 if (env->singlestep_enabled && ctx.bstate != BS_BRANCH) {
9507 save_cpu_state(&ctx, ctx.bstate == BS_NONE);
9508 gen_helper_0i(raise_exception, EXCP_DEBUG);
9509 } else {
9510 switch (ctx.bstate) {
9511 case BS_STOP:
9512 gen_helper_interrupt_restart();
9513 gen_goto_tb(&ctx, 0, ctx.pc);
9514 break;
9515 case BS_NONE:
9516 save_cpu_state(&ctx, 0);
9517 gen_goto_tb(&ctx, 0, ctx.pc);
9518 break;
9519 case BS_EXCP:
9520 gen_helper_interrupt_restart();
9521 tcg_gen_exit_tb(0);
9522 break;
9523 case BS_BRANCH:
9524 default:
9525 break;
9528 done_generating:
9529 gen_icount_end(tb, num_insns);
9530 *gen_opc_ptr = INDEX_op_end;
9531 if (search_pc) {
9532 j = gen_opc_ptr - gen_opc_buf;
9533 lj++;
9534 while (lj <= j)
9535 gen_opc_instr_start[lj++] = 0;
9536 } else {
9537 tb->size = ctx.pc - pc_start;
9538 tb->icount = num_insns;
9540 #ifdef DEBUG_DISAS
9541 LOG_DISAS("\n");
9542 if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) {
9543 qemu_log("IN: %s\n", lookup_symbol(pc_start));
9544 log_target_disas(pc_start, ctx.pc - pc_start, 0);
9545 qemu_log("\n");
9547 qemu_log_mask(CPU_LOG_TB_CPU, "---------------- %d %08x\n", ctx.bstate, ctx.hflags);
9548 #endif
9551 void gen_intermediate_code (CPUState *env, struct TranslationBlock *tb)
9553 gen_intermediate_code_internal(env, tb, 0);
9556 void gen_intermediate_code_pc (CPUState *env, struct TranslationBlock *tb)
9558 gen_intermediate_code_internal(env, tb, 1);
9561 static void fpu_dump_state(CPUState *env, FILE *f,
9562 int (*fpu_fprintf)(FILE *f, const char *fmt, ...),
9563 int flags)
9565 int i;
9566 int is_fpu64 = !!(env->hflags & MIPS_HFLAG_F64);
9568 #define printfpr(fp) \
9569 do { \
9570 if (is_fpu64) \
9571 fpu_fprintf(f, "w:%08x d:%016" PRIx64 \
9572 " fd:%13g fs:%13g psu: %13g\n", \
9573 (fp)->w[FP_ENDIAN_IDX], (fp)->d, \
9574 (double)(fp)->fd, \
9575 (double)(fp)->fs[FP_ENDIAN_IDX], \
9576 (double)(fp)->fs[!FP_ENDIAN_IDX]); \
9577 else { \
9578 fpr_t tmp; \
9579 tmp.w[FP_ENDIAN_IDX] = (fp)->w[FP_ENDIAN_IDX]; \
9580 tmp.w[!FP_ENDIAN_IDX] = ((fp) + 1)->w[FP_ENDIAN_IDX]; \
9581 fpu_fprintf(f, "w:%08x d:%016" PRIx64 \
9582 " fd:%13g fs:%13g psu:%13g\n", \
9583 tmp.w[FP_ENDIAN_IDX], tmp.d, \
9584 (double)tmp.fd, \
9585 (double)tmp.fs[FP_ENDIAN_IDX], \
9586 (double)tmp.fs[!FP_ENDIAN_IDX]); \
9588 } while(0)
9591 fpu_fprintf(f, "CP1 FCR0 0x%08x FCR31 0x%08x SR.FR %d fp_status 0x%08x(0x%02x)\n",
9592 env->active_fpu.fcr0, env->active_fpu.fcr31, is_fpu64, env->active_fpu.fp_status,
9593 get_float_exception_flags(&env->active_fpu.fp_status));
9594 for (i = 0; i < 32; (is_fpu64) ? i++ : (i += 2)) {
9595 fpu_fprintf(f, "%3s: ", fregnames[i]);
9596 printfpr(&env->active_fpu.fpr[i]);
9599 #undef printfpr
9602 #if defined(TARGET_MIPS64) && defined(MIPS_DEBUG_SIGN_EXTENSIONS)
9603 /* Debug help: The architecture requires 32bit code to maintain proper
9604 sign-extended values on 64bit machines. */
9606 #define SIGN_EXT_P(val) ((((val) & ~0x7fffffff) == 0) || (((val) & ~0x7fffffff) == ~0x7fffffff))
9608 static void
9609 cpu_mips_check_sign_extensions (CPUState *env, FILE *f,
9610 int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
9611 int flags)
9613 int i;
9615 if (!SIGN_EXT_P(env->active_tc.PC))
9616 cpu_fprintf(f, "BROKEN: pc=0x" TARGET_FMT_lx "\n", env->active_tc.PC);
9617 if (!SIGN_EXT_P(env->active_tc.HI[0]))
9618 cpu_fprintf(f, "BROKEN: HI=0x" TARGET_FMT_lx "\n", env->active_tc.HI[0]);
9619 if (!SIGN_EXT_P(env->active_tc.LO[0]))
9620 cpu_fprintf(f, "BROKEN: LO=0x" TARGET_FMT_lx "\n", env->active_tc.LO[0]);
9621 if (!SIGN_EXT_P(env->btarget))
9622 cpu_fprintf(f, "BROKEN: btarget=0x" TARGET_FMT_lx "\n", env->btarget);
9624 for (i = 0; i < 32; i++) {
9625 if (!SIGN_EXT_P(env->active_tc.gpr[i]))
9626 cpu_fprintf(f, "BROKEN: %s=0x" TARGET_FMT_lx "\n", regnames[i], env->active_tc.gpr[i]);
9629 if (!SIGN_EXT_P(env->CP0_EPC))
9630 cpu_fprintf(f, "BROKEN: EPC=0x" TARGET_FMT_lx "\n", env->CP0_EPC);
9631 if (!SIGN_EXT_P(env->lladdr))
9632 cpu_fprintf(f, "BROKEN: LLAddr=0x" TARGET_FMT_lx "\n", env->lladdr);
9634 #endif
9636 void cpu_dump_state (CPUState *env, FILE *f,
9637 int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
9638 int flags)
9640 int i;
9642 cpu_fprintf(f, "pc=0x" TARGET_FMT_lx " HI=0x" TARGET_FMT_lx
9643 " LO=0x" TARGET_FMT_lx " ds %04x "
9644 TARGET_FMT_lx " " TARGET_FMT_ld "\n",
9645 env->active_tc.PC, env->active_tc.HI[0], env->active_tc.LO[0],
9646 env->hflags, env->btarget, env->bcond);
9647 for (i = 0; i < 32; i++) {
9648 if ((i & 3) == 0)
9649 cpu_fprintf(f, "GPR%02d:", i);
9650 cpu_fprintf(f, " %s " TARGET_FMT_lx, regnames[i], env->active_tc.gpr[i]);
9651 if ((i & 3) == 3)
9652 cpu_fprintf(f, "\n");
9655 cpu_fprintf(f, "CP0 Status 0x%08x Cause 0x%08x EPC 0x" TARGET_FMT_lx "\n",
9656 env->CP0_Status, env->CP0_Cause, env->CP0_EPC);
9657 cpu_fprintf(f, " Config0 0x%08x Config1 0x%08x LLAddr 0x" TARGET_FMT_lx "\n",
9658 env->CP0_Config0, env->CP0_Config1, env->lladdr);
9659 if (env->hflags & MIPS_HFLAG_FPU)
9660 fpu_dump_state(env, f, cpu_fprintf, flags);
9661 #if defined(TARGET_MIPS64) && defined(MIPS_DEBUG_SIGN_EXTENSIONS)
9662 cpu_mips_check_sign_extensions(env, f, cpu_fprintf, flags);
9663 #endif
9666 static void mips_tcg_init(void)
9668 int i;
9669 static int inited;
9671 /* Initialize various static tables. */
9672 if (inited)
9673 return;
9675 cpu_env = tcg_global_reg_new_ptr(TCG_AREG0, "env");
9676 TCGV_UNUSED(cpu_gpr[0]);
9677 for (i = 1; i < 32; i++)
9678 cpu_gpr[i] = tcg_global_mem_new(TCG_AREG0,
9679 offsetof(CPUState, active_tc.gpr[i]),
9680 regnames[i]);
9681 cpu_PC = tcg_global_mem_new(TCG_AREG0,
9682 offsetof(CPUState, active_tc.PC), "PC");
9683 for (i = 0; i < MIPS_DSP_ACC; i++) {
9684 cpu_HI[i] = tcg_global_mem_new(TCG_AREG0,
9685 offsetof(CPUState, active_tc.HI[i]),
9686 regnames_HI[i]);
9687 cpu_LO[i] = tcg_global_mem_new(TCG_AREG0,
9688 offsetof(CPUState, active_tc.LO[i]),
9689 regnames_LO[i]);
9690 cpu_ACX[i] = tcg_global_mem_new(TCG_AREG0,
9691 offsetof(CPUState, active_tc.ACX[i]),
9692 regnames_ACX[i]);
9694 cpu_dspctrl = tcg_global_mem_new(TCG_AREG0,
9695 offsetof(CPUState, active_tc.DSPControl),
9696 "DSPControl");
9697 bcond = tcg_global_mem_new(TCG_AREG0,
9698 offsetof(CPUState, bcond), "bcond");
9699 btarget = tcg_global_mem_new(TCG_AREG0,
9700 offsetof(CPUState, btarget), "btarget");
9701 hflags = tcg_global_mem_new_i32(TCG_AREG0,
9702 offsetof(CPUState, hflags), "hflags");
9704 fpu_fcr0 = tcg_global_mem_new_i32(TCG_AREG0,
9705 offsetof(CPUState, active_fpu.fcr0),
9706 "fcr0");
9707 fpu_fcr31 = tcg_global_mem_new_i32(TCG_AREG0,
9708 offsetof(CPUState, active_fpu.fcr31),
9709 "fcr31");
9711 /* register helpers */
9712 #define GEN_HELPER 2
9713 #include "helper.h"
9715 inited = 1;
9718 #include "translate_init.c"
9720 CPUMIPSState *cpu_mips_init (const char *cpu_model)
9722 CPUMIPSState *env;
9723 const mips_def_t *def;
9725 def = cpu_mips_find_by_name(cpu_model);
9726 if (!def)
9727 return NULL;
9728 env = qemu_mallocz(sizeof(CPUMIPSState));
9729 env->cpu_model = def;
9730 env->cpu_model_str = cpu_model;
9732 cpu_exec_init(env);
9733 #ifndef CONFIG_USER_ONLY
9734 mmu_init(env, def);
9735 #endif
9736 fpu_init(env, def);
9737 mvp_init(env, def);
9738 mips_tcg_init();
9739 cpu_reset(env);
9740 qemu_init_vcpu(env);
9741 return env;
9744 void cpu_reset (CPUMIPSState *env)
9746 if (qemu_loglevel_mask(CPU_LOG_RESET)) {
9747 qemu_log("CPU Reset (CPU %d)\n", env->cpu_index);
9748 log_cpu_state(env, 0);
9751 memset(env, 0, offsetof(CPUMIPSState, breakpoints));
9752 tlb_flush(env, 1);
9754 /* Reset registers to their default values */
9755 env->CP0_PRid = env->cpu_model->CP0_PRid;
9756 env->CP0_Config0 = env->cpu_model->CP0_Config0;
9757 #ifdef TARGET_WORDS_BIGENDIAN
9758 env->CP0_Config0 |= (1 << CP0C0_BE);
9759 #endif
9760 env->CP0_Config1 = env->cpu_model->CP0_Config1;
9761 env->CP0_Config2 = env->cpu_model->CP0_Config2;
9762 env->CP0_Config3 = env->cpu_model->CP0_Config3;
9763 env->CP0_Config6 = env->cpu_model->CP0_Config6;
9764 env->CP0_Config7 = env->cpu_model->CP0_Config7;
9765 env->CP0_LLAddr_rw_bitmask = env->cpu_model->CP0_LLAddr_rw_bitmask
9766 << env->cpu_model->CP0_LLAddr_shift;
9767 env->CP0_LLAddr_shift = env->cpu_model->CP0_LLAddr_shift;
9768 env->SYNCI_Step = env->cpu_model->SYNCI_Step;
9769 env->CCRes = env->cpu_model->CCRes;
9770 env->CP0_Status_rw_bitmask = env->cpu_model->CP0_Status_rw_bitmask;
9771 env->CP0_TCStatus_rw_bitmask = env->cpu_model->CP0_TCStatus_rw_bitmask;
9772 env->CP0_SRSCtl = env->cpu_model->CP0_SRSCtl;
9773 env->current_tc = 0;
9774 env->SEGBITS = env->cpu_model->SEGBITS;
9775 env->SEGMask = (target_ulong)((1ULL << env->cpu_model->SEGBITS) - 1);
9776 #if defined(TARGET_MIPS64)
9777 if (env->cpu_model->insn_flags & ISA_MIPS3) {
9778 env->SEGMask |= 3ULL << 62;
9780 #endif
9781 env->PABITS = env->cpu_model->PABITS;
9782 env->PAMask = (target_ulong)((1ULL << env->cpu_model->PABITS) - 1);
9783 env->CP0_SRSConf0_rw_bitmask = env->cpu_model->CP0_SRSConf0_rw_bitmask;
9784 env->CP0_SRSConf0 = env->cpu_model->CP0_SRSConf0;
9785 env->CP0_SRSConf1_rw_bitmask = env->cpu_model->CP0_SRSConf1_rw_bitmask;
9786 env->CP0_SRSConf1 = env->cpu_model->CP0_SRSConf1;
9787 env->CP0_SRSConf2_rw_bitmask = env->cpu_model->CP0_SRSConf2_rw_bitmask;
9788 env->CP0_SRSConf2 = env->cpu_model->CP0_SRSConf2;
9789 env->CP0_SRSConf3_rw_bitmask = env->cpu_model->CP0_SRSConf3_rw_bitmask;
9790 env->CP0_SRSConf3 = env->cpu_model->CP0_SRSConf3;
9791 env->CP0_SRSConf4_rw_bitmask = env->cpu_model->CP0_SRSConf4_rw_bitmask;
9792 env->CP0_SRSConf4 = env->cpu_model->CP0_SRSConf4;
9793 env->insn_flags = env->cpu_model->insn_flags;
9795 #if defined(CONFIG_USER_ONLY)
9796 env->hflags = MIPS_HFLAG_UM;
9797 /* Enable access to the SYNCI_Step register. */
9798 env->CP0_HWREna |= (1 << 1);
9799 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
9800 env->hflags |= MIPS_HFLAG_FPU;
9802 #ifdef TARGET_MIPS64
9803 if (env->active_fpu.fcr0 & (1 << FCR0_F64)) {
9804 env->hflags |= MIPS_HFLAG_F64;
9806 #endif
9807 #else
9808 if (env->hflags & MIPS_HFLAG_BMASK) {
9809 /* If the exception was raised from a delay slot,
9810 come back to the jump. */
9811 env->CP0_ErrorEPC = env->active_tc.PC - 4;
9812 } else {
9813 env->CP0_ErrorEPC = env->active_tc.PC;
9815 env->active_tc.PC = (int32_t)0xBFC00000;
9816 env->CP0_Random = env->tlb->nb_tlb - 1;
9817 env->tlb->tlb_in_use = env->tlb->nb_tlb;
9818 env->CP0_Wired = 0;
9819 /* SMP not implemented */
9820 env->CP0_EBase = 0x80000000;
9821 env->CP0_Status = (1 << CP0St_BEV) | (1 << CP0St_ERL);
9822 /* vectored interrupts not implemented, timer on int 7,
9823 no performance counters. */
9824 env->CP0_IntCtl = 0xe0000000;
9826 int i;
9828 for (i = 0; i < 7; i++) {
9829 env->CP0_WatchLo[i] = 0;
9830 env->CP0_WatchHi[i] = 0x80000000;
9832 env->CP0_WatchLo[7] = 0;
9833 env->CP0_WatchHi[7] = 0;
9835 /* Count register increments in debug mode, EJTAG version 1 */
9836 env->CP0_Debug = (1 << CP0DB_CNT) | (0x1 << CP0DB_VER);
9837 env->hflags = MIPS_HFLAG_CP0;
9838 #endif
9839 #if defined(TARGET_MIPS64)
9840 if (env->cpu_model->insn_flags & ISA_MIPS3) {
9841 env->hflags |= MIPS_HFLAG_64;
9843 #endif
9844 env->exception_index = EXCP_NONE;
9847 void gen_pc_load(CPUState *env, TranslationBlock *tb,
9848 unsigned long searched_pc, int pc_pos, void *puc)
9850 env->active_tc.PC = gen_opc_pc[pc_pos];
9851 env->hflags &= ~MIPS_HFLAG_BMASK;
9852 env->hflags |= gen_opc_hflags[pc_pos];