Add support for generic notifier lists
[qemu/aliguori-queue.git] / target-mips / translate.c
blob0ade3bd48c52f3f2ec1953b1827706bea860167c
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 #include "gen-icount.h"
447 #define gen_helper_0i(name, arg) do { \
448 TCGv_i32 helper_tmp = tcg_const_i32(arg); \
449 gen_helper_##name(helper_tmp); \
450 tcg_temp_free_i32(helper_tmp); \
451 } while(0)
453 #define gen_helper_1i(name, arg1, arg2) do { \
454 TCGv_i32 helper_tmp = tcg_const_i32(arg2); \
455 gen_helper_##name(arg1, helper_tmp); \
456 tcg_temp_free_i32(helper_tmp); \
457 } while(0)
459 #define gen_helper_2i(name, arg1, arg2, arg3) do { \
460 TCGv_i32 helper_tmp = tcg_const_i32(arg3); \
461 gen_helper_##name(arg1, arg2, helper_tmp); \
462 tcg_temp_free_i32(helper_tmp); \
463 } while(0)
465 #define gen_helper_3i(name, arg1, arg2, arg3, arg4) do { \
466 TCGv_i32 helper_tmp = tcg_const_i32(arg4); \
467 gen_helper_##name(arg1, arg2, arg3, helper_tmp); \
468 tcg_temp_free_i32(helper_tmp); \
469 } while(0)
471 typedef struct DisasContext {
472 struct TranslationBlock *tb;
473 target_ulong pc, saved_pc;
474 uint32_t opcode;
475 int singlestep_enabled;
476 /* Routine used to access memory */
477 int mem_idx;
478 uint32_t hflags, saved_hflags;
479 int bstate;
480 target_ulong btarget;
481 } DisasContext;
483 enum {
484 BS_NONE = 0, /* We go out of the TB without reaching a branch or an
485 * exception condition */
486 BS_STOP = 1, /* We want to stop translation for any reason */
487 BS_BRANCH = 2, /* We reached a branch condition */
488 BS_EXCP = 3, /* We reached an exception condition */
491 static const char *regnames[] =
492 { "r0", "at", "v0", "v1", "a0", "a1", "a2", "a3",
493 "t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7",
494 "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7",
495 "t8", "t9", "k0", "k1", "gp", "sp", "s8", "ra", };
497 static const char *regnames_HI[] =
498 { "HI0", "HI1", "HI2", "HI3", };
500 static const char *regnames_LO[] =
501 { "LO0", "LO1", "LO2", "LO3", };
503 static const char *regnames_ACX[] =
504 { "ACX0", "ACX1", "ACX2", "ACX3", };
506 static const char *fregnames[] =
507 { "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7",
508 "f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15",
509 "f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23",
510 "f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31", };
512 #ifdef MIPS_DEBUG_DISAS
513 #define MIPS_DEBUG(fmt, ...) \
514 qemu_log_mask(CPU_LOG_TB_IN_ASM, \
515 TARGET_FMT_lx ": %08x " fmt "\n", \
516 ctx->pc, ctx->opcode , ## __VA_ARGS__)
517 #define LOG_DISAS(...) qemu_log_mask(CPU_LOG_TB_IN_ASM, ## __VA_ARGS__)
518 #else
519 #define MIPS_DEBUG(fmt, ...) do { } while(0)
520 #define LOG_DISAS(...) do { } while (0)
521 #endif
523 #define MIPS_INVAL(op) \
524 do { \
525 MIPS_DEBUG("Invalid %s %03x %03x %03x", op, ctx->opcode >> 26, \
526 ctx->opcode & 0x3F, ((ctx->opcode >> 16) & 0x1F)); \
527 } while (0)
529 /* General purpose registers moves. */
530 static inline void gen_load_gpr (TCGv t, int reg)
532 if (reg == 0)
533 tcg_gen_movi_tl(t, 0);
534 else
535 tcg_gen_mov_tl(t, cpu_gpr[reg]);
538 static inline void gen_store_gpr (TCGv t, int reg)
540 if (reg != 0)
541 tcg_gen_mov_tl(cpu_gpr[reg], t);
544 /* Moves to/from ACX register. */
545 static inline void gen_load_ACX (TCGv t, int reg)
547 tcg_gen_mov_tl(t, cpu_ACX[reg]);
550 static inline void gen_store_ACX (TCGv t, int reg)
552 tcg_gen_mov_tl(cpu_ACX[reg], t);
555 /* Moves to/from shadow registers. */
556 static inline void gen_load_srsgpr (int from, int to)
558 TCGv t0 = tcg_temp_new();
560 if (from == 0)
561 tcg_gen_movi_tl(t0, 0);
562 else {
563 TCGv_i32 t2 = tcg_temp_new_i32();
564 TCGv_ptr addr = tcg_temp_new_ptr();
566 tcg_gen_ld_i32(t2, cpu_env, offsetof(CPUState, CP0_SRSCtl));
567 tcg_gen_shri_i32(t2, t2, CP0SRSCtl_PSS);
568 tcg_gen_andi_i32(t2, t2, 0xf);
569 tcg_gen_muli_i32(t2, t2, sizeof(target_ulong) * 32);
570 tcg_gen_ext_i32_ptr(addr, t2);
571 tcg_gen_add_ptr(addr, cpu_env, addr);
573 tcg_gen_ld_tl(t0, addr, sizeof(target_ulong) * from);
574 tcg_temp_free_ptr(addr);
575 tcg_temp_free_i32(t2);
577 gen_store_gpr(t0, to);
578 tcg_temp_free(t0);
581 static inline void gen_store_srsgpr (int from, int to)
583 if (to != 0) {
584 TCGv t0 = tcg_temp_new();
585 TCGv_i32 t2 = tcg_temp_new_i32();
586 TCGv_ptr addr = tcg_temp_new_ptr();
588 gen_load_gpr(t0, from);
589 tcg_gen_ld_i32(t2, cpu_env, offsetof(CPUState, CP0_SRSCtl));
590 tcg_gen_shri_i32(t2, t2, CP0SRSCtl_PSS);
591 tcg_gen_andi_i32(t2, t2, 0xf);
592 tcg_gen_muli_i32(t2, t2, sizeof(target_ulong) * 32);
593 tcg_gen_ext_i32_ptr(addr, t2);
594 tcg_gen_add_ptr(addr, cpu_env, addr);
596 tcg_gen_st_tl(t0, addr, sizeof(target_ulong) * to);
597 tcg_temp_free_ptr(addr);
598 tcg_temp_free_i32(t2);
599 tcg_temp_free(t0);
603 /* Floating point register moves. */
604 static inline void gen_load_fpr32 (TCGv_i32 t, int reg)
606 tcg_gen_ld_i32(t, cpu_env, offsetof(CPUState, active_fpu.fpr[reg].w[FP_ENDIAN_IDX]));
609 static inline void gen_store_fpr32 (TCGv_i32 t, int reg)
611 tcg_gen_st_i32(t, cpu_env, offsetof(CPUState, active_fpu.fpr[reg].w[FP_ENDIAN_IDX]));
614 static inline void gen_load_fpr32h (TCGv_i32 t, int reg)
616 tcg_gen_ld_i32(t, cpu_env, offsetof(CPUState, active_fpu.fpr[reg].w[!FP_ENDIAN_IDX]));
619 static inline void gen_store_fpr32h (TCGv_i32 t, int reg)
621 tcg_gen_st_i32(t, cpu_env, offsetof(CPUState, active_fpu.fpr[reg].w[!FP_ENDIAN_IDX]));
624 static inline void gen_load_fpr64 (DisasContext *ctx, TCGv_i64 t, int reg)
626 if (ctx->hflags & MIPS_HFLAG_F64) {
627 tcg_gen_ld_i64(t, cpu_env, offsetof(CPUState, active_fpu.fpr[reg].d));
628 } else {
629 TCGv_i32 t0 = tcg_temp_new_i32();
630 TCGv_i32 t1 = tcg_temp_new_i32();
631 gen_load_fpr32(t0, reg & ~1);
632 gen_load_fpr32(t1, reg | 1);
633 tcg_gen_concat_i32_i64(t, t0, t1);
634 tcg_temp_free_i32(t0);
635 tcg_temp_free_i32(t1);
639 static inline void gen_store_fpr64 (DisasContext *ctx, TCGv_i64 t, int reg)
641 if (ctx->hflags & MIPS_HFLAG_F64) {
642 tcg_gen_st_i64(t, cpu_env, offsetof(CPUState, active_fpu.fpr[reg].d));
643 } else {
644 TCGv_i64 t0 = tcg_temp_new_i64();
645 TCGv_i32 t1 = tcg_temp_new_i32();
646 tcg_gen_trunc_i64_i32(t1, t);
647 gen_store_fpr32(t1, reg & ~1);
648 tcg_gen_shri_i64(t0, t, 32);
649 tcg_gen_trunc_i64_i32(t1, t0);
650 gen_store_fpr32(t1, reg | 1);
651 tcg_temp_free_i32(t1);
652 tcg_temp_free_i64(t0);
656 static inline int get_fp_bit (int cc)
658 if (cc)
659 return 24 + cc;
660 else
661 return 23;
664 #define FOP_CONDS(type, fmt, bits) \
665 static inline void gen_cmp ## type ## _ ## fmt(int n, TCGv_i##bits a, \
666 TCGv_i##bits b, int cc) \
668 switch (n) { \
669 case 0: gen_helper_2i(cmp ## type ## _ ## fmt ## _f, a, b, cc); break;\
670 case 1: gen_helper_2i(cmp ## type ## _ ## fmt ## _un, a, b, cc); break;\
671 case 2: gen_helper_2i(cmp ## type ## _ ## fmt ## _eq, a, b, cc); break;\
672 case 3: gen_helper_2i(cmp ## type ## _ ## fmt ## _ueq, a, b, cc); break;\
673 case 4: gen_helper_2i(cmp ## type ## _ ## fmt ## _olt, a, b, cc); break;\
674 case 5: gen_helper_2i(cmp ## type ## _ ## fmt ## _ult, a, b, cc); break;\
675 case 6: gen_helper_2i(cmp ## type ## _ ## fmt ## _ole, a, b, cc); break;\
676 case 7: gen_helper_2i(cmp ## type ## _ ## fmt ## _ule, a, b, cc); break;\
677 case 8: gen_helper_2i(cmp ## type ## _ ## fmt ## _sf, a, b, cc); break;\
678 case 9: gen_helper_2i(cmp ## type ## _ ## fmt ## _ngle, a, b, cc); break;\
679 case 10: gen_helper_2i(cmp ## type ## _ ## fmt ## _seq, a, b, cc); break;\
680 case 11: gen_helper_2i(cmp ## type ## _ ## fmt ## _ngl, a, b, cc); break;\
681 case 12: gen_helper_2i(cmp ## type ## _ ## fmt ## _lt, a, b, cc); break;\
682 case 13: gen_helper_2i(cmp ## type ## _ ## fmt ## _nge, a, b, cc); break;\
683 case 14: gen_helper_2i(cmp ## type ## _ ## fmt ## _le, a, b, cc); break;\
684 case 15: gen_helper_2i(cmp ## type ## _ ## fmt ## _ngt, a, b, cc); break;\
685 default: abort(); \
689 FOP_CONDS(, d, 64)
690 FOP_CONDS(abs, d, 64)
691 FOP_CONDS(, s, 32)
692 FOP_CONDS(abs, s, 32)
693 FOP_CONDS(, ps, 64)
694 FOP_CONDS(abs, ps, 64)
695 #undef FOP_CONDS
697 /* Tests */
698 static inline void gen_save_pc(target_ulong pc)
700 tcg_gen_movi_tl(cpu_PC, pc);
703 static inline void save_cpu_state (DisasContext *ctx, int do_save_pc)
705 LOG_DISAS("hflags %08x saved %08x\n", ctx->hflags, ctx->saved_hflags);
706 if (do_save_pc && ctx->pc != ctx->saved_pc) {
707 gen_save_pc(ctx->pc);
708 ctx->saved_pc = ctx->pc;
710 if (ctx->hflags != ctx->saved_hflags) {
711 tcg_gen_movi_i32(hflags, ctx->hflags);
712 ctx->saved_hflags = ctx->hflags;
713 switch (ctx->hflags & MIPS_HFLAG_BMASK_BASE) {
714 case MIPS_HFLAG_BR:
715 break;
716 case MIPS_HFLAG_BC:
717 case MIPS_HFLAG_BL:
718 case MIPS_HFLAG_B:
719 tcg_gen_movi_tl(btarget, ctx->btarget);
720 break;
725 static inline void restore_cpu_state (CPUState *env, DisasContext *ctx)
727 ctx->saved_hflags = ctx->hflags;
728 switch (ctx->hflags & MIPS_HFLAG_BMASK_BASE) {
729 case MIPS_HFLAG_BR:
730 break;
731 case MIPS_HFLAG_BC:
732 case MIPS_HFLAG_BL:
733 case MIPS_HFLAG_B:
734 ctx->btarget = env->btarget;
735 break;
739 static inline void
740 generate_exception_err (DisasContext *ctx, int excp, int err)
742 TCGv_i32 texcp = tcg_const_i32(excp);
743 TCGv_i32 terr = tcg_const_i32(err);
744 save_cpu_state(ctx, 1);
745 gen_helper_raise_exception_err(texcp, terr);
746 tcg_temp_free_i32(terr);
747 tcg_temp_free_i32(texcp);
750 static inline void
751 generate_exception (DisasContext *ctx, int excp)
753 save_cpu_state(ctx, 1);
754 gen_helper_0i(raise_exception, excp);
757 /* Addresses computation */
758 static inline void gen_op_addr_add (DisasContext *ctx, TCGv ret, TCGv arg0, TCGv arg1)
760 tcg_gen_add_tl(ret, arg0, arg1);
762 #if defined(TARGET_MIPS64)
763 /* For compatibility with 32-bit code, data reference in user mode
764 with Status_UX = 0 should be casted to 32-bit and sign extended.
765 See the MIPS64 PRA manual, section 4.10. */
766 if (((ctx->hflags & MIPS_HFLAG_KSU) == MIPS_HFLAG_UM) &&
767 !(ctx->hflags & MIPS_HFLAG_UX)) {
768 tcg_gen_ext32s_i64(ret, ret);
770 #endif
773 static inline void check_cp0_enabled(DisasContext *ctx)
775 if (unlikely(!(ctx->hflags & MIPS_HFLAG_CP0)))
776 generate_exception_err(ctx, EXCP_CpU, 0);
779 static inline void check_cp1_enabled(DisasContext *ctx)
781 if (unlikely(!(ctx->hflags & MIPS_HFLAG_FPU)))
782 generate_exception_err(ctx, EXCP_CpU, 1);
785 /* Verify that the processor is running with COP1X instructions enabled.
786 This is associated with the nabla symbol in the MIPS32 and MIPS64
787 opcode tables. */
789 static inline void check_cop1x(DisasContext *ctx)
791 if (unlikely(!(ctx->hflags & MIPS_HFLAG_COP1X)))
792 generate_exception(ctx, EXCP_RI);
795 /* Verify that the processor is running with 64-bit floating-point
796 operations enabled. */
798 static inline void check_cp1_64bitmode(DisasContext *ctx)
800 if (unlikely(~ctx->hflags & (MIPS_HFLAG_F64 | MIPS_HFLAG_COP1X)))
801 generate_exception(ctx, EXCP_RI);
805 * Verify if floating point register is valid; an operation is not defined
806 * if bit 0 of any register specification is set and the FR bit in the
807 * Status register equals zero, since the register numbers specify an
808 * even-odd pair of adjacent coprocessor general registers. When the FR bit
809 * in the Status register equals one, both even and odd register numbers
810 * are valid. This limitation exists only for 64 bit wide (d,l,ps) registers.
812 * Multiple 64 bit wide registers can be checked by calling
813 * gen_op_cp1_registers(freg1 | freg2 | ... | fregN);
815 static inline void check_cp1_registers(DisasContext *ctx, int regs)
817 if (unlikely(!(ctx->hflags & MIPS_HFLAG_F64) && (regs & 1)))
818 generate_exception(ctx, EXCP_RI);
821 /* This code generates a "reserved instruction" exception if the
822 CPU does not support the instruction set corresponding to flags. */
823 static inline void check_insn(CPUState *env, DisasContext *ctx, int flags)
825 if (unlikely(!(env->insn_flags & flags)))
826 generate_exception(ctx, EXCP_RI);
829 /* This code generates a "reserved instruction" exception if 64-bit
830 instructions are not enabled. */
831 static inline void check_mips_64(DisasContext *ctx)
833 if (unlikely(!(ctx->hflags & MIPS_HFLAG_64)))
834 generate_exception(ctx, EXCP_RI);
837 /* load/store instructions. */
838 #define OP_LD(insn,fname) \
839 static inline void op_ldst_##insn(TCGv ret, TCGv arg1, DisasContext *ctx) \
841 tcg_gen_qemu_##fname(ret, arg1, ctx->mem_idx); \
843 OP_LD(lb,ld8s);
844 OP_LD(lbu,ld8u);
845 OP_LD(lh,ld16s);
846 OP_LD(lhu,ld16u);
847 OP_LD(lw,ld32s);
848 #if defined(TARGET_MIPS64)
849 OP_LD(lwu,ld32u);
850 OP_LD(ld,ld64);
851 #endif
852 #undef OP_LD
854 #define OP_ST(insn,fname) \
855 static inline void op_ldst_##insn(TCGv arg1, TCGv arg2, DisasContext *ctx) \
857 tcg_gen_qemu_##fname(arg1, arg2, ctx->mem_idx); \
859 OP_ST(sb,st8);
860 OP_ST(sh,st16);
861 OP_ST(sw,st32);
862 #if defined(TARGET_MIPS64)
863 OP_ST(sd,st64);
864 #endif
865 #undef OP_ST
867 #ifdef CONFIG_USER_ONLY
868 #define OP_LD_ATOMIC(insn,fname) \
869 static inline void op_ldst_##insn(TCGv ret, TCGv arg1, DisasContext *ctx) \
871 TCGv t0 = tcg_temp_new(); \
872 tcg_gen_mov_tl(t0, arg1); \
873 tcg_gen_qemu_##fname(ret, arg1, ctx->mem_idx); \
874 tcg_gen_st_tl(t0, cpu_env, offsetof(CPUState, lladdr)); \
875 tcg_gen_st_tl(ret, cpu_env, offsetof(CPUState, llval)); \
876 tcg_temp_free(t0); \
878 #else
879 #define OP_LD_ATOMIC(insn,fname) \
880 static inline void op_ldst_##insn(TCGv ret, TCGv arg1, DisasContext *ctx) \
882 gen_helper_2i(insn, ret, arg1, ctx->mem_idx); \
884 #endif
885 OP_LD_ATOMIC(ll,ld32s);
886 #if defined(TARGET_MIPS64)
887 OP_LD_ATOMIC(lld,ld64);
888 #endif
889 #undef OP_LD_ATOMIC
891 #ifdef CONFIG_USER_ONLY
892 #define OP_ST_ATOMIC(insn,fname,ldname,almask) \
893 static inline void op_ldst_##insn(TCGv arg1, TCGv arg2, int rt, DisasContext *ctx) \
895 TCGv t0 = tcg_temp_new(); \
896 int l1 = gen_new_label(); \
897 int l2 = gen_new_label(); \
899 tcg_gen_andi_tl(t0, arg2, almask); \
900 tcg_gen_brcondi_tl(TCG_COND_EQ, t0, 0, l1); \
901 tcg_gen_st_tl(arg2, cpu_env, offsetof(CPUState, CP0_BadVAddr)); \
902 generate_exception(ctx, EXCP_AdES); \
903 gen_set_label(l1); \
904 tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUState, lladdr)); \
905 tcg_gen_brcond_tl(TCG_COND_NE, arg2, t0, l2); \
906 tcg_gen_movi_tl(t0, rt | ((almask << 3) & 0x20)); \
907 tcg_gen_st_tl(t0, cpu_env, offsetof(CPUState, llreg)); \
908 tcg_gen_st_tl(arg1, cpu_env, offsetof(CPUState, llnewval)); \
909 gen_helper_0i(raise_exception, EXCP_SC); \
910 gen_set_label(l2); \
911 tcg_gen_movi_tl(t0, 0); \
912 gen_store_gpr(t0, rt); \
913 tcg_temp_free(t0); \
915 #else
916 #define OP_ST_ATOMIC(insn,fname,ldname,almask) \
917 static inline void op_ldst_##insn(TCGv arg1, TCGv arg2, int rt, DisasContext *ctx) \
919 TCGv t0 = tcg_temp_new(); \
920 gen_helper_3i(insn, t0, arg1, arg2, ctx->mem_idx); \
921 gen_store_gpr(t0, rt); \
922 tcg_temp_free(t0); \
924 #endif
925 OP_ST_ATOMIC(sc,st32,ld32s,0x3);
926 #if defined(TARGET_MIPS64)
927 OP_ST_ATOMIC(scd,st64,ld64,0x7);
928 #endif
929 #undef OP_ST_ATOMIC
931 static void gen_base_offset_addr (DisasContext *ctx, TCGv addr,
932 int base, int16_t offset)
934 if (base == 0) {
935 tcg_gen_movi_tl(addr, offset);
936 } else if (offset == 0) {
937 gen_load_gpr(addr, base);
938 } else {
939 tcg_gen_movi_tl(addr, offset);
940 gen_op_addr_add(ctx, addr, cpu_gpr[base], addr);
944 static target_ulong pc_relative_pc (DisasContext *ctx)
946 target_ulong pc = ctx->pc;
948 if (ctx->hflags & MIPS_HFLAG_BMASK) {
949 int branch_bytes = ctx->hflags & MIPS_HFLAG_BDS16 ? 2 : 4;
951 pc -= branch_bytes;
954 pc &= ~(target_ulong)3;
955 return pc;
958 /* Load and store */
959 static void gen_ldst (DisasContext *ctx, uint32_t opc, int rt,
960 int base, int16_t offset)
962 const char *opn = "ldst";
963 TCGv t0 = tcg_temp_new();
964 TCGv t1 = tcg_temp_new();
966 gen_base_offset_addr(ctx, t0, base, offset);
967 /* Don't do NOP if destination is zero: we must perform the actual
968 memory access. */
969 switch (opc) {
970 #if defined(TARGET_MIPS64)
971 case OPC_LWU:
972 save_cpu_state(ctx, 0);
973 op_ldst_lwu(t0, t0, ctx);
974 gen_store_gpr(t0, rt);
975 opn = "lwu";
976 break;
977 case OPC_LD:
978 save_cpu_state(ctx, 0);
979 op_ldst_ld(t0, t0, ctx);
980 gen_store_gpr(t0, rt);
981 opn = "ld";
982 break;
983 case OPC_LLD:
984 save_cpu_state(ctx, 0);
985 op_ldst_lld(t0, t0, ctx);
986 gen_store_gpr(t0, rt);
987 opn = "lld";
988 break;
989 case OPC_SD:
990 save_cpu_state(ctx, 0);
991 gen_load_gpr(t1, rt);
992 op_ldst_sd(t1, t0, ctx);
993 opn = "sd";
994 break;
995 case OPC_LDL:
996 save_cpu_state(ctx, 1);
997 gen_load_gpr(t1, rt);
998 gen_helper_3i(ldl, t1, t1, t0, ctx->mem_idx);
999 gen_store_gpr(t1, rt);
1000 opn = "ldl";
1001 break;
1002 case OPC_SDL:
1003 save_cpu_state(ctx, 1);
1004 gen_load_gpr(t1, rt);
1005 gen_helper_2i(sdl, t1, t0, ctx->mem_idx);
1006 opn = "sdl";
1007 break;
1008 case OPC_LDR:
1009 save_cpu_state(ctx, 1);
1010 gen_load_gpr(t1, rt);
1011 gen_helper_3i(ldr, t1, t1, t0, ctx->mem_idx);
1012 gen_store_gpr(t1, rt);
1013 opn = "ldr";
1014 break;
1015 case OPC_SDR:
1016 save_cpu_state(ctx, 1);
1017 gen_load_gpr(t1, rt);
1018 gen_helper_2i(sdr, t1, t0, ctx->mem_idx);
1019 opn = "sdr";
1020 break;
1021 case OPC_LDPC:
1022 save_cpu_state(ctx, 1);
1023 tcg_gen_movi_tl(t1, pc_relative_pc(ctx));
1024 gen_op_addr_add(ctx, t0, t0, t1);
1025 op_ldst_ld(t0, t0, ctx);
1026 gen_store_gpr(t0, rt);
1027 break;
1028 #endif
1029 case OPC_LWPC:
1030 save_cpu_state(ctx, 1);
1031 tcg_gen_movi_tl(t1, pc_relative_pc(ctx));
1032 gen_op_addr_add(ctx, t0, t0, t1);
1033 op_ldst_lw(t0, t0, ctx);
1034 gen_store_gpr(t0, rt);
1035 break;
1036 case OPC_LW:
1037 save_cpu_state(ctx, 0);
1038 op_ldst_lw(t0, t0, ctx);
1039 gen_store_gpr(t0, rt);
1040 opn = "lw";
1041 break;
1042 case OPC_SW:
1043 save_cpu_state(ctx, 0);
1044 gen_load_gpr(t1, rt);
1045 op_ldst_sw(t1, t0, ctx);
1046 opn = "sw";
1047 break;
1048 case OPC_LH:
1049 save_cpu_state(ctx, 0);
1050 op_ldst_lh(t0, t0, ctx);
1051 gen_store_gpr(t0, rt);
1052 opn = "lh";
1053 break;
1054 case OPC_SH:
1055 save_cpu_state(ctx, 0);
1056 gen_load_gpr(t1, rt);
1057 op_ldst_sh(t1, t0, ctx);
1058 opn = "sh";
1059 break;
1060 case OPC_LHU:
1061 save_cpu_state(ctx, 0);
1062 op_ldst_lhu(t0, t0, ctx);
1063 gen_store_gpr(t0, rt);
1064 opn = "lhu";
1065 break;
1066 case OPC_LB:
1067 save_cpu_state(ctx, 0);
1068 op_ldst_lb(t0, t0, ctx);
1069 gen_store_gpr(t0, rt);
1070 opn = "lb";
1071 break;
1072 case OPC_SB:
1073 save_cpu_state(ctx, 0);
1074 gen_load_gpr(t1, rt);
1075 op_ldst_sb(t1, t0, ctx);
1076 opn = "sb";
1077 break;
1078 case OPC_LBU:
1079 save_cpu_state(ctx, 0);
1080 op_ldst_lbu(t0, t0, ctx);
1081 gen_store_gpr(t0, rt);
1082 opn = "lbu";
1083 break;
1084 case OPC_LWL:
1085 save_cpu_state(ctx, 1);
1086 gen_load_gpr(t1, rt);
1087 gen_helper_3i(lwl, t1, t1, t0, ctx->mem_idx);
1088 gen_store_gpr(t1, rt);
1089 opn = "lwl";
1090 break;
1091 case OPC_SWL:
1092 save_cpu_state(ctx, 1);
1093 gen_load_gpr(t1, rt);
1094 gen_helper_2i(swl, t1, t0, ctx->mem_idx);
1095 opn = "swr";
1096 break;
1097 case OPC_LWR:
1098 save_cpu_state(ctx, 1);
1099 gen_load_gpr(t1, rt);
1100 gen_helper_3i(lwr, t1, t1, t0, ctx->mem_idx);
1101 gen_store_gpr(t1, rt);
1102 opn = "lwr";
1103 break;
1104 case OPC_SWR:
1105 save_cpu_state(ctx, 1);
1106 gen_load_gpr(t1, rt);
1107 gen_helper_2i(swr, t1, t0, ctx->mem_idx);
1108 opn = "swr";
1109 break;
1110 case OPC_LL:
1111 save_cpu_state(ctx, 1);
1112 op_ldst_ll(t0, t0, ctx);
1113 gen_store_gpr(t0, rt);
1114 opn = "ll";
1115 break;
1117 MIPS_DEBUG("%s %s, %d(%s)", opn, regnames[rt], offset, regnames[base]);
1118 tcg_temp_free(t0);
1119 tcg_temp_free(t1);
1122 /* Store conditional */
1123 static void gen_st_cond (DisasContext *ctx, uint32_t opc, int rt,
1124 int base, int16_t offset)
1126 const char *opn = "st_cond";
1127 TCGv t0, t1;
1129 t0 = tcg_temp_local_new();
1131 gen_base_offset_addr(ctx, t0, base, offset);
1132 /* Don't do NOP if destination is zero: we must perform the actual
1133 memory access. */
1135 t1 = tcg_temp_local_new();
1136 gen_load_gpr(t1, rt);
1137 switch (opc) {
1138 #if defined(TARGET_MIPS64)
1139 case OPC_SCD:
1140 save_cpu_state(ctx, 0);
1141 op_ldst_scd(t1, t0, rt, ctx);
1142 opn = "scd";
1143 break;
1144 #endif
1145 case OPC_SC:
1146 save_cpu_state(ctx, 1);
1147 op_ldst_sc(t1, t0, rt, ctx);
1148 opn = "sc";
1149 break;
1151 MIPS_DEBUG("%s %s, %d(%s)", opn, regnames[rt], offset, regnames[base]);
1152 tcg_temp_free(t1);
1153 tcg_temp_free(t0);
1156 /* Load and store */
1157 static void gen_flt_ldst (DisasContext *ctx, uint32_t opc, int ft,
1158 int base, int16_t offset)
1160 const char *opn = "flt_ldst";
1161 TCGv t0 = tcg_temp_new();
1163 gen_base_offset_addr(ctx, t0, base, offset);
1164 /* Don't do NOP if destination is zero: we must perform the actual
1165 memory access. */
1166 switch (opc) {
1167 case OPC_LWC1:
1169 TCGv_i32 fp0 = tcg_temp_new_i32();
1171 tcg_gen_qemu_ld32s(t0, t0, ctx->mem_idx);
1172 tcg_gen_trunc_tl_i32(fp0, t0);
1173 gen_store_fpr32(fp0, ft);
1174 tcg_temp_free_i32(fp0);
1176 opn = "lwc1";
1177 break;
1178 case OPC_SWC1:
1180 TCGv_i32 fp0 = tcg_temp_new_i32();
1181 TCGv t1 = tcg_temp_new();
1183 gen_load_fpr32(fp0, ft);
1184 tcg_gen_extu_i32_tl(t1, fp0);
1185 tcg_gen_qemu_st32(t1, t0, ctx->mem_idx);
1186 tcg_temp_free(t1);
1187 tcg_temp_free_i32(fp0);
1189 opn = "swc1";
1190 break;
1191 case OPC_LDC1:
1193 TCGv_i64 fp0 = tcg_temp_new_i64();
1195 tcg_gen_qemu_ld64(fp0, t0, ctx->mem_idx);
1196 gen_store_fpr64(ctx, fp0, ft);
1197 tcg_temp_free_i64(fp0);
1199 opn = "ldc1";
1200 break;
1201 case OPC_SDC1:
1203 TCGv_i64 fp0 = tcg_temp_new_i64();
1205 gen_load_fpr64(ctx, fp0, ft);
1206 tcg_gen_qemu_st64(fp0, t0, ctx->mem_idx);
1207 tcg_temp_free_i64(fp0);
1209 opn = "sdc1";
1210 break;
1211 default:
1212 MIPS_INVAL(opn);
1213 generate_exception(ctx, EXCP_RI);
1214 goto out;
1216 MIPS_DEBUG("%s %s, %d(%s)", opn, fregnames[ft], offset, regnames[base]);
1217 out:
1218 tcg_temp_free(t0);
1221 /* Arithmetic with immediate operand */
1222 static void gen_arith_imm (CPUState *env, DisasContext *ctx, uint32_t opc,
1223 int rt, int rs, int16_t imm)
1225 target_ulong uimm = (target_long)imm; /* Sign extend to 32/64 bits */
1226 const char *opn = "imm arith";
1228 if (rt == 0 && opc != OPC_ADDI && opc != OPC_DADDI) {
1229 /* If no destination, treat it as a NOP.
1230 For addi, we must generate the overflow exception when needed. */
1231 MIPS_DEBUG("NOP");
1232 return;
1234 switch (opc) {
1235 case OPC_ADDI:
1237 TCGv t0 = tcg_temp_local_new();
1238 TCGv t1 = tcg_temp_new();
1239 TCGv t2 = tcg_temp_new();
1240 int l1 = gen_new_label();
1242 gen_load_gpr(t1, rs);
1243 tcg_gen_addi_tl(t0, t1, uimm);
1244 tcg_gen_ext32s_tl(t0, t0);
1246 tcg_gen_xori_tl(t1, t1, ~uimm);
1247 tcg_gen_xori_tl(t2, t0, uimm);
1248 tcg_gen_and_tl(t1, t1, t2);
1249 tcg_temp_free(t2);
1250 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
1251 tcg_temp_free(t1);
1252 /* operands of same sign, result different sign */
1253 generate_exception(ctx, EXCP_OVERFLOW);
1254 gen_set_label(l1);
1255 tcg_gen_ext32s_tl(t0, t0);
1256 gen_store_gpr(t0, rt);
1257 tcg_temp_free(t0);
1259 opn = "addi";
1260 break;
1261 case OPC_ADDIU:
1262 if (rs != 0) {
1263 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
1264 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
1265 } else {
1266 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
1268 opn = "addiu";
1269 break;
1270 #if defined(TARGET_MIPS64)
1271 case OPC_DADDI:
1273 TCGv t0 = tcg_temp_local_new();
1274 TCGv t1 = tcg_temp_new();
1275 TCGv t2 = tcg_temp_new();
1276 int l1 = gen_new_label();
1278 gen_load_gpr(t1, rs);
1279 tcg_gen_addi_tl(t0, t1, uimm);
1281 tcg_gen_xori_tl(t1, t1, ~uimm);
1282 tcg_gen_xori_tl(t2, t0, uimm);
1283 tcg_gen_and_tl(t1, t1, t2);
1284 tcg_temp_free(t2);
1285 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
1286 tcg_temp_free(t1);
1287 /* operands of same sign, result different sign */
1288 generate_exception(ctx, EXCP_OVERFLOW);
1289 gen_set_label(l1);
1290 gen_store_gpr(t0, rt);
1291 tcg_temp_free(t0);
1293 opn = "daddi";
1294 break;
1295 case OPC_DADDIU:
1296 if (rs != 0) {
1297 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
1298 } else {
1299 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
1301 opn = "daddiu";
1302 break;
1303 #endif
1305 MIPS_DEBUG("%s %s, %s, " TARGET_FMT_lx, opn, regnames[rt], regnames[rs], uimm);
1308 /* Logic with immediate operand */
1309 static void gen_logic_imm (CPUState *env, uint32_t opc, int rt, int rs, int16_t imm)
1311 target_ulong uimm;
1312 const char *opn = "imm logic";
1314 if (rt == 0) {
1315 /* If no destination, treat it as a NOP. */
1316 MIPS_DEBUG("NOP");
1317 return;
1319 uimm = (uint16_t)imm;
1320 switch (opc) {
1321 case OPC_ANDI:
1322 if (likely(rs != 0))
1323 tcg_gen_andi_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
1324 else
1325 tcg_gen_movi_tl(cpu_gpr[rt], 0);
1326 opn = "andi";
1327 break;
1328 case OPC_ORI:
1329 if (rs != 0)
1330 tcg_gen_ori_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
1331 else
1332 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
1333 opn = "ori";
1334 break;
1335 case OPC_XORI:
1336 if (likely(rs != 0))
1337 tcg_gen_xori_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
1338 else
1339 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
1340 opn = "xori";
1341 break;
1342 case OPC_LUI:
1343 tcg_gen_movi_tl(cpu_gpr[rt], imm << 16);
1344 opn = "lui";
1345 break;
1347 MIPS_DEBUG("%s %s, %s, " TARGET_FMT_lx, opn, regnames[rt], regnames[rs], uimm);
1350 /* Set on less than with immediate operand */
1351 static void gen_slt_imm (CPUState *env, uint32_t opc, int rt, int rs, int16_t imm)
1353 target_ulong uimm = (target_long)imm; /* Sign extend to 32/64 bits */
1354 const char *opn = "imm arith";
1355 TCGv t0;
1357 if (rt == 0) {
1358 /* If no destination, treat it as a NOP. */
1359 MIPS_DEBUG("NOP");
1360 return;
1362 t0 = tcg_temp_new();
1363 gen_load_gpr(t0, rs);
1364 switch (opc) {
1365 case OPC_SLTI:
1366 tcg_gen_setcondi_tl(TCG_COND_LT, cpu_gpr[rt], t0, uimm);
1367 opn = "slti";
1368 break;
1369 case OPC_SLTIU:
1370 tcg_gen_setcondi_tl(TCG_COND_LTU, cpu_gpr[rt], t0, uimm);
1371 opn = "sltiu";
1372 break;
1374 MIPS_DEBUG("%s %s, %s, " TARGET_FMT_lx, opn, regnames[rt], regnames[rs], uimm);
1375 tcg_temp_free(t0);
1378 /* Shifts with immediate operand */
1379 static void gen_shift_imm(CPUState *env, DisasContext *ctx, uint32_t opc,
1380 int rt, int rs, int16_t imm)
1382 target_ulong uimm = ((uint16_t)imm) & 0x1f;
1383 const char *opn = "imm shift";
1384 TCGv t0;
1386 if (rt == 0) {
1387 /* If no destination, treat it as a NOP. */
1388 MIPS_DEBUG("NOP");
1389 return;
1392 t0 = tcg_temp_new();
1393 gen_load_gpr(t0, rs);
1394 switch (opc) {
1395 case OPC_SLL:
1396 tcg_gen_shli_tl(t0, t0, uimm);
1397 tcg_gen_ext32s_tl(cpu_gpr[rt], t0);
1398 opn = "sll";
1399 break;
1400 case OPC_SRA:
1401 tcg_gen_sari_tl(cpu_gpr[rt], t0, uimm);
1402 opn = "sra";
1403 break;
1404 case OPC_SRL:
1405 if (uimm != 0) {
1406 tcg_gen_ext32u_tl(t0, t0);
1407 tcg_gen_shri_tl(cpu_gpr[rt], t0, uimm);
1408 } else {
1409 tcg_gen_ext32s_tl(cpu_gpr[rt], t0);
1411 opn = "srl";
1412 break;
1413 case OPC_ROTR:
1414 if (uimm != 0) {
1415 TCGv_i32 t1 = tcg_temp_new_i32();
1417 tcg_gen_trunc_tl_i32(t1, t0);
1418 tcg_gen_rotri_i32(t1, t1, uimm);
1419 tcg_gen_ext_i32_tl(cpu_gpr[rt], t1);
1420 tcg_temp_free_i32(t1);
1421 } else {
1422 tcg_gen_ext32s_tl(cpu_gpr[rt], t0);
1424 opn = "rotr";
1425 break;
1426 #if defined(TARGET_MIPS64)
1427 case OPC_DSLL:
1428 tcg_gen_shli_tl(cpu_gpr[rt], t0, uimm);
1429 opn = "dsll";
1430 break;
1431 case OPC_DSRA:
1432 tcg_gen_sari_tl(cpu_gpr[rt], t0, uimm);
1433 opn = "dsra";
1434 break;
1435 case OPC_DSRL:
1436 tcg_gen_shri_tl(cpu_gpr[rt], t0, uimm);
1437 opn = "dsrl";
1438 break;
1439 case OPC_DROTR:
1440 if (uimm != 0) {
1441 tcg_gen_rotri_tl(cpu_gpr[rt], t0, uimm);
1442 } else {
1443 tcg_gen_mov_tl(cpu_gpr[rt], t0);
1445 opn = "drotr";
1446 break;
1447 case OPC_DSLL32:
1448 tcg_gen_shli_tl(cpu_gpr[rt], t0, uimm + 32);
1449 opn = "dsll32";
1450 break;
1451 case OPC_DSRA32:
1452 tcg_gen_sari_tl(cpu_gpr[rt], t0, uimm + 32);
1453 opn = "dsra32";
1454 break;
1455 case OPC_DSRL32:
1456 tcg_gen_shri_tl(cpu_gpr[rt], t0, uimm + 32);
1457 opn = "dsrl32";
1458 break;
1459 case OPC_DROTR32:
1460 tcg_gen_rotri_tl(cpu_gpr[rt], t0, uimm + 32);
1461 opn = "drotr32";
1462 break;
1463 #endif
1465 MIPS_DEBUG("%s %s, %s, " TARGET_FMT_lx, opn, regnames[rt], regnames[rs], uimm);
1466 tcg_temp_free(t0);
1469 /* Arithmetic */
1470 static void gen_arith (CPUState *env, DisasContext *ctx, uint32_t opc,
1471 int rd, int rs, int rt)
1473 const char *opn = "arith";
1475 if (rd == 0 && opc != OPC_ADD && opc != OPC_SUB
1476 && opc != OPC_DADD && opc != OPC_DSUB) {
1477 /* If no destination, treat it as a NOP.
1478 For add & sub, we must generate the overflow exception when needed. */
1479 MIPS_DEBUG("NOP");
1480 return;
1483 switch (opc) {
1484 case OPC_ADD:
1486 TCGv t0 = tcg_temp_local_new();
1487 TCGv t1 = tcg_temp_new();
1488 TCGv t2 = tcg_temp_new();
1489 int l1 = gen_new_label();
1491 gen_load_gpr(t1, rs);
1492 gen_load_gpr(t2, rt);
1493 tcg_gen_add_tl(t0, t1, t2);
1494 tcg_gen_ext32s_tl(t0, t0);
1495 tcg_gen_xor_tl(t1, t1, t2);
1496 tcg_gen_xor_tl(t2, t0, t2);
1497 tcg_gen_andc_tl(t1, t2, t1);
1498 tcg_temp_free(t2);
1499 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
1500 tcg_temp_free(t1);
1501 /* operands of same sign, result different sign */
1502 generate_exception(ctx, EXCP_OVERFLOW);
1503 gen_set_label(l1);
1504 gen_store_gpr(t0, rd);
1505 tcg_temp_free(t0);
1507 opn = "add";
1508 break;
1509 case OPC_ADDU:
1510 if (rs != 0 && rt != 0) {
1511 tcg_gen_add_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
1512 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
1513 } else if (rs == 0 && rt != 0) {
1514 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
1515 } else if (rs != 0 && rt == 0) {
1516 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
1517 } else {
1518 tcg_gen_movi_tl(cpu_gpr[rd], 0);
1520 opn = "addu";
1521 break;
1522 case OPC_SUB:
1524 TCGv t0 = tcg_temp_local_new();
1525 TCGv t1 = tcg_temp_new();
1526 TCGv t2 = tcg_temp_new();
1527 int l1 = gen_new_label();
1529 gen_load_gpr(t1, rs);
1530 gen_load_gpr(t2, rt);
1531 tcg_gen_sub_tl(t0, t1, t2);
1532 tcg_gen_ext32s_tl(t0, t0);
1533 tcg_gen_xor_tl(t2, t1, t2);
1534 tcg_gen_xor_tl(t1, t0, t1);
1535 tcg_gen_and_tl(t1, t1, t2);
1536 tcg_temp_free(t2);
1537 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
1538 tcg_temp_free(t1);
1539 /* operands of different sign, first operand and result different sign */
1540 generate_exception(ctx, EXCP_OVERFLOW);
1541 gen_set_label(l1);
1542 gen_store_gpr(t0, rd);
1543 tcg_temp_free(t0);
1545 opn = "sub";
1546 break;
1547 case OPC_SUBU:
1548 if (rs != 0 && rt != 0) {
1549 tcg_gen_sub_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
1550 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
1551 } else if (rs == 0 && rt != 0) {
1552 tcg_gen_neg_tl(cpu_gpr[rd], cpu_gpr[rt]);
1553 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
1554 } else if (rs != 0 && rt == 0) {
1555 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
1556 } else {
1557 tcg_gen_movi_tl(cpu_gpr[rd], 0);
1559 opn = "subu";
1560 break;
1561 #if defined(TARGET_MIPS64)
1562 case OPC_DADD:
1564 TCGv t0 = tcg_temp_local_new();
1565 TCGv t1 = tcg_temp_new();
1566 TCGv t2 = tcg_temp_new();
1567 int l1 = gen_new_label();
1569 gen_load_gpr(t1, rs);
1570 gen_load_gpr(t2, rt);
1571 tcg_gen_add_tl(t0, t1, t2);
1572 tcg_gen_xor_tl(t1, t1, t2);
1573 tcg_gen_xor_tl(t2, t0, t2);
1574 tcg_gen_andc_tl(t1, t2, t1);
1575 tcg_temp_free(t2);
1576 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
1577 tcg_temp_free(t1);
1578 /* operands of same sign, result different sign */
1579 generate_exception(ctx, EXCP_OVERFLOW);
1580 gen_set_label(l1);
1581 gen_store_gpr(t0, rd);
1582 tcg_temp_free(t0);
1584 opn = "dadd";
1585 break;
1586 case OPC_DADDU:
1587 if (rs != 0 && rt != 0) {
1588 tcg_gen_add_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
1589 } else if (rs == 0 && rt != 0) {
1590 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
1591 } else if (rs != 0 && rt == 0) {
1592 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
1593 } else {
1594 tcg_gen_movi_tl(cpu_gpr[rd], 0);
1596 opn = "daddu";
1597 break;
1598 case OPC_DSUB:
1600 TCGv t0 = tcg_temp_local_new();
1601 TCGv t1 = tcg_temp_new();
1602 TCGv t2 = tcg_temp_new();
1603 int l1 = gen_new_label();
1605 gen_load_gpr(t1, rs);
1606 gen_load_gpr(t2, rt);
1607 tcg_gen_sub_tl(t0, t1, t2);
1608 tcg_gen_xor_tl(t2, t1, t2);
1609 tcg_gen_xor_tl(t1, t0, t1);
1610 tcg_gen_and_tl(t1, t1, t2);
1611 tcg_temp_free(t2);
1612 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
1613 tcg_temp_free(t1);
1614 /* operands of different sign, first operand and result different sign */
1615 generate_exception(ctx, EXCP_OVERFLOW);
1616 gen_set_label(l1);
1617 gen_store_gpr(t0, rd);
1618 tcg_temp_free(t0);
1620 opn = "dsub";
1621 break;
1622 case OPC_DSUBU:
1623 if (rs != 0 && rt != 0) {
1624 tcg_gen_sub_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
1625 } else if (rs == 0 && rt != 0) {
1626 tcg_gen_neg_tl(cpu_gpr[rd], cpu_gpr[rt]);
1627 } else if (rs != 0 && rt == 0) {
1628 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
1629 } else {
1630 tcg_gen_movi_tl(cpu_gpr[rd], 0);
1632 opn = "dsubu";
1633 break;
1634 #endif
1635 case OPC_MUL:
1636 if (likely(rs != 0 && rt != 0)) {
1637 tcg_gen_mul_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
1638 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
1639 } else {
1640 tcg_gen_movi_tl(cpu_gpr[rd], 0);
1642 opn = "mul";
1643 break;
1645 MIPS_DEBUG("%s %s, %s, %s", opn, regnames[rd], regnames[rs], regnames[rt]);
1648 /* Conditional move */
1649 static void gen_cond_move (CPUState *env, uint32_t opc, int rd, int rs, int rt)
1651 const char *opn = "cond move";
1652 int l1;
1654 if (rd == 0) {
1655 /* If no destination, treat it as a NOP.
1656 For add & sub, we must generate the overflow exception when needed. */
1657 MIPS_DEBUG("NOP");
1658 return;
1661 l1 = gen_new_label();
1662 switch (opc) {
1663 case OPC_MOVN:
1664 if (likely(rt != 0))
1665 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[rt], 0, l1);
1666 else
1667 tcg_gen_br(l1);
1668 opn = "movn";
1669 break;
1670 case OPC_MOVZ:
1671 if (likely(rt != 0))
1672 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[rt], 0, l1);
1673 opn = "movz";
1674 break;
1676 if (rs != 0)
1677 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
1678 else
1679 tcg_gen_movi_tl(cpu_gpr[rd], 0);
1680 gen_set_label(l1);
1682 MIPS_DEBUG("%s %s, %s, %s", opn, regnames[rd], regnames[rs], regnames[rt]);
1685 /* Logic */
1686 static void gen_logic (CPUState *env, uint32_t opc, int rd, int rs, int rt)
1688 const char *opn = "logic";
1690 if (rd == 0) {
1691 /* If no destination, treat it as a NOP. */
1692 MIPS_DEBUG("NOP");
1693 return;
1696 switch (opc) {
1697 case OPC_AND:
1698 if (likely(rs != 0 && rt != 0)) {
1699 tcg_gen_and_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
1700 } else {
1701 tcg_gen_movi_tl(cpu_gpr[rd], 0);
1703 opn = "and";
1704 break;
1705 case OPC_NOR:
1706 if (rs != 0 && rt != 0) {
1707 tcg_gen_nor_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
1708 } else if (rs == 0 && rt != 0) {
1709 tcg_gen_not_tl(cpu_gpr[rd], cpu_gpr[rt]);
1710 } else if (rs != 0 && rt == 0) {
1711 tcg_gen_not_tl(cpu_gpr[rd], cpu_gpr[rs]);
1712 } else {
1713 tcg_gen_movi_tl(cpu_gpr[rd], ~((target_ulong)0));
1715 opn = "nor";
1716 break;
1717 case OPC_OR:
1718 if (likely(rs != 0 && rt != 0)) {
1719 tcg_gen_or_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
1720 } else if (rs == 0 && rt != 0) {
1721 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
1722 } else if (rs != 0 && rt == 0) {
1723 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
1724 } else {
1725 tcg_gen_movi_tl(cpu_gpr[rd], 0);
1727 opn = "or";
1728 break;
1729 case OPC_XOR:
1730 if (likely(rs != 0 && rt != 0)) {
1731 tcg_gen_xor_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
1732 } else if (rs == 0 && rt != 0) {
1733 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
1734 } else if (rs != 0 && rt == 0) {
1735 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
1736 } else {
1737 tcg_gen_movi_tl(cpu_gpr[rd], 0);
1739 opn = "xor";
1740 break;
1742 MIPS_DEBUG("%s %s, %s, %s", opn, regnames[rd], regnames[rs], regnames[rt]);
1745 /* Set on lower than */
1746 static void gen_slt (CPUState *env, uint32_t opc, int rd, int rs, int rt)
1748 const char *opn = "slt";
1749 TCGv t0, t1;
1751 if (rd == 0) {
1752 /* If no destination, treat it as a NOP. */
1753 MIPS_DEBUG("NOP");
1754 return;
1757 t0 = tcg_temp_new();
1758 t1 = tcg_temp_new();
1759 gen_load_gpr(t0, rs);
1760 gen_load_gpr(t1, rt);
1761 switch (opc) {
1762 case OPC_SLT:
1763 tcg_gen_setcond_tl(TCG_COND_LT, cpu_gpr[rd], t0, t1);
1764 opn = "slt";
1765 break;
1766 case OPC_SLTU:
1767 tcg_gen_setcond_tl(TCG_COND_LTU, cpu_gpr[rd], t0, t1);
1768 opn = "sltu";
1769 break;
1771 MIPS_DEBUG("%s %s, %s, %s", opn, regnames[rd], regnames[rs], regnames[rt]);
1772 tcg_temp_free(t0);
1773 tcg_temp_free(t1);
1776 /* Shifts */
1777 static void gen_shift (CPUState *env, DisasContext *ctx, uint32_t opc,
1778 int rd, int rs, int rt)
1780 const char *opn = "shifts";
1781 TCGv t0, t1;
1783 if (rd == 0) {
1784 /* If no destination, treat it as a NOP.
1785 For add & sub, we must generate the overflow exception when needed. */
1786 MIPS_DEBUG("NOP");
1787 return;
1790 t0 = tcg_temp_new();
1791 t1 = tcg_temp_new();
1792 gen_load_gpr(t0, rs);
1793 gen_load_gpr(t1, rt);
1794 switch (opc) {
1795 case OPC_SLLV:
1796 tcg_gen_andi_tl(t0, t0, 0x1f);
1797 tcg_gen_shl_tl(t0, t1, t0);
1798 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
1799 opn = "sllv";
1800 break;
1801 case OPC_SRAV:
1802 tcg_gen_andi_tl(t0, t0, 0x1f);
1803 tcg_gen_sar_tl(cpu_gpr[rd], t1, t0);
1804 opn = "srav";
1805 break;
1806 case OPC_SRLV:
1807 tcg_gen_ext32u_tl(t1, t1);
1808 tcg_gen_andi_tl(t0, t0, 0x1f);
1809 tcg_gen_shr_tl(t0, t1, t0);
1810 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
1811 opn = "srlv";
1812 break;
1813 case OPC_ROTRV:
1815 TCGv_i32 t2 = tcg_temp_new_i32();
1816 TCGv_i32 t3 = tcg_temp_new_i32();
1818 tcg_gen_trunc_tl_i32(t2, t0);
1819 tcg_gen_trunc_tl_i32(t3, t1);
1820 tcg_gen_andi_i32(t2, t2, 0x1f);
1821 tcg_gen_rotr_i32(t2, t3, t2);
1822 tcg_gen_ext_i32_tl(cpu_gpr[rd], t2);
1823 tcg_temp_free_i32(t2);
1824 tcg_temp_free_i32(t3);
1825 opn = "rotrv";
1827 break;
1828 #if defined(TARGET_MIPS64)
1829 case OPC_DSLLV:
1830 tcg_gen_andi_tl(t0, t0, 0x3f);
1831 tcg_gen_shl_tl(cpu_gpr[rd], t1, t0);
1832 opn = "dsllv";
1833 break;
1834 case OPC_DSRAV:
1835 tcg_gen_andi_tl(t0, t0, 0x3f);
1836 tcg_gen_sar_tl(cpu_gpr[rd], t1, t0);
1837 opn = "dsrav";
1838 break;
1839 case OPC_DSRLV:
1840 tcg_gen_andi_tl(t0, t0, 0x3f);
1841 tcg_gen_shr_tl(cpu_gpr[rd], t1, t0);
1842 opn = "dsrlv";
1843 break;
1844 case OPC_DROTRV:
1845 tcg_gen_andi_tl(t0, t0, 0x3f);
1846 tcg_gen_rotr_tl(cpu_gpr[rd], t1, t0);
1847 opn = "drotrv";
1848 break;
1849 #endif
1851 MIPS_DEBUG("%s %s, %s, %s", opn, regnames[rd], regnames[rs], regnames[rt]);
1852 tcg_temp_free(t0);
1853 tcg_temp_free(t1);
1856 /* Arithmetic on HI/LO registers */
1857 static void gen_HILO (DisasContext *ctx, uint32_t opc, int reg)
1859 const char *opn = "hilo";
1861 if (reg == 0 && (opc == OPC_MFHI || opc == OPC_MFLO)) {
1862 /* Treat as NOP. */
1863 MIPS_DEBUG("NOP");
1864 return;
1866 switch (opc) {
1867 case OPC_MFHI:
1868 tcg_gen_mov_tl(cpu_gpr[reg], cpu_HI[0]);
1869 opn = "mfhi";
1870 break;
1871 case OPC_MFLO:
1872 tcg_gen_mov_tl(cpu_gpr[reg], cpu_LO[0]);
1873 opn = "mflo";
1874 break;
1875 case OPC_MTHI:
1876 if (reg != 0)
1877 tcg_gen_mov_tl(cpu_HI[0], cpu_gpr[reg]);
1878 else
1879 tcg_gen_movi_tl(cpu_HI[0], 0);
1880 opn = "mthi";
1881 break;
1882 case OPC_MTLO:
1883 if (reg != 0)
1884 tcg_gen_mov_tl(cpu_LO[0], cpu_gpr[reg]);
1885 else
1886 tcg_gen_movi_tl(cpu_LO[0], 0);
1887 opn = "mtlo";
1888 break;
1890 MIPS_DEBUG("%s %s", opn, regnames[reg]);
1893 static void gen_muldiv (DisasContext *ctx, uint32_t opc,
1894 int rs, int rt)
1896 const char *opn = "mul/div";
1897 TCGv t0, t1;
1899 switch (opc) {
1900 case OPC_DIV:
1901 case OPC_DIVU:
1902 #if defined(TARGET_MIPS64)
1903 case OPC_DDIV:
1904 case OPC_DDIVU:
1905 #endif
1906 t0 = tcg_temp_local_new();
1907 t1 = tcg_temp_local_new();
1908 break;
1909 default:
1910 t0 = tcg_temp_new();
1911 t1 = tcg_temp_new();
1912 break;
1915 gen_load_gpr(t0, rs);
1916 gen_load_gpr(t1, rt);
1917 switch (opc) {
1918 case OPC_DIV:
1920 int l1 = gen_new_label();
1921 int l2 = gen_new_label();
1923 tcg_gen_ext32s_tl(t0, t0);
1924 tcg_gen_ext32s_tl(t1, t1);
1925 tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
1926 tcg_gen_brcondi_tl(TCG_COND_NE, t0, INT_MIN, l2);
1927 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1, l2);
1929 tcg_gen_mov_tl(cpu_LO[0], t0);
1930 tcg_gen_movi_tl(cpu_HI[0], 0);
1931 tcg_gen_br(l1);
1932 gen_set_label(l2);
1933 tcg_gen_div_tl(cpu_LO[0], t0, t1);
1934 tcg_gen_rem_tl(cpu_HI[0], t0, t1);
1935 tcg_gen_ext32s_tl(cpu_LO[0], cpu_LO[0]);
1936 tcg_gen_ext32s_tl(cpu_HI[0], cpu_HI[0]);
1937 gen_set_label(l1);
1939 opn = "div";
1940 break;
1941 case OPC_DIVU:
1943 int l1 = gen_new_label();
1945 tcg_gen_ext32u_tl(t0, t0);
1946 tcg_gen_ext32u_tl(t1, t1);
1947 tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
1948 tcg_gen_divu_tl(cpu_LO[0], t0, t1);
1949 tcg_gen_remu_tl(cpu_HI[0], t0, t1);
1950 tcg_gen_ext32s_tl(cpu_LO[0], cpu_LO[0]);
1951 tcg_gen_ext32s_tl(cpu_HI[0], cpu_HI[0]);
1952 gen_set_label(l1);
1954 opn = "divu";
1955 break;
1956 case OPC_MULT:
1958 TCGv_i64 t2 = tcg_temp_new_i64();
1959 TCGv_i64 t3 = tcg_temp_new_i64();
1961 tcg_gen_ext_tl_i64(t2, t0);
1962 tcg_gen_ext_tl_i64(t3, t1);
1963 tcg_gen_mul_i64(t2, t2, t3);
1964 tcg_temp_free_i64(t3);
1965 tcg_gen_trunc_i64_tl(t0, t2);
1966 tcg_gen_shri_i64(t2, t2, 32);
1967 tcg_gen_trunc_i64_tl(t1, t2);
1968 tcg_temp_free_i64(t2);
1969 tcg_gen_ext32s_tl(cpu_LO[0], t0);
1970 tcg_gen_ext32s_tl(cpu_HI[0], t1);
1972 opn = "mult";
1973 break;
1974 case OPC_MULTU:
1976 TCGv_i64 t2 = tcg_temp_new_i64();
1977 TCGv_i64 t3 = tcg_temp_new_i64();
1979 tcg_gen_ext32u_tl(t0, t0);
1980 tcg_gen_ext32u_tl(t1, t1);
1981 tcg_gen_extu_tl_i64(t2, t0);
1982 tcg_gen_extu_tl_i64(t3, t1);
1983 tcg_gen_mul_i64(t2, t2, t3);
1984 tcg_temp_free_i64(t3);
1985 tcg_gen_trunc_i64_tl(t0, t2);
1986 tcg_gen_shri_i64(t2, t2, 32);
1987 tcg_gen_trunc_i64_tl(t1, t2);
1988 tcg_temp_free_i64(t2);
1989 tcg_gen_ext32s_tl(cpu_LO[0], t0);
1990 tcg_gen_ext32s_tl(cpu_HI[0], t1);
1992 opn = "multu";
1993 break;
1994 #if defined(TARGET_MIPS64)
1995 case OPC_DDIV:
1997 int l1 = gen_new_label();
1998 int l2 = gen_new_label();
2000 tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
2001 tcg_gen_brcondi_tl(TCG_COND_NE, t0, -1LL << 63, l2);
2002 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1LL, l2);
2003 tcg_gen_mov_tl(cpu_LO[0], t0);
2004 tcg_gen_movi_tl(cpu_HI[0], 0);
2005 tcg_gen_br(l1);
2006 gen_set_label(l2);
2007 tcg_gen_div_i64(cpu_LO[0], t0, t1);
2008 tcg_gen_rem_i64(cpu_HI[0], t0, t1);
2009 gen_set_label(l1);
2011 opn = "ddiv";
2012 break;
2013 case OPC_DDIVU:
2015 int l1 = gen_new_label();
2017 tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
2018 tcg_gen_divu_i64(cpu_LO[0], t0, t1);
2019 tcg_gen_remu_i64(cpu_HI[0], t0, t1);
2020 gen_set_label(l1);
2022 opn = "ddivu";
2023 break;
2024 case OPC_DMULT:
2025 gen_helper_dmult(t0, t1);
2026 opn = "dmult";
2027 break;
2028 case OPC_DMULTU:
2029 gen_helper_dmultu(t0, t1);
2030 opn = "dmultu";
2031 break;
2032 #endif
2033 case OPC_MADD:
2035 TCGv_i64 t2 = tcg_temp_new_i64();
2036 TCGv_i64 t3 = tcg_temp_new_i64();
2038 tcg_gen_ext_tl_i64(t2, t0);
2039 tcg_gen_ext_tl_i64(t3, t1);
2040 tcg_gen_mul_i64(t2, t2, t3);
2041 tcg_gen_concat_tl_i64(t3, cpu_LO[0], cpu_HI[0]);
2042 tcg_gen_add_i64(t2, t2, t3);
2043 tcg_temp_free_i64(t3);
2044 tcg_gen_trunc_i64_tl(t0, t2);
2045 tcg_gen_shri_i64(t2, t2, 32);
2046 tcg_gen_trunc_i64_tl(t1, t2);
2047 tcg_temp_free_i64(t2);
2048 tcg_gen_ext32s_tl(cpu_LO[0], t0);
2049 tcg_gen_ext32s_tl(cpu_HI[0], t1);
2051 opn = "madd";
2052 break;
2053 case OPC_MADDU:
2055 TCGv_i64 t2 = tcg_temp_new_i64();
2056 TCGv_i64 t3 = tcg_temp_new_i64();
2058 tcg_gen_ext32u_tl(t0, t0);
2059 tcg_gen_ext32u_tl(t1, t1);
2060 tcg_gen_extu_tl_i64(t2, t0);
2061 tcg_gen_extu_tl_i64(t3, t1);
2062 tcg_gen_mul_i64(t2, t2, t3);
2063 tcg_gen_concat_tl_i64(t3, cpu_LO[0], cpu_HI[0]);
2064 tcg_gen_add_i64(t2, t2, t3);
2065 tcg_temp_free_i64(t3);
2066 tcg_gen_trunc_i64_tl(t0, t2);
2067 tcg_gen_shri_i64(t2, t2, 32);
2068 tcg_gen_trunc_i64_tl(t1, t2);
2069 tcg_temp_free_i64(t2);
2070 tcg_gen_ext32s_tl(cpu_LO[0], t0);
2071 tcg_gen_ext32s_tl(cpu_HI[0], t1);
2073 opn = "maddu";
2074 break;
2075 case OPC_MSUB:
2077 TCGv_i64 t2 = tcg_temp_new_i64();
2078 TCGv_i64 t3 = tcg_temp_new_i64();
2080 tcg_gen_ext_tl_i64(t2, t0);
2081 tcg_gen_ext_tl_i64(t3, t1);
2082 tcg_gen_mul_i64(t2, t2, t3);
2083 tcg_gen_concat_tl_i64(t3, cpu_LO[0], cpu_HI[0]);
2084 tcg_gen_sub_i64(t2, t3, t2);
2085 tcg_temp_free_i64(t3);
2086 tcg_gen_trunc_i64_tl(t0, t2);
2087 tcg_gen_shri_i64(t2, t2, 32);
2088 tcg_gen_trunc_i64_tl(t1, t2);
2089 tcg_temp_free_i64(t2);
2090 tcg_gen_ext32s_tl(cpu_LO[0], t0);
2091 tcg_gen_ext32s_tl(cpu_HI[0], t1);
2093 opn = "msub";
2094 break;
2095 case OPC_MSUBU:
2097 TCGv_i64 t2 = tcg_temp_new_i64();
2098 TCGv_i64 t3 = tcg_temp_new_i64();
2100 tcg_gen_ext32u_tl(t0, t0);
2101 tcg_gen_ext32u_tl(t1, t1);
2102 tcg_gen_extu_tl_i64(t2, t0);
2103 tcg_gen_extu_tl_i64(t3, t1);
2104 tcg_gen_mul_i64(t2, t2, t3);
2105 tcg_gen_concat_tl_i64(t3, cpu_LO[0], cpu_HI[0]);
2106 tcg_gen_sub_i64(t2, t3, t2);
2107 tcg_temp_free_i64(t3);
2108 tcg_gen_trunc_i64_tl(t0, t2);
2109 tcg_gen_shri_i64(t2, t2, 32);
2110 tcg_gen_trunc_i64_tl(t1, t2);
2111 tcg_temp_free_i64(t2);
2112 tcg_gen_ext32s_tl(cpu_LO[0], t0);
2113 tcg_gen_ext32s_tl(cpu_HI[0], t1);
2115 opn = "msubu";
2116 break;
2117 default:
2118 MIPS_INVAL(opn);
2119 generate_exception(ctx, EXCP_RI);
2120 goto out;
2122 MIPS_DEBUG("%s %s %s", opn, regnames[rs], regnames[rt]);
2123 out:
2124 tcg_temp_free(t0);
2125 tcg_temp_free(t1);
2128 static void gen_mul_vr54xx (DisasContext *ctx, uint32_t opc,
2129 int rd, int rs, int rt)
2131 const char *opn = "mul vr54xx";
2132 TCGv t0 = tcg_temp_new();
2133 TCGv t1 = tcg_temp_new();
2135 gen_load_gpr(t0, rs);
2136 gen_load_gpr(t1, rt);
2138 switch (opc) {
2139 case OPC_VR54XX_MULS:
2140 gen_helper_muls(t0, t0, t1);
2141 opn = "muls";
2142 break;
2143 case OPC_VR54XX_MULSU:
2144 gen_helper_mulsu(t0, t0, t1);
2145 opn = "mulsu";
2146 break;
2147 case OPC_VR54XX_MACC:
2148 gen_helper_macc(t0, t0, t1);
2149 opn = "macc";
2150 break;
2151 case OPC_VR54XX_MACCU:
2152 gen_helper_maccu(t0, t0, t1);
2153 opn = "maccu";
2154 break;
2155 case OPC_VR54XX_MSAC:
2156 gen_helper_msac(t0, t0, t1);
2157 opn = "msac";
2158 break;
2159 case OPC_VR54XX_MSACU:
2160 gen_helper_msacu(t0, t0, t1);
2161 opn = "msacu";
2162 break;
2163 case OPC_VR54XX_MULHI:
2164 gen_helper_mulhi(t0, t0, t1);
2165 opn = "mulhi";
2166 break;
2167 case OPC_VR54XX_MULHIU:
2168 gen_helper_mulhiu(t0, t0, t1);
2169 opn = "mulhiu";
2170 break;
2171 case OPC_VR54XX_MULSHI:
2172 gen_helper_mulshi(t0, t0, t1);
2173 opn = "mulshi";
2174 break;
2175 case OPC_VR54XX_MULSHIU:
2176 gen_helper_mulshiu(t0, t0, t1);
2177 opn = "mulshiu";
2178 break;
2179 case OPC_VR54XX_MACCHI:
2180 gen_helper_macchi(t0, t0, t1);
2181 opn = "macchi";
2182 break;
2183 case OPC_VR54XX_MACCHIU:
2184 gen_helper_macchiu(t0, t0, t1);
2185 opn = "macchiu";
2186 break;
2187 case OPC_VR54XX_MSACHI:
2188 gen_helper_msachi(t0, t0, t1);
2189 opn = "msachi";
2190 break;
2191 case OPC_VR54XX_MSACHIU:
2192 gen_helper_msachiu(t0, t0, t1);
2193 opn = "msachiu";
2194 break;
2195 default:
2196 MIPS_INVAL("mul vr54xx");
2197 generate_exception(ctx, EXCP_RI);
2198 goto out;
2200 gen_store_gpr(t0, rd);
2201 MIPS_DEBUG("%s %s, %s, %s", opn, regnames[rd], regnames[rs], regnames[rt]);
2203 out:
2204 tcg_temp_free(t0);
2205 tcg_temp_free(t1);
2208 static void gen_cl (DisasContext *ctx, uint32_t opc,
2209 int rd, int rs)
2211 const char *opn = "CLx";
2212 TCGv t0;
2214 if (rd == 0) {
2215 /* Treat as NOP. */
2216 MIPS_DEBUG("NOP");
2217 return;
2219 t0 = tcg_temp_new();
2220 gen_load_gpr(t0, rs);
2221 switch (opc) {
2222 case OPC_CLO:
2223 gen_helper_clo(cpu_gpr[rd], t0);
2224 opn = "clo";
2225 break;
2226 case OPC_CLZ:
2227 gen_helper_clz(cpu_gpr[rd], t0);
2228 opn = "clz";
2229 break;
2230 #if defined(TARGET_MIPS64)
2231 case OPC_DCLO:
2232 gen_helper_dclo(cpu_gpr[rd], t0);
2233 opn = "dclo";
2234 break;
2235 case OPC_DCLZ:
2236 gen_helper_dclz(cpu_gpr[rd], t0);
2237 opn = "dclz";
2238 break;
2239 #endif
2241 MIPS_DEBUG("%s %s, %s", opn, regnames[rd], regnames[rs]);
2242 tcg_temp_free(t0);
2245 /* Traps */
2246 static void gen_trap (DisasContext *ctx, uint32_t opc,
2247 int rs, int rt, int16_t imm)
2249 int cond;
2250 TCGv t0 = tcg_temp_new();
2251 TCGv t1 = tcg_temp_new();
2253 cond = 0;
2254 /* Load needed operands */
2255 switch (opc) {
2256 case OPC_TEQ:
2257 case OPC_TGE:
2258 case OPC_TGEU:
2259 case OPC_TLT:
2260 case OPC_TLTU:
2261 case OPC_TNE:
2262 /* Compare two registers */
2263 if (rs != rt) {
2264 gen_load_gpr(t0, rs);
2265 gen_load_gpr(t1, rt);
2266 cond = 1;
2268 break;
2269 case OPC_TEQI:
2270 case OPC_TGEI:
2271 case OPC_TGEIU:
2272 case OPC_TLTI:
2273 case OPC_TLTIU:
2274 case OPC_TNEI:
2275 /* Compare register to immediate */
2276 if (rs != 0 || imm != 0) {
2277 gen_load_gpr(t0, rs);
2278 tcg_gen_movi_tl(t1, (int32_t)imm);
2279 cond = 1;
2281 break;
2283 if (cond == 0) {
2284 switch (opc) {
2285 case OPC_TEQ: /* rs == rs */
2286 case OPC_TEQI: /* r0 == 0 */
2287 case OPC_TGE: /* rs >= rs */
2288 case OPC_TGEI: /* r0 >= 0 */
2289 case OPC_TGEU: /* rs >= rs unsigned */
2290 case OPC_TGEIU: /* r0 >= 0 unsigned */
2291 /* Always trap */
2292 generate_exception(ctx, EXCP_TRAP);
2293 break;
2294 case OPC_TLT: /* rs < rs */
2295 case OPC_TLTI: /* r0 < 0 */
2296 case OPC_TLTU: /* rs < rs unsigned */
2297 case OPC_TLTIU: /* r0 < 0 unsigned */
2298 case OPC_TNE: /* rs != rs */
2299 case OPC_TNEI: /* r0 != 0 */
2300 /* Never trap: treat as NOP. */
2301 break;
2303 } else {
2304 int l1 = gen_new_label();
2306 switch (opc) {
2307 case OPC_TEQ:
2308 case OPC_TEQI:
2309 tcg_gen_brcond_tl(TCG_COND_NE, t0, t1, l1);
2310 break;
2311 case OPC_TGE:
2312 case OPC_TGEI:
2313 tcg_gen_brcond_tl(TCG_COND_LT, t0, t1, l1);
2314 break;
2315 case OPC_TGEU:
2316 case OPC_TGEIU:
2317 tcg_gen_brcond_tl(TCG_COND_LTU, t0, t1, l1);
2318 break;
2319 case OPC_TLT:
2320 case OPC_TLTI:
2321 tcg_gen_brcond_tl(TCG_COND_GE, t0, t1, l1);
2322 break;
2323 case OPC_TLTU:
2324 case OPC_TLTIU:
2325 tcg_gen_brcond_tl(TCG_COND_GEU, t0, t1, l1);
2326 break;
2327 case OPC_TNE:
2328 case OPC_TNEI:
2329 tcg_gen_brcond_tl(TCG_COND_EQ, t0, t1, l1);
2330 break;
2332 generate_exception(ctx, EXCP_TRAP);
2333 gen_set_label(l1);
2335 tcg_temp_free(t0);
2336 tcg_temp_free(t1);
2339 static inline void gen_goto_tb(DisasContext *ctx, int n, target_ulong dest)
2341 TranslationBlock *tb;
2342 tb = ctx->tb;
2343 if ((tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK) &&
2344 likely(!ctx->singlestep_enabled)) {
2345 tcg_gen_goto_tb(n);
2346 gen_save_pc(dest);
2347 tcg_gen_exit_tb((long)tb + n);
2348 } else {
2349 gen_save_pc(dest);
2350 if (ctx->singlestep_enabled) {
2351 save_cpu_state(ctx, 0);
2352 gen_helper_0i(raise_exception, EXCP_DEBUG);
2354 tcg_gen_exit_tb(0);
2358 /* Branches (before delay slot) */
2359 static void gen_compute_branch (DisasContext *ctx, uint32_t opc,
2360 int insn_bytes,
2361 int rs, int rt, int32_t offset)
2363 target_ulong btgt = -1;
2364 int blink = 0;
2365 int bcond_compute = 0;
2366 TCGv t0 = tcg_temp_new();
2367 TCGv t1 = tcg_temp_new();
2369 if (ctx->hflags & MIPS_HFLAG_BMASK) {
2370 #ifdef MIPS_DEBUG_DISAS
2371 LOG_DISAS("Branch in delay slot at PC 0x" TARGET_FMT_lx "\n", ctx->pc);
2372 #endif
2373 generate_exception(ctx, EXCP_RI);
2374 goto out;
2377 /* Load needed operands */
2378 switch (opc) {
2379 case OPC_BEQ:
2380 case OPC_BEQL:
2381 case OPC_BNE:
2382 case OPC_BNEL:
2383 /* Compare two registers */
2384 if (rs != rt) {
2385 gen_load_gpr(t0, rs);
2386 gen_load_gpr(t1, rt);
2387 bcond_compute = 1;
2389 btgt = ctx->pc + insn_bytes + offset;
2390 break;
2391 case OPC_BGEZ:
2392 case OPC_BGEZAL:
2393 case OPC_BGEZALL:
2394 case OPC_BGEZL:
2395 case OPC_BGTZ:
2396 case OPC_BGTZL:
2397 case OPC_BLEZ:
2398 case OPC_BLEZL:
2399 case OPC_BLTZ:
2400 case OPC_BLTZAL:
2401 case OPC_BLTZALL:
2402 case OPC_BLTZL:
2403 /* Compare to zero */
2404 if (rs != 0) {
2405 gen_load_gpr(t0, rs);
2406 bcond_compute = 1;
2408 btgt = ctx->pc + insn_bytes + offset;
2409 break;
2410 case OPC_J:
2411 case OPC_JAL:
2412 case OPC_JALX:
2413 /* Jump to immediate */
2414 btgt = ((ctx->pc + insn_bytes) & (int32_t)0xF0000000) | (uint32_t)offset;
2415 break;
2416 case OPC_JR:
2417 case OPC_JALR:
2418 case OPC_JALRC:
2419 /* Jump to register */
2420 if (offset != 0 && offset != 16) {
2421 /* Hint = 0 is JR/JALR, hint 16 is JR.HB/JALR.HB, the
2422 others are reserved. */
2423 MIPS_INVAL("jump hint");
2424 generate_exception(ctx, EXCP_RI);
2425 goto out;
2427 gen_load_gpr(btarget, rs);
2428 break;
2429 default:
2430 MIPS_INVAL("branch/jump");
2431 generate_exception(ctx, EXCP_RI);
2432 goto out;
2434 if (bcond_compute == 0) {
2435 /* No condition to be computed */
2436 switch (opc) {
2437 case OPC_BEQ: /* rx == rx */
2438 case OPC_BEQL: /* rx == rx likely */
2439 case OPC_BGEZ: /* 0 >= 0 */
2440 case OPC_BGEZL: /* 0 >= 0 likely */
2441 case OPC_BLEZ: /* 0 <= 0 */
2442 case OPC_BLEZL: /* 0 <= 0 likely */
2443 /* Always take */
2444 ctx->hflags |= MIPS_HFLAG_B;
2445 MIPS_DEBUG("balways");
2446 break;
2447 case OPC_BGEZAL: /* 0 >= 0 */
2448 case OPC_BGEZALL: /* 0 >= 0 likely */
2449 /* Always take and link */
2450 blink = 31;
2451 ctx->hflags |= MIPS_HFLAG_B;
2452 MIPS_DEBUG("balways and link");
2453 break;
2454 case OPC_BNE: /* rx != rx */
2455 case OPC_BGTZ: /* 0 > 0 */
2456 case OPC_BLTZ: /* 0 < 0 */
2457 /* Treat as NOP. */
2458 MIPS_DEBUG("bnever (NOP)");
2459 goto out;
2460 case OPC_BLTZAL: /* 0 < 0 */
2461 tcg_gen_movi_tl(cpu_gpr[31], ctx->pc + 8);
2462 MIPS_DEBUG("bnever and link");
2463 goto out;
2464 case OPC_BLTZALL: /* 0 < 0 likely */
2465 tcg_gen_movi_tl(cpu_gpr[31], ctx->pc + 8);
2466 /* Skip the instruction in the delay slot */
2467 MIPS_DEBUG("bnever, link and skip");
2468 ctx->pc += 4;
2469 goto out;
2470 case OPC_BNEL: /* rx != rx likely */
2471 case OPC_BGTZL: /* 0 > 0 likely */
2472 case OPC_BLTZL: /* 0 < 0 likely */
2473 /* Skip the instruction in the delay slot */
2474 MIPS_DEBUG("bnever and skip");
2475 ctx->pc += 4;
2476 goto out;
2477 case OPC_J:
2478 ctx->hflags |= MIPS_HFLAG_B;
2479 MIPS_DEBUG("j " TARGET_FMT_lx, btgt);
2480 break;
2481 case OPC_JALX:
2482 ctx->hflags |= MIPS_HFLAG_BX;
2483 /* Fallthrough */
2484 case OPC_JAL:
2485 blink = 31;
2486 ctx->hflags |= MIPS_HFLAG_B;
2487 ctx->hflags |= (ctx->hflags & MIPS_HFLAG_M16
2488 ? MIPS_HFLAG_BDS16
2489 : MIPS_HFLAG_BDS32);
2490 MIPS_DEBUG("jal " TARGET_FMT_lx, btgt);
2491 break;
2492 case OPC_JR:
2493 ctx->hflags |= MIPS_HFLAG_BR;
2494 if (ctx->hflags & MIPS_HFLAG_M16)
2495 ctx->hflags |= MIPS_HFLAG_BDS16;
2496 MIPS_DEBUG("jr %s", regnames[rs]);
2497 break;
2498 case OPC_JALR:
2499 case OPC_JALRC:
2500 blink = rt;
2501 ctx->hflags |= MIPS_HFLAG_BR;
2502 if (ctx->hflags & MIPS_HFLAG_M16)
2503 ctx->hflags |= MIPS_HFLAG_BDS16;
2504 MIPS_DEBUG("jalr %s, %s", regnames[rt], regnames[rs]);
2505 break;
2506 default:
2507 MIPS_INVAL("branch/jump");
2508 generate_exception(ctx, EXCP_RI);
2509 goto out;
2511 } else {
2512 switch (opc) {
2513 case OPC_BEQ:
2514 tcg_gen_setcond_tl(TCG_COND_EQ, bcond, t0, t1);
2515 MIPS_DEBUG("beq %s, %s, " TARGET_FMT_lx,
2516 regnames[rs], regnames[rt], btgt);
2517 goto not_likely;
2518 case OPC_BEQL:
2519 tcg_gen_setcond_tl(TCG_COND_EQ, bcond, t0, t1);
2520 MIPS_DEBUG("beql %s, %s, " TARGET_FMT_lx,
2521 regnames[rs], regnames[rt], btgt);
2522 goto likely;
2523 case OPC_BNE:
2524 tcg_gen_setcond_tl(TCG_COND_NE, bcond, t0, t1);
2525 MIPS_DEBUG("bne %s, %s, " TARGET_FMT_lx,
2526 regnames[rs], regnames[rt], btgt);
2527 goto not_likely;
2528 case OPC_BNEL:
2529 tcg_gen_setcond_tl(TCG_COND_NE, bcond, t0, t1);
2530 MIPS_DEBUG("bnel %s, %s, " TARGET_FMT_lx,
2531 regnames[rs], regnames[rt], btgt);
2532 goto likely;
2533 case OPC_BGEZ:
2534 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
2535 MIPS_DEBUG("bgez %s, " TARGET_FMT_lx, regnames[rs], btgt);
2536 goto not_likely;
2537 case OPC_BGEZL:
2538 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
2539 MIPS_DEBUG("bgezl %s, " TARGET_FMT_lx, regnames[rs], btgt);
2540 goto likely;
2541 case OPC_BGEZAL:
2542 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
2543 MIPS_DEBUG("bgezal %s, " TARGET_FMT_lx, regnames[rs], btgt);
2544 blink = 31;
2545 goto not_likely;
2546 case OPC_BGEZALL:
2547 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
2548 blink = 31;
2549 MIPS_DEBUG("bgezall %s, " TARGET_FMT_lx, regnames[rs], btgt);
2550 goto likely;
2551 case OPC_BGTZ:
2552 tcg_gen_setcondi_tl(TCG_COND_GT, bcond, t0, 0);
2553 MIPS_DEBUG("bgtz %s, " TARGET_FMT_lx, regnames[rs], btgt);
2554 goto not_likely;
2555 case OPC_BGTZL:
2556 tcg_gen_setcondi_tl(TCG_COND_GT, bcond, t0, 0);
2557 MIPS_DEBUG("bgtzl %s, " TARGET_FMT_lx, regnames[rs], btgt);
2558 goto likely;
2559 case OPC_BLEZ:
2560 tcg_gen_setcondi_tl(TCG_COND_LE, bcond, t0, 0);
2561 MIPS_DEBUG("blez %s, " TARGET_FMT_lx, regnames[rs], btgt);
2562 goto not_likely;
2563 case OPC_BLEZL:
2564 tcg_gen_setcondi_tl(TCG_COND_LE, bcond, t0, 0);
2565 MIPS_DEBUG("blezl %s, " TARGET_FMT_lx, regnames[rs], btgt);
2566 goto likely;
2567 case OPC_BLTZ:
2568 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
2569 MIPS_DEBUG("bltz %s, " TARGET_FMT_lx, regnames[rs], btgt);
2570 goto not_likely;
2571 case OPC_BLTZL:
2572 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
2573 MIPS_DEBUG("bltzl %s, " TARGET_FMT_lx, regnames[rs], btgt);
2574 goto likely;
2575 case OPC_BLTZAL:
2576 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
2577 blink = 31;
2578 MIPS_DEBUG("bltzal %s, " TARGET_FMT_lx, regnames[rs], btgt);
2579 not_likely:
2580 ctx->hflags |= MIPS_HFLAG_BC;
2581 break;
2582 case OPC_BLTZALL:
2583 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
2584 blink = 31;
2585 MIPS_DEBUG("bltzall %s, " TARGET_FMT_lx, regnames[rs], btgt);
2586 likely:
2587 ctx->hflags |= MIPS_HFLAG_BL;
2588 break;
2589 default:
2590 MIPS_INVAL("conditional branch/jump");
2591 generate_exception(ctx, EXCP_RI);
2592 goto out;
2595 MIPS_DEBUG("enter ds: link %d cond %02x target " TARGET_FMT_lx,
2596 blink, ctx->hflags, btgt);
2598 ctx->btarget = btgt;
2599 if (blink > 0) {
2600 int post_delay = insn_bytes;
2601 int lowbit = !!(ctx->hflags & MIPS_HFLAG_M16);
2603 if (opc != OPC_JALRC)
2604 post_delay += ((ctx->hflags & MIPS_HFLAG_BDS16) ? 2 : 4);
2606 tcg_gen_movi_tl(cpu_gpr[blink], ctx->pc + post_delay + lowbit);
2609 out:
2610 if (insn_bytes == 2)
2611 ctx->hflags |= MIPS_HFLAG_B16;
2612 tcg_temp_free(t0);
2613 tcg_temp_free(t1);
2616 /* special3 bitfield operations */
2617 static void gen_bitops (DisasContext *ctx, uint32_t opc, int rt,
2618 int rs, int lsb, int msb)
2620 TCGv t0 = tcg_temp_new();
2621 TCGv t1 = tcg_temp_new();
2622 target_ulong mask;
2624 gen_load_gpr(t1, rs);
2625 switch (opc) {
2626 case OPC_EXT:
2627 if (lsb + msb > 31)
2628 goto fail;
2629 tcg_gen_shri_tl(t0, t1, lsb);
2630 if (msb != 31) {
2631 tcg_gen_andi_tl(t0, t0, (1 << (msb + 1)) - 1);
2632 } else {
2633 tcg_gen_ext32s_tl(t0, t0);
2635 break;
2636 #if defined(TARGET_MIPS64)
2637 case OPC_DEXTM:
2638 tcg_gen_shri_tl(t0, t1, lsb);
2639 if (msb != 31) {
2640 tcg_gen_andi_tl(t0, t0, (1ULL << (msb + 1 + 32)) - 1);
2642 break;
2643 case OPC_DEXTU:
2644 tcg_gen_shri_tl(t0, t1, lsb + 32);
2645 tcg_gen_andi_tl(t0, t0, (1ULL << (msb + 1)) - 1);
2646 break;
2647 case OPC_DEXT:
2648 tcg_gen_shri_tl(t0, t1, lsb);
2649 tcg_gen_andi_tl(t0, t0, (1ULL << (msb + 1)) - 1);
2650 break;
2651 #endif
2652 case OPC_INS:
2653 if (lsb > msb)
2654 goto fail;
2655 mask = ((msb - lsb + 1 < 32) ? ((1 << (msb - lsb + 1)) - 1) : ~0) << lsb;
2656 gen_load_gpr(t0, rt);
2657 tcg_gen_andi_tl(t0, t0, ~mask);
2658 tcg_gen_shli_tl(t1, t1, lsb);
2659 tcg_gen_andi_tl(t1, t1, mask);
2660 tcg_gen_or_tl(t0, t0, t1);
2661 tcg_gen_ext32s_tl(t0, t0);
2662 break;
2663 #if defined(TARGET_MIPS64)
2664 case OPC_DINSM:
2665 if (lsb > msb)
2666 goto fail;
2667 mask = ((msb - lsb + 1 + 32 < 64) ? ((1ULL << (msb - lsb + 1 + 32)) - 1) : ~0ULL) << lsb;
2668 gen_load_gpr(t0, rt);
2669 tcg_gen_andi_tl(t0, t0, ~mask);
2670 tcg_gen_shli_tl(t1, t1, lsb);
2671 tcg_gen_andi_tl(t1, t1, mask);
2672 tcg_gen_or_tl(t0, t0, t1);
2673 break;
2674 case OPC_DINSU:
2675 if (lsb > msb)
2676 goto fail;
2677 mask = ((1ULL << (msb - lsb + 1)) - 1) << lsb;
2678 gen_load_gpr(t0, rt);
2679 tcg_gen_andi_tl(t0, t0, ~mask);
2680 tcg_gen_shli_tl(t1, t1, lsb + 32);
2681 tcg_gen_andi_tl(t1, t1, mask);
2682 tcg_gen_or_tl(t0, t0, t1);
2683 break;
2684 case OPC_DINS:
2685 if (lsb > msb)
2686 goto fail;
2687 gen_load_gpr(t0, rt);
2688 mask = ((1ULL << (msb - lsb + 1)) - 1) << lsb;
2689 gen_load_gpr(t0, rt);
2690 tcg_gen_andi_tl(t0, t0, ~mask);
2691 tcg_gen_shli_tl(t1, t1, lsb);
2692 tcg_gen_andi_tl(t1, t1, mask);
2693 tcg_gen_or_tl(t0, t0, t1);
2694 break;
2695 #endif
2696 default:
2697 fail:
2698 MIPS_INVAL("bitops");
2699 generate_exception(ctx, EXCP_RI);
2700 tcg_temp_free(t0);
2701 tcg_temp_free(t1);
2702 return;
2704 gen_store_gpr(t0, rt);
2705 tcg_temp_free(t0);
2706 tcg_temp_free(t1);
2709 static void gen_bshfl (DisasContext *ctx, uint32_t op2, int rt, int rd)
2711 TCGv t0;
2713 if (rd == 0) {
2714 /* If no destination, treat it as a NOP. */
2715 MIPS_DEBUG("NOP");
2716 return;
2719 t0 = tcg_temp_new();
2720 gen_load_gpr(t0, rt);
2721 switch (op2) {
2722 case OPC_WSBH:
2724 TCGv t1 = tcg_temp_new();
2726 tcg_gen_shri_tl(t1, t0, 8);
2727 tcg_gen_andi_tl(t1, t1, 0x00FF00FF);
2728 tcg_gen_shli_tl(t0, t0, 8);
2729 tcg_gen_andi_tl(t0, t0, ~0x00FF00FF);
2730 tcg_gen_or_tl(t0, t0, t1);
2731 tcg_temp_free(t1);
2732 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
2734 break;
2735 case OPC_SEB:
2736 tcg_gen_ext8s_tl(cpu_gpr[rd], t0);
2737 break;
2738 case OPC_SEH:
2739 tcg_gen_ext16s_tl(cpu_gpr[rd], t0);
2740 break;
2741 #if defined(TARGET_MIPS64)
2742 case OPC_DSBH:
2744 TCGv t1 = tcg_temp_new();
2746 tcg_gen_shri_tl(t1, t0, 8);
2747 tcg_gen_andi_tl(t1, t1, 0x00FF00FF00FF00FFULL);
2748 tcg_gen_shli_tl(t0, t0, 8);
2749 tcg_gen_andi_tl(t0, t0, ~0x00FF00FF00FF00FFULL);
2750 tcg_gen_or_tl(cpu_gpr[rd], t0, t1);
2751 tcg_temp_free(t1);
2753 break;
2754 case OPC_DSHD:
2756 TCGv t1 = tcg_temp_new();
2758 tcg_gen_shri_tl(t1, t0, 16);
2759 tcg_gen_andi_tl(t1, t1, 0x0000FFFF0000FFFFULL);
2760 tcg_gen_shli_tl(t0, t0, 16);
2761 tcg_gen_andi_tl(t0, t0, ~0x0000FFFF0000FFFFULL);
2762 tcg_gen_or_tl(t0, t0, t1);
2763 tcg_gen_shri_tl(t1, t0, 32);
2764 tcg_gen_shli_tl(t0, t0, 32);
2765 tcg_gen_or_tl(cpu_gpr[rd], t0, t1);
2766 tcg_temp_free(t1);
2768 break;
2769 #endif
2770 default:
2771 MIPS_INVAL("bsfhl");
2772 generate_exception(ctx, EXCP_RI);
2773 tcg_temp_free(t0);
2774 return;
2776 tcg_temp_free(t0);
2779 #ifndef CONFIG_USER_ONLY
2780 /* CP0 (MMU and control) */
2781 static inline void gen_mfc0_load32 (TCGv arg, target_ulong off)
2783 TCGv_i32 t0 = tcg_temp_new_i32();
2785 tcg_gen_ld_i32(t0, cpu_env, off);
2786 tcg_gen_ext_i32_tl(arg, t0);
2787 tcg_temp_free_i32(t0);
2790 static inline void gen_mfc0_load64 (TCGv arg, target_ulong off)
2792 tcg_gen_ld_tl(arg, cpu_env, off);
2793 tcg_gen_ext32s_tl(arg, arg);
2796 static inline void gen_mtc0_store32 (TCGv arg, target_ulong off)
2798 TCGv_i32 t0 = tcg_temp_new_i32();
2800 tcg_gen_trunc_tl_i32(t0, arg);
2801 tcg_gen_st_i32(t0, cpu_env, off);
2802 tcg_temp_free_i32(t0);
2805 static inline void gen_mtc0_store64 (TCGv arg, target_ulong off)
2807 tcg_gen_ext32s_tl(arg, arg);
2808 tcg_gen_st_tl(arg, cpu_env, off);
2811 static void gen_mfc0 (CPUState *env, DisasContext *ctx, TCGv arg, int reg, int sel)
2813 const char *rn = "invalid";
2815 if (sel != 0)
2816 check_insn(env, ctx, ISA_MIPS32);
2818 switch (reg) {
2819 case 0:
2820 switch (sel) {
2821 case 0:
2822 gen_mfc0_load32(arg, offsetof(CPUState, CP0_Index));
2823 rn = "Index";
2824 break;
2825 case 1:
2826 check_insn(env, ctx, ASE_MT);
2827 gen_helper_mfc0_mvpcontrol(arg);
2828 rn = "MVPControl";
2829 break;
2830 case 2:
2831 check_insn(env, ctx, ASE_MT);
2832 gen_helper_mfc0_mvpconf0(arg);
2833 rn = "MVPConf0";
2834 break;
2835 case 3:
2836 check_insn(env, ctx, ASE_MT);
2837 gen_helper_mfc0_mvpconf1(arg);
2838 rn = "MVPConf1";
2839 break;
2840 default:
2841 goto die;
2843 break;
2844 case 1:
2845 switch (sel) {
2846 case 0:
2847 gen_helper_mfc0_random(arg);
2848 rn = "Random";
2849 break;
2850 case 1:
2851 check_insn(env, ctx, ASE_MT);
2852 gen_mfc0_load32(arg, offsetof(CPUState, CP0_VPEControl));
2853 rn = "VPEControl";
2854 break;
2855 case 2:
2856 check_insn(env, ctx, ASE_MT);
2857 gen_mfc0_load32(arg, offsetof(CPUState, CP0_VPEConf0));
2858 rn = "VPEConf0";
2859 break;
2860 case 3:
2861 check_insn(env, ctx, ASE_MT);
2862 gen_mfc0_load32(arg, offsetof(CPUState, CP0_VPEConf1));
2863 rn = "VPEConf1";
2864 break;
2865 case 4:
2866 check_insn(env, ctx, ASE_MT);
2867 gen_mfc0_load64(arg, offsetof(CPUState, CP0_YQMask));
2868 rn = "YQMask";
2869 break;
2870 case 5:
2871 check_insn(env, ctx, ASE_MT);
2872 gen_mfc0_load64(arg, offsetof(CPUState, CP0_VPESchedule));
2873 rn = "VPESchedule";
2874 break;
2875 case 6:
2876 check_insn(env, ctx, ASE_MT);
2877 gen_mfc0_load64(arg, offsetof(CPUState, CP0_VPEScheFBack));
2878 rn = "VPEScheFBack";
2879 break;
2880 case 7:
2881 check_insn(env, ctx, ASE_MT);
2882 gen_mfc0_load32(arg, offsetof(CPUState, CP0_VPEOpt));
2883 rn = "VPEOpt";
2884 break;
2885 default:
2886 goto die;
2888 break;
2889 case 2:
2890 switch (sel) {
2891 case 0:
2892 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_EntryLo0));
2893 tcg_gen_ext32s_tl(arg, arg);
2894 rn = "EntryLo0";
2895 break;
2896 case 1:
2897 check_insn(env, ctx, ASE_MT);
2898 gen_helper_mfc0_tcstatus(arg);
2899 rn = "TCStatus";
2900 break;
2901 case 2:
2902 check_insn(env, ctx, ASE_MT);
2903 gen_helper_mfc0_tcbind(arg);
2904 rn = "TCBind";
2905 break;
2906 case 3:
2907 check_insn(env, ctx, ASE_MT);
2908 gen_helper_mfc0_tcrestart(arg);
2909 rn = "TCRestart";
2910 break;
2911 case 4:
2912 check_insn(env, ctx, ASE_MT);
2913 gen_helper_mfc0_tchalt(arg);
2914 rn = "TCHalt";
2915 break;
2916 case 5:
2917 check_insn(env, ctx, ASE_MT);
2918 gen_helper_mfc0_tccontext(arg);
2919 rn = "TCContext";
2920 break;
2921 case 6:
2922 check_insn(env, ctx, ASE_MT);
2923 gen_helper_mfc0_tcschedule(arg);
2924 rn = "TCSchedule";
2925 break;
2926 case 7:
2927 check_insn(env, ctx, ASE_MT);
2928 gen_helper_mfc0_tcschefback(arg);
2929 rn = "TCScheFBack";
2930 break;
2931 default:
2932 goto die;
2934 break;
2935 case 3:
2936 switch (sel) {
2937 case 0:
2938 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_EntryLo1));
2939 tcg_gen_ext32s_tl(arg, arg);
2940 rn = "EntryLo1";
2941 break;
2942 default:
2943 goto die;
2945 break;
2946 case 4:
2947 switch (sel) {
2948 case 0:
2949 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_Context));
2950 tcg_gen_ext32s_tl(arg, arg);
2951 rn = "Context";
2952 break;
2953 case 1:
2954 // gen_helper_mfc0_contextconfig(arg); /* SmartMIPS ASE */
2955 rn = "ContextConfig";
2956 // break;
2957 default:
2958 goto die;
2960 break;
2961 case 5:
2962 switch (sel) {
2963 case 0:
2964 gen_mfc0_load32(arg, offsetof(CPUState, CP0_PageMask));
2965 rn = "PageMask";
2966 break;
2967 case 1:
2968 check_insn(env, ctx, ISA_MIPS32R2);
2969 gen_mfc0_load32(arg, offsetof(CPUState, CP0_PageGrain));
2970 rn = "PageGrain";
2971 break;
2972 default:
2973 goto die;
2975 break;
2976 case 6:
2977 switch (sel) {
2978 case 0:
2979 gen_mfc0_load32(arg, offsetof(CPUState, CP0_Wired));
2980 rn = "Wired";
2981 break;
2982 case 1:
2983 check_insn(env, ctx, ISA_MIPS32R2);
2984 gen_mfc0_load32(arg, offsetof(CPUState, CP0_SRSConf0));
2985 rn = "SRSConf0";
2986 break;
2987 case 2:
2988 check_insn(env, ctx, ISA_MIPS32R2);
2989 gen_mfc0_load32(arg, offsetof(CPUState, CP0_SRSConf1));
2990 rn = "SRSConf1";
2991 break;
2992 case 3:
2993 check_insn(env, ctx, ISA_MIPS32R2);
2994 gen_mfc0_load32(arg, offsetof(CPUState, CP0_SRSConf2));
2995 rn = "SRSConf2";
2996 break;
2997 case 4:
2998 check_insn(env, ctx, ISA_MIPS32R2);
2999 gen_mfc0_load32(arg, offsetof(CPUState, CP0_SRSConf3));
3000 rn = "SRSConf3";
3001 break;
3002 case 5:
3003 check_insn(env, ctx, ISA_MIPS32R2);
3004 gen_mfc0_load32(arg, offsetof(CPUState, CP0_SRSConf4));
3005 rn = "SRSConf4";
3006 break;
3007 default:
3008 goto die;
3010 break;
3011 case 7:
3012 switch (sel) {
3013 case 0:
3014 check_insn(env, ctx, ISA_MIPS32R2);
3015 gen_mfc0_load32(arg, offsetof(CPUState, CP0_HWREna));
3016 rn = "HWREna";
3017 break;
3018 default:
3019 goto die;
3021 break;
3022 case 8:
3023 switch (sel) {
3024 case 0:
3025 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_BadVAddr));
3026 tcg_gen_ext32s_tl(arg, arg);
3027 rn = "BadVAddr";
3028 break;
3029 default:
3030 goto die;
3032 break;
3033 case 9:
3034 switch (sel) {
3035 case 0:
3036 /* Mark as an IO operation because we read the time. */
3037 if (use_icount)
3038 gen_io_start();
3039 gen_helper_mfc0_count(arg);
3040 if (use_icount) {
3041 gen_io_end();
3042 ctx->bstate = BS_STOP;
3044 rn = "Count";
3045 break;
3046 /* 6,7 are implementation dependent */
3047 default:
3048 goto die;
3050 break;
3051 case 10:
3052 switch (sel) {
3053 case 0:
3054 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_EntryHi));
3055 tcg_gen_ext32s_tl(arg, arg);
3056 rn = "EntryHi";
3057 break;
3058 default:
3059 goto die;
3061 break;
3062 case 11:
3063 switch (sel) {
3064 case 0:
3065 gen_mfc0_load32(arg, offsetof(CPUState, CP0_Compare));
3066 rn = "Compare";
3067 break;
3068 /* 6,7 are implementation dependent */
3069 default:
3070 goto die;
3072 break;
3073 case 12:
3074 switch (sel) {
3075 case 0:
3076 gen_mfc0_load32(arg, offsetof(CPUState, CP0_Status));
3077 rn = "Status";
3078 break;
3079 case 1:
3080 check_insn(env, ctx, ISA_MIPS32R2);
3081 gen_mfc0_load32(arg, offsetof(CPUState, CP0_IntCtl));
3082 rn = "IntCtl";
3083 break;
3084 case 2:
3085 check_insn(env, ctx, ISA_MIPS32R2);
3086 gen_mfc0_load32(arg, offsetof(CPUState, CP0_SRSCtl));
3087 rn = "SRSCtl";
3088 break;
3089 case 3:
3090 check_insn(env, ctx, ISA_MIPS32R2);
3091 gen_mfc0_load32(arg, offsetof(CPUState, CP0_SRSMap));
3092 rn = "SRSMap";
3093 break;
3094 default:
3095 goto die;
3097 break;
3098 case 13:
3099 switch (sel) {
3100 case 0:
3101 gen_mfc0_load32(arg, offsetof(CPUState, CP0_Cause));
3102 rn = "Cause";
3103 break;
3104 default:
3105 goto die;
3107 break;
3108 case 14:
3109 switch (sel) {
3110 case 0:
3111 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_EPC));
3112 tcg_gen_ext32s_tl(arg, arg);
3113 rn = "EPC";
3114 break;
3115 default:
3116 goto die;
3118 break;
3119 case 15:
3120 switch (sel) {
3121 case 0:
3122 gen_mfc0_load32(arg, offsetof(CPUState, CP0_PRid));
3123 rn = "PRid";
3124 break;
3125 case 1:
3126 check_insn(env, ctx, ISA_MIPS32R2);
3127 gen_mfc0_load32(arg, offsetof(CPUState, CP0_EBase));
3128 rn = "EBase";
3129 break;
3130 default:
3131 goto die;
3133 break;
3134 case 16:
3135 switch (sel) {
3136 case 0:
3137 gen_mfc0_load32(arg, offsetof(CPUState, CP0_Config0));
3138 rn = "Config";
3139 break;
3140 case 1:
3141 gen_mfc0_load32(arg, offsetof(CPUState, CP0_Config1));
3142 rn = "Config1";
3143 break;
3144 case 2:
3145 gen_mfc0_load32(arg, offsetof(CPUState, CP0_Config2));
3146 rn = "Config2";
3147 break;
3148 case 3:
3149 gen_mfc0_load32(arg, offsetof(CPUState, CP0_Config3));
3150 rn = "Config3";
3151 break;
3152 /* 4,5 are reserved */
3153 /* 6,7 are implementation dependent */
3154 case 6:
3155 gen_mfc0_load32(arg, offsetof(CPUState, CP0_Config6));
3156 rn = "Config6";
3157 break;
3158 case 7:
3159 gen_mfc0_load32(arg, offsetof(CPUState, CP0_Config7));
3160 rn = "Config7";
3161 break;
3162 default:
3163 goto die;
3165 break;
3166 case 17:
3167 switch (sel) {
3168 case 0:
3169 gen_helper_mfc0_lladdr(arg);
3170 rn = "LLAddr";
3171 break;
3172 default:
3173 goto die;
3175 break;
3176 case 18:
3177 switch (sel) {
3178 case 0 ... 7:
3179 gen_helper_1i(mfc0_watchlo, arg, sel);
3180 rn = "WatchLo";
3181 break;
3182 default:
3183 goto die;
3185 break;
3186 case 19:
3187 switch (sel) {
3188 case 0 ...7:
3189 gen_helper_1i(mfc0_watchhi, arg, sel);
3190 rn = "WatchHi";
3191 break;
3192 default:
3193 goto die;
3195 break;
3196 case 20:
3197 switch (sel) {
3198 case 0:
3199 #if defined(TARGET_MIPS64)
3200 check_insn(env, ctx, ISA_MIPS3);
3201 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_XContext));
3202 tcg_gen_ext32s_tl(arg, arg);
3203 rn = "XContext";
3204 break;
3205 #endif
3206 default:
3207 goto die;
3209 break;
3210 case 21:
3211 /* Officially reserved, but sel 0 is used for R1x000 framemask */
3212 switch (sel) {
3213 case 0:
3214 gen_mfc0_load32(arg, offsetof(CPUState, CP0_Framemask));
3215 rn = "Framemask";
3216 break;
3217 default:
3218 goto die;
3220 break;
3221 case 22:
3222 tcg_gen_movi_tl(arg, 0); /* unimplemented */
3223 rn = "'Diagnostic"; /* implementation dependent */
3224 break;
3225 case 23:
3226 switch (sel) {
3227 case 0:
3228 gen_helper_mfc0_debug(arg); /* EJTAG support */
3229 rn = "Debug";
3230 break;
3231 case 1:
3232 // gen_helper_mfc0_tracecontrol(arg); /* PDtrace support */
3233 rn = "TraceControl";
3234 // break;
3235 case 2:
3236 // gen_helper_mfc0_tracecontrol2(arg); /* PDtrace support */
3237 rn = "TraceControl2";
3238 // break;
3239 case 3:
3240 // gen_helper_mfc0_usertracedata(arg); /* PDtrace support */
3241 rn = "UserTraceData";
3242 // break;
3243 case 4:
3244 // gen_helper_mfc0_tracebpc(arg); /* PDtrace support */
3245 rn = "TraceBPC";
3246 // break;
3247 default:
3248 goto die;
3250 break;
3251 case 24:
3252 switch (sel) {
3253 case 0:
3254 /* EJTAG support */
3255 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_DEPC));
3256 tcg_gen_ext32s_tl(arg, arg);
3257 rn = "DEPC";
3258 break;
3259 default:
3260 goto die;
3262 break;
3263 case 25:
3264 switch (sel) {
3265 case 0:
3266 gen_mfc0_load32(arg, offsetof(CPUState, CP0_Performance0));
3267 rn = "Performance0";
3268 break;
3269 case 1:
3270 // gen_helper_mfc0_performance1(arg);
3271 rn = "Performance1";
3272 // break;
3273 case 2:
3274 // gen_helper_mfc0_performance2(arg);
3275 rn = "Performance2";
3276 // break;
3277 case 3:
3278 // gen_helper_mfc0_performance3(arg);
3279 rn = "Performance3";
3280 // break;
3281 case 4:
3282 // gen_helper_mfc0_performance4(arg);
3283 rn = "Performance4";
3284 // break;
3285 case 5:
3286 // gen_helper_mfc0_performance5(arg);
3287 rn = "Performance5";
3288 // break;
3289 case 6:
3290 // gen_helper_mfc0_performance6(arg);
3291 rn = "Performance6";
3292 // break;
3293 case 7:
3294 // gen_helper_mfc0_performance7(arg);
3295 rn = "Performance7";
3296 // break;
3297 default:
3298 goto die;
3300 break;
3301 case 26:
3302 tcg_gen_movi_tl(arg, 0); /* unimplemented */
3303 rn = "ECC";
3304 break;
3305 case 27:
3306 switch (sel) {
3307 case 0 ... 3:
3308 tcg_gen_movi_tl(arg, 0); /* unimplemented */
3309 rn = "CacheErr";
3310 break;
3311 default:
3312 goto die;
3314 break;
3315 case 28:
3316 switch (sel) {
3317 case 0:
3318 case 2:
3319 case 4:
3320 case 6:
3321 gen_mfc0_load32(arg, offsetof(CPUState, CP0_TagLo));
3322 rn = "TagLo";
3323 break;
3324 case 1:
3325 case 3:
3326 case 5:
3327 case 7:
3328 gen_mfc0_load32(arg, offsetof(CPUState, CP0_DataLo));
3329 rn = "DataLo";
3330 break;
3331 default:
3332 goto die;
3334 break;
3335 case 29:
3336 switch (sel) {
3337 case 0:
3338 case 2:
3339 case 4:
3340 case 6:
3341 gen_mfc0_load32(arg, offsetof(CPUState, CP0_TagHi));
3342 rn = "TagHi";
3343 break;
3344 case 1:
3345 case 3:
3346 case 5:
3347 case 7:
3348 gen_mfc0_load32(arg, offsetof(CPUState, CP0_DataHi));
3349 rn = "DataHi";
3350 break;
3351 default:
3352 goto die;
3354 break;
3355 case 30:
3356 switch (sel) {
3357 case 0:
3358 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_ErrorEPC));
3359 tcg_gen_ext32s_tl(arg, arg);
3360 rn = "ErrorEPC";
3361 break;
3362 default:
3363 goto die;
3365 break;
3366 case 31:
3367 switch (sel) {
3368 case 0:
3369 /* EJTAG support */
3370 gen_mfc0_load32(arg, offsetof(CPUState, CP0_DESAVE));
3371 rn = "DESAVE";
3372 break;
3373 default:
3374 goto die;
3376 break;
3377 default:
3378 goto die;
3380 LOG_DISAS("mfc0 %s (reg %d sel %d)\n", rn, reg, sel);
3381 return;
3383 die:
3384 LOG_DISAS("mfc0 %s (reg %d sel %d)\n", rn, reg, sel);
3385 generate_exception(ctx, EXCP_RI);
3388 static void gen_mtc0 (CPUState *env, DisasContext *ctx, TCGv arg, int reg, int sel)
3390 const char *rn = "invalid";
3392 if (sel != 0)
3393 check_insn(env, ctx, ISA_MIPS32);
3395 if (use_icount)
3396 gen_io_start();
3398 switch (reg) {
3399 case 0:
3400 switch (sel) {
3401 case 0:
3402 gen_helper_mtc0_index(arg);
3403 rn = "Index";
3404 break;
3405 case 1:
3406 check_insn(env, ctx, ASE_MT);
3407 gen_helper_mtc0_mvpcontrol(arg);
3408 rn = "MVPControl";
3409 break;
3410 case 2:
3411 check_insn(env, ctx, ASE_MT);
3412 /* ignored */
3413 rn = "MVPConf0";
3414 break;
3415 case 3:
3416 check_insn(env, ctx, ASE_MT);
3417 /* ignored */
3418 rn = "MVPConf1";
3419 break;
3420 default:
3421 goto die;
3423 break;
3424 case 1:
3425 switch (sel) {
3426 case 0:
3427 /* ignored */
3428 rn = "Random";
3429 break;
3430 case 1:
3431 check_insn(env, ctx, ASE_MT);
3432 gen_helper_mtc0_vpecontrol(arg);
3433 rn = "VPEControl";
3434 break;
3435 case 2:
3436 check_insn(env, ctx, ASE_MT);
3437 gen_helper_mtc0_vpeconf0(arg);
3438 rn = "VPEConf0";
3439 break;
3440 case 3:
3441 check_insn(env, ctx, ASE_MT);
3442 gen_helper_mtc0_vpeconf1(arg);
3443 rn = "VPEConf1";
3444 break;
3445 case 4:
3446 check_insn(env, ctx, ASE_MT);
3447 gen_helper_mtc0_yqmask(arg);
3448 rn = "YQMask";
3449 break;
3450 case 5:
3451 check_insn(env, ctx, ASE_MT);
3452 gen_mtc0_store64(arg, offsetof(CPUState, CP0_VPESchedule));
3453 rn = "VPESchedule";
3454 break;
3455 case 6:
3456 check_insn(env, ctx, ASE_MT);
3457 gen_mtc0_store64(arg, offsetof(CPUState, CP0_VPEScheFBack));
3458 rn = "VPEScheFBack";
3459 break;
3460 case 7:
3461 check_insn(env, ctx, ASE_MT);
3462 gen_helper_mtc0_vpeopt(arg);
3463 rn = "VPEOpt";
3464 break;
3465 default:
3466 goto die;
3468 break;
3469 case 2:
3470 switch (sel) {
3471 case 0:
3472 gen_helper_mtc0_entrylo0(arg);
3473 rn = "EntryLo0";
3474 break;
3475 case 1:
3476 check_insn(env, ctx, ASE_MT);
3477 gen_helper_mtc0_tcstatus(arg);
3478 rn = "TCStatus";
3479 break;
3480 case 2:
3481 check_insn(env, ctx, ASE_MT);
3482 gen_helper_mtc0_tcbind(arg);
3483 rn = "TCBind";
3484 break;
3485 case 3:
3486 check_insn(env, ctx, ASE_MT);
3487 gen_helper_mtc0_tcrestart(arg);
3488 rn = "TCRestart";
3489 break;
3490 case 4:
3491 check_insn(env, ctx, ASE_MT);
3492 gen_helper_mtc0_tchalt(arg);
3493 rn = "TCHalt";
3494 break;
3495 case 5:
3496 check_insn(env, ctx, ASE_MT);
3497 gen_helper_mtc0_tccontext(arg);
3498 rn = "TCContext";
3499 break;
3500 case 6:
3501 check_insn(env, ctx, ASE_MT);
3502 gen_helper_mtc0_tcschedule(arg);
3503 rn = "TCSchedule";
3504 break;
3505 case 7:
3506 check_insn(env, ctx, ASE_MT);
3507 gen_helper_mtc0_tcschefback(arg);
3508 rn = "TCScheFBack";
3509 break;
3510 default:
3511 goto die;
3513 break;
3514 case 3:
3515 switch (sel) {
3516 case 0:
3517 gen_helper_mtc0_entrylo1(arg);
3518 rn = "EntryLo1";
3519 break;
3520 default:
3521 goto die;
3523 break;
3524 case 4:
3525 switch (sel) {
3526 case 0:
3527 gen_helper_mtc0_context(arg);
3528 rn = "Context";
3529 break;
3530 case 1:
3531 // gen_helper_mtc0_contextconfig(arg); /* SmartMIPS ASE */
3532 rn = "ContextConfig";
3533 // break;
3534 default:
3535 goto die;
3537 break;
3538 case 5:
3539 switch (sel) {
3540 case 0:
3541 gen_helper_mtc0_pagemask(arg);
3542 rn = "PageMask";
3543 break;
3544 case 1:
3545 check_insn(env, ctx, ISA_MIPS32R2);
3546 gen_helper_mtc0_pagegrain(arg);
3547 rn = "PageGrain";
3548 break;
3549 default:
3550 goto die;
3552 break;
3553 case 6:
3554 switch (sel) {
3555 case 0:
3556 gen_helper_mtc0_wired(arg);
3557 rn = "Wired";
3558 break;
3559 case 1:
3560 check_insn(env, ctx, ISA_MIPS32R2);
3561 gen_helper_mtc0_srsconf0(arg);
3562 rn = "SRSConf0";
3563 break;
3564 case 2:
3565 check_insn(env, ctx, ISA_MIPS32R2);
3566 gen_helper_mtc0_srsconf1(arg);
3567 rn = "SRSConf1";
3568 break;
3569 case 3:
3570 check_insn(env, ctx, ISA_MIPS32R2);
3571 gen_helper_mtc0_srsconf2(arg);
3572 rn = "SRSConf2";
3573 break;
3574 case 4:
3575 check_insn(env, ctx, ISA_MIPS32R2);
3576 gen_helper_mtc0_srsconf3(arg);
3577 rn = "SRSConf3";
3578 break;
3579 case 5:
3580 check_insn(env, ctx, ISA_MIPS32R2);
3581 gen_helper_mtc0_srsconf4(arg);
3582 rn = "SRSConf4";
3583 break;
3584 default:
3585 goto die;
3587 break;
3588 case 7:
3589 switch (sel) {
3590 case 0:
3591 check_insn(env, ctx, ISA_MIPS32R2);
3592 gen_helper_mtc0_hwrena(arg);
3593 rn = "HWREna";
3594 break;
3595 default:
3596 goto die;
3598 break;
3599 case 8:
3600 /* ignored */
3601 rn = "BadVAddr";
3602 break;
3603 case 9:
3604 switch (sel) {
3605 case 0:
3606 gen_helper_mtc0_count(arg);
3607 rn = "Count";
3608 break;
3609 /* 6,7 are implementation dependent */
3610 default:
3611 goto die;
3613 break;
3614 case 10:
3615 switch (sel) {
3616 case 0:
3617 gen_helper_mtc0_entryhi(arg);
3618 rn = "EntryHi";
3619 break;
3620 default:
3621 goto die;
3623 break;
3624 case 11:
3625 switch (sel) {
3626 case 0:
3627 gen_helper_mtc0_compare(arg);
3628 rn = "Compare";
3629 break;
3630 /* 6,7 are implementation dependent */
3631 default:
3632 goto die;
3634 break;
3635 case 12:
3636 switch (sel) {
3637 case 0:
3638 save_cpu_state(ctx, 1);
3639 gen_helper_mtc0_status(arg);
3640 /* BS_STOP isn't good enough here, hflags may have changed. */
3641 gen_save_pc(ctx->pc + 4);
3642 ctx->bstate = BS_EXCP;
3643 rn = "Status";
3644 break;
3645 case 1:
3646 check_insn(env, ctx, ISA_MIPS32R2);
3647 gen_helper_mtc0_intctl(arg);
3648 /* Stop translation as we may have switched the execution mode */
3649 ctx->bstate = BS_STOP;
3650 rn = "IntCtl";
3651 break;
3652 case 2:
3653 check_insn(env, ctx, ISA_MIPS32R2);
3654 gen_helper_mtc0_srsctl(arg);
3655 /* Stop translation as we may have switched the execution mode */
3656 ctx->bstate = BS_STOP;
3657 rn = "SRSCtl";
3658 break;
3659 case 3:
3660 check_insn(env, ctx, ISA_MIPS32R2);
3661 gen_mtc0_store32(arg, offsetof(CPUState, CP0_SRSMap));
3662 /* Stop translation as we may have switched the execution mode */
3663 ctx->bstate = BS_STOP;
3664 rn = "SRSMap";
3665 break;
3666 default:
3667 goto die;
3669 break;
3670 case 13:
3671 switch (sel) {
3672 case 0:
3673 save_cpu_state(ctx, 1);
3674 gen_helper_mtc0_cause(arg);
3675 rn = "Cause";
3676 break;
3677 default:
3678 goto die;
3680 break;
3681 case 14:
3682 switch (sel) {
3683 case 0:
3684 gen_mtc0_store64(arg, offsetof(CPUState, CP0_EPC));
3685 rn = "EPC";
3686 break;
3687 default:
3688 goto die;
3690 break;
3691 case 15:
3692 switch (sel) {
3693 case 0:
3694 /* ignored */
3695 rn = "PRid";
3696 break;
3697 case 1:
3698 check_insn(env, ctx, ISA_MIPS32R2);
3699 gen_helper_mtc0_ebase(arg);
3700 rn = "EBase";
3701 break;
3702 default:
3703 goto die;
3705 break;
3706 case 16:
3707 switch (sel) {
3708 case 0:
3709 gen_helper_mtc0_config0(arg);
3710 rn = "Config";
3711 /* Stop translation as we may have switched the execution mode */
3712 ctx->bstate = BS_STOP;
3713 break;
3714 case 1:
3715 /* ignored, read only */
3716 rn = "Config1";
3717 break;
3718 case 2:
3719 gen_helper_mtc0_config2(arg);
3720 rn = "Config2";
3721 /* Stop translation as we may have switched the execution mode */
3722 ctx->bstate = BS_STOP;
3723 break;
3724 case 3:
3725 /* ignored, read only */
3726 rn = "Config3";
3727 break;
3728 /* 4,5 are reserved */
3729 /* 6,7 are implementation dependent */
3730 case 6:
3731 /* ignored */
3732 rn = "Config6";
3733 break;
3734 case 7:
3735 /* ignored */
3736 rn = "Config7";
3737 break;
3738 default:
3739 rn = "Invalid config selector";
3740 goto die;
3742 break;
3743 case 17:
3744 switch (sel) {
3745 case 0:
3746 gen_helper_mtc0_lladdr(arg);
3747 rn = "LLAddr";
3748 break;
3749 default:
3750 goto die;
3752 break;
3753 case 18:
3754 switch (sel) {
3755 case 0 ... 7:
3756 gen_helper_1i(mtc0_watchlo, arg, sel);
3757 rn = "WatchLo";
3758 break;
3759 default:
3760 goto die;
3762 break;
3763 case 19:
3764 switch (sel) {
3765 case 0 ... 7:
3766 gen_helper_1i(mtc0_watchhi, arg, sel);
3767 rn = "WatchHi";
3768 break;
3769 default:
3770 goto die;
3772 break;
3773 case 20:
3774 switch (sel) {
3775 case 0:
3776 #if defined(TARGET_MIPS64)
3777 check_insn(env, ctx, ISA_MIPS3);
3778 gen_helper_mtc0_xcontext(arg);
3779 rn = "XContext";
3780 break;
3781 #endif
3782 default:
3783 goto die;
3785 break;
3786 case 21:
3787 /* Officially reserved, but sel 0 is used for R1x000 framemask */
3788 switch (sel) {
3789 case 0:
3790 gen_helper_mtc0_framemask(arg);
3791 rn = "Framemask";
3792 break;
3793 default:
3794 goto die;
3796 break;
3797 case 22:
3798 /* ignored */
3799 rn = "Diagnostic"; /* implementation dependent */
3800 break;
3801 case 23:
3802 switch (sel) {
3803 case 0:
3804 gen_helper_mtc0_debug(arg); /* EJTAG support */
3805 /* BS_STOP isn't good enough here, hflags may have changed. */
3806 gen_save_pc(ctx->pc + 4);
3807 ctx->bstate = BS_EXCP;
3808 rn = "Debug";
3809 break;
3810 case 1:
3811 // gen_helper_mtc0_tracecontrol(arg); /* PDtrace support */
3812 rn = "TraceControl";
3813 /* Stop translation as we may have switched the execution mode */
3814 ctx->bstate = BS_STOP;
3815 // break;
3816 case 2:
3817 // gen_helper_mtc0_tracecontrol2(arg); /* PDtrace support */
3818 rn = "TraceControl2";
3819 /* Stop translation as we may have switched the execution mode */
3820 ctx->bstate = BS_STOP;
3821 // break;
3822 case 3:
3823 /* Stop translation as we may have switched the execution mode */
3824 ctx->bstate = BS_STOP;
3825 // gen_helper_mtc0_usertracedata(arg); /* PDtrace support */
3826 rn = "UserTraceData";
3827 /* Stop translation as we may have switched the execution mode */
3828 ctx->bstate = BS_STOP;
3829 // break;
3830 case 4:
3831 // gen_helper_mtc0_tracebpc(arg); /* PDtrace support */
3832 /* Stop translation as we may have switched the execution mode */
3833 ctx->bstate = BS_STOP;
3834 rn = "TraceBPC";
3835 // break;
3836 default:
3837 goto die;
3839 break;
3840 case 24:
3841 switch (sel) {
3842 case 0:
3843 /* EJTAG support */
3844 gen_mtc0_store64(arg, offsetof(CPUState, CP0_DEPC));
3845 rn = "DEPC";
3846 break;
3847 default:
3848 goto die;
3850 break;
3851 case 25:
3852 switch (sel) {
3853 case 0:
3854 gen_helper_mtc0_performance0(arg);
3855 rn = "Performance0";
3856 break;
3857 case 1:
3858 // gen_helper_mtc0_performance1(arg);
3859 rn = "Performance1";
3860 // break;
3861 case 2:
3862 // gen_helper_mtc0_performance2(arg);
3863 rn = "Performance2";
3864 // break;
3865 case 3:
3866 // gen_helper_mtc0_performance3(arg);
3867 rn = "Performance3";
3868 // break;
3869 case 4:
3870 // gen_helper_mtc0_performance4(arg);
3871 rn = "Performance4";
3872 // break;
3873 case 5:
3874 // gen_helper_mtc0_performance5(arg);
3875 rn = "Performance5";
3876 // break;
3877 case 6:
3878 // gen_helper_mtc0_performance6(arg);
3879 rn = "Performance6";
3880 // break;
3881 case 7:
3882 // gen_helper_mtc0_performance7(arg);
3883 rn = "Performance7";
3884 // break;
3885 default:
3886 goto die;
3888 break;
3889 case 26:
3890 /* ignored */
3891 rn = "ECC";
3892 break;
3893 case 27:
3894 switch (sel) {
3895 case 0 ... 3:
3896 /* ignored */
3897 rn = "CacheErr";
3898 break;
3899 default:
3900 goto die;
3902 break;
3903 case 28:
3904 switch (sel) {
3905 case 0:
3906 case 2:
3907 case 4:
3908 case 6:
3909 gen_helper_mtc0_taglo(arg);
3910 rn = "TagLo";
3911 break;
3912 case 1:
3913 case 3:
3914 case 5:
3915 case 7:
3916 gen_helper_mtc0_datalo(arg);
3917 rn = "DataLo";
3918 break;
3919 default:
3920 goto die;
3922 break;
3923 case 29:
3924 switch (sel) {
3925 case 0:
3926 case 2:
3927 case 4:
3928 case 6:
3929 gen_helper_mtc0_taghi(arg);
3930 rn = "TagHi";
3931 break;
3932 case 1:
3933 case 3:
3934 case 5:
3935 case 7:
3936 gen_helper_mtc0_datahi(arg);
3937 rn = "DataHi";
3938 break;
3939 default:
3940 rn = "invalid sel";
3941 goto die;
3943 break;
3944 case 30:
3945 switch (sel) {
3946 case 0:
3947 gen_mtc0_store64(arg, offsetof(CPUState, CP0_ErrorEPC));
3948 rn = "ErrorEPC";
3949 break;
3950 default:
3951 goto die;
3953 break;
3954 case 31:
3955 switch (sel) {
3956 case 0:
3957 /* EJTAG support */
3958 gen_mtc0_store32(arg, offsetof(CPUState, CP0_DESAVE));
3959 rn = "DESAVE";
3960 break;
3961 default:
3962 goto die;
3964 /* Stop translation as we may have switched the execution mode */
3965 ctx->bstate = BS_STOP;
3966 break;
3967 default:
3968 goto die;
3970 LOG_DISAS("mtc0 %s (reg %d sel %d)\n", rn, reg, sel);
3971 /* For simplicity assume that all writes can cause interrupts. */
3972 if (use_icount) {
3973 gen_io_end();
3974 ctx->bstate = BS_STOP;
3976 return;
3978 die:
3979 LOG_DISAS("mtc0 %s (reg %d sel %d)\n", rn, reg, sel);
3980 generate_exception(ctx, EXCP_RI);
3983 #if defined(TARGET_MIPS64)
3984 static void gen_dmfc0 (CPUState *env, DisasContext *ctx, TCGv arg, int reg, int sel)
3986 const char *rn = "invalid";
3988 if (sel != 0)
3989 check_insn(env, ctx, ISA_MIPS64);
3991 switch (reg) {
3992 case 0:
3993 switch (sel) {
3994 case 0:
3995 gen_mfc0_load32(arg, offsetof(CPUState, CP0_Index));
3996 rn = "Index";
3997 break;
3998 case 1:
3999 check_insn(env, ctx, ASE_MT);
4000 gen_helper_mfc0_mvpcontrol(arg);
4001 rn = "MVPControl";
4002 break;
4003 case 2:
4004 check_insn(env, ctx, ASE_MT);
4005 gen_helper_mfc0_mvpconf0(arg);
4006 rn = "MVPConf0";
4007 break;
4008 case 3:
4009 check_insn(env, ctx, ASE_MT);
4010 gen_helper_mfc0_mvpconf1(arg);
4011 rn = "MVPConf1";
4012 break;
4013 default:
4014 goto die;
4016 break;
4017 case 1:
4018 switch (sel) {
4019 case 0:
4020 gen_helper_mfc0_random(arg);
4021 rn = "Random";
4022 break;
4023 case 1:
4024 check_insn(env, ctx, ASE_MT);
4025 gen_mfc0_load32(arg, offsetof(CPUState, CP0_VPEControl));
4026 rn = "VPEControl";
4027 break;
4028 case 2:
4029 check_insn(env, ctx, ASE_MT);
4030 gen_mfc0_load32(arg, offsetof(CPUState, CP0_VPEConf0));
4031 rn = "VPEConf0";
4032 break;
4033 case 3:
4034 check_insn(env, ctx, ASE_MT);
4035 gen_mfc0_load32(arg, offsetof(CPUState, CP0_VPEConf1));
4036 rn = "VPEConf1";
4037 break;
4038 case 4:
4039 check_insn(env, ctx, ASE_MT);
4040 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_YQMask));
4041 rn = "YQMask";
4042 break;
4043 case 5:
4044 check_insn(env, ctx, ASE_MT);
4045 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_VPESchedule));
4046 rn = "VPESchedule";
4047 break;
4048 case 6:
4049 check_insn(env, ctx, ASE_MT);
4050 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_VPEScheFBack));
4051 rn = "VPEScheFBack";
4052 break;
4053 case 7:
4054 check_insn(env, ctx, ASE_MT);
4055 gen_mfc0_load32(arg, offsetof(CPUState, CP0_VPEOpt));
4056 rn = "VPEOpt";
4057 break;
4058 default:
4059 goto die;
4061 break;
4062 case 2:
4063 switch (sel) {
4064 case 0:
4065 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_EntryLo0));
4066 rn = "EntryLo0";
4067 break;
4068 case 1:
4069 check_insn(env, ctx, ASE_MT);
4070 gen_helper_mfc0_tcstatus(arg);
4071 rn = "TCStatus";
4072 break;
4073 case 2:
4074 check_insn(env, ctx, ASE_MT);
4075 gen_helper_mfc0_tcbind(arg);
4076 rn = "TCBind";
4077 break;
4078 case 3:
4079 check_insn(env, ctx, ASE_MT);
4080 gen_helper_dmfc0_tcrestart(arg);
4081 rn = "TCRestart";
4082 break;
4083 case 4:
4084 check_insn(env, ctx, ASE_MT);
4085 gen_helper_dmfc0_tchalt(arg);
4086 rn = "TCHalt";
4087 break;
4088 case 5:
4089 check_insn(env, ctx, ASE_MT);
4090 gen_helper_dmfc0_tccontext(arg);
4091 rn = "TCContext";
4092 break;
4093 case 6:
4094 check_insn(env, ctx, ASE_MT);
4095 gen_helper_dmfc0_tcschedule(arg);
4096 rn = "TCSchedule";
4097 break;
4098 case 7:
4099 check_insn(env, ctx, ASE_MT);
4100 gen_helper_dmfc0_tcschefback(arg);
4101 rn = "TCScheFBack";
4102 break;
4103 default:
4104 goto die;
4106 break;
4107 case 3:
4108 switch (sel) {
4109 case 0:
4110 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_EntryLo1));
4111 rn = "EntryLo1";
4112 break;
4113 default:
4114 goto die;
4116 break;
4117 case 4:
4118 switch (sel) {
4119 case 0:
4120 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_Context));
4121 rn = "Context";
4122 break;
4123 case 1:
4124 // gen_helper_dmfc0_contextconfig(arg); /* SmartMIPS ASE */
4125 rn = "ContextConfig";
4126 // break;
4127 default:
4128 goto die;
4130 break;
4131 case 5:
4132 switch (sel) {
4133 case 0:
4134 gen_mfc0_load32(arg, offsetof(CPUState, CP0_PageMask));
4135 rn = "PageMask";
4136 break;
4137 case 1:
4138 check_insn(env, ctx, ISA_MIPS32R2);
4139 gen_mfc0_load32(arg, offsetof(CPUState, CP0_PageGrain));
4140 rn = "PageGrain";
4141 break;
4142 default:
4143 goto die;
4145 break;
4146 case 6:
4147 switch (sel) {
4148 case 0:
4149 gen_mfc0_load32(arg, offsetof(CPUState, CP0_Wired));
4150 rn = "Wired";
4151 break;
4152 case 1:
4153 check_insn(env, ctx, ISA_MIPS32R2);
4154 gen_mfc0_load32(arg, offsetof(CPUState, CP0_SRSConf0));
4155 rn = "SRSConf0";
4156 break;
4157 case 2:
4158 check_insn(env, ctx, ISA_MIPS32R2);
4159 gen_mfc0_load32(arg, offsetof(CPUState, CP0_SRSConf1));
4160 rn = "SRSConf1";
4161 break;
4162 case 3:
4163 check_insn(env, ctx, ISA_MIPS32R2);
4164 gen_mfc0_load32(arg, offsetof(CPUState, CP0_SRSConf2));
4165 rn = "SRSConf2";
4166 break;
4167 case 4:
4168 check_insn(env, ctx, ISA_MIPS32R2);
4169 gen_mfc0_load32(arg, offsetof(CPUState, CP0_SRSConf3));
4170 rn = "SRSConf3";
4171 break;
4172 case 5:
4173 check_insn(env, ctx, ISA_MIPS32R2);
4174 gen_mfc0_load32(arg, offsetof(CPUState, CP0_SRSConf4));
4175 rn = "SRSConf4";
4176 break;
4177 default:
4178 goto die;
4180 break;
4181 case 7:
4182 switch (sel) {
4183 case 0:
4184 check_insn(env, ctx, ISA_MIPS32R2);
4185 gen_mfc0_load32(arg, offsetof(CPUState, CP0_HWREna));
4186 rn = "HWREna";
4187 break;
4188 default:
4189 goto die;
4191 break;
4192 case 8:
4193 switch (sel) {
4194 case 0:
4195 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_BadVAddr));
4196 rn = "BadVAddr";
4197 break;
4198 default:
4199 goto die;
4201 break;
4202 case 9:
4203 switch (sel) {
4204 case 0:
4205 /* Mark as an IO operation because we read the time. */
4206 if (use_icount)
4207 gen_io_start();
4208 gen_helper_mfc0_count(arg);
4209 if (use_icount) {
4210 gen_io_end();
4211 ctx->bstate = BS_STOP;
4213 rn = "Count";
4214 break;
4215 /* 6,7 are implementation dependent */
4216 default:
4217 goto die;
4219 break;
4220 case 10:
4221 switch (sel) {
4222 case 0:
4223 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_EntryHi));
4224 rn = "EntryHi";
4225 break;
4226 default:
4227 goto die;
4229 break;
4230 case 11:
4231 switch (sel) {
4232 case 0:
4233 gen_mfc0_load32(arg, offsetof(CPUState, CP0_Compare));
4234 rn = "Compare";
4235 break;
4236 /* 6,7 are implementation dependent */
4237 default:
4238 goto die;
4240 break;
4241 case 12:
4242 switch (sel) {
4243 case 0:
4244 gen_mfc0_load32(arg, offsetof(CPUState, CP0_Status));
4245 rn = "Status";
4246 break;
4247 case 1:
4248 check_insn(env, ctx, ISA_MIPS32R2);
4249 gen_mfc0_load32(arg, offsetof(CPUState, CP0_IntCtl));
4250 rn = "IntCtl";
4251 break;
4252 case 2:
4253 check_insn(env, ctx, ISA_MIPS32R2);
4254 gen_mfc0_load32(arg, offsetof(CPUState, CP0_SRSCtl));
4255 rn = "SRSCtl";
4256 break;
4257 case 3:
4258 check_insn(env, ctx, ISA_MIPS32R2);
4259 gen_mfc0_load32(arg, offsetof(CPUState, CP0_SRSMap));
4260 rn = "SRSMap";
4261 break;
4262 default:
4263 goto die;
4265 break;
4266 case 13:
4267 switch (sel) {
4268 case 0:
4269 gen_mfc0_load32(arg, offsetof(CPUState, CP0_Cause));
4270 rn = "Cause";
4271 break;
4272 default:
4273 goto die;
4275 break;
4276 case 14:
4277 switch (sel) {
4278 case 0:
4279 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_EPC));
4280 rn = "EPC";
4281 break;
4282 default:
4283 goto die;
4285 break;
4286 case 15:
4287 switch (sel) {
4288 case 0:
4289 gen_mfc0_load32(arg, offsetof(CPUState, CP0_PRid));
4290 rn = "PRid";
4291 break;
4292 case 1:
4293 check_insn(env, ctx, ISA_MIPS32R2);
4294 gen_mfc0_load32(arg, offsetof(CPUState, CP0_EBase));
4295 rn = "EBase";
4296 break;
4297 default:
4298 goto die;
4300 break;
4301 case 16:
4302 switch (sel) {
4303 case 0:
4304 gen_mfc0_load32(arg, offsetof(CPUState, CP0_Config0));
4305 rn = "Config";
4306 break;
4307 case 1:
4308 gen_mfc0_load32(arg, offsetof(CPUState, CP0_Config1));
4309 rn = "Config1";
4310 break;
4311 case 2:
4312 gen_mfc0_load32(arg, offsetof(CPUState, CP0_Config2));
4313 rn = "Config2";
4314 break;
4315 case 3:
4316 gen_mfc0_load32(arg, offsetof(CPUState, CP0_Config3));
4317 rn = "Config3";
4318 break;
4319 /* 6,7 are implementation dependent */
4320 case 6:
4321 gen_mfc0_load32(arg, offsetof(CPUState, CP0_Config6));
4322 rn = "Config6";
4323 break;
4324 case 7:
4325 gen_mfc0_load32(arg, offsetof(CPUState, CP0_Config7));
4326 rn = "Config7";
4327 break;
4328 default:
4329 goto die;
4331 break;
4332 case 17:
4333 switch (sel) {
4334 case 0:
4335 gen_helper_dmfc0_lladdr(arg);
4336 rn = "LLAddr";
4337 break;
4338 default:
4339 goto die;
4341 break;
4342 case 18:
4343 switch (sel) {
4344 case 0 ... 7:
4345 gen_helper_1i(dmfc0_watchlo, arg, sel);
4346 rn = "WatchLo";
4347 break;
4348 default:
4349 goto die;
4351 break;
4352 case 19:
4353 switch (sel) {
4354 case 0 ... 7:
4355 gen_helper_1i(mfc0_watchhi, arg, sel);
4356 rn = "WatchHi";
4357 break;
4358 default:
4359 goto die;
4361 break;
4362 case 20:
4363 switch (sel) {
4364 case 0:
4365 check_insn(env, ctx, ISA_MIPS3);
4366 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_XContext));
4367 rn = "XContext";
4368 break;
4369 default:
4370 goto die;
4372 break;
4373 case 21:
4374 /* Officially reserved, but sel 0 is used for R1x000 framemask */
4375 switch (sel) {
4376 case 0:
4377 gen_mfc0_load32(arg, offsetof(CPUState, CP0_Framemask));
4378 rn = "Framemask";
4379 break;
4380 default:
4381 goto die;
4383 break;
4384 case 22:
4385 tcg_gen_movi_tl(arg, 0); /* unimplemented */
4386 rn = "'Diagnostic"; /* implementation dependent */
4387 break;
4388 case 23:
4389 switch (sel) {
4390 case 0:
4391 gen_helper_mfc0_debug(arg); /* EJTAG support */
4392 rn = "Debug";
4393 break;
4394 case 1:
4395 // gen_helper_dmfc0_tracecontrol(arg); /* PDtrace support */
4396 rn = "TraceControl";
4397 // break;
4398 case 2:
4399 // gen_helper_dmfc0_tracecontrol2(arg); /* PDtrace support */
4400 rn = "TraceControl2";
4401 // break;
4402 case 3:
4403 // gen_helper_dmfc0_usertracedata(arg); /* PDtrace support */
4404 rn = "UserTraceData";
4405 // break;
4406 case 4:
4407 // gen_helper_dmfc0_tracebpc(arg); /* PDtrace support */
4408 rn = "TraceBPC";
4409 // break;
4410 default:
4411 goto die;
4413 break;
4414 case 24:
4415 switch (sel) {
4416 case 0:
4417 /* EJTAG support */
4418 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_DEPC));
4419 rn = "DEPC";
4420 break;
4421 default:
4422 goto die;
4424 break;
4425 case 25:
4426 switch (sel) {
4427 case 0:
4428 gen_mfc0_load32(arg, offsetof(CPUState, CP0_Performance0));
4429 rn = "Performance0";
4430 break;
4431 case 1:
4432 // gen_helper_dmfc0_performance1(arg);
4433 rn = "Performance1";
4434 // break;
4435 case 2:
4436 // gen_helper_dmfc0_performance2(arg);
4437 rn = "Performance2";
4438 // break;
4439 case 3:
4440 // gen_helper_dmfc0_performance3(arg);
4441 rn = "Performance3";
4442 // break;
4443 case 4:
4444 // gen_helper_dmfc0_performance4(arg);
4445 rn = "Performance4";
4446 // break;
4447 case 5:
4448 // gen_helper_dmfc0_performance5(arg);
4449 rn = "Performance5";
4450 // break;
4451 case 6:
4452 // gen_helper_dmfc0_performance6(arg);
4453 rn = "Performance6";
4454 // break;
4455 case 7:
4456 // gen_helper_dmfc0_performance7(arg);
4457 rn = "Performance7";
4458 // break;
4459 default:
4460 goto die;
4462 break;
4463 case 26:
4464 tcg_gen_movi_tl(arg, 0); /* unimplemented */
4465 rn = "ECC";
4466 break;
4467 case 27:
4468 switch (sel) {
4469 /* ignored */
4470 case 0 ... 3:
4471 tcg_gen_movi_tl(arg, 0); /* unimplemented */
4472 rn = "CacheErr";
4473 break;
4474 default:
4475 goto die;
4477 break;
4478 case 28:
4479 switch (sel) {
4480 case 0:
4481 case 2:
4482 case 4:
4483 case 6:
4484 gen_mfc0_load32(arg, offsetof(CPUState, CP0_TagLo));
4485 rn = "TagLo";
4486 break;
4487 case 1:
4488 case 3:
4489 case 5:
4490 case 7:
4491 gen_mfc0_load32(arg, offsetof(CPUState, CP0_DataLo));
4492 rn = "DataLo";
4493 break;
4494 default:
4495 goto die;
4497 break;
4498 case 29:
4499 switch (sel) {
4500 case 0:
4501 case 2:
4502 case 4:
4503 case 6:
4504 gen_mfc0_load32(arg, offsetof(CPUState, CP0_TagHi));
4505 rn = "TagHi";
4506 break;
4507 case 1:
4508 case 3:
4509 case 5:
4510 case 7:
4511 gen_mfc0_load32(arg, offsetof(CPUState, CP0_DataHi));
4512 rn = "DataHi";
4513 break;
4514 default:
4515 goto die;
4517 break;
4518 case 30:
4519 switch (sel) {
4520 case 0:
4521 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_ErrorEPC));
4522 rn = "ErrorEPC";
4523 break;
4524 default:
4525 goto die;
4527 break;
4528 case 31:
4529 switch (sel) {
4530 case 0:
4531 /* EJTAG support */
4532 gen_mfc0_load32(arg, offsetof(CPUState, CP0_DESAVE));
4533 rn = "DESAVE";
4534 break;
4535 default:
4536 goto die;
4538 break;
4539 default:
4540 goto die;
4542 LOG_DISAS("dmfc0 %s (reg %d sel %d)\n", rn, reg, sel);
4543 return;
4545 die:
4546 LOG_DISAS("dmfc0 %s (reg %d sel %d)\n", rn, reg, sel);
4547 generate_exception(ctx, EXCP_RI);
4550 static void gen_dmtc0 (CPUState *env, DisasContext *ctx, TCGv arg, int reg, int sel)
4552 const char *rn = "invalid";
4554 if (sel != 0)
4555 check_insn(env, ctx, ISA_MIPS64);
4557 if (use_icount)
4558 gen_io_start();
4560 switch (reg) {
4561 case 0:
4562 switch (sel) {
4563 case 0:
4564 gen_helper_mtc0_index(arg);
4565 rn = "Index";
4566 break;
4567 case 1:
4568 check_insn(env, ctx, ASE_MT);
4569 gen_helper_mtc0_mvpcontrol(arg);
4570 rn = "MVPControl";
4571 break;
4572 case 2:
4573 check_insn(env, ctx, ASE_MT);
4574 /* ignored */
4575 rn = "MVPConf0";
4576 break;
4577 case 3:
4578 check_insn(env, ctx, ASE_MT);
4579 /* ignored */
4580 rn = "MVPConf1";
4581 break;
4582 default:
4583 goto die;
4585 break;
4586 case 1:
4587 switch (sel) {
4588 case 0:
4589 /* ignored */
4590 rn = "Random";
4591 break;
4592 case 1:
4593 check_insn(env, ctx, ASE_MT);
4594 gen_helper_mtc0_vpecontrol(arg);
4595 rn = "VPEControl";
4596 break;
4597 case 2:
4598 check_insn(env, ctx, ASE_MT);
4599 gen_helper_mtc0_vpeconf0(arg);
4600 rn = "VPEConf0";
4601 break;
4602 case 3:
4603 check_insn(env, ctx, ASE_MT);
4604 gen_helper_mtc0_vpeconf1(arg);
4605 rn = "VPEConf1";
4606 break;
4607 case 4:
4608 check_insn(env, ctx, ASE_MT);
4609 gen_helper_mtc0_yqmask(arg);
4610 rn = "YQMask";
4611 break;
4612 case 5:
4613 check_insn(env, ctx, ASE_MT);
4614 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUState, CP0_VPESchedule));
4615 rn = "VPESchedule";
4616 break;
4617 case 6:
4618 check_insn(env, ctx, ASE_MT);
4619 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUState, CP0_VPEScheFBack));
4620 rn = "VPEScheFBack";
4621 break;
4622 case 7:
4623 check_insn(env, ctx, ASE_MT);
4624 gen_helper_mtc0_vpeopt(arg);
4625 rn = "VPEOpt";
4626 break;
4627 default:
4628 goto die;
4630 break;
4631 case 2:
4632 switch (sel) {
4633 case 0:
4634 gen_helper_mtc0_entrylo0(arg);
4635 rn = "EntryLo0";
4636 break;
4637 case 1:
4638 check_insn(env, ctx, ASE_MT);
4639 gen_helper_mtc0_tcstatus(arg);
4640 rn = "TCStatus";
4641 break;
4642 case 2:
4643 check_insn(env, ctx, ASE_MT);
4644 gen_helper_mtc0_tcbind(arg);
4645 rn = "TCBind";
4646 break;
4647 case 3:
4648 check_insn(env, ctx, ASE_MT);
4649 gen_helper_mtc0_tcrestart(arg);
4650 rn = "TCRestart";
4651 break;
4652 case 4:
4653 check_insn(env, ctx, ASE_MT);
4654 gen_helper_mtc0_tchalt(arg);
4655 rn = "TCHalt";
4656 break;
4657 case 5:
4658 check_insn(env, ctx, ASE_MT);
4659 gen_helper_mtc0_tccontext(arg);
4660 rn = "TCContext";
4661 break;
4662 case 6:
4663 check_insn(env, ctx, ASE_MT);
4664 gen_helper_mtc0_tcschedule(arg);
4665 rn = "TCSchedule";
4666 break;
4667 case 7:
4668 check_insn(env, ctx, ASE_MT);
4669 gen_helper_mtc0_tcschefback(arg);
4670 rn = "TCScheFBack";
4671 break;
4672 default:
4673 goto die;
4675 break;
4676 case 3:
4677 switch (sel) {
4678 case 0:
4679 gen_helper_mtc0_entrylo1(arg);
4680 rn = "EntryLo1";
4681 break;
4682 default:
4683 goto die;
4685 break;
4686 case 4:
4687 switch (sel) {
4688 case 0:
4689 gen_helper_mtc0_context(arg);
4690 rn = "Context";
4691 break;
4692 case 1:
4693 // gen_helper_mtc0_contextconfig(arg); /* SmartMIPS ASE */
4694 rn = "ContextConfig";
4695 // break;
4696 default:
4697 goto die;
4699 break;
4700 case 5:
4701 switch (sel) {
4702 case 0:
4703 gen_helper_mtc0_pagemask(arg);
4704 rn = "PageMask";
4705 break;
4706 case 1:
4707 check_insn(env, ctx, ISA_MIPS32R2);
4708 gen_helper_mtc0_pagegrain(arg);
4709 rn = "PageGrain";
4710 break;
4711 default:
4712 goto die;
4714 break;
4715 case 6:
4716 switch (sel) {
4717 case 0:
4718 gen_helper_mtc0_wired(arg);
4719 rn = "Wired";
4720 break;
4721 case 1:
4722 check_insn(env, ctx, ISA_MIPS32R2);
4723 gen_helper_mtc0_srsconf0(arg);
4724 rn = "SRSConf0";
4725 break;
4726 case 2:
4727 check_insn(env, ctx, ISA_MIPS32R2);
4728 gen_helper_mtc0_srsconf1(arg);
4729 rn = "SRSConf1";
4730 break;
4731 case 3:
4732 check_insn(env, ctx, ISA_MIPS32R2);
4733 gen_helper_mtc0_srsconf2(arg);
4734 rn = "SRSConf2";
4735 break;
4736 case 4:
4737 check_insn(env, ctx, ISA_MIPS32R2);
4738 gen_helper_mtc0_srsconf3(arg);
4739 rn = "SRSConf3";
4740 break;
4741 case 5:
4742 check_insn(env, ctx, ISA_MIPS32R2);
4743 gen_helper_mtc0_srsconf4(arg);
4744 rn = "SRSConf4";
4745 break;
4746 default:
4747 goto die;
4749 break;
4750 case 7:
4751 switch (sel) {
4752 case 0:
4753 check_insn(env, ctx, ISA_MIPS32R2);
4754 gen_helper_mtc0_hwrena(arg);
4755 rn = "HWREna";
4756 break;
4757 default:
4758 goto die;
4760 break;
4761 case 8:
4762 /* ignored */
4763 rn = "BadVAddr";
4764 break;
4765 case 9:
4766 switch (sel) {
4767 case 0:
4768 gen_helper_mtc0_count(arg);
4769 rn = "Count";
4770 break;
4771 /* 6,7 are implementation dependent */
4772 default:
4773 goto die;
4775 /* Stop translation as we may have switched the execution mode */
4776 ctx->bstate = BS_STOP;
4777 break;
4778 case 10:
4779 switch (sel) {
4780 case 0:
4781 gen_helper_mtc0_entryhi(arg);
4782 rn = "EntryHi";
4783 break;
4784 default:
4785 goto die;
4787 break;
4788 case 11:
4789 switch (sel) {
4790 case 0:
4791 gen_helper_mtc0_compare(arg);
4792 rn = "Compare";
4793 break;
4794 /* 6,7 are implementation dependent */
4795 default:
4796 goto die;
4798 /* Stop translation as we may have switched the execution mode */
4799 ctx->bstate = BS_STOP;
4800 break;
4801 case 12:
4802 switch (sel) {
4803 case 0:
4804 save_cpu_state(ctx, 1);
4805 gen_helper_mtc0_status(arg);
4806 /* BS_STOP isn't good enough here, hflags may have changed. */
4807 gen_save_pc(ctx->pc + 4);
4808 ctx->bstate = BS_EXCP;
4809 rn = "Status";
4810 break;
4811 case 1:
4812 check_insn(env, ctx, ISA_MIPS32R2);
4813 gen_helper_mtc0_intctl(arg);
4814 /* Stop translation as we may have switched the execution mode */
4815 ctx->bstate = BS_STOP;
4816 rn = "IntCtl";
4817 break;
4818 case 2:
4819 check_insn(env, ctx, ISA_MIPS32R2);
4820 gen_helper_mtc0_srsctl(arg);
4821 /* Stop translation as we may have switched the execution mode */
4822 ctx->bstate = BS_STOP;
4823 rn = "SRSCtl";
4824 break;
4825 case 3:
4826 check_insn(env, ctx, ISA_MIPS32R2);
4827 gen_mtc0_store32(arg, offsetof(CPUState, CP0_SRSMap));
4828 /* Stop translation as we may have switched the execution mode */
4829 ctx->bstate = BS_STOP;
4830 rn = "SRSMap";
4831 break;
4832 default:
4833 goto die;
4835 break;
4836 case 13:
4837 switch (sel) {
4838 case 0:
4839 save_cpu_state(ctx, 1);
4840 gen_helper_mtc0_cause(arg);
4841 rn = "Cause";
4842 break;
4843 default:
4844 goto die;
4846 break;
4847 case 14:
4848 switch (sel) {
4849 case 0:
4850 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUState, CP0_EPC));
4851 rn = "EPC";
4852 break;
4853 default:
4854 goto die;
4856 break;
4857 case 15:
4858 switch (sel) {
4859 case 0:
4860 /* ignored */
4861 rn = "PRid";
4862 break;
4863 case 1:
4864 check_insn(env, ctx, ISA_MIPS32R2);
4865 gen_helper_mtc0_ebase(arg);
4866 rn = "EBase";
4867 break;
4868 default:
4869 goto die;
4871 break;
4872 case 16:
4873 switch (sel) {
4874 case 0:
4875 gen_helper_mtc0_config0(arg);
4876 rn = "Config";
4877 /* Stop translation as we may have switched the execution mode */
4878 ctx->bstate = BS_STOP;
4879 break;
4880 case 1:
4881 /* ignored, read only */
4882 rn = "Config1";
4883 break;
4884 case 2:
4885 gen_helper_mtc0_config2(arg);
4886 rn = "Config2";
4887 /* Stop translation as we may have switched the execution mode */
4888 ctx->bstate = BS_STOP;
4889 break;
4890 case 3:
4891 /* ignored */
4892 rn = "Config3";
4893 break;
4894 /* 6,7 are implementation dependent */
4895 default:
4896 rn = "Invalid config selector";
4897 goto die;
4899 break;
4900 case 17:
4901 switch (sel) {
4902 case 0:
4903 gen_helper_mtc0_lladdr(arg);
4904 rn = "LLAddr";
4905 break;
4906 default:
4907 goto die;
4909 break;
4910 case 18:
4911 switch (sel) {
4912 case 0 ... 7:
4913 gen_helper_1i(mtc0_watchlo, arg, sel);
4914 rn = "WatchLo";
4915 break;
4916 default:
4917 goto die;
4919 break;
4920 case 19:
4921 switch (sel) {
4922 case 0 ... 7:
4923 gen_helper_1i(mtc0_watchhi, arg, sel);
4924 rn = "WatchHi";
4925 break;
4926 default:
4927 goto die;
4929 break;
4930 case 20:
4931 switch (sel) {
4932 case 0:
4933 check_insn(env, ctx, ISA_MIPS3);
4934 gen_helper_mtc0_xcontext(arg);
4935 rn = "XContext";
4936 break;
4937 default:
4938 goto die;
4940 break;
4941 case 21:
4942 /* Officially reserved, but sel 0 is used for R1x000 framemask */
4943 switch (sel) {
4944 case 0:
4945 gen_helper_mtc0_framemask(arg);
4946 rn = "Framemask";
4947 break;
4948 default:
4949 goto die;
4951 break;
4952 case 22:
4953 /* ignored */
4954 rn = "Diagnostic"; /* implementation dependent */
4955 break;
4956 case 23:
4957 switch (sel) {
4958 case 0:
4959 gen_helper_mtc0_debug(arg); /* EJTAG support */
4960 /* BS_STOP isn't good enough here, hflags may have changed. */
4961 gen_save_pc(ctx->pc + 4);
4962 ctx->bstate = BS_EXCP;
4963 rn = "Debug";
4964 break;
4965 case 1:
4966 // gen_helper_mtc0_tracecontrol(arg); /* PDtrace support */
4967 /* Stop translation as we may have switched the execution mode */
4968 ctx->bstate = BS_STOP;
4969 rn = "TraceControl";
4970 // break;
4971 case 2:
4972 // gen_helper_mtc0_tracecontrol2(arg); /* PDtrace support */
4973 /* Stop translation as we may have switched the execution mode */
4974 ctx->bstate = BS_STOP;
4975 rn = "TraceControl2";
4976 // break;
4977 case 3:
4978 // gen_helper_mtc0_usertracedata(arg); /* PDtrace support */
4979 /* Stop translation as we may have switched the execution mode */
4980 ctx->bstate = BS_STOP;
4981 rn = "UserTraceData";
4982 // break;
4983 case 4:
4984 // gen_helper_mtc0_tracebpc(arg); /* PDtrace support */
4985 /* Stop translation as we may have switched the execution mode */
4986 ctx->bstate = BS_STOP;
4987 rn = "TraceBPC";
4988 // break;
4989 default:
4990 goto die;
4992 break;
4993 case 24:
4994 switch (sel) {
4995 case 0:
4996 /* EJTAG support */
4997 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUState, CP0_DEPC));
4998 rn = "DEPC";
4999 break;
5000 default:
5001 goto die;
5003 break;
5004 case 25:
5005 switch (sel) {
5006 case 0:
5007 gen_helper_mtc0_performance0(arg);
5008 rn = "Performance0";
5009 break;
5010 case 1:
5011 // gen_helper_mtc0_performance1(arg);
5012 rn = "Performance1";
5013 // break;
5014 case 2:
5015 // gen_helper_mtc0_performance2(arg);
5016 rn = "Performance2";
5017 // break;
5018 case 3:
5019 // gen_helper_mtc0_performance3(arg);
5020 rn = "Performance3";
5021 // break;
5022 case 4:
5023 // gen_helper_mtc0_performance4(arg);
5024 rn = "Performance4";
5025 // break;
5026 case 5:
5027 // gen_helper_mtc0_performance5(arg);
5028 rn = "Performance5";
5029 // break;
5030 case 6:
5031 // gen_helper_mtc0_performance6(arg);
5032 rn = "Performance6";
5033 // break;
5034 case 7:
5035 // gen_helper_mtc0_performance7(arg);
5036 rn = "Performance7";
5037 // break;
5038 default:
5039 goto die;
5041 break;
5042 case 26:
5043 /* ignored */
5044 rn = "ECC";
5045 break;
5046 case 27:
5047 switch (sel) {
5048 case 0 ... 3:
5049 /* ignored */
5050 rn = "CacheErr";
5051 break;
5052 default:
5053 goto die;
5055 break;
5056 case 28:
5057 switch (sel) {
5058 case 0:
5059 case 2:
5060 case 4:
5061 case 6:
5062 gen_helper_mtc0_taglo(arg);
5063 rn = "TagLo";
5064 break;
5065 case 1:
5066 case 3:
5067 case 5:
5068 case 7:
5069 gen_helper_mtc0_datalo(arg);
5070 rn = "DataLo";
5071 break;
5072 default:
5073 goto die;
5075 break;
5076 case 29:
5077 switch (sel) {
5078 case 0:
5079 case 2:
5080 case 4:
5081 case 6:
5082 gen_helper_mtc0_taghi(arg);
5083 rn = "TagHi";
5084 break;
5085 case 1:
5086 case 3:
5087 case 5:
5088 case 7:
5089 gen_helper_mtc0_datahi(arg);
5090 rn = "DataHi";
5091 break;
5092 default:
5093 rn = "invalid sel";
5094 goto die;
5096 break;
5097 case 30:
5098 switch (sel) {
5099 case 0:
5100 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUState, CP0_ErrorEPC));
5101 rn = "ErrorEPC";
5102 break;
5103 default:
5104 goto die;
5106 break;
5107 case 31:
5108 switch (sel) {
5109 case 0:
5110 /* EJTAG support */
5111 gen_mtc0_store32(arg, offsetof(CPUState, CP0_DESAVE));
5112 rn = "DESAVE";
5113 break;
5114 default:
5115 goto die;
5117 /* Stop translation as we may have switched the execution mode */
5118 ctx->bstate = BS_STOP;
5119 break;
5120 default:
5121 goto die;
5123 LOG_DISAS("dmtc0 %s (reg %d sel %d)\n", rn, reg, sel);
5124 /* For simplicity assume that all writes can cause interrupts. */
5125 if (use_icount) {
5126 gen_io_end();
5127 ctx->bstate = BS_STOP;
5129 return;
5131 die:
5132 LOG_DISAS("dmtc0 %s (reg %d sel %d)\n", rn, reg, sel);
5133 generate_exception(ctx, EXCP_RI);
5135 #endif /* TARGET_MIPS64 */
5137 static void gen_mftr(CPUState *env, DisasContext *ctx, int rt, int rd,
5138 int u, int sel, int h)
5140 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
5141 TCGv t0 = tcg_temp_local_new();
5143 if ((env->CP0_VPEConf0 & (1 << CP0VPEC0_MVP)) == 0 &&
5144 ((env->tcs[other_tc].CP0_TCBind & (0xf << CP0TCBd_CurVPE)) !=
5145 (env->active_tc.CP0_TCBind & (0xf << CP0TCBd_CurVPE))))
5146 tcg_gen_movi_tl(t0, -1);
5147 else if ((env->CP0_VPEControl & (0xff << CP0VPECo_TargTC)) >
5148 (env->mvp->CP0_MVPConf0 & (0xff << CP0MVPC0_PTC)))
5149 tcg_gen_movi_tl(t0, -1);
5150 else if (u == 0) {
5151 switch (rt) {
5152 case 2:
5153 switch (sel) {
5154 case 1:
5155 gen_helper_mftc0_tcstatus(t0);
5156 break;
5157 case 2:
5158 gen_helper_mftc0_tcbind(t0);
5159 break;
5160 case 3:
5161 gen_helper_mftc0_tcrestart(t0);
5162 break;
5163 case 4:
5164 gen_helper_mftc0_tchalt(t0);
5165 break;
5166 case 5:
5167 gen_helper_mftc0_tccontext(t0);
5168 break;
5169 case 6:
5170 gen_helper_mftc0_tcschedule(t0);
5171 break;
5172 case 7:
5173 gen_helper_mftc0_tcschefback(t0);
5174 break;
5175 default:
5176 gen_mfc0(env, ctx, t0, rt, sel);
5177 break;
5179 break;
5180 case 10:
5181 switch (sel) {
5182 case 0:
5183 gen_helper_mftc0_entryhi(t0);
5184 break;
5185 default:
5186 gen_mfc0(env, ctx, t0, rt, sel);
5187 break;
5189 case 12:
5190 switch (sel) {
5191 case 0:
5192 gen_helper_mftc0_status(t0);
5193 break;
5194 default:
5195 gen_mfc0(env, ctx, t0, rt, sel);
5196 break;
5198 case 23:
5199 switch (sel) {
5200 case 0:
5201 gen_helper_mftc0_debug(t0);
5202 break;
5203 default:
5204 gen_mfc0(env, ctx, t0, rt, sel);
5205 break;
5207 break;
5208 default:
5209 gen_mfc0(env, ctx, t0, rt, sel);
5211 } else switch (sel) {
5212 /* GPR registers. */
5213 case 0:
5214 gen_helper_1i(mftgpr, t0, rt);
5215 break;
5216 /* Auxiliary CPU registers */
5217 case 1:
5218 switch (rt) {
5219 case 0:
5220 gen_helper_1i(mftlo, t0, 0);
5221 break;
5222 case 1:
5223 gen_helper_1i(mfthi, t0, 0);
5224 break;
5225 case 2:
5226 gen_helper_1i(mftacx, t0, 0);
5227 break;
5228 case 4:
5229 gen_helper_1i(mftlo, t0, 1);
5230 break;
5231 case 5:
5232 gen_helper_1i(mfthi, t0, 1);
5233 break;
5234 case 6:
5235 gen_helper_1i(mftacx, t0, 1);
5236 break;
5237 case 8:
5238 gen_helper_1i(mftlo, t0, 2);
5239 break;
5240 case 9:
5241 gen_helper_1i(mfthi, t0, 2);
5242 break;
5243 case 10:
5244 gen_helper_1i(mftacx, t0, 2);
5245 break;
5246 case 12:
5247 gen_helper_1i(mftlo, t0, 3);
5248 break;
5249 case 13:
5250 gen_helper_1i(mfthi, t0, 3);
5251 break;
5252 case 14:
5253 gen_helper_1i(mftacx, t0, 3);
5254 break;
5255 case 16:
5256 gen_helper_mftdsp(t0);
5257 break;
5258 default:
5259 goto die;
5261 break;
5262 /* Floating point (COP1). */
5263 case 2:
5264 /* XXX: For now we support only a single FPU context. */
5265 if (h == 0) {
5266 TCGv_i32 fp0 = tcg_temp_new_i32();
5268 gen_load_fpr32(fp0, rt);
5269 tcg_gen_ext_i32_tl(t0, fp0);
5270 tcg_temp_free_i32(fp0);
5271 } else {
5272 TCGv_i32 fp0 = tcg_temp_new_i32();
5274 gen_load_fpr32h(fp0, rt);
5275 tcg_gen_ext_i32_tl(t0, fp0);
5276 tcg_temp_free_i32(fp0);
5278 break;
5279 case 3:
5280 /* XXX: For now we support only a single FPU context. */
5281 gen_helper_1i(cfc1, t0, rt);
5282 break;
5283 /* COP2: Not implemented. */
5284 case 4:
5285 case 5:
5286 /* fall through */
5287 default:
5288 goto die;
5290 LOG_DISAS("mftr (reg %d u %d sel %d h %d)\n", rt, u, sel, h);
5291 gen_store_gpr(t0, rd);
5292 tcg_temp_free(t0);
5293 return;
5295 die:
5296 tcg_temp_free(t0);
5297 LOG_DISAS("mftr (reg %d u %d sel %d h %d)\n", rt, u, sel, h);
5298 generate_exception(ctx, EXCP_RI);
5301 static void gen_mttr(CPUState *env, DisasContext *ctx, int rd, int rt,
5302 int u, int sel, int h)
5304 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
5305 TCGv t0 = tcg_temp_local_new();
5307 gen_load_gpr(t0, rt);
5308 if ((env->CP0_VPEConf0 & (1 << CP0VPEC0_MVP)) == 0 &&
5309 ((env->tcs[other_tc].CP0_TCBind & (0xf << CP0TCBd_CurVPE)) !=
5310 (env->active_tc.CP0_TCBind & (0xf << CP0TCBd_CurVPE))))
5311 /* NOP */ ;
5312 else if ((env->CP0_VPEControl & (0xff << CP0VPECo_TargTC)) >
5313 (env->mvp->CP0_MVPConf0 & (0xff << CP0MVPC0_PTC)))
5314 /* NOP */ ;
5315 else if (u == 0) {
5316 switch (rd) {
5317 case 2:
5318 switch (sel) {
5319 case 1:
5320 gen_helper_mttc0_tcstatus(t0);
5321 break;
5322 case 2:
5323 gen_helper_mttc0_tcbind(t0);
5324 break;
5325 case 3:
5326 gen_helper_mttc0_tcrestart(t0);
5327 break;
5328 case 4:
5329 gen_helper_mttc0_tchalt(t0);
5330 break;
5331 case 5:
5332 gen_helper_mttc0_tccontext(t0);
5333 break;
5334 case 6:
5335 gen_helper_mttc0_tcschedule(t0);
5336 break;
5337 case 7:
5338 gen_helper_mttc0_tcschefback(t0);
5339 break;
5340 default:
5341 gen_mtc0(env, ctx, t0, rd, sel);
5342 break;
5344 break;
5345 case 10:
5346 switch (sel) {
5347 case 0:
5348 gen_helper_mttc0_entryhi(t0);
5349 break;
5350 default:
5351 gen_mtc0(env, ctx, t0, rd, sel);
5352 break;
5354 case 12:
5355 switch (sel) {
5356 case 0:
5357 gen_helper_mttc0_status(t0);
5358 break;
5359 default:
5360 gen_mtc0(env, ctx, t0, rd, sel);
5361 break;
5363 case 23:
5364 switch (sel) {
5365 case 0:
5366 gen_helper_mttc0_debug(t0);
5367 break;
5368 default:
5369 gen_mtc0(env, ctx, t0, rd, sel);
5370 break;
5372 break;
5373 default:
5374 gen_mtc0(env, ctx, t0, rd, sel);
5376 } else switch (sel) {
5377 /* GPR registers. */
5378 case 0:
5379 gen_helper_1i(mttgpr, t0, rd);
5380 break;
5381 /* Auxiliary CPU registers */
5382 case 1:
5383 switch (rd) {
5384 case 0:
5385 gen_helper_1i(mttlo, t0, 0);
5386 break;
5387 case 1:
5388 gen_helper_1i(mtthi, t0, 0);
5389 break;
5390 case 2:
5391 gen_helper_1i(mttacx, t0, 0);
5392 break;
5393 case 4:
5394 gen_helper_1i(mttlo, t0, 1);
5395 break;
5396 case 5:
5397 gen_helper_1i(mtthi, t0, 1);
5398 break;
5399 case 6:
5400 gen_helper_1i(mttacx, t0, 1);
5401 break;
5402 case 8:
5403 gen_helper_1i(mttlo, t0, 2);
5404 break;
5405 case 9:
5406 gen_helper_1i(mtthi, t0, 2);
5407 break;
5408 case 10:
5409 gen_helper_1i(mttacx, t0, 2);
5410 break;
5411 case 12:
5412 gen_helper_1i(mttlo, t0, 3);
5413 break;
5414 case 13:
5415 gen_helper_1i(mtthi, t0, 3);
5416 break;
5417 case 14:
5418 gen_helper_1i(mttacx, t0, 3);
5419 break;
5420 case 16:
5421 gen_helper_mttdsp(t0);
5422 break;
5423 default:
5424 goto die;
5426 break;
5427 /* Floating point (COP1). */
5428 case 2:
5429 /* XXX: For now we support only a single FPU context. */
5430 if (h == 0) {
5431 TCGv_i32 fp0 = tcg_temp_new_i32();
5433 tcg_gen_trunc_tl_i32(fp0, t0);
5434 gen_store_fpr32(fp0, rd);
5435 tcg_temp_free_i32(fp0);
5436 } else {
5437 TCGv_i32 fp0 = tcg_temp_new_i32();
5439 tcg_gen_trunc_tl_i32(fp0, t0);
5440 gen_store_fpr32h(fp0, rd);
5441 tcg_temp_free_i32(fp0);
5443 break;
5444 case 3:
5445 /* XXX: For now we support only a single FPU context. */
5446 gen_helper_1i(ctc1, t0, rd);
5447 break;
5448 /* COP2: Not implemented. */
5449 case 4:
5450 case 5:
5451 /* fall through */
5452 default:
5453 goto die;
5455 LOG_DISAS("mttr (reg %d u %d sel %d h %d)\n", rd, u, sel, h);
5456 tcg_temp_free(t0);
5457 return;
5459 die:
5460 tcg_temp_free(t0);
5461 LOG_DISAS("mttr (reg %d u %d sel %d h %d)\n", rd, u, sel, h);
5462 generate_exception(ctx, EXCP_RI);
5465 static void gen_cp0 (CPUState *env, DisasContext *ctx, uint32_t opc, int rt, int rd)
5467 const char *opn = "ldst";
5469 switch (opc) {
5470 case OPC_MFC0:
5471 if (rt == 0) {
5472 /* Treat as NOP. */
5473 return;
5475 gen_mfc0(env, ctx, cpu_gpr[rt], rd, ctx->opcode & 0x7);
5476 opn = "mfc0";
5477 break;
5478 case OPC_MTC0:
5480 TCGv t0 = tcg_temp_new();
5482 gen_load_gpr(t0, rt);
5483 gen_mtc0(env, ctx, t0, rd, ctx->opcode & 0x7);
5484 tcg_temp_free(t0);
5486 opn = "mtc0";
5487 break;
5488 #if defined(TARGET_MIPS64)
5489 case OPC_DMFC0:
5490 check_insn(env, ctx, ISA_MIPS3);
5491 if (rt == 0) {
5492 /* Treat as NOP. */
5493 return;
5495 gen_dmfc0(env, ctx, cpu_gpr[rt], rd, ctx->opcode & 0x7);
5496 opn = "dmfc0";
5497 break;
5498 case OPC_DMTC0:
5499 check_insn(env, ctx, ISA_MIPS3);
5501 TCGv t0 = tcg_temp_new();
5503 gen_load_gpr(t0, rt);
5504 gen_dmtc0(env, ctx, t0, rd, ctx->opcode & 0x7);
5505 tcg_temp_free(t0);
5507 opn = "dmtc0";
5508 break;
5509 #endif
5510 case OPC_MFTR:
5511 check_insn(env, ctx, ASE_MT);
5512 if (rd == 0) {
5513 /* Treat as NOP. */
5514 return;
5516 gen_mftr(env, ctx, rt, rd, (ctx->opcode >> 5) & 1,
5517 ctx->opcode & 0x7, (ctx->opcode >> 4) & 1);
5518 opn = "mftr";
5519 break;
5520 case OPC_MTTR:
5521 check_insn(env, ctx, ASE_MT);
5522 gen_mttr(env, ctx, rd, rt, (ctx->opcode >> 5) & 1,
5523 ctx->opcode & 0x7, (ctx->opcode >> 4) & 1);
5524 opn = "mttr";
5525 break;
5526 case OPC_TLBWI:
5527 opn = "tlbwi";
5528 if (!env->tlb->helper_tlbwi)
5529 goto die;
5530 gen_helper_tlbwi();
5531 break;
5532 case OPC_TLBWR:
5533 opn = "tlbwr";
5534 if (!env->tlb->helper_tlbwr)
5535 goto die;
5536 gen_helper_tlbwr();
5537 break;
5538 case OPC_TLBP:
5539 opn = "tlbp";
5540 if (!env->tlb->helper_tlbp)
5541 goto die;
5542 gen_helper_tlbp();
5543 break;
5544 case OPC_TLBR:
5545 opn = "tlbr";
5546 if (!env->tlb->helper_tlbr)
5547 goto die;
5548 gen_helper_tlbr();
5549 break;
5550 case OPC_ERET:
5551 opn = "eret";
5552 check_insn(env, ctx, ISA_MIPS2);
5553 gen_helper_eret();
5554 ctx->bstate = BS_EXCP;
5555 break;
5556 case OPC_DERET:
5557 opn = "deret";
5558 check_insn(env, ctx, ISA_MIPS32);
5559 if (!(ctx->hflags & MIPS_HFLAG_DM)) {
5560 MIPS_INVAL(opn);
5561 generate_exception(ctx, EXCP_RI);
5562 } else {
5563 gen_helper_deret();
5564 ctx->bstate = BS_EXCP;
5566 break;
5567 case OPC_WAIT:
5568 opn = "wait";
5569 check_insn(env, ctx, ISA_MIPS3 | ISA_MIPS32);
5570 /* If we get an exception, we want to restart at next instruction */
5571 ctx->pc += 4;
5572 save_cpu_state(ctx, 1);
5573 ctx->pc -= 4;
5574 gen_helper_wait();
5575 ctx->bstate = BS_EXCP;
5576 break;
5577 default:
5578 die:
5579 MIPS_INVAL(opn);
5580 generate_exception(ctx, EXCP_RI);
5581 return;
5583 MIPS_DEBUG("%s %s %d", opn, regnames[rt], rd);
5585 #endif /* !CONFIG_USER_ONLY */
5587 /* CP1 Branches (before delay slot) */
5588 static void gen_compute_branch1 (CPUState *env, DisasContext *ctx, uint32_t op,
5589 int32_t cc, int32_t offset)
5591 target_ulong btarget;
5592 const char *opn = "cp1 cond branch";
5593 TCGv_i32 t0 = tcg_temp_new_i32();
5595 if (cc != 0)
5596 check_insn(env, ctx, ISA_MIPS4 | ISA_MIPS32);
5598 btarget = ctx->pc + 4 + offset;
5600 switch (op) {
5601 case OPC_BC1F:
5602 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
5603 tcg_gen_not_i32(t0, t0);
5604 tcg_gen_andi_i32(t0, t0, 1);
5605 tcg_gen_extu_i32_tl(bcond, t0);
5606 opn = "bc1f";
5607 goto not_likely;
5608 case OPC_BC1FL:
5609 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
5610 tcg_gen_not_i32(t0, t0);
5611 tcg_gen_andi_i32(t0, t0, 1);
5612 tcg_gen_extu_i32_tl(bcond, t0);
5613 opn = "bc1fl";
5614 goto likely;
5615 case OPC_BC1T:
5616 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
5617 tcg_gen_andi_i32(t0, t0, 1);
5618 tcg_gen_extu_i32_tl(bcond, t0);
5619 opn = "bc1t";
5620 goto not_likely;
5621 case OPC_BC1TL:
5622 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
5623 tcg_gen_andi_i32(t0, t0, 1);
5624 tcg_gen_extu_i32_tl(bcond, t0);
5625 opn = "bc1tl";
5626 likely:
5627 ctx->hflags |= MIPS_HFLAG_BL;
5628 break;
5629 case OPC_BC1FANY2:
5631 TCGv_i32 t1 = tcg_temp_new_i32();
5632 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
5633 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+1));
5634 tcg_gen_nor_i32(t0, t0, t1);
5635 tcg_temp_free_i32(t1);
5636 tcg_gen_andi_i32(t0, t0, 1);
5637 tcg_gen_extu_i32_tl(bcond, t0);
5639 opn = "bc1any2f";
5640 goto not_likely;
5641 case OPC_BC1TANY2:
5643 TCGv_i32 t1 = tcg_temp_new_i32();
5644 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
5645 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+1));
5646 tcg_gen_or_i32(t0, t0, t1);
5647 tcg_temp_free_i32(t1);
5648 tcg_gen_andi_i32(t0, t0, 1);
5649 tcg_gen_extu_i32_tl(bcond, t0);
5651 opn = "bc1any2t";
5652 goto not_likely;
5653 case OPC_BC1FANY4:
5655 TCGv_i32 t1 = tcg_temp_new_i32();
5656 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
5657 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+1));
5658 tcg_gen_or_i32(t0, t0, t1);
5659 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+2));
5660 tcg_gen_or_i32(t0, t0, t1);
5661 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+3));
5662 tcg_gen_nor_i32(t0, t0, t1);
5663 tcg_temp_free_i32(t1);
5664 tcg_gen_andi_i32(t0, t0, 1);
5665 tcg_gen_extu_i32_tl(bcond, t0);
5667 opn = "bc1any4f";
5668 goto not_likely;
5669 case OPC_BC1TANY4:
5671 TCGv_i32 t1 = tcg_temp_new_i32();
5672 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
5673 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+1));
5674 tcg_gen_or_i32(t0, t0, t1);
5675 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+2));
5676 tcg_gen_or_i32(t0, t0, t1);
5677 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+3));
5678 tcg_gen_or_i32(t0, t0, t1);
5679 tcg_temp_free_i32(t1);
5680 tcg_gen_andi_i32(t0, t0, 1);
5681 tcg_gen_extu_i32_tl(bcond, t0);
5683 opn = "bc1any4t";
5684 not_likely:
5685 ctx->hflags |= MIPS_HFLAG_BC;
5686 break;
5687 default:
5688 MIPS_INVAL(opn);
5689 generate_exception (ctx, EXCP_RI);
5690 goto out;
5692 MIPS_DEBUG("%s: cond %02x target " TARGET_FMT_lx, opn,
5693 ctx->hflags, btarget);
5694 ctx->btarget = btarget;
5696 out:
5697 tcg_temp_free_i32(t0);
5700 /* Coprocessor 1 (FPU) */
5702 #define FOP(func, fmt) (((fmt) << 21) | (func))
5704 static void gen_cp1 (DisasContext *ctx, uint32_t opc, int rt, int fs)
5706 const char *opn = "cp1 move";
5707 TCGv t0 = tcg_temp_new();
5709 switch (opc) {
5710 case OPC_MFC1:
5712 TCGv_i32 fp0 = tcg_temp_new_i32();
5714 gen_load_fpr32(fp0, fs);
5715 tcg_gen_ext_i32_tl(t0, fp0);
5716 tcg_temp_free_i32(fp0);
5718 gen_store_gpr(t0, rt);
5719 opn = "mfc1";
5720 break;
5721 case OPC_MTC1:
5722 gen_load_gpr(t0, rt);
5724 TCGv_i32 fp0 = tcg_temp_new_i32();
5726 tcg_gen_trunc_tl_i32(fp0, t0);
5727 gen_store_fpr32(fp0, fs);
5728 tcg_temp_free_i32(fp0);
5730 opn = "mtc1";
5731 break;
5732 case OPC_CFC1:
5733 gen_helper_1i(cfc1, t0, fs);
5734 gen_store_gpr(t0, rt);
5735 opn = "cfc1";
5736 break;
5737 case OPC_CTC1:
5738 gen_load_gpr(t0, rt);
5739 gen_helper_1i(ctc1, t0, fs);
5740 opn = "ctc1";
5741 break;
5742 #if defined(TARGET_MIPS64)
5743 case OPC_DMFC1:
5744 gen_load_fpr64(ctx, t0, fs);
5745 gen_store_gpr(t0, rt);
5746 opn = "dmfc1";
5747 break;
5748 case OPC_DMTC1:
5749 gen_load_gpr(t0, rt);
5750 gen_store_fpr64(ctx, t0, fs);
5751 opn = "dmtc1";
5752 break;
5753 #endif
5754 case OPC_MFHC1:
5756 TCGv_i32 fp0 = tcg_temp_new_i32();
5758 gen_load_fpr32h(fp0, fs);
5759 tcg_gen_ext_i32_tl(t0, fp0);
5760 tcg_temp_free_i32(fp0);
5762 gen_store_gpr(t0, rt);
5763 opn = "mfhc1";
5764 break;
5765 case OPC_MTHC1:
5766 gen_load_gpr(t0, rt);
5768 TCGv_i32 fp0 = tcg_temp_new_i32();
5770 tcg_gen_trunc_tl_i32(fp0, t0);
5771 gen_store_fpr32h(fp0, fs);
5772 tcg_temp_free_i32(fp0);
5774 opn = "mthc1";
5775 break;
5776 default:
5777 MIPS_INVAL(opn);
5778 generate_exception (ctx, EXCP_RI);
5779 goto out;
5781 MIPS_DEBUG("%s %s %s", opn, regnames[rt], fregnames[fs]);
5783 out:
5784 tcg_temp_free(t0);
5787 static void gen_movci (DisasContext *ctx, int rd, int rs, int cc, int tf)
5789 int l1;
5790 TCGCond cond;
5791 TCGv_i32 t0;
5793 if (rd == 0) {
5794 /* Treat as NOP. */
5795 return;
5798 if (tf)
5799 cond = TCG_COND_EQ;
5800 else
5801 cond = TCG_COND_NE;
5803 l1 = gen_new_label();
5804 t0 = tcg_temp_new_i32();
5805 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
5806 tcg_gen_brcondi_i32(cond, t0, 0, l1);
5807 tcg_temp_free_i32(t0);
5808 if (rs == 0) {
5809 tcg_gen_movi_tl(cpu_gpr[rd], 0);
5810 } else {
5811 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
5813 gen_set_label(l1);
5816 static inline void gen_movcf_s (int fs, int fd, int cc, int tf)
5818 int cond;
5819 TCGv_i32 t0 = tcg_temp_new_i32();
5820 int l1 = gen_new_label();
5822 if (tf)
5823 cond = TCG_COND_EQ;
5824 else
5825 cond = TCG_COND_NE;
5827 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
5828 tcg_gen_brcondi_i32(cond, t0, 0, l1);
5829 gen_load_fpr32(t0, fs);
5830 gen_store_fpr32(t0, fd);
5831 gen_set_label(l1);
5832 tcg_temp_free_i32(t0);
5835 static inline void gen_movcf_d (DisasContext *ctx, int fs, int fd, int cc, int tf)
5837 int cond;
5838 TCGv_i32 t0 = tcg_temp_new_i32();
5839 TCGv_i64 fp0;
5840 int l1 = gen_new_label();
5842 if (tf)
5843 cond = TCG_COND_EQ;
5844 else
5845 cond = TCG_COND_NE;
5847 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
5848 tcg_gen_brcondi_i32(cond, t0, 0, l1);
5849 tcg_temp_free_i32(t0);
5850 fp0 = tcg_temp_new_i64();
5851 gen_load_fpr64(ctx, fp0, fs);
5852 gen_store_fpr64(ctx, fp0, fd);
5853 tcg_temp_free_i64(fp0);
5854 gen_set_label(l1);
5857 static inline void gen_movcf_ps (int fs, int fd, int cc, int tf)
5859 int cond;
5860 TCGv_i32 t0 = tcg_temp_new_i32();
5861 int l1 = gen_new_label();
5862 int l2 = gen_new_label();
5864 if (tf)
5865 cond = TCG_COND_EQ;
5866 else
5867 cond = TCG_COND_NE;
5869 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
5870 tcg_gen_brcondi_i32(cond, t0, 0, l1);
5871 gen_load_fpr32(t0, fs);
5872 gen_store_fpr32(t0, fd);
5873 gen_set_label(l1);
5875 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc+1));
5876 tcg_gen_brcondi_i32(cond, t0, 0, l2);
5877 gen_load_fpr32h(t0, fs);
5878 gen_store_fpr32h(t0, fd);
5879 tcg_temp_free_i32(t0);
5880 gen_set_label(l2);
5884 static void gen_farith (DisasContext *ctx, uint32_t op1,
5885 int ft, int fs, int fd, int cc)
5887 const char *opn = "farith";
5888 const char *condnames[] = {
5889 "c.f",
5890 "c.un",
5891 "c.eq",
5892 "c.ueq",
5893 "c.olt",
5894 "c.ult",
5895 "c.ole",
5896 "c.ule",
5897 "c.sf",
5898 "c.ngle",
5899 "c.seq",
5900 "c.ngl",
5901 "c.lt",
5902 "c.nge",
5903 "c.le",
5904 "c.ngt",
5906 const char *condnames_abs[] = {
5907 "cabs.f",
5908 "cabs.un",
5909 "cabs.eq",
5910 "cabs.ueq",
5911 "cabs.olt",
5912 "cabs.ult",
5913 "cabs.ole",
5914 "cabs.ule",
5915 "cabs.sf",
5916 "cabs.ngle",
5917 "cabs.seq",
5918 "cabs.ngl",
5919 "cabs.lt",
5920 "cabs.nge",
5921 "cabs.le",
5922 "cabs.ngt",
5924 enum { BINOP, CMPOP, OTHEROP } optype = OTHEROP;
5925 uint32_t func = ctx->opcode & 0x3f;
5927 switch (ctx->opcode & FOP(0x3f, 0x1f)) {
5928 case FOP(0, 16):
5930 TCGv_i32 fp0 = tcg_temp_new_i32();
5931 TCGv_i32 fp1 = tcg_temp_new_i32();
5933 gen_load_fpr32(fp0, fs);
5934 gen_load_fpr32(fp1, ft);
5935 gen_helper_float_add_s(fp0, fp0, fp1);
5936 tcg_temp_free_i32(fp1);
5937 gen_store_fpr32(fp0, fd);
5938 tcg_temp_free_i32(fp0);
5940 opn = "add.s";
5941 optype = BINOP;
5942 break;
5943 case FOP(1, 16):
5945 TCGv_i32 fp0 = tcg_temp_new_i32();
5946 TCGv_i32 fp1 = tcg_temp_new_i32();
5948 gen_load_fpr32(fp0, fs);
5949 gen_load_fpr32(fp1, ft);
5950 gen_helper_float_sub_s(fp0, fp0, fp1);
5951 tcg_temp_free_i32(fp1);
5952 gen_store_fpr32(fp0, fd);
5953 tcg_temp_free_i32(fp0);
5955 opn = "sub.s";
5956 optype = BINOP;
5957 break;
5958 case FOP(2, 16):
5960 TCGv_i32 fp0 = tcg_temp_new_i32();
5961 TCGv_i32 fp1 = tcg_temp_new_i32();
5963 gen_load_fpr32(fp0, fs);
5964 gen_load_fpr32(fp1, ft);
5965 gen_helper_float_mul_s(fp0, fp0, fp1);
5966 tcg_temp_free_i32(fp1);
5967 gen_store_fpr32(fp0, fd);
5968 tcg_temp_free_i32(fp0);
5970 opn = "mul.s";
5971 optype = BINOP;
5972 break;
5973 case FOP(3, 16):
5975 TCGv_i32 fp0 = tcg_temp_new_i32();
5976 TCGv_i32 fp1 = tcg_temp_new_i32();
5978 gen_load_fpr32(fp0, fs);
5979 gen_load_fpr32(fp1, ft);
5980 gen_helper_float_div_s(fp0, fp0, fp1);
5981 tcg_temp_free_i32(fp1);
5982 gen_store_fpr32(fp0, fd);
5983 tcg_temp_free_i32(fp0);
5985 opn = "div.s";
5986 optype = BINOP;
5987 break;
5988 case FOP(4, 16):
5990 TCGv_i32 fp0 = tcg_temp_new_i32();
5992 gen_load_fpr32(fp0, fs);
5993 gen_helper_float_sqrt_s(fp0, fp0);
5994 gen_store_fpr32(fp0, fd);
5995 tcg_temp_free_i32(fp0);
5997 opn = "sqrt.s";
5998 break;
5999 case FOP(5, 16):
6001 TCGv_i32 fp0 = tcg_temp_new_i32();
6003 gen_load_fpr32(fp0, fs);
6004 gen_helper_float_abs_s(fp0, fp0);
6005 gen_store_fpr32(fp0, fd);
6006 tcg_temp_free_i32(fp0);
6008 opn = "abs.s";
6009 break;
6010 case FOP(6, 16):
6012 TCGv_i32 fp0 = tcg_temp_new_i32();
6014 gen_load_fpr32(fp0, fs);
6015 gen_store_fpr32(fp0, fd);
6016 tcg_temp_free_i32(fp0);
6018 opn = "mov.s";
6019 break;
6020 case FOP(7, 16):
6022 TCGv_i32 fp0 = tcg_temp_new_i32();
6024 gen_load_fpr32(fp0, fs);
6025 gen_helper_float_chs_s(fp0, fp0);
6026 gen_store_fpr32(fp0, fd);
6027 tcg_temp_free_i32(fp0);
6029 opn = "neg.s";
6030 break;
6031 case FOP(8, 16):
6032 check_cp1_64bitmode(ctx);
6034 TCGv_i32 fp32 = tcg_temp_new_i32();
6035 TCGv_i64 fp64 = tcg_temp_new_i64();
6037 gen_load_fpr32(fp32, fs);
6038 gen_helper_float_roundl_s(fp64, fp32);
6039 tcg_temp_free_i32(fp32);
6040 gen_store_fpr64(ctx, fp64, fd);
6041 tcg_temp_free_i64(fp64);
6043 opn = "round.l.s";
6044 break;
6045 case FOP(9, 16):
6046 check_cp1_64bitmode(ctx);
6048 TCGv_i32 fp32 = tcg_temp_new_i32();
6049 TCGv_i64 fp64 = tcg_temp_new_i64();
6051 gen_load_fpr32(fp32, fs);
6052 gen_helper_float_truncl_s(fp64, fp32);
6053 tcg_temp_free_i32(fp32);
6054 gen_store_fpr64(ctx, fp64, fd);
6055 tcg_temp_free_i64(fp64);
6057 opn = "trunc.l.s";
6058 break;
6059 case FOP(10, 16):
6060 check_cp1_64bitmode(ctx);
6062 TCGv_i32 fp32 = tcg_temp_new_i32();
6063 TCGv_i64 fp64 = tcg_temp_new_i64();
6065 gen_load_fpr32(fp32, fs);
6066 gen_helper_float_ceill_s(fp64, fp32);
6067 tcg_temp_free_i32(fp32);
6068 gen_store_fpr64(ctx, fp64, fd);
6069 tcg_temp_free_i64(fp64);
6071 opn = "ceil.l.s";
6072 break;
6073 case FOP(11, 16):
6074 check_cp1_64bitmode(ctx);
6076 TCGv_i32 fp32 = tcg_temp_new_i32();
6077 TCGv_i64 fp64 = tcg_temp_new_i64();
6079 gen_load_fpr32(fp32, fs);
6080 gen_helper_float_floorl_s(fp64, fp32);
6081 tcg_temp_free_i32(fp32);
6082 gen_store_fpr64(ctx, fp64, fd);
6083 tcg_temp_free_i64(fp64);
6085 opn = "floor.l.s";
6086 break;
6087 case FOP(12, 16):
6089 TCGv_i32 fp0 = tcg_temp_new_i32();
6091 gen_load_fpr32(fp0, fs);
6092 gen_helper_float_roundw_s(fp0, fp0);
6093 gen_store_fpr32(fp0, fd);
6094 tcg_temp_free_i32(fp0);
6096 opn = "round.w.s";
6097 break;
6098 case FOP(13, 16):
6100 TCGv_i32 fp0 = tcg_temp_new_i32();
6102 gen_load_fpr32(fp0, fs);
6103 gen_helper_float_truncw_s(fp0, fp0);
6104 gen_store_fpr32(fp0, fd);
6105 tcg_temp_free_i32(fp0);
6107 opn = "trunc.w.s";
6108 break;
6109 case FOP(14, 16):
6111 TCGv_i32 fp0 = tcg_temp_new_i32();
6113 gen_load_fpr32(fp0, fs);
6114 gen_helper_float_ceilw_s(fp0, fp0);
6115 gen_store_fpr32(fp0, fd);
6116 tcg_temp_free_i32(fp0);
6118 opn = "ceil.w.s";
6119 break;
6120 case FOP(15, 16):
6122 TCGv_i32 fp0 = tcg_temp_new_i32();
6124 gen_load_fpr32(fp0, fs);
6125 gen_helper_float_floorw_s(fp0, fp0);
6126 gen_store_fpr32(fp0, fd);
6127 tcg_temp_free_i32(fp0);
6129 opn = "floor.w.s";
6130 break;
6131 case FOP(17, 16):
6132 gen_movcf_s(fs, fd, (ft >> 2) & 0x7, ft & 0x1);
6133 opn = "movcf.s";
6134 break;
6135 case FOP(18, 16):
6137 int l1 = gen_new_label();
6138 TCGv_i32 fp0;
6140 if (ft != 0) {
6141 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[ft], 0, l1);
6143 fp0 = tcg_temp_new_i32();
6144 gen_load_fpr32(fp0, fs);
6145 gen_store_fpr32(fp0, fd);
6146 tcg_temp_free_i32(fp0);
6147 gen_set_label(l1);
6149 opn = "movz.s";
6150 break;
6151 case FOP(19, 16):
6153 int l1 = gen_new_label();
6154 TCGv_i32 fp0;
6156 if (ft != 0) {
6157 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[ft], 0, l1);
6158 fp0 = tcg_temp_new_i32();
6159 gen_load_fpr32(fp0, fs);
6160 gen_store_fpr32(fp0, fd);
6161 tcg_temp_free_i32(fp0);
6162 gen_set_label(l1);
6165 opn = "movn.s";
6166 break;
6167 case FOP(21, 16):
6168 check_cop1x(ctx);
6170 TCGv_i32 fp0 = tcg_temp_new_i32();
6172 gen_load_fpr32(fp0, fs);
6173 gen_helper_float_recip_s(fp0, fp0);
6174 gen_store_fpr32(fp0, fd);
6175 tcg_temp_free_i32(fp0);
6177 opn = "recip.s";
6178 break;
6179 case FOP(22, 16):
6180 check_cop1x(ctx);
6182 TCGv_i32 fp0 = tcg_temp_new_i32();
6184 gen_load_fpr32(fp0, fs);
6185 gen_helper_float_rsqrt_s(fp0, fp0);
6186 gen_store_fpr32(fp0, fd);
6187 tcg_temp_free_i32(fp0);
6189 opn = "rsqrt.s";
6190 break;
6191 case FOP(28, 16):
6192 check_cp1_64bitmode(ctx);
6194 TCGv_i32 fp0 = tcg_temp_new_i32();
6195 TCGv_i32 fp1 = tcg_temp_new_i32();
6197 gen_load_fpr32(fp0, fs);
6198 gen_load_fpr32(fp1, fd);
6199 gen_helper_float_recip2_s(fp0, fp0, fp1);
6200 tcg_temp_free_i32(fp1);
6201 gen_store_fpr32(fp0, fd);
6202 tcg_temp_free_i32(fp0);
6204 opn = "recip2.s";
6205 break;
6206 case FOP(29, 16):
6207 check_cp1_64bitmode(ctx);
6209 TCGv_i32 fp0 = tcg_temp_new_i32();
6211 gen_load_fpr32(fp0, fs);
6212 gen_helper_float_recip1_s(fp0, fp0);
6213 gen_store_fpr32(fp0, fd);
6214 tcg_temp_free_i32(fp0);
6216 opn = "recip1.s";
6217 break;
6218 case FOP(30, 16):
6219 check_cp1_64bitmode(ctx);
6221 TCGv_i32 fp0 = tcg_temp_new_i32();
6223 gen_load_fpr32(fp0, fs);
6224 gen_helper_float_rsqrt1_s(fp0, fp0);
6225 gen_store_fpr32(fp0, fd);
6226 tcg_temp_free_i32(fp0);
6228 opn = "rsqrt1.s";
6229 break;
6230 case FOP(31, 16):
6231 check_cp1_64bitmode(ctx);
6233 TCGv_i32 fp0 = tcg_temp_new_i32();
6234 TCGv_i32 fp1 = tcg_temp_new_i32();
6236 gen_load_fpr32(fp0, fs);
6237 gen_load_fpr32(fp1, ft);
6238 gen_helper_float_rsqrt2_s(fp0, fp0, fp1);
6239 tcg_temp_free_i32(fp1);
6240 gen_store_fpr32(fp0, fd);
6241 tcg_temp_free_i32(fp0);
6243 opn = "rsqrt2.s";
6244 break;
6245 case FOP(33, 16):
6246 check_cp1_registers(ctx, fd);
6248 TCGv_i32 fp32 = tcg_temp_new_i32();
6249 TCGv_i64 fp64 = tcg_temp_new_i64();
6251 gen_load_fpr32(fp32, fs);
6252 gen_helper_float_cvtd_s(fp64, fp32);
6253 tcg_temp_free_i32(fp32);
6254 gen_store_fpr64(ctx, fp64, fd);
6255 tcg_temp_free_i64(fp64);
6257 opn = "cvt.d.s";
6258 break;
6259 case FOP(36, 16):
6261 TCGv_i32 fp0 = tcg_temp_new_i32();
6263 gen_load_fpr32(fp0, fs);
6264 gen_helper_float_cvtw_s(fp0, fp0);
6265 gen_store_fpr32(fp0, fd);
6266 tcg_temp_free_i32(fp0);
6268 opn = "cvt.w.s";
6269 break;
6270 case FOP(37, 16):
6271 check_cp1_64bitmode(ctx);
6273 TCGv_i32 fp32 = tcg_temp_new_i32();
6274 TCGv_i64 fp64 = tcg_temp_new_i64();
6276 gen_load_fpr32(fp32, fs);
6277 gen_helper_float_cvtl_s(fp64, fp32);
6278 tcg_temp_free_i32(fp32);
6279 gen_store_fpr64(ctx, fp64, fd);
6280 tcg_temp_free_i64(fp64);
6282 opn = "cvt.l.s";
6283 break;
6284 case FOP(38, 16):
6285 check_cp1_64bitmode(ctx);
6287 TCGv_i64 fp64 = tcg_temp_new_i64();
6288 TCGv_i32 fp32_0 = tcg_temp_new_i32();
6289 TCGv_i32 fp32_1 = tcg_temp_new_i32();
6291 gen_load_fpr32(fp32_0, fs);
6292 gen_load_fpr32(fp32_1, ft);
6293 tcg_gen_concat_i32_i64(fp64, fp32_0, fp32_1);
6294 tcg_temp_free_i32(fp32_1);
6295 tcg_temp_free_i32(fp32_0);
6296 gen_store_fpr64(ctx, fp64, fd);
6297 tcg_temp_free_i64(fp64);
6299 opn = "cvt.ps.s";
6300 break;
6301 case FOP(48, 16):
6302 case FOP(49, 16):
6303 case FOP(50, 16):
6304 case FOP(51, 16):
6305 case FOP(52, 16):
6306 case FOP(53, 16):
6307 case FOP(54, 16):
6308 case FOP(55, 16):
6309 case FOP(56, 16):
6310 case FOP(57, 16):
6311 case FOP(58, 16):
6312 case FOP(59, 16):
6313 case FOP(60, 16):
6314 case FOP(61, 16):
6315 case FOP(62, 16):
6316 case FOP(63, 16):
6318 TCGv_i32 fp0 = tcg_temp_new_i32();
6319 TCGv_i32 fp1 = tcg_temp_new_i32();
6321 gen_load_fpr32(fp0, fs);
6322 gen_load_fpr32(fp1, ft);
6323 if (ctx->opcode & (1 << 6)) {
6324 check_cop1x(ctx);
6325 gen_cmpabs_s(func-48, fp0, fp1, cc);
6326 opn = condnames_abs[func-48];
6327 } else {
6328 gen_cmp_s(func-48, fp0, fp1, cc);
6329 opn = condnames[func-48];
6331 tcg_temp_free_i32(fp0);
6332 tcg_temp_free_i32(fp1);
6334 break;
6335 case FOP(0, 17):
6336 check_cp1_registers(ctx, fs | ft | fd);
6338 TCGv_i64 fp0 = tcg_temp_new_i64();
6339 TCGv_i64 fp1 = tcg_temp_new_i64();
6341 gen_load_fpr64(ctx, fp0, fs);
6342 gen_load_fpr64(ctx, fp1, ft);
6343 gen_helper_float_add_d(fp0, fp0, fp1);
6344 tcg_temp_free_i64(fp1);
6345 gen_store_fpr64(ctx, fp0, fd);
6346 tcg_temp_free_i64(fp0);
6348 opn = "add.d";
6349 optype = BINOP;
6350 break;
6351 case FOP(1, 17):
6352 check_cp1_registers(ctx, fs | ft | fd);
6354 TCGv_i64 fp0 = tcg_temp_new_i64();
6355 TCGv_i64 fp1 = tcg_temp_new_i64();
6357 gen_load_fpr64(ctx, fp0, fs);
6358 gen_load_fpr64(ctx, fp1, ft);
6359 gen_helper_float_sub_d(fp0, fp0, fp1);
6360 tcg_temp_free_i64(fp1);
6361 gen_store_fpr64(ctx, fp0, fd);
6362 tcg_temp_free_i64(fp0);
6364 opn = "sub.d";
6365 optype = BINOP;
6366 break;
6367 case FOP(2, 17):
6368 check_cp1_registers(ctx, fs | ft | fd);
6370 TCGv_i64 fp0 = tcg_temp_new_i64();
6371 TCGv_i64 fp1 = tcg_temp_new_i64();
6373 gen_load_fpr64(ctx, fp0, fs);
6374 gen_load_fpr64(ctx, fp1, ft);
6375 gen_helper_float_mul_d(fp0, fp0, fp1);
6376 tcg_temp_free_i64(fp1);
6377 gen_store_fpr64(ctx, fp0, fd);
6378 tcg_temp_free_i64(fp0);
6380 opn = "mul.d";
6381 optype = BINOP;
6382 break;
6383 case FOP(3, 17):
6384 check_cp1_registers(ctx, fs | ft | fd);
6386 TCGv_i64 fp0 = tcg_temp_new_i64();
6387 TCGv_i64 fp1 = tcg_temp_new_i64();
6389 gen_load_fpr64(ctx, fp0, fs);
6390 gen_load_fpr64(ctx, fp1, ft);
6391 gen_helper_float_div_d(fp0, fp0, fp1);
6392 tcg_temp_free_i64(fp1);
6393 gen_store_fpr64(ctx, fp0, fd);
6394 tcg_temp_free_i64(fp0);
6396 opn = "div.d";
6397 optype = BINOP;
6398 break;
6399 case FOP(4, 17):
6400 check_cp1_registers(ctx, fs | fd);
6402 TCGv_i64 fp0 = tcg_temp_new_i64();
6404 gen_load_fpr64(ctx, fp0, fs);
6405 gen_helper_float_sqrt_d(fp0, fp0);
6406 gen_store_fpr64(ctx, fp0, fd);
6407 tcg_temp_free_i64(fp0);
6409 opn = "sqrt.d";
6410 break;
6411 case FOP(5, 17):
6412 check_cp1_registers(ctx, fs | fd);
6414 TCGv_i64 fp0 = tcg_temp_new_i64();
6416 gen_load_fpr64(ctx, fp0, fs);
6417 gen_helper_float_abs_d(fp0, fp0);
6418 gen_store_fpr64(ctx, fp0, fd);
6419 tcg_temp_free_i64(fp0);
6421 opn = "abs.d";
6422 break;
6423 case FOP(6, 17):
6424 check_cp1_registers(ctx, fs | fd);
6426 TCGv_i64 fp0 = tcg_temp_new_i64();
6428 gen_load_fpr64(ctx, fp0, fs);
6429 gen_store_fpr64(ctx, fp0, fd);
6430 tcg_temp_free_i64(fp0);
6432 opn = "mov.d";
6433 break;
6434 case FOP(7, 17):
6435 check_cp1_registers(ctx, fs | fd);
6437 TCGv_i64 fp0 = tcg_temp_new_i64();
6439 gen_load_fpr64(ctx, fp0, fs);
6440 gen_helper_float_chs_d(fp0, fp0);
6441 gen_store_fpr64(ctx, fp0, fd);
6442 tcg_temp_free_i64(fp0);
6444 opn = "neg.d";
6445 break;
6446 case FOP(8, 17):
6447 check_cp1_64bitmode(ctx);
6449 TCGv_i64 fp0 = tcg_temp_new_i64();
6451 gen_load_fpr64(ctx, fp0, fs);
6452 gen_helper_float_roundl_d(fp0, fp0);
6453 gen_store_fpr64(ctx, fp0, fd);
6454 tcg_temp_free_i64(fp0);
6456 opn = "round.l.d";
6457 break;
6458 case FOP(9, 17):
6459 check_cp1_64bitmode(ctx);
6461 TCGv_i64 fp0 = tcg_temp_new_i64();
6463 gen_load_fpr64(ctx, fp0, fs);
6464 gen_helper_float_truncl_d(fp0, fp0);
6465 gen_store_fpr64(ctx, fp0, fd);
6466 tcg_temp_free_i64(fp0);
6468 opn = "trunc.l.d";
6469 break;
6470 case FOP(10, 17):
6471 check_cp1_64bitmode(ctx);
6473 TCGv_i64 fp0 = tcg_temp_new_i64();
6475 gen_load_fpr64(ctx, fp0, fs);
6476 gen_helper_float_ceill_d(fp0, fp0);
6477 gen_store_fpr64(ctx, fp0, fd);
6478 tcg_temp_free_i64(fp0);
6480 opn = "ceil.l.d";
6481 break;
6482 case FOP(11, 17):
6483 check_cp1_64bitmode(ctx);
6485 TCGv_i64 fp0 = tcg_temp_new_i64();
6487 gen_load_fpr64(ctx, fp0, fs);
6488 gen_helper_float_floorl_d(fp0, fp0);
6489 gen_store_fpr64(ctx, fp0, fd);
6490 tcg_temp_free_i64(fp0);
6492 opn = "floor.l.d";
6493 break;
6494 case FOP(12, 17):
6495 check_cp1_registers(ctx, fs);
6497 TCGv_i32 fp32 = tcg_temp_new_i32();
6498 TCGv_i64 fp64 = tcg_temp_new_i64();
6500 gen_load_fpr64(ctx, fp64, fs);
6501 gen_helper_float_roundw_d(fp32, fp64);
6502 tcg_temp_free_i64(fp64);
6503 gen_store_fpr32(fp32, fd);
6504 tcg_temp_free_i32(fp32);
6506 opn = "round.w.d";
6507 break;
6508 case FOP(13, 17):
6509 check_cp1_registers(ctx, fs);
6511 TCGv_i32 fp32 = tcg_temp_new_i32();
6512 TCGv_i64 fp64 = tcg_temp_new_i64();
6514 gen_load_fpr64(ctx, fp64, fs);
6515 gen_helper_float_truncw_d(fp32, fp64);
6516 tcg_temp_free_i64(fp64);
6517 gen_store_fpr32(fp32, fd);
6518 tcg_temp_free_i32(fp32);
6520 opn = "trunc.w.d";
6521 break;
6522 case FOP(14, 17):
6523 check_cp1_registers(ctx, fs);
6525 TCGv_i32 fp32 = tcg_temp_new_i32();
6526 TCGv_i64 fp64 = tcg_temp_new_i64();
6528 gen_load_fpr64(ctx, fp64, fs);
6529 gen_helper_float_ceilw_d(fp32, fp64);
6530 tcg_temp_free_i64(fp64);
6531 gen_store_fpr32(fp32, fd);
6532 tcg_temp_free_i32(fp32);
6534 opn = "ceil.w.d";
6535 break;
6536 case FOP(15, 17):
6537 check_cp1_registers(ctx, fs);
6539 TCGv_i32 fp32 = tcg_temp_new_i32();
6540 TCGv_i64 fp64 = tcg_temp_new_i64();
6542 gen_load_fpr64(ctx, fp64, fs);
6543 gen_helper_float_floorw_d(fp32, fp64);
6544 tcg_temp_free_i64(fp64);
6545 gen_store_fpr32(fp32, fd);
6546 tcg_temp_free_i32(fp32);
6548 opn = "floor.w.d";
6549 break;
6550 case FOP(17, 17):
6551 gen_movcf_d(ctx, fs, fd, (ft >> 2) & 0x7, ft & 0x1);
6552 opn = "movcf.d";
6553 break;
6554 case FOP(18, 17):
6556 int l1 = gen_new_label();
6557 TCGv_i64 fp0;
6559 if (ft != 0) {
6560 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[ft], 0, l1);
6562 fp0 = tcg_temp_new_i64();
6563 gen_load_fpr64(ctx, fp0, fs);
6564 gen_store_fpr64(ctx, fp0, fd);
6565 tcg_temp_free_i64(fp0);
6566 gen_set_label(l1);
6568 opn = "movz.d";
6569 break;
6570 case FOP(19, 17):
6572 int l1 = gen_new_label();
6573 TCGv_i64 fp0;
6575 if (ft != 0) {
6576 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[ft], 0, l1);
6577 fp0 = tcg_temp_new_i64();
6578 gen_load_fpr64(ctx, fp0, fs);
6579 gen_store_fpr64(ctx, fp0, fd);
6580 tcg_temp_free_i64(fp0);
6581 gen_set_label(l1);
6584 opn = "movn.d";
6585 break;
6586 case FOP(21, 17):
6587 check_cp1_64bitmode(ctx);
6589 TCGv_i64 fp0 = tcg_temp_new_i64();
6591 gen_load_fpr64(ctx, fp0, fs);
6592 gen_helper_float_recip_d(fp0, fp0);
6593 gen_store_fpr64(ctx, fp0, fd);
6594 tcg_temp_free_i64(fp0);
6596 opn = "recip.d";
6597 break;
6598 case FOP(22, 17):
6599 check_cp1_64bitmode(ctx);
6601 TCGv_i64 fp0 = tcg_temp_new_i64();
6603 gen_load_fpr64(ctx, fp0, fs);
6604 gen_helper_float_rsqrt_d(fp0, fp0);
6605 gen_store_fpr64(ctx, fp0, fd);
6606 tcg_temp_free_i64(fp0);
6608 opn = "rsqrt.d";
6609 break;
6610 case FOP(28, 17):
6611 check_cp1_64bitmode(ctx);
6613 TCGv_i64 fp0 = tcg_temp_new_i64();
6614 TCGv_i64 fp1 = tcg_temp_new_i64();
6616 gen_load_fpr64(ctx, fp0, fs);
6617 gen_load_fpr64(ctx, fp1, ft);
6618 gen_helper_float_recip2_d(fp0, fp0, fp1);
6619 tcg_temp_free_i64(fp1);
6620 gen_store_fpr64(ctx, fp0, fd);
6621 tcg_temp_free_i64(fp0);
6623 opn = "recip2.d";
6624 break;
6625 case FOP(29, 17):
6626 check_cp1_64bitmode(ctx);
6628 TCGv_i64 fp0 = tcg_temp_new_i64();
6630 gen_load_fpr64(ctx, fp0, fs);
6631 gen_helper_float_recip1_d(fp0, fp0);
6632 gen_store_fpr64(ctx, fp0, fd);
6633 tcg_temp_free_i64(fp0);
6635 opn = "recip1.d";
6636 break;
6637 case FOP(30, 17):
6638 check_cp1_64bitmode(ctx);
6640 TCGv_i64 fp0 = tcg_temp_new_i64();
6642 gen_load_fpr64(ctx, fp0, fs);
6643 gen_helper_float_rsqrt1_d(fp0, fp0);
6644 gen_store_fpr64(ctx, fp0, fd);
6645 tcg_temp_free_i64(fp0);
6647 opn = "rsqrt1.d";
6648 break;
6649 case FOP(31, 17):
6650 check_cp1_64bitmode(ctx);
6652 TCGv_i64 fp0 = tcg_temp_new_i64();
6653 TCGv_i64 fp1 = tcg_temp_new_i64();
6655 gen_load_fpr64(ctx, fp0, fs);
6656 gen_load_fpr64(ctx, fp1, ft);
6657 gen_helper_float_rsqrt2_d(fp0, fp0, fp1);
6658 tcg_temp_free_i64(fp1);
6659 gen_store_fpr64(ctx, fp0, fd);
6660 tcg_temp_free_i64(fp0);
6662 opn = "rsqrt2.d";
6663 break;
6664 case FOP(48, 17):
6665 case FOP(49, 17):
6666 case FOP(50, 17):
6667 case FOP(51, 17):
6668 case FOP(52, 17):
6669 case FOP(53, 17):
6670 case FOP(54, 17):
6671 case FOP(55, 17):
6672 case FOP(56, 17):
6673 case FOP(57, 17):
6674 case FOP(58, 17):
6675 case FOP(59, 17):
6676 case FOP(60, 17):
6677 case FOP(61, 17):
6678 case FOP(62, 17):
6679 case FOP(63, 17):
6681 TCGv_i64 fp0 = tcg_temp_new_i64();
6682 TCGv_i64 fp1 = tcg_temp_new_i64();
6684 gen_load_fpr64(ctx, fp0, fs);
6685 gen_load_fpr64(ctx, fp1, ft);
6686 if (ctx->opcode & (1 << 6)) {
6687 check_cop1x(ctx);
6688 check_cp1_registers(ctx, fs | ft);
6689 gen_cmpabs_d(func-48, fp0, fp1, cc);
6690 opn = condnames_abs[func-48];
6691 } else {
6692 check_cp1_registers(ctx, fs | ft);
6693 gen_cmp_d(func-48, fp0, fp1, cc);
6694 opn = condnames[func-48];
6696 tcg_temp_free_i64(fp0);
6697 tcg_temp_free_i64(fp1);
6699 break;
6700 case FOP(32, 17):
6701 check_cp1_registers(ctx, fs);
6703 TCGv_i32 fp32 = tcg_temp_new_i32();
6704 TCGv_i64 fp64 = tcg_temp_new_i64();
6706 gen_load_fpr64(ctx, fp64, fs);
6707 gen_helper_float_cvts_d(fp32, fp64);
6708 tcg_temp_free_i64(fp64);
6709 gen_store_fpr32(fp32, fd);
6710 tcg_temp_free_i32(fp32);
6712 opn = "cvt.s.d";
6713 break;
6714 case FOP(36, 17):
6715 check_cp1_registers(ctx, fs);
6717 TCGv_i32 fp32 = tcg_temp_new_i32();
6718 TCGv_i64 fp64 = tcg_temp_new_i64();
6720 gen_load_fpr64(ctx, fp64, fs);
6721 gen_helper_float_cvtw_d(fp32, fp64);
6722 tcg_temp_free_i64(fp64);
6723 gen_store_fpr32(fp32, fd);
6724 tcg_temp_free_i32(fp32);
6726 opn = "cvt.w.d";
6727 break;
6728 case FOP(37, 17):
6729 check_cp1_64bitmode(ctx);
6731 TCGv_i64 fp0 = tcg_temp_new_i64();
6733 gen_load_fpr64(ctx, fp0, fs);
6734 gen_helper_float_cvtl_d(fp0, fp0);
6735 gen_store_fpr64(ctx, fp0, fd);
6736 tcg_temp_free_i64(fp0);
6738 opn = "cvt.l.d";
6739 break;
6740 case FOP(32, 20):
6742 TCGv_i32 fp0 = tcg_temp_new_i32();
6744 gen_load_fpr32(fp0, fs);
6745 gen_helper_float_cvts_w(fp0, fp0);
6746 gen_store_fpr32(fp0, fd);
6747 tcg_temp_free_i32(fp0);
6749 opn = "cvt.s.w";
6750 break;
6751 case FOP(33, 20):
6752 check_cp1_registers(ctx, fd);
6754 TCGv_i32 fp32 = tcg_temp_new_i32();
6755 TCGv_i64 fp64 = tcg_temp_new_i64();
6757 gen_load_fpr32(fp32, fs);
6758 gen_helper_float_cvtd_w(fp64, fp32);
6759 tcg_temp_free_i32(fp32);
6760 gen_store_fpr64(ctx, fp64, fd);
6761 tcg_temp_free_i64(fp64);
6763 opn = "cvt.d.w";
6764 break;
6765 case FOP(32, 21):
6766 check_cp1_64bitmode(ctx);
6768 TCGv_i32 fp32 = tcg_temp_new_i32();
6769 TCGv_i64 fp64 = tcg_temp_new_i64();
6771 gen_load_fpr64(ctx, fp64, fs);
6772 gen_helper_float_cvts_l(fp32, fp64);
6773 tcg_temp_free_i64(fp64);
6774 gen_store_fpr32(fp32, fd);
6775 tcg_temp_free_i32(fp32);
6777 opn = "cvt.s.l";
6778 break;
6779 case FOP(33, 21):
6780 check_cp1_64bitmode(ctx);
6782 TCGv_i64 fp0 = tcg_temp_new_i64();
6784 gen_load_fpr64(ctx, fp0, fs);
6785 gen_helper_float_cvtd_l(fp0, fp0);
6786 gen_store_fpr64(ctx, fp0, fd);
6787 tcg_temp_free_i64(fp0);
6789 opn = "cvt.d.l";
6790 break;
6791 case FOP(38, 20):
6792 check_cp1_64bitmode(ctx);
6794 TCGv_i64 fp0 = tcg_temp_new_i64();
6796 gen_load_fpr64(ctx, fp0, fs);
6797 gen_helper_float_cvtps_pw(fp0, fp0);
6798 gen_store_fpr64(ctx, fp0, fd);
6799 tcg_temp_free_i64(fp0);
6801 opn = "cvt.ps.pw";
6802 break;
6803 case FOP(0, 22):
6804 check_cp1_64bitmode(ctx);
6806 TCGv_i64 fp0 = tcg_temp_new_i64();
6807 TCGv_i64 fp1 = tcg_temp_new_i64();
6809 gen_load_fpr64(ctx, fp0, fs);
6810 gen_load_fpr64(ctx, fp1, ft);
6811 gen_helper_float_add_ps(fp0, fp0, fp1);
6812 tcg_temp_free_i64(fp1);
6813 gen_store_fpr64(ctx, fp0, fd);
6814 tcg_temp_free_i64(fp0);
6816 opn = "add.ps";
6817 break;
6818 case FOP(1, 22):
6819 check_cp1_64bitmode(ctx);
6821 TCGv_i64 fp0 = tcg_temp_new_i64();
6822 TCGv_i64 fp1 = tcg_temp_new_i64();
6824 gen_load_fpr64(ctx, fp0, fs);
6825 gen_load_fpr64(ctx, fp1, ft);
6826 gen_helper_float_sub_ps(fp0, fp0, fp1);
6827 tcg_temp_free_i64(fp1);
6828 gen_store_fpr64(ctx, fp0, fd);
6829 tcg_temp_free_i64(fp0);
6831 opn = "sub.ps";
6832 break;
6833 case FOP(2, 22):
6834 check_cp1_64bitmode(ctx);
6836 TCGv_i64 fp0 = tcg_temp_new_i64();
6837 TCGv_i64 fp1 = tcg_temp_new_i64();
6839 gen_load_fpr64(ctx, fp0, fs);
6840 gen_load_fpr64(ctx, fp1, ft);
6841 gen_helper_float_mul_ps(fp0, fp0, fp1);
6842 tcg_temp_free_i64(fp1);
6843 gen_store_fpr64(ctx, fp0, fd);
6844 tcg_temp_free_i64(fp0);
6846 opn = "mul.ps";
6847 break;
6848 case FOP(5, 22):
6849 check_cp1_64bitmode(ctx);
6851 TCGv_i64 fp0 = tcg_temp_new_i64();
6853 gen_load_fpr64(ctx, fp0, fs);
6854 gen_helper_float_abs_ps(fp0, fp0);
6855 gen_store_fpr64(ctx, fp0, fd);
6856 tcg_temp_free_i64(fp0);
6858 opn = "abs.ps";
6859 break;
6860 case FOP(6, 22):
6861 check_cp1_64bitmode(ctx);
6863 TCGv_i64 fp0 = tcg_temp_new_i64();
6865 gen_load_fpr64(ctx, fp0, fs);
6866 gen_store_fpr64(ctx, fp0, fd);
6867 tcg_temp_free_i64(fp0);
6869 opn = "mov.ps";
6870 break;
6871 case FOP(7, 22):
6872 check_cp1_64bitmode(ctx);
6874 TCGv_i64 fp0 = tcg_temp_new_i64();
6876 gen_load_fpr64(ctx, fp0, fs);
6877 gen_helper_float_chs_ps(fp0, fp0);
6878 gen_store_fpr64(ctx, fp0, fd);
6879 tcg_temp_free_i64(fp0);
6881 opn = "neg.ps";
6882 break;
6883 case FOP(17, 22):
6884 check_cp1_64bitmode(ctx);
6885 gen_movcf_ps(fs, fd, (ft >> 2) & 0x7, ft & 0x1);
6886 opn = "movcf.ps";
6887 break;
6888 case FOP(18, 22):
6889 check_cp1_64bitmode(ctx);
6891 int l1 = gen_new_label();
6892 TCGv_i64 fp0;
6894 if (ft != 0)
6895 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[ft], 0, l1);
6896 fp0 = tcg_temp_new_i64();
6897 gen_load_fpr64(ctx, fp0, fs);
6898 gen_store_fpr64(ctx, fp0, fd);
6899 tcg_temp_free_i64(fp0);
6900 gen_set_label(l1);
6902 opn = "movz.ps";
6903 break;
6904 case FOP(19, 22):
6905 check_cp1_64bitmode(ctx);
6907 int l1 = gen_new_label();
6908 TCGv_i64 fp0;
6910 if (ft != 0) {
6911 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[ft], 0, l1);
6912 fp0 = tcg_temp_new_i64();
6913 gen_load_fpr64(ctx, fp0, fs);
6914 gen_store_fpr64(ctx, fp0, fd);
6915 tcg_temp_free_i64(fp0);
6916 gen_set_label(l1);
6919 opn = "movn.ps";
6920 break;
6921 case FOP(24, 22):
6922 check_cp1_64bitmode(ctx);
6924 TCGv_i64 fp0 = tcg_temp_new_i64();
6925 TCGv_i64 fp1 = tcg_temp_new_i64();
6927 gen_load_fpr64(ctx, fp0, ft);
6928 gen_load_fpr64(ctx, fp1, fs);
6929 gen_helper_float_addr_ps(fp0, fp0, fp1);
6930 tcg_temp_free_i64(fp1);
6931 gen_store_fpr64(ctx, fp0, fd);
6932 tcg_temp_free_i64(fp0);
6934 opn = "addr.ps";
6935 break;
6936 case FOP(26, 22):
6937 check_cp1_64bitmode(ctx);
6939 TCGv_i64 fp0 = tcg_temp_new_i64();
6940 TCGv_i64 fp1 = tcg_temp_new_i64();
6942 gen_load_fpr64(ctx, fp0, ft);
6943 gen_load_fpr64(ctx, fp1, fs);
6944 gen_helper_float_mulr_ps(fp0, fp0, fp1);
6945 tcg_temp_free_i64(fp1);
6946 gen_store_fpr64(ctx, fp0, fd);
6947 tcg_temp_free_i64(fp0);
6949 opn = "mulr.ps";
6950 break;
6951 case FOP(28, 22):
6952 check_cp1_64bitmode(ctx);
6954 TCGv_i64 fp0 = tcg_temp_new_i64();
6955 TCGv_i64 fp1 = tcg_temp_new_i64();
6957 gen_load_fpr64(ctx, fp0, fs);
6958 gen_load_fpr64(ctx, fp1, fd);
6959 gen_helper_float_recip2_ps(fp0, fp0, fp1);
6960 tcg_temp_free_i64(fp1);
6961 gen_store_fpr64(ctx, fp0, fd);
6962 tcg_temp_free_i64(fp0);
6964 opn = "recip2.ps";
6965 break;
6966 case FOP(29, 22):
6967 check_cp1_64bitmode(ctx);
6969 TCGv_i64 fp0 = tcg_temp_new_i64();
6971 gen_load_fpr64(ctx, fp0, fs);
6972 gen_helper_float_recip1_ps(fp0, fp0);
6973 gen_store_fpr64(ctx, fp0, fd);
6974 tcg_temp_free_i64(fp0);
6976 opn = "recip1.ps";
6977 break;
6978 case FOP(30, 22):
6979 check_cp1_64bitmode(ctx);
6981 TCGv_i64 fp0 = tcg_temp_new_i64();
6983 gen_load_fpr64(ctx, fp0, fs);
6984 gen_helper_float_rsqrt1_ps(fp0, fp0);
6985 gen_store_fpr64(ctx, fp0, fd);
6986 tcg_temp_free_i64(fp0);
6988 opn = "rsqrt1.ps";
6989 break;
6990 case FOP(31, 22):
6991 check_cp1_64bitmode(ctx);
6993 TCGv_i64 fp0 = tcg_temp_new_i64();
6994 TCGv_i64 fp1 = tcg_temp_new_i64();
6996 gen_load_fpr64(ctx, fp0, fs);
6997 gen_load_fpr64(ctx, fp1, ft);
6998 gen_helper_float_rsqrt2_ps(fp0, fp0, fp1);
6999 tcg_temp_free_i64(fp1);
7000 gen_store_fpr64(ctx, fp0, fd);
7001 tcg_temp_free_i64(fp0);
7003 opn = "rsqrt2.ps";
7004 break;
7005 case FOP(32, 22):
7006 check_cp1_64bitmode(ctx);
7008 TCGv_i32 fp0 = tcg_temp_new_i32();
7010 gen_load_fpr32h(fp0, fs);
7011 gen_helper_float_cvts_pu(fp0, fp0);
7012 gen_store_fpr32(fp0, fd);
7013 tcg_temp_free_i32(fp0);
7015 opn = "cvt.s.pu";
7016 break;
7017 case FOP(36, 22):
7018 check_cp1_64bitmode(ctx);
7020 TCGv_i64 fp0 = tcg_temp_new_i64();
7022 gen_load_fpr64(ctx, fp0, fs);
7023 gen_helper_float_cvtpw_ps(fp0, fp0);
7024 gen_store_fpr64(ctx, fp0, fd);
7025 tcg_temp_free_i64(fp0);
7027 opn = "cvt.pw.ps";
7028 break;
7029 case FOP(40, 22):
7030 check_cp1_64bitmode(ctx);
7032 TCGv_i32 fp0 = tcg_temp_new_i32();
7034 gen_load_fpr32(fp0, fs);
7035 gen_helper_float_cvts_pl(fp0, fp0);
7036 gen_store_fpr32(fp0, fd);
7037 tcg_temp_free_i32(fp0);
7039 opn = "cvt.s.pl";
7040 break;
7041 case FOP(44, 22):
7042 check_cp1_64bitmode(ctx);
7044 TCGv_i32 fp0 = tcg_temp_new_i32();
7045 TCGv_i32 fp1 = tcg_temp_new_i32();
7047 gen_load_fpr32(fp0, fs);
7048 gen_load_fpr32(fp1, ft);
7049 gen_store_fpr32h(fp0, fd);
7050 gen_store_fpr32(fp1, fd);
7051 tcg_temp_free_i32(fp0);
7052 tcg_temp_free_i32(fp1);
7054 opn = "pll.ps";
7055 break;
7056 case FOP(45, 22):
7057 check_cp1_64bitmode(ctx);
7059 TCGv_i32 fp0 = tcg_temp_new_i32();
7060 TCGv_i32 fp1 = tcg_temp_new_i32();
7062 gen_load_fpr32(fp0, fs);
7063 gen_load_fpr32h(fp1, ft);
7064 gen_store_fpr32(fp1, fd);
7065 gen_store_fpr32h(fp0, fd);
7066 tcg_temp_free_i32(fp0);
7067 tcg_temp_free_i32(fp1);
7069 opn = "plu.ps";
7070 break;
7071 case FOP(46, 22):
7072 check_cp1_64bitmode(ctx);
7074 TCGv_i32 fp0 = tcg_temp_new_i32();
7075 TCGv_i32 fp1 = tcg_temp_new_i32();
7077 gen_load_fpr32h(fp0, fs);
7078 gen_load_fpr32(fp1, ft);
7079 gen_store_fpr32(fp1, fd);
7080 gen_store_fpr32h(fp0, fd);
7081 tcg_temp_free_i32(fp0);
7082 tcg_temp_free_i32(fp1);
7084 opn = "pul.ps";
7085 break;
7086 case FOP(47, 22):
7087 check_cp1_64bitmode(ctx);
7089 TCGv_i32 fp0 = tcg_temp_new_i32();
7090 TCGv_i32 fp1 = tcg_temp_new_i32();
7092 gen_load_fpr32h(fp0, fs);
7093 gen_load_fpr32h(fp1, ft);
7094 gen_store_fpr32(fp1, fd);
7095 gen_store_fpr32h(fp0, fd);
7096 tcg_temp_free_i32(fp0);
7097 tcg_temp_free_i32(fp1);
7099 opn = "puu.ps";
7100 break;
7101 case FOP(48, 22):
7102 case FOP(49, 22):
7103 case FOP(50, 22):
7104 case FOP(51, 22):
7105 case FOP(52, 22):
7106 case FOP(53, 22):
7107 case FOP(54, 22):
7108 case FOP(55, 22):
7109 case FOP(56, 22):
7110 case FOP(57, 22):
7111 case FOP(58, 22):
7112 case FOP(59, 22):
7113 case FOP(60, 22):
7114 case FOP(61, 22):
7115 case FOP(62, 22):
7116 case FOP(63, 22):
7117 check_cp1_64bitmode(ctx);
7119 TCGv_i64 fp0 = tcg_temp_new_i64();
7120 TCGv_i64 fp1 = tcg_temp_new_i64();
7122 gen_load_fpr64(ctx, fp0, fs);
7123 gen_load_fpr64(ctx, fp1, ft);
7124 if (ctx->opcode & (1 << 6)) {
7125 gen_cmpabs_ps(func-48, fp0, fp1, cc);
7126 opn = condnames_abs[func-48];
7127 } else {
7128 gen_cmp_ps(func-48, fp0, fp1, cc);
7129 opn = condnames[func-48];
7131 tcg_temp_free_i64(fp0);
7132 tcg_temp_free_i64(fp1);
7134 break;
7135 default:
7136 MIPS_INVAL(opn);
7137 generate_exception (ctx, EXCP_RI);
7138 return;
7140 switch (optype) {
7141 case BINOP:
7142 MIPS_DEBUG("%s %s, %s, %s", opn, fregnames[fd], fregnames[fs], fregnames[ft]);
7143 break;
7144 case CMPOP:
7145 MIPS_DEBUG("%s %s,%s", opn, fregnames[fs], fregnames[ft]);
7146 break;
7147 default:
7148 MIPS_DEBUG("%s %s,%s", opn, fregnames[fd], fregnames[fs]);
7149 break;
7153 /* Coprocessor 3 (FPU) */
7154 static void gen_flt3_ldst (DisasContext *ctx, uint32_t opc,
7155 int fd, int fs, int base, int index)
7157 const char *opn = "extended float load/store";
7158 int store = 0;
7159 TCGv t0 = tcg_temp_new();
7161 if (base == 0) {
7162 gen_load_gpr(t0, index);
7163 } else if (index == 0) {
7164 gen_load_gpr(t0, base);
7165 } else {
7166 gen_load_gpr(t0, index);
7167 gen_op_addr_add(ctx, t0, cpu_gpr[base], t0);
7169 /* Don't do NOP if destination is zero: we must perform the actual
7170 memory access. */
7171 save_cpu_state(ctx, 0);
7172 switch (opc) {
7173 case OPC_LWXC1:
7174 check_cop1x(ctx);
7176 TCGv_i32 fp0 = tcg_temp_new_i32();
7178 tcg_gen_qemu_ld32s(t0, t0, ctx->mem_idx);
7179 tcg_gen_trunc_tl_i32(fp0, t0);
7180 gen_store_fpr32(fp0, fd);
7181 tcg_temp_free_i32(fp0);
7183 opn = "lwxc1";
7184 break;
7185 case OPC_LDXC1:
7186 check_cop1x(ctx);
7187 check_cp1_registers(ctx, fd);
7189 TCGv_i64 fp0 = tcg_temp_new_i64();
7191 tcg_gen_qemu_ld64(fp0, t0, ctx->mem_idx);
7192 gen_store_fpr64(ctx, fp0, fd);
7193 tcg_temp_free_i64(fp0);
7195 opn = "ldxc1";
7196 break;
7197 case OPC_LUXC1:
7198 check_cp1_64bitmode(ctx);
7199 tcg_gen_andi_tl(t0, t0, ~0x7);
7201 TCGv_i64 fp0 = tcg_temp_new_i64();
7203 tcg_gen_qemu_ld64(fp0, t0, ctx->mem_idx);
7204 gen_store_fpr64(ctx, fp0, fd);
7205 tcg_temp_free_i64(fp0);
7207 opn = "luxc1";
7208 break;
7209 case OPC_SWXC1:
7210 check_cop1x(ctx);
7212 TCGv_i32 fp0 = tcg_temp_new_i32();
7213 TCGv t1 = tcg_temp_new();
7215 gen_load_fpr32(fp0, fs);
7216 tcg_gen_extu_i32_tl(t1, fp0);
7217 tcg_gen_qemu_st32(t1, t0, ctx->mem_idx);
7218 tcg_temp_free_i32(fp0);
7219 tcg_temp_free(t1);
7221 opn = "swxc1";
7222 store = 1;
7223 break;
7224 case OPC_SDXC1:
7225 check_cop1x(ctx);
7226 check_cp1_registers(ctx, fs);
7228 TCGv_i64 fp0 = tcg_temp_new_i64();
7230 gen_load_fpr64(ctx, fp0, fs);
7231 tcg_gen_qemu_st64(fp0, t0, ctx->mem_idx);
7232 tcg_temp_free_i64(fp0);
7234 opn = "sdxc1";
7235 store = 1;
7236 break;
7237 case OPC_SUXC1:
7238 check_cp1_64bitmode(ctx);
7239 tcg_gen_andi_tl(t0, t0, ~0x7);
7241 TCGv_i64 fp0 = tcg_temp_new_i64();
7243 gen_load_fpr64(ctx, fp0, fs);
7244 tcg_gen_qemu_st64(fp0, t0, ctx->mem_idx);
7245 tcg_temp_free_i64(fp0);
7247 opn = "suxc1";
7248 store = 1;
7249 break;
7251 tcg_temp_free(t0);
7252 MIPS_DEBUG("%s %s, %s(%s)", opn, fregnames[store ? fs : fd],
7253 regnames[index], regnames[base]);
7256 static void gen_flt3_arith (DisasContext *ctx, uint32_t opc,
7257 int fd, int fr, int fs, int ft)
7259 const char *opn = "flt3_arith";
7261 switch (opc) {
7262 case OPC_ALNV_PS:
7263 check_cp1_64bitmode(ctx);
7265 TCGv t0 = tcg_temp_local_new();
7266 TCGv_i32 fp = tcg_temp_new_i32();
7267 TCGv_i32 fph = tcg_temp_new_i32();
7268 int l1 = gen_new_label();
7269 int l2 = gen_new_label();
7271 gen_load_gpr(t0, fr);
7272 tcg_gen_andi_tl(t0, t0, 0x7);
7274 tcg_gen_brcondi_tl(TCG_COND_NE, t0, 0, l1);
7275 gen_load_fpr32(fp, fs);
7276 gen_load_fpr32h(fph, fs);
7277 gen_store_fpr32(fp, fd);
7278 gen_store_fpr32h(fph, fd);
7279 tcg_gen_br(l2);
7280 gen_set_label(l1);
7281 tcg_gen_brcondi_tl(TCG_COND_NE, t0, 4, l2);
7282 tcg_temp_free(t0);
7283 #ifdef TARGET_WORDS_BIGENDIAN
7284 gen_load_fpr32(fp, fs);
7285 gen_load_fpr32h(fph, ft);
7286 gen_store_fpr32h(fp, fd);
7287 gen_store_fpr32(fph, fd);
7288 #else
7289 gen_load_fpr32h(fph, fs);
7290 gen_load_fpr32(fp, ft);
7291 gen_store_fpr32(fph, fd);
7292 gen_store_fpr32h(fp, fd);
7293 #endif
7294 gen_set_label(l2);
7295 tcg_temp_free_i32(fp);
7296 tcg_temp_free_i32(fph);
7298 opn = "alnv.ps";
7299 break;
7300 case OPC_MADD_S:
7301 check_cop1x(ctx);
7303 TCGv_i32 fp0 = tcg_temp_new_i32();
7304 TCGv_i32 fp1 = tcg_temp_new_i32();
7305 TCGv_i32 fp2 = tcg_temp_new_i32();
7307 gen_load_fpr32(fp0, fs);
7308 gen_load_fpr32(fp1, ft);
7309 gen_load_fpr32(fp2, fr);
7310 gen_helper_float_muladd_s(fp2, fp0, fp1, fp2);
7311 tcg_temp_free_i32(fp0);
7312 tcg_temp_free_i32(fp1);
7313 gen_store_fpr32(fp2, fd);
7314 tcg_temp_free_i32(fp2);
7316 opn = "madd.s";
7317 break;
7318 case OPC_MADD_D:
7319 check_cop1x(ctx);
7320 check_cp1_registers(ctx, fd | fs | ft | fr);
7322 TCGv_i64 fp0 = tcg_temp_new_i64();
7323 TCGv_i64 fp1 = tcg_temp_new_i64();
7324 TCGv_i64 fp2 = tcg_temp_new_i64();
7326 gen_load_fpr64(ctx, fp0, fs);
7327 gen_load_fpr64(ctx, fp1, ft);
7328 gen_load_fpr64(ctx, fp2, fr);
7329 gen_helper_float_muladd_d(fp2, fp0, fp1, fp2);
7330 tcg_temp_free_i64(fp0);
7331 tcg_temp_free_i64(fp1);
7332 gen_store_fpr64(ctx, fp2, fd);
7333 tcg_temp_free_i64(fp2);
7335 opn = "madd.d";
7336 break;
7337 case OPC_MADD_PS:
7338 check_cp1_64bitmode(ctx);
7340 TCGv_i64 fp0 = tcg_temp_new_i64();
7341 TCGv_i64 fp1 = tcg_temp_new_i64();
7342 TCGv_i64 fp2 = tcg_temp_new_i64();
7344 gen_load_fpr64(ctx, fp0, fs);
7345 gen_load_fpr64(ctx, fp1, ft);
7346 gen_load_fpr64(ctx, fp2, fr);
7347 gen_helper_float_muladd_ps(fp2, fp0, fp1, fp2);
7348 tcg_temp_free_i64(fp0);
7349 tcg_temp_free_i64(fp1);
7350 gen_store_fpr64(ctx, fp2, fd);
7351 tcg_temp_free_i64(fp2);
7353 opn = "madd.ps";
7354 break;
7355 case OPC_MSUB_S:
7356 check_cop1x(ctx);
7358 TCGv_i32 fp0 = tcg_temp_new_i32();
7359 TCGv_i32 fp1 = tcg_temp_new_i32();
7360 TCGv_i32 fp2 = tcg_temp_new_i32();
7362 gen_load_fpr32(fp0, fs);
7363 gen_load_fpr32(fp1, ft);
7364 gen_load_fpr32(fp2, fr);
7365 gen_helper_float_mulsub_s(fp2, fp0, fp1, fp2);
7366 tcg_temp_free_i32(fp0);
7367 tcg_temp_free_i32(fp1);
7368 gen_store_fpr32(fp2, fd);
7369 tcg_temp_free_i32(fp2);
7371 opn = "msub.s";
7372 break;
7373 case OPC_MSUB_D:
7374 check_cop1x(ctx);
7375 check_cp1_registers(ctx, fd | fs | ft | fr);
7377 TCGv_i64 fp0 = tcg_temp_new_i64();
7378 TCGv_i64 fp1 = tcg_temp_new_i64();
7379 TCGv_i64 fp2 = tcg_temp_new_i64();
7381 gen_load_fpr64(ctx, fp0, fs);
7382 gen_load_fpr64(ctx, fp1, ft);
7383 gen_load_fpr64(ctx, fp2, fr);
7384 gen_helper_float_mulsub_d(fp2, fp0, fp1, fp2);
7385 tcg_temp_free_i64(fp0);
7386 tcg_temp_free_i64(fp1);
7387 gen_store_fpr64(ctx, fp2, fd);
7388 tcg_temp_free_i64(fp2);
7390 opn = "msub.d";
7391 break;
7392 case OPC_MSUB_PS:
7393 check_cp1_64bitmode(ctx);
7395 TCGv_i64 fp0 = tcg_temp_new_i64();
7396 TCGv_i64 fp1 = tcg_temp_new_i64();
7397 TCGv_i64 fp2 = tcg_temp_new_i64();
7399 gen_load_fpr64(ctx, fp0, fs);
7400 gen_load_fpr64(ctx, fp1, ft);
7401 gen_load_fpr64(ctx, fp2, fr);
7402 gen_helper_float_mulsub_ps(fp2, fp0, fp1, fp2);
7403 tcg_temp_free_i64(fp0);
7404 tcg_temp_free_i64(fp1);
7405 gen_store_fpr64(ctx, fp2, fd);
7406 tcg_temp_free_i64(fp2);
7408 opn = "msub.ps";
7409 break;
7410 case OPC_NMADD_S:
7411 check_cop1x(ctx);
7413 TCGv_i32 fp0 = tcg_temp_new_i32();
7414 TCGv_i32 fp1 = tcg_temp_new_i32();
7415 TCGv_i32 fp2 = tcg_temp_new_i32();
7417 gen_load_fpr32(fp0, fs);
7418 gen_load_fpr32(fp1, ft);
7419 gen_load_fpr32(fp2, fr);
7420 gen_helper_float_nmuladd_s(fp2, fp0, fp1, fp2);
7421 tcg_temp_free_i32(fp0);
7422 tcg_temp_free_i32(fp1);
7423 gen_store_fpr32(fp2, fd);
7424 tcg_temp_free_i32(fp2);
7426 opn = "nmadd.s";
7427 break;
7428 case OPC_NMADD_D:
7429 check_cop1x(ctx);
7430 check_cp1_registers(ctx, fd | fs | ft | fr);
7432 TCGv_i64 fp0 = tcg_temp_new_i64();
7433 TCGv_i64 fp1 = tcg_temp_new_i64();
7434 TCGv_i64 fp2 = tcg_temp_new_i64();
7436 gen_load_fpr64(ctx, fp0, fs);
7437 gen_load_fpr64(ctx, fp1, ft);
7438 gen_load_fpr64(ctx, fp2, fr);
7439 gen_helper_float_nmuladd_d(fp2, fp0, fp1, fp2);
7440 tcg_temp_free_i64(fp0);
7441 tcg_temp_free_i64(fp1);
7442 gen_store_fpr64(ctx, fp2, fd);
7443 tcg_temp_free_i64(fp2);
7445 opn = "nmadd.d";
7446 break;
7447 case OPC_NMADD_PS:
7448 check_cp1_64bitmode(ctx);
7450 TCGv_i64 fp0 = tcg_temp_new_i64();
7451 TCGv_i64 fp1 = tcg_temp_new_i64();
7452 TCGv_i64 fp2 = tcg_temp_new_i64();
7454 gen_load_fpr64(ctx, fp0, fs);
7455 gen_load_fpr64(ctx, fp1, ft);
7456 gen_load_fpr64(ctx, fp2, fr);
7457 gen_helper_float_nmuladd_ps(fp2, fp0, fp1, fp2);
7458 tcg_temp_free_i64(fp0);
7459 tcg_temp_free_i64(fp1);
7460 gen_store_fpr64(ctx, fp2, fd);
7461 tcg_temp_free_i64(fp2);
7463 opn = "nmadd.ps";
7464 break;
7465 case OPC_NMSUB_S:
7466 check_cop1x(ctx);
7468 TCGv_i32 fp0 = tcg_temp_new_i32();
7469 TCGv_i32 fp1 = tcg_temp_new_i32();
7470 TCGv_i32 fp2 = tcg_temp_new_i32();
7472 gen_load_fpr32(fp0, fs);
7473 gen_load_fpr32(fp1, ft);
7474 gen_load_fpr32(fp2, fr);
7475 gen_helper_float_nmulsub_s(fp2, fp0, fp1, fp2);
7476 tcg_temp_free_i32(fp0);
7477 tcg_temp_free_i32(fp1);
7478 gen_store_fpr32(fp2, fd);
7479 tcg_temp_free_i32(fp2);
7481 opn = "nmsub.s";
7482 break;
7483 case OPC_NMSUB_D:
7484 check_cop1x(ctx);
7485 check_cp1_registers(ctx, fd | fs | ft | fr);
7487 TCGv_i64 fp0 = tcg_temp_new_i64();
7488 TCGv_i64 fp1 = tcg_temp_new_i64();
7489 TCGv_i64 fp2 = tcg_temp_new_i64();
7491 gen_load_fpr64(ctx, fp0, fs);
7492 gen_load_fpr64(ctx, fp1, ft);
7493 gen_load_fpr64(ctx, fp2, fr);
7494 gen_helper_float_nmulsub_d(fp2, fp0, fp1, fp2);
7495 tcg_temp_free_i64(fp0);
7496 tcg_temp_free_i64(fp1);
7497 gen_store_fpr64(ctx, fp2, fd);
7498 tcg_temp_free_i64(fp2);
7500 opn = "nmsub.d";
7501 break;
7502 case OPC_NMSUB_PS:
7503 check_cp1_64bitmode(ctx);
7505 TCGv_i64 fp0 = tcg_temp_new_i64();
7506 TCGv_i64 fp1 = tcg_temp_new_i64();
7507 TCGv_i64 fp2 = tcg_temp_new_i64();
7509 gen_load_fpr64(ctx, fp0, fs);
7510 gen_load_fpr64(ctx, fp1, ft);
7511 gen_load_fpr64(ctx, fp2, fr);
7512 gen_helper_float_nmulsub_ps(fp2, fp0, fp1, fp2);
7513 tcg_temp_free_i64(fp0);
7514 tcg_temp_free_i64(fp1);
7515 gen_store_fpr64(ctx, fp2, fd);
7516 tcg_temp_free_i64(fp2);
7518 opn = "nmsub.ps";
7519 break;
7520 default:
7521 MIPS_INVAL(opn);
7522 generate_exception (ctx, EXCP_RI);
7523 return;
7525 MIPS_DEBUG("%s %s, %s, %s, %s", opn, fregnames[fd], fregnames[fr],
7526 fregnames[fs], fregnames[ft]);
7529 static void handle_delay_slot (CPUState *env, DisasContext *ctx,
7530 int insn_bytes)
7532 if (ctx->hflags & MIPS_HFLAG_BMASK) {
7533 int proc_hflags = ctx->hflags & MIPS_HFLAG_BMASK;
7534 /* Branches completion */
7535 ctx->hflags &= ~MIPS_HFLAG_BMASK;
7536 ctx->bstate = BS_BRANCH;
7537 save_cpu_state(ctx, 0);
7538 /* FIXME: Need to clear can_do_io. */
7539 switch (proc_hflags & MIPS_HFLAG_BMASK_BASE) {
7540 case MIPS_HFLAG_B:
7541 /* unconditional branch */
7542 MIPS_DEBUG("unconditional branch");
7543 if (proc_hflags & MIPS_HFLAG_BX) {
7544 tcg_gen_xori_i32(hflags, hflags, MIPS_HFLAG_M16);
7546 gen_goto_tb(ctx, 0, ctx->btarget);
7547 break;
7548 case MIPS_HFLAG_BL:
7549 /* blikely taken case */
7550 MIPS_DEBUG("blikely branch taken");
7551 gen_goto_tb(ctx, 0, ctx->btarget);
7552 break;
7553 case MIPS_HFLAG_BC:
7554 /* Conditional branch */
7555 MIPS_DEBUG("conditional branch");
7557 int l1 = gen_new_label();
7559 tcg_gen_brcondi_tl(TCG_COND_NE, bcond, 0, l1);
7560 gen_goto_tb(ctx, 1, ctx->pc + insn_bytes);
7561 gen_set_label(l1);
7562 gen_goto_tb(ctx, 0, ctx->btarget);
7564 break;
7565 case MIPS_HFLAG_BR:
7566 /* unconditional branch to register */
7567 MIPS_DEBUG("branch to register");
7568 if (env->insn_flags & ASE_MIPS16) {
7569 TCGv t0 = tcg_temp_new();
7570 TCGv_i32 t1 = tcg_temp_new_i32();
7572 tcg_gen_andi_tl(t0, btarget, 0x1);
7573 tcg_gen_trunc_tl_i32(t1, t0);
7574 tcg_temp_free(t0);
7575 tcg_gen_andi_i32(hflags, hflags, ~(uint32_t)MIPS_HFLAG_M16);
7576 tcg_gen_shli_i32(t1, t1, MIPS_HFLAG_M16_SHIFT);
7577 tcg_gen_or_i32(hflags, hflags, t1);
7578 tcg_temp_free_i32(t1);
7580 tcg_gen_andi_tl(cpu_PC, btarget, ~(target_ulong)0x1);
7581 } else {
7582 tcg_gen_mov_tl(cpu_PC, btarget);
7584 if (ctx->singlestep_enabled) {
7585 save_cpu_state(ctx, 0);
7586 gen_helper_0i(raise_exception, EXCP_DEBUG);
7588 tcg_gen_exit_tb(0);
7589 break;
7590 default:
7591 MIPS_DEBUG("unknown branch");
7592 break;
7597 /* ISA extensions (ASEs) */
7598 /* MIPS16 extension to MIPS32 */
7600 /* MIPS16 major opcodes */
7601 enum {
7602 M16_OPC_ADDIUSP = 0x00,
7603 M16_OPC_ADDIUPC = 0x01,
7604 M16_OPC_B = 0x02,
7605 M16_OPC_JAL = 0x03,
7606 M16_OPC_BEQZ = 0x04,
7607 M16_OPC_BNEQZ = 0x05,
7608 M16_OPC_SHIFT = 0x06,
7609 M16_OPC_LD = 0x07,
7610 M16_OPC_RRIA = 0x08,
7611 M16_OPC_ADDIU8 = 0x09,
7612 M16_OPC_SLTI = 0x0a,
7613 M16_OPC_SLTIU = 0x0b,
7614 M16_OPC_I8 = 0x0c,
7615 M16_OPC_LI = 0x0d,
7616 M16_OPC_CMPI = 0x0e,
7617 M16_OPC_SD = 0x0f,
7618 M16_OPC_LB = 0x10,
7619 M16_OPC_LH = 0x11,
7620 M16_OPC_LWSP = 0x12,
7621 M16_OPC_LW = 0x13,
7622 M16_OPC_LBU = 0x14,
7623 M16_OPC_LHU = 0x15,
7624 M16_OPC_LWPC = 0x16,
7625 M16_OPC_LWU = 0x17,
7626 M16_OPC_SB = 0x18,
7627 M16_OPC_SH = 0x19,
7628 M16_OPC_SWSP = 0x1a,
7629 M16_OPC_SW = 0x1b,
7630 M16_OPC_RRR = 0x1c,
7631 M16_OPC_RR = 0x1d,
7632 M16_OPC_EXTEND = 0x1e,
7633 M16_OPC_I64 = 0x1f
7636 /* I8 funct field */
7637 enum {
7638 I8_BTEQZ = 0x0,
7639 I8_BTNEZ = 0x1,
7640 I8_SWRASP = 0x2,
7641 I8_ADJSP = 0x3,
7642 I8_SVRS = 0x4,
7643 I8_MOV32R = 0x5,
7644 I8_MOVR32 = 0x7
7647 /* RRR f field */
7648 enum {
7649 RRR_DADDU = 0x0,
7650 RRR_ADDU = 0x1,
7651 RRR_DSUBU = 0x2,
7652 RRR_SUBU = 0x3
7655 /* RR funct field */
7656 enum {
7657 RR_JR = 0x00,
7658 RR_SDBBP = 0x01,
7659 RR_SLT = 0x02,
7660 RR_SLTU = 0x03,
7661 RR_SLLV = 0x04,
7662 RR_BREAK = 0x05,
7663 RR_SRLV = 0x06,
7664 RR_SRAV = 0x07,
7665 RR_DSRL = 0x08,
7666 RR_CMP = 0x0a,
7667 RR_NEG = 0x0b,
7668 RR_AND = 0x0c,
7669 RR_OR = 0x0d,
7670 RR_XOR = 0x0e,
7671 RR_NOT = 0x0f,
7672 RR_MFHI = 0x10,
7673 RR_CNVT = 0x11,
7674 RR_MFLO = 0x12,
7675 RR_DSRA = 0x13,
7676 RR_DSLLV = 0x14,
7677 RR_DSRLV = 0x16,
7678 RR_DSRAV = 0x17,
7679 RR_MULT = 0x18,
7680 RR_MULTU = 0x19,
7681 RR_DIV = 0x1a,
7682 RR_DIVU = 0x1b,
7683 RR_DMULT = 0x1c,
7684 RR_DMULTU = 0x1d,
7685 RR_DDIV = 0x1e,
7686 RR_DDIVU = 0x1f
7689 /* I64 funct field */
7690 enum {
7691 I64_LDSP = 0x0,
7692 I64_SDSP = 0x1,
7693 I64_SDRASP = 0x2,
7694 I64_DADJSP = 0x3,
7695 I64_LDPC = 0x4,
7696 I64_DADDIU5 = 0x5,
7697 I64_DADDIUPC = 0x6,
7698 I64_DADDIUSP = 0x7
7701 /* RR ry field for CNVT */
7702 enum {
7703 RR_RY_CNVT_ZEB = 0x0,
7704 RR_RY_CNVT_ZEH = 0x1,
7705 RR_RY_CNVT_ZEW = 0x2,
7706 RR_RY_CNVT_SEB = 0x4,
7707 RR_RY_CNVT_SEH = 0x5,
7708 RR_RY_CNVT_SEW = 0x6,
7711 static int xlat (int r)
7713 static int map[] = { 16, 17, 2, 3, 4, 5, 6, 7 };
7715 return map[r];
7718 static void gen_mips16_save (DisasContext *ctx,
7719 int xsregs, int aregs,
7720 int do_ra, int do_s0, int do_s1,
7721 int framesize)
7723 TCGv t0 = tcg_temp_new();
7724 TCGv t1 = tcg_temp_new();
7725 int args, astatic;
7727 switch (aregs) {
7728 case 0:
7729 case 1:
7730 case 2:
7731 case 3:
7732 case 11:
7733 args = 0;
7734 break;
7735 case 4:
7736 case 5:
7737 case 6:
7738 case 7:
7739 args = 1;
7740 break;
7741 case 8:
7742 case 9:
7743 case 10:
7744 args = 2;
7745 break;
7746 case 12:
7747 case 13:
7748 args = 3;
7749 break;
7750 case 14:
7751 args = 4;
7752 break;
7753 default:
7754 generate_exception(ctx, EXCP_RI);
7755 return;
7758 switch (args) {
7759 case 4:
7760 gen_base_offset_addr(ctx, t0, 29, 12);
7761 gen_load_gpr(t1, 7);
7762 op_ldst_sw(t1, t0, ctx);
7763 /* Fall through */
7764 case 3:
7765 gen_base_offset_addr(ctx, t0, 29, 8);
7766 gen_load_gpr(t1, 6);
7767 op_ldst_sw(t1, t0, ctx);
7768 /* Fall through */
7769 case 2:
7770 gen_base_offset_addr(ctx, t0, 29, 4);
7771 gen_load_gpr(t1, 5);
7772 op_ldst_sw(t1, t0, ctx);
7773 /* Fall through */
7774 case 1:
7775 gen_base_offset_addr(ctx, t0, 29, 0);
7776 gen_load_gpr(t1, 4);
7777 op_ldst_sw(t1, t0, ctx);
7780 gen_load_gpr(t0, 29);
7782 #define DECR_AND_STORE(reg) do { \
7783 tcg_gen_subi_tl(t0, t0, 4); \
7784 gen_load_gpr(t1, reg); \
7785 op_ldst_sw(t1, t0, ctx); \
7786 } while (0)
7788 if (do_ra) {
7789 DECR_AND_STORE(31);
7792 switch (xsregs) {
7793 case 7:
7794 DECR_AND_STORE(30);
7795 /* Fall through */
7796 case 6:
7797 DECR_AND_STORE(23);
7798 /* Fall through */
7799 case 5:
7800 DECR_AND_STORE(22);
7801 /* Fall through */
7802 case 4:
7803 DECR_AND_STORE(21);
7804 /* Fall through */
7805 case 3:
7806 DECR_AND_STORE(20);
7807 /* Fall through */
7808 case 2:
7809 DECR_AND_STORE(19);
7810 /* Fall through */
7811 case 1:
7812 DECR_AND_STORE(18);
7815 if (do_s1) {
7816 DECR_AND_STORE(17);
7818 if (do_s0) {
7819 DECR_AND_STORE(16);
7822 switch (aregs) {
7823 case 0:
7824 case 4:
7825 case 8:
7826 case 12:
7827 case 14:
7828 astatic = 0;
7829 break;
7830 case 1:
7831 case 5:
7832 case 9:
7833 case 13:
7834 astatic = 1;
7835 break;
7836 case 2:
7837 case 6:
7838 case 10:
7839 astatic = 2;
7840 break;
7841 case 3:
7842 case 7:
7843 astatic = 3;
7844 break;
7845 case 11:
7846 astatic = 4;
7847 break;
7848 default:
7849 generate_exception(ctx, EXCP_RI);
7850 return;
7853 if (astatic > 0) {
7854 DECR_AND_STORE(7);
7855 if (astatic > 1) {
7856 DECR_AND_STORE(6);
7857 if (astatic > 2) {
7858 DECR_AND_STORE(5);
7859 if (astatic > 3) {
7860 DECR_AND_STORE(4);
7865 #undef DECR_AND_STORE
7867 tcg_gen_subi_tl(cpu_gpr[29], cpu_gpr[29], framesize);
7868 tcg_temp_free(t0);
7869 tcg_temp_free(t1);
7872 static void gen_mips16_restore (DisasContext *ctx,
7873 int xsregs, int aregs,
7874 int do_ra, int do_s0, int do_s1,
7875 int framesize)
7877 int astatic;
7878 TCGv t0 = tcg_temp_new();
7879 TCGv t1 = tcg_temp_new();
7881 tcg_gen_addi_tl(t0, cpu_gpr[29], framesize);
7883 #define DECR_AND_LOAD(reg) do { \
7884 tcg_gen_subi_tl(t0, t0, 4); \
7885 op_ldst_lw(t1, t0, ctx); \
7886 gen_store_gpr(t1, reg); \
7887 } while (0)
7889 if (do_ra) {
7890 DECR_AND_LOAD(31);
7893 switch (xsregs) {
7894 case 7:
7895 DECR_AND_LOAD(30);
7896 /* Fall through */
7897 case 6:
7898 DECR_AND_LOAD(23);
7899 /* Fall through */
7900 case 5:
7901 DECR_AND_LOAD(22);
7902 /* Fall through */
7903 case 4:
7904 DECR_AND_LOAD(21);
7905 /* Fall through */
7906 case 3:
7907 DECR_AND_LOAD(20);
7908 /* Fall through */
7909 case 2:
7910 DECR_AND_LOAD(19);
7911 /* Fall through */
7912 case 1:
7913 DECR_AND_LOAD(18);
7916 if (do_s1) {
7917 DECR_AND_LOAD(17);
7919 if (do_s0) {
7920 DECR_AND_LOAD(16);
7923 switch (aregs) {
7924 case 0:
7925 case 4:
7926 case 8:
7927 case 12:
7928 case 14:
7929 astatic = 0;
7930 break;
7931 case 1:
7932 case 5:
7933 case 9:
7934 case 13:
7935 astatic = 1;
7936 break;
7937 case 2:
7938 case 6:
7939 case 10:
7940 astatic = 2;
7941 break;
7942 case 3:
7943 case 7:
7944 astatic = 3;
7945 break;
7946 case 11:
7947 astatic = 4;
7948 break;
7949 default:
7950 generate_exception(ctx, EXCP_RI);
7951 return;
7954 if (astatic > 0) {
7955 DECR_AND_LOAD(7);
7956 if (astatic > 1) {
7957 DECR_AND_LOAD(6);
7958 if (astatic > 2) {
7959 DECR_AND_LOAD(5);
7960 if (astatic > 3) {
7961 DECR_AND_LOAD(4);
7966 #undef DECR_AND_LOAD
7968 tcg_gen_addi_tl(cpu_gpr[29], cpu_gpr[29], framesize);
7969 tcg_temp_free(t0);
7970 tcg_temp_free(t1);
7973 static void gen_addiupc (DisasContext *ctx, int rx, int imm,
7974 int is_64_bit, int extended)
7976 TCGv t0;
7978 if (extended && (ctx->hflags & MIPS_HFLAG_BMASK)) {
7979 generate_exception(ctx, EXCP_RI);
7980 return;
7983 t0 = tcg_temp_new();
7985 tcg_gen_movi_tl(t0, pc_relative_pc(ctx));
7986 tcg_gen_addi_tl(cpu_gpr[rx], t0, imm);
7987 if (!is_64_bit) {
7988 tcg_gen_ext32s_tl(cpu_gpr[rx], cpu_gpr[rx]);
7991 tcg_temp_free(t0);
7994 #if defined(TARGET_MIPS64)
7995 static void decode_i64_mips16 (CPUState *env, DisasContext *ctx,
7996 int ry, int funct, int16_t offset,
7997 int extended)
7999 switch (funct) {
8000 case I64_LDSP:
8001 check_mips_64(ctx);
8002 offset = extended ? offset : offset << 3;
8003 gen_ldst(ctx, OPC_LD, ry, 29, offset);
8004 break;
8005 case I64_SDSP:
8006 check_mips_64(ctx);
8007 offset = extended ? offset : offset << 3;
8008 gen_ldst(ctx, OPC_SD, ry, 29, offset);
8009 break;
8010 case I64_SDRASP:
8011 check_mips_64(ctx);
8012 offset = extended ? offset : (ctx->opcode & 0xff) << 3;
8013 gen_ldst(ctx, OPC_SD, 31, 29, offset);
8014 break;
8015 case I64_DADJSP:
8016 check_mips_64(ctx);
8017 offset = extended ? offset : ((int8_t)ctx->opcode) << 3;
8018 gen_arith_imm(env, ctx, OPC_DADDIU, 29, 29, offset);
8019 break;
8020 case I64_LDPC:
8021 if (extended && (ctx->hflags & MIPS_HFLAG_BMASK)) {
8022 generate_exception(ctx, EXCP_RI);
8023 } else {
8024 offset = extended ? offset : offset << 3;
8025 gen_ldst(ctx, OPC_LDPC, ry, 0, offset);
8027 break;
8028 case I64_DADDIU5:
8029 check_mips_64(ctx);
8030 offset = extended ? offset : ((int8_t)(offset << 3)) >> 3;
8031 gen_arith_imm(env, ctx, OPC_DADDIU, ry, ry, offset);
8032 break;
8033 case I64_DADDIUPC:
8034 check_mips_64(ctx);
8035 offset = extended ? offset : offset << 2;
8036 gen_addiupc(ctx, ry, offset, 1, extended);
8037 break;
8038 case I64_DADDIUSP:
8039 check_mips_64(ctx);
8040 offset = extended ? offset : offset << 2;
8041 gen_arith_imm(env, ctx, OPC_DADDIU, ry, 29, offset);
8042 break;
8045 #endif
8047 static int decode_extended_mips16_opc (CPUState *env, DisasContext *ctx,
8048 int *is_branch)
8050 int extend = lduw_code(ctx->pc + 2);
8051 int op, rx, ry, funct, sa;
8052 int16_t imm, offset;
8054 ctx->opcode = (ctx->opcode << 16) | extend;
8055 op = (ctx->opcode >> 11) & 0x1f;
8056 sa = (ctx->opcode >> 22) & 0x1f;
8057 funct = (ctx->opcode >> 8) & 0x7;
8058 rx = xlat((ctx->opcode >> 8) & 0x7);
8059 ry = xlat((ctx->opcode >> 5) & 0x7);
8060 offset = imm = (int16_t) (((ctx->opcode >> 16) & 0x1f) << 11
8061 | ((ctx->opcode >> 21) & 0x3f) << 5
8062 | (ctx->opcode & 0x1f));
8064 /* The extended opcodes cleverly reuse the opcodes from their 16-bit
8065 counterparts. */
8066 switch (op) {
8067 case M16_OPC_ADDIUSP:
8068 gen_arith_imm(env, ctx, OPC_ADDIU, rx, 29, imm);
8069 break;
8070 case M16_OPC_ADDIUPC:
8071 gen_addiupc(ctx, rx, imm, 0, 1);
8072 break;
8073 case M16_OPC_B:
8074 gen_compute_branch(ctx, OPC_BEQ, 4, 0, 0, offset << 1);
8075 /* No delay slot, so just process as a normal instruction */
8076 break;
8077 case M16_OPC_BEQZ:
8078 gen_compute_branch(ctx, OPC_BEQ, 4, rx, 0, offset << 1);
8079 /* No delay slot, so just process as a normal instruction */
8080 break;
8081 case M16_OPC_BNEQZ:
8082 gen_compute_branch(ctx, OPC_BNE, 4, rx, 0, offset << 1);
8083 /* No delay slot, so just process as a normal instruction */
8084 break;
8085 case M16_OPC_SHIFT:
8086 switch (ctx->opcode & 0x3) {
8087 case 0x0:
8088 gen_shift_imm(env, ctx, OPC_SLL, rx, ry, sa);
8089 break;
8090 case 0x1:
8091 #if defined(TARGET_MIPS64)
8092 check_mips_64(ctx);
8093 gen_shift_imm(env, ctx, OPC_DSLL, rx, ry, sa);
8094 #else
8095 generate_exception(ctx, EXCP_RI);
8096 #endif
8097 break;
8098 case 0x2:
8099 gen_shift_imm(env, ctx, OPC_SRL, rx, ry, sa);
8100 break;
8101 case 0x3:
8102 gen_shift_imm(env, ctx, OPC_SRA, rx, ry, sa);
8103 break;
8105 break;
8106 #if defined(TARGET_MIPS64)
8107 case M16_OPC_LD:
8108 check_mips_64(ctx);
8109 gen_ldst(ctx, OPC_LD, ry, rx, offset);
8110 break;
8111 #endif
8112 case M16_OPC_RRIA:
8113 imm = ctx->opcode & 0xf;
8114 imm = imm | ((ctx->opcode >> 20) & 0x7f) << 4;
8115 imm = imm | ((ctx->opcode >> 16) & 0xf) << 11;
8116 imm = (int16_t) (imm << 1) >> 1;
8117 if ((ctx->opcode >> 4) & 0x1) {
8118 #if defined(TARGET_MIPS64)
8119 check_mips_64(ctx);
8120 gen_arith_imm(env, ctx, OPC_DADDIU, ry, rx, imm);
8121 #else
8122 generate_exception(ctx, EXCP_RI);
8123 #endif
8124 } else {
8125 gen_arith_imm(env, ctx, OPC_ADDIU, ry, rx, imm);
8127 break;
8128 case M16_OPC_ADDIU8:
8129 gen_arith_imm(env, ctx, OPC_ADDIU, rx, rx, imm);
8130 break;
8131 case M16_OPC_SLTI:
8132 gen_slt_imm(env, OPC_SLTI, 24, rx, imm);
8133 break;
8134 case M16_OPC_SLTIU:
8135 gen_slt_imm(env, OPC_SLTIU, 24, rx, imm);
8136 break;
8137 case M16_OPC_I8:
8138 switch (funct) {
8139 case I8_BTEQZ:
8140 gen_compute_branch(ctx, OPC_BEQ, 4, 24, 0, offset << 1);
8141 break;
8142 case I8_BTNEZ:
8143 gen_compute_branch(ctx, OPC_BNE, 4, 24, 0, offset << 1);
8144 break;
8145 case I8_SWRASP:
8146 gen_ldst(ctx, OPC_SW, 31, 29, imm);
8147 break;
8148 case I8_ADJSP:
8149 gen_arith_imm(env, ctx, OPC_ADDIU, 29, 29, imm);
8150 break;
8151 case I8_SVRS:
8153 int xsregs = (ctx->opcode >> 24) & 0x7;
8154 int aregs = (ctx->opcode >> 16) & 0xf;
8155 int do_ra = (ctx->opcode >> 6) & 0x1;
8156 int do_s0 = (ctx->opcode >> 5) & 0x1;
8157 int do_s1 = (ctx->opcode >> 4) & 0x1;
8158 int framesize = (((ctx->opcode >> 20) & 0xf) << 4
8159 | (ctx->opcode & 0xf)) << 3;
8161 if (ctx->opcode & (1 << 7)) {
8162 gen_mips16_save(ctx, xsregs, aregs,
8163 do_ra, do_s0, do_s1,
8164 framesize);
8165 } else {
8166 gen_mips16_restore(ctx, xsregs, aregs,
8167 do_ra, do_s0, do_s1,
8168 framesize);
8171 break;
8172 default:
8173 generate_exception(ctx, EXCP_RI);
8174 break;
8176 break;
8177 case M16_OPC_LI:
8178 tcg_gen_movi_tl(cpu_gpr[rx], (uint16_t) imm);
8179 break;
8180 case M16_OPC_CMPI:
8181 tcg_gen_xori_tl(cpu_gpr[24], cpu_gpr[rx], (uint16_t) imm);
8182 break;
8183 #if defined(TARGET_MIPS64)
8184 case M16_OPC_SD:
8185 gen_ldst(ctx, OPC_SD, ry, rx, offset);
8186 break;
8187 #endif
8188 case M16_OPC_LB:
8189 gen_ldst(ctx, OPC_LB, ry, rx, offset);
8190 break;
8191 case M16_OPC_LH:
8192 gen_ldst(ctx, OPC_LH, ry, rx, offset);
8193 break;
8194 case M16_OPC_LWSP:
8195 gen_ldst(ctx, OPC_LW, rx, 29, offset);
8196 break;
8197 case M16_OPC_LW:
8198 gen_ldst(ctx, OPC_LW, ry, rx, offset);
8199 break;
8200 case M16_OPC_LBU:
8201 gen_ldst(ctx, OPC_LBU, ry, rx, offset);
8202 break;
8203 case M16_OPC_LHU:
8204 gen_ldst(ctx, OPC_LHU, ry, rx, offset);
8205 break;
8206 case M16_OPC_LWPC:
8207 gen_ldst(ctx, OPC_LWPC, rx, 0, offset);
8208 break;
8209 #if defined(TARGET_MIPS64)
8210 case M16_OPC_LWU:
8211 gen_ldst(ctx, OPC_LWU, ry, rx, offset);
8212 break;
8213 #endif
8214 case M16_OPC_SB:
8215 gen_ldst(ctx, OPC_SB, ry, rx, offset);
8216 break;
8217 case M16_OPC_SH:
8218 gen_ldst(ctx, OPC_SH, ry, rx, offset);
8219 break;
8220 case M16_OPC_SWSP:
8221 gen_ldst(ctx, OPC_SW, rx, 29, offset);
8222 break;
8223 case M16_OPC_SW:
8224 gen_ldst(ctx, OPC_SW, ry, rx, offset);
8225 break;
8226 #if defined(TARGET_MIPS64)
8227 case M16_OPC_I64:
8228 decode_i64_mips16(env, ctx, ry, funct, offset, 1);
8229 break;
8230 #endif
8231 default:
8232 generate_exception(ctx, EXCP_RI);
8233 break;
8236 return 4;
8239 static int decode_mips16_opc (CPUState *env, DisasContext *ctx,
8240 int *is_branch)
8242 int rx, ry;
8243 int sa;
8244 int op, cnvt_op, op1, offset;
8245 int funct;
8246 int n_bytes;
8248 op = (ctx->opcode >> 11) & 0x1f;
8249 sa = (ctx->opcode >> 2) & 0x7;
8250 sa = sa == 0 ? 8 : sa;
8251 rx = xlat((ctx->opcode >> 8) & 0x7);
8252 cnvt_op = (ctx->opcode >> 5) & 0x7;
8253 ry = xlat((ctx->opcode >> 5) & 0x7);
8254 op1 = offset = ctx->opcode & 0x1f;
8256 n_bytes = 2;
8258 switch (op) {
8259 case M16_OPC_ADDIUSP:
8261 int16_t imm = ((uint8_t) ctx->opcode) << 2;
8263 gen_arith_imm(env, ctx, OPC_ADDIU, rx, 29, imm);
8265 break;
8266 case M16_OPC_ADDIUPC:
8267 gen_addiupc(ctx, rx, ((uint8_t) ctx->opcode) << 2, 0, 0);
8268 break;
8269 case M16_OPC_B:
8270 offset = (ctx->opcode & 0x7ff) << 1;
8271 offset = (int16_t)(offset << 4) >> 4;
8272 gen_compute_branch(ctx, OPC_BEQ, 2, 0, 0, offset);
8273 /* No delay slot, so just process as a normal instruction */
8274 break;
8275 case M16_OPC_JAL:
8276 offset = lduw_code(ctx->pc + 2);
8277 offset = (((ctx->opcode & 0x1f) << 21)
8278 | ((ctx->opcode >> 5) & 0x1f) << 16
8279 | offset) << 2;
8280 op = ((ctx->opcode >> 10) & 0x1) ? OPC_JALX : OPC_JAL;
8281 gen_compute_branch(ctx, op, 4, rx, ry, offset);
8282 n_bytes = 4;
8283 *is_branch = 1;
8284 break;
8285 case M16_OPC_BEQZ:
8286 gen_compute_branch(ctx, OPC_BEQ, 2, rx, 0, ((int8_t)ctx->opcode) << 1);
8287 /* No delay slot, so just process as a normal instruction */
8288 break;
8289 case M16_OPC_BNEQZ:
8290 gen_compute_branch(ctx, OPC_BNE, 2, rx, 0, ((int8_t)ctx->opcode) << 1);
8291 /* No delay slot, so just process as a normal instruction */
8292 break;
8293 case M16_OPC_SHIFT:
8294 switch (ctx->opcode & 0x3) {
8295 case 0x0:
8296 gen_shift_imm(env, ctx, OPC_SLL, rx, ry, sa);
8297 break;
8298 case 0x1:
8299 #if defined(TARGET_MIPS64)
8300 check_mips_64(ctx);
8301 gen_shift_imm(env, ctx, OPC_DSLL, rx, ry, sa);
8302 #else
8303 generate_exception(ctx, EXCP_RI);
8304 #endif
8305 break;
8306 case 0x2:
8307 gen_shift_imm(env, ctx, OPC_SRL, rx, ry, sa);
8308 break;
8309 case 0x3:
8310 gen_shift_imm(env, ctx, OPC_SRA, rx, ry, sa);
8311 break;
8313 break;
8314 #if defined(TARGET_MIPS64)
8315 case M16_OPC_LD:
8316 check_mips_64(ctx);
8317 gen_ldst(ctx, OPC_LD, ry, rx, offset << 3);
8318 break;
8319 #endif
8320 case M16_OPC_RRIA:
8322 int16_t imm = (int8_t)((ctx->opcode & 0xf) << 4) >> 4;
8324 if ((ctx->opcode >> 4) & 1) {
8325 #if defined(TARGET_MIPS64)
8326 check_mips_64(ctx);
8327 gen_arith_imm(env, ctx, OPC_DADDIU, ry, rx, imm);
8328 #else
8329 generate_exception(ctx, EXCP_RI);
8330 #endif
8331 } else {
8332 gen_arith_imm(env, ctx, OPC_ADDIU, ry, rx, imm);
8335 break;
8336 case M16_OPC_ADDIU8:
8338 int16_t imm = (int8_t) ctx->opcode;
8340 gen_arith_imm(env, ctx, OPC_ADDIU, rx, rx, imm);
8342 break;
8343 case M16_OPC_SLTI:
8345 int16_t imm = (uint8_t) ctx->opcode;
8347 gen_slt_imm(env, OPC_SLTI, 24, rx, imm);
8349 break;
8350 case M16_OPC_SLTIU:
8352 int16_t imm = (uint8_t) ctx->opcode;
8354 gen_slt_imm(env, OPC_SLTIU, 24, rx, imm);
8356 break;
8357 case M16_OPC_I8:
8359 int reg32;
8361 funct = (ctx->opcode >> 8) & 0x7;
8362 switch (funct) {
8363 case I8_BTEQZ:
8364 gen_compute_branch(ctx, OPC_BEQ, 2, 24, 0,
8365 ((int8_t)ctx->opcode) << 1);
8366 break;
8367 case I8_BTNEZ:
8368 gen_compute_branch(ctx, OPC_BNE, 2, 24, 0,
8369 ((int8_t)ctx->opcode) << 1);
8370 break;
8371 case I8_SWRASP:
8372 gen_ldst(ctx, OPC_SW, 31, 29, (ctx->opcode & 0xff) << 2);
8373 break;
8374 case I8_ADJSP:
8375 gen_arith_imm(env, ctx, OPC_ADDIU, 29, 29,
8376 ((int8_t)ctx->opcode) << 3);
8377 break;
8378 case I8_SVRS:
8380 int do_ra = ctx->opcode & (1 << 6);
8381 int do_s0 = ctx->opcode & (1 << 5);
8382 int do_s1 = ctx->opcode & (1 << 4);
8383 int framesize = ctx->opcode & 0xf;
8385 if (framesize == 0) {
8386 framesize = 128;
8387 } else {
8388 framesize = framesize << 3;
8391 if (ctx->opcode & (1 << 7)) {
8392 gen_mips16_save(ctx, 0, 0,
8393 do_ra, do_s0, do_s1, framesize);
8394 } else {
8395 gen_mips16_restore(ctx, 0, 0,
8396 do_ra, do_s0, do_s1, framesize);
8399 break;
8400 case I8_MOV32R:
8402 int rz = xlat(ctx->opcode & 0x7);
8404 reg32 = (((ctx->opcode >> 3) & 0x3) << 3) |
8405 ((ctx->opcode >> 5) & 0x7);
8406 gen_arith(env, ctx, OPC_ADDU, reg32, rz, 0);
8408 break;
8409 case I8_MOVR32:
8410 reg32 = ctx->opcode & 0x1f;
8411 gen_arith(env, ctx, OPC_ADDU, ry, reg32, 0);
8412 break;
8413 default:
8414 generate_exception(ctx, EXCP_RI);
8415 break;
8418 break;
8419 case M16_OPC_LI:
8421 int16_t imm = (uint8_t) ctx->opcode;
8423 gen_arith_imm(env, ctx, OPC_ADDIU, rx, 0, imm);
8425 break;
8426 case M16_OPC_CMPI:
8428 int16_t imm = (uint8_t) ctx->opcode;
8430 gen_logic_imm(env, OPC_XORI, 24, rx, imm);
8432 break;
8433 #if defined(TARGET_MIPS64)
8434 case M16_OPC_SD:
8435 check_mips_64(ctx);
8436 gen_ldst(ctx, OPC_SD, ry, rx, offset << 3);
8437 break;
8438 #endif
8439 case M16_OPC_LB:
8440 gen_ldst(ctx, OPC_LB, ry, rx, offset);
8441 break;
8442 case M16_OPC_LH:
8443 gen_ldst(ctx, OPC_LH, ry, rx, offset << 1);
8444 break;
8445 case M16_OPC_LWSP:
8446 gen_ldst(ctx, OPC_LW, rx, 29, ((uint8_t)ctx->opcode) << 2);
8447 break;
8448 case M16_OPC_LW:
8449 gen_ldst(ctx, OPC_LW, ry, rx, offset << 2);
8450 break;
8451 case M16_OPC_LBU:
8452 gen_ldst(ctx, OPC_LBU, ry, rx, offset);
8453 break;
8454 case M16_OPC_LHU:
8455 gen_ldst(ctx, OPC_LHU, ry, rx, offset << 1);
8456 break;
8457 case M16_OPC_LWPC:
8458 gen_ldst(ctx, OPC_LWPC, rx, 0, ((uint8_t)ctx->opcode) << 2);
8459 break;
8460 #if defined (TARGET_MIPS64)
8461 case M16_OPC_LWU:
8462 check_mips_64(ctx);
8463 gen_ldst(ctx, OPC_LWU, ry, rx, offset << 2);
8464 break;
8465 #endif
8466 case M16_OPC_SB:
8467 gen_ldst(ctx, OPC_SB, ry, rx, offset);
8468 break;
8469 case M16_OPC_SH:
8470 gen_ldst(ctx, OPC_SH, ry, rx, offset << 1);
8471 break;
8472 case M16_OPC_SWSP:
8473 gen_ldst(ctx, OPC_SW, rx, 29, ((uint8_t)ctx->opcode) << 2);
8474 break;
8475 case M16_OPC_SW:
8476 gen_ldst(ctx, OPC_SW, ry, rx, offset << 2);
8477 break;
8478 case M16_OPC_RRR:
8480 int rz = xlat((ctx->opcode >> 2) & 0x7);
8481 int mips32_op;
8483 switch (ctx->opcode & 0x3) {
8484 case RRR_ADDU:
8485 mips32_op = OPC_ADDU;
8486 break;
8487 case RRR_SUBU:
8488 mips32_op = OPC_SUBU;
8489 break;
8490 #if defined(TARGET_MIPS64)
8491 case RRR_DADDU:
8492 mips32_op = OPC_DADDU;
8493 check_mips_64(ctx);
8494 break;
8495 case RRR_DSUBU:
8496 mips32_op = OPC_DSUBU;
8497 check_mips_64(ctx);
8498 break;
8499 #endif
8500 default:
8501 generate_exception(ctx, EXCP_RI);
8502 goto done;
8505 gen_arith(env, ctx, mips32_op, rz, rx, ry);
8506 done:
8509 break;
8510 case M16_OPC_RR:
8511 switch (op1) {
8512 case RR_JR:
8514 int nd = (ctx->opcode >> 7) & 0x1;
8515 int link = (ctx->opcode >> 6) & 0x1;
8516 int ra = (ctx->opcode >> 5) & 0x1;
8518 if (link) {
8519 op = nd ? OPC_JALRC : OPC_JALR;
8520 } else {
8521 op = OPC_JR;
8524 gen_compute_branch(ctx, op, 2, ra ? 31 : rx, 31, 0);
8525 if (!nd) {
8526 *is_branch = 1;
8529 break;
8530 case RR_SDBBP:
8531 /* XXX: not clear which exception should be raised
8532 * when in debug mode...
8534 check_insn(env, ctx, ISA_MIPS32);
8535 if (!(ctx->hflags & MIPS_HFLAG_DM)) {
8536 generate_exception(ctx, EXCP_DBp);
8537 } else {
8538 generate_exception(ctx, EXCP_DBp);
8540 break;
8541 case RR_SLT:
8542 gen_slt(env, OPC_SLT, 24, rx, ry);
8543 break;
8544 case RR_SLTU:
8545 gen_slt(env, OPC_SLTU, 24, rx, ry);
8546 break;
8547 case RR_BREAK:
8548 generate_exception(ctx, EXCP_BREAK);
8549 break;
8550 case RR_SLLV:
8551 gen_shift(env, ctx, OPC_SLLV, ry, rx, ry);
8552 break;
8553 case RR_SRLV:
8554 gen_shift(env, ctx, OPC_SRLV, ry, rx, ry);
8555 break;
8556 case RR_SRAV:
8557 gen_shift(env, ctx, OPC_SRAV, ry, rx, ry);
8558 break;
8559 #if defined (TARGET_MIPS64)
8560 case RR_DSRL:
8561 check_mips_64(ctx);
8562 gen_shift_imm(env, ctx, OPC_DSRL, ry, ry, sa);
8563 break;
8564 #endif
8565 case RR_CMP:
8566 gen_logic(env, OPC_XOR, 24, rx, ry);
8567 break;
8568 case RR_NEG:
8569 gen_arith(env, ctx, OPC_SUBU, rx, 0, ry);
8570 break;
8571 case RR_AND:
8572 gen_logic(env, OPC_AND, rx, rx, ry);
8573 break;
8574 case RR_OR:
8575 gen_logic(env, OPC_OR, rx, rx, ry);
8576 break;
8577 case RR_XOR:
8578 gen_logic(env, OPC_XOR, rx, rx, ry);
8579 break;
8580 case RR_NOT:
8581 gen_logic(env, OPC_NOR, rx, ry, 0);
8582 break;
8583 case RR_MFHI:
8584 gen_HILO(ctx, OPC_MFHI, rx);
8585 break;
8586 case RR_CNVT:
8587 switch (cnvt_op) {
8588 case RR_RY_CNVT_ZEB:
8589 tcg_gen_ext8u_tl(cpu_gpr[rx], cpu_gpr[rx]);
8590 break;
8591 case RR_RY_CNVT_ZEH:
8592 tcg_gen_ext16u_tl(cpu_gpr[rx], cpu_gpr[rx]);
8593 break;
8594 case RR_RY_CNVT_SEB:
8595 tcg_gen_ext8s_tl(cpu_gpr[rx], cpu_gpr[rx]);
8596 break;
8597 case RR_RY_CNVT_SEH:
8598 tcg_gen_ext16s_tl(cpu_gpr[rx], cpu_gpr[rx]);
8599 break;
8600 #if defined (TARGET_MIPS64)
8601 case RR_RY_CNVT_ZEW:
8602 check_mips_64(ctx);
8603 tcg_gen_ext32u_tl(cpu_gpr[rx], cpu_gpr[rx]);
8604 break;
8605 case RR_RY_CNVT_SEW:
8606 check_mips_64(ctx);
8607 tcg_gen_ext32s_tl(cpu_gpr[rx], cpu_gpr[rx]);
8608 break;
8609 #endif
8610 default:
8611 generate_exception(ctx, EXCP_RI);
8612 break;
8614 break;
8615 case RR_MFLO:
8616 gen_HILO(ctx, OPC_MFLO, rx);
8617 break;
8618 #if defined (TARGET_MIPS64)
8619 case RR_DSRA:
8620 check_mips_64(ctx);
8621 gen_shift_imm(env, ctx, OPC_DSRA, ry, ry, sa);
8622 break;
8623 case RR_DSLLV:
8624 check_mips_64(ctx);
8625 gen_shift(env, ctx, OPC_DSLLV, ry, rx, ry);
8626 break;
8627 case RR_DSRLV:
8628 check_mips_64(ctx);
8629 gen_shift(env, ctx, OPC_DSRLV, ry, rx, ry);
8630 break;
8631 case RR_DSRAV:
8632 check_mips_64(ctx);
8633 gen_shift(env, ctx, OPC_DSRAV, ry, rx, ry);
8634 break;
8635 #endif
8636 case RR_MULT:
8637 gen_muldiv(ctx, OPC_MULT, rx, ry);
8638 break;
8639 case RR_MULTU:
8640 gen_muldiv(ctx, OPC_MULTU, rx, ry);
8641 break;
8642 case RR_DIV:
8643 gen_muldiv(ctx, OPC_DIV, rx, ry);
8644 break;
8645 case RR_DIVU:
8646 gen_muldiv(ctx, OPC_DIVU, rx, ry);
8647 break;
8648 #if defined (TARGET_MIPS64)
8649 case RR_DMULT:
8650 check_mips_64(ctx);
8651 gen_muldiv(ctx, OPC_DMULT, rx, ry);
8652 break;
8653 case RR_DMULTU:
8654 check_mips_64(ctx);
8655 gen_muldiv(ctx, OPC_DMULTU, rx, ry);
8656 break;
8657 case RR_DDIV:
8658 check_mips_64(ctx);
8659 gen_muldiv(ctx, OPC_DDIV, rx, ry);
8660 break;
8661 case RR_DDIVU:
8662 check_mips_64(ctx);
8663 gen_muldiv(ctx, OPC_DDIVU, rx, ry);
8664 break;
8665 #endif
8666 default:
8667 generate_exception(ctx, EXCP_RI);
8668 break;
8670 break;
8671 case M16_OPC_EXTEND:
8672 decode_extended_mips16_opc(env, ctx, is_branch);
8673 n_bytes = 4;
8674 break;
8675 #if defined(TARGET_MIPS64)
8676 case M16_OPC_I64:
8677 funct = (ctx->opcode >> 8) & 0x7;
8678 decode_i64_mips16(env, ctx, ry, funct, offset, 0);
8679 break;
8680 #endif
8681 default:
8682 generate_exception(ctx, EXCP_RI);
8683 break;
8686 return n_bytes;
8689 /* SmartMIPS extension to MIPS32 */
8691 #if defined(TARGET_MIPS64)
8693 /* MDMX extension to MIPS64 */
8695 #endif
8697 static void decode_opc (CPUState *env, DisasContext *ctx, int *is_branch)
8699 int32_t offset;
8700 int rs, rt, rd, sa;
8701 uint32_t op, op1, op2;
8702 int16_t imm;
8704 /* make sure instructions are on a word boundary */
8705 if (ctx->pc & 0x3) {
8706 env->CP0_BadVAddr = ctx->pc;
8707 generate_exception(ctx, EXCP_AdEL);
8708 return;
8711 /* Handle blikely not taken case */
8712 if ((ctx->hflags & MIPS_HFLAG_BMASK_BASE) == MIPS_HFLAG_BL) {
8713 int l1 = gen_new_label();
8715 MIPS_DEBUG("blikely condition (" TARGET_FMT_lx ")", ctx->pc + 4);
8716 tcg_gen_brcondi_tl(TCG_COND_NE, bcond, 0, l1);
8717 tcg_gen_movi_i32(hflags, ctx->hflags & ~MIPS_HFLAG_BMASK);
8718 gen_goto_tb(ctx, 1, ctx->pc + 4);
8719 gen_set_label(l1);
8722 if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP)))
8723 tcg_gen_debug_insn_start(ctx->pc);
8725 op = MASK_OP_MAJOR(ctx->opcode);
8726 rs = (ctx->opcode >> 21) & 0x1f;
8727 rt = (ctx->opcode >> 16) & 0x1f;
8728 rd = (ctx->opcode >> 11) & 0x1f;
8729 sa = (ctx->opcode >> 6) & 0x1f;
8730 imm = (int16_t)ctx->opcode;
8731 switch (op) {
8732 case OPC_SPECIAL:
8733 op1 = MASK_SPECIAL(ctx->opcode);
8734 switch (op1) {
8735 case OPC_SLL: /* Shift with immediate */
8736 case OPC_SRA:
8737 gen_shift_imm(env, ctx, op1, rd, rt, sa);
8738 break;
8739 case OPC_SRL:
8740 switch ((ctx->opcode >> 21) & 0x1f) {
8741 case 1:
8742 /* rotr is decoded as srl on non-R2 CPUs */
8743 if (env->insn_flags & ISA_MIPS32R2) {
8744 op1 = OPC_ROTR;
8746 /* Fallthrough */
8747 case 0:
8748 gen_shift_imm(env, ctx, op1, rd, rt, sa);
8749 break;
8750 default:
8751 generate_exception(ctx, EXCP_RI);
8752 break;
8754 break;
8755 case OPC_MOVN: /* Conditional move */
8756 case OPC_MOVZ:
8757 check_insn(env, ctx, ISA_MIPS4 | ISA_MIPS32);
8758 gen_cond_move(env, op1, rd, rs, rt);
8759 break;
8760 case OPC_ADD ... OPC_SUBU:
8761 gen_arith(env, ctx, op1, rd, rs, rt);
8762 break;
8763 case OPC_SLLV: /* Shifts */
8764 case OPC_SRAV:
8765 gen_shift(env, ctx, op1, rd, rs, rt);
8766 break;
8767 case OPC_SRLV:
8768 switch ((ctx->opcode >> 6) & 0x1f) {
8769 case 1:
8770 /* rotrv is decoded as srlv on non-R2 CPUs */
8771 if (env->insn_flags & ISA_MIPS32R2) {
8772 op1 = OPC_ROTRV;
8774 /* Fallthrough */
8775 case 0:
8776 gen_shift(env, ctx, op1, rd, rs, rt);
8777 break;
8778 default:
8779 generate_exception(ctx, EXCP_RI);
8780 break;
8782 break;
8783 case OPC_SLT: /* Set on less than */
8784 case OPC_SLTU:
8785 gen_slt(env, op1, rd, rs, rt);
8786 break;
8787 case OPC_AND: /* Logic*/
8788 case OPC_OR:
8789 case OPC_NOR:
8790 case OPC_XOR:
8791 gen_logic(env, op1, rd, rs, rt);
8792 break;
8793 case OPC_MULT ... OPC_DIVU:
8794 if (sa) {
8795 check_insn(env, ctx, INSN_VR54XX);
8796 op1 = MASK_MUL_VR54XX(ctx->opcode);
8797 gen_mul_vr54xx(ctx, op1, rd, rs, rt);
8798 } else
8799 gen_muldiv(ctx, op1, rs, rt);
8800 break;
8801 case OPC_JR ... OPC_JALR:
8802 gen_compute_branch(ctx, op1, 4, rs, rd, sa);
8803 *is_branch = 1;
8804 break;
8805 case OPC_TGE ... OPC_TEQ: /* Traps */
8806 case OPC_TNE:
8807 gen_trap(ctx, op1, rs, rt, -1);
8808 break;
8809 case OPC_MFHI: /* Move from HI/LO */
8810 case OPC_MFLO:
8811 gen_HILO(ctx, op1, rd);
8812 break;
8813 case OPC_MTHI:
8814 case OPC_MTLO: /* Move to HI/LO */
8815 gen_HILO(ctx, op1, rs);
8816 break;
8817 case OPC_PMON: /* Pmon entry point, also R4010 selsl */
8818 #ifdef MIPS_STRICT_STANDARD
8819 MIPS_INVAL("PMON / selsl");
8820 generate_exception(ctx, EXCP_RI);
8821 #else
8822 gen_helper_0i(pmon, sa);
8823 #endif
8824 break;
8825 case OPC_SYSCALL:
8826 generate_exception(ctx, EXCP_SYSCALL);
8827 ctx->bstate = BS_STOP;
8828 break;
8829 case OPC_BREAK:
8830 generate_exception(ctx, EXCP_BREAK);
8831 break;
8832 case OPC_SPIM:
8833 #ifdef MIPS_STRICT_STANDARD
8834 MIPS_INVAL("SPIM");
8835 generate_exception(ctx, EXCP_RI);
8836 #else
8837 /* Implemented as RI exception for now. */
8838 MIPS_INVAL("spim (unofficial)");
8839 generate_exception(ctx, EXCP_RI);
8840 #endif
8841 break;
8842 case OPC_SYNC:
8843 /* Treat as NOP. */
8844 break;
8846 case OPC_MOVCI:
8847 check_insn(env, ctx, ISA_MIPS4 | ISA_MIPS32);
8848 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
8849 check_cp1_enabled(ctx);
8850 gen_movci(ctx, rd, rs, (ctx->opcode >> 18) & 0x7,
8851 (ctx->opcode >> 16) & 1);
8852 } else {
8853 generate_exception_err(ctx, EXCP_CpU, 1);
8855 break;
8857 #if defined(TARGET_MIPS64)
8858 /* MIPS64 specific opcodes */
8859 case OPC_DSLL:
8860 case OPC_DSRA:
8861 case OPC_DSLL32:
8862 case OPC_DSRA32:
8863 check_insn(env, ctx, ISA_MIPS3);
8864 check_mips_64(ctx);
8865 gen_shift_imm(env, ctx, op1, rd, rt, sa);
8866 break;
8867 case OPC_DSRL:
8868 switch ((ctx->opcode >> 21) & 0x1f) {
8869 case 1:
8870 /* drotr is decoded as dsrl on non-R2 CPUs */
8871 if (env->insn_flags & ISA_MIPS32R2) {
8872 op1 = OPC_DROTR;
8874 /* Fallthrough */
8875 case 0:
8876 check_insn(env, ctx, ISA_MIPS3);
8877 check_mips_64(ctx);
8878 gen_shift_imm(env, ctx, op1, rd, rt, sa);
8879 break;
8880 default:
8881 generate_exception(ctx, EXCP_RI);
8882 break;
8884 break;
8885 case OPC_DSRL32:
8886 switch ((ctx->opcode >> 21) & 0x1f) {
8887 case 1:
8888 /* drotr32 is decoded as dsrl32 on non-R2 CPUs */
8889 if (env->insn_flags & ISA_MIPS32R2) {
8890 op1 = OPC_DROTR32;
8892 /* Fallthrough */
8893 case 0:
8894 check_insn(env, ctx, ISA_MIPS3);
8895 check_mips_64(ctx);
8896 gen_shift_imm(env, ctx, op1, rd, rt, sa);
8897 break;
8898 default:
8899 generate_exception(ctx, EXCP_RI);
8900 break;
8902 break;
8903 case OPC_DADD ... OPC_DSUBU:
8904 check_insn(env, ctx, ISA_MIPS3);
8905 check_mips_64(ctx);
8906 gen_arith(env, ctx, op1, rd, rs, rt);
8907 break;
8908 case OPC_DSLLV:
8909 case OPC_DSRAV:
8910 check_insn(env, ctx, ISA_MIPS3);
8911 check_mips_64(ctx);
8912 gen_shift(env, ctx, op1, rd, rs, rt);
8913 break;
8914 case OPC_DSRLV:
8915 switch ((ctx->opcode >> 6) & 0x1f) {
8916 case 1:
8917 /* drotrv is decoded as dsrlv on non-R2 CPUs */
8918 if (env->insn_flags & ISA_MIPS32R2) {
8919 op1 = OPC_DROTRV;
8921 /* Fallthrough */
8922 case 0:
8923 check_insn(env, ctx, ISA_MIPS3);
8924 check_mips_64(ctx);
8925 gen_shift(env, ctx, op1, rd, rs, rt);
8926 break;
8927 default:
8928 generate_exception(ctx, EXCP_RI);
8929 break;
8931 break;
8932 case OPC_DMULT ... OPC_DDIVU:
8933 check_insn(env, ctx, ISA_MIPS3);
8934 check_mips_64(ctx);
8935 gen_muldiv(ctx, op1, rs, rt);
8936 break;
8937 #endif
8938 default: /* Invalid */
8939 MIPS_INVAL("special");
8940 generate_exception(ctx, EXCP_RI);
8941 break;
8943 break;
8944 case OPC_SPECIAL2:
8945 op1 = MASK_SPECIAL2(ctx->opcode);
8946 switch (op1) {
8947 case OPC_MADD ... OPC_MADDU: /* Multiply and add/sub */
8948 case OPC_MSUB ... OPC_MSUBU:
8949 check_insn(env, ctx, ISA_MIPS32);
8950 gen_muldiv(ctx, op1, rs, rt);
8951 break;
8952 case OPC_MUL:
8953 gen_arith(env, ctx, op1, rd, rs, rt);
8954 break;
8955 case OPC_CLO:
8956 case OPC_CLZ:
8957 check_insn(env, ctx, ISA_MIPS32);
8958 gen_cl(ctx, op1, rd, rs);
8959 break;
8960 case OPC_SDBBP:
8961 /* XXX: not clear which exception should be raised
8962 * when in debug mode...
8964 check_insn(env, ctx, ISA_MIPS32);
8965 if (!(ctx->hflags & MIPS_HFLAG_DM)) {
8966 generate_exception(ctx, EXCP_DBp);
8967 } else {
8968 generate_exception(ctx, EXCP_DBp);
8970 /* Treat as NOP. */
8971 break;
8972 #if defined(TARGET_MIPS64)
8973 case OPC_DCLO:
8974 case OPC_DCLZ:
8975 check_insn(env, ctx, ISA_MIPS64);
8976 check_mips_64(ctx);
8977 gen_cl(ctx, op1, rd, rs);
8978 break;
8979 #endif
8980 default: /* Invalid */
8981 MIPS_INVAL("special2");
8982 generate_exception(ctx, EXCP_RI);
8983 break;
8985 break;
8986 case OPC_SPECIAL3:
8987 op1 = MASK_SPECIAL3(ctx->opcode);
8988 switch (op1) {
8989 case OPC_EXT:
8990 case OPC_INS:
8991 check_insn(env, ctx, ISA_MIPS32R2);
8992 gen_bitops(ctx, op1, rt, rs, sa, rd);
8993 break;
8994 case OPC_BSHFL:
8995 check_insn(env, ctx, ISA_MIPS32R2);
8996 op2 = MASK_BSHFL(ctx->opcode);
8997 gen_bshfl(ctx, op2, rt, rd);
8998 break;
8999 case OPC_RDHWR:
9000 check_insn(env, ctx, ISA_MIPS32R2);
9002 TCGv t0 = tcg_temp_new();
9004 switch (rd) {
9005 case 0:
9006 save_cpu_state(ctx, 1);
9007 gen_helper_rdhwr_cpunum(t0);
9008 gen_store_gpr(t0, rt);
9009 break;
9010 case 1:
9011 save_cpu_state(ctx, 1);
9012 gen_helper_rdhwr_synci_step(t0);
9013 gen_store_gpr(t0, rt);
9014 break;
9015 case 2:
9016 save_cpu_state(ctx, 1);
9017 gen_helper_rdhwr_cc(t0);
9018 gen_store_gpr(t0, rt);
9019 break;
9020 case 3:
9021 save_cpu_state(ctx, 1);
9022 gen_helper_rdhwr_ccres(t0);
9023 gen_store_gpr(t0, rt);
9024 break;
9025 case 29:
9026 #if defined(CONFIG_USER_ONLY)
9027 tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUState, tls_value));
9028 gen_store_gpr(t0, rt);
9029 break;
9030 #else
9031 /* XXX: Some CPUs implement this in hardware.
9032 Not supported yet. */
9033 #endif
9034 default: /* Invalid */
9035 MIPS_INVAL("rdhwr");
9036 generate_exception(ctx, EXCP_RI);
9037 break;
9039 tcg_temp_free(t0);
9041 break;
9042 case OPC_FORK:
9043 check_insn(env, ctx, ASE_MT);
9045 TCGv t0 = tcg_temp_new();
9046 TCGv t1 = tcg_temp_new();
9048 gen_load_gpr(t0, rt);
9049 gen_load_gpr(t1, rs);
9050 gen_helper_fork(t0, t1);
9051 tcg_temp_free(t0);
9052 tcg_temp_free(t1);
9054 break;
9055 case OPC_YIELD:
9056 check_insn(env, ctx, ASE_MT);
9058 TCGv t0 = tcg_temp_new();
9060 save_cpu_state(ctx, 1);
9061 gen_load_gpr(t0, rs);
9062 gen_helper_yield(t0, t0);
9063 gen_store_gpr(t0, rd);
9064 tcg_temp_free(t0);
9066 break;
9067 #if defined(TARGET_MIPS64)
9068 case OPC_DEXTM ... OPC_DEXT:
9069 case OPC_DINSM ... OPC_DINS:
9070 check_insn(env, ctx, ISA_MIPS64R2);
9071 check_mips_64(ctx);
9072 gen_bitops(ctx, op1, rt, rs, sa, rd);
9073 break;
9074 case OPC_DBSHFL:
9075 check_insn(env, ctx, ISA_MIPS64R2);
9076 check_mips_64(ctx);
9077 op2 = MASK_DBSHFL(ctx->opcode);
9078 gen_bshfl(ctx, op2, rt, rd);
9079 break;
9080 #endif
9081 default: /* Invalid */
9082 MIPS_INVAL("special3");
9083 generate_exception(ctx, EXCP_RI);
9084 break;
9086 break;
9087 case OPC_REGIMM:
9088 op1 = MASK_REGIMM(ctx->opcode);
9089 switch (op1) {
9090 case OPC_BLTZ ... OPC_BGEZL: /* REGIMM branches */
9091 case OPC_BLTZAL ... OPC_BGEZALL:
9092 gen_compute_branch(ctx, op1, 4, rs, -1, imm << 2);
9093 *is_branch = 1;
9094 break;
9095 case OPC_TGEI ... OPC_TEQI: /* REGIMM traps */
9096 case OPC_TNEI:
9097 gen_trap(ctx, op1, rs, -1, imm);
9098 break;
9099 case OPC_SYNCI:
9100 check_insn(env, ctx, ISA_MIPS32R2);
9101 /* Treat as NOP. */
9102 break;
9103 default: /* Invalid */
9104 MIPS_INVAL("regimm");
9105 generate_exception(ctx, EXCP_RI);
9106 break;
9108 break;
9109 case OPC_CP0:
9110 check_cp0_enabled(ctx);
9111 op1 = MASK_CP0(ctx->opcode);
9112 switch (op1) {
9113 case OPC_MFC0:
9114 case OPC_MTC0:
9115 case OPC_MFTR:
9116 case OPC_MTTR:
9117 #if defined(TARGET_MIPS64)
9118 case OPC_DMFC0:
9119 case OPC_DMTC0:
9120 #endif
9121 #ifndef CONFIG_USER_ONLY
9122 gen_cp0(env, ctx, op1, rt, rd);
9123 #endif /* !CONFIG_USER_ONLY */
9124 break;
9125 case OPC_C0_FIRST ... OPC_C0_LAST:
9126 #ifndef CONFIG_USER_ONLY
9127 gen_cp0(env, ctx, MASK_C0(ctx->opcode), rt, rd);
9128 #endif /* !CONFIG_USER_ONLY */
9129 break;
9130 case OPC_MFMC0:
9131 #ifndef CONFIG_USER_ONLY
9133 TCGv t0 = tcg_temp_new();
9135 op2 = MASK_MFMC0(ctx->opcode);
9136 switch (op2) {
9137 case OPC_DMT:
9138 check_insn(env, ctx, ASE_MT);
9139 gen_helper_dmt(t0, t0);
9140 gen_store_gpr(t0, rt);
9141 break;
9142 case OPC_EMT:
9143 check_insn(env, ctx, ASE_MT);
9144 gen_helper_emt(t0, t0);
9145 gen_store_gpr(t0, rt);
9146 break;
9147 case OPC_DVPE:
9148 check_insn(env, ctx, ASE_MT);
9149 gen_helper_dvpe(t0, t0);
9150 gen_store_gpr(t0, rt);
9151 break;
9152 case OPC_EVPE:
9153 check_insn(env, ctx, ASE_MT);
9154 gen_helper_evpe(t0, t0);
9155 gen_store_gpr(t0, rt);
9156 break;
9157 case OPC_DI:
9158 check_insn(env, ctx, ISA_MIPS32R2);
9159 save_cpu_state(ctx, 1);
9160 gen_helper_di(t0);
9161 gen_store_gpr(t0, rt);
9162 /* Stop translation as we may have switched the execution mode */
9163 ctx->bstate = BS_STOP;
9164 break;
9165 case OPC_EI:
9166 check_insn(env, ctx, ISA_MIPS32R2);
9167 save_cpu_state(ctx, 1);
9168 gen_helper_ei(t0);
9169 gen_store_gpr(t0, rt);
9170 /* Stop translation as we may have switched the execution mode */
9171 ctx->bstate = BS_STOP;
9172 break;
9173 default: /* Invalid */
9174 MIPS_INVAL("mfmc0");
9175 generate_exception(ctx, EXCP_RI);
9176 break;
9178 tcg_temp_free(t0);
9180 #endif /* !CONFIG_USER_ONLY */
9181 break;
9182 case OPC_RDPGPR:
9183 check_insn(env, ctx, ISA_MIPS32R2);
9184 gen_load_srsgpr(rt, rd);
9185 break;
9186 case OPC_WRPGPR:
9187 check_insn(env, ctx, ISA_MIPS32R2);
9188 gen_store_srsgpr(rt, rd);
9189 break;
9190 default:
9191 MIPS_INVAL("cp0");
9192 generate_exception(ctx, EXCP_RI);
9193 break;
9195 break;
9196 case OPC_ADDI: /* Arithmetic with immediate opcode */
9197 case OPC_ADDIU:
9198 gen_arith_imm(env, ctx, op, rt, rs, imm);
9199 break;
9200 case OPC_SLTI: /* Set on less than with immediate opcode */
9201 case OPC_SLTIU:
9202 gen_slt_imm(env, op, rt, rs, imm);
9203 break;
9204 case OPC_ANDI: /* Arithmetic with immediate opcode */
9205 case OPC_LUI:
9206 case OPC_ORI:
9207 case OPC_XORI:
9208 gen_logic_imm(env, op, rt, rs, imm);
9209 break;
9210 case OPC_J ... OPC_JAL: /* Jump */
9211 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2;
9212 gen_compute_branch(ctx, op, 4, rs, rt, offset);
9213 *is_branch = 1;
9214 break;
9215 case OPC_BEQ ... OPC_BGTZ: /* Branch */
9216 case OPC_BEQL ... OPC_BGTZL:
9217 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2);
9218 *is_branch = 1;
9219 break;
9220 case OPC_LB ... OPC_LWR: /* Load and stores */
9221 case OPC_SB ... OPC_SW:
9222 case OPC_SWR:
9223 case OPC_LL:
9224 gen_ldst(ctx, op, rt, rs, imm);
9225 break;
9226 case OPC_SC:
9227 gen_st_cond(ctx, op, rt, rs, imm);
9228 break;
9229 case OPC_CACHE:
9230 check_insn(env, ctx, ISA_MIPS3 | ISA_MIPS32);
9231 /* Treat as NOP. */
9232 break;
9233 case OPC_PREF:
9234 check_insn(env, ctx, ISA_MIPS4 | ISA_MIPS32);
9235 /* Treat as NOP. */
9236 break;
9238 /* Floating point (COP1). */
9239 case OPC_LWC1:
9240 case OPC_LDC1:
9241 case OPC_SWC1:
9242 case OPC_SDC1:
9243 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
9244 check_cp1_enabled(ctx);
9245 gen_flt_ldst(ctx, op, rt, rs, imm);
9246 } else {
9247 generate_exception_err(ctx, EXCP_CpU, 1);
9249 break;
9251 case OPC_CP1:
9252 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
9253 check_cp1_enabled(ctx);
9254 op1 = MASK_CP1(ctx->opcode);
9255 switch (op1) {
9256 case OPC_MFHC1:
9257 case OPC_MTHC1:
9258 check_insn(env, ctx, ISA_MIPS32R2);
9259 case OPC_MFC1:
9260 case OPC_CFC1:
9261 case OPC_MTC1:
9262 case OPC_CTC1:
9263 gen_cp1(ctx, op1, rt, rd);
9264 break;
9265 #if defined(TARGET_MIPS64)
9266 case OPC_DMFC1:
9267 case OPC_DMTC1:
9268 check_insn(env, ctx, ISA_MIPS3);
9269 gen_cp1(ctx, op1, rt, rd);
9270 break;
9271 #endif
9272 case OPC_BC1ANY2:
9273 case OPC_BC1ANY4:
9274 check_cop1x(ctx);
9275 check_insn(env, ctx, ASE_MIPS3D);
9276 /* fall through */
9277 case OPC_BC1:
9278 gen_compute_branch1(env, ctx, MASK_BC1(ctx->opcode),
9279 (rt >> 2) & 0x7, imm << 2);
9280 *is_branch = 1;
9281 break;
9282 case OPC_S_FMT:
9283 case OPC_D_FMT:
9284 case OPC_W_FMT:
9285 case OPC_L_FMT:
9286 case OPC_PS_FMT:
9287 gen_farith(ctx, MASK_CP1_FUNC(ctx->opcode), rt, rd, sa,
9288 (imm >> 8) & 0x7);
9289 break;
9290 default:
9291 MIPS_INVAL("cp1");
9292 generate_exception (ctx, EXCP_RI);
9293 break;
9295 } else {
9296 generate_exception_err(ctx, EXCP_CpU, 1);
9298 break;
9300 /* COP2. */
9301 case OPC_LWC2:
9302 case OPC_LDC2:
9303 case OPC_SWC2:
9304 case OPC_SDC2:
9305 case OPC_CP2:
9306 /* COP2: Not implemented. */
9307 generate_exception_err(ctx, EXCP_CpU, 2);
9308 break;
9310 case OPC_CP3:
9311 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
9312 check_cp1_enabled(ctx);
9313 op1 = MASK_CP3(ctx->opcode);
9314 switch (op1) {
9315 case OPC_LWXC1:
9316 case OPC_LDXC1:
9317 case OPC_LUXC1:
9318 case OPC_SWXC1:
9319 case OPC_SDXC1:
9320 case OPC_SUXC1:
9321 gen_flt3_ldst(ctx, op1, sa, rd, rs, rt);
9322 break;
9323 case OPC_PREFX:
9324 /* Treat as NOP. */
9325 break;
9326 case OPC_ALNV_PS:
9327 case OPC_MADD_S:
9328 case OPC_MADD_D:
9329 case OPC_MADD_PS:
9330 case OPC_MSUB_S:
9331 case OPC_MSUB_D:
9332 case OPC_MSUB_PS:
9333 case OPC_NMADD_S:
9334 case OPC_NMADD_D:
9335 case OPC_NMADD_PS:
9336 case OPC_NMSUB_S:
9337 case OPC_NMSUB_D:
9338 case OPC_NMSUB_PS:
9339 gen_flt3_arith(ctx, op1, sa, rs, rd, rt);
9340 break;
9341 default:
9342 MIPS_INVAL("cp3");
9343 generate_exception (ctx, EXCP_RI);
9344 break;
9346 } else {
9347 generate_exception_err(ctx, EXCP_CpU, 1);
9349 break;
9351 #if defined(TARGET_MIPS64)
9352 /* MIPS64 opcodes */
9353 case OPC_LWU:
9354 case OPC_LDL ... OPC_LDR:
9355 case OPC_SDL ... OPC_SDR:
9356 case OPC_LLD:
9357 case OPC_LD:
9358 case OPC_SD:
9359 check_insn(env, ctx, ISA_MIPS3);
9360 check_mips_64(ctx);
9361 gen_ldst(ctx, op, rt, rs, imm);
9362 break;
9363 case OPC_SCD:
9364 check_insn(env, ctx, ISA_MIPS3);
9365 check_mips_64(ctx);
9366 gen_st_cond(ctx, op, rt, rs, imm);
9367 break;
9368 case OPC_DADDI:
9369 case OPC_DADDIU:
9370 check_insn(env, ctx, ISA_MIPS3);
9371 check_mips_64(ctx);
9372 gen_arith_imm(env, ctx, op, rt, rs, imm);
9373 break;
9374 #endif
9375 case OPC_JALX:
9376 check_insn(env, ctx, ASE_MIPS16);
9377 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2;
9378 gen_compute_branch(ctx, op, 4, rs, rt, offset);
9379 *is_branch = 1;
9380 break;
9381 case OPC_MDMX:
9382 check_insn(env, ctx, ASE_MDMX);
9383 /* MDMX: Not implemented. */
9384 default: /* Invalid */
9385 MIPS_INVAL("major opcode");
9386 generate_exception(ctx, EXCP_RI);
9387 break;
9391 static inline void
9392 gen_intermediate_code_internal (CPUState *env, TranslationBlock *tb,
9393 int search_pc)
9395 DisasContext ctx;
9396 target_ulong pc_start;
9397 uint16_t *gen_opc_end;
9398 CPUBreakpoint *bp;
9399 int j, lj = -1;
9400 int num_insns;
9401 int max_insns;
9402 int insn_bytes;
9403 int is_branch;
9405 if (search_pc)
9406 qemu_log("search pc %d\n", search_pc);
9408 pc_start = tb->pc;
9409 gen_opc_end = gen_opc_buf + OPC_MAX_SIZE;
9410 ctx.pc = pc_start;
9411 ctx.saved_pc = -1;
9412 ctx.singlestep_enabled = env->singlestep_enabled;
9413 ctx.tb = tb;
9414 ctx.bstate = BS_NONE;
9415 /* Restore delay slot state from the tb context. */
9416 ctx.hflags = (uint32_t)tb->flags; /* FIXME: maybe use 64 bits here? */
9417 restore_cpu_state(env, &ctx);
9418 #ifdef CONFIG_USER_ONLY
9419 ctx.mem_idx = MIPS_HFLAG_UM;
9420 #else
9421 ctx.mem_idx = ctx.hflags & MIPS_HFLAG_KSU;
9422 #endif
9423 num_insns = 0;
9424 max_insns = tb->cflags & CF_COUNT_MASK;
9425 if (max_insns == 0)
9426 max_insns = CF_COUNT_MASK;
9427 #ifdef DEBUG_DISAS
9428 qemu_log_mask(CPU_LOG_TB_CPU, "------------------------------------------------\n");
9429 /* FIXME: This may print out stale hflags from env... */
9430 log_cpu_state_mask(CPU_LOG_TB_CPU, env, 0);
9431 #endif
9432 LOG_DISAS("\ntb %p idx %d hflags %04x\n", tb, ctx.mem_idx, ctx.hflags);
9433 gen_icount_start();
9434 while (ctx.bstate == BS_NONE) {
9435 if (unlikely(!QTAILQ_EMPTY(&env->breakpoints))) {
9436 QTAILQ_FOREACH(bp, &env->breakpoints, entry) {
9437 if (bp->pc == ctx.pc) {
9438 save_cpu_state(&ctx, 1);
9439 ctx.bstate = BS_BRANCH;
9440 gen_helper_0i(raise_exception, EXCP_DEBUG);
9441 /* Include the breakpoint location or the tb won't
9442 * be flushed when it must be. */
9443 ctx.pc += 4;
9444 goto done_generating;
9449 if (search_pc) {
9450 j = gen_opc_ptr - gen_opc_buf;
9451 if (lj < j) {
9452 lj++;
9453 while (lj < j)
9454 gen_opc_instr_start[lj++] = 0;
9456 gen_opc_pc[lj] = ctx.pc;
9457 gen_opc_hflags[lj] = ctx.hflags & MIPS_HFLAG_BMASK;
9458 gen_opc_instr_start[lj] = 1;
9459 gen_opc_icount[lj] = num_insns;
9461 if (num_insns + 1 == max_insns && (tb->cflags & CF_LAST_IO))
9462 gen_io_start();
9464 is_branch = 0;
9465 if (!(ctx.hflags & MIPS_HFLAG_M16)) {
9466 ctx.opcode = ldl_code(ctx.pc);
9467 insn_bytes = 4;
9468 decode_opc(env, &ctx, &is_branch);
9469 } else if (env->insn_flags & ASE_MIPS16) {
9470 ctx.opcode = lduw_code(ctx.pc);
9471 insn_bytes = decode_mips16_opc(env, &ctx, &is_branch);
9472 } else {
9473 generate_exception(&ctx, EXCP_RI);
9474 break;
9476 if (!is_branch) {
9477 handle_delay_slot(env, &ctx, insn_bytes);
9479 ctx.pc += insn_bytes;
9481 num_insns++;
9483 /* Execute a branch and its delay slot as a single instruction.
9484 This is what GDB expects and is consistent with what the
9485 hardware does (e.g. if a delay slot instruction faults, the
9486 reported PC is the PC of the branch). */
9487 if (env->singlestep_enabled && (ctx.hflags & MIPS_HFLAG_BMASK) == 0)
9488 break;
9490 if ((ctx.pc & (TARGET_PAGE_SIZE - 1)) == 0)
9491 break;
9493 if (gen_opc_ptr >= gen_opc_end)
9494 break;
9496 if (num_insns >= max_insns)
9497 break;
9499 if (singlestep)
9500 break;
9502 if (tb->cflags & CF_LAST_IO)
9503 gen_io_end();
9504 if (env->singlestep_enabled && ctx.bstate != BS_BRANCH) {
9505 save_cpu_state(&ctx, ctx.bstate == BS_NONE);
9506 gen_helper_0i(raise_exception, EXCP_DEBUG);
9507 } else {
9508 switch (ctx.bstate) {
9509 case BS_STOP:
9510 gen_helper_interrupt_restart();
9511 gen_goto_tb(&ctx, 0, ctx.pc);
9512 break;
9513 case BS_NONE:
9514 save_cpu_state(&ctx, 0);
9515 gen_goto_tb(&ctx, 0, ctx.pc);
9516 break;
9517 case BS_EXCP:
9518 gen_helper_interrupt_restart();
9519 tcg_gen_exit_tb(0);
9520 break;
9521 case BS_BRANCH:
9522 default:
9523 break;
9526 done_generating:
9527 gen_icount_end(tb, num_insns);
9528 *gen_opc_ptr = INDEX_op_end;
9529 if (search_pc) {
9530 j = gen_opc_ptr - gen_opc_buf;
9531 lj++;
9532 while (lj <= j)
9533 gen_opc_instr_start[lj++] = 0;
9534 } else {
9535 tb->size = ctx.pc - pc_start;
9536 tb->icount = num_insns;
9538 #ifdef DEBUG_DISAS
9539 LOG_DISAS("\n");
9540 if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) {
9541 qemu_log("IN: %s\n", lookup_symbol(pc_start));
9542 log_target_disas(pc_start, ctx.pc - pc_start, 0);
9543 qemu_log("\n");
9545 qemu_log_mask(CPU_LOG_TB_CPU, "---------------- %d %08x\n", ctx.bstate, ctx.hflags);
9546 #endif
9549 void gen_intermediate_code (CPUState *env, struct TranslationBlock *tb)
9551 gen_intermediate_code_internal(env, tb, 0);
9554 void gen_intermediate_code_pc (CPUState *env, struct TranslationBlock *tb)
9556 gen_intermediate_code_internal(env, tb, 1);
9559 static void fpu_dump_state(CPUState *env, FILE *f,
9560 int (*fpu_fprintf)(FILE *f, const char *fmt, ...),
9561 int flags)
9563 int i;
9564 int is_fpu64 = !!(env->hflags & MIPS_HFLAG_F64);
9566 #define printfpr(fp) \
9567 do { \
9568 if (is_fpu64) \
9569 fpu_fprintf(f, "w:%08x d:%016lx fd:%13g fs:%13g psu: %13g\n", \
9570 (fp)->w[FP_ENDIAN_IDX], (fp)->d, (fp)->fd, \
9571 (fp)->fs[FP_ENDIAN_IDX], (fp)->fs[!FP_ENDIAN_IDX]); \
9572 else { \
9573 fpr_t tmp; \
9574 tmp.w[FP_ENDIAN_IDX] = (fp)->w[FP_ENDIAN_IDX]; \
9575 tmp.w[!FP_ENDIAN_IDX] = ((fp) + 1)->w[FP_ENDIAN_IDX]; \
9576 fpu_fprintf(f, "w:%08x d:%016lx fd:%13g fs:%13g psu:%13g\n", \
9577 tmp.w[FP_ENDIAN_IDX], tmp.d, tmp.fd, \
9578 tmp.fs[FP_ENDIAN_IDX], tmp.fs[!FP_ENDIAN_IDX]); \
9580 } while(0)
9583 fpu_fprintf(f, "CP1 FCR0 0x%08x FCR31 0x%08x SR.FR %d fp_status 0x%08x(0x%02x)\n",
9584 env->active_fpu.fcr0, env->active_fpu.fcr31, is_fpu64, env->active_fpu.fp_status,
9585 get_float_exception_flags(&env->active_fpu.fp_status));
9586 for (i = 0; i < 32; (is_fpu64) ? i++ : (i += 2)) {
9587 fpu_fprintf(f, "%3s: ", fregnames[i]);
9588 printfpr(&env->active_fpu.fpr[i]);
9591 #undef printfpr
9594 #if defined(TARGET_MIPS64) && defined(MIPS_DEBUG_SIGN_EXTENSIONS)
9595 /* Debug help: The architecture requires 32bit code to maintain proper
9596 sign-extended values on 64bit machines. */
9598 #define SIGN_EXT_P(val) ((((val) & ~0x7fffffff) == 0) || (((val) & ~0x7fffffff) == ~0x7fffffff))
9600 static void
9601 cpu_mips_check_sign_extensions (CPUState *env, FILE *f,
9602 int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
9603 int flags)
9605 int i;
9607 if (!SIGN_EXT_P(env->active_tc.PC))
9608 cpu_fprintf(f, "BROKEN: pc=0x" TARGET_FMT_lx "\n", env->active_tc.PC);
9609 if (!SIGN_EXT_P(env->active_tc.HI[0]))
9610 cpu_fprintf(f, "BROKEN: HI=0x" TARGET_FMT_lx "\n", env->active_tc.HI[0]);
9611 if (!SIGN_EXT_P(env->active_tc.LO[0]))
9612 cpu_fprintf(f, "BROKEN: LO=0x" TARGET_FMT_lx "\n", env->active_tc.LO[0]);
9613 if (!SIGN_EXT_P(env->btarget))
9614 cpu_fprintf(f, "BROKEN: btarget=0x" TARGET_FMT_lx "\n", env->btarget);
9616 for (i = 0; i < 32; i++) {
9617 if (!SIGN_EXT_P(env->active_tc.gpr[i]))
9618 cpu_fprintf(f, "BROKEN: %s=0x" TARGET_FMT_lx "\n", regnames[i], env->active_tc.gpr[i]);
9621 if (!SIGN_EXT_P(env->CP0_EPC))
9622 cpu_fprintf(f, "BROKEN: EPC=0x" TARGET_FMT_lx "\n", env->CP0_EPC);
9623 if (!SIGN_EXT_P(env->lladdr))
9624 cpu_fprintf(f, "BROKEN: LLAddr=0x" TARGET_FMT_lx "\n", env->lladdr);
9626 #endif
9628 void cpu_dump_state (CPUState *env, FILE *f,
9629 int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
9630 int flags)
9632 int i;
9634 cpu_fprintf(f, "pc=0x" TARGET_FMT_lx " HI=0x" TARGET_FMT_lx " LO=0x" TARGET_FMT_lx " ds %04x " TARGET_FMT_lx " %d\n",
9635 env->active_tc.PC, env->active_tc.HI[0], env->active_tc.LO[0],
9636 env->hflags, env->btarget, env->bcond);
9637 for (i = 0; i < 32; i++) {
9638 if ((i & 3) == 0)
9639 cpu_fprintf(f, "GPR%02d:", i);
9640 cpu_fprintf(f, " %s " TARGET_FMT_lx, regnames[i], env->active_tc.gpr[i]);
9641 if ((i & 3) == 3)
9642 cpu_fprintf(f, "\n");
9645 cpu_fprintf(f, "CP0 Status 0x%08x Cause 0x%08x EPC 0x" TARGET_FMT_lx "\n",
9646 env->CP0_Status, env->CP0_Cause, env->CP0_EPC);
9647 cpu_fprintf(f, " Config0 0x%08x Config1 0x%08x LLAddr 0x" TARGET_FMT_lx "\n",
9648 env->CP0_Config0, env->CP0_Config1, env->lladdr);
9649 if (env->hflags & MIPS_HFLAG_FPU)
9650 fpu_dump_state(env, f, cpu_fprintf, flags);
9651 #if defined(TARGET_MIPS64) && defined(MIPS_DEBUG_SIGN_EXTENSIONS)
9652 cpu_mips_check_sign_extensions(env, f, cpu_fprintf, flags);
9653 #endif
9656 static void mips_tcg_init(void)
9658 int i;
9659 static int inited;
9661 /* Initialize various static tables. */
9662 if (inited)
9663 return;
9665 cpu_env = tcg_global_reg_new_ptr(TCG_AREG0, "env");
9666 TCGV_UNUSED(cpu_gpr[0]);
9667 for (i = 1; i < 32; i++)
9668 cpu_gpr[i] = tcg_global_mem_new(TCG_AREG0,
9669 offsetof(CPUState, active_tc.gpr[i]),
9670 regnames[i]);
9671 cpu_PC = tcg_global_mem_new(TCG_AREG0,
9672 offsetof(CPUState, active_tc.PC), "PC");
9673 for (i = 0; i < MIPS_DSP_ACC; i++) {
9674 cpu_HI[i] = tcg_global_mem_new(TCG_AREG0,
9675 offsetof(CPUState, active_tc.HI[i]),
9676 regnames_HI[i]);
9677 cpu_LO[i] = tcg_global_mem_new(TCG_AREG0,
9678 offsetof(CPUState, active_tc.LO[i]),
9679 regnames_LO[i]);
9680 cpu_ACX[i] = tcg_global_mem_new(TCG_AREG0,
9681 offsetof(CPUState, active_tc.ACX[i]),
9682 regnames_ACX[i]);
9684 cpu_dspctrl = tcg_global_mem_new(TCG_AREG0,
9685 offsetof(CPUState, active_tc.DSPControl),
9686 "DSPControl");
9687 bcond = tcg_global_mem_new(TCG_AREG0,
9688 offsetof(CPUState, bcond), "bcond");
9689 btarget = tcg_global_mem_new(TCG_AREG0,
9690 offsetof(CPUState, btarget), "btarget");
9691 hflags = tcg_global_mem_new_i32(TCG_AREG0,
9692 offsetof(CPUState, hflags), "hflags");
9694 fpu_fcr0 = tcg_global_mem_new_i32(TCG_AREG0,
9695 offsetof(CPUState, active_fpu.fcr0),
9696 "fcr0");
9697 fpu_fcr31 = tcg_global_mem_new_i32(TCG_AREG0,
9698 offsetof(CPUState, active_fpu.fcr31),
9699 "fcr31");
9701 /* register helpers */
9702 #define GEN_HELPER 2
9703 #include "helper.h"
9705 inited = 1;
9708 #include "translate_init.c"
9710 CPUMIPSState *cpu_mips_init (const char *cpu_model)
9712 CPUMIPSState *env;
9713 const mips_def_t *def;
9715 def = cpu_mips_find_by_name(cpu_model);
9716 if (!def)
9717 return NULL;
9718 env = qemu_mallocz(sizeof(CPUMIPSState));
9719 env->cpu_model = def;
9720 env->cpu_model_str = cpu_model;
9722 cpu_exec_init(env);
9723 #ifndef CONFIG_USER_ONLY
9724 mmu_init(env, def);
9725 #endif
9726 fpu_init(env, def);
9727 mvp_init(env, def);
9728 mips_tcg_init();
9729 cpu_reset(env);
9730 qemu_init_vcpu(env);
9731 return env;
9734 void cpu_reset (CPUMIPSState *env)
9736 if (qemu_loglevel_mask(CPU_LOG_RESET)) {
9737 qemu_log("CPU Reset (CPU %d)\n", env->cpu_index);
9738 log_cpu_state(env, 0);
9741 memset(env, 0, offsetof(CPUMIPSState, breakpoints));
9742 tlb_flush(env, 1);
9744 /* Reset registers to their default values */
9745 env->CP0_PRid = env->cpu_model->CP0_PRid;
9746 env->CP0_Config0 = env->cpu_model->CP0_Config0;
9747 #ifdef TARGET_WORDS_BIGENDIAN
9748 env->CP0_Config0 |= (1 << CP0C0_BE);
9749 #endif
9750 env->CP0_Config1 = env->cpu_model->CP0_Config1;
9751 env->CP0_Config2 = env->cpu_model->CP0_Config2;
9752 env->CP0_Config3 = env->cpu_model->CP0_Config3;
9753 env->CP0_Config6 = env->cpu_model->CP0_Config6;
9754 env->CP0_Config7 = env->cpu_model->CP0_Config7;
9755 env->CP0_LLAddr_rw_bitmask = env->cpu_model->CP0_LLAddr_rw_bitmask
9756 << env->cpu_model->CP0_LLAddr_shift;
9757 env->CP0_LLAddr_shift = env->cpu_model->CP0_LLAddr_shift;
9758 env->SYNCI_Step = env->cpu_model->SYNCI_Step;
9759 env->CCRes = env->cpu_model->CCRes;
9760 env->CP0_Status_rw_bitmask = env->cpu_model->CP0_Status_rw_bitmask;
9761 env->CP0_TCStatus_rw_bitmask = env->cpu_model->CP0_TCStatus_rw_bitmask;
9762 env->CP0_SRSCtl = env->cpu_model->CP0_SRSCtl;
9763 env->current_tc = 0;
9764 env->SEGBITS = env->cpu_model->SEGBITS;
9765 env->SEGMask = (target_ulong)((1ULL << env->cpu_model->SEGBITS) - 1);
9766 #if defined(TARGET_MIPS64)
9767 if (env->cpu_model->insn_flags & ISA_MIPS3) {
9768 env->SEGMask |= 3ULL << 62;
9770 #endif
9771 env->PABITS = env->cpu_model->PABITS;
9772 env->PAMask = (target_ulong)((1ULL << env->cpu_model->PABITS) - 1);
9773 env->CP0_SRSConf0_rw_bitmask = env->cpu_model->CP0_SRSConf0_rw_bitmask;
9774 env->CP0_SRSConf0 = env->cpu_model->CP0_SRSConf0;
9775 env->CP0_SRSConf1_rw_bitmask = env->cpu_model->CP0_SRSConf1_rw_bitmask;
9776 env->CP0_SRSConf1 = env->cpu_model->CP0_SRSConf1;
9777 env->CP0_SRSConf2_rw_bitmask = env->cpu_model->CP0_SRSConf2_rw_bitmask;
9778 env->CP0_SRSConf2 = env->cpu_model->CP0_SRSConf2;
9779 env->CP0_SRSConf3_rw_bitmask = env->cpu_model->CP0_SRSConf3_rw_bitmask;
9780 env->CP0_SRSConf3 = env->cpu_model->CP0_SRSConf3;
9781 env->CP0_SRSConf4_rw_bitmask = env->cpu_model->CP0_SRSConf4_rw_bitmask;
9782 env->CP0_SRSConf4 = env->cpu_model->CP0_SRSConf4;
9783 env->insn_flags = env->cpu_model->insn_flags;
9785 #if defined(CONFIG_USER_ONLY)
9786 env->hflags = MIPS_HFLAG_UM;
9787 /* Enable access to the SYNCI_Step register. */
9788 env->CP0_HWREna |= (1 << 1);
9789 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
9790 env->hflags |= MIPS_HFLAG_FPU;
9792 #ifdef TARGET_MIPS64
9793 if (env->active_fpu.fcr0 & (1 << FCR0_F64)) {
9794 env->hflags |= MIPS_HFLAG_F64;
9796 #endif
9797 #else
9798 if (env->hflags & MIPS_HFLAG_BMASK) {
9799 /* If the exception was raised from a delay slot,
9800 come back to the jump. */
9801 env->CP0_ErrorEPC = env->active_tc.PC - 4;
9802 } else {
9803 env->CP0_ErrorEPC = env->active_tc.PC;
9805 env->active_tc.PC = (int32_t)0xBFC00000;
9806 env->CP0_Random = env->tlb->nb_tlb - 1;
9807 env->tlb->tlb_in_use = env->tlb->nb_tlb;
9808 env->CP0_Wired = 0;
9809 /* SMP not implemented */
9810 env->CP0_EBase = 0x80000000;
9811 env->CP0_Status = (1 << CP0St_BEV) | (1 << CP0St_ERL);
9812 /* vectored interrupts not implemented, timer on int 7,
9813 no performance counters. */
9814 env->CP0_IntCtl = 0xe0000000;
9816 int i;
9818 for (i = 0; i < 7; i++) {
9819 env->CP0_WatchLo[i] = 0;
9820 env->CP0_WatchHi[i] = 0x80000000;
9822 env->CP0_WatchLo[7] = 0;
9823 env->CP0_WatchHi[7] = 0;
9825 /* Count register increments in debug mode, EJTAG version 1 */
9826 env->CP0_Debug = (1 << CP0DB_CNT) | (0x1 << CP0DB_VER);
9827 env->hflags = MIPS_HFLAG_CP0;
9828 #endif
9829 #if defined(TARGET_MIPS64)
9830 if (env->cpu_model->insn_flags & ISA_MIPS3) {
9831 env->hflags |= MIPS_HFLAG_64;
9833 #endif
9834 env->exception_index = EXCP_NONE;
9837 void gen_pc_load(CPUState *env, TranslationBlock *tb,
9838 unsigned long searched_pc, int pc_pos, void *puc)
9840 env->active_tc.PC = gen_opc_pc[pc_pos];
9841 env->hflags &= ~MIPS_HFLAG_BMASK;
9842 env->hflags |= gen_opc_hflags[pc_pos];