target-mips: mips16 cleanups
[qemu.git] / target-mips / translate.c
blob78783a8d51ae525853318bdb8a913a0ae6d7978c
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_JALS = OPC_JAL | 0x5,
72 OPC_BEQ = (0x04 << 26), /* Unconditional if rs = rt = 0 (B) */
73 OPC_BEQL = (0x14 << 26),
74 OPC_BNE = (0x05 << 26),
75 OPC_BNEL = (0x15 << 26),
76 OPC_BLEZ = (0x06 << 26),
77 OPC_BLEZL = (0x16 << 26),
78 OPC_BGTZ = (0x07 << 26),
79 OPC_BGTZL = (0x17 << 26),
80 OPC_JALX = (0x1D << 26), /* MIPS 16 only */
81 OPC_JALXS = OPC_JALX | 0x5,
82 /* Load and stores */
83 OPC_LDL = (0x1A << 26),
84 OPC_LDR = (0x1B << 26),
85 OPC_LB = (0x20 << 26),
86 OPC_LH = (0x21 << 26),
87 OPC_LWL = (0x22 << 26),
88 OPC_LW = (0x23 << 26),
89 OPC_LWPC = OPC_LW | 0x5,
90 OPC_LBU = (0x24 << 26),
91 OPC_LHU = (0x25 << 26),
92 OPC_LWR = (0x26 << 26),
93 OPC_LWU = (0x27 << 26),
94 OPC_SB = (0x28 << 26),
95 OPC_SH = (0x29 << 26),
96 OPC_SWL = (0x2A << 26),
97 OPC_SW = (0x2B << 26),
98 OPC_SDL = (0x2C << 26),
99 OPC_SDR = (0x2D << 26),
100 OPC_SWR = (0x2E << 26),
101 OPC_LL = (0x30 << 26),
102 OPC_LLD = (0x34 << 26),
103 OPC_LD = (0x37 << 26),
104 OPC_LDPC = OPC_LD | 0x5,
105 OPC_SC = (0x38 << 26),
106 OPC_SCD = (0x3C << 26),
107 OPC_SD = (0x3F << 26),
108 /* Floating point load/store */
109 OPC_LWC1 = (0x31 << 26),
110 OPC_LWC2 = (0x32 << 26),
111 OPC_LDC1 = (0x35 << 26),
112 OPC_LDC2 = (0x36 << 26),
113 OPC_SWC1 = (0x39 << 26),
114 OPC_SWC2 = (0x3A << 26),
115 OPC_SDC1 = (0x3D << 26),
116 OPC_SDC2 = (0x3E << 26),
117 /* MDMX ASE specific */
118 OPC_MDMX = (0x1E << 26),
119 /* Cache and prefetch */
120 OPC_CACHE = (0x2F << 26),
121 OPC_PREF = (0x33 << 26),
122 /* Reserved major opcode */
123 OPC_MAJOR3B_RESERVED = (0x3B << 26),
126 /* MIPS special opcodes */
127 #define MASK_SPECIAL(op) MASK_OP_MAJOR(op) | (op & 0x3F)
129 enum {
130 /* Shifts */
131 OPC_SLL = 0x00 | OPC_SPECIAL,
132 /* NOP is SLL r0, r0, 0 */
133 /* SSNOP is SLL r0, r0, 1 */
134 /* EHB is SLL r0, r0, 3 */
135 OPC_SRL = 0x02 | OPC_SPECIAL, /* also ROTR */
136 OPC_ROTR = OPC_SRL | (1 << 21),
137 OPC_SRA = 0x03 | OPC_SPECIAL,
138 OPC_SLLV = 0x04 | OPC_SPECIAL,
139 OPC_SRLV = 0x06 | OPC_SPECIAL, /* also ROTRV */
140 OPC_ROTRV = OPC_SRLV | (1 << 6),
141 OPC_SRAV = 0x07 | OPC_SPECIAL,
142 OPC_DSLLV = 0x14 | OPC_SPECIAL,
143 OPC_DSRLV = 0x16 | OPC_SPECIAL, /* also DROTRV */
144 OPC_DROTRV = OPC_DSRLV | (1 << 6),
145 OPC_DSRAV = 0x17 | OPC_SPECIAL,
146 OPC_DSLL = 0x38 | OPC_SPECIAL,
147 OPC_DSRL = 0x3A | OPC_SPECIAL, /* also DROTR */
148 OPC_DROTR = OPC_DSRL | (1 << 21),
149 OPC_DSRA = 0x3B | OPC_SPECIAL,
150 OPC_DSLL32 = 0x3C | OPC_SPECIAL,
151 OPC_DSRL32 = 0x3E | OPC_SPECIAL, /* also DROTR32 */
152 OPC_DROTR32 = OPC_DSRL32 | (1 << 21),
153 OPC_DSRA32 = 0x3F | OPC_SPECIAL,
154 /* Multiplication / division */
155 OPC_MULT = 0x18 | OPC_SPECIAL,
156 OPC_MULTU = 0x19 | OPC_SPECIAL,
157 OPC_DIV = 0x1A | OPC_SPECIAL,
158 OPC_DIVU = 0x1B | OPC_SPECIAL,
159 OPC_DMULT = 0x1C | OPC_SPECIAL,
160 OPC_DMULTU = 0x1D | OPC_SPECIAL,
161 OPC_DDIV = 0x1E | OPC_SPECIAL,
162 OPC_DDIVU = 0x1F | OPC_SPECIAL,
163 /* 2 registers arithmetic / logic */
164 OPC_ADD = 0x20 | OPC_SPECIAL,
165 OPC_ADDU = 0x21 | OPC_SPECIAL,
166 OPC_SUB = 0x22 | OPC_SPECIAL,
167 OPC_SUBU = 0x23 | OPC_SPECIAL,
168 OPC_AND = 0x24 | OPC_SPECIAL,
169 OPC_OR = 0x25 | OPC_SPECIAL,
170 OPC_XOR = 0x26 | OPC_SPECIAL,
171 OPC_NOR = 0x27 | OPC_SPECIAL,
172 OPC_SLT = 0x2A | OPC_SPECIAL,
173 OPC_SLTU = 0x2B | OPC_SPECIAL,
174 OPC_DADD = 0x2C | OPC_SPECIAL,
175 OPC_DADDU = 0x2D | OPC_SPECIAL,
176 OPC_DSUB = 0x2E | OPC_SPECIAL,
177 OPC_DSUBU = 0x2F | OPC_SPECIAL,
178 /* Jumps */
179 OPC_JR = 0x08 | OPC_SPECIAL, /* Also JR.HB */
180 OPC_JALR = 0x09 | OPC_SPECIAL, /* Also JALR.HB */
181 OPC_JALRC = OPC_JALR | (0x5 << 6),
182 OPC_JALRS = 0x10 | OPC_SPECIAL | (0x5 << 6),
183 /* Traps */
184 OPC_TGE = 0x30 | OPC_SPECIAL,
185 OPC_TGEU = 0x31 | OPC_SPECIAL,
186 OPC_TLT = 0x32 | OPC_SPECIAL,
187 OPC_TLTU = 0x33 | OPC_SPECIAL,
188 OPC_TEQ = 0x34 | OPC_SPECIAL,
189 OPC_TNE = 0x36 | OPC_SPECIAL,
190 /* HI / LO registers load & stores */
191 OPC_MFHI = 0x10 | OPC_SPECIAL,
192 OPC_MTHI = 0x11 | OPC_SPECIAL,
193 OPC_MFLO = 0x12 | OPC_SPECIAL,
194 OPC_MTLO = 0x13 | OPC_SPECIAL,
195 /* Conditional moves */
196 OPC_MOVZ = 0x0A | OPC_SPECIAL,
197 OPC_MOVN = 0x0B | OPC_SPECIAL,
199 OPC_MOVCI = 0x01 | OPC_SPECIAL,
201 /* Special */
202 OPC_PMON = 0x05 | OPC_SPECIAL, /* unofficial */
203 OPC_SYSCALL = 0x0C | OPC_SPECIAL,
204 OPC_BREAK = 0x0D | OPC_SPECIAL,
205 OPC_SPIM = 0x0E | OPC_SPECIAL, /* unofficial */
206 OPC_SYNC = 0x0F | OPC_SPECIAL,
208 OPC_SPECIAL15_RESERVED = 0x15 | OPC_SPECIAL,
209 OPC_SPECIAL28_RESERVED = 0x28 | OPC_SPECIAL,
210 OPC_SPECIAL29_RESERVED = 0x29 | OPC_SPECIAL,
211 OPC_SPECIAL35_RESERVED = 0x35 | OPC_SPECIAL,
212 OPC_SPECIAL37_RESERVED = 0x37 | OPC_SPECIAL,
213 OPC_SPECIAL39_RESERVED = 0x39 | OPC_SPECIAL,
214 OPC_SPECIAL3D_RESERVED = 0x3D | OPC_SPECIAL,
217 /* Multiplication variants of the vr54xx. */
218 #define MASK_MUL_VR54XX(op) MASK_SPECIAL(op) | (op & (0x1F << 6))
220 enum {
221 OPC_VR54XX_MULS = (0x03 << 6) | OPC_MULT,
222 OPC_VR54XX_MULSU = (0x03 << 6) | OPC_MULTU,
223 OPC_VR54XX_MACC = (0x05 << 6) | OPC_MULT,
224 OPC_VR54XX_MACCU = (0x05 << 6) | OPC_MULTU,
225 OPC_VR54XX_MSAC = (0x07 << 6) | OPC_MULT,
226 OPC_VR54XX_MSACU = (0x07 << 6) | OPC_MULTU,
227 OPC_VR54XX_MULHI = (0x09 << 6) | OPC_MULT,
228 OPC_VR54XX_MULHIU = (0x09 << 6) | OPC_MULTU,
229 OPC_VR54XX_MULSHI = (0x0B << 6) | OPC_MULT,
230 OPC_VR54XX_MULSHIU = (0x0B << 6) | OPC_MULTU,
231 OPC_VR54XX_MACCHI = (0x0D << 6) | OPC_MULT,
232 OPC_VR54XX_MACCHIU = (0x0D << 6) | OPC_MULTU,
233 OPC_VR54XX_MSACHI = (0x0F << 6) | OPC_MULT,
234 OPC_VR54XX_MSACHIU = (0x0F << 6) | OPC_MULTU,
237 /* REGIMM (rt field) opcodes */
238 #define MASK_REGIMM(op) MASK_OP_MAJOR(op) | (op & (0x1F << 16))
240 enum {
241 OPC_BLTZ = (0x00 << 16) | OPC_REGIMM,
242 OPC_BLTZL = (0x02 << 16) | OPC_REGIMM,
243 OPC_BGEZ = (0x01 << 16) | OPC_REGIMM,
244 OPC_BGEZL = (0x03 << 16) | OPC_REGIMM,
245 OPC_BLTZAL = (0x10 << 16) | OPC_REGIMM,
246 OPC_BLTZALL = (0x12 << 16) | OPC_REGIMM,
247 OPC_BGEZAL = (0x11 << 16) | OPC_REGIMM,
248 OPC_BGEZALL = (0x13 << 16) | OPC_REGIMM,
249 OPC_TGEI = (0x08 << 16) | OPC_REGIMM,
250 OPC_TGEIU = (0x09 << 16) | OPC_REGIMM,
251 OPC_TLTI = (0x0A << 16) | OPC_REGIMM,
252 OPC_TLTIU = (0x0B << 16) | OPC_REGIMM,
253 OPC_TEQI = (0x0C << 16) | OPC_REGIMM,
254 OPC_TNEI = (0x0E << 16) | OPC_REGIMM,
255 OPC_SYNCI = (0x1F << 16) | OPC_REGIMM,
258 /* Special2 opcodes */
259 #define MASK_SPECIAL2(op) MASK_OP_MAJOR(op) | (op & 0x3F)
261 enum {
262 /* Multiply & xxx operations */
263 OPC_MADD = 0x00 | OPC_SPECIAL2,
264 OPC_MADDU = 0x01 | OPC_SPECIAL2,
265 OPC_MUL = 0x02 | OPC_SPECIAL2,
266 OPC_MSUB = 0x04 | OPC_SPECIAL2,
267 OPC_MSUBU = 0x05 | OPC_SPECIAL2,
268 /* Misc */
269 OPC_CLZ = 0x20 | OPC_SPECIAL2,
270 OPC_CLO = 0x21 | OPC_SPECIAL2,
271 OPC_DCLZ = 0x24 | OPC_SPECIAL2,
272 OPC_DCLO = 0x25 | OPC_SPECIAL2,
273 /* Special */
274 OPC_SDBBP = 0x3F | OPC_SPECIAL2,
277 /* Special3 opcodes */
278 #define MASK_SPECIAL3(op) MASK_OP_MAJOR(op) | (op & 0x3F)
280 enum {
281 OPC_EXT = 0x00 | OPC_SPECIAL3,
282 OPC_DEXTM = 0x01 | OPC_SPECIAL3,
283 OPC_DEXTU = 0x02 | OPC_SPECIAL3,
284 OPC_DEXT = 0x03 | OPC_SPECIAL3,
285 OPC_INS = 0x04 | OPC_SPECIAL3,
286 OPC_DINSM = 0x05 | OPC_SPECIAL3,
287 OPC_DINSU = 0x06 | OPC_SPECIAL3,
288 OPC_DINS = 0x07 | OPC_SPECIAL3,
289 OPC_FORK = 0x08 | OPC_SPECIAL3,
290 OPC_YIELD = 0x09 | OPC_SPECIAL3,
291 OPC_BSHFL = 0x20 | OPC_SPECIAL3,
292 OPC_DBSHFL = 0x24 | OPC_SPECIAL3,
293 OPC_RDHWR = 0x3B | OPC_SPECIAL3,
296 /* BSHFL opcodes */
297 #define MASK_BSHFL(op) MASK_SPECIAL3(op) | (op & (0x1F << 6))
299 enum {
300 OPC_WSBH = (0x02 << 6) | OPC_BSHFL,
301 OPC_SEB = (0x10 << 6) | OPC_BSHFL,
302 OPC_SEH = (0x18 << 6) | OPC_BSHFL,
305 /* DBSHFL opcodes */
306 #define MASK_DBSHFL(op) MASK_SPECIAL3(op) | (op & (0x1F << 6))
308 enum {
309 OPC_DSBH = (0x02 << 6) | OPC_DBSHFL,
310 OPC_DSHD = (0x05 << 6) | OPC_DBSHFL,
313 /* Coprocessor 0 (rs field) */
314 #define MASK_CP0(op) MASK_OP_MAJOR(op) | (op & (0x1F << 21))
316 enum {
317 OPC_MFC0 = (0x00 << 21) | OPC_CP0,
318 OPC_DMFC0 = (0x01 << 21) | OPC_CP0,
319 OPC_MTC0 = (0x04 << 21) | OPC_CP0,
320 OPC_DMTC0 = (0x05 << 21) | OPC_CP0,
321 OPC_MFTR = (0x08 << 21) | OPC_CP0,
322 OPC_RDPGPR = (0x0A << 21) | OPC_CP0,
323 OPC_MFMC0 = (0x0B << 21) | OPC_CP0,
324 OPC_MTTR = (0x0C << 21) | OPC_CP0,
325 OPC_WRPGPR = (0x0E << 21) | OPC_CP0,
326 OPC_C0 = (0x10 << 21) | OPC_CP0,
327 OPC_C0_FIRST = (0x10 << 21) | OPC_CP0,
328 OPC_C0_LAST = (0x1F << 21) | OPC_CP0,
331 /* MFMC0 opcodes */
332 #define MASK_MFMC0(op) MASK_CP0(op) | (op & 0xFFFF)
334 enum {
335 OPC_DMT = 0x01 | (0 << 5) | (0x0F << 6) | (0x01 << 11) | OPC_MFMC0,
336 OPC_EMT = 0x01 | (1 << 5) | (0x0F << 6) | (0x01 << 11) | OPC_MFMC0,
337 OPC_DVPE = 0x01 | (0 << 5) | OPC_MFMC0,
338 OPC_EVPE = 0x01 | (1 << 5) | OPC_MFMC0,
339 OPC_DI = (0 << 5) | (0x0C << 11) | OPC_MFMC0,
340 OPC_EI = (1 << 5) | (0x0C << 11) | OPC_MFMC0,
343 /* Coprocessor 0 (with rs == C0) */
344 #define MASK_C0(op) MASK_CP0(op) | (op & 0x3F)
346 enum {
347 OPC_TLBR = 0x01 | OPC_C0,
348 OPC_TLBWI = 0x02 | OPC_C0,
349 OPC_TLBWR = 0x06 | OPC_C0,
350 OPC_TLBP = 0x08 | OPC_C0,
351 OPC_RFE = 0x10 | OPC_C0,
352 OPC_ERET = 0x18 | OPC_C0,
353 OPC_DERET = 0x1F | OPC_C0,
354 OPC_WAIT = 0x20 | OPC_C0,
357 /* Coprocessor 1 (rs field) */
358 #define MASK_CP1(op) MASK_OP_MAJOR(op) | (op & (0x1F << 21))
360 /* Values for the fmt field in FP instructions */
361 enum {
362 /* 0 - 15 are reserved */
363 FMT_S = 16, /* single fp */
364 FMT_D = 17, /* double fp */
365 FMT_E = 18, /* extended fp */
366 FMT_Q = 19, /* quad fp */
367 FMT_W = 20, /* 32-bit fixed */
368 FMT_L = 21, /* 64-bit fixed */
369 FMT_PS = 22, /* paired single fp */
370 /* 23 - 31 are reserved */
373 enum {
374 OPC_MFC1 = (0x00 << 21) | OPC_CP1,
375 OPC_DMFC1 = (0x01 << 21) | OPC_CP1,
376 OPC_CFC1 = (0x02 << 21) | OPC_CP1,
377 OPC_MFHC1 = (0x03 << 21) | OPC_CP1,
378 OPC_MTC1 = (0x04 << 21) | OPC_CP1,
379 OPC_DMTC1 = (0x05 << 21) | OPC_CP1,
380 OPC_CTC1 = (0x06 << 21) | OPC_CP1,
381 OPC_MTHC1 = (0x07 << 21) | OPC_CP1,
382 OPC_BC1 = (0x08 << 21) | OPC_CP1, /* bc */
383 OPC_BC1ANY2 = (0x09 << 21) | OPC_CP1,
384 OPC_BC1ANY4 = (0x0A << 21) | OPC_CP1,
385 OPC_S_FMT = (FMT_S << 21) | OPC_CP1,
386 OPC_D_FMT = (FMT_D << 21) | OPC_CP1,
387 OPC_E_FMT = (FMT_E << 21) | OPC_CP1,
388 OPC_Q_FMT = (FMT_Q << 21) | OPC_CP1,
389 OPC_W_FMT = (FMT_W << 21) | OPC_CP1,
390 OPC_L_FMT = (FMT_L << 21) | OPC_CP1,
391 OPC_PS_FMT = (FMT_PS << 21) | OPC_CP1,
394 #define MASK_CP1_FUNC(op) MASK_CP1(op) | (op & 0x3F)
395 #define MASK_BC1(op) MASK_CP1(op) | (op & (0x3 << 16))
397 enum {
398 OPC_BC1F = (0x00 << 16) | OPC_BC1,
399 OPC_BC1T = (0x01 << 16) | OPC_BC1,
400 OPC_BC1FL = (0x02 << 16) | OPC_BC1,
401 OPC_BC1TL = (0x03 << 16) | OPC_BC1,
404 enum {
405 OPC_BC1FANY2 = (0x00 << 16) | OPC_BC1ANY2,
406 OPC_BC1TANY2 = (0x01 << 16) | OPC_BC1ANY2,
409 enum {
410 OPC_BC1FANY4 = (0x00 << 16) | OPC_BC1ANY4,
411 OPC_BC1TANY4 = (0x01 << 16) | OPC_BC1ANY4,
414 #define MASK_CP2(op) MASK_OP_MAJOR(op) | (op & (0x1F << 21))
416 enum {
417 OPC_MFC2 = (0x00 << 21) | OPC_CP2,
418 OPC_DMFC2 = (0x01 << 21) | OPC_CP2,
419 OPC_CFC2 = (0x02 << 21) | OPC_CP2,
420 OPC_MFHC2 = (0x03 << 21) | OPC_CP2,
421 OPC_MTC2 = (0x04 << 21) | OPC_CP2,
422 OPC_DMTC2 = (0x05 << 21) | OPC_CP2,
423 OPC_CTC2 = (0x06 << 21) | OPC_CP2,
424 OPC_MTHC2 = (0x07 << 21) | OPC_CP2,
425 OPC_BC2 = (0x08 << 21) | OPC_CP2,
428 #define MASK_CP3(op) MASK_OP_MAJOR(op) | (op & 0x3F)
430 enum {
431 OPC_LWXC1 = 0x00 | OPC_CP3,
432 OPC_LDXC1 = 0x01 | OPC_CP3,
433 OPC_LUXC1 = 0x05 | OPC_CP3,
434 OPC_SWXC1 = 0x08 | OPC_CP3,
435 OPC_SDXC1 = 0x09 | OPC_CP3,
436 OPC_SUXC1 = 0x0D | OPC_CP3,
437 OPC_PREFX = 0x0F | OPC_CP3,
438 OPC_ALNV_PS = 0x1E | OPC_CP3,
439 OPC_MADD_S = 0x20 | OPC_CP3,
440 OPC_MADD_D = 0x21 | OPC_CP3,
441 OPC_MADD_PS = 0x26 | OPC_CP3,
442 OPC_MSUB_S = 0x28 | OPC_CP3,
443 OPC_MSUB_D = 0x29 | OPC_CP3,
444 OPC_MSUB_PS = 0x2E | OPC_CP3,
445 OPC_NMADD_S = 0x30 | OPC_CP3,
446 OPC_NMADD_D = 0x31 | OPC_CP3,
447 OPC_NMADD_PS= 0x36 | OPC_CP3,
448 OPC_NMSUB_S = 0x38 | OPC_CP3,
449 OPC_NMSUB_D = 0x39 | OPC_CP3,
450 OPC_NMSUB_PS= 0x3E | OPC_CP3,
453 /* global register indices */
454 static TCGv_ptr cpu_env;
455 static TCGv cpu_gpr[32], cpu_PC;
456 static TCGv cpu_HI[MIPS_DSP_ACC], cpu_LO[MIPS_DSP_ACC], cpu_ACX[MIPS_DSP_ACC];
457 static TCGv cpu_dspctrl, btarget, bcond;
458 static TCGv_i32 hflags;
459 static TCGv_i32 fpu_fcr0, fpu_fcr31;
461 static uint32_t gen_opc_hflags[OPC_BUF_SIZE];
463 #include "gen-icount.h"
465 #define gen_helper_0i(name, arg) do { \
466 TCGv_i32 helper_tmp = tcg_const_i32(arg); \
467 gen_helper_##name(helper_tmp); \
468 tcg_temp_free_i32(helper_tmp); \
469 } while(0)
471 #define gen_helper_1i(name, arg1, arg2) do { \
472 TCGv_i32 helper_tmp = tcg_const_i32(arg2); \
473 gen_helper_##name(arg1, helper_tmp); \
474 tcg_temp_free_i32(helper_tmp); \
475 } while(0)
477 #define gen_helper_2i(name, arg1, arg2, arg3) do { \
478 TCGv_i32 helper_tmp = tcg_const_i32(arg3); \
479 gen_helper_##name(arg1, arg2, helper_tmp); \
480 tcg_temp_free_i32(helper_tmp); \
481 } while(0)
483 #define gen_helper_3i(name, arg1, arg2, arg3, arg4) do { \
484 TCGv_i32 helper_tmp = tcg_const_i32(arg4); \
485 gen_helper_##name(arg1, arg2, arg3, helper_tmp); \
486 tcg_temp_free_i32(helper_tmp); \
487 } while(0)
489 typedef struct DisasContext {
490 struct TranslationBlock *tb;
491 target_ulong pc, saved_pc;
492 uint32_t opcode;
493 int singlestep_enabled;
494 /* Routine used to access memory */
495 int mem_idx;
496 uint32_t hflags, saved_hflags;
497 int bstate;
498 target_ulong btarget;
499 } DisasContext;
501 enum {
502 BS_NONE = 0, /* We go out of the TB without reaching a branch or an
503 * exception condition */
504 BS_STOP = 1, /* We want to stop translation for any reason */
505 BS_BRANCH = 2, /* We reached a branch condition */
506 BS_EXCP = 3, /* We reached an exception condition */
509 static const char *regnames[] =
510 { "r0", "at", "v0", "v1", "a0", "a1", "a2", "a3",
511 "t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7",
512 "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7",
513 "t8", "t9", "k0", "k1", "gp", "sp", "s8", "ra", };
515 static const char *regnames_HI[] =
516 { "HI0", "HI1", "HI2", "HI3", };
518 static const char *regnames_LO[] =
519 { "LO0", "LO1", "LO2", "LO3", };
521 static const char *regnames_ACX[] =
522 { "ACX0", "ACX1", "ACX2", "ACX3", };
524 static const char *fregnames[] =
525 { "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7",
526 "f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15",
527 "f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23",
528 "f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31", };
530 #ifdef MIPS_DEBUG_DISAS
531 #define MIPS_DEBUG(fmt, ...) \
532 qemu_log_mask(CPU_LOG_TB_IN_ASM, \
533 TARGET_FMT_lx ": %08x " fmt "\n", \
534 ctx->pc, ctx->opcode , ## __VA_ARGS__)
535 #define LOG_DISAS(...) qemu_log_mask(CPU_LOG_TB_IN_ASM, ## __VA_ARGS__)
536 #else
537 #define MIPS_DEBUG(fmt, ...) do { } while(0)
538 #define LOG_DISAS(...) do { } while (0)
539 #endif
541 #define MIPS_INVAL(op) \
542 do { \
543 MIPS_DEBUG("Invalid %s %03x %03x %03x", op, ctx->opcode >> 26, \
544 ctx->opcode & 0x3F, ((ctx->opcode >> 16) & 0x1F)); \
545 } while (0)
547 /* General purpose registers moves. */
548 static inline void gen_load_gpr (TCGv t, int reg)
550 if (reg == 0)
551 tcg_gen_movi_tl(t, 0);
552 else
553 tcg_gen_mov_tl(t, cpu_gpr[reg]);
556 static inline void gen_store_gpr (TCGv t, int reg)
558 if (reg != 0)
559 tcg_gen_mov_tl(cpu_gpr[reg], t);
562 /* Moves to/from ACX register. */
563 static inline void gen_load_ACX (TCGv t, int reg)
565 tcg_gen_mov_tl(t, cpu_ACX[reg]);
568 static inline void gen_store_ACX (TCGv t, int reg)
570 tcg_gen_mov_tl(cpu_ACX[reg], t);
573 /* Moves to/from shadow registers. */
574 static inline void gen_load_srsgpr (int from, int to)
576 TCGv t0 = tcg_temp_new();
578 if (from == 0)
579 tcg_gen_movi_tl(t0, 0);
580 else {
581 TCGv_i32 t2 = tcg_temp_new_i32();
582 TCGv_ptr addr = tcg_temp_new_ptr();
584 tcg_gen_ld_i32(t2, cpu_env, offsetof(CPUState, CP0_SRSCtl));
585 tcg_gen_shri_i32(t2, t2, CP0SRSCtl_PSS);
586 tcg_gen_andi_i32(t2, t2, 0xf);
587 tcg_gen_muli_i32(t2, t2, sizeof(target_ulong) * 32);
588 tcg_gen_ext_i32_ptr(addr, t2);
589 tcg_gen_add_ptr(addr, cpu_env, addr);
591 tcg_gen_ld_tl(t0, addr, sizeof(target_ulong) * from);
592 tcg_temp_free_ptr(addr);
593 tcg_temp_free_i32(t2);
595 gen_store_gpr(t0, to);
596 tcg_temp_free(t0);
599 static inline void gen_store_srsgpr (int from, int to)
601 if (to != 0) {
602 TCGv t0 = tcg_temp_new();
603 TCGv_i32 t2 = tcg_temp_new_i32();
604 TCGv_ptr addr = tcg_temp_new_ptr();
606 gen_load_gpr(t0, from);
607 tcg_gen_ld_i32(t2, cpu_env, offsetof(CPUState, CP0_SRSCtl));
608 tcg_gen_shri_i32(t2, t2, CP0SRSCtl_PSS);
609 tcg_gen_andi_i32(t2, t2, 0xf);
610 tcg_gen_muli_i32(t2, t2, sizeof(target_ulong) * 32);
611 tcg_gen_ext_i32_ptr(addr, t2);
612 tcg_gen_add_ptr(addr, cpu_env, addr);
614 tcg_gen_st_tl(t0, addr, sizeof(target_ulong) * to);
615 tcg_temp_free_ptr(addr);
616 tcg_temp_free_i32(t2);
617 tcg_temp_free(t0);
621 /* Floating point register moves. */
622 static inline void gen_load_fpr32 (TCGv_i32 t, int reg)
624 tcg_gen_ld_i32(t, cpu_env, offsetof(CPUState, active_fpu.fpr[reg].w[FP_ENDIAN_IDX]));
627 static inline void gen_store_fpr32 (TCGv_i32 t, int reg)
629 tcg_gen_st_i32(t, cpu_env, offsetof(CPUState, active_fpu.fpr[reg].w[FP_ENDIAN_IDX]));
632 static inline void gen_load_fpr32h (TCGv_i32 t, int reg)
634 tcg_gen_ld_i32(t, cpu_env, offsetof(CPUState, active_fpu.fpr[reg].w[!FP_ENDIAN_IDX]));
637 static inline void gen_store_fpr32h (TCGv_i32 t, int reg)
639 tcg_gen_st_i32(t, cpu_env, offsetof(CPUState, active_fpu.fpr[reg].w[!FP_ENDIAN_IDX]));
642 static inline void gen_load_fpr64 (DisasContext *ctx, TCGv_i64 t, int reg)
644 if (ctx->hflags & MIPS_HFLAG_F64) {
645 tcg_gen_ld_i64(t, cpu_env, offsetof(CPUState, active_fpu.fpr[reg].d));
646 } else {
647 TCGv_i32 t0 = tcg_temp_new_i32();
648 TCGv_i32 t1 = tcg_temp_new_i32();
649 gen_load_fpr32(t0, reg & ~1);
650 gen_load_fpr32(t1, reg | 1);
651 tcg_gen_concat_i32_i64(t, t0, t1);
652 tcg_temp_free_i32(t0);
653 tcg_temp_free_i32(t1);
657 static inline void gen_store_fpr64 (DisasContext *ctx, TCGv_i64 t, int reg)
659 if (ctx->hflags & MIPS_HFLAG_F64) {
660 tcg_gen_st_i64(t, cpu_env, offsetof(CPUState, active_fpu.fpr[reg].d));
661 } else {
662 TCGv_i64 t0 = tcg_temp_new_i64();
663 TCGv_i32 t1 = tcg_temp_new_i32();
664 tcg_gen_trunc_i64_i32(t1, t);
665 gen_store_fpr32(t1, reg & ~1);
666 tcg_gen_shri_i64(t0, t, 32);
667 tcg_gen_trunc_i64_i32(t1, t0);
668 gen_store_fpr32(t1, reg | 1);
669 tcg_temp_free_i32(t1);
670 tcg_temp_free_i64(t0);
674 static inline int get_fp_bit (int cc)
676 if (cc)
677 return 24 + cc;
678 else
679 return 23;
682 /* Tests */
683 static inline void gen_save_pc(target_ulong pc)
685 tcg_gen_movi_tl(cpu_PC, pc);
688 static inline void save_cpu_state (DisasContext *ctx, int do_save_pc)
690 LOG_DISAS("hflags %08x saved %08x\n", ctx->hflags, ctx->saved_hflags);
691 if (do_save_pc && ctx->pc != ctx->saved_pc) {
692 gen_save_pc(ctx->pc);
693 ctx->saved_pc = ctx->pc;
695 if (ctx->hflags != ctx->saved_hflags) {
696 tcg_gen_movi_i32(hflags, ctx->hflags);
697 ctx->saved_hflags = ctx->hflags;
698 switch (ctx->hflags & MIPS_HFLAG_BMASK_BASE) {
699 case MIPS_HFLAG_BR:
700 break;
701 case MIPS_HFLAG_BC:
702 case MIPS_HFLAG_BL:
703 case MIPS_HFLAG_B:
704 tcg_gen_movi_tl(btarget, ctx->btarget);
705 break;
710 static inline void restore_cpu_state (CPUState *env, DisasContext *ctx)
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 ctx->btarget = env->btarget;
720 break;
724 static inline void
725 generate_exception_err (DisasContext *ctx, int excp, int err)
727 TCGv_i32 texcp = tcg_const_i32(excp);
728 TCGv_i32 terr = tcg_const_i32(err);
729 save_cpu_state(ctx, 1);
730 gen_helper_raise_exception_err(texcp, terr);
731 tcg_temp_free_i32(terr);
732 tcg_temp_free_i32(texcp);
735 static inline void
736 generate_exception (DisasContext *ctx, int excp)
738 save_cpu_state(ctx, 1);
739 gen_helper_0i(raise_exception, excp);
742 /* Addresses computation */
743 static inline void gen_op_addr_add (DisasContext *ctx, TCGv ret, TCGv arg0, TCGv arg1)
745 tcg_gen_add_tl(ret, arg0, arg1);
747 #if defined(TARGET_MIPS64)
748 /* For compatibility with 32-bit code, data reference in user mode
749 with Status_UX = 0 should be casted to 32-bit and sign extended.
750 See the MIPS64 PRA manual, section 4.10. */
751 if (((ctx->hflags & MIPS_HFLAG_KSU) == MIPS_HFLAG_UM) &&
752 !(ctx->hflags & MIPS_HFLAG_UX)) {
753 tcg_gen_ext32s_i64(ret, ret);
755 #endif
758 static inline void check_cp0_enabled(DisasContext *ctx)
760 if (unlikely(!(ctx->hflags & MIPS_HFLAG_CP0)))
761 generate_exception_err(ctx, EXCP_CpU, 0);
764 static inline void check_cp1_enabled(DisasContext *ctx)
766 if (unlikely(!(ctx->hflags & MIPS_HFLAG_FPU)))
767 generate_exception_err(ctx, EXCP_CpU, 1);
770 /* Verify that the processor is running with COP1X instructions enabled.
771 This is associated with the nabla symbol in the MIPS32 and MIPS64
772 opcode tables. */
774 static inline void check_cop1x(DisasContext *ctx)
776 if (unlikely(!(ctx->hflags & MIPS_HFLAG_COP1X)))
777 generate_exception(ctx, EXCP_RI);
780 /* Verify that the processor is running with 64-bit floating-point
781 operations enabled. */
783 static inline void check_cp1_64bitmode(DisasContext *ctx)
785 if (unlikely(~ctx->hflags & (MIPS_HFLAG_F64 | MIPS_HFLAG_COP1X)))
786 generate_exception(ctx, EXCP_RI);
790 * Verify if floating point register is valid; an operation is not defined
791 * if bit 0 of any register specification is set and the FR bit in the
792 * Status register equals zero, since the register numbers specify an
793 * even-odd pair of adjacent coprocessor general registers. When the FR bit
794 * in the Status register equals one, both even and odd register numbers
795 * are valid. This limitation exists only for 64 bit wide (d,l,ps) registers.
797 * Multiple 64 bit wide registers can be checked by calling
798 * gen_op_cp1_registers(freg1 | freg2 | ... | fregN);
800 static inline void check_cp1_registers(DisasContext *ctx, int regs)
802 if (unlikely(!(ctx->hflags & MIPS_HFLAG_F64) && (regs & 1)))
803 generate_exception(ctx, EXCP_RI);
806 /* This code generates a "reserved instruction" exception if the
807 CPU does not support the instruction set corresponding to flags. */
808 static inline void check_insn(CPUState *env, DisasContext *ctx, int flags)
810 if (unlikely(!(env->insn_flags & flags)))
811 generate_exception(ctx, EXCP_RI);
814 /* This code generates a "reserved instruction" exception if 64-bit
815 instructions are not enabled. */
816 static inline void check_mips_64(DisasContext *ctx)
818 if (unlikely(!(ctx->hflags & MIPS_HFLAG_64)))
819 generate_exception(ctx, EXCP_RI);
822 /* Define small wrappers for gen_load_fpr* so that we have a uniform
823 calling interface for 32 and 64-bit FPRs. No sense in changing
824 all callers for gen_load_fpr32 when we need the CTX parameter for
825 this one use. */
826 #define gen_ldcmp_fpr32(ctx, x, y) gen_load_fpr32(x, y)
827 #define gen_ldcmp_fpr64(ctx, x, y) gen_load_fpr64(ctx, x, y)
828 #define FOP_CONDS(type, abs, fmt, ifmt, bits) \
829 static inline void gen_cmp ## type ## _ ## fmt(DisasContext *ctx, int n, \
830 int ft, int fs, int cc) \
832 TCGv_i##bits fp0 = tcg_temp_new_i##bits (); \
833 TCGv_i##bits fp1 = tcg_temp_new_i##bits (); \
834 switch (ifmt) { \
835 case FMT_PS: \
836 check_cp1_64bitmode(ctx); \
837 break; \
838 case FMT_D: \
839 if (abs) { \
840 check_cop1x(ctx); \
842 check_cp1_registers(ctx, fs | ft); \
843 break; \
844 case FMT_S: \
845 if (abs) { \
846 check_cop1x(ctx); \
848 break; \
850 gen_ldcmp_fpr##bits (ctx, fp0, fs); \
851 gen_ldcmp_fpr##bits (ctx, fp1, ft); \
852 switch (n) { \
853 case 0: gen_helper_2i(cmp ## type ## _ ## fmt ## _f, fp0, fp1, cc); break;\
854 case 1: gen_helper_2i(cmp ## type ## _ ## fmt ## _un, fp0, fp1, cc); break;\
855 case 2: gen_helper_2i(cmp ## type ## _ ## fmt ## _eq, fp0, fp1, cc); break;\
856 case 3: gen_helper_2i(cmp ## type ## _ ## fmt ## _ueq, fp0, fp1, cc); break;\
857 case 4: gen_helper_2i(cmp ## type ## _ ## fmt ## _olt, fp0, fp1, cc); break;\
858 case 5: gen_helper_2i(cmp ## type ## _ ## fmt ## _ult, fp0, fp1, cc); break;\
859 case 6: gen_helper_2i(cmp ## type ## _ ## fmt ## _ole, fp0, fp1, cc); break;\
860 case 7: gen_helper_2i(cmp ## type ## _ ## fmt ## _ule, fp0, fp1, cc); break;\
861 case 8: gen_helper_2i(cmp ## type ## _ ## fmt ## _sf, fp0, fp1, cc); break;\
862 case 9: gen_helper_2i(cmp ## type ## _ ## fmt ## _ngle, fp0, fp1, cc); break;\
863 case 10: gen_helper_2i(cmp ## type ## _ ## fmt ## _seq, fp0, fp1, cc); break;\
864 case 11: gen_helper_2i(cmp ## type ## _ ## fmt ## _ngl, fp0, fp1, cc); break;\
865 case 12: gen_helper_2i(cmp ## type ## _ ## fmt ## _lt, fp0, fp1, cc); break;\
866 case 13: gen_helper_2i(cmp ## type ## _ ## fmt ## _nge, fp0, fp1, cc); break;\
867 case 14: gen_helper_2i(cmp ## type ## _ ## fmt ## _le, fp0, fp1, cc); break;\
868 case 15: gen_helper_2i(cmp ## type ## _ ## fmt ## _ngt, fp0, fp1, cc); break;\
869 default: abort(); \
871 tcg_temp_free_i##bits (fp0); \
872 tcg_temp_free_i##bits (fp1); \
875 FOP_CONDS(, 0, d, FMT_D, 64)
876 FOP_CONDS(abs, 1, d, FMT_D, 64)
877 FOP_CONDS(, 0, s, FMT_S, 32)
878 FOP_CONDS(abs, 1, s, FMT_S, 32)
879 FOP_CONDS(, 0, ps, FMT_PS, 64)
880 FOP_CONDS(abs, 1, ps, FMT_PS, 64)
881 #undef FOP_CONDS
882 #undef gen_ldcmp_fpr32
883 #undef gen_ldcmp_fpr64
885 /* load/store instructions. */
886 #define OP_LD(insn,fname) \
887 static inline void op_ldst_##insn(TCGv ret, TCGv arg1, DisasContext *ctx) \
889 tcg_gen_qemu_##fname(ret, arg1, ctx->mem_idx); \
891 OP_LD(lb,ld8s);
892 OP_LD(lbu,ld8u);
893 OP_LD(lh,ld16s);
894 OP_LD(lhu,ld16u);
895 OP_LD(lw,ld32s);
896 #if defined(TARGET_MIPS64)
897 OP_LD(lwu,ld32u);
898 OP_LD(ld,ld64);
899 #endif
900 #undef OP_LD
902 #define OP_ST(insn,fname) \
903 static inline void op_ldst_##insn(TCGv arg1, TCGv arg2, DisasContext *ctx) \
905 tcg_gen_qemu_##fname(arg1, arg2, ctx->mem_idx); \
907 OP_ST(sb,st8);
908 OP_ST(sh,st16);
909 OP_ST(sw,st32);
910 #if defined(TARGET_MIPS64)
911 OP_ST(sd,st64);
912 #endif
913 #undef OP_ST
915 #ifdef CONFIG_USER_ONLY
916 #define OP_LD_ATOMIC(insn,fname) \
917 static inline void op_ldst_##insn(TCGv ret, TCGv arg1, DisasContext *ctx) \
919 TCGv t0 = tcg_temp_new(); \
920 tcg_gen_mov_tl(t0, arg1); \
921 tcg_gen_qemu_##fname(ret, arg1, ctx->mem_idx); \
922 tcg_gen_st_tl(t0, cpu_env, offsetof(CPUState, lladdr)); \
923 tcg_gen_st_tl(ret, cpu_env, offsetof(CPUState, llval)); \
924 tcg_temp_free(t0); \
926 #else
927 #define OP_LD_ATOMIC(insn,fname) \
928 static inline void op_ldst_##insn(TCGv ret, TCGv arg1, DisasContext *ctx) \
930 gen_helper_2i(insn, ret, arg1, ctx->mem_idx); \
932 #endif
933 OP_LD_ATOMIC(ll,ld32s);
934 #if defined(TARGET_MIPS64)
935 OP_LD_ATOMIC(lld,ld64);
936 #endif
937 #undef OP_LD_ATOMIC
939 #ifdef CONFIG_USER_ONLY
940 #define OP_ST_ATOMIC(insn,fname,ldname,almask) \
941 static inline void op_ldst_##insn(TCGv arg1, TCGv arg2, int rt, DisasContext *ctx) \
943 TCGv t0 = tcg_temp_new(); \
944 int l1 = gen_new_label(); \
945 int l2 = gen_new_label(); \
947 tcg_gen_andi_tl(t0, arg2, almask); \
948 tcg_gen_brcondi_tl(TCG_COND_EQ, t0, 0, l1); \
949 tcg_gen_st_tl(arg2, cpu_env, offsetof(CPUState, CP0_BadVAddr)); \
950 generate_exception(ctx, EXCP_AdES); \
951 gen_set_label(l1); \
952 tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUState, lladdr)); \
953 tcg_gen_brcond_tl(TCG_COND_NE, arg2, t0, l2); \
954 tcg_gen_movi_tl(t0, rt | ((almask << 3) & 0x20)); \
955 tcg_gen_st_tl(t0, cpu_env, offsetof(CPUState, llreg)); \
956 tcg_gen_st_tl(arg1, cpu_env, offsetof(CPUState, llnewval)); \
957 gen_helper_0i(raise_exception, EXCP_SC); \
958 gen_set_label(l2); \
959 tcg_gen_movi_tl(t0, 0); \
960 gen_store_gpr(t0, rt); \
961 tcg_temp_free(t0); \
963 #else
964 #define OP_ST_ATOMIC(insn,fname,ldname,almask) \
965 static inline void op_ldst_##insn(TCGv arg1, TCGv arg2, int rt, DisasContext *ctx) \
967 TCGv t0 = tcg_temp_new(); \
968 gen_helper_3i(insn, t0, arg1, arg2, ctx->mem_idx); \
969 gen_store_gpr(t0, rt); \
970 tcg_temp_free(t0); \
972 #endif
973 OP_ST_ATOMIC(sc,st32,ld32s,0x3);
974 #if defined(TARGET_MIPS64)
975 OP_ST_ATOMIC(scd,st64,ld64,0x7);
976 #endif
977 #undef OP_ST_ATOMIC
979 static void gen_base_offset_addr (DisasContext *ctx, TCGv addr,
980 int base, int16_t offset)
982 if (base == 0) {
983 tcg_gen_movi_tl(addr, offset);
984 } else if (offset == 0) {
985 gen_load_gpr(addr, base);
986 } else {
987 tcg_gen_movi_tl(addr, offset);
988 gen_op_addr_add(ctx, addr, cpu_gpr[base], addr);
992 static target_ulong pc_relative_pc (DisasContext *ctx)
994 target_ulong pc = ctx->pc;
996 if (ctx->hflags & MIPS_HFLAG_BMASK) {
997 int branch_bytes = ctx->hflags & MIPS_HFLAG_BDS16 ? 2 : 4;
999 pc -= branch_bytes;
1002 pc &= ~(target_ulong)3;
1003 return pc;
1006 /* Load and store */
1007 static void gen_ldst (DisasContext *ctx, uint32_t opc, int rt,
1008 int base, int16_t offset)
1010 const char *opn = "ldst";
1011 TCGv t0 = tcg_temp_new();
1012 TCGv t1 = tcg_temp_new();
1014 gen_base_offset_addr(ctx, t0, base, offset);
1015 /* Don't do NOP if destination is zero: we must perform the actual
1016 memory access. */
1017 switch (opc) {
1018 #if defined(TARGET_MIPS64)
1019 case OPC_LWU:
1020 save_cpu_state(ctx, 0);
1021 op_ldst_lwu(t0, t0, ctx);
1022 gen_store_gpr(t0, rt);
1023 opn = "lwu";
1024 break;
1025 case OPC_LD:
1026 save_cpu_state(ctx, 0);
1027 op_ldst_ld(t0, t0, ctx);
1028 gen_store_gpr(t0, rt);
1029 opn = "ld";
1030 break;
1031 case OPC_LLD:
1032 save_cpu_state(ctx, 0);
1033 op_ldst_lld(t0, t0, ctx);
1034 gen_store_gpr(t0, rt);
1035 opn = "lld";
1036 break;
1037 case OPC_SD:
1038 save_cpu_state(ctx, 0);
1039 gen_load_gpr(t1, rt);
1040 op_ldst_sd(t1, t0, ctx);
1041 opn = "sd";
1042 break;
1043 case OPC_LDL:
1044 save_cpu_state(ctx, 1);
1045 gen_load_gpr(t1, rt);
1046 gen_helper_3i(ldl, t1, t1, t0, ctx->mem_idx);
1047 gen_store_gpr(t1, rt);
1048 opn = "ldl";
1049 break;
1050 case OPC_SDL:
1051 save_cpu_state(ctx, 1);
1052 gen_load_gpr(t1, rt);
1053 gen_helper_2i(sdl, t1, t0, ctx->mem_idx);
1054 opn = "sdl";
1055 break;
1056 case OPC_LDR:
1057 save_cpu_state(ctx, 1);
1058 gen_load_gpr(t1, rt);
1059 gen_helper_3i(ldr, t1, t1, t0, ctx->mem_idx);
1060 gen_store_gpr(t1, rt);
1061 opn = "ldr";
1062 break;
1063 case OPC_SDR:
1064 save_cpu_state(ctx, 1);
1065 gen_load_gpr(t1, rt);
1066 gen_helper_2i(sdr, t1, t0, ctx->mem_idx);
1067 opn = "sdr";
1068 break;
1069 case OPC_LDPC:
1070 save_cpu_state(ctx, 1);
1071 tcg_gen_movi_tl(t1, pc_relative_pc(ctx));
1072 gen_op_addr_add(ctx, t0, t0, t1);
1073 op_ldst_ld(t0, t0, ctx);
1074 gen_store_gpr(t0, rt);
1075 break;
1076 #endif
1077 case OPC_LWPC:
1078 save_cpu_state(ctx, 1);
1079 tcg_gen_movi_tl(t1, pc_relative_pc(ctx));
1080 gen_op_addr_add(ctx, t0, t0, t1);
1081 op_ldst_lw(t0, t0, ctx);
1082 gen_store_gpr(t0, rt);
1083 break;
1084 case OPC_LW:
1085 save_cpu_state(ctx, 0);
1086 op_ldst_lw(t0, t0, ctx);
1087 gen_store_gpr(t0, rt);
1088 opn = "lw";
1089 break;
1090 case OPC_SW:
1091 save_cpu_state(ctx, 0);
1092 gen_load_gpr(t1, rt);
1093 op_ldst_sw(t1, t0, ctx);
1094 opn = "sw";
1095 break;
1096 case OPC_LH:
1097 save_cpu_state(ctx, 0);
1098 op_ldst_lh(t0, t0, ctx);
1099 gen_store_gpr(t0, rt);
1100 opn = "lh";
1101 break;
1102 case OPC_SH:
1103 save_cpu_state(ctx, 0);
1104 gen_load_gpr(t1, rt);
1105 op_ldst_sh(t1, t0, ctx);
1106 opn = "sh";
1107 break;
1108 case OPC_LHU:
1109 save_cpu_state(ctx, 0);
1110 op_ldst_lhu(t0, t0, ctx);
1111 gen_store_gpr(t0, rt);
1112 opn = "lhu";
1113 break;
1114 case OPC_LB:
1115 save_cpu_state(ctx, 0);
1116 op_ldst_lb(t0, t0, ctx);
1117 gen_store_gpr(t0, rt);
1118 opn = "lb";
1119 break;
1120 case OPC_SB:
1121 save_cpu_state(ctx, 0);
1122 gen_load_gpr(t1, rt);
1123 op_ldst_sb(t1, t0, ctx);
1124 opn = "sb";
1125 break;
1126 case OPC_LBU:
1127 save_cpu_state(ctx, 0);
1128 op_ldst_lbu(t0, t0, ctx);
1129 gen_store_gpr(t0, rt);
1130 opn = "lbu";
1131 break;
1132 case OPC_LWL:
1133 save_cpu_state(ctx, 1);
1134 gen_load_gpr(t1, rt);
1135 gen_helper_3i(lwl, t1, t1, t0, ctx->mem_idx);
1136 gen_store_gpr(t1, rt);
1137 opn = "lwl";
1138 break;
1139 case OPC_SWL:
1140 save_cpu_state(ctx, 1);
1141 gen_load_gpr(t1, rt);
1142 gen_helper_2i(swl, t1, t0, ctx->mem_idx);
1143 opn = "swr";
1144 break;
1145 case OPC_LWR:
1146 save_cpu_state(ctx, 1);
1147 gen_load_gpr(t1, rt);
1148 gen_helper_3i(lwr, t1, t1, t0, ctx->mem_idx);
1149 gen_store_gpr(t1, rt);
1150 opn = "lwr";
1151 break;
1152 case OPC_SWR:
1153 save_cpu_state(ctx, 1);
1154 gen_load_gpr(t1, rt);
1155 gen_helper_2i(swr, t1, t0, ctx->mem_idx);
1156 opn = "swr";
1157 break;
1158 case OPC_LL:
1159 save_cpu_state(ctx, 1);
1160 op_ldst_ll(t0, t0, ctx);
1161 gen_store_gpr(t0, rt);
1162 opn = "ll";
1163 break;
1165 MIPS_DEBUG("%s %s, %d(%s)", opn, regnames[rt], offset, regnames[base]);
1166 tcg_temp_free(t0);
1167 tcg_temp_free(t1);
1170 /* Store conditional */
1171 static void gen_st_cond (DisasContext *ctx, uint32_t opc, int rt,
1172 int base, int16_t offset)
1174 const char *opn = "st_cond";
1175 TCGv t0, t1;
1177 t0 = tcg_temp_local_new();
1179 gen_base_offset_addr(ctx, t0, base, offset);
1180 /* Don't do NOP if destination is zero: we must perform the actual
1181 memory access. */
1183 t1 = tcg_temp_local_new();
1184 gen_load_gpr(t1, rt);
1185 switch (opc) {
1186 #if defined(TARGET_MIPS64)
1187 case OPC_SCD:
1188 save_cpu_state(ctx, 0);
1189 op_ldst_scd(t1, t0, rt, ctx);
1190 opn = "scd";
1191 break;
1192 #endif
1193 case OPC_SC:
1194 save_cpu_state(ctx, 1);
1195 op_ldst_sc(t1, t0, rt, ctx);
1196 opn = "sc";
1197 break;
1199 MIPS_DEBUG("%s %s, %d(%s)", opn, regnames[rt], offset, regnames[base]);
1200 tcg_temp_free(t1);
1201 tcg_temp_free(t0);
1204 /* Load and store */
1205 static void gen_flt_ldst (DisasContext *ctx, uint32_t opc, int ft,
1206 int base, int16_t offset)
1208 const char *opn = "flt_ldst";
1209 TCGv t0 = tcg_temp_new();
1211 gen_base_offset_addr(ctx, t0, base, offset);
1212 /* Don't do NOP if destination is zero: we must perform the actual
1213 memory access. */
1214 switch (opc) {
1215 case OPC_LWC1:
1217 TCGv_i32 fp0 = tcg_temp_new_i32();
1219 tcg_gen_qemu_ld32s(t0, t0, ctx->mem_idx);
1220 tcg_gen_trunc_tl_i32(fp0, t0);
1221 gen_store_fpr32(fp0, ft);
1222 tcg_temp_free_i32(fp0);
1224 opn = "lwc1";
1225 break;
1226 case OPC_SWC1:
1228 TCGv_i32 fp0 = tcg_temp_new_i32();
1229 TCGv t1 = tcg_temp_new();
1231 gen_load_fpr32(fp0, ft);
1232 tcg_gen_extu_i32_tl(t1, fp0);
1233 tcg_gen_qemu_st32(t1, t0, ctx->mem_idx);
1234 tcg_temp_free(t1);
1235 tcg_temp_free_i32(fp0);
1237 opn = "swc1";
1238 break;
1239 case OPC_LDC1:
1241 TCGv_i64 fp0 = tcg_temp_new_i64();
1243 tcg_gen_qemu_ld64(fp0, t0, ctx->mem_idx);
1244 gen_store_fpr64(ctx, fp0, ft);
1245 tcg_temp_free_i64(fp0);
1247 opn = "ldc1";
1248 break;
1249 case OPC_SDC1:
1251 TCGv_i64 fp0 = tcg_temp_new_i64();
1253 gen_load_fpr64(ctx, fp0, ft);
1254 tcg_gen_qemu_st64(fp0, t0, ctx->mem_idx);
1255 tcg_temp_free_i64(fp0);
1257 opn = "sdc1";
1258 break;
1259 default:
1260 MIPS_INVAL(opn);
1261 generate_exception(ctx, EXCP_RI);
1262 goto out;
1264 MIPS_DEBUG("%s %s, %d(%s)", opn, fregnames[ft], offset, regnames[base]);
1265 out:
1266 tcg_temp_free(t0);
1269 static void gen_cop1_ldst(CPUState *env, DisasContext *ctx,
1270 uint32_t op, int rt, int rs, int16_t imm)
1272 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
1273 check_cp1_enabled(ctx);
1274 gen_flt_ldst(ctx, op, rt, rs, imm);
1275 } else {
1276 generate_exception_err(ctx, EXCP_CpU, 1);
1280 /* Arithmetic with immediate operand */
1281 static void gen_arith_imm (CPUState *env, DisasContext *ctx, uint32_t opc,
1282 int rt, int rs, int16_t imm)
1284 target_ulong uimm = (target_long)imm; /* Sign extend to 32/64 bits */
1285 const char *opn = "imm arith";
1287 if (rt == 0 && opc != OPC_ADDI && opc != OPC_DADDI) {
1288 /* If no destination, treat it as a NOP.
1289 For addi, we must generate the overflow exception when needed. */
1290 MIPS_DEBUG("NOP");
1291 return;
1293 switch (opc) {
1294 case OPC_ADDI:
1296 TCGv t0 = tcg_temp_local_new();
1297 TCGv t1 = tcg_temp_new();
1298 TCGv t2 = tcg_temp_new();
1299 int l1 = gen_new_label();
1301 gen_load_gpr(t1, rs);
1302 tcg_gen_addi_tl(t0, t1, uimm);
1303 tcg_gen_ext32s_tl(t0, t0);
1305 tcg_gen_xori_tl(t1, t1, ~uimm);
1306 tcg_gen_xori_tl(t2, t0, uimm);
1307 tcg_gen_and_tl(t1, t1, t2);
1308 tcg_temp_free(t2);
1309 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
1310 tcg_temp_free(t1);
1311 /* operands of same sign, result different sign */
1312 generate_exception(ctx, EXCP_OVERFLOW);
1313 gen_set_label(l1);
1314 tcg_gen_ext32s_tl(t0, t0);
1315 gen_store_gpr(t0, rt);
1316 tcg_temp_free(t0);
1318 opn = "addi";
1319 break;
1320 case OPC_ADDIU:
1321 if (rs != 0) {
1322 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
1323 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
1324 } else {
1325 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
1327 opn = "addiu";
1328 break;
1329 #if defined(TARGET_MIPS64)
1330 case OPC_DADDI:
1332 TCGv t0 = tcg_temp_local_new();
1333 TCGv t1 = tcg_temp_new();
1334 TCGv t2 = tcg_temp_new();
1335 int l1 = gen_new_label();
1337 gen_load_gpr(t1, rs);
1338 tcg_gen_addi_tl(t0, t1, uimm);
1340 tcg_gen_xori_tl(t1, t1, ~uimm);
1341 tcg_gen_xori_tl(t2, t0, uimm);
1342 tcg_gen_and_tl(t1, t1, t2);
1343 tcg_temp_free(t2);
1344 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
1345 tcg_temp_free(t1);
1346 /* operands of same sign, result different sign */
1347 generate_exception(ctx, EXCP_OVERFLOW);
1348 gen_set_label(l1);
1349 gen_store_gpr(t0, rt);
1350 tcg_temp_free(t0);
1352 opn = "daddi";
1353 break;
1354 case OPC_DADDIU:
1355 if (rs != 0) {
1356 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
1357 } else {
1358 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
1360 opn = "daddiu";
1361 break;
1362 #endif
1364 MIPS_DEBUG("%s %s, %s, " TARGET_FMT_lx, opn, regnames[rt], regnames[rs], uimm);
1367 /* Logic with immediate operand */
1368 static void gen_logic_imm (CPUState *env, uint32_t opc, int rt, int rs, int16_t imm)
1370 target_ulong uimm;
1371 const char *opn = "imm logic";
1373 if (rt == 0) {
1374 /* If no destination, treat it as a NOP. */
1375 MIPS_DEBUG("NOP");
1376 return;
1378 uimm = (uint16_t)imm;
1379 switch (opc) {
1380 case OPC_ANDI:
1381 if (likely(rs != 0))
1382 tcg_gen_andi_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
1383 else
1384 tcg_gen_movi_tl(cpu_gpr[rt], 0);
1385 opn = "andi";
1386 break;
1387 case OPC_ORI:
1388 if (rs != 0)
1389 tcg_gen_ori_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
1390 else
1391 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
1392 opn = "ori";
1393 break;
1394 case OPC_XORI:
1395 if (likely(rs != 0))
1396 tcg_gen_xori_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
1397 else
1398 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
1399 opn = "xori";
1400 break;
1401 case OPC_LUI:
1402 tcg_gen_movi_tl(cpu_gpr[rt], imm << 16);
1403 opn = "lui";
1404 break;
1406 MIPS_DEBUG("%s %s, %s, " TARGET_FMT_lx, opn, regnames[rt], regnames[rs], uimm);
1409 /* Set on less than with immediate operand */
1410 static void gen_slt_imm (CPUState *env, uint32_t opc, int rt, int rs, int16_t imm)
1412 target_ulong uimm = (target_long)imm; /* Sign extend to 32/64 bits */
1413 const char *opn = "imm arith";
1414 TCGv t0;
1416 if (rt == 0) {
1417 /* If no destination, treat it as a NOP. */
1418 MIPS_DEBUG("NOP");
1419 return;
1421 t0 = tcg_temp_new();
1422 gen_load_gpr(t0, rs);
1423 switch (opc) {
1424 case OPC_SLTI:
1425 tcg_gen_setcondi_tl(TCG_COND_LT, cpu_gpr[rt], t0, uimm);
1426 opn = "slti";
1427 break;
1428 case OPC_SLTIU:
1429 tcg_gen_setcondi_tl(TCG_COND_LTU, cpu_gpr[rt], t0, uimm);
1430 opn = "sltiu";
1431 break;
1433 MIPS_DEBUG("%s %s, %s, " TARGET_FMT_lx, opn, regnames[rt], regnames[rs], uimm);
1434 tcg_temp_free(t0);
1437 /* Shifts with immediate operand */
1438 static void gen_shift_imm(CPUState *env, DisasContext *ctx, uint32_t opc,
1439 int rt, int rs, int16_t imm)
1441 target_ulong uimm = ((uint16_t)imm) & 0x1f;
1442 const char *opn = "imm shift";
1443 TCGv t0;
1445 if (rt == 0) {
1446 /* If no destination, treat it as a NOP. */
1447 MIPS_DEBUG("NOP");
1448 return;
1451 t0 = tcg_temp_new();
1452 gen_load_gpr(t0, rs);
1453 switch (opc) {
1454 case OPC_SLL:
1455 tcg_gen_shli_tl(t0, t0, uimm);
1456 tcg_gen_ext32s_tl(cpu_gpr[rt], t0);
1457 opn = "sll";
1458 break;
1459 case OPC_SRA:
1460 tcg_gen_sari_tl(cpu_gpr[rt], t0, uimm);
1461 opn = "sra";
1462 break;
1463 case OPC_SRL:
1464 if (uimm != 0) {
1465 tcg_gen_ext32u_tl(t0, t0);
1466 tcg_gen_shri_tl(cpu_gpr[rt], t0, uimm);
1467 } else {
1468 tcg_gen_ext32s_tl(cpu_gpr[rt], t0);
1470 opn = "srl";
1471 break;
1472 case OPC_ROTR:
1473 if (uimm != 0) {
1474 TCGv_i32 t1 = tcg_temp_new_i32();
1476 tcg_gen_trunc_tl_i32(t1, t0);
1477 tcg_gen_rotri_i32(t1, t1, uimm);
1478 tcg_gen_ext_i32_tl(cpu_gpr[rt], t1);
1479 tcg_temp_free_i32(t1);
1480 } else {
1481 tcg_gen_ext32s_tl(cpu_gpr[rt], t0);
1483 opn = "rotr";
1484 break;
1485 #if defined(TARGET_MIPS64)
1486 case OPC_DSLL:
1487 tcg_gen_shli_tl(cpu_gpr[rt], t0, uimm);
1488 opn = "dsll";
1489 break;
1490 case OPC_DSRA:
1491 tcg_gen_sari_tl(cpu_gpr[rt], t0, uimm);
1492 opn = "dsra";
1493 break;
1494 case OPC_DSRL:
1495 tcg_gen_shri_tl(cpu_gpr[rt], t0, uimm);
1496 opn = "dsrl";
1497 break;
1498 case OPC_DROTR:
1499 if (uimm != 0) {
1500 tcg_gen_rotri_tl(cpu_gpr[rt], t0, uimm);
1501 } else {
1502 tcg_gen_mov_tl(cpu_gpr[rt], t0);
1504 opn = "drotr";
1505 break;
1506 case OPC_DSLL32:
1507 tcg_gen_shli_tl(cpu_gpr[rt], t0, uimm + 32);
1508 opn = "dsll32";
1509 break;
1510 case OPC_DSRA32:
1511 tcg_gen_sari_tl(cpu_gpr[rt], t0, uimm + 32);
1512 opn = "dsra32";
1513 break;
1514 case OPC_DSRL32:
1515 tcg_gen_shri_tl(cpu_gpr[rt], t0, uimm + 32);
1516 opn = "dsrl32";
1517 break;
1518 case OPC_DROTR32:
1519 tcg_gen_rotri_tl(cpu_gpr[rt], t0, uimm + 32);
1520 opn = "drotr32";
1521 break;
1522 #endif
1524 MIPS_DEBUG("%s %s, %s, " TARGET_FMT_lx, opn, regnames[rt], regnames[rs], uimm);
1525 tcg_temp_free(t0);
1528 /* Arithmetic */
1529 static void gen_arith (CPUState *env, DisasContext *ctx, uint32_t opc,
1530 int rd, int rs, int rt)
1532 const char *opn = "arith";
1534 if (rd == 0 && opc != OPC_ADD && opc != OPC_SUB
1535 && opc != OPC_DADD && opc != OPC_DSUB) {
1536 /* If no destination, treat it as a NOP.
1537 For add & sub, we must generate the overflow exception when needed. */
1538 MIPS_DEBUG("NOP");
1539 return;
1542 switch (opc) {
1543 case OPC_ADD:
1545 TCGv t0 = tcg_temp_local_new();
1546 TCGv t1 = tcg_temp_new();
1547 TCGv t2 = tcg_temp_new();
1548 int l1 = gen_new_label();
1550 gen_load_gpr(t1, rs);
1551 gen_load_gpr(t2, rt);
1552 tcg_gen_add_tl(t0, t1, t2);
1553 tcg_gen_ext32s_tl(t0, t0);
1554 tcg_gen_xor_tl(t1, t1, t2);
1555 tcg_gen_xor_tl(t2, t0, t2);
1556 tcg_gen_andc_tl(t1, t2, t1);
1557 tcg_temp_free(t2);
1558 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
1559 tcg_temp_free(t1);
1560 /* operands of same sign, result different sign */
1561 generate_exception(ctx, EXCP_OVERFLOW);
1562 gen_set_label(l1);
1563 gen_store_gpr(t0, rd);
1564 tcg_temp_free(t0);
1566 opn = "add";
1567 break;
1568 case OPC_ADDU:
1569 if (rs != 0 && rt != 0) {
1570 tcg_gen_add_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
1571 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
1572 } else if (rs == 0 && rt != 0) {
1573 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
1574 } else if (rs != 0 && rt == 0) {
1575 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
1576 } else {
1577 tcg_gen_movi_tl(cpu_gpr[rd], 0);
1579 opn = "addu";
1580 break;
1581 case OPC_SUB:
1583 TCGv t0 = tcg_temp_local_new();
1584 TCGv t1 = tcg_temp_new();
1585 TCGv t2 = tcg_temp_new();
1586 int l1 = gen_new_label();
1588 gen_load_gpr(t1, rs);
1589 gen_load_gpr(t2, rt);
1590 tcg_gen_sub_tl(t0, t1, t2);
1591 tcg_gen_ext32s_tl(t0, t0);
1592 tcg_gen_xor_tl(t2, t1, t2);
1593 tcg_gen_xor_tl(t1, t0, t1);
1594 tcg_gen_and_tl(t1, t1, t2);
1595 tcg_temp_free(t2);
1596 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
1597 tcg_temp_free(t1);
1598 /* operands of different sign, first operand and result different sign */
1599 generate_exception(ctx, EXCP_OVERFLOW);
1600 gen_set_label(l1);
1601 gen_store_gpr(t0, rd);
1602 tcg_temp_free(t0);
1604 opn = "sub";
1605 break;
1606 case OPC_SUBU:
1607 if (rs != 0 && rt != 0) {
1608 tcg_gen_sub_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
1609 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
1610 } else if (rs == 0 && rt != 0) {
1611 tcg_gen_neg_tl(cpu_gpr[rd], cpu_gpr[rt]);
1612 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
1613 } else if (rs != 0 && rt == 0) {
1614 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
1615 } else {
1616 tcg_gen_movi_tl(cpu_gpr[rd], 0);
1618 opn = "subu";
1619 break;
1620 #if defined(TARGET_MIPS64)
1621 case OPC_DADD:
1623 TCGv t0 = tcg_temp_local_new();
1624 TCGv t1 = tcg_temp_new();
1625 TCGv t2 = tcg_temp_new();
1626 int l1 = gen_new_label();
1628 gen_load_gpr(t1, rs);
1629 gen_load_gpr(t2, rt);
1630 tcg_gen_add_tl(t0, t1, t2);
1631 tcg_gen_xor_tl(t1, t1, t2);
1632 tcg_gen_xor_tl(t2, t0, t2);
1633 tcg_gen_andc_tl(t1, t2, t1);
1634 tcg_temp_free(t2);
1635 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
1636 tcg_temp_free(t1);
1637 /* operands of same sign, result different sign */
1638 generate_exception(ctx, EXCP_OVERFLOW);
1639 gen_set_label(l1);
1640 gen_store_gpr(t0, rd);
1641 tcg_temp_free(t0);
1643 opn = "dadd";
1644 break;
1645 case OPC_DADDU:
1646 if (rs != 0 && rt != 0) {
1647 tcg_gen_add_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
1648 } else if (rs == 0 && rt != 0) {
1649 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
1650 } else if (rs != 0 && rt == 0) {
1651 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
1652 } else {
1653 tcg_gen_movi_tl(cpu_gpr[rd], 0);
1655 opn = "daddu";
1656 break;
1657 case OPC_DSUB:
1659 TCGv t0 = tcg_temp_local_new();
1660 TCGv t1 = tcg_temp_new();
1661 TCGv t2 = tcg_temp_new();
1662 int l1 = gen_new_label();
1664 gen_load_gpr(t1, rs);
1665 gen_load_gpr(t2, rt);
1666 tcg_gen_sub_tl(t0, t1, t2);
1667 tcg_gen_xor_tl(t2, t1, t2);
1668 tcg_gen_xor_tl(t1, t0, t1);
1669 tcg_gen_and_tl(t1, t1, t2);
1670 tcg_temp_free(t2);
1671 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
1672 tcg_temp_free(t1);
1673 /* operands of different sign, first operand and result different sign */
1674 generate_exception(ctx, EXCP_OVERFLOW);
1675 gen_set_label(l1);
1676 gen_store_gpr(t0, rd);
1677 tcg_temp_free(t0);
1679 opn = "dsub";
1680 break;
1681 case OPC_DSUBU:
1682 if (rs != 0 && rt != 0) {
1683 tcg_gen_sub_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
1684 } else if (rs == 0 && rt != 0) {
1685 tcg_gen_neg_tl(cpu_gpr[rd], cpu_gpr[rt]);
1686 } else if (rs != 0 && rt == 0) {
1687 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
1688 } else {
1689 tcg_gen_movi_tl(cpu_gpr[rd], 0);
1691 opn = "dsubu";
1692 break;
1693 #endif
1694 case OPC_MUL:
1695 if (likely(rs != 0 && rt != 0)) {
1696 tcg_gen_mul_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
1697 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
1698 } else {
1699 tcg_gen_movi_tl(cpu_gpr[rd], 0);
1701 opn = "mul";
1702 break;
1704 MIPS_DEBUG("%s %s, %s, %s", opn, regnames[rd], regnames[rs], regnames[rt]);
1707 /* Conditional move */
1708 static void gen_cond_move (CPUState *env, uint32_t opc, int rd, int rs, int rt)
1710 const char *opn = "cond move";
1711 int l1;
1713 if (rd == 0) {
1714 /* If no destination, treat it as a NOP.
1715 For add & sub, we must generate the overflow exception when needed. */
1716 MIPS_DEBUG("NOP");
1717 return;
1720 l1 = gen_new_label();
1721 switch (opc) {
1722 case OPC_MOVN:
1723 if (likely(rt != 0))
1724 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[rt], 0, l1);
1725 else
1726 tcg_gen_br(l1);
1727 opn = "movn";
1728 break;
1729 case OPC_MOVZ:
1730 if (likely(rt != 0))
1731 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[rt], 0, l1);
1732 opn = "movz";
1733 break;
1735 if (rs != 0)
1736 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
1737 else
1738 tcg_gen_movi_tl(cpu_gpr[rd], 0);
1739 gen_set_label(l1);
1741 MIPS_DEBUG("%s %s, %s, %s", opn, regnames[rd], regnames[rs], regnames[rt]);
1744 /* Logic */
1745 static void gen_logic (CPUState *env, uint32_t opc, int rd, int rs, int rt)
1747 const char *opn = "logic";
1749 if (rd == 0) {
1750 /* If no destination, treat it as a NOP. */
1751 MIPS_DEBUG("NOP");
1752 return;
1755 switch (opc) {
1756 case OPC_AND:
1757 if (likely(rs != 0 && rt != 0)) {
1758 tcg_gen_and_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
1759 } else {
1760 tcg_gen_movi_tl(cpu_gpr[rd], 0);
1762 opn = "and";
1763 break;
1764 case OPC_NOR:
1765 if (rs != 0 && rt != 0) {
1766 tcg_gen_nor_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
1767 } else if (rs == 0 && rt != 0) {
1768 tcg_gen_not_tl(cpu_gpr[rd], cpu_gpr[rt]);
1769 } else if (rs != 0 && rt == 0) {
1770 tcg_gen_not_tl(cpu_gpr[rd], cpu_gpr[rs]);
1771 } else {
1772 tcg_gen_movi_tl(cpu_gpr[rd], ~((target_ulong)0));
1774 opn = "nor";
1775 break;
1776 case OPC_OR:
1777 if (likely(rs != 0 && rt != 0)) {
1778 tcg_gen_or_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
1779 } else if (rs == 0 && rt != 0) {
1780 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
1781 } else if (rs != 0 && rt == 0) {
1782 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
1783 } else {
1784 tcg_gen_movi_tl(cpu_gpr[rd], 0);
1786 opn = "or";
1787 break;
1788 case OPC_XOR:
1789 if (likely(rs != 0 && rt != 0)) {
1790 tcg_gen_xor_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
1791 } else if (rs == 0 && rt != 0) {
1792 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
1793 } else if (rs != 0 && rt == 0) {
1794 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
1795 } else {
1796 tcg_gen_movi_tl(cpu_gpr[rd], 0);
1798 opn = "xor";
1799 break;
1801 MIPS_DEBUG("%s %s, %s, %s", opn, regnames[rd], regnames[rs], regnames[rt]);
1804 /* Set on lower than */
1805 static void gen_slt (CPUState *env, uint32_t opc, int rd, int rs, int rt)
1807 const char *opn = "slt";
1808 TCGv t0, t1;
1810 if (rd == 0) {
1811 /* If no destination, treat it as a NOP. */
1812 MIPS_DEBUG("NOP");
1813 return;
1816 t0 = tcg_temp_new();
1817 t1 = tcg_temp_new();
1818 gen_load_gpr(t0, rs);
1819 gen_load_gpr(t1, rt);
1820 switch (opc) {
1821 case OPC_SLT:
1822 tcg_gen_setcond_tl(TCG_COND_LT, cpu_gpr[rd], t0, t1);
1823 opn = "slt";
1824 break;
1825 case OPC_SLTU:
1826 tcg_gen_setcond_tl(TCG_COND_LTU, cpu_gpr[rd], t0, t1);
1827 opn = "sltu";
1828 break;
1830 MIPS_DEBUG("%s %s, %s, %s", opn, regnames[rd], regnames[rs], regnames[rt]);
1831 tcg_temp_free(t0);
1832 tcg_temp_free(t1);
1835 /* Shifts */
1836 static void gen_shift (CPUState *env, DisasContext *ctx, uint32_t opc,
1837 int rd, int rs, int rt)
1839 const char *opn = "shifts";
1840 TCGv t0, t1;
1842 if (rd == 0) {
1843 /* If no destination, treat it as a NOP.
1844 For add & sub, we must generate the overflow exception when needed. */
1845 MIPS_DEBUG("NOP");
1846 return;
1849 t0 = tcg_temp_new();
1850 t1 = tcg_temp_new();
1851 gen_load_gpr(t0, rs);
1852 gen_load_gpr(t1, rt);
1853 switch (opc) {
1854 case OPC_SLLV:
1855 tcg_gen_andi_tl(t0, t0, 0x1f);
1856 tcg_gen_shl_tl(t0, t1, t0);
1857 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
1858 opn = "sllv";
1859 break;
1860 case OPC_SRAV:
1861 tcg_gen_andi_tl(t0, t0, 0x1f);
1862 tcg_gen_sar_tl(cpu_gpr[rd], t1, t0);
1863 opn = "srav";
1864 break;
1865 case OPC_SRLV:
1866 tcg_gen_ext32u_tl(t1, t1);
1867 tcg_gen_andi_tl(t0, t0, 0x1f);
1868 tcg_gen_shr_tl(t0, t1, t0);
1869 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
1870 opn = "srlv";
1871 break;
1872 case OPC_ROTRV:
1874 TCGv_i32 t2 = tcg_temp_new_i32();
1875 TCGv_i32 t3 = tcg_temp_new_i32();
1877 tcg_gen_trunc_tl_i32(t2, t0);
1878 tcg_gen_trunc_tl_i32(t3, t1);
1879 tcg_gen_andi_i32(t2, t2, 0x1f);
1880 tcg_gen_rotr_i32(t2, t3, t2);
1881 tcg_gen_ext_i32_tl(cpu_gpr[rd], t2);
1882 tcg_temp_free_i32(t2);
1883 tcg_temp_free_i32(t3);
1884 opn = "rotrv";
1886 break;
1887 #if defined(TARGET_MIPS64)
1888 case OPC_DSLLV:
1889 tcg_gen_andi_tl(t0, t0, 0x3f);
1890 tcg_gen_shl_tl(cpu_gpr[rd], t1, t0);
1891 opn = "dsllv";
1892 break;
1893 case OPC_DSRAV:
1894 tcg_gen_andi_tl(t0, t0, 0x3f);
1895 tcg_gen_sar_tl(cpu_gpr[rd], t1, t0);
1896 opn = "dsrav";
1897 break;
1898 case OPC_DSRLV:
1899 tcg_gen_andi_tl(t0, t0, 0x3f);
1900 tcg_gen_shr_tl(cpu_gpr[rd], t1, t0);
1901 opn = "dsrlv";
1902 break;
1903 case OPC_DROTRV:
1904 tcg_gen_andi_tl(t0, t0, 0x3f);
1905 tcg_gen_rotr_tl(cpu_gpr[rd], t1, t0);
1906 opn = "drotrv";
1907 break;
1908 #endif
1910 MIPS_DEBUG("%s %s, %s, %s", opn, regnames[rd], regnames[rs], regnames[rt]);
1911 tcg_temp_free(t0);
1912 tcg_temp_free(t1);
1915 /* Arithmetic on HI/LO registers */
1916 static void gen_HILO (DisasContext *ctx, uint32_t opc, int reg)
1918 const char *opn = "hilo";
1920 if (reg == 0 && (opc == OPC_MFHI || opc == OPC_MFLO)) {
1921 /* Treat as NOP. */
1922 MIPS_DEBUG("NOP");
1923 return;
1925 switch (opc) {
1926 case OPC_MFHI:
1927 tcg_gen_mov_tl(cpu_gpr[reg], cpu_HI[0]);
1928 opn = "mfhi";
1929 break;
1930 case OPC_MFLO:
1931 tcg_gen_mov_tl(cpu_gpr[reg], cpu_LO[0]);
1932 opn = "mflo";
1933 break;
1934 case OPC_MTHI:
1935 if (reg != 0)
1936 tcg_gen_mov_tl(cpu_HI[0], cpu_gpr[reg]);
1937 else
1938 tcg_gen_movi_tl(cpu_HI[0], 0);
1939 opn = "mthi";
1940 break;
1941 case OPC_MTLO:
1942 if (reg != 0)
1943 tcg_gen_mov_tl(cpu_LO[0], cpu_gpr[reg]);
1944 else
1945 tcg_gen_movi_tl(cpu_LO[0], 0);
1946 opn = "mtlo";
1947 break;
1949 MIPS_DEBUG("%s %s", opn, regnames[reg]);
1952 static void gen_muldiv (DisasContext *ctx, uint32_t opc,
1953 int rs, int rt)
1955 const char *opn = "mul/div";
1956 TCGv t0, t1;
1958 switch (opc) {
1959 case OPC_DIV:
1960 case OPC_DIVU:
1961 #if defined(TARGET_MIPS64)
1962 case OPC_DDIV:
1963 case OPC_DDIVU:
1964 #endif
1965 t0 = tcg_temp_local_new();
1966 t1 = tcg_temp_local_new();
1967 break;
1968 default:
1969 t0 = tcg_temp_new();
1970 t1 = tcg_temp_new();
1971 break;
1974 gen_load_gpr(t0, rs);
1975 gen_load_gpr(t1, rt);
1976 switch (opc) {
1977 case OPC_DIV:
1979 int l1 = gen_new_label();
1980 int l2 = gen_new_label();
1982 tcg_gen_ext32s_tl(t0, t0);
1983 tcg_gen_ext32s_tl(t1, t1);
1984 tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
1985 tcg_gen_brcondi_tl(TCG_COND_NE, t0, INT_MIN, l2);
1986 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1, l2);
1988 tcg_gen_mov_tl(cpu_LO[0], t0);
1989 tcg_gen_movi_tl(cpu_HI[0], 0);
1990 tcg_gen_br(l1);
1991 gen_set_label(l2);
1992 tcg_gen_div_tl(cpu_LO[0], t0, t1);
1993 tcg_gen_rem_tl(cpu_HI[0], t0, t1);
1994 tcg_gen_ext32s_tl(cpu_LO[0], cpu_LO[0]);
1995 tcg_gen_ext32s_tl(cpu_HI[0], cpu_HI[0]);
1996 gen_set_label(l1);
1998 opn = "div";
1999 break;
2000 case OPC_DIVU:
2002 int l1 = gen_new_label();
2004 tcg_gen_ext32u_tl(t0, t0);
2005 tcg_gen_ext32u_tl(t1, t1);
2006 tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
2007 tcg_gen_divu_tl(cpu_LO[0], t0, t1);
2008 tcg_gen_remu_tl(cpu_HI[0], t0, t1);
2009 tcg_gen_ext32s_tl(cpu_LO[0], cpu_LO[0]);
2010 tcg_gen_ext32s_tl(cpu_HI[0], cpu_HI[0]);
2011 gen_set_label(l1);
2013 opn = "divu";
2014 break;
2015 case OPC_MULT:
2017 TCGv_i64 t2 = tcg_temp_new_i64();
2018 TCGv_i64 t3 = tcg_temp_new_i64();
2020 tcg_gen_ext_tl_i64(t2, t0);
2021 tcg_gen_ext_tl_i64(t3, t1);
2022 tcg_gen_mul_i64(t2, t2, t3);
2023 tcg_temp_free_i64(t3);
2024 tcg_gen_trunc_i64_tl(t0, t2);
2025 tcg_gen_shri_i64(t2, t2, 32);
2026 tcg_gen_trunc_i64_tl(t1, t2);
2027 tcg_temp_free_i64(t2);
2028 tcg_gen_ext32s_tl(cpu_LO[0], t0);
2029 tcg_gen_ext32s_tl(cpu_HI[0], t1);
2031 opn = "mult";
2032 break;
2033 case OPC_MULTU:
2035 TCGv_i64 t2 = tcg_temp_new_i64();
2036 TCGv_i64 t3 = tcg_temp_new_i64();
2038 tcg_gen_ext32u_tl(t0, t0);
2039 tcg_gen_ext32u_tl(t1, t1);
2040 tcg_gen_extu_tl_i64(t2, t0);
2041 tcg_gen_extu_tl_i64(t3, t1);
2042 tcg_gen_mul_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 = "multu";
2052 break;
2053 #if defined(TARGET_MIPS64)
2054 case OPC_DDIV:
2056 int l1 = gen_new_label();
2057 int l2 = gen_new_label();
2059 tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
2060 tcg_gen_brcondi_tl(TCG_COND_NE, t0, -1LL << 63, l2);
2061 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1LL, l2);
2062 tcg_gen_mov_tl(cpu_LO[0], t0);
2063 tcg_gen_movi_tl(cpu_HI[0], 0);
2064 tcg_gen_br(l1);
2065 gen_set_label(l2);
2066 tcg_gen_div_i64(cpu_LO[0], t0, t1);
2067 tcg_gen_rem_i64(cpu_HI[0], t0, t1);
2068 gen_set_label(l1);
2070 opn = "ddiv";
2071 break;
2072 case OPC_DDIVU:
2074 int l1 = gen_new_label();
2076 tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
2077 tcg_gen_divu_i64(cpu_LO[0], t0, t1);
2078 tcg_gen_remu_i64(cpu_HI[0], t0, t1);
2079 gen_set_label(l1);
2081 opn = "ddivu";
2082 break;
2083 case OPC_DMULT:
2084 gen_helper_dmult(t0, t1);
2085 opn = "dmult";
2086 break;
2087 case OPC_DMULTU:
2088 gen_helper_dmultu(t0, t1);
2089 opn = "dmultu";
2090 break;
2091 #endif
2092 case OPC_MADD:
2094 TCGv_i64 t2 = tcg_temp_new_i64();
2095 TCGv_i64 t3 = tcg_temp_new_i64();
2097 tcg_gen_ext_tl_i64(t2, t0);
2098 tcg_gen_ext_tl_i64(t3, t1);
2099 tcg_gen_mul_i64(t2, t2, t3);
2100 tcg_gen_concat_tl_i64(t3, cpu_LO[0], cpu_HI[0]);
2101 tcg_gen_add_i64(t2, t2, t3);
2102 tcg_temp_free_i64(t3);
2103 tcg_gen_trunc_i64_tl(t0, t2);
2104 tcg_gen_shri_i64(t2, t2, 32);
2105 tcg_gen_trunc_i64_tl(t1, t2);
2106 tcg_temp_free_i64(t2);
2107 tcg_gen_ext32s_tl(cpu_LO[0], t0);
2108 tcg_gen_ext32s_tl(cpu_HI[0], t1);
2110 opn = "madd";
2111 break;
2112 case OPC_MADDU:
2114 TCGv_i64 t2 = tcg_temp_new_i64();
2115 TCGv_i64 t3 = tcg_temp_new_i64();
2117 tcg_gen_ext32u_tl(t0, t0);
2118 tcg_gen_ext32u_tl(t1, t1);
2119 tcg_gen_extu_tl_i64(t2, t0);
2120 tcg_gen_extu_tl_i64(t3, t1);
2121 tcg_gen_mul_i64(t2, t2, t3);
2122 tcg_gen_concat_tl_i64(t3, cpu_LO[0], cpu_HI[0]);
2123 tcg_gen_add_i64(t2, t2, t3);
2124 tcg_temp_free_i64(t3);
2125 tcg_gen_trunc_i64_tl(t0, t2);
2126 tcg_gen_shri_i64(t2, t2, 32);
2127 tcg_gen_trunc_i64_tl(t1, t2);
2128 tcg_temp_free_i64(t2);
2129 tcg_gen_ext32s_tl(cpu_LO[0], t0);
2130 tcg_gen_ext32s_tl(cpu_HI[0], t1);
2132 opn = "maddu";
2133 break;
2134 case OPC_MSUB:
2136 TCGv_i64 t2 = tcg_temp_new_i64();
2137 TCGv_i64 t3 = tcg_temp_new_i64();
2139 tcg_gen_ext_tl_i64(t2, t0);
2140 tcg_gen_ext_tl_i64(t3, t1);
2141 tcg_gen_mul_i64(t2, t2, t3);
2142 tcg_gen_concat_tl_i64(t3, cpu_LO[0], cpu_HI[0]);
2143 tcg_gen_sub_i64(t2, t3, t2);
2144 tcg_temp_free_i64(t3);
2145 tcg_gen_trunc_i64_tl(t0, t2);
2146 tcg_gen_shri_i64(t2, t2, 32);
2147 tcg_gen_trunc_i64_tl(t1, t2);
2148 tcg_temp_free_i64(t2);
2149 tcg_gen_ext32s_tl(cpu_LO[0], t0);
2150 tcg_gen_ext32s_tl(cpu_HI[0], t1);
2152 opn = "msub";
2153 break;
2154 case OPC_MSUBU:
2156 TCGv_i64 t2 = tcg_temp_new_i64();
2157 TCGv_i64 t3 = tcg_temp_new_i64();
2159 tcg_gen_ext32u_tl(t0, t0);
2160 tcg_gen_ext32u_tl(t1, t1);
2161 tcg_gen_extu_tl_i64(t2, t0);
2162 tcg_gen_extu_tl_i64(t3, t1);
2163 tcg_gen_mul_i64(t2, t2, t3);
2164 tcg_gen_concat_tl_i64(t3, cpu_LO[0], cpu_HI[0]);
2165 tcg_gen_sub_i64(t2, t3, t2);
2166 tcg_temp_free_i64(t3);
2167 tcg_gen_trunc_i64_tl(t0, t2);
2168 tcg_gen_shri_i64(t2, t2, 32);
2169 tcg_gen_trunc_i64_tl(t1, t2);
2170 tcg_temp_free_i64(t2);
2171 tcg_gen_ext32s_tl(cpu_LO[0], t0);
2172 tcg_gen_ext32s_tl(cpu_HI[0], t1);
2174 opn = "msubu";
2175 break;
2176 default:
2177 MIPS_INVAL(opn);
2178 generate_exception(ctx, EXCP_RI);
2179 goto out;
2181 MIPS_DEBUG("%s %s %s", opn, regnames[rs], regnames[rt]);
2182 out:
2183 tcg_temp_free(t0);
2184 tcg_temp_free(t1);
2187 static void gen_mul_vr54xx (DisasContext *ctx, uint32_t opc,
2188 int rd, int rs, int rt)
2190 const char *opn = "mul vr54xx";
2191 TCGv t0 = tcg_temp_new();
2192 TCGv t1 = tcg_temp_new();
2194 gen_load_gpr(t0, rs);
2195 gen_load_gpr(t1, rt);
2197 switch (opc) {
2198 case OPC_VR54XX_MULS:
2199 gen_helper_muls(t0, t0, t1);
2200 opn = "muls";
2201 break;
2202 case OPC_VR54XX_MULSU:
2203 gen_helper_mulsu(t0, t0, t1);
2204 opn = "mulsu";
2205 break;
2206 case OPC_VR54XX_MACC:
2207 gen_helper_macc(t0, t0, t1);
2208 opn = "macc";
2209 break;
2210 case OPC_VR54XX_MACCU:
2211 gen_helper_maccu(t0, t0, t1);
2212 opn = "maccu";
2213 break;
2214 case OPC_VR54XX_MSAC:
2215 gen_helper_msac(t0, t0, t1);
2216 opn = "msac";
2217 break;
2218 case OPC_VR54XX_MSACU:
2219 gen_helper_msacu(t0, t0, t1);
2220 opn = "msacu";
2221 break;
2222 case OPC_VR54XX_MULHI:
2223 gen_helper_mulhi(t0, t0, t1);
2224 opn = "mulhi";
2225 break;
2226 case OPC_VR54XX_MULHIU:
2227 gen_helper_mulhiu(t0, t0, t1);
2228 opn = "mulhiu";
2229 break;
2230 case OPC_VR54XX_MULSHI:
2231 gen_helper_mulshi(t0, t0, t1);
2232 opn = "mulshi";
2233 break;
2234 case OPC_VR54XX_MULSHIU:
2235 gen_helper_mulshiu(t0, t0, t1);
2236 opn = "mulshiu";
2237 break;
2238 case OPC_VR54XX_MACCHI:
2239 gen_helper_macchi(t0, t0, t1);
2240 opn = "macchi";
2241 break;
2242 case OPC_VR54XX_MACCHIU:
2243 gen_helper_macchiu(t0, t0, t1);
2244 opn = "macchiu";
2245 break;
2246 case OPC_VR54XX_MSACHI:
2247 gen_helper_msachi(t0, t0, t1);
2248 opn = "msachi";
2249 break;
2250 case OPC_VR54XX_MSACHIU:
2251 gen_helper_msachiu(t0, t0, t1);
2252 opn = "msachiu";
2253 break;
2254 default:
2255 MIPS_INVAL("mul vr54xx");
2256 generate_exception(ctx, EXCP_RI);
2257 goto out;
2259 gen_store_gpr(t0, rd);
2260 MIPS_DEBUG("%s %s, %s, %s", opn, regnames[rd], regnames[rs], regnames[rt]);
2262 out:
2263 tcg_temp_free(t0);
2264 tcg_temp_free(t1);
2267 static void gen_cl (DisasContext *ctx, uint32_t opc,
2268 int rd, int rs)
2270 const char *opn = "CLx";
2271 TCGv t0;
2273 if (rd == 0) {
2274 /* Treat as NOP. */
2275 MIPS_DEBUG("NOP");
2276 return;
2278 t0 = tcg_temp_new();
2279 gen_load_gpr(t0, rs);
2280 switch (opc) {
2281 case OPC_CLO:
2282 gen_helper_clo(cpu_gpr[rd], t0);
2283 opn = "clo";
2284 break;
2285 case OPC_CLZ:
2286 gen_helper_clz(cpu_gpr[rd], t0);
2287 opn = "clz";
2288 break;
2289 #if defined(TARGET_MIPS64)
2290 case OPC_DCLO:
2291 gen_helper_dclo(cpu_gpr[rd], t0);
2292 opn = "dclo";
2293 break;
2294 case OPC_DCLZ:
2295 gen_helper_dclz(cpu_gpr[rd], t0);
2296 opn = "dclz";
2297 break;
2298 #endif
2300 MIPS_DEBUG("%s %s, %s", opn, regnames[rd], regnames[rs]);
2301 tcg_temp_free(t0);
2304 /* Traps */
2305 static void gen_trap (DisasContext *ctx, uint32_t opc,
2306 int rs, int rt, int16_t imm)
2308 int cond;
2309 TCGv t0 = tcg_temp_new();
2310 TCGv t1 = tcg_temp_new();
2312 cond = 0;
2313 /* Load needed operands */
2314 switch (opc) {
2315 case OPC_TEQ:
2316 case OPC_TGE:
2317 case OPC_TGEU:
2318 case OPC_TLT:
2319 case OPC_TLTU:
2320 case OPC_TNE:
2321 /* Compare two registers */
2322 if (rs != rt) {
2323 gen_load_gpr(t0, rs);
2324 gen_load_gpr(t1, rt);
2325 cond = 1;
2327 break;
2328 case OPC_TEQI:
2329 case OPC_TGEI:
2330 case OPC_TGEIU:
2331 case OPC_TLTI:
2332 case OPC_TLTIU:
2333 case OPC_TNEI:
2334 /* Compare register to immediate */
2335 if (rs != 0 || imm != 0) {
2336 gen_load_gpr(t0, rs);
2337 tcg_gen_movi_tl(t1, (int32_t)imm);
2338 cond = 1;
2340 break;
2342 if (cond == 0) {
2343 switch (opc) {
2344 case OPC_TEQ: /* rs == rs */
2345 case OPC_TEQI: /* r0 == 0 */
2346 case OPC_TGE: /* rs >= rs */
2347 case OPC_TGEI: /* r0 >= 0 */
2348 case OPC_TGEU: /* rs >= rs unsigned */
2349 case OPC_TGEIU: /* r0 >= 0 unsigned */
2350 /* Always trap */
2351 generate_exception(ctx, EXCP_TRAP);
2352 break;
2353 case OPC_TLT: /* rs < rs */
2354 case OPC_TLTI: /* r0 < 0 */
2355 case OPC_TLTU: /* rs < rs unsigned */
2356 case OPC_TLTIU: /* r0 < 0 unsigned */
2357 case OPC_TNE: /* rs != rs */
2358 case OPC_TNEI: /* r0 != 0 */
2359 /* Never trap: treat as NOP. */
2360 break;
2362 } else {
2363 int l1 = gen_new_label();
2365 switch (opc) {
2366 case OPC_TEQ:
2367 case OPC_TEQI:
2368 tcg_gen_brcond_tl(TCG_COND_NE, t0, t1, l1);
2369 break;
2370 case OPC_TGE:
2371 case OPC_TGEI:
2372 tcg_gen_brcond_tl(TCG_COND_LT, t0, t1, l1);
2373 break;
2374 case OPC_TGEU:
2375 case OPC_TGEIU:
2376 tcg_gen_brcond_tl(TCG_COND_LTU, t0, t1, l1);
2377 break;
2378 case OPC_TLT:
2379 case OPC_TLTI:
2380 tcg_gen_brcond_tl(TCG_COND_GE, t0, t1, l1);
2381 break;
2382 case OPC_TLTU:
2383 case OPC_TLTIU:
2384 tcg_gen_brcond_tl(TCG_COND_GEU, t0, t1, l1);
2385 break;
2386 case OPC_TNE:
2387 case OPC_TNEI:
2388 tcg_gen_brcond_tl(TCG_COND_EQ, t0, t1, l1);
2389 break;
2391 generate_exception(ctx, EXCP_TRAP);
2392 gen_set_label(l1);
2394 tcg_temp_free(t0);
2395 tcg_temp_free(t1);
2398 static inline void gen_goto_tb(DisasContext *ctx, int n, target_ulong dest)
2400 TranslationBlock *tb;
2401 tb = ctx->tb;
2402 if ((tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK) &&
2403 likely(!ctx->singlestep_enabled)) {
2404 tcg_gen_goto_tb(n);
2405 gen_save_pc(dest);
2406 tcg_gen_exit_tb((long)tb + n);
2407 } else {
2408 gen_save_pc(dest);
2409 if (ctx->singlestep_enabled) {
2410 save_cpu_state(ctx, 0);
2411 gen_helper_0i(raise_exception, EXCP_DEBUG);
2413 tcg_gen_exit_tb(0);
2417 /* Branches (before delay slot) */
2418 static void gen_compute_branch (DisasContext *ctx, uint32_t opc,
2419 int insn_bytes,
2420 int rs, int rt, int32_t offset)
2422 target_ulong btgt = -1;
2423 int blink = 0;
2424 int bcond_compute = 0;
2425 TCGv t0 = tcg_temp_new();
2426 TCGv t1 = tcg_temp_new();
2428 if (ctx->hflags & MIPS_HFLAG_BMASK) {
2429 #ifdef MIPS_DEBUG_DISAS
2430 LOG_DISAS("Branch in delay slot at PC 0x" TARGET_FMT_lx "\n", ctx->pc);
2431 #endif
2432 generate_exception(ctx, EXCP_RI);
2433 goto out;
2436 /* Load needed operands */
2437 switch (opc) {
2438 case OPC_BEQ:
2439 case OPC_BEQL:
2440 case OPC_BNE:
2441 case OPC_BNEL:
2442 /* Compare two registers */
2443 if (rs != rt) {
2444 gen_load_gpr(t0, rs);
2445 gen_load_gpr(t1, rt);
2446 bcond_compute = 1;
2448 btgt = ctx->pc + insn_bytes + offset;
2449 break;
2450 case OPC_BGEZ:
2451 case OPC_BGEZAL:
2452 case OPC_BGEZALL:
2453 case OPC_BGEZL:
2454 case OPC_BGTZ:
2455 case OPC_BGTZL:
2456 case OPC_BLEZ:
2457 case OPC_BLEZL:
2458 case OPC_BLTZ:
2459 case OPC_BLTZAL:
2460 case OPC_BLTZALL:
2461 case OPC_BLTZL:
2462 /* Compare to zero */
2463 if (rs != 0) {
2464 gen_load_gpr(t0, rs);
2465 bcond_compute = 1;
2467 btgt = ctx->pc + insn_bytes + offset;
2468 break;
2469 case OPC_J:
2470 case OPC_JAL:
2471 case OPC_JALX:
2472 case OPC_JALS:
2473 case OPC_JALXS:
2474 /* Jump to immediate */
2475 btgt = ((ctx->pc + insn_bytes) & (int32_t)0xF0000000) | (uint32_t)offset;
2476 break;
2477 case OPC_JR:
2478 case OPC_JALR:
2479 case OPC_JALRC:
2480 case OPC_JALRS:
2481 /* Jump to register */
2482 if (offset != 0 && offset != 16) {
2483 /* Hint = 0 is JR/JALR, hint 16 is JR.HB/JALR.HB, the
2484 others are reserved. */
2485 MIPS_INVAL("jump hint");
2486 generate_exception(ctx, EXCP_RI);
2487 goto out;
2489 gen_load_gpr(btarget, rs);
2490 break;
2491 default:
2492 MIPS_INVAL("branch/jump");
2493 generate_exception(ctx, EXCP_RI);
2494 goto out;
2496 if (bcond_compute == 0) {
2497 /* No condition to be computed */
2498 switch (opc) {
2499 case OPC_BEQ: /* rx == rx */
2500 case OPC_BEQL: /* rx == rx likely */
2501 case OPC_BGEZ: /* 0 >= 0 */
2502 case OPC_BGEZL: /* 0 >= 0 likely */
2503 case OPC_BLEZ: /* 0 <= 0 */
2504 case OPC_BLEZL: /* 0 <= 0 likely */
2505 /* Always take */
2506 ctx->hflags |= MIPS_HFLAG_B;
2507 MIPS_DEBUG("balways");
2508 break;
2509 case OPC_BGEZAL: /* 0 >= 0 */
2510 case OPC_BGEZALL: /* 0 >= 0 likely */
2511 /* Always take and link */
2512 blink = 31;
2513 ctx->hflags |= MIPS_HFLAG_B;
2514 MIPS_DEBUG("balways and link");
2515 break;
2516 case OPC_BNE: /* rx != rx */
2517 case OPC_BGTZ: /* 0 > 0 */
2518 case OPC_BLTZ: /* 0 < 0 */
2519 /* Treat as NOP. */
2520 MIPS_DEBUG("bnever (NOP)");
2521 goto out;
2522 case OPC_BLTZAL: /* 0 < 0 */
2523 tcg_gen_movi_tl(cpu_gpr[31], ctx->pc + 8);
2524 MIPS_DEBUG("bnever and link");
2525 goto out;
2526 case OPC_BLTZALL: /* 0 < 0 likely */
2527 tcg_gen_movi_tl(cpu_gpr[31], ctx->pc + 8);
2528 /* Skip the instruction in the delay slot */
2529 MIPS_DEBUG("bnever, link and skip");
2530 ctx->pc += 4;
2531 goto out;
2532 case OPC_BNEL: /* rx != rx likely */
2533 case OPC_BGTZL: /* 0 > 0 likely */
2534 case OPC_BLTZL: /* 0 < 0 likely */
2535 /* Skip the instruction in the delay slot */
2536 MIPS_DEBUG("bnever and skip");
2537 ctx->pc += 4;
2538 goto out;
2539 case OPC_J:
2540 ctx->hflags |= MIPS_HFLAG_B;
2541 MIPS_DEBUG("j " TARGET_FMT_lx, btgt);
2542 break;
2543 case OPC_JALXS:
2544 case OPC_JALX:
2545 ctx->hflags |= MIPS_HFLAG_BX;
2546 /* Fallthrough */
2547 case OPC_JALS:
2548 case OPC_JAL:
2549 blink = 31;
2550 ctx->hflags |= MIPS_HFLAG_B;
2551 ctx->hflags |= ((opc == OPC_JALS || opc == OPC_JALXS)
2552 ? MIPS_HFLAG_BDS16
2553 : MIPS_HFLAG_BDS32);
2554 MIPS_DEBUG("jal " TARGET_FMT_lx, btgt);
2555 break;
2556 case OPC_JR:
2557 ctx->hflags |= MIPS_HFLAG_BR;
2558 if (insn_bytes == 4)
2559 ctx->hflags |= MIPS_HFLAG_BDS32;
2560 MIPS_DEBUG("jr %s", regnames[rs]);
2561 break;
2562 case OPC_JALRS:
2563 case OPC_JALR:
2564 case OPC_JALRC:
2565 blink = rt;
2566 ctx->hflags |= MIPS_HFLAG_BR;
2567 ctx->hflags |= (opc == OPC_JALRS
2568 ? MIPS_HFLAG_BDS16
2569 : MIPS_HFLAG_BDS32);
2570 MIPS_DEBUG("jalr %s, %s", regnames[rt], regnames[rs]);
2571 break;
2572 default:
2573 MIPS_INVAL("branch/jump");
2574 generate_exception(ctx, EXCP_RI);
2575 goto out;
2577 } else {
2578 switch (opc) {
2579 case OPC_BEQ:
2580 tcg_gen_setcond_tl(TCG_COND_EQ, bcond, t0, t1);
2581 MIPS_DEBUG("beq %s, %s, " TARGET_FMT_lx,
2582 regnames[rs], regnames[rt], btgt);
2583 goto not_likely;
2584 case OPC_BEQL:
2585 tcg_gen_setcond_tl(TCG_COND_EQ, bcond, t0, t1);
2586 MIPS_DEBUG("beql %s, %s, " TARGET_FMT_lx,
2587 regnames[rs], regnames[rt], btgt);
2588 goto likely;
2589 case OPC_BNE:
2590 tcg_gen_setcond_tl(TCG_COND_NE, bcond, t0, t1);
2591 MIPS_DEBUG("bne %s, %s, " TARGET_FMT_lx,
2592 regnames[rs], regnames[rt], btgt);
2593 goto not_likely;
2594 case OPC_BNEL:
2595 tcg_gen_setcond_tl(TCG_COND_NE, bcond, t0, t1);
2596 MIPS_DEBUG("bnel %s, %s, " TARGET_FMT_lx,
2597 regnames[rs], regnames[rt], btgt);
2598 goto likely;
2599 case OPC_BGEZ:
2600 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
2601 MIPS_DEBUG("bgez %s, " TARGET_FMT_lx, regnames[rs], btgt);
2602 goto not_likely;
2603 case OPC_BGEZL:
2604 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
2605 MIPS_DEBUG("bgezl %s, " TARGET_FMT_lx, regnames[rs], btgt);
2606 goto likely;
2607 case OPC_BGEZAL:
2608 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
2609 MIPS_DEBUG("bgezal %s, " TARGET_FMT_lx, regnames[rs], btgt);
2610 blink = 31;
2611 goto not_likely;
2612 case OPC_BGEZALL:
2613 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
2614 blink = 31;
2615 MIPS_DEBUG("bgezall %s, " TARGET_FMT_lx, regnames[rs], btgt);
2616 goto likely;
2617 case OPC_BGTZ:
2618 tcg_gen_setcondi_tl(TCG_COND_GT, bcond, t0, 0);
2619 MIPS_DEBUG("bgtz %s, " TARGET_FMT_lx, regnames[rs], btgt);
2620 goto not_likely;
2621 case OPC_BGTZL:
2622 tcg_gen_setcondi_tl(TCG_COND_GT, bcond, t0, 0);
2623 MIPS_DEBUG("bgtzl %s, " TARGET_FMT_lx, regnames[rs], btgt);
2624 goto likely;
2625 case OPC_BLEZ:
2626 tcg_gen_setcondi_tl(TCG_COND_LE, bcond, t0, 0);
2627 MIPS_DEBUG("blez %s, " TARGET_FMT_lx, regnames[rs], btgt);
2628 goto not_likely;
2629 case OPC_BLEZL:
2630 tcg_gen_setcondi_tl(TCG_COND_LE, bcond, t0, 0);
2631 MIPS_DEBUG("blezl %s, " TARGET_FMT_lx, regnames[rs], btgt);
2632 goto likely;
2633 case OPC_BLTZ:
2634 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
2635 MIPS_DEBUG("bltz %s, " TARGET_FMT_lx, regnames[rs], btgt);
2636 goto not_likely;
2637 case OPC_BLTZL:
2638 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
2639 MIPS_DEBUG("bltzl %s, " TARGET_FMT_lx, regnames[rs], btgt);
2640 goto likely;
2641 case OPC_BLTZAL:
2642 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
2643 blink = 31;
2644 MIPS_DEBUG("bltzal %s, " TARGET_FMT_lx, regnames[rs], btgt);
2645 not_likely:
2646 ctx->hflags |= MIPS_HFLAG_BC;
2647 break;
2648 case OPC_BLTZALL:
2649 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
2650 blink = 31;
2651 MIPS_DEBUG("bltzall %s, " TARGET_FMT_lx, regnames[rs], btgt);
2652 likely:
2653 ctx->hflags |= MIPS_HFLAG_BL;
2654 break;
2655 default:
2656 MIPS_INVAL("conditional branch/jump");
2657 generate_exception(ctx, EXCP_RI);
2658 goto out;
2661 MIPS_DEBUG("enter ds: link %d cond %02x target " TARGET_FMT_lx,
2662 blink, ctx->hflags, btgt);
2664 ctx->btarget = btgt;
2665 if (blink > 0) {
2666 int post_delay = insn_bytes;
2667 int lowbit = !!(ctx->hflags & MIPS_HFLAG_M16);
2669 if (opc != OPC_JALRC)
2670 post_delay += ((ctx->hflags & MIPS_HFLAG_BDS16) ? 2 : 4);
2672 tcg_gen_movi_tl(cpu_gpr[blink], ctx->pc + post_delay + lowbit);
2675 out:
2676 if (insn_bytes == 2)
2677 ctx->hflags |= MIPS_HFLAG_B16;
2678 tcg_temp_free(t0);
2679 tcg_temp_free(t1);
2682 /* special3 bitfield operations */
2683 static void gen_bitops (DisasContext *ctx, uint32_t opc, int rt,
2684 int rs, int lsb, int msb)
2686 TCGv t0 = tcg_temp_new();
2687 TCGv t1 = tcg_temp_new();
2688 target_ulong mask;
2690 gen_load_gpr(t1, rs);
2691 switch (opc) {
2692 case OPC_EXT:
2693 if (lsb + msb > 31)
2694 goto fail;
2695 tcg_gen_shri_tl(t0, t1, lsb);
2696 if (msb != 31) {
2697 tcg_gen_andi_tl(t0, t0, (1 << (msb + 1)) - 1);
2698 } else {
2699 tcg_gen_ext32s_tl(t0, t0);
2701 break;
2702 #if defined(TARGET_MIPS64)
2703 case OPC_DEXTM:
2704 tcg_gen_shri_tl(t0, t1, lsb);
2705 if (msb != 31) {
2706 tcg_gen_andi_tl(t0, t0, (1ULL << (msb + 1 + 32)) - 1);
2708 break;
2709 case OPC_DEXTU:
2710 tcg_gen_shri_tl(t0, t1, lsb + 32);
2711 tcg_gen_andi_tl(t0, t0, (1ULL << (msb + 1)) - 1);
2712 break;
2713 case OPC_DEXT:
2714 tcg_gen_shri_tl(t0, t1, lsb);
2715 tcg_gen_andi_tl(t0, t0, (1ULL << (msb + 1)) - 1);
2716 break;
2717 #endif
2718 case OPC_INS:
2719 if (lsb > msb)
2720 goto fail;
2721 mask = ((msb - lsb + 1 < 32) ? ((1 << (msb - lsb + 1)) - 1) : ~0) << lsb;
2722 gen_load_gpr(t0, rt);
2723 tcg_gen_andi_tl(t0, t0, ~mask);
2724 tcg_gen_shli_tl(t1, t1, lsb);
2725 tcg_gen_andi_tl(t1, t1, mask);
2726 tcg_gen_or_tl(t0, t0, t1);
2727 tcg_gen_ext32s_tl(t0, t0);
2728 break;
2729 #if defined(TARGET_MIPS64)
2730 case OPC_DINSM:
2731 if (lsb > msb)
2732 goto fail;
2733 mask = ((msb - lsb + 1 + 32 < 64) ? ((1ULL << (msb - lsb + 1 + 32)) - 1) : ~0ULL) << lsb;
2734 gen_load_gpr(t0, rt);
2735 tcg_gen_andi_tl(t0, t0, ~mask);
2736 tcg_gen_shli_tl(t1, t1, lsb);
2737 tcg_gen_andi_tl(t1, t1, mask);
2738 tcg_gen_or_tl(t0, t0, t1);
2739 break;
2740 case OPC_DINSU:
2741 if (lsb > msb)
2742 goto fail;
2743 mask = ((1ULL << (msb - lsb + 1)) - 1) << lsb;
2744 gen_load_gpr(t0, rt);
2745 tcg_gen_andi_tl(t0, t0, ~mask);
2746 tcg_gen_shli_tl(t1, t1, lsb + 32);
2747 tcg_gen_andi_tl(t1, t1, mask);
2748 tcg_gen_or_tl(t0, t0, t1);
2749 break;
2750 case OPC_DINS:
2751 if (lsb > msb)
2752 goto fail;
2753 gen_load_gpr(t0, rt);
2754 mask = ((1ULL << (msb - lsb + 1)) - 1) << lsb;
2755 gen_load_gpr(t0, rt);
2756 tcg_gen_andi_tl(t0, t0, ~mask);
2757 tcg_gen_shli_tl(t1, t1, lsb);
2758 tcg_gen_andi_tl(t1, t1, mask);
2759 tcg_gen_or_tl(t0, t0, t1);
2760 break;
2761 #endif
2762 default:
2763 fail:
2764 MIPS_INVAL("bitops");
2765 generate_exception(ctx, EXCP_RI);
2766 tcg_temp_free(t0);
2767 tcg_temp_free(t1);
2768 return;
2770 gen_store_gpr(t0, rt);
2771 tcg_temp_free(t0);
2772 tcg_temp_free(t1);
2775 static void gen_bshfl (DisasContext *ctx, uint32_t op2, int rt, int rd)
2777 TCGv t0;
2779 if (rd == 0) {
2780 /* If no destination, treat it as a NOP. */
2781 MIPS_DEBUG("NOP");
2782 return;
2785 t0 = tcg_temp_new();
2786 gen_load_gpr(t0, rt);
2787 switch (op2) {
2788 case OPC_WSBH:
2790 TCGv t1 = tcg_temp_new();
2792 tcg_gen_shri_tl(t1, t0, 8);
2793 tcg_gen_andi_tl(t1, t1, 0x00FF00FF);
2794 tcg_gen_shli_tl(t0, t0, 8);
2795 tcg_gen_andi_tl(t0, t0, ~0x00FF00FF);
2796 tcg_gen_or_tl(t0, t0, t1);
2797 tcg_temp_free(t1);
2798 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
2800 break;
2801 case OPC_SEB:
2802 tcg_gen_ext8s_tl(cpu_gpr[rd], t0);
2803 break;
2804 case OPC_SEH:
2805 tcg_gen_ext16s_tl(cpu_gpr[rd], t0);
2806 break;
2807 #if defined(TARGET_MIPS64)
2808 case OPC_DSBH:
2810 TCGv t1 = tcg_temp_new();
2812 tcg_gen_shri_tl(t1, t0, 8);
2813 tcg_gen_andi_tl(t1, t1, 0x00FF00FF00FF00FFULL);
2814 tcg_gen_shli_tl(t0, t0, 8);
2815 tcg_gen_andi_tl(t0, t0, ~0x00FF00FF00FF00FFULL);
2816 tcg_gen_or_tl(cpu_gpr[rd], t0, t1);
2817 tcg_temp_free(t1);
2819 break;
2820 case OPC_DSHD:
2822 TCGv t1 = tcg_temp_new();
2824 tcg_gen_shri_tl(t1, t0, 16);
2825 tcg_gen_andi_tl(t1, t1, 0x0000FFFF0000FFFFULL);
2826 tcg_gen_shli_tl(t0, t0, 16);
2827 tcg_gen_andi_tl(t0, t0, ~0x0000FFFF0000FFFFULL);
2828 tcg_gen_or_tl(t0, t0, t1);
2829 tcg_gen_shri_tl(t1, t0, 32);
2830 tcg_gen_shli_tl(t0, t0, 32);
2831 tcg_gen_or_tl(cpu_gpr[rd], t0, t1);
2832 tcg_temp_free(t1);
2834 break;
2835 #endif
2836 default:
2837 MIPS_INVAL("bsfhl");
2838 generate_exception(ctx, EXCP_RI);
2839 tcg_temp_free(t0);
2840 return;
2842 tcg_temp_free(t0);
2845 #ifndef CONFIG_USER_ONLY
2846 /* CP0 (MMU and control) */
2847 static inline void gen_mfc0_load32 (TCGv arg, target_ulong off)
2849 TCGv_i32 t0 = tcg_temp_new_i32();
2851 tcg_gen_ld_i32(t0, cpu_env, off);
2852 tcg_gen_ext_i32_tl(arg, t0);
2853 tcg_temp_free_i32(t0);
2856 static inline void gen_mfc0_load64 (TCGv arg, target_ulong off)
2858 tcg_gen_ld_tl(arg, cpu_env, off);
2859 tcg_gen_ext32s_tl(arg, arg);
2862 static inline void gen_mtc0_store32 (TCGv arg, target_ulong off)
2864 TCGv_i32 t0 = tcg_temp_new_i32();
2866 tcg_gen_trunc_tl_i32(t0, arg);
2867 tcg_gen_st_i32(t0, cpu_env, off);
2868 tcg_temp_free_i32(t0);
2871 static inline void gen_mtc0_store64 (TCGv arg, target_ulong off)
2873 tcg_gen_ext32s_tl(arg, arg);
2874 tcg_gen_st_tl(arg, cpu_env, off);
2877 static void gen_mfc0 (CPUState *env, DisasContext *ctx, TCGv arg, int reg, int sel)
2879 const char *rn = "invalid";
2881 if (sel != 0)
2882 check_insn(env, ctx, ISA_MIPS32);
2884 switch (reg) {
2885 case 0:
2886 switch (sel) {
2887 case 0:
2888 gen_mfc0_load32(arg, offsetof(CPUState, CP0_Index));
2889 rn = "Index";
2890 break;
2891 case 1:
2892 check_insn(env, ctx, ASE_MT);
2893 gen_helper_mfc0_mvpcontrol(arg);
2894 rn = "MVPControl";
2895 break;
2896 case 2:
2897 check_insn(env, ctx, ASE_MT);
2898 gen_helper_mfc0_mvpconf0(arg);
2899 rn = "MVPConf0";
2900 break;
2901 case 3:
2902 check_insn(env, ctx, ASE_MT);
2903 gen_helper_mfc0_mvpconf1(arg);
2904 rn = "MVPConf1";
2905 break;
2906 default:
2907 goto die;
2909 break;
2910 case 1:
2911 switch (sel) {
2912 case 0:
2913 gen_helper_mfc0_random(arg);
2914 rn = "Random";
2915 break;
2916 case 1:
2917 check_insn(env, ctx, ASE_MT);
2918 gen_mfc0_load32(arg, offsetof(CPUState, CP0_VPEControl));
2919 rn = "VPEControl";
2920 break;
2921 case 2:
2922 check_insn(env, ctx, ASE_MT);
2923 gen_mfc0_load32(arg, offsetof(CPUState, CP0_VPEConf0));
2924 rn = "VPEConf0";
2925 break;
2926 case 3:
2927 check_insn(env, ctx, ASE_MT);
2928 gen_mfc0_load32(arg, offsetof(CPUState, CP0_VPEConf1));
2929 rn = "VPEConf1";
2930 break;
2931 case 4:
2932 check_insn(env, ctx, ASE_MT);
2933 gen_mfc0_load64(arg, offsetof(CPUState, CP0_YQMask));
2934 rn = "YQMask";
2935 break;
2936 case 5:
2937 check_insn(env, ctx, ASE_MT);
2938 gen_mfc0_load64(arg, offsetof(CPUState, CP0_VPESchedule));
2939 rn = "VPESchedule";
2940 break;
2941 case 6:
2942 check_insn(env, ctx, ASE_MT);
2943 gen_mfc0_load64(arg, offsetof(CPUState, CP0_VPEScheFBack));
2944 rn = "VPEScheFBack";
2945 break;
2946 case 7:
2947 check_insn(env, ctx, ASE_MT);
2948 gen_mfc0_load32(arg, offsetof(CPUState, CP0_VPEOpt));
2949 rn = "VPEOpt";
2950 break;
2951 default:
2952 goto die;
2954 break;
2955 case 2:
2956 switch (sel) {
2957 case 0:
2958 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_EntryLo0));
2959 tcg_gen_ext32s_tl(arg, arg);
2960 rn = "EntryLo0";
2961 break;
2962 case 1:
2963 check_insn(env, ctx, ASE_MT);
2964 gen_helper_mfc0_tcstatus(arg);
2965 rn = "TCStatus";
2966 break;
2967 case 2:
2968 check_insn(env, ctx, ASE_MT);
2969 gen_helper_mfc0_tcbind(arg);
2970 rn = "TCBind";
2971 break;
2972 case 3:
2973 check_insn(env, ctx, ASE_MT);
2974 gen_helper_mfc0_tcrestart(arg);
2975 rn = "TCRestart";
2976 break;
2977 case 4:
2978 check_insn(env, ctx, ASE_MT);
2979 gen_helper_mfc0_tchalt(arg);
2980 rn = "TCHalt";
2981 break;
2982 case 5:
2983 check_insn(env, ctx, ASE_MT);
2984 gen_helper_mfc0_tccontext(arg);
2985 rn = "TCContext";
2986 break;
2987 case 6:
2988 check_insn(env, ctx, ASE_MT);
2989 gen_helper_mfc0_tcschedule(arg);
2990 rn = "TCSchedule";
2991 break;
2992 case 7:
2993 check_insn(env, ctx, ASE_MT);
2994 gen_helper_mfc0_tcschefback(arg);
2995 rn = "TCScheFBack";
2996 break;
2997 default:
2998 goto die;
3000 break;
3001 case 3:
3002 switch (sel) {
3003 case 0:
3004 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_EntryLo1));
3005 tcg_gen_ext32s_tl(arg, arg);
3006 rn = "EntryLo1";
3007 break;
3008 default:
3009 goto die;
3011 break;
3012 case 4:
3013 switch (sel) {
3014 case 0:
3015 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_Context));
3016 tcg_gen_ext32s_tl(arg, arg);
3017 rn = "Context";
3018 break;
3019 case 1:
3020 // gen_helper_mfc0_contextconfig(arg); /* SmartMIPS ASE */
3021 rn = "ContextConfig";
3022 // break;
3023 default:
3024 goto die;
3026 break;
3027 case 5:
3028 switch (sel) {
3029 case 0:
3030 gen_mfc0_load32(arg, offsetof(CPUState, CP0_PageMask));
3031 rn = "PageMask";
3032 break;
3033 case 1:
3034 check_insn(env, ctx, ISA_MIPS32R2);
3035 gen_mfc0_load32(arg, offsetof(CPUState, CP0_PageGrain));
3036 rn = "PageGrain";
3037 break;
3038 default:
3039 goto die;
3041 break;
3042 case 6:
3043 switch (sel) {
3044 case 0:
3045 gen_mfc0_load32(arg, offsetof(CPUState, CP0_Wired));
3046 rn = "Wired";
3047 break;
3048 case 1:
3049 check_insn(env, ctx, ISA_MIPS32R2);
3050 gen_mfc0_load32(arg, offsetof(CPUState, CP0_SRSConf0));
3051 rn = "SRSConf0";
3052 break;
3053 case 2:
3054 check_insn(env, ctx, ISA_MIPS32R2);
3055 gen_mfc0_load32(arg, offsetof(CPUState, CP0_SRSConf1));
3056 rn = "SRSConf1";
3057 break;
3058 case 3:
3059 check_insn(env, ctx, ISA_MIPS32R2);
3060 gen_mfc0_load32(arg, offsetof(CPUState, CP0_SRSConf2));
3061 rn = "SRSConf2";
3062 break;
3063 case 4:
3064 check_insn(env, ctx, ISA_MIPS32R2);
3065 gen_mfc0_load32(arg, offsetof(CPUState, CP0_SRSConf3));
3066 rn = "SRSConf3";
3067 break;
3068 case 5:
3069 check_insn(env, ctx, ISA_MIPS32R2);
3070 gen_mfc0_load32(arg, offsetof(CPUState, CP0_SRSConf4));
3071 rn = "SRSConf4";
3072 break;
3073 default:
3074 goto die;
3076 break;
3077 case 7:
3078 switch (sel) {
3079 case 0:
3080 check_insn(env, ctx, ISA_MIPS32R2);
3081 gen_mfc0_load32(arg, offsetof(CPUState, CP0_HWREna));
3082 rn = "HWREna";
3083 break;
3084 default:
3085 goto die;
3087 break;
3088 case 8:
3089 switch (sel) {
3090 case 0:
3091 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_BadVAddr));
3092 tcg_gen_ext32s_tl(arg, arg);
3093 rn = "BadVAddr";
3094 break;
3095 default:
3096 goto die;
3098 break;
3099 case 9:
3100 switch (sel) {
3101 case 0:
3102 /* Mark as an IO operation because we read the time. */
3103 if (use_icount)
3104 gen_io_start();
3105 gen_helper_mfc0_count(arg);
3106 if (use_icount) {
3107 gen_io_end();
3108 ctx->bstate = BS_STOP;
3110 rn = "Count";
3111 break;
3112 /* 6,7 are implementation dependent */
3113 default:
3114 goto die;
3116 break;
3117 case 10:
3118 switch (sel) {
3119 case 0:
3120 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_EntryHi));
3121 tcg_gen_ext32s_tl(arg, arg);
3122 rn = "EntryHi";
3123 break;
3124 default:
3125 goto die;
3127 break;
3128 case 11:
3129 switch (sel) {
3130 case 0:
3131 gen_mfc0_load32(arg, offsetof(CPUState, CP0_Compare));
3132 rn = "Compare";
3133 break;
3134 /* 6,7 are implementation dependent */
3135 default:
3136 goto die;
3138 break;
3139 case 12:
3140 switch (sel) {
3141 case 0:
3142 gen_mfc0_load32(arg, offsetof(CPUState, CP0_Status));
3143 rn = "Status";
3144 break;
3145 case 1:
3146 check_insn(env, ctx, ISA_MIPS32R2);
3147 gen_mfc0_load32(arg, offsetof(CPUState, CP0_IntCtl));
3148 rn = "IntCtl";
3149 break;
3150 case 2:
3151 check_insn(env, ctx, ISA_MIPS32R2);
3152 gen_mfc0_load32(arg, offsetof(CPUState, CP0_SRSCtl));
3153 rn = "SRSCtl";
3154 break;
3155 case 3:
3156 check_insn(env, ctx, ISA_MIPS32R2);
3157 gen_mfc0_load32(arg, offsetof(CPUState, CP0_SRSMap));
3158 rn = "SRSMap";
3159 break;
3160 default:
3161 goto die;
3163 break;
3164 case 13:
3165 switch (sel) {
3166 case 0:
3167 gen_mfc0_load32(arg, offsetof(CPUState, CP0_Cause));
3168 rn = "Cause";
3169 break;
3170 default:
3171 goto die;
3173 break;
3174 case 14:
3175 switch (sel) {
3176 case 0:
3177 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_EPC));
3178 tcg_gen_ext32s_tl(arg, arg);
3179 rn = "EPC";
3180 break;
3181 default:
3182 goto die;
3184 break;
3185 case 15:
3186 switch (sel) {
3187 case 0:
3188 gen_mfc0_load32(arg, offsetof(CPUState, CP0_PRid));
3189 rn = "PRid";
3190 break;
3191 case 1:
3192 check_insn(env, ctx, ISA_MIPS32R2);
3193 gen_mfc0_load32(arg, offsetof(CPUState, CP0_EBase));
3194 rn = "EBase";
3195 break;
3196 default:
3197 goto die;
3199 break;
3200 case 16:
3201 switch (sel) {
3202 case 0:
3203 gen_mfc0_load32(arg, offsetof(CPUState, CP0_Config0));
3204 rn = "Config";
3205 break;
3206 case 1:
3207 gen_mfc0_load32(arg, offsetof(CPUState, CP0_Config1));
3208 rn = "Config1";
3209 break;
3210 case 2:
3211 gen_mfc0_load32(arg, offsetof(CPUState, CP0_Config2));
3212 rn = "Config2";
3213 break;
3214 case 3:
3215 gen_mfc0_load32(arg, offsetof(CPUState, CP0_Config3));
3216 rn = "Config3";
3217 break;
3218 /* 4,5 are reserved */
3219 /* 6,7 are implementation dependent */
3220 case 6:
3221 gen_mfc0_load32(arg, offsetof(CPUState, CP0_Config6));
3222 rn = "Config6";
3223 break;
3224 case 7:
3225 gen_mfc0_load32(arg, offsetof(CPUState, CP0_Config7));
3226 rn = "Config7";
3227 break;
3228 default:
3229 goto die;
3231 break;
3232 case 17:
3233 switch (sel) {
3234 case 0:
3235 gen_helper_mfc0_lladdr(arg);
3236 rn = "LLAddr";
3237 break;
3238 default:
3239 goto die;
3241 break;
3242 case 18:
3243 switch (sel) {
3244 case 0 ... 7:
3245 gen_helper_1i(mfc0_watchlo, arg, sel);
3246 rn = "WatchLo";
3247 break;
3248 default:
3249 goto die;
3251 break;
3252 case 19:
3253 switch (sel) {
3254 case 0 ...7:
3255 gen_helper_1i(mfc0_watchhi, arg, sel);
3256 rn = "WatchHi";
3257 break;
3258 default:
3259 goto die;
3261 break;
3262 case 20:
3263 switch (sel) {
3264 case 0:
3265 #if defined(TARGET_MIPS64)
3266 check_insn(env, ctx, ISA_MIPS3);
3267 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_XContext));
3268 tcg_gen_ext32s_tl(arg, arg);
3269 rn = "XContext";
3270 break;
3271 #endif
3272 default:
3273 goto die;
3275 break;
3276 case 21:
3277 /* Officially reserved, but sel 0 is used for R1x000 framemask */
3278 switch (sel) {
3279 case 0:
3280 gen_mfc0_load32(arg, offsetof(CPUState, CP0_Framemask));
3281 rn = "Framemask";
3282 break;
3283 default:
3284 goto die;
3286 break;
3287 case 22:
3288 tcg_gen_movi_tl(arg, 0); /* unimplemented */
3289 rn = "'Diagnostic"; /* implementation dependent */
3290 break;
3291 case 23:
3292 switch (sel) {
3293 case 0:
3294 gen_helper_mfc0_debug(arg); /* EJTAG support */
3295 rn = "Debug";
3296 break;
3297 case 1:
3298 // gen_helper_mfc0_tracecontrol(arg); /* PDtrace support */
3299 rn = "TraceControl";
3300 // break;
3301 case 2:
3302 // gen_helper_mfc0_tracecontrol2(arg); /* PDtrace support */
3303 rn = "TraceControl2";
3304 // break;
3305 case 3:
3306 // gen_helper_mfc0_usertracedata(arg); /* PDtrace support */
3307 rn = "UserTraceData";
3308 // break;
3309 case 4:
3310 // gen_helper_mfc0_tracebpc(arg); /* PDtrace support */
3311 rn = "TraceBPC";
3312 // break;
3313 default:
3314 goto die;
3316 break;
3317 case 24:
3318 switch (sel) {
3319 case 0:
3320 /* EJTAG support */
3321 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_DEPC));
3322 tcg_gen_ext32s_tl(arg, arg);
3323 rn = "DEPC";
3324 break;
3325 default:
3326 goto die;
3328 break;
3329 case 25:
3330 switch (sel) {
3331 case 0:
3332 gen_mfc0_load32(arg, offsetof(CPUState, CP0_Performance0));
3333 rn = "Performance0";
3334 break;
3335 case 1:
3336 // gen_helper_mfc0_performance1(arg);
3337 rn = "Performance1";
3338 // break;
3339 case 2:
3340 // gen_helper_mfc0_performance2(arg);
3341 rn = "Performance2";
3342 // break;
3343 case 3:
3344 // gen_helper_mfc0_performance3(arg);
3345 rn = "Performance3";
3346 // break;
3347 case 4:
3348 // gen_helper_mfc0_performance4(arg);
3349 rn = "Performance4";
3350 // break;
3351 case 5:
3352 // gen_helper_mfc0_performance5(arg);
3353 rn = "Performance5";
3354 // break;
3355 case 6:
3356 // gen_helper_mfc0_performance6(arg);
3357 rn = "Performance6";
3358 // break;
3359 case 7:
3360 // gen_helper_mfc0_performance7(arg);
3361 rn = "Performance7";
3362 // break;
3363 default:
3364 goto die;
3366 break;
3367 case 26:
3368 tcg_gen_movi_tl(arg, 0); /* unimplemented */
3369 rn = "ECC";
3370 break;
3371 case 27:
3372 switch (sel) {
3373 case 0 ... 3:
3374 tcg_gen_movi_tl(arg, 0); /* unimplemented */
3375 rn = "CacheErr";
3376 break;
3377 default:
3378 goto die;
3380 break;
3381 case 28:
3382 switch (sel) {
3383 case 0:
3384 case 2:
3385 case 4:
3386 case 6:
3387 gen_mfc0_load32(arg, offsetof(CPUState, CP0_TagLo));
3388 rn = "TagLo";
3389 break;
3390 case 1:
3391 case 3:
3392 case 5:
3393 case 7:
3394 gen_mfc0_load32(arg, offsetof(CPUState, CP0_DataLo));
3395 rn = "DataLo";
3396 break;
3397 default:
3398 goto die;
3400 break;
3401 case 29:
3402 switch (sel) {
3403 case 0:
3404 case 2:
3405 case 4:
3406 case 6:
3407 gen_mfc0_load32(arg, offsetof(CPUState, CP0_TagHi));
3408 rn = "TagHi";
3409 break;
3410 case 1:
3411 case 3:
3412 case 5:
3413 case 7:
3414 gen_mfc0_load32(arg, offsetof(CPUState, CP0_DataHi));
3415 rn = "DataHi";
3416 break;
3417 default:
3418 goto die;
3420 break;
3421 case 30:
3422 switch (sel) {
3423 case 0:
3424 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_ErrorEPC));
3425 tcg_gen_ext32s_tl(arg, arg);
3426 rn = "ErrorEPC";
3427 break;
3428 default:
3429 goto die;
3431 break;
3432 case 31:
3433 switch (sel) {
3434 case 0:
3435 /* EJTAG support */
3436 gen_mfc0_load32(arg, offsetof(CPUState, CP0_DESAVE));
3437 rn = "DESAVE";
3438 break;
3439 default:
3440 goto die;
3442 break;
3443 default:
3444 goto die;
3446 LOG_DISAS("mfc0 %s (reg %d sel %d)\n", rn, reg, sel);
3447 return;
3449 die:
3450 LOG_DISAS("mfc0 %s (reg %d sel %d)\n", rn, reg, sel);
3451 generate_exception(ctx, EXCP_RI);
3454 static void gen_mtc0 (CPUState *env, DisasContext *ctx, TCGv arg, int reg, int sel)
3456 const char *rn = "invalid";
3458 if (sel != 0)
3459 check_insn(env, ctx, ISA_MIPS32);
3461 if (use_icount)
3462 gen_io_start();
3464 switch (reg) {
3465 case 0:
3466 switch (sel) {
3467 case 0:
3468 gen_helper_mtc0_index(arg);
3469 rn = "Index";
3470 break;
3471 case 1:
3472 check_insn(env, ctx, ASE_MT);
3473 gen_helper_mtc0_mvpcontrol(arg);
3474 rn = "MVPControl";
3475 break;
3476 case 2:
3477 check_insn(env, ctx, ASE_MT);
3478 /* ignored */
3479 rn = "MVPConf0";
3480 break;
3481 case 3:
3482 check_insn(env, ctx, ASE_MT);
3483 /* ignored */
3484 rn = "MVPConf1";
3485 break;
3486 default:
3487 goto die;
3489 break;
3490 case 1:
3491 switch (sel) {
3492 case 0:
3493 /* ignored */
3494 rn = "Random";
3495 break;
3496 case 1:
3497 check_insn(env, ctx, ASE_MT);
3498 gen_helper_mtc0_vpecontrol(arg);
3499 rn = "VPEControl";
3500 break;
3501 case 2:
3502 check_insn(env, ctx, ASE_MT);
3503 gen_helper_mtc0_vpeconf0(arg);
3504 rn = "VPEConf0";
3505 break;
3506 case 3:
3507 check_insn(env, ctx, ASE_MT);
3508 gen_helper_mtc0_vpeconf1(arg);
3509 rn = "VPEConf1";
3510 break;
3511 case 4:
3512 check_insn(env, ctx, ASE_MT);
3513 gen_helper_mtc0_yqmask(arg);
3514 rn = "YQMask";
3515 break;
3516 case 5:
3517 check_insn(env, ctx, ASE_MT);
3518 gen_mtc0_store64(arg, offsetof(CPUState, CP0_VPESchedule));
3519 rn = "VPESchedule";
3520 break;
3521 case 6:
3522 check_insn(env, ctx, ASE_MT);
3523 gen_mtc0_store64(arg, offsetof(CPUState, CP0_VPEScheFBack));
3524 rn = "VPEScheFBack";
3525 break;
3526 case 7:
3527 check_insn(env, ctx, ASE_MT);
3528 gen_helper_mtc0_vpeopt(arg);
3529 rn = "VPEOpt";
3530 break;
3531 default:
3532 goto die;
3534 break;
3535 case 2:
3536 switch (sel) {
3537 case 0:
3538 gen_helper_mtc0_entrylo0(arg);
3539 rn = "EntryLo0";
3540 break;
3541 case 1:
3542 check_insn(env, ctx, ASE_MT);
3543 gen_helper_mtc0_tcstatus(arg);
3544 rn = "TCStatus";
3545 break;
3546 case 2:
3547 check_insn(env, ctx, ASE_MT);
3548 gen_helper_mtc0_tcbind(arg);
3549 rn = "TCBind";
3550 break;
3551 case 3:
3552 check_insn(env, ctx, ASE_MT);
3553 gen_helper_mtc0_tcrestart(arg);
3554 rn = "TCRestart";
3555 break;
3556 case 4:
3557 check_insn(env, ctx, ASE_MT);
3558 gen_helper_mtc0_tchalt(arg);
3559 rn = "TCHalt";
3560 break;
3561 case 5:
3562 check_insn(env, ctx, ASE_MT);
3563 gen_helper_mtc0_tccontext(arg);
3564 rn = "TCContext";
3565 break;
3566 case 6:
3567 check_insn(env, ctx, ASE_MT);
3568 gen_helper_mtc0_tcschedule(arg);
3569 rn = "TCSchedule";
3570 break;
3571 case 7:
3572 check_insn(env, ctx, ASE_MT);
3573 gen_helper_mtc0_tcschefback(arg);
3574 rn = "TCScheFBack";
3575 break;
3576 default:
3577 goto die;
3579 break;
3580 case 3:
3581 switch (sel) {
3582 case 0:
3583 gen_helper_mtc0_entrylo1(arg);
3584 rn = "EntryLo1";
3585 break;
3586 default:
3587 goto die;
3589 break;
3590 case 4:
3591 switch (sel) {
3592 case 0:
3593 gen_helper_mtc0_context(arg);
3594 rn = "Context";
3595 break;
3596 case 1:
3597 // gen_helper_mtc0_contextconfig(arg); /* SmartMIPS ASE */
3598 rn = "ContextConfig";
3599 // break;
3600 default:
3601 goto die;
3603 break;
3604 case 5:
3605 switch (sel) {
3606 case 0:
3607 gen_helper_mtc0_pagemask(arg);
3608 rn = "PageMask";
3609 break;
3610 case 1:
3611 check_insn(env, ctx, ISA_MIPS32R2);
3612 gen_helper_mtc0_pagegrain(arg);
3613 rn = "PageGrain";
3614 break;
3615 default:
3616 goto die;
3618 break;
3619 case 6:
3620 switch (sel) {
3621 case 0:
3622 gen_helper_mtc0_wired(arg);
3623 rn = "Wired";
3624 break;
3625 case 1:
3626 check_insn(env, ctx, ISA_MIPS32R2);
3627 gen_helper_mtc0_srsconf0(arg);
3628 rn = "SRSConf0";
3629 break;
3630 case 2:
3631 check_insn(env, ctx, ISA_MIPS32R2);
3632 gen_helper_mtc0_srsconf1(arg);
3633 rn = "SRSConf1";
3634 break;
3635 case 3:
3636 check_insn(env, ctx, ISA_MIPS32R2);
3637 gen_helper_mtc0_srsconf2(arg);
3638 rn = "SRSConf2";
3639 break;
3640 case 4:
3641 check_insn(env, ctx, ISA_MIPS32R2);
3642 gen_helper_mtc0_srsconf3(arg);
3643 rn = "SRSConf3";
3644 break;
3645 case 5:
3646 check_insn(env, ctx, ISA_MIPS32R2);
3647 gen_helper_mtc0_srsconf4(arg);
3648 rn = "SRSConf4";
3649 break;
3650 default:
3651 goto die;
3653 break;
3654 case 7:
3655 switch (sel) {
3656 case 0:
3657 check_insn(env, ctx, ISA_MIPS32R2);
3658 gen_helper_mtc0_hwrena(arg);
3659 rn = "HWREna";
3660 break;
3661 default:
3662 goto die;
3664 break;
3665 case 8:
3666 /* ignored */
3667 rn = "BadVAddr";
3668 break;
3669 case 9:
3670 switch (sel) {
3671 case 0:
3672 gen_helper_mtc0_count(arg);
3673 rn = "Count";
3674 break;
3675 /* 6,7 are implementation dependent */
3676 default:
3677 goto die;
3679 break;
3680 case 10:
3681 switch (sel) {
3682 case 0:
3683 gen_helper_mtc0_entryhi(arg);
3684 rn = "EntryHi";
3685 break;
3686 default:
3687 goto die;
3689 break;
3690 case 11:
3691 switch (sel) {
3692 case 0:
3693 gen_helper_mtc0_compare(arg);
3694 rn = "Compare";
3695 break;
3696 /* 6,7 are implementation dependent */
3697 default:
3698 goto die;
3700 break;
3701 case 12:
3702 switch (sel) {
3703 case 0:
3704 save_cpu_state(ctx, 1);
3705 gen_helper_mtc0_status(arg);
3706 /* BS_STOP isn't good enough here, hflags may have changed. */
3707 gen_save_pc(ctx->pc + 4);
3708 ctx->bstate = BS_EXCP;
3709 rn = "Status";
3710 break;
3711 case 1:
3712 check_insn(env, ctx, ISA_MIPS32R2);
3713 gen_helper_mtc0_intctl(arg);
3714 /* Stop translation as we may have switched the execution mode */
3715 ctx->bstate = BS_STOP;
3716 rn = "IntCtl";
3717 break;
3718 case 2:
3719 check_insn(env, ctx, ISA_MIPS32R2);
3720 gen_helper_mtc0_srsctl(arg);
3721 /* Stop translation as we may have switched the execution mode */
3722 ctx->bstate = BS_STOP;
3723 rn = "SRSCtl";
3724 break;
3725 case 3:
3726 check_insn(env, ctx, ISA_MIPS32R2);
3727 gen_mtc0_store32(arg, offsetof(CPUState, CP0_SRSMap));
3728 /* Stop translation as we may have switched the execution mode */
3729 ctx->bstate = BS_STOP;
3730 rn = "SRSMap";
3731 break;
3732 default:
3733 goto die;
3735 break;
3736 case 13:
3737 switch (sel) {
3738 case 0:
3739 save_cpu_state(ctx, 1);
3740 gen_helper_mtc0_cause(arg);
3741 rn = "Cause";
3742 break;
3743 default:
3744 goto die;
3746 break;
3747 case 14:
3748 switch (sel) {
3749 case 0:
3750 gen_mtc0_store64(arg, offsetof(CPUState, CP0_EPC));
3751 rn = "EPC";
3752 break;
3753 default:
3754 goto die;
3756 break;
3757 case 15:
3758 switch (sel) {
3759 case 0:
3760 /* ignored */
3761 rn = "PRid";
3762 break;
3763 case 1:
3764 check_insn(env, ctx, ISA_MIPS32R2);
3765 gen_helper_mtc0_ebase(arg);
3766 rn = "EBase";
3767 break;
3768 default:
3769 goto die;
3771 break;
3772 case 16:
3773 switch (sel) {
3774 case 0:
3775 gen_helper_mtc0_config0(arg);
3776 rn = "Config";
3777 /* Stop translation as we may have switched the execution mode */
3778 ctx->bstate = BS_STOP;
3779 break;
3780 case 1:
3781 /* ignored, read only */
3782 rn = "Config1";
3783 break;
3784 case 2:
3785 gen_helper_mtc0_config2(arg);
3786 rn = "Config2";
3787 /* Stop translation as we may have switched the execution mode */
3788 ctx->bstate = BS_STOP;
3789 break;
3790 case 3:
3791 /* ignored, read only */
3792 rn = "Config3";
3793 break;
3794 /* 4,5 are reserved */
3795 /* 6,7 are implementation dependent */
3796 case 6:
3797 /* ignored */
3798 rn = "Config6";
3799 break;
3800 case 7:
3801 /* ignored */
3802 rn = "Config7";
3803 break;
3804 default:
3805 rn = "Invalid config selector";
3806 goto die;
3808 break;
3809 case 17:
3810 switch (sel) {
3811 case 0:
3812 gen_helper_mtc0_lladdr(arg);
3813 rn = "LLAddr";
3814 break;
3815 default:
3816 goto die;
3818 break;
3819 case 18:
3820 switch (sel) {
3821 case 0 ... 7:
3822 gen_helper_1i(mtc0_watchlo, arg, sel);
3823 rn = "WatchLo";
3824 break;
3825 default:
3826 goto die;
3828 break;
3829 case 19:
3830 switch (sel) {
3831 case 0 ... 7:
3832 gen_helper_1i(mtc0_watchhi, arg, sel);
3833 rn = "WatchHi";
3834 break;
3835 default:
3836 goto die;
3838 break;
3839 case 20:
3840 switch (sel) {
3841 case 0:
3842 #if defined(TARGET_MIPS64)
3843 check_insn(env, ctx, ISA_MIPS3);
3844 gen_helper_mtc0_xcontext(arg);
3845 rn = "XContext";
3846 break;
3847 #endif
3848 default:
3849 goto die;
3851 break;
3852 case 21:
3853 /* Officially reserved, but sel 0 is used for R1x000 framemask */
3854 switch (sel) {
3855 case 0:
3856 gen_helper_mtc0_framemask(arg);
3857 rn = "Framemask";
3858 break;
3859 default:
3860 goto die;
3862 break;
3863 case 22:
3864 /* ignored */
3865 rn = "Diagnostic"; /* implementation dependent */
3866 break;
3867 case 23:
3868 switch (sel) {
3869 case 0:
3870 gen_helper_mtc0_debug(arg); /* EJTAG support */
3871 /* BS_STOP isn't good enough here, hflags may have changed. */
3872 gen_save_pc(ctx->pc + 4);
3873 ctx->bstate = BS_EXCP;
3874 rn = "Debug";
3875 break;
3876 case 1:
3877 // gen_helper_mtc0_tracecontrol(arg); /* PDtrace support */
3878 rn = "TraceControl";
3879 /* Stop translation as we may have switched the execution mode */
3880 ctx->bstate = BS_STOP;
3881 // break;
3882 case 2:
3883 // gen_helper_mtc0_tracecontrol2(arg); /* PDtrace support */
3884 rn = "TraceControl2";
3885 /* Stop translation as we may have switched the execution mode */
3886 ctx->bstate = BS_STOP;
3887 // break;
3888 case 3:
3889 /* Stop translation as we may have switched the execution mode */
3890 ctx->bstate = BS_STOP;
3891 // gen_helper_mtc0_usertracedata(arg); /* PDtrace support */
3892 rn = "UserTraceData";
3893 /* Stop translation as we may have switched the execution mode */
3894 ctx->bstate = BS_STOP;
3895 // break;
3896 case 4:
3897 // gen_helper_mtc0_tracebpc(arg); /* PDtrace support */
3898 /* Stop translation as we may have switched the execution mode */
3899 ctx->bstate = BS_STOP;
3900 rn = "TraceBPC";
3901 // break;
3902 default:
3903 goto die;
3905 break;
3906 case 24:
3907 switch (sel) {
3908 case 0:
3909 /* EJTAG support */
3910 gen_mtc0_store64(arg, offsetof(CPUState, CP0_DEPC));
3911 rn = "DEPC";
3912 break;
3913 default:
3914 goto die;
3916 break;
3917 case 25:
3918 switch (sel) {
3919 case 0:
3920 gen_helper_mtc0_performance0(arg);
3921 rn = "Performance0";
3922 break;
3923 case 1:
3924 // gen_helper_mtc0_performance1(arg);
3925 rn = "Performance1";
3926 // break;
3927 case 2:
3928 // gen_helper_mtc0_performance2(arg);
3929 rn = "Performance2";
3930 // break;
3931 case 3:
3932 // gen_helper_mtc0_performance3(arg);
3933 rn = "Performance3";
3934 // break;
3935 case 4:
3936 // gen_helper_mtc0_performance4(arg);
3937 rn = "Performance4";
3938 // break;
3939 case 5:
3940 // gen_helper_mtc0_performance5(arg);
3941 rn = "Performance5";
3942 // break;
3943 case 6:
3944 // gen_helper_mtc0_performance6(arg);
3945 rn = "Performance6";
3946 // break;
3947 case 7:
3948 // gen_helper_mtc0_performance7(arg);
3949 rn = "Performance7";
3950 // break;
3951 default:
3952 goto die;
3954 break;
3955 case 26:
3956 /* ignored */
3957 rn = "ECC";
3958 break;
3959 case 27:
3960 switch (sel) {
3961 case 0 ... 3:
3962 /* ignored */
3963 rn = "CacheErr";
3964 break;
3965 default:
3966 goto die;
3968 break;
3969 case 28:
3970 switch (sel) {
3971 case 0:
3972 case 2:
3973 case 4:
3974 case 6:
3975 gen_helper_mtc0_taglo(arg);
3976 rn = "TagLo";
3977 break;
3978 case 1:
3979 case 3:
3980 case 5:
3981 case 7:
3982 gen_helper_mtc0_datalo(arg);
3983 rn = "DataLo";
3984 break;
3985 default:
3986 goto die;
3988 break;
3989 case 29:
3990 switch (sel) {
3991 case 0:
3992 case 2:
3993 case 4:
3994 case 6:
3995 gen_helper_mtc0_taghi(arg);
3996 rn = "TagHi";
3997 break;
3998 case 1:
3999 case 3:
4000 case 5:
4001 case 7:
4002 gen_helper_mtc0_datahi(arg);
4003 rn = "DataHi";
4004 break;
4005 default:
4006 rn = "invalid sel";
4007 goto die;
4009 break;
4010 case 30:
4011 switch (sel) {
4012 case 0:
4013 gen_mtc0_store64(arg, offsetof(CPUState, CP0_ErrorEPC));
4014 rn = "ErrorEPC";
4015 break;
4016 default:
4017 goto die;
4019 break;
4020 case 31:
4021 switch (sel) {
4022 case 0:
4023 /* EJTAG support */
4024 gen_mtc0_store32(arg, offsetof(CPUState, CP0_DESAVE));
4025 rn = "DESAVE";
4026 break;
4027 default:
4028 goto die;
4030 /* Stop translation as we may have switched the execution mode */
4031 ctx->bstate = BS_STOP;
4032 break;
4033 default:
4034 goto die;
4036 LOG_DISAS("mtc0 %s (reg %d sel %d)\n", rn, reg, sel);
4037 /* For simplicity assume that all writes can cause interrupts. */
4038 if (use_icount) {
4039 gen_io_end();
4040 ctx->bstate = BS_STOP;
4042 return;
4044 die:
4045 LOG_DISAS("mtc0 %s (reg %d sel %d)\n", rn, reg, sel);
4046 generate_exception(ctx, EXCP_RI);
4049 #if defined(TARGET_MIPS64)
4050 static void gen_dmfc0 (CPUState *env, DisasContext *ctx, TCGv arg, int reg, int sel)
4052 const char *rn = "invalid";
4054 if (sel != 0)
4055 check_insn(env, ctx, ISA_MIPS64);
4057 switch (reg) {
4058 case 0:
4059 switch (sel) {
4060 case 0:
4061 gen_mfc0_load32(arg, offsetof(CPUState, CP0_Index));
4062 rn = "Index";
4063 break;
4064 case 1:
4065 check_insn(env, ctx, ASE_MT);
4066 gen_helper_mfc0_mvpcontrol(arg);
4067 rn = "MVPControl";
4068 break;
4069 case 2:
4070 check_insn(env, ctx, ASE_MT);
4071 gen_helper_mfc0_mvpconf0(arg);
4072 rn = "MVPConf0";
4073 break;
4074 case 3:
4075 check_insn(env, ctx, ASE_MT);
4076 gen_helper_mfc0_mvpconf1(arg);
4077 rn = "MVPConf1";
4078 break;
4079 default:
4080 goto die;
4082 break;
4083 case 1:
4084 switch (sel) {
4085 case 0:
4086 gen_helper_mfc0_random(arg);
4087 rn = "Random";
4088 break;
4089 case 1:
4090 check_insn(env, ctx, ASE_MT);
4091 gen_mfc0_load32(arg, offsetof(CPUState, CP0_VPEControl));
4092 rn = "VPEControl";
4093 break;
4094 case 2:
4095 check_insn(env, ctx, ASE_MT);
4096 gen_mfc0_load32(arg, offsetof(CPUState, CP0_VPEConf0));
4097 rn = "VPEConf0";
4098 break;
4099 case 3:
4100 check_insn(env, ctx, ASE_MT);
4101 gen_mfc0_load32(arg, offsetof(CPUState, CP0_VPEConf1));
4102 rn = "VPEConf1";
4103 break;
4104 case 4:
4105 check_insn(env, ctx, ASE_MT);
4106 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_YQMask));
4107 rn = "YQMask";
4108 break;
4109 case 5:
4110 check_insn(env, ctx, ASE_MT);
4111 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_VPESchedule));
4112 rn = "VPESchedule";
4113 break;
4114 case 6:
4115 check_insn(env, ctx, ASE_MT);
4116 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_VPEScheFBack));
4117 rn = "VPEScheFBack";
4118 break;
4119 case 7:
4120 check_insn(env, ctx, ASE_MT);
4121 gen_mfc0_load32(arg, offsetof(CPUState, CP0_VPEOpt));
4122 rn = "VPEOpt";
4123 break;
4124 default:
4125 goto die;
4127 break;
4128 case 2:
4129 switch (sel) {
4130 case 0:
4131 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_EntryLo0));
4132 rn = "EntryLo0";
4133 break;
4134 case 1:
4135 check_insn(env, ctx, ASE_MT);
4136 gen_helper_mfc0_tcstatus(arg);
4137 rn = "TCStatus";
4138 break;
4139 case 2:
4140 check_insn(env, ctx, ASE_MT);
4141 gen_helper_mfc0_tcbind(arg);
4142 rn = "TCBind";
4143 break;
4144 case 3:
4145 check_insn(env, ctx, ASE_MT);
4146 gen_helper_dmfc0_tcrestart(arg);
4147 rn = "TCRestart";
4148 break;
4149 case 4:
4150 check_insn(env, ctx, ASE_MT);
4151 gen_helper_dmfc0_tchalt(arg);
4152 rn = "TCHalt";
4153 break;
4154 case 5:
4155 check_insn(env, ctx, ASE_MT);
4156 gen_helper_dmfc0_tccontext(arg);
4157 rn = "TCContext";
4158 break;
4159 case 6:
4160 check_insn(env, ctx, ASE_MT);
4161 gen_helper_dmfc0_tcschedule(arg);
4162 rn = "TCSchedule";
4163 break;
4164 case 7:
4165 check_insn(env, ctx, ASE_MT);
4166 gen_helper_dmfc0_tcschefback(arg);
4167 rn = "TCScheFBack";
4168 break;
4169 default:
4170 goto die;
4172 break;
4173 case 3:
4174 switch (sel) {
4175 case 0:
4176 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_EntryLo1));
4177 rn = "EntryLo1";
4178 break;
4179 default:
4180 goto die;
4182 break;
4183 case 4:
4184 switch (sel) {
4185 case 0:
4186 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_Context));
4187 rn = "Context";
4188 break;
4189 case 1:
4190 // gen_helper_dmfc0_contextconfig(arg); /* SmartMIPS ASE */
4191 rn = "ContextConfig";
4192 // break;
4193 default:
4194 goto die;
4196 break;
4197 case 5:
4198 switch (sel) {
4199 case 0:
4200 gen_mfc0_load32(arg, offsetof(CPUState, CP0_PageMask));
4201 rn = "PageMask";
4202 break;
4203 case 1:
4204 check_insn(env, ctx, ISA_MIPS32R2);
4205 gen_mfc0_load32(arg, offsetof(CPUState, CP0_PageGrain));
4206 rn = "PageGrain";
4207 break;
4208 default:
4209 goto die;
4211 break;
4212 case 6:
4213 switch (sel) {
4214 case 0:
4215 gen_mfc0_load32(arg, offsetof(CPUState, CP0_Wired));
4216 rn = "Wired";
4217 break;
4218 case 1:
4219 check_insn(env, ctx, ISA_MIPS32R2);
4220 gen_mfc0_load32(arg, offsetof(CPUState, CP0_SRSConf0));
4221 rn = "SRSConf0";
4222 break;
4223 case 2:
4224 check_insn(env, ctx, ISA_MIPS32R2);
4225 gen_mfc0_load32(arg, offsetof(CPUState, CP0_SRSConf1));
4226 rn = "SRSConf1";
4227 break;
4228 case 3:
4229 check_insn(env, ctx, ISA_MIPS32R2);
4230 gen_mfc0_load32(arg, offsetof(CPUState, CP0_SRSConf2));
4231 rn = "SRSConf2";
4232 break;
4233 case 4:
4234 check_insn(env, ctx, ISA_MIPS32R2);
4235 gen_mfc0_load32(arg, offsetof(CPUState, CP0_SRSConf3));
4236 rn = "SRSConf3";
4237 break;
4238 case 5:
4239 check_insn(env, ctx, ISA_MIPS32R2);
4240 gen_mfc0_load32(arg, offsetof(CPUState, CP0_SRSConf4));
4241 rn = "SRSConf4";
4242 break;
4243 default:
4244 goto die;
4246 break;
4247 case 7:
4248 switch (sel) {
4249 case 0:
4250 check_insn(env, ctx, ISA_MIPS32R2);
4251 gen_mfc0_load32(arg, offsetof(CPUState, CP0_HWREna));
4252 rn = "HWREna";
4253 break;
4254 default:
4255 goto die;
4257 break;
4258 case 8:
4259 switch (sel) {
4260 case 0:
4261 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_BadVAddr));
4262 rn = "BadVAddr";
4263 break;
4264 default:
4265 goto die;
4267 break;
4268 case 9:
4269 switch (sel) {
4270 case 0:
4271 /* Mark as an IO operation because we read the time. */
4272 if (use_icount)
4273 gen_io_start();
4274 gen_helper_mfc0_count(arg);
4275 if (use_icount) {
4276 gen_io_end();
4277 ctx->bstate = BS_STOP;
4279 rn = "Count";
4280 break;
4281 /* 6,7 are implementation dependent */
4282 default:
4283 goto die;
4285 break;
4286 case 10:
4287 switch (sel) {
4288 case 0:
4289 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_EntryHi));
4290 rn = "EntryHi";
4291 break;
4292 default:
4293 goto die;
4295 break;
4296 case 11:
4297 switch (sel) {
4298 case 0:
4299 gen_mfc0_load32(arg, offsetof(CPUState, CP0_Compare));
4300 rn = "Compare";
4301 break;
4302 /* 6,7 are implementation dependent */
4303 default:
4304 goto die;
4306 break;
4307 case 12:
4308 switch (sel) {
4309 case 0:
4310 gen_mfc0_load32(arg, offsetof(CPUState, CP0_Status));
4311 rn = "Status";
4312 break;
4313 case 1:
4314 check_insn(env, ctx, ISA_MIPS32R2);
4315 gen_mfc0_load32(arg, offsetof(CPUState, CP0_IntCtl));
4316 rn = "IntCtl";
4317 break;
4318 case 2:
4319 check_insn(env, ctx, ISA_MIPS32R2);
4320 gen_mfc0_load32(arg, offsetof(CPUState, CP0_SRSCtl));
4321 rn = "SRSCtl";
4322 break;
4323 case 3:
4324 check_insn(env, ctx, ISA_MIPS32R2);
4325 gen_mfc0_load32(arg, offsetof(CPUState, CP0_SRSMap));
4326 rn = "SRSMap";
4327 break;
4328 default:
4329 goto die;
4331 break;
4332 case 13:
4333 switch (sel) {
4334 case 0:
4335 gen_mfc0_load32(arg, offsetof(CPUState, CP0_Cause));
4336 rn = "Cause";
4337 break;
4338 default:
4339 goto die;
4341 break;
4342 case 14:
4343 switch (sel) {
4344 case 0:
4345 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_EPC));
4346 rn = "EPC";
4347 break;
4348 default:
4349 goto die;
4351 break;
4352 case 15:
4353 switch (sel) {
4354 case 0:
4355 gen_mfc0_load32(arg, offsetof(CPUState, CP0_PRid));
4356 rn = "PRid";
4357 break;
4358 case 1:
4359 check_insn(env, ctx, ISA_MIPS32R2);
4360 gen_mfc0_load32(arg, offsetof(CPUState, CP0_EBase));
4361 rn = "EBase";
4362 break;
4363 default:
4364 goto die;
4366 break;
4367 case 16:
4368 switch (sel) {
4369 case 0:
4370 gen_mfc0_load32(arg, offsetof(CPUState, CP0_Config0));
4371 rn = "Config";
4372 break;
4373 case 1:
4374 gen_mfc0_load32(arg, offsetof(CPUState, CP0_Config1));
4375 rn = "Config1";
4376 break;
4377 case 2:
4378 gen_mfc0_load32(arg, offsetof(CPUState, CP0_Config2));
4379 rn = "Config2";
4380 break;
4381 case 3:
4382 gen_mfc0_load32(arg, offsetof(CPUState, CP0_Config3));
4383 rn = "Config3";
4384 break;
4385 /* 6,7 are implementation dependent */
4386 case 6:
4387 gen_mfc0_load32(arg, offsetof(CPUState, CP0_Config6));
4388 rn = "Config6";
4389 break;
4390 case 7:
4391 gen_mfc0_load32(arg, offsetof(CPUState, CP0_Config7));
4392 rn = "Config7";
4393 break;
4394 default:
4395 goto die;
4397 break;
4398 case 17:
4399 switch (sel) {
4400 case 0:
4401 gen_helper_dmfc0_lladdr(arg);
4402 rn = "LLAddr";
4403 break;
4404 default:
4405 goto die;
4407 break;
4408 case 18:
4409 switch (sel) {
4410 case 0 ... 7:
4411 gen_helper_1i(dmfc0_watchlo, arg, sel);
4412 rn = "WatchLo";
4413 break;
4414 default:
4415 goto die;
4417 break;
4418 case 19:
4419 switch (sel) {
4420 case 0 ... 7:
4421 gen_helper_1i(mfc0_watchhi, arg, sel);
4422 rn = "WatchHi";
4423 break;
4424 default:
4425 goto die;
4427 break;
4428 case 20:
4429 switch (sel) {
4430 case 0:
4431 check_insn(env, ctx, ISA_MIPS3);
4432 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_XContext));
4433 rn = "XContext";
4434 break;
4435 default:
4436 goto die;
4438 break;
4439 case 21:
4440 /* Officially reserved, but sel 0 is used for R1x000 framemask */
4441 switch (sel) {
4442 case 0:
4443 gen_mfc0_load32(arg, offsetof(CPUState, CP0_Framemask));
4444 rn = "Framemask";
4445 break;
4446 default:
4447 goto die;
4449 break;
4450 case 22:
4451 tcg_gen_movi_tl(arg, 0); /* unimplemented */
4452 rn = "'Diagnostic"; /* implementation dependent */
4453 break;
4454 case 23:
4455 switch (sel) {
4456 case 0:
4457 gen_helper_mfc0_debug(arg); /* EJTAG support */
4458 rn = "Debug";
4459 break;
4460 case 1:
4461 // gen_helper_dmfc0_tracecontrol(arg); /* PDtrace support */
4462 rn = "TraceControl";
4463 // break;
4464 case 2:
4465 // gen_helper_dmfc0_tracecontrol2(arg); /* PDtrace support */
4466 rn = "TraceControl2";
4467 // break;
4468 case 3:
4469 // gen_helper_dmfc0_usertracedata(arg); /* PDtrace support */
4470 rn = "UserTraceData";
4471 // break;
4472 case 4:
4473 // gen_helper_dmfc0_tracebpc(arg); /* PDtrace support */
4474 rn = "TraceBPC";
4475 // break;
4476 default:
4477 goto die;
4479 break;
4480 case 24:
4481 switch (sel) {
4482 case 0:
4483 /* EJTAG support */
4484 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_DEPC));
4485 rn = "DEPC";
4486 break;
4487 default:
4488 goto die;
4490 break;
4491 case 25:
4492 switch (sel) {
4493 case 0:
4494 gen_mfc0_load32(arg, offsetof(CPUState, CP0_Performance0));
4495 rn = "Performance0";
4496 break;
4497 case 1:
4498 // gen_helper_dmfc0_performance1(arg);
4499 rn = "Performance1";
4500 // break;
4501 case 2:
4502 // gen_helper_dmfc0_performance2(arg);
4503 rn = "Performance2";
4504 // break;
4505 case 3:
4506 // gen_helper_dmfc0_performance3(arg);
4507 rn = "Performance3";
4508 // break;
4509 case 4:
4510 // gen_helper_dmfc0_performance4(arg);
4511 rn = "Performance4";
4512 // break;
4513 case 5:
4514 // gen_helper_dmfc0_performance5(arg);
4515 rn = "Performance5";
4516 // break;
4517 case 6:
4518 // gen_helper_dmfc0_performance6(arg);
4519 rn = "Performance6";
4520 // break;
4521 case 7:
4522 // gen_helper_dmfc0_performance7(arg);
4523 rn = "Performance7";
4524 // break;
4525 default:
4526 goto die;
4528 break;
4529 case 26:
4530 tcg_gen_movi_tl(arg, 0); /* unimplemented */
4531 rn = "ECC";
4532 break;
4533 case 27:
4534 switch (sel) {
4535 /* ignored */
4536 case 0 ... 3:
4537 tcg_gen_movi_tl(arg, 0); /* unimplemented */
4538 rn = "CacheErr";
4539 break;
4540 default:
4541 goto die;
4543 break;
4544 case 28:
4545 switch (sel) {
4546 case 0:
4547 case 2:
4548 case 4:
4549 case 6:
4550 gen_mfc0_load32(arg, offsetof(CPUState, CP0_TagLo));
4551 rn = "TagLo";
4552 break;
4553 case 1:
4554 case 3:
4555 case 5:
4556 case 7:
4557 gen_mfc0_load32(arg, offsetof(CPUState, CP0_DataLo));
4558 rn = "DataLo";
4559 break;
4560 default:
4561 goto die;
4563 break;
4564 case 29:
4565 switch (sel) {
4566 case 0:
4567 case 2:
4568 case 4:
4569 case 6:
4570 gen_mfc0_load32(arg, offsetof(CPUState, CP0_TagHi));
4571 rn = "TagHi";
4572 break;
4573 case 1:
4574 case 3:
4575 case 5:
4576 case 7:
4577 gen_mfc0_load32(arg, offsetof(CPUState, CP0_DataHi));
4578 rn = "DataHi";
4579 break;
4580 default:
4581 goto die;
4583 break;
4584 case 30:
4585 switch (sel) {
4586 case 0:
4587 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_ErrorEPC));
4588 rn = "ErrorEPC";
4589 break;
4590 default:
4591 goto die;
4593 break;
4594 case 31:
4595 switch (sel) {
4596 case 0:
4597 /* EJTAG support */
4598 gen_mfc0_load32(arg, offsetof(CPUState, CP0_DESAVE));
4599 rn = "DESAVE";
4600 break;
4601 default:
4602 goto die;
4604 break;
4605 default:
4606 goto die;
4608 LOG_DISAS("dmfc0 %s (reg %d sel %d)\n", rn, reg, sel);
4609 return;
4611 die:
4612 LOG_DISAS("dmfc0 %s (reg %d sel %d)\n", rn, reg, sel);
4613 generate_exception(ctx, EXCP_RI);
4616 static void gen_dmtc0 (CPUState *env, DisasContext *ctx, TCGv arg, int reg, int sel)
4618 const char *rn = "invalid";
4620 if (sel != 0)
4621 check_insn(env, ctx, ISA_MIPS64);
4623 if (use_icount)
4624 gen_io_start();
4626 switch (reg) {
4627 case 0:
4628 switch (sel) {
4629 case 0:
4630 gen_helper_mtc0_index(arg);
4631 rn = "Index";
4632 break;
4633 case 1:
4634 check_insn(env, ctx, ASE_MT);
4635 gen_helper_mtc0_mvpcontrol(arg);
4636 rn = "MVPControl";
4637 break;
4638 case 2:
4639 check_insn(env, ctx, ASE_MT);
4640 /* ignored */
4641 rn = "MVPConf0";
4642 break;
4643 case 3:
4644 check_insn(env, ctx, ASE_MT);
4645 /* ignored */
4646 rn = "MVPConf1";
4647 break;
4648 default:
4649 goto die;
4651 break;
4652 case 1:
4653 switch (sel) {
4654 case 0:
4655 /* ignored */
4656 rn = "Random";
4657 break;
4658 case 1:
4659 check_insn(env, ctx, ASE_MT);
4660 gen_helper_mtc0_vpecontrol(arg);
4661 rn = "VPEControl";
4662 break;
4663 case 2:
4664 check_insn(env, ctx, ASE_MT);
4665 gen_helper_mtc0_vpeconf0(arg);
4666 rn = "VPEConf0";
4667 break;
4668 case 3:
4669 check_insn(env, ctx, ASE_MT);
4670 gen_helper_mtc0_vpeconf1(arg);
4671 rn = "VPEConf1";
4672 break;
4673 case 4:
4674 check_insn(env, ctx, ASE_MT);
4675 gen_helper_mtc0_yqmask(arg);
4676 rn = "YQMask";
4677 break;
4678 case 5:
4679 check_insn(env, ctx, ASE_MT);
4680 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUState, CP0_VPESchedule));
4681 rn = "VPESchedule";
4682 break;
4683 case 6:
4684 check_insn(env, ctx, ASE_MT);
4685 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUState, CP0_VPEScheFBack));
4686 rn = "VPEScheFBack";
4687 break;
4688 case 7:
4689 check_insn(env, ctx, ASE_MT);
4690 gen_helper_mtc0_vpeopt(arg);
4691 rn = "VPEOpt";
4692 break;
4693 default:
4694 goto die;
4696 break;
4697 case 2:
4698 switch (sel) {
4699 case 0:
4700 gen_helper_mtc0_entrylo0(arg);
4701 rn = "EntryLo0";
4702 break;
4703 case 1:
4704 check_insn(env, ctx, ASE_MT);
4705 gen_helper_mtc0_tcstatus(arg);
4706 rn = "TCStatus";
4707 break;
4708 case 2:
4709 check_insn(env, ctx, ASE_MT);
4710 gen_helper_mtc0_tcbind(arg);
4711 rn = "TCBind";
4712 break;
4713 case 3:
4714 check_insn(env, ctx, ASE_MT);
4715 gen_helper_mtc0_tcrestart(arg);
4716 rn = "TCRestart";
4717 break;
4718 case 4:
4719 check_insn(env, ctx, ASE_MT);
4720 gen_helper_mtc0_tchalt(arg);
4721 rn = "TCHalt";
4722 break;
4723 case 5:
4724 check_insn(env, ctx, ASE_MT);
4725 gen_helper_mtc0_tccontext(arg);
4726 rn = "TCContext";
4727 break;
4728 case 6:
4729 check_insn(env, ctx, ASE_MT);
4730 gen_helper_mtc0_tcschedule(arg);
4731 rn = "TCSchedule";
4732 break;
4733 case 7:
4734 check_insn(env, ctx, ASE_MT);
4735 gen_helper_mtc0_tcschefback(arg);
4736 rn = "TCScheFBack";
4737 break;
4738 default:
4739 goto die;
4741 break;
4742 case 3:
4743 switch (sel) {
4744 case 0:
4745 gen_helper_mtc0_entrylo1(arg);
4746 rn = "EntryLo1";
4747 break;
4748 default:
4749 goto die;
4751 break;
4752 case 4:
4753 switch (sel) {
4754 case 0:
4755 gen_helper_mtc0_context(arg);
4756 rn = "Context";
4757 break;
4758 case 1:
4759 // gen_helper_mtc0_contextconfig(arg); /* SmartMIPS ASE */
4760 rn = "ContextConfig";
4761 // break;
4762 default:
4763 goto die;
4765 break;
4766 case 5:
4767 switch (sel) {
4768 case 0:
4769 gen_helper_mtc0_pagemask(arg);
4770 rn = "PageMask";
4771 break;
4772 case 1:
4773 check_insn(env, ctx, ISA_MIPS32R2);
4774 gen_helper_mtc0_pagegrain(arg);
4775 rn = "PageGrain";
4776 break;
4777 default:
4778 goto die;
4780 break;
4781 case 6:
4782 switch (sel) {
4783 case 0:
4784 gen_helper_mtc0_wired(arg);
4785 rn = "Wired";
4786 break;
4787 case 1:
4788 check_insn(env, ctx, ISA_MIPS32R2);
4789 gen_helper_mtc0_srsconf0(arg);
4790 rn = "SRSConf0";
4791 break;
4792 case 2:
4793 check_insn(env, ctx, ISA_MIPS32R2);
4794 gen_helper_mtc0_srsconf1(arg);
4795 rn = "SRSConf1";
4796 break;
4797 case 3:
4798 check_insn(env, ctx, ISA_MIPS32R2);
4799 gen_helper_mtc0_srsconf2(arg);
4800 rn = "SRSConf2";
4801 break;
4802 case 4:
4803 check_insn(env, ctx, ISA_MIPS32R2);
4804 gen_helper_mtc0_srsconf3(arg);
4805 rn = "SRSConf3";
4806 break;
4807 case 5:
4808 check_insn(env, ctx, ISA_MIPS32R2);
4809 gen_helper_mtc0_srsconf4(arg);
4810 rn = "SRSConf4";
4811 break;
4812 default:
4813 goto die;
4815 break;
4816 case 7:
4817 switch (sel) {
4818 case 0:
4819 check_insn(env, ctx, ISA_MIPS32R2);
4820 gen_helper_mtc0_hwrena(arg);
4821 rn = "HWREna";
4822 break;
4823 default:
4824 goto die;
4826 break;
4827 case 8:
4828 /* ignored */
4829 rn = "BadVAddr";
4830 break;
4831 case 9:
4832 switch (sel) {
4833 case 0:
4834 gen_helper_mtc0_count(arg);
4835 rn = "Count";
4836 break;
4837 /* 6,7 are implementation dependent */
4838 default:
4839 goto die;
4841 /* Stop translation as we may have switched the execution mode */
4842 ctx->bstate = BS_STOP;
4843 break;
4844 case 10:
4845 switch (sel) {
4846 case 0:
4847 gen_helper_mtc0_entryhi(arg);
4848 rn = "EntryHi";
4849 break;
4850 default:
4851 goto die;
4853 break;
4854 case 11:
4855 switch (sel) {
4856 case 0:
4857 gen_helper_mtc0_compare(arg);
4858 rn = "Compare";
4859 break;
4860 /* 6,7 are implementation dependent */
4861 default:
4862 goto die;
4864 /* Stop translation as we may have switched the execution mode */
4865 ctx->bstate = BS_STOP;
4866 break;
4867 case 12:
4868 switch (sel) {
4869 case 0:
4870 save_cpu_state(ctx, 1);
4871 gen_helper_mtc0_status(arg);
4872 /* BS_STOP isn't good enough here, hflags may have changed. */
4873 gen_save_pc(ctx->pc + 4);
4874 ctx->bstate = BS_EXCP;
4875 rn = "Status";
4876 break;
4877 case 1:
4878 check_insn(env, ctx, ISA_MIPS32R2);
4879 gen_helper_mtc0_intctl(arg);
4880 /* Stop translation as we may have switched the execution mode */
4881 ctx->bstate = BS_STOP;
4882 rn = "IntCtl";
4883 break;
4884 case 2:
4885 check_insn(env, ctx, ISA_MIPS32R2);
4886 gen_helper_mtc0_srsctl(arg);
4887 /* Stop translation as we may have switched the execution mode */
4888 ctx->bstate = BS_STOP;
4889 rn = "SRSCtl";
4890 break;
4891 case 3:
4892 check_insn(env, ctx, ISA_MIPS32R2);
4893 gen_mtc0_store32(arg, offsetof(CPUState, CP0_SRSMap));
4894 /* Stop translation as we may have switched the execution mode */
4895 ctx->bstate = BS_STOP;
4896 rn = "SRSMap";
4897 break;
4898 default:
4899 goto die;
4901 break;
4902 case 13:
4903 switch (sel) {
4904 case 0:
4905 save_cpu_state(ctx, 1);
4906 gen_helper_mtc0_cause(arg);
4907 rn = "Cause";
4908 break;
4909 default:
4910 goto die;
4912 break;
4913 case 14:
4914 switch (sel) {
4915 case 0:
4916 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUState, CP0_EPC));
4917 rn = "EPC";
4918 break;
4919 default:
4920 goto die;
4922 break;
4923 case 15:
4924 switch (sel) {
4925 case 0:
4926 /* ignored */
4927 rn = "PRid";
4928 break;
4929 case 1:
4930 check_insn(env, ctx, ISA_MIPS32R2);
4931 gen_helper_mtc0_ebase(arg);
4932 rn = "EBase";
4933 break;
4934 default:
4935 goto die;
4937 break;
4938 case 16:
4939 switch (sel) {
4940 case 0:
4941 gen_helper_mtc0_config0(arg);
4942 rn = "Config";
4943 /* Stop translation as we may have switched the execution mode */
4944 ctx->bstate = BS_STOP;
4945 break;
4946 case 1:
4947 /* ignored, read only */
4948 rn = "Config1";
4949 break;
4950 case 2:
4951 gen_helper_mtc0_config2(arg);
4952 rn = "Config2";
4953 /* Stop translation as we may have switched the execution mode */
4954 ctx->bstate = BS_STOP;
4955 break;
4956 case 3:
4957 /* ignored */
4958 rn = "Config3";
4959 break;
4960 /* 6,7 are implementation dependent */
4961 default:
4962 rn = "Invalid config selector";
4963 goto die;
4965 break;
4966 case 17:
4967 switch (sel) {
4968 case 0:
4969 gen_helper_mtc0_lladdr(arg);
4970 rn = "LLAddr";
4971 break;
4972 default:
4973 goto die;
4975 break;
4976 case 18:
4977 switch (sel) {
4978 case 0 ... 7:
4979 gen_helper_1i(mtc0_watchlo, arg, sel);
4980 rn = "WatchLo";
4981 break;
4982 default:
4983 goto die;
4985 break;
4986 case 19:
4987 switch (sel) {
4988 case 0 ... 7:
4989 gen_helper_1i(mtc0_watchhi, arg, sel);
4990 rn = "WatchHi";
4991 break;
4992 default:
4993 goto die;
4995 break;
4996 case 20:
4997 switch (sel) {
4998 case 0:
4999 check_insn(env, ctx, ISA_MIPS3);
5000 gen_helper_mtc0_xcontext(arg);
5001 rn = "XContext";
5002 break;
5003 default:
5004 goto die;
5006 break;
5007 case 21:
5008 /* Officially reserved, but sel 0 is used for R1x000 framemask */
5009 switch (sel) {
5010 case 0:
5011 gen_helper_mtc0_framemask(arg);
5012 rn = "Framemask";
5013 break;
5014 default:
5015 goto die;
5017 break;
5018 case 22:
5019 /* ignored */
5020 rn = "Diagnostic"; /* implementation dependent */
5021 break;
5022 case 23:
5023 switch (sel) {
5024 case 0:
5025 gen_helper_mtc0_debug(arg); /* EJTAG support */
5026 /* BS_STOP isn't good enough here, hflags may have changed. */
5027 gen_save_pc(ctx->pc + 4);
5028 ctx->bstate = BS_EXCP;
5029 rn = "Debug";
5030 break;
5031 case 1:
5032 // gen_helper_mtc0_tracecontrol(arg); /* PDtrace support */
5033 /* Stop translation as we may have switched the execution mode */
5034 ctx->bstate = BS_STOP;
5035 rn = "TraceControl";
5036 // break;
5037 case 2:
5038 // gen_helper_mtc0_tracecontrol2(arg); /* PDtrace support */
5039 /* Stop translation as we may have switched the execution mode */
5040 ctx->bstate = BS_STOP;
5041 rn = "TraceControl2";
5042 // break;
5043 case 3:
5044 // gen_helper_mtc0_usertracedata(arg); /* PDtrace support */
5045 /* Stop translation as we may have switched the execution mode */
5046 ctx->bstate = BS_STOP;
5047 rn = "UserTraceData";
5048 // break;
5049 case 4:
5050 // gen_helper_mtc0_tracebpc(arg); /* PDtrace support */
5051 /* Stop translation as we may have switched the execution mode */
5052 ctx->bstate = BS_STOP;
5053 rn = "TraceBPC";
5054 // break;
5055 default:
5056 goto die;
5058 break;
5059 case 24:
5060 switch (sel) {
5061 case 0:
5062 /* EJTAG support */
5063 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUState, CP0_DEPC));
5064 rn = "DEPC";
5065 break;
5066 default:
5067 goto die;
5069 break;
5070 case 25:
5071 switch (sel) {
5072 case 0:
5073 gen_helper_mtc0_performance0(arg);
5074 rn = "Performance0";
5075 break;
5076 case 1:
5077 // gen_helper_mtc0_performance1(arg);
5078 rn = "Performance1";
5079 // break;
5080 case 2:
5081 // gen_helper_mtc0_performance2(arg);
5082 rn = "Performance2";
5083 // break;
5084 case 3:
5085 // gen_helper_mtc0_performance3(arg);
5086 rn = "Performance3";
5087 // break;
5088 case 4:
5089 // gen_helper_mtc0_performance4(arg);
5090 rn = "Performance4";
5091 // break;
5092 case 5:
5093 // gen_helper_mtc0_performance5(arg);
5094 rn = "Performance5";
5095 // break;
5096 case 6:
5097 // gen_helper_mtc0_performance6(arg);
5098 rn = "Performance6";
5099 // break;
5100 case 7:
5101 // gen_helper_mtc0_performance7(arg);
5102 rn = "Performance7";
5103 // break;
5104 default:
5105 goto die;
5107 break;
5108 case 26:
5109 /* ignored */
5110 rn = "ECC";
5111 break;
5112 case 27:
5113 switch (sel) {
5114 case 0 ... 3:
5115 /* ignored */
5116 rn = "CacheErr";
5117 break;
5118 default:
5119 goto die;
5121 break;
5122 case 28:
5123 switch (sel) {
5124 case 0:
5125 case 2:
5126 case 4:
5127 case 6:
5128 gen_helper_mtc0_taglo(arg);
5129 rn = "TagLo";
5130 break;
5131 case 1:
5132 case 3:
5133 case 5:
5134 case 7:
5135 gen_helper_mtc0_datalo(arg);
5136 rn = "DataLo";
5137 break;
5138 default:
5139 goto die;
5141 break;
5142 case 29:
5143 switch (sel) {
5144 case 0:
5145 case 2:
5146 case 4:
5147 case 6:
5148 gen_helper_mtc0_taghi(arg);
5149 rn = "TagHi";
5150 break;
5151 case 1:
5152 case 3:
5153 case 5:
5154 case 7:
5155 gen_helper_mtc0_datahi(arg);
5156 rn = "DataHi";
5157 break;
5158 default:
5159 rn = "invalid sel";
5160 goto die;
5162 break;
5163 case 30:
5164 switch (sel) {
5165 case 0:
5166 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUState, CP0_ErrorEPC));
5167 rn = "ErrorEPC";
5168 break;
5169 default:
5170 goto die;
5172 break;
5173 case 31:
5174 switch (sel) {
5175 case 0:
5176 /* EJTAG support */
5177 gen_mtc0_store32(arg, offsetof(CPUState, CP0_DESAVE));
5178 rn = "DESAVE";
5179 break;
5180 default:
5181 goto die;
5183 /* Stop translation as we may have switched the execution mode */
5184 ctx->bstate = BS_STOP;
5185 break;
5186 default:
5187 goto die;
5189 LOG_DISAS("dmtc0 %s (reg %d sel %d)\n", rn, reg, sel);
5190 /* For simplicity assume that all writes can cause interrupts. */
5191 if (use_icount) {
5192 gen_io_end();
5193 ctx->bstate = BS_STOP;
5195 return;
5197 die:
5198 LOG_DISAS("dmtc0 %s (reg %d sel %d)\n", rn, reg, sel);
5199 generate_exception(ctx, EXCP_RI);
5201 #endif /* TARGET_MIPS64 */
5203 static void gen_mftr(CPUState *env, DisasContext *ctx, int rt, int rd,
5204 int u, int sel, int h)
5206 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
5207 TCGv t0 = tcg_temp_local_new();
5209 if ((env->CP0_VPEConf0 & (1 << CP0VPEC0_MVP)) == 0 &&
5210 ((env->tcs[other_tc].CP0_TCBind & (0xf << CP0TCBd_CurVPE)) !=
5211 (env->active_tc.CP0_TCBind & (0xf << CP0TCBd_CurVPE))))
5212 tcg_gen_movi_tl(t0, -1);
5213 else if ((env->CP0_VPEControl & (0xff << CP0VPECo_TargTC)) >
5214 (env->mvp->CP0_MVPConf0 & (0xff << CP0MVPC0_PTC)))
5215 tcg_gen_movi_tl(t0, -1);
5216 else if (u == 0) {
5217 switch (rt) {
5218 case 2:
5219 switch (sel) {
5220 case 1:
5221 gen_helper_mftc0_tcstatus(t0);
5222 break;
5223 case 2:
5224 gen_helper_mftc0_tcbind(t0);
5225 break;
5226 case 3:
5227 gen_helper_mftc0_tcrestart(t0);
5228 break;
5229 case 4:
5230 gen_helper_mftc0_tchalt(t0);
5231 break;
5232 case 5:
5233 gen_helper_mftc0_tccontext(t0);
5234 break;
5235 case 6:
5236 gen_helper_mftc0_tcschedule(t0);
5237 break;
5238 case 7:
5239 gen_helper_mftc0_tcschefback(t0);
5240 break;
5241 default:
5242 gen_mfc0(env, ctx, t0, rt, sel);
5243 break;
5245 break;
5246 case 10:
5247 switch (sel) {
5248 case 0:
5249 gen_helper_mftc0_entryhi(t0);
5250 break;
5251 default:
5252 gen_mfc0(env, ctx, t0, rt, sel);
5253 break;
5255 case 12:
5256 switch (sel) {
5257 case 0:
5258 gen_helper_mftc0_status(t0);
5259 break;
5260 default:
5261 gen_mfc0(env, ctx, t0, rt, sel);
5262 break;
5264 case 23:
5265 switch (sel) {
5266 case 0:
5267 gen_helper_mftc0_debug(t0);
5268 break;
5269 default:
5270 gen_mfc0(env, ctx, t0, rt, sel);
5271 break;
5273 break;
5274 default:
5275 gen_mfc0(env, ctx, t0, rt, sel);
5277 } else switch (sel) {
5278 /* GPR registers. */
5279 case 0:
5280 gen_helper_1i(mftgpr, t0, rt);
5281 break;
5282 /* Auxiliary CPU registers */
5283 case 1:
5284 switch (rt) {
5285 case 0:
5286 gen_helper_1i(mftlo, t0, 0);
5287 break;
5288 case 1:
5289 gen_helper_1i(mfthi, t0, 0);
5290 break;
5291 case 2:
5292 gen_helper_1i(mftacx, t0, 0);
5293 break;
5294 case 4:
5295 gen_helper_1i(mftlo, t0, 1);
5296 break;
5297 case 5:
5298 gen_helper_1i(mfthi, t0, 1);
5299 break;
5300 case 6:
5301 gen_helper_1i(mftacx, t0, 1);
5302 break;
5303 case 8:
5304 gen_helper_1i(mftlo, t0, 2);
5305 break;
5306 case 9:
5307 gen_helper_1i(mfthi, t0, 2);
5308 break;
5309 case 10:
5310 gen_helper_1i(mftacx, t0, 2);
5311 break;
5312 case 12:
5313 gen_helper_1i(mftlo, t0, 3);
5314 break;
5315 case 13:
5316 gen_helper_1i(mfthi, t0, 3);
5317 break;
5318 case 14:
5319 gen_helper_1i(mftacx, t0, 3);
5320 break;
5321 case 16:
5322 gen_helper_mftdsp(t0);
5323 break;
5324 default:
5325 goto die;
5327 break;
5328 /* Floating point (COP1). */
5329 case 2:
5330 /* XXX: For now we support only a single FPU context. */
5331 if (h == 0) {
5332 TCGv_i32 fp0 = tcg_temp_new_i32();
5334 gen_load_fpr32(fp0, rt);
5335 tcg_gen_ext_i32_tl(t0, fp0);
5336 tcg_temp_free_i32(fp0);
5337 } else {
5338 TCGv_i32 fp0 = tcg_temp_new_i32();
5340 gen_load_fpr32h(fp0, rt);
5341 tcg_gen_ext_i32_tl(t0, fp0);
5342 tcg_temp_free_i32(fp0);
5344 break;
5345 case 3:
5346 /* XXX: For now we support only a single FPU context. */
5347 gen_helper_1i(cfc1, t0, rt);
5348 break;
5349 /* COP2: Not implemented. */
5350 case 4:
5351 case 5:
5352 /* fall through */
5353 default:
5354 goto die;
5356 LOG_DISAS("mftr (reg %d u %d sel %d h %d)\n", rt, u, sel, h);
5357 gen_store_gpr(t0, rd);
5358 tcg_temp_free(t0);
5359 return;
5361 die:
5362 tcg_temp_free(t0);
5363 LOG_DISAS("mftr (reg %d u %d sel %d h %d)\n", rt, u, sel, h);
5364 generate_exception(ctx, EXCP_RI);
5367 static void gen_mttr(CPUState *env, DisasContext *ctx, int rd, int rt,
5368 int u, int sel, int h)
5370 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
5371 TCGv t0 = tcg_temp_local_new();
5373 gen_load_gpr(t0, rt);
5374 if ((env->CP0_VPEConf0 & (1 << CP0VPEC0_MVP)) == 0 &&
5375 ((env->tcs[other_tc].CP0_TCBind & (0xf << CP0TCBd_CurVPE)) !=
5376 (env->active_tc.CP0_TCBind & (0xf << CP0TCBd_CurVPE))))
5377 /* NOP */ ;
5378 else if ((env->CP0_VPEControl & (0xff << CP0VPECo_TargTC)) >
5379 (env->mvp->CP0_MVPConf0 & (0xff << CP0MVPC0_PTC)))
5380 /* NOP */ ;
5381 else if (u == 0) {
5382 switch (rd) {
5383 case 2:
5384 switch (sel) {
5385 case 1:
5386 gen_helper_mttc0_tcstatus(t0);
5387 break;
5388 case 2:
5389 gen_helper_mttc0_tcbind(t0);
5390 break;
5391 case 3:
5392 gen_helper_mttc0_tcrestart(t0);
5393 break;
5394 case 4:
5395 gen_helper_mttc0_tchalt(t0);
5396 break;
5397 case 5:
5398 gen_helper_mttc0_tccontext(t0);
5399 break;
5400 case 6:
5401 gen_helper_mttc0_tcschedule(t0);
5402 break;
5403 case 7:
5404 gen_helper_mttc0_tcschefback(t0);
5405 break;
5406 default:
5407 gen_mtc0(env, ctx, t0, rd, sel);
5408 break;
5410 break;
5411 case 10:
5412 switch (sel) {
5413 case 0:
5414 gen_helper_mttc0_entryhi(t0);
5415 break;
5416 default:
5417 gen_mtc0(env, ctx, t0, rd, sel);
5418 break;
5420 case 12:
5421 switch (sel) {
5422 case 0:
5423 gen_helper_mttc0_status(t0);
5424 break;
5425 default:
5426 gen_mtc0(env, ctx, t0, rd, sel);
5427 break;
5429 case 23:
5430 switch (sel) {
5431 case 0:
5432 gen_helper_mttc0_debug(t0);
5433 break;
5434 default:
5435 gen_mtc0(env, ctx, t0, rd, sel);
5436 break;
5438 break;
5439 default:
5440 gen_mtc0(env, ctx, t0, rd, sel);
5442 } else switch (sel) {
5443 /* GPR registers. */
5444 case 0:
5445 gen_helper_1i(mttgpr, t0, rd);
5446 break;
5447 /* Auxiliary CPU registers */
5448 case 1:
5449 switch (rd) {
5450 case 0:
5451 gen_helper_1i(mttlo, t0, 0);
5452 break;
5453 case 1:
5454 gen_helper_1i(mtthi, t0, 0);
5455 break;
5456 case 2:
5457 gen_helper_1i(mttacx, t0, 0);
5458 break;
5459 case 4:
5460 gen_helper_1i(mttlo, t0, 1);
5461 break;
5462 case 5:
5463 gen_helper_1i(mtthi, t0, 1);
5464 break;
5465 case 6:
5466 gen_helper_1i(mttacx, t0, 1);
5467 break;
5468 case 8:
5469 gen_helper_1i(mttlo, t0, 2);
5470 break;
5471 case 9:
5472 gen_helper_1i(mtthi, t0, 2);
5473 break;
5474 case 10:
5475 gen_helper_1i(mttacx, t0, 2);
5476 break;
5477 case 12:
5478 gen_helper_1i(mttlo, t0, 3);
5479 break;
5480 case 13:
5481 gen_helper_1i(mtthi, t0, 3);
5482 break;
5483 case 14:
5484 gen_helper_1i(mttacx, t0, 3);
5485 break;
5486 case 16:
5487 gen_helper_mttdsp(t0);
5488 break;
5489 default:
5490 goto die;
5492 break;
5493 /* Floating point (COP1). */
5494 case 2:
5495 /* XXX: For now we support only a single FPU context. */
5496 if (h == 0) {
5497 TCGv_i32 fp0 = tcg_temp_new_i32();
5499 tcg_gen_trunc_tl_i32(fp0, t0);
5500 gen_store_fpr32(fp0, rd);
5501 tcg_temp_free_i32(fp0);
5502 } else {
5503 TCGv_i32 fp0 = tcg_temp_new_i32();
5505 tcg_gen_trunc_tl_i32(fp0, t0);
5506 gen_store_fpr32h(fp0, rd);
5507 tcg_temp_free_i32(fp0);
5509 break;
5510 case 3:
5511 /* XXX: For now we support only a single FPU context. */
5512 gen_helper_1i(ctc1, t0, rd);
5513 break;
5514 /* COP2: Not implemented. */
5515 case 4:
5516 case 5:
5517 /* fall through */
5518 default:
5519 goto die;
5521 LOG_DISAS("mttr (reg %d u %d sel %d h %d)\n", rd, u, sel, h);
5522 tcg_temp_free(t0);
5523 return;
5525 die:
5526 tcg_temp_free(t0);
5527 LOG_DISAS("mttr (reg %d u %d sel %d h %d)\n", rd, u, sel, h);
5528 generate_exception(ctx, EXCP_RI);
5531 static void gen_cp0 (CPUState *env, DisasContext *ctx, uint32_t opc, int rt, int rd)
5533 const char *opn = "ldst";
5535 switch (opc) {
5536 case OPC_MFC0:
5537 if (rt == 0) {
5538 /* Treat as NOP. */
5539 return;
5541 gen_mfc0(env, ctx, cpu_gpr[rt], rd, ctx->opcode & 0x7);
5542 opn = "mfc0";
5543 break;
5544 case OPC_MTC0:
5546 TCGv t0 = tcg_temp_new();
5548 gen_load_gpr(t0, rt);
5549 gen_mtc0(env, ctx, t0, rd, ctx->opcode & 0x7);
5550 tcg_temp_free(t0);
5552 opn = "mtc0";
5553 break;
5554 #if defined(TARGET_MIPS64)
5555 case OPC_DMFC0:
5556 check_insn(env, ctx, ISA_MIPS3);
5557 if (rt == 0) {
5558 /* Treat as NOP. */
5559 return;
5561 gen_dmfc0(env, ctx, cpu_gpr[rt], rd, ctx->opcode & 0x7);
5562 opn = "dmfc0";
5563 break;
5564 case OPC_DMTC0:
5565 check_insn(env, ctx, ISA_MIPS3);
5567 TCGv t0 = tcg_temp_new();
5569 gen_load_gpr(t0, rt);
5570 gen_dmtc0(env, ctx, t0, rd, ctx->opcode & 0x7);
5571 tcg_temp_free(t0);
5573 opn = "dmtc0";
5574 break;
5575 #endif
5576 case OPC_MFTR:
5577 check_insn(env, ctx, ASE_MT);
5578 if (rd == 0) {
5579 /* Treat as NOP. */
5580 return;
5582 gen_mftr(env, ctx, rt, rd, (ctx->opcode >> 5) & 1,
5583 ctx->opcode & 0x7, (ctx->opcode >> 4) & 1);
5584 opn = "mftr";
5585 break;
5586 case OPC_MTTR:
5587 check_insn(env, ctx, ASE_MT);
5588 gen_mttr(env, ctx, rd, rt, (ctx->opcode >> 5) & 1,
5589 ctx->opcode & 0x7, (ctx->opcode >> 4) & 1);
5590 opn = "mttr";
5591 break;
5592 case OPC_TLBWI:
5593 opn = "tlbwi";
5594 if (!env->tlb->helper_tlbwi)
5595 goto die;
5596 gen_helper_tlbwi();
5597 break;
5598 case OPC_TLBWR:
5599 opn = "tlbwr";
5600 if (!env->tlb->helper_tlbwr)
5601 goto die;
5602 gen_helper_tlbwr();
5603 break;
5604 case OPC_TLBP:
5605 opn = "tlbp";
5606 if (!env->tlb->helper_tlbp)
5607 goto die;
5608 gen_helper_tlbp();
5609 break;
5610 case OPC_TLBR:
5611 opn = "tlbr";
5612 if (!env->tlb->helper_tlbr)
5613 goto die;
5614 gen_helper_tlbr();
5615 break;
5616 case OPC_ERET:
5617 opn = "eret";
5618 check_insn(env, ctx, ISA_MIPS2);
5619 gen_helper_eret();
5620 ctx->bstate = BS_EXCP;
5621 break;
5622 case OPC_DERET:
5623 opn = "deret";
5624 check_insn(env, ctx, ISA_MIPS32);
5625 if (!(ctx->hflags & MIPS_HFLAG_DM)) {
5626 MIPS_INVAL(opn);
5627 generate_exception(ctx, EXCP_RI);
5628 } else {
5629 gen_helper_deret();
5630 ctx->bstate = BS_EXCP;
5632 break;
5633 case OPC_WAIT:
5634 opn = "wait";
5635 check_insn(env, ctx, ISA_MIPS3 | ISA_MIPS32);
5636 /* If we get an exception, we want to restart at next instruction */
5637 ctx->pc += 4;
5638 save_cpu_state(ctx, 1);
5639 ctx->pc -= 4;
5640 gen_helper_wait();
5641 ctx->bstate = BS_EXCP;
5642 break;
5643 default:
5644 die:
5645 MIPS_INVAL(opn);
5646 generate_exception(ctx, EXCP_RI);
5647 return;
5649 MIPS_DEBUG("%s %s %d", opn, regnames[rt], rd);
5651 #endif /* !CONFIG_USER_ONLY */
5653 /* CP1 Branches (before delay slot) */
5654 static void gen_compute_branch1 (CPUState *env, DisasContext *ctx, uint32_t op,
5655 int32_t cc, int32_t offset)
5657 target_ulong btarget;
5658 const char *opn = "cp1 cond branch";
5659 TCGv_i32 t0 = tcg_temp_new_i32();
5661 if (cc != 0)
5662 check_insn(env, ctx, ISA_MIPS4 | ISA_MIPS32);
5664 btarget = ctx->pc + 4 + offset;
5666 switch (op) {
5667 case OPC_BC1F:
5668 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
5669 tcg_gen_not_i32(t0, t0);
5670 tcg_gen_andi_i32(t0, t0, 1);
5671 tcg_gen_extu_i32_tl(bcond, t0);
5672 opn = "bc1f";
5673 goto not_likely;
5674 case OPC_BC1FL:
5675 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
5676 tcg_gen_not_i32(t0, t0);
5677 tcg_gen_andi_i32(t0, t0, 1);
5678 tcg_gen_extu_i32_tl(bcond, t0);
5679 opn = "bc1fl";
5680 goto likely;
5681 case OPC_BC1T:
5682 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
5683 tcg_gen_andi_i32(t0, t0, 1);
5684 tcg_gen_extu_i32_tl(bcond, t0);
5685 opn = "bc1t";
5686 goto not_likely;
5687 case OPC_BC1TL:
5688 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
5689 tcg_gen_andi_i32(t0, t0, 1);
5690 tcg_gen_extu_i32_tl(bcond, t0);
5691 opn = "bc1tl";
5692 likely:
5693 ctx->hflags |= MIPS_HFLAG_BL;
5694 break;
5695 case OPC_BC1FANY2:
5697 TCGv_i32 t1 = tcg_temp_new_i32();
5698 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
5699 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+1));
5700 tcg_gen_nor_i32(t0, t0, t1);
5701 tcg_temp_free_i32(t1);
5702 tcg_gen_andi_i32(t0, t0, 1);
5703 tcg_gen_extu_i32_tl(bcond, t0);
5705 opn = "bc1any2f";
5706 goto not_likely;
5707 case OPC_BC1TANY2:
5709 TCGv_i32 t1 = tcg_temp_new_i32();
5710 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
5711 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+1));
5712 tcg_gen_or_i32(t0, t0, t1);
5713 tcg_temp_free_i32(t1);
5714 tcg_gen_andi_i32(t0, t0, 1);
5715 tcg_gen_extu_i32_tl(bcond, t0);
5717 opn = "bc1any2t";
5718 goto not_likely;
5719 case OPC_BC1FANY4:
5721 TCGv_i32 t1 = tcg_temp_new_i32();
5722 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
5723 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+1));
5724 tcg_gen_or_i32(t0, t0, t1);
5725 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+2));
5726 tcg_gen_or_i32(t0, t0, t1);
5727 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+3));
5728 tcg_gen_nor_i32(t0, t0, t1);
5729 tcg_temp_free_i32(t1);
5730 tcg_gen_andi_i32(t0, t0, 1);
5731 tcg_gen_extu_i32_tl(bcond, t0);
5733 opn = "bc1any4f";
5734 goto not_likely;
5735 case OPC_BC1TANY4:
5737 TCGv_i32 t1 = tcg_temp_new_i32();
5738 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
5739 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+1));
5740 tcg_gen_or_i32(t0, t0, t1);
5741 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+2));
5742 tcg_gen_or_i32(t0, t0, t1);
5743 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+3));
5744 tcg_gen_or_i32(t0, t0, t1);
5745 tcg_temp_free_i32(t1);
5746 tcg_gen_andi_i32(t0, t0, 1);
5747 tcg_gen_extu_i32_tl(bcond, t0);
5749 opn = "bc1any4t";
5750 not_likely:
5751 ctx->hflags |= MIPS_HFLAG_BC;
5752 break;
5753 default:
5754 MIPS_INVAL(opn);
5755 generate_exception (ctx, EXCP_RI);
5756 goto out;
5758 MIPS_DEBUG("%s: cond %02x target " TARGET_FMT_lx, opn,
5759 ctx->hflags, btarget);
5760 ctx->btarget = btarget;
5762 out:
5763 tcg_temp_free_i32(t0);
5766 /* Coprocessor 1 (FPU) */
5768 #define FOP(func, fmt) (((fmt) << 21) | (func))
5770 enum fopcode {
5771 OPC_ADD_S = FOP(0, FMT_S),
5772 OPC_SUB_S = FOP(1, FMT_S),
5773 OPC_MUL_S = FOP(2, FMT_S),
5774 OPC_DIV_S = FOP(3, FMT_S),
5775 OPC_SQRT_S = FOP(4, FMT_S),
5776 OPC_ABS_S = FOP(5, FMT_S),
5777 OPC_MOV_S = FOP(6, FMT_S),
5778 OPC_NEG_S = FOP(7, FMT_S),
5779 OPC_ROUND_L_S = FOP(8, FMT_S),
5780 OPC_TRUNC_L_S = FOP(9, FMT_S),
5781 OPC_CEIL_L_S = FOP(10, FMT_S),
5782 OPC_FLOOR_L_S = FOP(11, FMT_S),
5783 OPC_ROUND_W_S = FOP(12, FMT_S),
5784 OPC_TRUNC_W_S = FOP(13, FMT_S),
5785 OPC_CEIL_W_S = FOP(14, FMT_S),
5786 OPC_FLOOR_W_S = FOP(15, FMT_S),
5787 OPC_MOVCF_S = FOP(17, FMT_S),
5788 OPC_MOVZ_S = FOP(18, FMT_S),
5789 OPC_MOVN_S = FOP(19, FMT_S),
5790 OPC_RECIP_S = FOP(21, FMT_S),
5791 OPC_RSQRT_S = FOP(22, FMT_S),
5792 OPC_RECIP2_S = FOP(28, FMT_S),
5793 OPC_RECIP1_S = FOP(29, FMT_S),
5794 OPC_RSQRT1_S = FOP(30, FMT_S),
5795 OPC_RSQRT2_S = FOP(31, FMT_S),
5796 OPC_CVT_D_S = FOP(33, FMT_S),
5797 OPC_CVT_W_S = FOP(36, FMT_S),
5798 OPC_CVT_L_S = FOP(37, FMT_S),
5799 OPC_CVT_PS_S = FOP(38, FMT_S),
5800 OPC_CMP_F_S = FOP (48, FMT_S),
5801 OPC_CMP_UN_S = FOP (49, FMT_S),
5802 OPC_CMP_EQ_S = FOP (50, FMT_S),
5803 OPC_CMP_UEQ_S = FOP (51, FMT_S),
5804 OPC_CMP_OLT_S = FOP (52, FMT_S),
5805 OPC_CMP_ULT_S = FOP (53, FMT_S),
5806 OPC_CMP_OLE_S = FOP (54, FMT_S),
5807 OPC_CMP_ULE_S = FOP (55, FMT_S),
5808 OPC_CMP_SF_S = FOP (56, FMT_S),
5809 OPC_CMP_NGLE_S = FOP (57, FMT_S),
5810 OPC_CMP_SEQ_S = FOP (58, FMT_S),
5811 OPC_CMP_NGL_S = FOP (59, FMT_S),
5812 OPC_CMP_LT_S = FOP (60, FMT_S),
5813 OPC_CMP_NGE_S = FOP (61, FMT_S),
5814 OPC_CMP_LE_S = FOP (62, FMT_S),
5815 OPC_CMP_NGT_S = FOP (63, FMT_S),
5817 OPC_ADD_D = FOP(0, FMT_D),
5818 OPC_SUB_D = FOP(1, FMT_D),
5819 OPC_MUL_D = FOP(2, FMT_D),
5820 OPC_DIV_D = FOP(3, FMT_D),
5821 OPC_SQRT_D = FOP(4, FMT_D),
5822 OPC_ABS_D = FOP(5, FMT_D),
5823 OPC_MOV_D = FOP(6, FMT_D),
5824 OPC_NEG_D = FOP(7, FMT_D),
5825 OPC_ROUND_L_D = FOP(8, FMT_D),
5826 OPC_TRUNC_L_D = FOP(9, FMT_D),
5827 OPC_CEIL_L_D = FOP(10, FMT_D),
5828 OPC_FLOOR_L_D = FOP(11, FMT_D),
5829 OPC_ROUND_W_D = FOP(12, FMT_D),
5830 OPC_TRUNC_W_D = FOP(13, FMT_D),
5831 OPC_CEIL_W_D = FOP(14, FMT_D),
5832 OPC_FLOOR_W_D = FOP(15, FMT_D),
5833 OPC_MOVCF_D = FOP(17, FMT_D),
5834 OPC_MOVZ_D = FOP(18, FMT_D),
5835 OPC_MOVN_D = FOP(19, FMT_D),
5836 OPC_RECIP_D = FOP(21, FMT_D),
5837 OPC_RSQRT_D = FOP(22, FMT_D),
5838 OPC_RECIP2_D = FOP(28, FMT_D),
5839 OPC_RECIP1_D = FOP(29, FMT_D),
5840 OPC_RSQRT1_D = FOP(30, FMT_D),
5841 OPC_RSQRT2_D = FOP(31, FMT_D),
5842 OPC_CVT_S_D = FOP(32, FMT_D),
5843 OPC_CVT_W_D = FOP(36, FMT_D),
5844 OPC_CVT_L_D = FOP(37, FMT_D),
5845 OPC_CMP_F_D = FOP (48, FMT_D),
5846 OPC_CMP_UN_D = FOP (49, FMT_D),
5847 OPC_CMP_EQ_D = FOP (50, FMT_D),
5848 OPC_CMP_UEQ_D = FOP (51, FMT_D),
5849 OPC_CMP_OLT_D = FOP (52, FMT_D),
5850 OPC_CMP_ULT_D = FOP (53, FMT_D),
5851 OPC_CMP_OLE_D = FOP (54, FMT_D),
5852 OPC_CMP_ULE_D = FOP (55, FMT_D),
5853 OPC_CMP_SF_D = FOP (56, FMT_D),
5854 OPC_CMP_NGLE_D = FOP (57, FMT_D),
5855 OPC_CMP_SEQ_D = FOP (58, FMT_D),
5856 OPC_CMP_NGL_D = FOP (59, FMT_D),
5857 OPC_CMP_LT_D = FOP (60, FMT_D),
5858 OPC_CMP_NGE_D = FOP (61, FMT_D),
5859 OPC_CMP_LE_D = FOP (62, FMT_D),
5860 OPC_CMP_NGT_D = FOP (63, FMT_D),
5862 OPC_CVT_S_W = FOP(32, FMT_W),
5863 OPC_CVT_D_W = FOP(33, FMT_W),
5864 OPC_CVT_S_L = FOP(32, FMT_L),
5865 OPC_CVT_D_L = FOP(33, FMT_L),
5866 OPC_CVT_PS_PW = FOP(38, FMT_W),
5868 OPC_ADD_PS = FOP(0, FMT_PS),
5869 OPC_SUB_PS = FOP(1, FMT_PS),
5870 OPC_MUL_PS = FOP(2, FMT_PS),
5871 OPC_DIV_PS = FOP(3, FMT_PS),
5872 OPC_ABS_PS = FOP(5, FMT_PS),
5873 OPC_MOV_PS = FOP(6, FMT_PS),
5874 OPC_NEG_PS = FOP(7, FMT_PS),
5875 OPC_MOVCF_PS = FOP(17, FMT_PS),
5876 OPC_MOVZ_PS = FOP(18, FMT_PS),
5877 OPC_MOVN_PS = FOP(19, FMT_PS),
5878 OPC_ADDR_PS = FOP(24, FMT_PS),
5879 OPC_MULR_PS = FOP(26, FMT_PS),
5880 OPC_RECIP2_PS = FOP(28, FMT_PS),
5881 OPC_RECIP1_PS = FOP(29, FMT_PS),
5882 OPC_RSQRT1_PS = FOP(30, FMT_PS),
5883 OPC_RSQRT2_PS = FOP(31, FMT_PS),
5885 OPC_CVT_S_PU = FOP(32, FMT_PS),
5886 OPC_CVT_PW_PS = FOP(36, FMT_PS),
5887 OPC_CVT_S_PL = FOP(40, FMT_PS),
5888 OPC_PLL_PS = FOP(44, FMT_PS),
5889 OPC_PLU_PS = FOP(45, FMT_PS),
5890 OPC_PUL_PS = FOP(46, FMT_PS),
5891 OPC_PUU_PS = FOP(47, FMT_PS),
5892 OPC_CMP_F_PS = FOP (48, FMT_PS),
5893 OPC_CMP_UN_PS = FOP (49, FMT_PS),
5894 OPC_CMP_EQ_PS = FOP (50, FMT_PS),
5895 OPC_CMP_UEQ_PS = FOP (51, FMT_PS),
5896 OPC_CMP_OLT_PS = FOP (52, FMT_PS),
5897 OPC_CMP_ULT_PS = FOP (53, FMT_PS),
5898 OPC_CMP_OLE_PS = FOP (54, FMT_PS),
5899 OPC_CMP_ULE_PS = FOP (55, FMT_PS),
5900 OPC_CMP_SF_PS = FOP (56, FMT_PS),
5901 OPC_CMP_NGLE_PS = FOP (57, FMT_PS),
5902 OPC_CMP_SEQ_PS = FOP (58, FMT_PS),
5903 OPC_CMP_NGL_PS = FOP (59, FMT_PS),
5904 OPC_CMP_LT_PS = FOP (60, FMT_PS),
5905 OPC_CMP_NGE_PS = FOP (61, FMT_PS),
5906 OPC_CMP_LE_PS = FOP (62, FMT_PS),
5907 OPC_CMP_NGT_PS = FOP (63, FMT_PS),
5910 static void gen_cp1 (DisasContext *ctx, uint32_t opc, int rt, int fs)
5912 const char *opn = "cp1 move";
5913 TCGv t0 = tcg_temp_new();
5915 switch (opc) {
5916 case OPC_MFC1:
5918 TCGv_i32 fp0 = tcg_temp_new_i32();
5920 gen_load_fpr32(fp0, fs);
5921 tcg_gen_ext_i32_tl(t0, fp0);
5922 tcg_temp_free_i32(fp0);
5924 gen_store_gpr(t0, rt);
5925 opn = "mfc1";
5926 break;
5927 case OPC_MTC1:
5928 gen_load_gpr(t0, rt);
5930 TCGv_i32 fp0 = tcg_temp_new_i32();
5932 tcg_gen_trunc_tl_i32(fp0, t0);
5933 gen_store_fpr32(fp0, fs);
5934 tcg_temp_free_i32(fp0);
5936 opn = "mtc1";
5937 break;
5938 case OPC_CFC1:
5939 gen_helper_1i(cfc1, t0, fs);
5940 gen_store_gpr(t0, rt);
5941 opn = "cfc1";
5942 break;
5943 case OPC_CTC1:
5944 gen_load_gpr(t0, rt);
5945 gen_helper_1i(ctc1, t0, fs);
5946 opn = "ctc1";
5947 break;
5948 #if defined(TARGET_MIPS64)
5949 case OPC_DMFC1:
5950 gen_load_fpr64(ctx, t0, fs);
5951 gen_store_gpr(t0, rt);
5952 opn = "dmfc1";
5953 break;
5954 case OPC_DMTC1:
5955 gen_load_gpr(t0, rt);
5956 gen_store_fpr64(ctx, t0, fs);
5957 opn = "dmtc1";
5958 break;
5959 #endif
5960 case OPC_MFHC1:
5962 TCGv_i32 fp0 = tcg_temp_new_i32();
5964 gen_load_fpr32h(fp0, fs);
5965 tcg_gen_ext_i32_tl(t0, fp0);
5966 tcg_temp_free_i32(fp0);
5968 gen_store_gpr(t0, rt);
5969 opn = "mfhc1";
5970 break;
5971 case OPC_MTHC1:
5972 gen_load_gpr(t0, rt);
5974 TCGv_i32 fp0 = tcg_temp_new_i32();
5976 tcg_gen_trunc_tl_i32(fp0, t0);
5977 gen_store_fpr32h(fp0, fs);
5978 tcg_temp_free_i32(fp0);
5980 opn = "mthc1";
5981 break;
5982 default:
5983 MIPS_INVAL(opn);
5984 generate_exception (ctx, EXCP_RI);
5985 goto out;
5987 MIPS_DEBUG("%s %s %s", opn, regnames[rt], fregnames[fs]);
5989 out:
5990 tcg_temp_free(t0);
5993 static void gen_movci (DisasContext *ctx, int rd, int rs, int cc, int tf)
5995 int l1;
5996 TCGCond cond;
5997 TCGv_i32 t0;
5999 if (rd == 0) {
6000 /* Treat as NOP. */
6001 return;
6004 if (tf)
6005 cond = TCG_COND_EQ;
6006 else
6007 cond = TCG_COND_NE;
6009 l1 = gen_new_label();
6010 t0 = tcg_temp_new_i32();
6011 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
6012 tcg_gen_brcondi_i32(cond, t0, 0, l1);
6013 tcg_temp_free_i32(t0);
6014 if (rs == 0) {
6015 tcg_gen_movi_tl(cpu_gpr[rd], 0);
6016 } else {
6017 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
6019 gen_set_label(l1);
6022 static inline void gen_movcf_s (int fs, int fd, int cc, int tf)
6024 int cond;
6025 TCGv_i32 t0 = tcg_temp_new_i32();
6026 int l1 = gen_new_label();
6028 if (tf)
6029 cond = TCG_COND_EQ;
6030 else
6031 cond = TCG_COND_NE;
6033 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
6034 tcg_gen_brcondi_i32(cond, t0, 0, l1);
6035 gen_load_fpr32(t0, fs);
6036 gen_store_fpr32(t0, fd);
6037 gen_set_label(l1);
6038 tcg_temp_free_i32(t0);
6041 static inline void gen_movcf_d (DisasContext *ctx, int fs, int fd, int cc, int tf)
6043 int cond;
6044 TCGv_i32 t0 = tcg_temp_new_i32();
6045 TCGv_i64 fp0;
6046 int l1 = gen_new_label();
6048 if (tf)
6049 cond = TCG_COND_EQ;
6050 else
6051 cond = TCG_COND_NE;
6053 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
6054 tcg_gen_brcondi_i32(cond, t0, 0, l1);
6055 tcg_temp_free_i32(t0);
6056 fp0 = tcg_temp_new_i64();
6057 gen_load_fpr64(ctx, fp0, fs);
6058 gen_store_fpr64(ctx, fp0, fd);
6059 tcg_temp_free_i64(fp0);
6060 gen_set_label(l1);
6063 static inline void gen_movcf_ps (int fs, int fd, int cc, int tf)
6065 int cond;
6066 TCGv_i32 t0 = tcg_temp_new_i32();
6067 int l1 = gen_new_label();
6068 int l2 = gen_new_label();
6070 if (tf)
6071 cond = TCG_COND_EQ;
6072 else
6073 cond = TCG_COND_NE;
6075 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
6076 tcg_gen_brcondi_i32(cond, t0, 0, l1);
6077 gen_load_fpr32(t0, fs);
6078 gen_store_fpr32(t0, fd);
6079 gen_set_label(l1);
6081 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc+1));
6082 tcg_gen_brcondi_i32(cond, t0, 0, l2);
6083 gen_load_fpr32h(t0, fs);
6084 gen_store_fpr32h(t0, fd);
6085 tcg_temp_free_i32(t0);
6086 gen_set_label(l2);
6090 static void gen_farith (DisasContext *ctx, enum fopcode op1,
6091 int ft, int fs, int fd, int cc)
6093 const char *opn = "farith";
6094 const char *condnames[] = {
6095 "c.f",
6096 "c.un",
6097 "c.eq",
6098 "c.ueq",
6099 "c.olt",
6100 "c.ult",
6101 "c.ole",
6102 "c.ule",
6103 "c.sf",
6104 "c.ngle",
6105 "c.seq",
6106 "c.ngl",
6107 "c.lt",
6108 "c.nge",
6109 "c.le",
6110 "c.ngt",
6112 const char *condnames_abs[] = {
6113 "cabs.f",
6114 "cabs.un",
6115 "cabs.eq",
6116 "cabs.ueq",
6117 "cabs.olt",
6118 "cabs.ult",
6119 "cabs.ole",
6120 "cabs.ule",
6121 "cabs.sf",
6122 "cabs.ngle",
6123 "cabs.seq",
6124 "cabs.ngl",
6125 "cabs.lt",
6126 "cabs.nge",
6127 "cabs.le",
6128 "cabs.ngt",
6130 enum { BINOP, CMPOP, OTHEROP } optype = OTHEROP;
6131 uint32_t func = ctx->opcode & 0x3f;
6133 switch (op1) {
6134 case OPC_ADD_S:
6136 TCGv_i32 fp0 = tcg_temp_new_i32();
6137 TCGv_i32 fp1 = tcg_temp_new_i32();
6139 gen_load_fpr32(fp0, fs);
6140 gen_load_fpr32(fp1, ft);
6141 gen_helper_float_add_s(fp0, fp0, fp1);
6142 tcg_temp_free_i32(fp1);
6143 gen_store_fpr32(fp0, fd);
6144 tcg_temp_free_i32(fp0);
6146 opn = "add.s";
6147 optype = BINOP;
6148 break;
6149 case OPC_SUB_S:
6151 TCGv_i32 fp0 = tcg_temp_new_i32();
6152 TCGv_i32 fp1 = tcg_temp_new_i32();
6154 gen_load_fpr32(fp0, fs);
6155 gen_load_fpr32(fp1, ft);
6156 gen_helper_float_sub_s(fp0, fp0, fp1);
6157 tcg_temp_free_i32(fp1);
6158 gen_store_fpr32(fp0, fd);
6159 tcg_temp_free_i32(fp0);
6161 opn = "sub.s";
6162 optype = BINOP;
6163 break;
6164 case OPC_MUL_S:
6166 TCGv_i32 fp0 = tcg_temp_new_i32();
6167 TCGv_i32 fp1 = tcg_temp_new_i32();
6169 gen_load_fpr32(fp0, fs);
6170 gen_load_fpr32(fp1, ft);
6171 gen_helper_float_mul_s(fp0, fp0, fp1);
6172 tcg_temp_free_i32(fp1);
6173 gen_store_fpr32(fp0, fd);
6174 tcg_temp_free_i32(fp0);
6176 opn = "mul.s";
6177 optype = BINOP;
6178 break;
6179 case OPC_DIV_S:
6181 TCGv_i32 fp0 = tcg_temp_new_i32();
6182 TCGv_i32 fp1 = tcg_temp_new_i32();
6184 gen_load_fpr32(fp0, fs);
6185 gen_load_fpr32(fp1, ft);
6186 gen_helper_float_div_s(fp0, fp0, fp1);
6187 tcg_temp_free_i32(fp1);
6188 gen_store_fpr32(fp0, fd);
6189 tcg_temp_free_i32(fp0);
6191 opn = "div.s";
6192 optype = BINOP;
6193 break;
6194 case OPC_SQRT_S:
6196 TCGv_i32 fp0 = tcg_temp_new_i32();
6198 gen_load_fpr32(fp0, fs);
6199 gen_helper_float_sqrt_s(fp0, fp0);
6200 gen_store_fpr32(fp0, fd);
6201 tcg_temp_free_i32(fp0);
6203 opn = "sqrt.s";
6204 break;
6205 case OPC_ABS_S:
6207 TCGv_i32 fp0 = tcg_temp_new_i32();
6209 gen_load_fpr32(fp0, fs);
6210 gen_helper_float_abs_s(fp0, fp0);
6211 gen_store_fpr32(fp0, fd);
6212 tcg_temp_free_i32(fp0);
6214 opn = "abs.s";
6215 break;
6216 case OPC_MOV_S:
6218 TCGv_i32 fp0 = tcg_temp_new_i32();
6220 gen_load_fpr32(fp0, fs);
6221 gen_store_fpr32(fp0, fd);
6222 tcg_temp_free_i32(fp0);
6224 opn = "mov.s";
6225 break;
6226 case OPC_NEG_S:
6228 TCGv_i32 fp0 = tcg_temp_new_i32();
6230 gen_load_fpr32(fp0, fs);
6231 gen_helper_float_chs_s(fp0, fp0);
6232 gen_store_fpr32(fp0, fd);
6233 tcg_temp_free_i32(fp0);
6235 opn = "neg.s";
6236 break;
6237 case OPC_ROUND_L_S:
6238 check_cp1_64bitmode(ctx);
6240 TCGv_i32 fp32 = tcg_temp_new_i32();
6241 TCGv_i64 fp64 = tcg_temp_new_i64();
6243 gen_load_fpr32(fp32, fs);
6244 gen_helper_float_roundl_s(fp64, fp32);
6245 tcg_temp_free_i32(fp32);
6246 gen_store_fpr64(ctx, fp64, fd);
6247 tcg_temp_free_i64(fp64);
6249 opn = "round.l.s";
6250 break;
6251 case OPC_TRUNC_L_S:
6252 check_cp1_64bitmode(ctx);
6254 TCGv_i32 fp32 = tcg_temp_new_i32();
6255 TCGv_i64 fp64 = tcg_temp_new_i64();
6257 gen_load_fpr32(fp32, fs);
6258 gen_helper_float_truncl_s(fp64, fp32);
6259 tcg_temp_free_i32(fp32);
6260 gen_store_fpr64(ctx, fp64, fd);
6261 tcg_temp_free_i64(fp64);
6263 opn = "trunc.l.s";
6264 break;
6265 case OPC_CEIL_L_S:
6266 check_cp1_64bitmode(ctx);
6268 TCGv_i32 fp32 = tcg_temp_new_i32();
6269 TCGv_i64 fp64 = tcg_temp_new_i64();
6271 gen_load_fpr32(fp32, fs);
6272 gen_helper_float_ceill_s(fp64, fp32);
6273 tcg_temp_free_i32(fp32);
6274 gen_store_fpr64(ctx, fp64, fd);
6275 tcg_temp_free_i64(fp64);
6277 opn = "ceil.l.s";
6278 break;
6279 case OPC_FLOOR_L_S:
6280 check_cp1_64bitmode(ctx);
6282 TCGv_i32 fp32 = tcg_temp_new_i32();
6283 TCGv_i64 fp64 = tcg_temp_new_i64();
6285 gen_load_fpr32(fp32, fs);
6286 gen_helper_float_floorl_s(fp64, fp32);
6287 tcg_temp_free_i32(fp32);
6288 gen_store_fpr64(ctx, fp64, fd);
6289 tcg_temp_free_i64(fp64);
6291 opn = "floor.l.s";
6292 break;
6293 case OPC_ROUND_W_S:
6295 TCGv_i32 fp0 = tcg_temp_new_i32();
6297 gen_load_fpr32(fp0, fs);
6298 gen_helper_float_roundw_s(fp0, fp0);
6299 gen_store_fpr32(fp0, fd);
6300 tcg_temp_free_i32(fp0);
6302 opn = "round.w.s";
6303 break;
6304 case OPC_TRUNC_W_S:
6306 TCGv_i32 fp0 = tcg_temp_new_i32();
6308 gen_load_fpr32(fp0, fs);
6309 gen_helper_float_truncw_s(fp0, fp0);
6310 gen_store_fpr32(fp0, fd);
6311 tcg_temp_free_i32(fp0);
6313 opn = "trunc.w.s";
6314 break;
6315 case OPC_CEIL_W_S:
6317 TCGv_i32 fp0 = tcg_temp_new_i32();
6319 gen_load_fpr32(fp0, fs);
6320 gen_helper_float_ceilw_s(fp0, fp0);
6321 gen_store_fpr32(fp0, fd);
6322 tcg_temp_free_i32(fp0);
6324 opn = "ceil.w.s";
6325 break;
6326 case OPC_FLOOR_W_S:
6328 TCGv_i32 fp0 = tcg_temp_new_i32();
6330 gen_load_fpr32(fp0, fs);
6331 gen_helper_float_floorw_s(fp0, fp0);
6332 gen_store_fpr32(fp0, fd);
6333 tcg_temp_free_i32(fp0);
6335 opn = "floor.w.s";
6336 break;
6337 case OPC_MOVCF_S:
6338 gen_movcf_s(fs, fd, (ft >> 2) & 0x7, ft & 0x1);
6339 opn = "movcf.s";
6340 break;
6341 case OPC_MOVZ_S:
6343 int l1 = gen_new_label();
6344 TCGv_i32 fp0;
6346 if (ft != 0) {
6347 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[ft], 0, l1);
6349 fp0 = tcg_temp_new_i32();
6350 gen_load_fpr32(fp0, fs);
6351 gen_store_fpr32(fp0, fd);
6352 tcg_temp_free_i32(fp0);
6353 gen_set_label(l1);
6355 opn = "movz.s";
6356 break;
6357 case OPC_MOVN_S:
6359 int l1 = gen_new_label();
6360 TCGv_i32 fp0;
6362 if (ft != 0) {
6363 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[ft], 0, l1);
6364 fp0 = tcg_temp_new_i32();
6365 gen_load_fpr32(fp0, fs);
6366 gen_store_fpr32(fp0, fd);
6367 tcg_temp_free_i32(fp0);
6368 gen_set_label(l1);
6371 opn = "movn.s";
6372 break;
6373 case OPC_RECIP_S:
6374 check_cop1x(ctx);
6376 TCGv_i32 fp0 = tcg_temp_new_i32();
6378 gen_load_fpr32(fp0, fs);
6379 gen_helper_float_recip_s(fp0, fp0);
6380 gen_store_fpr32(fp0, fd);
6381 tcg_temp_free_i32(fp0);
6383 opn = "recip.s";
6384 break;
6385 case OPC_RSQRT_S:
6386 check_cop1x(ctx);
6388 TCGv_i32 fp0 = tcg_temp_new_i32();
6390 gen_load_fpr32(fp0, fs);
6391 gen_helper_float_rsqrt_s(fp0, fp0);
6392 gen_store_fpr32(fp0, fd);
6393 tcg_temp_free_i32(fp0);
6395 opn = "rsqrt.s";
6396 break;
6397 case OPC_RECIP2_S:
6398 check_cp1_64bitmode(ctx);
6400 TCGv_i32 fp0 = tcg_temp_new_i32();
6401 TCGv_i32 fp1 = tcg_temp_new_i32();
6403 gen_load_fpr32(fp0, fs);
6404 gen_load_fpr32(fp1, fd);
6405 gen_helper_float_recip2_s(fp0, fp0, fp1);
6406 tcg_temp_free_i32(fp1);
6407 gen_store_fpr32(fp0, fd);
6408 tcg_temp_free_i32(fp0);
6410 opn = "recip2.s";
6411 break;
6412 case OPC_RECIP1_S:
6413 check_cp1_64bitmode(ctx);
6415 TCGv_i32 fp0 = tcg_temp_new_i32();
6417 gen_load_fpr32(fp0, fs);
6418 gen_helper_float_recip1_s(fp0, fp0);
6419 gen_store_fpr32(fp0, fd);
6420 tcg_temp_free_i32(fp0);
6422 opn = "recip1.s";
6423 break;
6424 case OPC_RSQRT1_S:
6425 check_cp1_64bitmode(ctx);
6427 TCGv_i32 fp0 = tcg_temp_new_i32();
6429 gen_load_fpr32(fp0, fs);
6430 gen_helper_float_rsqrt1_s(fp0, fp0);
6431 gen_store_fpr32(fp0, fd);
6432 tcg_temp_free_i32(fp0);
6434 opn = "rsqrt1.s";
6435 break;
6436 case OPC_RSQRT2_S:
6437 check_cp1_64bitmode(ctx);
6439 TCGv_i32 fp0 = tcg_temp_new_i32();
6440 TCGv_i32 fp1 = tcg_temp_new_i32();
6442 gen_load_fpr32(fp0, fs);
6443 gen_load_fpr32(fp1, ft);
6444 gen_helper_float_rsqrt2_s(fp0, fp0, fp1);
6445 tcg_temp_free_i32(fp1);
6446 gen_store_fpr32(fp0, fd);
6447 tcg_temp_free_i32(fp0);
6449 opn = "rsqrt2.s";
6450 break;
6451 case OPC_CVT_D_S:
6452 check_cp1_registers(ctx, fd);
6454 TCGv_i32 fp32 = tcg_temp_new_i32();
6455 TCGv_i64 fp64 = tcg_temp_new_i64();
6457 gen_load_fpr32(fp32, fs);
6458 gen_helper_float_cvtd_s(fp64, fp32);
6459 tcg_temp_free_i32(fp32);
6460 gen_store_fpr64(ctx, fp64, fd);
6461 tcg_temp_free_i64(fp64);
6463 opn = "cvt.d.s";
6464 break;
6465 case OPC_CVT_W_S:
6467 TCGv_i32 fp0 = tcg_temp_new_i32();
6469 gen_load_fpr32(fp0, fs);
6470 gen_helper_float_cvtw_s(fp0, fp0);
6471 gen_store_fpr32(fp0, fd);
6472 tcg_temp_free_i32(fp0);
6474 opn = "cvt.w.s";
6475 break;
6476 case OPC_CVT_L_S:
6477 check_cp1_64bitmode(ctx);
6479 TCGv_i32 fp32 = tcg_temp_new_i32();
6480 TCGv_i64 fp64 = tcg_temp_new_i64();
6482 gen_load_fpr32(fp32, fs);
6483 gen_helper_float_cvtl_s(fp64, fp32);
6484 tcg_temp_free_i32(fp32);
6485 gen_store_fpr64(ctx, fp64, fd);
6486 tcg_temp_free_i64(fp64);
6488 opn = "cvt.l.s";
6489 break;
6490 case OPC_CVT_PS_S:
6491 check_cp1_64bitmode(ctx);
6493 TCGv_i64 fp64 = tcg_temp_new_i64();
6494 TCGv_i32 fp32_0 = tcg_temp_new_i32();
6495 TCGv_i32 fp32_1 = tcg_temp_new_i32();
6497 gen_load_fpr32(fp32_0, fs);
6498 gen_load_fpr32(fp32_1, ft);
6499 tcg_gen_concat_i32_i64(fp64, fp32_0, fp32_1);
6500 tcg_temp_free_i32(fp32_1);
6501 tcg_temp_free_i32(fp32_0);
6502 gen_store_fpr64(ctx, fp64, fd);
6503 tcg_temp_free_i64(fp64);
6505 opn = "cvt.ps.s";
6506 break;
6507 case OPC_CMP_F_S:
6508 case OPC_CMP_UN_S:
6509 case OPC_CMP_EQ_S:
6510 case OPC_CMP_UEQ_S:
6511 case OPC_CMP_OLT_S:
6512 case OPC_CMP_ULT_S:
6513 case OPC_CMP_OLE_S:
6514 case OPC_CMP_ULE_S:
6515 case OPC_CMP_SF_S:
6516 case OPC_CMP_NGLE_S:
6517 case OPC_CMP_SEQ_S:
6518 case OPC_CMP_NGL_S:
6519 case OPC_CMP_LT_S:
6520 case OPC_CMP_NGE_S:
6521 case OPC_CMP_LE_S:
6522 case OPC_CMP_NGT_S:
6523 if (ctx->opcode & (1 << 6)) {
6524 gen_cmpabs_s(ctx, func-48, ft, fs, cc);
6525 opn = condnames_abs[func-48];
6526 } else {
6527 gen_cmp_s(ctx, func-48, ft, fs, cc);
6528 opn = condnames[func-48];
6530 break;
6531 case OPC_ADD_D:
6532 check_cp1_registers(ctx, fs | ft | fd);
6534 TCGv_i64 fp0 = tcg_temp_new_i64();
6535 TCGv_i64 fp1 = tcg_temp_new_i64();
6537 gen_load_fpr64(ctx, fp0, fs);
6538 gen_load_fpr64(ctx, fp1, ft);
6539 gen_helper_float_add_d(fp0, fp0, fp1);
6540 tcg_temp_free_i64(fp1);
6541 gen_store_fpr64(ctx, fp0, fd);
6542 tcg_temp_free_i64(fp0);
6544 opn = "add.d";
6545 optype = BINOP;
6546 break;
6547 case OPC_SUB_D:
6548 check_cp1_registers(ctx, fs | ft | fd);
6550 TCGv_i64 fp0 = tcg_temp_new_i64();
6551 TCGv_i64 fp1 = tcg_temp_new_i64();
6553 gen_load_fpr64(ctx, fp0, fs);
6554 gen_load_fpr64(ctx, fp1, ft);
6555 gen_helper_float_sub_d(fp0, fp0, fp1);
6556 tcg_temp_free_i64(fp1);
6557 gen_store_fpr64(ctx, fp0, fd);
6558 tcg_temp_free_i64(fp0);
6560 opn = "sub.d";
6561 optype = BINOP;
6562 break;
6563 case OPC_MUL_D:
6564 check_cp1_registers(ctx, fs | ft | fd);
6566 TCGv_i64 fp0 = tcg_temp_new_i64();
6567 TCGv_i64 fp1 = tcg_temp_new_i64();
6569 gen_load_fpr64(ctx, fp0, fs);
6570 gen_load_fpr64(ctx, fp1, ft);
6571 gen_helper_float_mul_d(fp0, fp0, fp1);
6572 tcg_temp_free_i64(fp1);
6573 gen_store_fpr64(ctx, fp0, fd);
6574 tcg_temp_free_i64(fp0);
6576 opn = "mul.d";
6577 optype = BINOP;
6578 break;
6579 case OPC_DIV_D:
6580 check_cp1_registers(ctx, fs | ft | fd);
6582 TCGv_i64 fp0 = tcg_temp_new_i64();
6583 TCGv_i64 fp1 = tcg_temp_new_i64();
6585 gen_load_fpr64(ctx, fp0, fs);
6586 gen_load_fpr64(ctx, fp1, ft);
6587 gen_helper_float_div_d(fp0, fp0, fp1);
6588 tcg_temp_free_i64(fp1);
6589 gen_store_fpr64(ctx, fp0, fd);
6590 tcg_temp_free_i64(fp0);
6592 opn = "div.d";
6593 optype = BINOP;
6594 break;
6595 case OPC_SQRT_D:
6596 check_cp1_registers(ctx, fs | fd);
6598 TCGv_i64 fp0 = tcg_temp_new_i64();
6600 gen_load_fpr64(ctx, fp0, fs);
6601 gen_helper_float_sqrt_d(fp0, fp0);
6602 gen_store_fpr64(ctx, fp0, fd);
6603 tcg_temp_free_i64(fp0);
6605 opn = "sqrt.d";
6606 break;
6607 case OPC_ABS_D:
6608 check_cp1_registers(ctx, fs | fd);
6610 TCGv_i64 fp0 = tcg_temp_new_i64();
6612 gen_load_fpr64(ctx, fp0, fs);
6613 gen_helper_float_abs_d(fp0, fp0);
6614 gen_store_fpr64(ctx, fp0, fd);
6615 tcg_temp_free_i64(fp0);
6617 opn = "abs.d";
6618 break;
6619 case OPC_MOV_D:
6620 check_cp1_registers(ctx, fs | fd);
6622 TCGv_i64 fp0 = tcg_temp_new_i64();
6624 gen_load_fpr64(ctx, fp0, fs);
6625 gen_store_fpr64(ctx, fp0, fd);
6626 tcg_temp_free_i64(fp0);
6628 opn = "mov.d";
6629 break;
6630 case OPC_NEG_D:
6631 check_cp1_registers(ctx, fs | fd);
6633 TCGv_i64 fp0 = tcg_temp_new_i64();
6635 gen_load_fpr64(ctx, fp0, fs);
6636 gen_helper_float_chs_d(fp0, fp0);
6637 gen_store_fpr64(ctx, fp0, fd);
6638 tcg_temp_free_i64(fp0);
6640 opn = "neg.d";
6641 break;
6642 case OPC_ROUND_L_D:
6643 check_cp1_64bitmode(ctx);
6645 TCGv_i64 fp0 = tcg_temp_new_i64();
6647 gen_load_fpr64(ctx, fp0, fs);
6648 gen_helper_float_roundl_d(fp0, fp0);
6649 gen_store_fpr64(ctx, fp0, fd);
6650 tcg_temp_free_i64(fp0);
6652 opn = "round.l.d";
6653 break;
6654 case OPC_TRUNC_L_D:
6655 check_cp1_64bitmode(ctx);
6657 TCGv_i64 fp0 = tcg_temp_new_i64();
6659 gen_load_fpr64(ctx, fp0, fs);
6660 gen_helper_float_truncl_d(fp0, fp0);
6661 gen_store_fpr64(ctx, fp0, fd);
6662 tcg_temp_free_i64(fp0);
6664 opn = "trunc.l.d";
6665 break;
6666 case OPC_CEIL_L_D:
6667 check_cp1_64bitmode(ctx);
6669 TCGv_i64 fp0 = tcg_temp_new_i64();
6671 gen_load_fpr64(ctx, fp0, fs);
6672 gen_helper_float_ceill_d(fp0, fp0);
6673 gen_store_fpr64(ctx, fp0, fd);
6674 tcg_temp_free_i64(fp0);
6676 opn = "ceil.l.d";
6677 break;
6678 case OPC_FLOOR_L_D:
6679 check_cp1_64bitmode(ctx);
6681 TCGv_i64 fp0 = tcg_temp_new_i64();
6683 gen_load_fpr64(ctx, fp0, fs);
6684 gen_helper_float_floorl_d(fp0, fp0);
6685 gen_store_fpr64(ctx, fp0, fd);
6686 tcg_temp_free_i64(fp0);
6688 opn = "floor.l.d";
6689 break;
6690 case OPC_ROUND_W_D:
6691 check_cp1_registers(ctx, fs);
6693 TCGv_i32 fp32 = tcg_temp_new_i32();
6694 TCGv_i64 fp64 = tcg_temp_new_i64();
6696 gen_load_fpr64(ctx, fp64, fs);
6697 gen_helper_float_roundw_d(fp32, fp64);
6698 tcg_temp_free_i64(fp64);
6699 gen_store_fpr32(fp32, fd);
6700 tcg_temp_free_i32(fp32);
6702 opn = "round.w.d";
6703 break;
6704 case OPC_TRUNC_W_D:
6705 check_cp1_registers(ctx, fs);
6707 TCGv_i32 fp32 = tcg_temp_new_i32();
6708 TCGv_i64 fp64 = tcg_temp_new_i64();
6710 gen_load_fpr64(ctx, fp64, fs);
6711 gen_helper_float_truncw_d(fp32, fp64);
6712 tcg_temp_free_i64(fp64);
6713 gen_store_fpr32(fp32, fd);
6714 tcg_temp_free_i32(fp32);
6716 opn = "trunc.w.d";
6717 break;
6718 case OPC_CEIL_W_D:
6719 check_cp1_registers(ctx, fs);
6721 TCGv_i32 fp32 = tcg_temp_new_i32();
6722 TCGv_i64 fp64 = tcg_temp_new_i64();
6724 gen_load_fpr64(ctx, fp64, fs);
6725 gen_helper_float_ceilw_d(fp32, fp64);
6726 tcg_temp_free_i64(fp64);
6727 gen_store_fpr32(fp32, fd);
6728 tcg_temp_free_i32(fp32);
6730 opn = "ceil.w.d";
6731 break;
6732 case OPC_FLOOR_W_D:
6733 check_cp1_registers(ctx, fs);
6735 TCGv_i32 fp32 = tcg_temp_new_i32();
6736 TCGv_i64 fp64 = tcg_temp_new_i64();
6738 gen_load_fpr64(ctx, fp64, fs);
6739 gen_helper_float_floorw_d(fp32, fp64);
6740 tcg_temp_free_i64(fp64);
6741 gen_store_fpr32(fp32, fd);
6742 tcg_temp_free_i32(fp32);
6744 opn = "floor.w.d";
6745 break;
6746 case OPC_MOVCF_D:
6747 gen_movcf_d(ctx, fs, fd, (ft >> 2) & 0x7, ft & 0x1);
6748 opn = "movcf.d";
6749 break;
6750 case OPC_MOVZ_D:
6752 int l1 = gen_new_label();
6753 TCGv_i64 fp0;
6755 if (ft != 0) {
6756 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[ft], 0, l1);
6758 fp0 = tcg_temp_new_i64();
6759 gen_load_fpr64(ctx, fp0, fs);
6760 gen_store_fpr64(ctx, fp0, fd);
6761 tcg_temp_free_i64(fp0);
6762 gen_set_label(l1);
6764 opn = "movz.d";
6765 break;
6766 case OPC_MOVN_D:
6768 int l1 = gen_new_label();
6769 TCGv_i64 fp0;
6771 if (ft != 0) {
6772 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[ft], 0, l1);
6773 fp0 = tcg_temp_new_i64();
6774 gen_load_fpr64(ctx, fp0, fs);
6775 gen_store_fpr64(ctx, fp0, fd);
6776 tcg_temp_free_i64(fp0);
6777 gen_set_label(l1);
6780 opn = "movn.d";
6781 break;
6782 case OPC_RECIP_D:
6783 check_cp1_64bitmode(ctx);
6785 TCGv_i64 fp0 = tcg_temp_new_i64();
6787 gen_load_fpr64(ctx, fp0, fs);
6788 gen_helper_float_recip_d(fp0, fp0);
6789 gen_store_fpr64(ctx, fp0, fd);
6790 tcg_temp_free_i64(fp0);
6792 opn = "recip.d";
6793 break;
6794 case OPC_RSQRT_D:
6795 check_cp1_64bitmode(ctx);
6797 TCGv_i64 fp0 = tcg_temp_new_i64();
6799 gen_load_fpr64(ctx, fp0, fs);
6800 gen_helper_float_rsqrt_d(fp0, fp0);
6801 gen_store_fpr64(ctx, fp0, fd);
6802 tcg_temp_free_i64(fp0);
6804 opn = "rsqrt.d";
6805 break;
6806 case OPC_RECIP2_D:
6807 check_cp1_64bitmode(ctx);
6809 TCGv_i64 fp0 = tcg_temp_new_i64();
6810 TCGv_i64 fp1 = tcg_temp_new_i64();
6812 gen_load_fpr64(ctx, fp0, fs);
6813 gen_load_fpr64(ctx, fp1, ft);
6814 gen_helper_float_recip2_d(fp0, fp0, fp1);
6815 tcg_temp_free_i64(fp1);
6816 gen_store_fpr64(ctx, fp0, fd);
6817 tcg_temp_free_i64(fp0);
6819 opn = "recip2.d";
6820 break;
6821 case OPC_RECIP1_D:
6822 check_cp1_64bitmode(ctx);
6824 TCGv_i64 fp0 = tcg_temp_new_i64();
6826 gen_load_fpr64(ctx, fp0, fs);
6827 gen_helper_float_recip1_d(fp0, fp0);
6828 gen_store_fpr64(ctx, fp0, fd);
6829 tcg_temp_free_i64(fp0);
6831 opn = "recip1.d";
6832 break;
6833 case OPC_RSQRT1_D:
6834 check_cp1_64bitmode(ctx);
6836 TCGv_i64 fp0 = tcg_temp_new_i64();
6838 gen_load_fpr64(ctx, fp0, fs);
6839 gen_helper_float_rsqrt1_d(fp0, fp0);
6840 gen_store_fpr64(ctx, fp0, fd);
6841 tcg_temp_free_i64(fp0);
6843 opn = "rsqrt1.d";
6844 break;
6845 case OPC_RSQRT2_D:
6846 check_cp1_64bitmode(ctx);
6848 TCGv_i64 fp0 = tcg_temp_new_i64();
6849 TCGv_i64 fp1 = tcg_temp_new_i64();
6851 gen_load_fpr64(ctx, fp0, fs);
6852 gen_load_fpr64(ctx, fp1, ft);
6853 gen_helper_float_rsqrt2_d(fp0, fp0, fp1);
6854 tcg_temp_free_i64(fp1);
6855 gen_store_fpr64(ctx, fp0, fd);
6856 tcg_temp_free_i64(fp0);
6858 opn = "rsqrt2.d";
6859 break;
6860 case OPC_CMP_F_D:
6861 case OPC_CMP_UN_D:
6862 case OPC_CMP_EQ_D:
6863 case OPC_CMP_UEQ_D:
6864 case OPC_CMP_OLT_D:
6865 case OPC_CMP_ULT_D:
6866 case OPC_CMP_OLE_D:
6867 case OPC_CMP_ULE_D:
6868 case OPC_CMP_SF_D:
6869 case OPC_CMP_NGLE_D:
6870 case OPC_CMP_SEQ_D:
6871 case OPC_CMP_NGL_D:
6872 case OPC_CMP_LT_D:
6873 case OPC_CMP_NGE_D:
6874 case OPC_CMP_LE_D:
6875 case OPC_CMP_NGT_D:
6876 if (ctx->opcode & (1 << 6)) {
6877 gen_cmpabs_d(ctx, func-48, ft, fs, cc);
6878 opn = condnames_abs[func-48];
6879 } else {
6880 gen_cmp_d(ctx, func-48, ft, fs, cc);
6881 opn = condnames[func-48];
6883 break;
6884 case OPC_CVT_S_D:
6885 check_cp1_registers(ctx, fs);
6887 TCGv_i32 fp32 = tcg_temp_new_i32();
6888 TCGv_i64 fp64 = tcg_temp_new_i64();
6890 gen_load_fpr64(ctx, fp64, fs);
6891 gen_helper_float_cvts_d(fp32, fp64);
6892 tcg_temp_free_i64(fp64);
6893 gen_store_fpr32(fp32, fd);
6894 tcg_temp_free_i32(fp32);
6896 opn = "cvt.s.d";
6897 break;
6898 case OPC_CVT_W_D:
6899 check_cp1_registers(ctx, fs);
6901 TCGv_i32 fp32 = tcg_temp_new_i32();
6902 TCGv_i64 fp64 = tcg_temp_new_i64();
6904 gen_load_fpr64(ctx, fp64, fs);
6905 gen_helper_float_cvtw_d(fp32, fp64);
6906 tcg_temp_free_i64(fp64);
6907 gen_store_fpr32(fp32, fd);
6908 tcg_temp_free_i32(fp32);
6910 opn = "cvt.w.d";
6911 break;
6912 case OPC_CVT_L_D:
6913 check_cp1_64bitmode(ctx);
6915 TCGv_i64 fp0 = tcg_temp_new_i64();
6917 gen_load_fpr64(ctx, fp0, fs);
6918 gen_helper_float_cvtl_d(fp0, fp0);
6919 gen_store_fpr64(ctx, fp0, fd);
6920 tcg_temp_free_i64(fp0);
6922 opn = "cvt.l.d";
6923 break;
6924 case OPC_CVT_S_W:
6926 TCGv_i32 fp0 = tcg_temp_new_i32();
6928 gen_load_fpr32(fp0, fs);
6929 gen_helper_float_cvts_w(fp0, fp0);
6930 gen_store_fpr32(fp0, fd);
6931 tcg_temp_free_i32(fp0);
6933 opn = "cvt.s.w";
6934 break;
6935 case OPC_CVT_D_W:
6936 check_cp1_registers(ctx, fd);
6938 TCGv_i32 fp32 = tcg_temp_new_i32();
6939 TCGv_i64 fp64 = tcg_temp_new_i64();
6941 gen_load_fpr32(fp32, fs);
6942 gen_helper_float_cvtd_w(fp64, fp32);
6943 tcg_temp_free_i32(fp32);
6944 gen_store_fpr64(ctx, fp64, fd);
6945 tcg_temp_free_i64(fp64);
6947 opn = "cvt.d.w";
6948 break;
6949 case OPC_CVT_S_L:
6950 check_cp1_64bitmode(ctx);
6952 TCGv_i32 fp32 = tcg_temp_new_i32();
6953 TCGv_i64 fp64 = tcg_temp_new_i64();
6955 gen_load_fpr64(ctx, fp64, fs);
6956 gen_helper_float_cvts_l(fp32, fp64);
6957 tcg_temp_free_i64(fp64);
6958 gen_store_fpr32(fp32, fd);
6959 tcg_temp_free_i32(fp32);
6961 opn = "cvt.s.l";
6962 break;
6963 case OPC_CVT_D_L:
6964 check_cp1_64bitmode(ctx);
6966 TCGv_i64 fp0 = tcg_temp_new_i64();
6968 gen_load_fpr64(ctx, fp0, fs);
6969 gen_helper_float_cvtd_l(fp0, fp0);
6970 gen_store_fpr64(ctx, fp0, fd);
6971 tcg_temp_free_i64(fp0);
6973 opn = "cvt.d.l";
6974 break;
6975 case OPC_CVT_PS_PW:
6976 check_cp1_64bitmode(ctx);
6978 TCGv_i64 fp0 = tcg_temp_new_i64();
6980 gen_load_fpr64(ctx, fp0, fs);
6981 gen_helper_float_cvtps_pw(fp0, fp0);
6982 gen_store_fpr64(ctx, fp0, fd);
6983 tcg_temp_free_i64(fp0);
6985 opn = "cvt.ps.pw";
6986 break;
6987 case OPC_ADD_PS:
6988 check_cp1_64bitmode(ctx);
6990 TCGv_i64 fp0 = tcg_temp_new_i64();
6991 TCGv_i64 fp1 = tcg_temp_new_i64();
6993 gen_load_fpr64(ctx, fp0, fs);
6994 gen_load_fpr64(ctx, fp1, ft);
6995 gen_helper_float_add_ps(fp0, fp0, fp1);
6996 tcg_temp_free_i64(fp1);
6997 gen_store_fpr64(ctx, fp0, fd);
6998 tcg_temp_free_i64(fp0);
7000 opn = "add.ps";
7001 break;
7002 case OPC_SUB_PS:
7003 check_cp1_64bitmode(ctx);
7005 TCGv_i64 fp0 = tcg_temp_new_i64();
7006 TCGv_i64 fp1 = tcg_temp_new_i64();
7008 gen_load_fpr64(ctx, fp0, fs);
7009 gen_load_fpr64(ctx, fp1, ft);
7010 gen_helper_float_sub_ps(fp0, fp0, fp1);
7011 tcg_temp_free_i64(fp1);
7012 gen_store_fpr64(ctx, fp0, fd);
7013 tcg_temp_free_i64(fp0);
7015 opn = "sub.ps";
7016 break;
7017 case OPC_MUL_PS:
7018 check_cp1_64bitmode(ctx);
7020 TCGv_i64 fp0 = tcg_temp_new_i64();
7021 TCGv_i64 fp1 = tcg_temp_new_i64();
7023 gen_load_fpr64(ctx, fp0, fs);
7024 gen_load_fpr64(ctx, fp1, ft);
7025 gen_helper_float_mul_ps(fp0, fp0, fp1);
7026 tcg_temp_free_i64(fp1);
7027 gen_store_fpr64(ctx, fp0, fd);
7028 tcg_temp_free_i64(fp0);
7030 opn = "mul.ps";
7031 break;
7032 case OPC_ABS_PS:
7033 check_cp1_64bitmode(ctx);
7035 TCGv_i64 fp0 = tcg_temp_new_i64();
7037 gen_load_fpr64(ctx, fp0, fs);
7038 gen_helper_float_abs_ps(fp0, fp0);
7039 gen_store_fpr64(ctx, fp0, fd);
7040 tcg_temp_free_i64(fp0);
7042 opn = "abs.ps";
7043 break;
7044 case OPC_MOV_PS:
7045 check_cp1_64bitmode(ctx);
7047 TCGv_i64 fp0 = tcg_temp_new_i64();
7049 gen_load_fpr64(ctx, fp0, fs);
7050 gen_store_fpr64(ctx, fp0, fd);
7051 tcg_temp_free_i64(fp0);
7053 opn = "mov.ps";
7054 break;
7055 case OPC_NEG_PS:
7056 check_cp1_64bitmode(ctx);
7058 TCGv_i64 fp0 = tcg_temp_new_i64();
7060 gen_load_fpr64(ctx, fp0, fs);
7061 gen_helper_float_chs_ps(fp0, fp0);
7062 gen_store_fpr64(ctx, fp0, fd);
7063 tcg_temp_free_i64(fp0);
7065 opn = "neg.ps";
7066 break;
7067 case OPC_MOVCF_PS:
7068 check_cp1_64bitmode(ctx);
7069 gen_movcf_ps(fs, fd, (ft >> 2) & 0x7, ft & 0x1);
7070 opn = "movcf.ps";
7071 break;
7072 case OPC_MOVZ_PS:
7073 check_cp1_64bitmode(ctx);
7075 int l1 = gen_new_label();
7076 TCGv_i64 fp0;
7078 if (ft != 0)
7079 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[ft], 0, l1);
7080 fp0 = tcg_temp_new_i64();
7081 gen_load_fpr64(ctx, fp0, fs);
7082 gen_store_fpr64(ctx, fp0, fd);
7083 tcg_temp_free_i64(fp0);
7084 gen_set_label(l1);
7086 opn = "movz.ps";
7087 break;
7088 case OPC_MOVN_PS:
7089 check_cp1_64bitmode(ctx);
7091 int l1 = gen_new_label();
7092 TCGv_i64 fp0;
7094 if (ft != 0) {
7095 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[ft], 0, l1);
7096 fp0 = tcg_temp_new_i64();
7097 gen_load_fpr64(ctx, fp0, fs);
7098 gen_store_fpr64(ctx, fp0, fd);
7099 tcg_temp_free_i64(fp0);
7100 gen_set_label(l1);
7103 opn = "movn.ps";
7104 break;
7105 case OPC_ADDR_PS:
7106 check_cp1_64bitmode(ctx);
7108 TCGv_i64 fp0 = tcg_temp_new_i64();
7109 TCGv_i64 fp1 = tcg_temp_new_i64();
7111 gen_load_fpr64(ctx, fp0, ft);
7112 gen_load_fpr64(ctx, fp1, fs);
7113 gen_helper_float_addr_ps(fp0, fp0, fp1);
7114 tcg_temp_free_i64(fp1);
7115 gen_store_fpr64(ctx, fp0, fd);
7116 tcg_temp_free_i64(fp0);
7118 opn = "addr.ps";
7119 break;
7120 case OPC_MULR_PS:
7121 check_cp1_64bitmode(ctx);
7123 TCGv_i64 fp0 = tcg_temp_new_i64();
7124 TCGv_i64 fp1 = tcg_temp_new_i64();
7126 gen_load_fpr64(ctx, fp0, ft);
7127 gen_load_fpr64(ctx, fp1, fs);
7128 gen_helper_float_mulr_ps(fp0, fp0, fp1);
7129 tcg_temp_free_i64(fp1);
7130 gen_store_fpr64(ctx, fp0, fd);
7131 tcg_temp_free_i64(fp0);
7133 opn = "mulr.ps";
7134 break;
7135 case OPC_RECIP2_PS:
7136 check_cp1_64bitmode(ctx);
7138 TCGv_i64 fp0 = tcg_temp_new_i64();
7139 TCGv_i64 fp1 = tcg_temp_new_i64();
7141 gen_load_fpr64(ctx, fp0, fs);
7142 gen_load_fpr64(ctx, fp1, fd);
7143 gen_helper_float_recip2_ps(fp0, fp0, fp1);
7144 tcg_temp_free_i64(fp1);
7145 gen_store_fpr64(ctx, fp0, fd);
7146 tcg_temp_free_i64(fp0);
7148 opn = "recip2.ps";
7149 break;
7150 case OPC_RECIP1_PS:
7151 check_cp1_64bitmode(ctx);
7153 TCGv_i64 fp0 = tcg_temp_new_i64();
7155 gen_load_fpr64(ctx, fp0, fs);
7156 gen_helper_float_recip1_ps(fp0, fp0);
7157 gen_store_fpr64(ctx, fp0, fd);
7158 tcg_temp_free_i64(fp0);
7160 opn = "recip1.ps";
7161 break;
7162 case OPC_RSQRT1_PS:
7163 check_cp1_64bitmode(ctx);
7165 TCGv_i64 fp0 = tcg_temp_new_i64();
7167 gen_load_fpr64(ctx, fp0, fs);
7168 gen_helper_float_rsqrt1_ps(fp0, fp0);
7169 gen_store_fpr64(ctx, fp0, fd);
7170 tcg_temp_free_i64(fp0);
7172 opn = "rsqrt1.ps";
7173 break;
7174 case OPC_RSQRT2_PS:
7175 check_cp1_64bitmode(ctx);
7177 TCGv_i64 fp0 = tcg_temp_new_i64();
7178 TCGv_i64 fp1 = tcg_temp_new_i64();
7180 gen_load_fpr64(ctx, fp0, fs);
7181 gen_load_fpr64(ctx, fp1, ft);
7182 gen_helper_float_rsqrt2_ps(fp0, fp0, fp1);
7183 tcg_temp_free_i64(fp1);
7184 gen_store_fpr64(ctx, fp0, fd);
7185 tcg_temp_free_i64(fp0);
7187 opn = "rsqrt2.ps";
7188 break;
7189 case OPC_CVT_S_PU:
7190 check_cp1_64bitmode(ctx);
7192 TCGv_i32 fp0 = tcg_temp_new_i32();
7194 gen_load_fpr32h(fp0, fs);
7195 gen_helper_float_cvts_pu(fp0, fp0);
7196 gen_store_fpr32(fp0, fd);
7197 tcg_temp_free_i32(fp0);
7199 opn = "cvt.s.pu";
7200 break;
7201 case OPC_CVT_PW_PS:
7202 check_cp1_64bitmode(ctx);
7204 TCGv_i64 fp0 = tcg_temp_new_i64();
7206 gen_load_fpr64(ctx, fp0, fs);
7207 gen_helper_float_cvtpw_ps(fp0, fp0);
7208 gen_store_fpr64(ctx, fp0, fd);
7209 tcg_temp_free_i64(fp0);
7211 opn = "cvt.pw.ps";
7212 break;
7213 case OPC_CVT_S_PL:
7214 check_cp1_64bitmode(ctx);
7216 TCGv_i32 fp0 = tcg_temp_new_i32();
7218 gen_load_fpr32(fp0, fs);
7219 gen_helper_float_cvts_pl(fp0, fp0);
7220 gen_store_fpr32(fp0, fd);
7221 tcg_temp_free_i32(fp0);
7223 opn = "cvt.s.pl";
7224 break;
7225 case OPC_PLL_PS:
7226 check_cp1_64bitmode(ctx);
7228 TCGv_i32 fp0 = tcg_temp_new_i32();
7229 TCGv_i32 fp1 = tcg_temp_new_i32();
7231 gen_load_fpr32(fp0, fs);
7232 gen_load_fpr32(fp1, ft);
7233 gen_store_fpr32h(fp0, fd);
7234 gen_store_fpr32(fp1, fd);
7235 tcg_temp_free_i32(fp0);
7236 tcg_temp_free_i32(fp1);
7238 opn = "pll.ps";
7239 break;
7240 case OPC_PLU_PS:
7241 check_cp1_64bitmode(ctx);
7243 TCGv_i32 fp0 = tcg_temp_new_i32();
7244 TCGv_i32 fp1 = tcg_temp_new_i32();
7246 gen_load_fpr32(fp0, fs);
7247 gen_load_fpr32h(fp1, ft);
7248 gen_store_fpr32(fp1, fd);
7249 gen_store_fpr32h(fp0, fd);
7250 tcg_temp_free_i32(fp0);
7251 tcg_temp_free_i32(fp1);
7253 opn = "plu.ps";
7254 break;
7255 case OPC_PUL_PS:
7256 check_cp1_64bitmode(ctx);
7258 TCGv_i32 fp0 = tcg_temp_new_i32();
7259 TCGv_i32 fp1 = tcg_temp_new_i32();
7261 gen_load_fpr32h(fp0, fs);
7262 gen_load_fpr32(fp1, ft);
7263 gen_store_fpr32(fp1, fd);
7264 gen_store_fpr32h(fp0, fd);
7265 tcg_temp_free_i32(fp0);
7266 tcg_temp_free_i32(fp1);
7268 opn = "pul.ps";
7269 break;
7270 case OPC_PUU_PS:
7271 check_cp1_64bitmode(ctx);
7273 TCGv_i32 fp0 = tcg_temp_new_i32();
7274 TCGv_i32 fp1 = tcg_temp_new_i32();
7276 gen_load_fpr32h(fp0, fs);
7277 gen_load_fpr32h(fp1, ft);
7278 gen_store_fpr32(fp1, fd);
7279 gen_store_fpr32h(fp0, fd);
7280 tcg_temp_free_i32(fp0);
7281 tcg_temp_free_i32(fp1);
7283 opn = "puu.ps";
7284 break;
7285 case OPC_CMP_F_PS:
7286 case OPC_CMP_UN_PS:
7287 case OPC_CMP_EQ_PS:
7288 case OPC_CMP_UEQ_PS:
7289 case OPC_CMP_OLT_PS:
7290 case OPC_CMP_ULT_PS:
7291 case OPC_CMP_OLE_PS:
7292 case OPC_CMP_ULE_PS:
7293 case OPC_CMP_SF_PS:
7294 case OPC_CMP_NGLE_PS:
7295 case OPC_CMP_SEQ_PS:
7296 case OPC_CMP_NGL_PS:
7297 case OPC_CMP_LT_PS:
7298 case OPC_CMP_NGE_PS:
7299 case OPC_CMP_LE_PS:
7300 case OPC_CMP_NGT_PS:
7301 if (ctx->opcode & (1 << 6)) {
7302 gen_cmpabs_ps(ctx, func-48, ft, fs, cc);
7303 opn = condnames_abs[func-48];
7304 } else {
7305 gen_cmp_ps(ctx, func-48, ft, fs, cc);
7306 opn = condnames[func-48];
7308 break;
7309 default:
7310 MIPS_INVAL(opn);
7311 generate_exception (ctx, EXCP_RI);
7312 return;
7314 switch (optype) {
7315 case BINOP:
7316 MIPS_DEBUG("%s %s, %s, %s", opn, fregnames[fd], fregnames[fs], fregnames[ft]);
7317 break;
7318 case CMPOP:
7319 MIPS_DEBUG("%s %s,%s", opn, fregnames[fs], fregnames[ft]);
7320 break;
7321 default:
7322 MIPS_DEBUG("%s %s,%s", opn, fregnames[fd], fregnames[fs]);
7323 break;
7327 /* Coprocessor 3 (FPU) */
7328 static void gen_flt3_ldst (DisasContext *ctx, uint32_t opc,
7329 int fd, int fs, int base, int index)
7331 const char *opn = "extended float load/store";
7332 int store = 0;
7333 TCGv t0 = tcg_temp_new();
7335 if (base == 0) {
7336 gen_load_gpr(t0, index);
7337 } else if (index == 0) {
7338 gen_load_gpr(t0, base);
7339 } else {
7340 gen_load_gpr(t0, index);
7341 gen_op_addr_add(ctx, t0, cpu_gpr[base], t0);
7343 /* Don't do NOP if destination is zero: we must perform the actual
7344 memory access. */
7345 save_cpu_state(ctx, 0);
7346 switch (opc) {
7347 case OPC_LWXC1:
7348 check_cop1x(ctx);
7350 TCGv_i32 fp0 = tcg_temp_new_i32();
7352 tcg_gen_qemu_ld32s(t0, t0, ctx->mem_idx);
7353 tcg_gen_trunc_tl_i32(fp0, t0);
7354 gen_store_fpr32(fp0, fd);
7355 tcg_temp_free_i32(fp0);
7357 opn = "lwxc1";
7358 break;
7359 case OPC_LDXC1:
7360 check_cop1x(ctx);
7361 check_cp1_registers(ctx, fd);
7363 TCGv_i64 fp0 = tcg_temp_new_i64();
7365 tcg_gen_qemu_ld64(fp0, t0, ctx->mem_idx);
7366 gen_store_fpr64(ctx, fp0, fd);
7367 tcg_temp_free_i64(fp0);
7369 opn = "ldxc1";
7370 break;
7371 case OPC_LUXC1:
7372 check_cp1_64bitmode(ctx);
7373 tcg_gen_andi_tl(t0, t0, ~0x7);
7375 TCGv_i64 fp0 = tcg_temp_new_i64();
7377 tcg_gen_qemu_ld64(fp0, t0, ctx->mem_idx);
7378 gen_store_fpr64(ctx, fp0, fd);
7379 tcg_temp_free_i64(fp0);
7381 opn = "luxc1";
7382 break;
7383 case OPC_SWXC1:
7384 check_cop1x(ctx);
7386 TCGv_i32 fp0 = tcg_temp_new_i32();
7387 TCGv t1 = tcg_temp_new();
7389 gen_load_fpr32(fp0, fs);
7390 tcg_gen_extu_i32_tl(t1, fp0);
7391 tcg_gen_qemu_st32(t1, t0, ctx->mem_idx);
7392 tcg_temp_free_i32(fp0);
7393 tcg_temp_free(t1);
7395 opn = "swxc1";
7396 store = 1;
7397 break;
7398 case OPC_SDXC1:
7399 check_cop1x(ctx);
7400 check_cp1_registers(ctx, fs);
7402 TCGv_i64 fp0 = tcg_temp_new_i64();
7404 gen_load_fpr64(ctx, fp0, fs);
7405 tcg_gen_qemu_st64(fp0, t0, ctx->mem_idx);
7406 tcg_temp_free_i64(fp0);
7408 opn = "sdxc1";
7409 store = 1;
7410 break;
7411 case OPC_SUXC1:
7412 check_cp1_64bitmode(ctx);
7413 tcg_gen_andi_tl(t0, t0, ~0x7);
7415 TCGv_i64 fp0 = tcg_temp_new_i64();
7417 gen_load_fpr64(ctx, fp0, fs);
7418 tcg_gen_qemu_st64(fp0, t0, ctx->mem_idx);
7419 tcg_temp_free_i64(fp0);
7421 opn = "suxc1";
7422 store = 1;
7423 break;
7425 tcg_temp_free(t0);
7426 MIPS_DEBUG("%s %s, %s(%s)", opn, fregnames[store ? fs : fd],
7427 regnames[index], regnames[base]);
7430 static void gen_flt3_arith (DisasContext *ctx, uint32_t opc,
7431 int fd, int fr, int fs, int ft)
7433 const char *opn = "flt3_arith";
7435 switch (opc) {
7436 case OPC_ALNV_PS:
7437 check_cp1_64bitmode(ctx);
7439 TCGv t0 = tcg_temp_local_new();
7440 TCGv_i32 fp = tcg_temp_new_i32();
7441 TCGv_i32 fph = tcg_temp_new_i32();
7442 int l1 = gen_new_label();
7443 int l2 = gen_new_label();
7445 gen_load_gpr(t0, fr);
7446 tcg_gen_andi_tl(t0, t0, 0x7);
7448 tcg_gen_brcondi_tl(TCG_COND_NE, t0, 0, l1);
7449 gen_load_fpr32(fp, fs);
7450 gen_load_fpr32h(fph, fs);
7451 gen_store_fpr32(fp, fd);
7452 gen_store_fpr32h(fph, fd);
7453 tcg_gen_br(l2);
7454 gen_set_label(l1);
7455 tcg_gen_brcondi_tl(TCG_COND_NE, t0, 4, l2);
7456 tcg_temp_free(t0);
7457 #ifdef TARGET_WORDS_BIGENDIAN
7458 gen_load_fpr32(fp, fs);
7459 gen_load_fpr32h(fph, ft);
7460 gen_store_fpr32h(fp, fd);
7461 gen_store_fpr32(fph, fd);
7462 #else
7463 gen_load_fpr32h(fph, fs);
7464 gen_load_fpr32(fp, ft);
7465 gen_store_fpr32(fph, fd);
7466 gen_store_fpr32h(fp, fd);
7467 #endif
7468 gen_set_label(l2);
7469 tcg_temp_free_i32(fp);
7470 tcg_temp_free_i32(fph);
7472 opn = "alnv.ps";
7473 break;
7474 case OPC_MADD_S:
7475 check_cop1x(ctx);
7477 TCGv_i32 fp0 = tcg_temp_new_i32();
7478 TCGv_i32 fp1 = tcg_temp_new_i32();
7479 TCGv_i32 fp2 = tcg_temp_new_i32();
7481 gen_load_fpr32(fp0, fs);
7482 gen_load_fpr32(fp1, ft);
7483 gen_load_fpr32(fp2, fr);
7484 gen_helper_float_muladd_s(fp2, fp0, fp1, fp2);
7485 tcg_temp_free_i32(fp0);
7486 tcg_temp_free_i32(fp1);
7487 gen_store_fpr32(fp2, fd);
7488 tcg_temp_free_i32(fp2);
7490 opn = "madd.s";
7491 break;
7492 case OPC_MADD_D:
7493 check_cop1x(ctx);
7494 check_cp1_registers(ctx, fd | fs | ft | fr);
7496 TCGv_i64 fp0 = tcg_temp_new_i64();
7497 TCGv_i64 fp1 = tcg_temp_new_i64();
7498 TCGv_i64 fp2 = tcg_temp_new_i64();
7500 gen_load_fpr64(ctx, fp0, fs);
7501 gen_load_fpr64(ctx, fp1, ft);
7502 gen_load_fpr64(ctx, fp2, fr);
7503 gen_helper_float_muladd_d(fp2, fp0, fp1, fp2);
7504 tcg_temp_free_i64(fp0);
7505 tcg_temp_free_i64(fp1);
7506 gen_store_fpr64(ctx, fp2, fd);
7507 tcg_temp_free_i64(fp2);
7509 opn = "madd.d";
7510 break;
7511 case OPC_MADD_PS:
7512 check_cp1_64bitmode(ctx);
7514 TCGv_i64 fp0 = tcg_temp_new_i64();
7515 TCGv_i64 fp1 = tcg_temp_new_i64();
7516 TCGv_i64 fp2 = tcg_temp_new_i64();
7518 gen_load_fpr64(ctx, fp0, fs);
7519 gen_load_fpr64(ctx, fp1, ft);
7520 gen_load_fpr64(ctx, fp2, fr);
7521 gen_helper_float_muladd_ps(fp2, fp0, fp1, fp2);
7522 tcg_temp_free_i64(fp0);
7523 tcg_temp_free_i64(fp1);
7524 gen_store_fpr64(ctx, fp2, fd);
7525 tcg_temp_free_i64(fp2);
7527 opn = "madd.ps";
7528 break;
7529 case OPC_MSUB_S:
7530 check_cop1x(ctx);
7532 TCGv_i32 fp0 = tcg_temp_new_i32();
7533 TCGv_i32 fp1 = tcg_temp_new_i32();
7534 TCGv_i32 fp2 = tcg_temp_new_i32();
7536 gen_load_fpr32(fp0, fs);
7537 gen_load_fpr32(fp1, ft);
7538 gen_load_fpr32(fp2, fr);
7539 gen_helper_float_mulsub_s(fp2, fp0, fp1, fp2);
7540 tcg_temp_free_i32(fp0);
7541 tcg_temp_free_i32(fp1);
7542 gen_store_fpr32(fp2, fd);
7543 tcg_temp_free_i32(fp2);
7545 opn = "msub.s";
7546 break;
7547 case OPC_MSUB_D:
7548 check_cop1x(ctx);
7549 check_cp1_registers(ctx, fd | fs | ft | fr);
7551 TCGv_i64 fp0 = tcg_temp_new_i64();
7552 TCGv_i64 fp1 = tcg_temp_new_i64();
7553 TCGv_i64 fp2 = tcg_temp_new_i64();
7555 gen_load_fpr64(ctx, fp0, fs);
7556 gen_load_fpr64(ctx, fp1, ft);
7557 gen_load_fpr64(ctx, fp2, fr);
7558 gen_helper_float_mulsub_d(fp2, fp0, fp1, fp2);
7559 tcg_temp_free_i64(fp0);
7560 tcg_temp_free_i64(fp1);
7561 gen_store_fpr64(ctx, fp2, fd);
7562 tcg_temp_free_i64(fp2);
7564 opn = "msub.d";
7565 break;
7566 case OPC_MSUB_PS:
7567 check_cp1_64bitmode(ctx);
7569 TCGv_i64 fp0 = tcg_temp_new_i64();
7570 TCGv_i64 fp1 = tcg_temp_new_i64();
7571 TCGv_i64 fp2 = tcg_temp_new_i64();
7573 gen_load_fpr64(ctx, fp0, fs);
7574 gen_load_fpr64(ctx, fp1, ft);
7575 gen_load_fpr64(ctx, fp2, fr);
7576 gen_helper_float_mulsub_ps(fp2, fp0, fp1, fp2);
7577 tcg_temp_free_i64(fp0);
7578 tcg_temp_free_i64(fp1);
7579 gen_store_fpr64(ctx, fp2, fd);
7580 tcg_temp_free_i64(fp2);
7582 opn = "msub.ps";
7583 break;
7584 case OPC_NMADD_S:
7585 check_cop1x(ctx);
7587 TCGv_i32 fp0 = tcg_temp_new_i32();
7588 TCGv_i32 fp1 = tcg_temp_new_i32();
7589 TCGv_i32 fp2 = tcg_temp_new_i32();
7591 gen_load_fpr32(fp0, fs);
7592 gen_load_fpr32(fp1, ft);
7593 gen_load_fpr32(fp2, fr);
7594 gen_helper_float_nmuladd_s(fp2, fp0, fp1, fp2);
7595 tcg_temp_free_i32(fp0);
7596 tcg_temp_free_i32(fp1);
7597 gen_store_fpr32(fp2, fd);
7598 tcg_temp_free_i32(fp2);
7600 opn = "nmadd.s";
7601 break;
7602 case OPC_NMADD_D:
7603 check_cop1x(ctx);
7604 check_cp1_registers(ctx, fd | fs | ft | fr);
7606 TCGv_i64 fp0 = tcg_temp_new_i64();
7607 TCGv_i64 fp1 = tcg_temp_new_i64();
7608 TCGv_i64 fp2 = tcg_temp_new_i64();
7610 gen_load_fpr64(ctx, fp0, fs);
7611 gen_load_fpr64(ctx, fp1, ft);
7612 gen_load_fpr64(ctx, fp2, fr);
7613 gen_helper_float_nmuladd_d(fp2, fp0, fp1, fp2);
7614 tcg_temp_free_i64(fp0);
7615 tcg_temp_free_i64(fp1);
7616 gen_store_fpr64(ctx, fp2, fd);
7617 tcg_temp_free_i64(fp2);
7619 opn = "nmadd.d";
7620 break;
7621 case OPC_NMADD_PS:
7622 check_cp1_64bitmode(ctx);
7624 TCGv_i64 fp0 = tcg_temp_new_i64();
7625 TCGv_i64 fp1 = tcg_temp_new_i64();
7626 TCGv_i64 fp2 = tcg_temp_new_i64();
7628 gen_load_fpr64(ctx, fp0, fs);
7629 gen_load_fpr64(ctx, fp1, ft);
7630 gen_load_fpr64(ctx, fp2, fr);
7631 gen_helper_float_nmuladd_ps(fp2, fp0, fp1, fp2);
7632 tcg_temp_free_i64(fp0);
7633 tcg_temp_free_i64(fp1);
7634 gen_store_fpr64(ctx, fp2, fd);
7635 tcg_temp_free_i64(fp2);
7637 opn = "nmadd.ps";
7638 break;
7639 case OPC_NMSUB_S:
7640 check_cop1x(ctx);
7642 TCGv_i32 fp0 = tcg_temp_new_i32();
7643 TCGv_i32 fp1 = tcg_temp_new_i32();
7644 TCGv_i32 fp2 = tcg_temp_new_i32();
7646 gen_load_fpr32(fp0, fs);
7647 gen_load_fpr32(fp1, ft);
7648 gen_load_fpr32(fp2, fr);
7649 gen_helper_float_nmulsub_s(fp2, fp0, fp1, fp2);
7650 tcg_temp_free_i32(fp0);
7651 tcg_temp_free_i32(fp1);
7652 gen_store_fpr32(fp2, fd);
7653 tcg_temp_free_i32(fp2);
7655 opn = "nmsub.s";
7656 break;
7657 case OPC_NMSUB_D:
7658 check_cop1x(ctx);
7659 check_cp1_registers(ctx, fd | fs | ft | fr);
7661 TCGv_i64 fp0 = tcg_temp_new_i64();
7662 TCGv_i64 fp1 = tcg_temp_new_i64();
7663 TCGv_i64 fp2 = tcg_temp_new_i64();
7665 gen_load_fpr64(ctx, fp0, fs);
7666 gen_load_fpr64(ctx, fp1, ft);
7667 gen_load_fpr64(ctx, fp2, fr);
7668 gen_helper_float_nmulsub_d(fp2, fp0, fp1, fp2);
7669 tcg_temp_free_i64(fp0);
7670 tcg_temp_free_i64(fp1);
7671 gen_store_fpr64(ctx, fp2, fd);
7672 tcg_temp_free_i64(fp2);
7674 opn = "nmsub.d";
7675 break;
7676 case OPC_NMSUB_PS:
7677 check_cp1_64bitmode(ctx);
7679 TCGv_i64 fp0 = tcg_temp_new_i64();
7680 TCGv_i64 fp1 = tcg_temp_new_i64();
7681 TCGv_i64 fp2 = tcg_temp_new_i64();
7683 gen_load_fpr64(ctx, fp0, fs);
7684 gen_load_fpr64(ctx, fp1, ft);
7685 gen_load_fpr64(ctx, fp2, fr);
7686 gen_helper_float_nmulsub_ps(fp2, fp0, fp1, fp2);
7687 tcg_temp_free_i64(fp0);
7688 tcg_temp_free_i64(fp1);
7689 gen_store_fpr64(ctx, fp2, fd);
7690 tcg_temp_free_i64(fp2);
7692 opn = "nmsub.ps";
7693 break;
7694 default:
7695 MIPS_INVAL(opn);
7696 generate_exception (ctx, EXCP_RI);
7697 return;
7699 MIPS_DEBUG("%s %s, %s, %s, %s", opn, fregnames[fd], fregnames[fr],
7700 fregnames[fs], fregnames[ft]);
7703 static void
7704 gen_rdhwr (CPUState *env, DisasContext *ctx, int rt, int rd)
7706 TCGv t0;
7708 check_insn(env, ctx, ISA_MIPS32R2);
7709 t0 = tcg_temp_new();
7711 switch (rd) {
7712 case 0:
7713 save_cpu_state(ctx, 1);
7714 gen_helper_rdhwr_cpunum(t0);
7715 gen_store_gpr(t0, rt);
7716 break;
7717 case 1:
7718 save_cpu_state(ctx, 1);
7719 gen_helper_rdhwr_synci_step(t0);
7720 gen_store_gpr(t0, rt);
7721 break;
7722 case 2:
7723 save_cpu_state(ctx, 1);
7724 gen_helper_rdhwr_cc(t0);
7725 gen_store_gpr(t0, rt);
7726 break;
7727 case 3:
7728 save_cpu_state(ctx, 1);
7729 gen_helper_rdhwr_ccres(t0);
7730 gen_store_gpr(t0, rt);
7731 break;
7732 case 29:
7733 #if defined(CONFIG_USER_ONLY)
7734 tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUState, tls_value));
7735 gen_store_gpr(t0, rt);
7736 break;
7737 #else
7738 /* XXX: Some CPUs implement this in hardware.
7739 Not supported yet. */
7740 #endif
7741 default: /* Invalid */
7742 MIPS_INVAL("rdhwr");
7743 generate_exception(ctx, EXCP_RI);
7744 break;
7746 tcg_temp_free(t0);
7749 static void handle_delay_slot (CPUState *env, DisasContext *ctx,
7750 int insn_bytes)
7752 if (ctx->hflags & MIPS_HFLAG_BMASK) {
7753 int proc_hflags = ctx->hflags & MIPS_HFLAG_BMASK;
7754 /* Branches completion */
7755 ctx->hflags &= ~MIPS_HFLAG_BMASK;
7756 ctx->bstate = BS_BRANCH;
7757 save_cpu_state(ctx, 0);
7758 /* FIXME: Need to clear can_do_io. */
7759 switch (proc_hflags & MIPS_HFLAG_BMASK_BASE) {
7760 case MIPS_HFLAG_B:
7761 /* unconditional branch */
7762 MIPS_DEBUG("unconditional branch");
7763 if (proc_hflags & MIPS_HFLAG_BX) {
7764 tcg_gen_xori_i32(hflags, hflags, MIPS_HFLAG_M16);
7766 gen_goto_tb(ctx, 0, ctx->btarget);
7767 break;
7768 case MIPS_HFLAG_BL:
7769 /* blikely taken case */
7770 MIPS_DEBUG("blikely branch taken");
7771 gen_goto_tb(ctx, 0, ctx->btarget);
7772 break;
7773 case MIPS_HFLAG_BC:
7774 /* Conditional branch */
7775 MIPS_DEBUG("conditional branch");
7777 int l1 = gen_new_label();
7779 tcg_gen_brcondi_tl(TCG_COND_NE, bcond, 0, l1);
7780 gen_goto_tb(ctx, 1, ctx->pc + insn_bytes);
7781 gen_set_label(l1);
7782 gen_goto_tb(ctx, 0, ctx->btarget);
7784 break;
7785 case MIPS_HFLAG_BR:
7786 /* unconditional branch to register */
7787 MIPS_DEBUG("branch to register");
7788 if (env->insn_flags & ASE_MIPS16) {
7789 TCGv t0 = tcg_temp_new();
7790 TCGv_i32 t1 = tcg_temp_new_i32();
7792 tcg_gen_andi_tl(t0, btarget, 0x1);
7793 tcg_gen_trunc_tl_i32(t1, t0);
7794 tcg_temp_free(t0);
7795 tcg_gen_andi_i32(hflags, hflags, ~(uint32_t)MIPS_HFLAG_M16);
7796 tcg_gen_shli_i32(t1, t1, MIPS_HFLAG_M16_SHIFT);
7797 tcg_gen_or_i32(hflags, hflags, t1);
7798 tcg_temp_free_i32(t1);
7800 tcg_gen_andi_tl(cpu_PC, btarget, ~(target_ulong)0x1);
7801 } else {
7802 tcg_gen_mov_tl(cpu_PC, btarget);
7804 if (ctx->singlestep_enabled) {
7805 save_cpu_state(ctx, 0);
7806 gen_helper_0i(raise_exception, EXCP_DEBUG);
7808 tcg_gen_exit_tb(0);
7809 break;
7810 default:
7811 MIPS_DEBUG("unknown branch");
7812 break;
7817 /* ISA extensions (ASEs) */
7818 /* MIPS16 extension to MIPS32 */
7820 /* MIPS16 major opcodes */
7821 enum {
7822 M16_OPC_ADDIUSP = 0x00,
7823 M16_OPC_ADDIUPC = 0x01,
7824 M16_OPC_B = 0x02,
7825 M16_OPC_JAL = 0x03,
7826 M16_OPC_BEQZ = 0x04,
7827 M16_OPC_BNEQZ = 0x05,
7828 M16_OPC_SHIFT = 0x06,
7829 M16_OPC_LD = 0x07,
7830 M16_OPC_RRIA = 0x08,
7831 M16_OPC_ADDIU8 = 0x09,
7832 M16_OPC_SLTI = 0x0a,
7833 M16_OPC_SLTIU = 0x0b,
7834 M16_OPC_I8 = 0x0c,
7835 M16_OPC_LI = 0x0d,
7836 M16_OPC_CMPI = 0x0e,
7837 M16_OPC_SD = 0x0f,
7838 M16_OPC_LB = 0x10,
7839 M16_OPC_LH = 0x11,
7840 M16_OPC_LWSP = 0x12,
7841 M16_OPC_LW = 0x13,
7842 M16_OPC_LBU = 0x14,
7843 M16_OPC_LHU = 0x15,
7844 M16_OPC_LWPC = 0x16,
7845 M16_OPC_LWU = 0x17,
7846 M16_OPC_SB = 0x18,
7847 M16_OPC_SH = 0x19,
7848 M16_OPC_SWSP = 0x1a,
7849 M16_OPC_SW = 0x1b,
7850 M16_OPC_RRR = 0x1c,
7851 M16_OPC_RR = 0x1d,
7852 M16_OPC_EXTEND = 0x1e,
7853 M16_OPC_I64 = 0x1f
7856 /* I8 funct field */
7857 enum {
7858 I8_BTEQZ = 0x0,
7859 I8_BTNEZ = 0x1,
7860 I8_SWRASP = 0x2,
7861 I8_ADJSP = 0x3,
7862 I8_SVRS = 0x4,
7863 I8_MOV32R = 0x5,
7864 I8_MOVR32 = 0x7
7867 /* RRR f field */
7868 enum {
7869 RRR_DADDU = 0x0,
7870 RRR_ADDU = 0x1,
7871 RRR_DSUBU = 0x2,
7872 RRR_SUBU = 0x3
7875 /* RR funct field */
7876 enum {
7877 RR_JR = 0x00,
7878 RR_SDBBP = 0x01,
7879 RR_SLT = 0x02,
7880 RR_SLTU = 0x03,
7881 RR_SLLV = 0x04,
7882 RR_BREAK = 0x05,
7883 RR_SRLV = 0x06,
7884 RR_SRAV = 0x07,
7885 RR_DSRL = 0x08,
7886 RR_CMP = 0x0a,
7887 RR_NEG = 0x0b,
7888 RR_AND = 0x0c,
7889 RR_OR = 0x0d,
7890 RR_XOR = 0x0e,
7891 RR_NOT = 0x0f,
7892 RR_MFHI = 0x10,
7893 RR_CNVT = 0x11,
7894 RR_MFLO = 0x12,
7895 RR_DSRA = 0x13,
7896 RR_DSLLV = 0x14,
7897 RR_DSRLV = 0x16,
7898 RR_DSRAV = 0x17,
7899 RR_MULT = 0x18,
7900 RR_MULTU = 0x19,
7901 RR_DIV = 0x1a,
7902 RR_DIVU = 0x1b,
7903 RR_DMULT = 0x1c,
7904 RR_DMULTU = 0x1d,
7905 RR_DDIV = 0x1e,
7906 RR_DDIVU = 0x1f
7909 /* I64 funct field */
7910 enum {
7911 I64_LDSP = 0x0,
7912 I64_SDSP = 0x1,
7913 I64_SDRASP = 0x2,
7914 I64_DADJSP = 0x3,
7915 I64_LDPC = 0x4,
7916 I64_DADDIU5 = 0x5,
7917 I64_DADDIUPC = 0x6,
7918 I64_DADDIUSP = 0x7
7921 /* RR ry field for CNVT */
7922 enum {
7923 RR_RY_CNVT_ZEB = 0x0,
7924 RR_RY_CNVT_ZEH = 0x1,
7925 RR_RY_CNVT_ZEW = 0x2,
7926 RR_RY_CNVT_SEB = 0x4,
7927 RR_RY_CNVT_SEH = 0x5,
7928 RR_RY_CNVT_SEW = 0x6,
7931 static int xlat (int r)
7933 static int map[] = { 16, 17, 2, 3, 4, 5, 6, 7 };
7935 return map[r];
7938 static void gen_mips16_save (DisasContext *ctx,
7939 int xsregs, int aregs,
7940 int do_ra, int do_s0, int do_s1,
7941 int framesize)
7943 TCGv t0 = tcg_temp_new();
7944 TCGv t1 = tcg_temp_new();
7945 int args, astatic;
7947 switch (aregs) {
7948 case 0:
7949 case 1:
7950 case 2:
7951 case 3:
7952 case 11:
7953 args = 0;
7954 break;
7955 case 4:
7956 case 5:
7957 case 6:
7958 case 7:
7959 args = 1;
7960 break;
7961 case 8:
7962 case 9:
7963 case 10:
7964 args = 2;
7965 break;
7966 case 12:
7967 case 13:
7968 args = 3;
7969 break;
7970 case 14:
7971 args = 4;
7972 break;
7973 default:
7974 generate_exception(ctx, EXCP_RI);
7975 return;
7978 switch (args) {
7979 case 4:
7980 gen_base_offset_addr(ctx, t0, 29, 12);
7981 gen_load_gpr(t1, 7);
7982 op_ldst_sw(t1, t0, ctx);
7983 /* Fall through */
7984 case 3:
7985 gen_base_offset_addr(ctx, t0, 29, 8);
7986 gen_load_gpr(t1, 6);
7987 op_ldst_sw(t1, t0, ctx);
7988 /* Fall through */
7989 case 2:
7990 gen_base_offset_addr(ctx, t0, 29, 4);
7991 gen_load_gpr(t1, 5);
7992 op_ldst_sw(t1, t0, ctx);
7993 /* Fall through */
7994 case 1:
7995 gen_base_offset_addr(ctx, t0, 29, 0);
7996 gen_load_gpr(t1, 4);
7997 op_ldst_sw(t1, t0, ctx);
8000 gen_load_gpr(t0, 29);
8002 #define DECR_AND_STORE(reg) do { \
8003 tcg_gen_subi_tl(t0, t0, 4); \
8004 gen_load_gpr(t1, reg); \
8005 op_ldst_sw(t1, t0, ctx); \
8006 } while (0)
8008 if (do_ra) {
8009 DECR_AND_STORE(31);
8012 switch (xsregs) {
8013 case 7:
8014 DECR_AND_STORE(30);
8015 /* Fall through */
8016 case 6:
8017 DECR_AND_STORE(23);
8018 /* Fall through */
8019 case 5:
8020 DECR_AND_STORE(22);
8021 /* Fall through */
8022 case 4:
8023 DECR_AND_STORE(21);
8024 /* Fall through */
8025 case 3:
8026 DECR_AND_STORE(20);
8027 /* Fall through */
8028 case 2:
8029 DECR_AND_STORE(19);
8030 /* Fall through */
8031 case 1:
8032 DECR_AND_STORE(18);
8035 if (do_s1) {
8036 DECR_AND_STORE(17);
8038 if (do_s0) {
8039 DECR_AND_STORE(16);
8042 switch (aregs) {
8043 case 0:
8044 case 4:
8045 case 8:
8046 case 12:
8047 case 14:
8048 astatic = 0;
8049 break;
8050 case 1:
8051 case 5:
8052 case 9:
8053 case 13:
8054 astatic = 1;
8055 break;
8056 case 2:
8057 case 6:
8058 case 10:
8059 astatic = 2;
8060 break;
8061 case 3:
8062 case 7:
8063 astatic = 3;
8064 break;
8065 case 11:
8066 astatic = 4;
8067 break;
8068 default:
8069 generate_exception(ctx, EXCP_RI);
8070 return;
8073 if (astatic > 0) {
8074 DECR_AND_STORE(7);
8075 if (astatic > 1) {
8076 DECR_AND_STORE(6);
8077 if (astatic > 2) {
8078 DECR_AND_STORE(5);
8079 if (astatic > 3) {
8080 DECR_AND_STORE(4);
8085 #undef DECR_AND_STORE
8087 tcg_gen_subi_tl(cpu_gpr[29], cpu_gpr[29], framesize);
8088 tcg_temp_free(t0);
8089 tcg_temp_free(t1);
8092 static void gen_mips16_restore (DisasContext *ctx,
8093 int xsregs, int aregs,
8094 int do_ra, int do_s0, int do_s1,
8095 int framesize)
8097 int astatic;
8098 TCGv t0 = tcg_temp_new();
8099 TCGv t1 = tcg_temp_new();
8101 tcg_gen_addi_tl(t0, cpu_gpr[29], framesize);
8103 #define DECR_AND_LOAD(reg) do { \
8104 tcg_gen_subi_tl(t0, t0, 4); \
8105 op_ldst_lw(t1, t0, ctx); \
8106 gen_store_gpr(t1, reg); \
8107 } while (0)
8109 if (do_ra) {
8110 DECR_AND_LOAD(31);
8113 switch (xsregs) {
8114 case 7:
8115 DECR_AND_LOAD(30);
8116 /* Fall through */
8117 case 6:
8118 DECR_AND_LOAD(23);
8119 /* Fall through */
8120 case 5:
8121 DECR_AND_LOAD(22);
8122 /* Fall through */
8123 case 4:
8124 DECR_AND_LOAD(21);
8125 /* Fall through */
8126 case 3:
8127 DECR_AND_LOAD(20);
8128 /* Fall through */
8129 case 2:
8130 DECR_AND_LOAD(19);
8131 /* Fall through */
8132 case 1:
8133 DECR_AND_LOAD(18);
8136 if (do_s1) {
8137 DECR_AND_LOAD(17);
8139 if (do_s0) {
8140 DECR_AND_LOAD(16);
8143 switch (aregs) {
8144 case 0:
8145 case 4:
8146 case 8:
8147 case 12:
8148 case 14:
8149 astatic = 0;
8150 break;
8151 case 1:
8152 case 5:
8153 case 9:
8154 case 13:
8155 astatic = 1;
8156 break;
8157 case 2:
8158 case 6:
8159 case 10:
8160 astatic = 2;
8161 break;
8162 case 3:
8163 case 7:
8164 astatic = 3;
8165 break;
8166 case 11:
8167 astatic = 4;
8168 break;
8169 default:
8170 generate_exception(ctx, EXCP_RI);
8171 return;
8174 if (astatic > 0) {
8175 DECR_AND_LOAD(7);
8176 if (astatic > 1) {
8177 DECR_AND_LOAD(6);
8178 if (astatic > 2) {
8179 DECR_AND_LOAD(5);
8180 if (astatic > 3) {
8181 DECR_AND_LOAD(4);
8186 #undef DECR_AND_LOAD
8188 tcg_gen_addi_tl(cpu_gpr[29], cpu_gpr[29], framesize);
8189 tcg_temp_free(t0);
8190 tcg_temp_free(t1);
8193 static void gen_addiupc (DisasContext *ctx, int rx, int imm,
8194 int is_64_bit, int extended)
8196 TCGv t0;
8198 if (extended && (ctx->hflags & MIPS_HFLAG_BMASK)) {
8199 generate_exception(ctx, EXCP_RI);
8200 return;
8203 t0 = tcg_temp_new();
8205 tcg_gen_movi_tl(t0, pc_relative_pc(ctx));
8206 tcg_gen_addi_tl(cpu_gpr[rx], t0, imm);
8207 if (!is_64_bit) {
8208 tcg_gen_ext32s_tl(cpu_gpr[rx], cpu_gpr[rx]);
8211 tcg_temp_free(t0);
8214 #if defined(TARGET_MIPS64)
8215 static void decode_i64_mips16 (CPUState *env, DisasContext *ctx,
8216 int ry, int funct, int16_t offset,
8217 int extended)
8219 switch (funct) {
8220 case I64_LDSP:
8221 check_mips_64(ctx);
8222 offset = extended ? offset : offset << 3;
8223 gen_ldst(ctx, OPC_LD, ry, 29, offset);
8224 break;
8225 case I64_SDSP:
8226 check_mips_64(ctx);
8227 offset = extended ? offset : offset << 3;
8228 gen_ldst(ctx, OPC_SD, ry, 29, offset);
8229 break;
8230 case I64_SDRASP:
8231 check_mips_64(ctx);
8232 offset = extended ? offset : (ctx->opcode & 0xff) << 3;
8233 gen_ldst(ctx, OPC_SD, 31, 29, offset);
8234 break;
8235 case I64_DADJSP:
8236 check_mips_64(ctx);
8237 offset = extended ? offset : ((int8_t)ctx->opcode) << 3;
8238 gen_arith_imm(env, ctx, OPC_DADDIU, 29, 29, offset);
8239 break;
8240 case I64_LDPC:
8241 if (extended && (ctx->hflags & MIPS_HFLAG_BMASK)) {
8242 generate_exception(ctx, EXCP_RI);
8243 } else {
8244 offset = extended ? offset : offset << 3;
8245 gen_ldst(ctx, OPC_LDPC, ry, 0, offset);
8247 break;
8248 case I64_DADDIU5:
8249 check_mips_64(ctx);
8250 offset = extended ? offset : ((int8_t)(offset << 3)) >> 3;
8251 gen_arith_imm(env, ctx, OPC_DADDIU, ry, ry, offset);
8252 break;
8253 case I64_DADDIUPC:
8254 check_mips_64(ctx);
8255 offset = extended ? offset : offset << 2;
8256 gen_addiupc(ctx, ry, offset, 1, extended);
8257 break;
8258 case I64_DADDIUSP:
8259 check_mips_64(ctx);
8260 offset = extended ? offset : offset << 2;
8261 gen_arith_imm(env, ctx, OPC_DADDIU, ry, 29, offset);
8262 break;
8265 #endif
8267 static int decode_extended_mips16_opc (CPUState *env, DisasContext *ctx,
8268 int *is_branch)
8270 int extend = lduw_code(ctx->pc + 2);
8271 int op, rx, ry, funct, sa;
8272 int16_t imm, offset;
8274 ctx->opcode = (ctx->opcode << 16) | extend;
8275 op = (ctx->opcode >> 11) & 0x1f;
8276 sa = (ctx->opcode >> 22) & 0x1f;
8277 funct = (ctx->opcode >> 8) & 0x7;
8278 rx = xlat((ctx->opcode >> 8) & 0x7);
8279 ry = xlat((ctx->opcode >> 5) & 0x7);
8280 offset = imm = (int16_t) (((ctx->opcode >> 16) & 0x1f) << 11
8281 | ((ctx->opcode >> 21) & 0x3f) << 5
8282 | (ctx->opcode & 0x1f));
8284 /* The extended opcodes cleverly reuse the opcodes from their 16-bit
8285 counterparts. */
8286 switch (op) {
8287 case M16_OPC_ADDIUSP:
8288 gen_arith_imm(env, ctx, OPC_ADDIU, rx, 29, imm);
8289 break;
8290 case M16_OPC_ADDIUPC:
8291 gen_addiupc(ctx, rx, imm, 0, 1);
8292 break;
8293 case M16_OPC_B:
8294 gen_compute_branch(ctx, OPC_BEQ, 4, 0, 0, offset << 1);
8295 /* No delay slot, so just process as a normal instruction */
8296 break;
8297 case M16_OPC_BEQZ:
8298 gen_compute_branch(ctx, OPC_BEQ, 4, rx, 0, offset << 1);
8299 /* No delay slot, so just process as a normal instruction */
8300 break;
8301 case M16_OPC_BNEQZ:
8302 gen_compute_branch(ctx, OPC_BNE, 4, rx, 0, offset << 1);
8303 /* No delay slot, so just process as a normal instruction */
8304 break;
8305 case M16_OPC_SHIFT:
8306 switch (ctx->opcode & 0x3) {
8307 case 0x0:
8308 gen_shift_imm(env, ctx, OPC_SLL, rx, ry, sa);
8309 break;
8310 case 0x1:
8311 #if defined(TARGET_MIPS64)
8312 check_mips_64(ctx);
8313 gen_shift_imm(env, ctx, OPC_DSLL, rx, ry, sa);
8314 #else
8315 generate_exception(ctx, EXCP_RI);
8316 #endif
8317 break;
8318 case 0x2:
8319 gen_shift_imm(env, ctx, OPC_SRL, rx, ry, sa);
8320 break;
8321 case 0x3:
8322 gen_shift_imm(env, ctx, OPC_SRA, rx, ry, sa);
8323 break;
8325 break;
8326 #if defined(TARGET_MIPS64)
8327 case M16_OPC_LD:
8328 check_mips_64(ctx);
8329 gen_ldst(ctx, OPC_LD, ry, rx, offset);
8330 break;
8331 #endif
8332 case M16_OPC_RRIA:
8333 imm = ctx->opcode & 0xf;
8334 imm = imm | ((ctx->opcode >> 20) & 0x7f) << 4;
8335 imm = imm | ((ctx->opcode >> 16) & 0xf) << 11;
8336 imm = (int16_t) (imm << 1) >> 1;
8337 if ((ctx->opcode >> 4) & 0x1) {
8338 #if defined(TARGET_MIPS64)
8339 check_mips_64(ctx);
8340 gen_arith_imm(env, ctx, OPC_DADDIU, ry, rx, imm);
8341 #else
8342 generate_exception(ctx, EXCP_RI);
8343 #endif
8344 } else {
8345 gen_arith_imm(env, ctx, OPC_ADDIU, ry, rx, imm);
8347 break;
8348 case M16_OPC_ADDIU8:
8349 gen_arith_imm(env, ctx, OPC_ADDIU, rx, rx, imm);
8350 break;
8351 case M16_OPC_SLTI:
8352 gen_slt_imm(env, OPC_SLTI, 24, rx, imm);
8353 break;
8354 case M16_OPC_SLTIU:
8355 gen_slt_imm(env, OPC_SLTIU, 24, rx, imm);
8356 break;
8357 case M16_OPC_I8:
8358 switch (funct) {
8359 case I8_BTEQZ:
8360 gen_compute_branch(ctx, OPC_BEQ, 4, 24, 0, offset << 1);
8361 break;
8362 case I8_BTNEZ:
8363 gen_compute_branch(ctx, OPC_BNE, 4, 24, 0, offset << 1);
8364 break;
8365 case I8_SWRASP:
8366 gen_ldst(ctx, OPC_SW, 31, 29, imm);
8367 break;
8368 case I8_ADJSP:
8369 gen_arith_imm(env, ctx, OPC_ADDIU, 29, 29, imm);
8370 break;
8371 case I8_SVRS:
8373 int xsregs = (ctx->opcode >> 24) & 0x7;
8374 int aregs = (ctx->opcode >> 16) & 0xf;
8375 int do_ra = (ctx->opcode >> 6) & 0x1;
8376 int do_s0 = (ctx->opcode >> 5) & 0x1;
8377 int do_s1 = (ctx->opcode >> 4) & 0x1;
8378 int framesize = (((ctx->opcode >> 20) & 0xf) << 4
8379 | (ctx->opcode & 0xf)) << 3;
8381 if (ctx->opcode & (1 << 7)) {
8382 gen_mips16_save(ctx, xsregs, aregs,
8383 do_ra, do_s0, do_s1,
8384 framesize);
8385 } else {
8386 gen_mips16_restore(ctx, xsregs, aregs,
8387 do_ra, do_s0, do_s1,
8388 framesize);
8391 break;
8392 default:
8393 generate_exception(ctx, EXCP_RI);
8394 break;
8396 break;
8397 case M16_OPC_LI:
8398 tcg_gen_movi_tl(cpu_gpr[rx], (uint16_t) imm);
8399 break;
8400 case M16_OPC_CMPI:
8401 tcg_gen_xori_tl(cpu_gpr[24], cpu_gpr[rx], (uint16_t) imm);
8402 break;
8403 #if defined(TARGET_MIPS64)
8404 case M16_OPC_SD:
8405 gen_ldst(ctx, OPC_SD, ry, rx, offset);
8406 break;
8407 #endif
8408 case M16_OPC_LB:
8409 gen_ldst(ctx, OPC_LB, ry, rx, offset);
8410 break;
8411 case M16_OPC_LH:
8412 gen_ldst(ctx, OPC_LH, ry, rx, offset);
8413 break;
8414 case M16_OPC_LWSP:
8415 gen_ldst(ctx, OPC_LW, rx, 29, offset);
8416 break;
8417 case M16_OPC_LW:
8418 gen_ldst(ctx, OPC_LW, ry, rx, offset);
8419 break;
8420 case M16_OPC_LBU:
8421 gen_ldst(ctx, OPC_LBU, ry, rx, offset);
8422 break;
8423 case M16_OPC_LHU:
8424 gen_ldst(ctx, OPC_LHU, ry, rx, offset);
8425 break;
8426 case M16_OPC_LWPC:
8427 gen_ldst(ctx, OPC_LWPC, rx, 0, offset);
8428 break;
8429 #if defined(TARGET_MIPS64)
8430 case M16_OPC_LWU:
8431 gen_ldst(ctx, OPC_LWU, ry, rx, offset);
8432 break;
8433 #endif
8434 case M16_OPC_SB:
8435 gen_ldst(ctx, OPC_SB, ry, rx, offset);
8436 break;
8437 case M16_OPC_SH:
8438 gen_ldst(ctx, OPC_SH, ry, rx, offset);
8439 break;
8440 case M16_OPC_SWSP:
8441 gen_ldst(ctx, OPC_SW, rx, 29, offset);
8442 break;
8443 case M16_OPC_SW:
8444 gen_ldst(ctx, OPC_SW, ry, rx, offset);
8445 break;
8446 #if defined(TARGET_MIPS64)
8447 case M16_OPC_I64:
8448 decode_i64_mips16(env, ctx, ry, funct, offset, 1);
8449 break;
8450 #endif
8451 default:
8452 generate_exception(ctx, EXCP_RI);
8453 break;
8456 return 4;
8459 static int decode_mips16_opc (CPUState *env, DisasContext *ctx,
8460 int *is_branch)
8462 int rx, ry;
8463 int sa;
8464 int op, cnvt_op, op1, offset;
8465 int funct;
8466 int n_bytes;
8468 op = (ctx->opcode >> 11) & 0x1f;
8469 sa = (ctx->opcode >> 2) & 0x7;
8470 sa = sa == 0 ? 8 : sa;
8471 rx = xlat((ctx->opcode >> 8) & 0x7);
8472 cnvt_op = (ctx->opcode >> 5) & 0x7;
8473 ry = xlat((ctx->opcode >> 5) & 0x7);
8474 op1 = offset = ctx->opcode & 0x1f;
8476 n_bytes = 2;
8478 switch (op) {
8479 case M16_OPC_ADDIUSP:
8481 int16_t imm = ((uint8_t) ctx->opcode) << 2;
8483 gen_arith_imm(env, ctx, OPC_ADDIU, rx, 29, imm);
8485 break;
8486 case M16_OPC_ADDIUPC:
8487 gen_addiupc(ctx, rx, ((uint8_t) ctx->opcode) << 2, 0, 0);
8488 break;
8489 case M16_OPC_B:
8490 offset = (ctx->opcode & 0x7ff) << 1;
8491 offset = (int16_t)(offset << 4) >> 4;
8492 gen_compute_branch(ctx, OPC_BEQ, 2, 0, 0, offset);
8493 /* No delay slot, so just process as a normal instruction */
8494 break;
8495 case M16_OPC_JAL:
8496 offset = lduw_code(ctx->pc + 2);
8497 offset = (((ctx->opcode & 0x1f) << 21)
8498 | ((ctx->opcode >> 5) & 0x1f) << 16
8499 | offset) << 2;
8500 op = ((ctx->opcode >> 10) & 0x1) ? OPC_JALXS : OPC_JALS;
8501 gen_compute_branch(ctx, op, 4, rx, ry, offset);
8502 n_bytes = 4;
8503 *is_branch = 1;
8504 break;
8505 case M16_OPC_BEQZ:
8506 gen_compute_branch(ctx, OPC_BEQ, 2, rx, 0, ((int8_t)ctx->opcode) << 1);
8507 /* No delay slot, so just process as a normal instruction */
8508 break;
8509 case M16_OPC_BNEQZ:
8510 gen_compute_branch(ctx, OPC_BNE, 2, rx, 0, ((int8_t)ctx->opcode) << 1);
8511 /* No delay slot, so just process as a normal instruction */
8512 break;
8513 case M16_OPC_SHIFT:
8514 switch (ctx->opcode & 0x3) {
8515 case 0x0:
8516 gen_shift_imm(env, ctx, OPC_SLL, rx, ry, sa);
8517 break;
8518 case 0x1:
8519 #if defined(TARGET_MIPS64)
8520 check_mips_64(ctx);
8521 gen_shift_imm(env, ctx, OPC_DSLL, rx, ry, sa);
8522 #else
8523 generate_exception(ctx, EXCP_RI);
8524 #endif
8525 break;
8526 case 0x2:
8527 gen_shift_imm(env, ctx, OPC_SRL, rx, ry, sa);
8528 break;
8529 case 0x3:
8530 gen_shift_imm(env, ctx, OPC_SRA, rx, ry, sa);
8531 break;
8533 break;
8534 #if defined(TARGET_MIPS64)
8535 case M16_OPC_LD:
8536 check_mips_64(ctx);
8537 gen_ldst(ctx, OPC_LD, ry, rx, offset << 3);
8538 break;
8539 #endif
8540 case M16_OPC_RRIA:
8542 int16_t imm = (int8_t)((ctx->opcode & 0xf) << 4) >> 4;
8544 if ((ctx->opcode >> 4) & 1) {
8545 #if defined(TARGET_MIPS64)
8546 check_mips_64(ctx);
8547 gen_arith_imm(env, ctx, OPC_DADDIU, ry, rx, imm);
8548 #else
8549 generate_exception(ctx, EXCP_RI);
8550 #endif
8551 } else {
8552 gen_arith_imm(env, ctx, OPC_ADDIU, ry, rx, imm);
8555 break;
8556 case M16_OPC_ADDIU8:
8558 int16_t imm = (int8_t) ctx->opcode;
8560 gen_arith_imm(env, ctx, OPC_ADDIU, rx, rx, imm);
8562 break;
8563 case M16_OPC_SLTI:
8565 int16_t imm = (uint8_t) ctx->opcode;
8567 gen_slt_imm(env, OPC_SLTI, 24, rx, imm);
8569 break;
8570 case M16_OPC_SLTIU:
8572 int16_t imm = (uint8_t) ctx->opcode;
8574 gen_slt_imm(env, OPC_SLTIU, 24, rx, imm);
8576 break;
8577 case M16_OPC_I8:
8579 int reg32;
8581 funct = (ctx->opcode >> 8) & 0x7;
8582 switch (funct) {
8583 case I8_BTEQZ:
8584 gen_compute_branch(ctx, OPC_BEQ, 2, 24, 0,
8585 ((int8_t)ctx->opcode) << 1);
8586 break;
8587 case I8_BTNEZ:
8588 gen_compute_branch(ctx, OPC_BNE, 2, 24, 0,
8589 ((int8_t)ctx->opcode) << 1);
8590 break;
8591 case I8_SWRASP:
8592 gen_ldst(ctx, OPC_SW, 31, 29, (ctx->opcode & 0xff) << 2);
8593 break;
8594 case I8_ADJSP:
8595 gen_arith_imm(env, ctx, OPC_ADDIU, 29, 29,
8596 ((int8_t)ctx->opcode) << 3);
8597 break;
8598 case I8_SVRS:
8600 int do_ra = ctx->opcode & (1 << 6);
8601 int do_s0 = ctx->opcode & (1 << 5);
8602 int do_s1 = ctx->opcode & (1 << 4);
8603 int framesize = ctx->opcode & 0xf;
8605 if (framesize == 0) {
8606 framesize = 128;
8607 } else {
8608 framesize = framesize << 3;
8611 if (ctx->opcode & (1 << 7)) {
8612 gen_mips16_save(ctx, 0, 0,
8613 do_ra, do_s0, do_s1, framesize);
8614 } else {
8615 gen_mips16_restore(ctx, 0, 0,
8616 do_ra, do_s0, do_s1, framesize);
8619 break;
8620 case I8_MOV32R:
8622 int rz = xlat(ctx->opcode & 0x7);
8624 reg32 = (((ctx->opcode >> 3) & 0x3) << 3) |
8625 ((ctx->opcode >> 5) & 0x7);
8626 gen_arith(env, ctx, OPC_ADDU, reg32, rz, 0);
8628 break;
8629 case I8_MOVR32:
8630 reg32 = ctx->opcode & 0x1f;
8631 gen_arith(env, ctx, OPC_ADDU, ry, reg32, 0);
8632 break;
8633 default:
8634 generate_exception(ctx, EXCP_RI);
8635 break;
8638 break;
8639 case M16_OPC_LI:
8641 int16_t imm = (uint8_t) ctx->opcode;
8643 gen_arith_imm(env, ctx, OPC_ADDIU, rx, 0, imm);
8645 break;
8646 case M16_OPC_CMPI:
8648 int16_t imm = (uint8_t) ctx->opcode;
8650 gen_logic_imm(env, OPC_XORI, 24, rx, imm);
8652 break;
8653 #if defined(TARGET_MIPS64)
8654 case M16_OPC_SD:
8655 check_mips_64(ctx);
8656 gen_ldst(ctx, OPC_SD, ry, rx, offset << 3);
8657 break;
8658 #endif
8659 case M16_OPC_LB:
8660 gen_ldst(ctx, OPC_LB, ry, rx, offset);
8661 break;
8662 case M16_OPC_LH:
8663 gen_ldst(ctx, OPC_LH, ry, rx, offset << 1);
8664 break;
8665 case M16_OPC_LWSP:
8666 gen_ldst(ctx, OPC_LW, rx, 29, ((uint8_t)ctx->opcode) << 2);
8667 break;
8668 case M16_OPC_LW:
8669 gen_ldst(ctx, OPC_LW, ry, rx, offset << 2);
8670 break;
8671 case M16_OPC_LBU:
8672 gen_ldst(ctx, OPC_LBU, ry, rx, offset);
8673 break;
8674 case M16_OPC_LHU:
8675 gen_ldst(ctx, OPC_LHU, ry, rx, offset << 1);
8676 break;
8677 case M16_OPC_LWPC:
8678 gen_ldst(ctx, OPC_LWPC, rx, 0, ((uint8_t)ctx->opcode) << 2);
8679 break;
8680 #if defined (TARGET_MIPS64)
8681 case M16_OPC_LWU:
8682 check_mips_64(ctx);
8683 gen_ldst(ctx, OPC_LWU, ry, rx, offset << 2);
8684 break;
8685 #endif
8686 case M16_OPC_SB:
8687 gen_ldst(ctx, OPC_SB, ry, rx, offset);
8688 break;
8689 case M16_OPC_SH:
8690 gen_ldst(ctx, OPC_SH, ry, rx, offset << 1);
8691 break;
8692 case M16_OPC_SWSP:
8693 gen_ldst(ctx, OPC_SW, rx, 29, ((uint8_t)ctx->opcode) << 2);
8694 break;
8695 case M16_OPC_SW:
8696 gen_ldst(ctx, OPC_SW, ry, rx, offset << 2);
8697 break;
8698 case M16_OPC_RRR:
8700 int rz = xlat((ctx->opcode >> 2) & 0x7);
8701 int mips32_op;
8703 switch (ctx->opcode & 0x3) {
8704 case RRR_ADDU:
8705 mips32_op = OPC_ADDU;
8706 break;
8707 case RRR_SUBU:
8708 mips32_op = OPC_SUBU;
8709 break;
8710 #if defined(TARGET_MIPS64)
8711 case RRR_DADDU:
8712 mips32_op = OPC_DADDU;
8713 check_mips_64(ctx);
8714 break;
8715 case RRR_DSUBU:
8716 mips32_op = OPC_DSUBU;
8717 check_mips_64(ctx);
8718 break;
8719 #endif
8720 default:
8721 generate_exception(ctx, EXCP_RI);
8722 goto done;
8725 gen_arith(env, ctx, mips32_op, rz, rx, ry);
8726 done:
8729 break;
8730 case M16_OPC_RR:
8731 switch (op1) {
8732 case RR_JR:
8734 int nd = (ctx->opcode >> 7) & 0x1;
8735 int link = (ctx->opcode >> 6) & 0x1;
8736 int ra = (ctx->opcode >> 5) & 0x1;
8738 if (link) {
8739 op = nd ? OPC_JALRC : OPC_JALRS;
8740 } else {
8741 op = OPC_JR;
8744 gen_compute_branch(ctx, op, 2, ra ? 31 : rx, 31, 0);
8745 if (!nd) {
8746 *is_branch = 1;
8749 break;
8750 case RR_SDBBP:
8751 /* XXX: not clear which exception should be raised
8752 * when in debug mode...
8754 check_insn(env, ctx, ISA_MIPS32);
8755 if (!(ctx->hflags & MIPS_HFLAG_DM)) {
8756 generate_exception(ctx, EXCP_DBp);
8757 } else {
8758 generate_exception(ctx, EXCP_DBp);
8760 break;
8761 case RR_SLT:
8762 gen_slt(env, OPC_SLT, 24, rx, ry);
8763 break;
8764 case RR_SLTU:
8765 gen_slt(env, OPC_SLTU, 24, rx, ry);
8766 break;
8767 case RR_BREAK:
8768 generate_exception(ctx, EXCP_BREAK);
8769 break;
8770 case RR_SLLV:
8771 gen_shift(env, ctx, OPC_SLLV, ry, rx, ry);
8772 break;
8773 case RR_SRLV:
8774 gen_shift(env, ctx, OPC_SRLV, ry, rx, ry);
8775 break;
8776 case RR_SRAV:
8777 gen_shift(env, ctx, OPC_SRAV, ry, rx, ry);
8778 break;
8779 #if defined (TARGET_MIPS64)
8780 case RR_DSRL:
8781 check_mips_64(ctx);
8782 gen_shift_imm(env, ctx, OPC_DSRL, ry, ry, sa);
8783 break;
8784 #endif
8785 case RR_CMP:
8786 gen_logic(env, OPC_XOR, 24, rx, ry);
8787 break;
8788 case RR_NEG:
8789 gen_arith(env, ctx, OPC_SUBU, rx, 0, ry);
8790 break;
8791 case RR_AND:
8792 gen_logic(env, OPC_AND, rx, rx, ry);
8793 break;
8794 case RR_OR:
8795 gen_logic(env, OPC_OR, rx, rx, ry);
8796 break;
8797 case RR_XOR:
8798 gen_logic(env, OPC_XOR, rx, rx, ry);
8799 break;
8800 case RR_NOT:
8801 gen_logic(env, OPC_NOR, rx, ry, 0);
8802 break;
8803 case RR_MFHI:
8804 gen_HILO(ctx, OPC_MFHI, rx);
8805 break;
8806 case RR_CNVT:
8807 switch (cnvt_op) {
8808 case RR_RY_CNVT_ZEB:
8809 tcg_gen_ext8u_tl(cpu_gpr[rx], cpu_gpr[rx]);
8810 break;
8811 case RR_RY_CNVT_ZEH:
8812 tcg_gen_ext16u_tl(cpu_gpr[rx], cpu_gpr[rx]);
8813 break;
8814 case RR_RY_CNVT_SEB:
8815 tcg_gen_ext8s_tl(cpu_gpr[rx], cpu_gpr[rx]);
8816 break;
8817 case RR_RY_CNVT_SEH:
8818 tcg_gen_ext16s_tl(cpu_gpr[rx], cpu_gpr[rx]);
8819 break;
8820 #if defined (TARGET_MIPS64)
8821 case RR_RY_CNVT_ZEW:
8822 check_mips_64(ctx);
8823 tcg_gen_ext32u_tl(cpu_gpr[rx], cpu_gpr[rx]);
8824 break;
8825 case RR_RY_CNVT_SEW:
8826 check_mips_64(ctx);
8827 tcg_gen_ext32s_tl(cpu_gpr[rx], cpu_gpr[rx]);
8828 break;
8829 #endif
8830 default:
8831 generate_exception(ctx, EXCP_RI);
8832 break;
8834 break;
8835 case RR_MFLO:
8836 gen_HILO(ctx, OPC_MFLO, rx);
8837 break;
8838 #if defined (TARGET_MIPS64)
8839 case RR_DSRA:
8840 check_mips_64(ctx);
8841 gen_shift_imm(env, ctx, OPC_DSRA, ry, ry, sa);
8842 break;
8843 case RR_DSLLV:
8844 check_mips_64(ctx);
8845 gen_shift(env, ctx, OPC_DSLLV, ry, rx, ry);
8846 break;
8847 case RR_DSRLV:
8848 check_mips_64(ctx);
8849 gen_shift(env, ctx, OPC_DSRLV, ry, rx, ry);
8850 break;
8851 case RR_DSRAV:
8852 check_mips_64(ctx);
8853 gen_shift(env, ctx, OPC_DSRAV, ry, rx, ry);
8854 break;
8855 #endif
8856 case RR_MULT:
8857 gen_muldiv(ctx, OPC_MULT, rx, ry);
8858 break;
8859 case RR_MULTU:
8860 gen_muldiv(ctx, OPC_MULTU, rx, ry);
8861 break;
8862 case RR_DIV:
8863 gen_muldiv(ctx, OPC_DIV, rx, ry);
8864 break;
8865 case RR_DIVU:
8866 gen_muldiv(ctx, OPC_DIVU, rx, ry);
8867 break;
8868 #if defined (TARGET_MIPS64)
8869 case RR_DMULT:
8870 check_mips_64(ctx);
8871 gen_muldiv(ctx, OPC_DMULT, rx, ry);
8872 break;
8873 case RR_DMULTU:
8874 check_mips_64(ctx);
8875 gen_muldiv(ctx, OPC_DMULTU, rx, ry);
8876 break;
8877 case RR_DDIV:
8878 check_mips_64(ctx);
8879 gen_muldiv(ctx, OPC_DDIV, rx, ry);
8880 break;
8881 case RR_DDIVU:
8882 check_mips_64(ctx);
8883 gen_muldiv(ctx, OPC_DDIVU, rx, ry);
8884 break;
8885 #endif
8886 default:
8887 generate_exception(ctx, EXCP_RI);
8888 break;
8890 break;
8891 case M16_OPC_EXTEND:
8892 decode_extended_mips16_opc(env, ctx, is_branch);
8893 n_bytes = 4;
8894 break;
8895 #if defined(TARGET_MIPS64)
8896 case M16_OPC_I64:
8897 funct = (ctx->opcode >> 8) & 0x7;
8898 decode_i64_mips16(env, ctx, ry, funct, offset, 0);
8899 break;
8900 #endif
8901 default:
8902 generate_exception(ctx, EXCP_RI);
8903 break;
8906 return n_bytes;
8909 /* SmartMIPS extension to MIPS32 */
8911 #if defined(TARGET_MIPS64)
8913 /* MDMX extension to MIPS64 */
8915 #endif
8917 static void decode_opc (CPUState *env, DisasContext *ctx, int *is_branch)
8919 int32_t offset;
8920 int rs, rt, rd, sa;
8921 uint32_t op, op1, op2;
8922 int16_t imm;
8924 /* make sure instructions are on a word boundary */
8925 if (ctx->pc & 0x3) {
8926 env->CP0_BadVAddr = ctx->pc;
8927 generate_exception(ctx, EXCP_AdEL);
8928 return;
8931 /* Handle blikely not taken case */
8932 if ((ctx->hflags & MIPS_HFLAG_BMASK_BASE) == MIPS_HFLAG_BL) {
8933 int l1 = gen_new_label();
8935 MIPS_DEBUG("blikely condition (" TARGET_FMT_lx ")", ctx->pc + 4);
8936 tcg_gen_brcondi_tl(TCG_COND_NE, bcond, 0, l1);
8937 tcg_gen_movi_i32(hflags, ctx->hflags & ~MIPS_HFLAG_BMASK);
8938 gen_goto_tb(ctx, 1, ctx->pc + 4);
8939 gen_set_label(l1);
8942 if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP)))
8943 tcg_gen_debug_insn_start(ctx->pc);
8945 op = MASK_OP_MAJOR(ctx->opcode);
8946 rs = (ctx->opcode >> 21) & 0x1f;
8947 rt = (ctx->opcode >> 16) & 0x1f;
8948 rd = (ctx->opcode >> 11) & 0x1f;
8949 sa = (ctx->opcode >> 6) & 0x1f;
8950 imm = (int16_t)ctx->opcode;
8951 switch (op) {
8952 case OPC_SPECIAL:
8953 op1 = MASK_SPECIAL(ctx->opcode);
8954 switch (op1) {
8955 case OPC_SLL: /* Shift with immediate */
8956 case OPC_SRA:
8957 gen_shift_imm(env, ctx, op1, rd, rt, sa);
8958 break;
8959 case OPC_SRL:
8960 switch ((ctx->opcode >> 21) & 0x1f) {
8961 case 1:
8962 /* rotr is decoded as srl on non-R2 CPUs */
8963 if (env->insn_flags & ISA_MIPS32R2) {
8964 op1 = OPC_ROTR;
8966 /* Fallthrough */
8967 case 0:
8968 gen_shift_imm(env, ctx, op1, rd, rt, sa);
8969 break;
8970 default:
8971 generate_exception(ctx, EXCP_RI);
8972 break;
8974 break;
8975 case OPC_MOVN: /* Conditional move */
8976 case OPC_MOVZ:
8977 check_insn(env, ctx, ISA_MIPS4 | ISA_MIPS32);
8978 gen_cond_move(env, op1, rd, rs, rt);
8979 break;
8980 case OPC_ADD ... OPC_SUBU:
8981 gen_arith(env, ctx, op1, rd, rs, rt);
8982 break;
8983 case OPC_SLLV: /* Shifts */
8984 case OPC_SRAV:
8985 gen_shift(env, ctx, op1, rd, rs, rt);
8986 break;
8987 case OPC_SRLV:
8988 switch ((ctx->opcode >> 6) & 0x1f) {
8989 case 1:
8990 /* rotrv is decoded as srlv on non-R2 CPUs */
8991 if (env->insn_flags & ISA_MIPS32R2) {
8992 op1 = OPC_ROTRV;
8994 /* Fallthrough */
8995 case 0:
8996 gen_shift(env, ctx, op1, rd, rs, rt);
8997 break;
8998 default:
8999 generate_exception(ctx, EXCP_RI);
9000 break;
9002 break;
9003 case OPC_SLT: /* Set on less than */
9004 case OPC_SLTU:
9005 gen_slt(env, op1, rd, rs, rt);
9006 break;
9007 case OPC_AND: /* Logic*/
9008 case OPC_OR:
9009 case OPC_NOR:
9010 case OPC_XOR:
9011 gen_logic(env, op1, rd, rs, rt);
9012 break;
9013 case OPC_MULT ... OPC_DIVU:
9014 if (sa) {
9015 check_insn(env, ctx, INSN_VR54XX);
9016 op1 = MASK_MUL_VR54XX(ctx->opcode);
9017 gen_mul_vr54xx(ctx, op1, rd, rs, rt);
9018 } else
9019 gen_muldiv(ctx, op1, rs, rt);
9020 break;
9021 case OPC_JR ... OPC_JALR:
9022 gen_compute_branch(ctx, op1, 4, rs, rd, sa);
9023 *is_branch = 1;
9024 break;
9025 case OPC_TGE ... OPC_TEQ: /* Traps */
9026 case OPC_TNE:
9027 gen_trap(ctx, op1, rs, rt, -1);
9028 break;
9029 case OPC_MFHI: /* Move from HI/LO */
9030 case OPC_MFLO:
9031 gen_HILO(ctx, op1, rd);
9032 break;
9033 case OPC_MTHI:
9034 case OPC_MTLO: /* Move to HI/LO */
9035 gen_HILO(ctx, op1, rs);
9036 break;
9037 case OPC_PMON: /* Pmon entry point, also R4010 selsl */
9038 #ifdef MIPS_STRICT_STANDARD
9039 MIPS_INVAL("PMON / selsl");
9040 generate_exception(ctx, EXCP_RI);
9041 #else
9042 gen_helper_0i(pmon, sa);
9043 #endif
9044 break;
9045 case OPC_SYSCALL:
9046 generate_exception(ctx, EXCP_SYSCALL);
9047 ctx->bstate = BS_STOP;
9048 break;
9049 case OPC_BREAK:
9050 generate_exception(ctx, EXCP_BREAK);
9051 break;
9052 case OPC_SPIM:
9053 #ifdef MIPS_STRICT_STANDARD
9054 MIPS_INVAL("SPIM");
9055 generate_exception(ctx, EXCP_RI);
9056 #else
9057 /* Implemented as RI exception for now. */
9058 MIPS_INVAL("spim (unofficial)");
9059 generate_exception(ctx, EXCP_RI);
9060 #endif
9061 break;
9062 case OPC_SYNC:
9063 /* Treat as NOP. */
9064 break;
9066 case OPC_MOVCI:
9067 check_insn(env, ctx, ISA_MIPS4 | ISA_MIPS32);
9068 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
9069 check_cp1_enabled(ctx);
9070 gen_movci(ctx, rd, rs, (ctx->opcode >> 18) & 0x7,
9071 (ctx->opcode >> 16) & 1);
9072 } else {
9073 generate_exception_err(ctx, EXCP_CpU, 1);
9075 break;
9077 #if defined(TARGET_MIPS64)
9078 /* MIPS64 specific opcodes */
9079 case OPC_DSLL:
9080 case OPC_DSRA:
9081 case OPC_DSLL32:
9082 case OPC_DSRA32:
9083 check_insn(env, ctx, ISA_MIPS3);
9084 check_mips_64(ctx);
9085 gen_shift_imm(env, ctx, op1, rd, rt, sa);
9086 break;
9087 case OPC_DSRL:
9088 switch ((ctx->opcode >> 21) & 0x1f) {
9089 case 1:
9090 /* drotr is decoded as dsrl on non-R2 CPUs */
9091 if (env->insn_flags & ISA_MIPS32R2) {
9092 op1 = OPC_DROTR;
9094 /* Fallthrough */
9095 case 0:
9096 check_insn(env, ctx, ISA_MIPS3);
9097 check_mips_64(ctx);
9098 gen_shift_imm(env, ctx, op1, rd, rt, sa);
9099 break;
9100 default:
9101 generate_exception(ctx, EXCP_RI);
9102 break;
9104 break;
9105 case OPC_DSRL32:
9106 switch ((ctx->opcode >> 21) & 0x1f) {
9107 case 1:
9108 /* drotr32 is decoded as dsrl32 on non-R2 CPUs */
9109 if (env->insn_flags & ISA_MIPS32R2) {
9110 op1 = OPC_DROTR32;
9112 /* Fallthrough */
9113 case 0:
9114 check_insn(env, ctx, ISA_MIPS3);
9115 check_mips_64(ctx);
9116 gen_shift_imm(env, ctx, op1, rd, rt, sa);
9117 break;
9118 default:
9119 generate_exception(ctx, EXCP_RI);
9120 break;
9122 break;
9123 case OPC_DADD ... OPC_DSUBU:
9124 check_insn(env, ctx, ISA_MIPS3);
9125 check_mips_64(ctx);
9126 gen_arith(env, ctx, op1, rd, rs, rt);
9127 break;
9128 case OPC_DSLLV:
9129 case OPC_DSRAV:
9130 check_insn(env, ctx, ISA_MIPS3);
9131 check_mips_64(ctx);
9132 gen_shift(env, ctx, op1, rd, rs, rt);
9133 break;
9134 case OPC_DSRLV:
9135 switch ((ctx->opcode >> 6) & 0x1f) {
9136 case 1:
9137 /* drotrv is decoded as dsrlv on non-R2 CPUs */
9138 if (env->insn_flags & ISA_MIPS32R2) {
9139 op1 = OPC_DROTRV;
9141 /* Fallthrough */
9142 case 0:
9143 check_insn(env, ctx, ISA_MIPS3);
9144 check_mips_64(ctx);
9145 gen_shift(env, ctx, op1, rd, rs, rt);
9146 break;
9147 default:
9148 generate_exception(ctx, EXCP_RI);
9149 break;
9151 break;
9152 case OPC_DMULT ... OPC_DDIVU:
9153 check_insn(env, ctx, ISA_MIPS3);
9154 check_mips_64(ctx);
9155 gen_muldiv(ctx, op1, rs, rt);
9156 break;
9157 #endif
9158 default: /* Invalid */
9159 MIPS_INVAL("special");
9160 generate_exception(ctx, EXCP_RI);
9161 break;
9163 break;
9164 case OPC_SPECIAL2:
9165 op1 = MASK_SPECIAL2(ctx->opcode);
9166 switch (op1) {
9167 case OPC_MADD ... OPC_MADDU: /* Multiply and add/sub */
9168 case OPC_MSUB ... OPC_MSUBU:
9169 check_insn(env, ctx, ISA_MIPS32);
9170 gen_muldiv(ctx, op1, rs, rt);
9171 break;
9172 case OPC_MUL:
9173 gen_arith(env, ctx, op1, rd, rs, rt);
9174 break;
9175 case OPC_CLO:
9176 case OPC_CLZ:
9177 check_insn(env, ctx, ISA_MIPS32);
9178 gen_cl(ctx, op1, rd, rs);
9179 break;
9180 case OPC_SDBBP:
9181 /* XXX: not clear which exception should be raised
9182 * when in debug mode...
9184 check_insn(env, ctx, ISA_MIPS32);
9185 if (!(ctx->hflags & MIPS_HFLAG_DM)) {
9186 generate_exception(ctx, EXCP_DBp);
9187 } else {
9188 generate_exception(ctx, EXCP_DBp);
9190 /* Treat as NOP. */
9191 break;
9192 #if defined(TARGET_MIPS64)
9193 case OPC_DCLO:
9194 case OPC_DCLZ:
9195 check_insn(env, ctx, ISA_MIPS64);
9196 check_mips_64(ctx);
9197 gen_cl(ctx, op1, rd, rs);
9198 break;
9199 #endif
9200 default: /* Invalid */
9201 MIPS_INVAL("special2");
9202 generate_exception(ctx, EXCP_RI);
9203 break;
9205 break;
9206 case OPC_SPECIAL3:
9207 op1 = MASK_SPECIAL3(ctx->opcode);
9208 switch (op1) {
9209 case OPC_EXT:
9210 case OPC_INS:
9211 check_insn(env, ctx, ISA_MIPS32R2);
9212 gen_bitops(ctx, op1, rt, rs, sa, rd);
9213 break;
9214 case OPC_BSHFL:
9215 check_insn(env, ctx, ISA_MIPS32R2);
9216 op2 = MASK_BSHFL(ctx->opcode);
9217 gen_bshfl(ctx, op2, rt, rd);
9218 break;
9219 case OPC_RDHWR:
9220 gen_rdhwr(env, ctx, rt, rd);
9221 break;
9222 case OPC_FORK:
9223 check_insn(env, ctx, ASE_MT);
9225 TCGv t0 = tcg_temp_new();
9226 TCGv t1 = tcg_temp_new();
9228 gen_load_gpr(t0, rt);
9229 gen_load_gpr(t1, rs);
9230 gen_helper_fork(t0, t1);
9231 tcg_temp_free(t0);
9232 tcg_temp_free(t1);
9234 break;
9235 case OPC_YIELD:
9236 check_insn(env, ctx, ASE_MT);
9238 TCGv t0 = tcg_temp_new();
9240 save_cpu_state(ctx, 1);
9241 gen_load_gpr(t0, rs);
9242 gen_helper_yield(t0, t0);
9243 gen_store_gpr(t0, rd);
9244 tcg_temp_free(t0);
9246 break;
9247 #if defined(TARGET_MIPS64)
9248 case OPC_DEXTM ... OPC_DEXT:
9249 case OPC_DINSM ... OPC_DINS:
9250 check_insn(env, ctx, ISA_MIPS64R2);
9251 check_mips_64(ctx);
9252 gen_bitops(ctx, op1, rt, rs, sa, rd);
9253 break;
9254 case OPC_DBSHFL:
9255 check_insn(env, ctx, ISA_MIPS64R2);
9256 check_mips_64(ctx);
9257 op2 = MASK_DBSHFL(ctx->opcode);
9258 gen_bshfl(ctx, op2, rt, rd);
9259 break;
9260 #endif
9261 default: /* Invalid */
9262 MIPS_INVAL("special3");
9263 generate_exception(ctx, EXCP_RI);
9264 break;
9266 break;
9267 case OPC_REGIMM:
9268 op1 = MASK_REGIMM(ctx->opcode);
9269 switch (op1) {
9270 case OPC_BLTZ ... OPC_BGEZL: /* REGIMM branches */
9271 case OPC_BLTZAL ... OPC_BGEZALL:
9272 gen_compute_branch(ctx, op1, 4, rs, -1, imm << 2);
9273 *is_branch = 1;
9274 break;
9275 case OPC_TGEI ... OPC_TEQI: /* REGIMM traps */
9276 case OPC_TNEI:
9277 gen_trap(ctx, op1, rs, -1, imm);
9278 break;
9279 case OPC_SYNCI:
9280 check_insn(env, ctx, ISA_MIPS32R2);
9281 /* Treat as NOP. */
9282 break;
9283 default: /* Invalid */
9284 MIPS_INVAL("regimm");
9285 generate_exception(ctx, EXCP_RI);
9286 break;
9288 break;
9289 case OPC_CP0:
9290 check_cp0_enabled(ctx);
9291 op1 = MASK_CP0(ctx->opcode);
9292 switch (op1) {
9293 case OPC_MFC0:
9294 case OPC_MTC0:
9295 case OPC_MFTR:
9296 case OPC_MTTR:
9297 #if defined(TARGET_MIPS64)
9298 case OPC_DMFC0:
9299 case OPC_DMTC0:
9300 #endif
9301 #ifndef CONFIG_USER_ONLY
9302 gen_cp0(env, ctx, op1, rt, rd);
9303 #endif /* !CONFIG_USER_ONLY */
9304 break;
9305 case OPC_C0_FIRST ... OPC_C0_LAST:
9306 #ifndef CONFIG_USER_ONLY
9307 gen_cp0(env, ctx, MASK_C0(ctx->opcode), rt, rd);
9308 #endif /* !CONFIG_USER_ONLY */
9309 break;
9310 case OPC_MFMC0:
9311 #ifndef CONFIG_USER_ONLY
9313 TCGv t0 = tcg_temp_new();
9315 op2 = MASK_MFMC0(ctx->opcode);
9316 switch (op2) {
9317 case OPC_DMT:
9318 check_insn(env, ctx, ASE_MT);
9319 gen_helper_dmt(t0, t0);
9320 gen_store_gpr(t0, rt);
9321 break;
9322 case OPC_EMT:
9323 check_insn(env, ctx, ASE_MT);
9324 gen_helper_emt(t0, t0);
9325 gen_store_gpr(t0, rt);
9326 break;
9327 case OPC_DVPE:
9328 check_insn(env, ctx, ASE_MT);
9329 gen_helper_dvpe(t0, t0);
9330 gen_store_gpr(t0, rt);
9331 break;
9332 case OPC_EVPE:
9333 check_insn(env, ctx, ASE_MT);
9334 gen_helper_evpe(t0, t0);
9335 gen_store_gpr(t0, rt);
9336 break;
9337 case OPC_DI:
9338 check_insn(env, ctx, ISA_MIPS32R2);
9339 save_cpu_state(ctx, 1);
9340 gen_helper_di(t0);
9341 gen_store_gpr(t0, rt);
9342 /* Stop translation as we may have switched the execution mode */
9343 ctx->bstate = BS_STOP;
9344 break;
9345 case OPC_EI:
9346 check_insn(env, ctx, ISA_MIPS32R2);
9347 save_cpu_state(ctx, 1);
9348 gen_helper_ei(t0);
9349 gen_store_gpr(t0, rt);
9350 /* Stop translation as we may have switched the execution mode */
9351 ctx->bstate = BS_STOP;
9352 break;
9353 default: /* Invalid */
9354 MIPS_INVAL("mfmc0");
9355 generate_exception(ctx, EXCP_RI);
9356 break;
9358 tcg_temp_free(t0);
9360 #endif /* !CONFIG_USER_ONLY */
9361 break;
9362 case OPC_RDPGPR:
9363 check_insn(env, ctx, ISA_MIPS32R2);
9364 gen_load_srsgpr(rt, rd);
9365 break;
9366 case OPC_WRPGPR:
9367 check_insn(env, ctx, ISA_MIPS32R2);
9368 gen_store_srsgpr(rt, rd);
9369 break;
9370 default:
9371 MIPS_INVAL("cp0");
9372 generate_exception(ctx, EXCP_RI);
9373 break;
9375 break;
9376 case OPC_ADDI: /* Arithmetic with immediate opcode */
9377 case OPC_ADDIU:
9378 gen_arith_imm(env, ctx, op, rt, rs, imm);
9379 break;
9380 case OPC_SLTI: /* Set on less than with immediate opcode */
9381 case OPC_SLTIU:
9382 gen_slt_imm(env, op, rt, rs, imm);
9383 break;
9384 case OPC_ANDI: /* Arithmetic with immediate opcode */
9385 case OPC_LUI:
9386 case OPC_ORI:
9387 case OPC_XORI:
9388 gen_logic_imm(env, op, rt, rs, imm);
9389 break;
9390 case OPC_J ... OPC_JAL: /* Jump */
9391 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2;
9392 gen_compute_branch(ctx, op, 4, rs, rt, offset);
9393 *is_branch = 1;
9394 break;
9395 case OPC_BEQ ... OPC_BGTZ: /* Branch */
9396 case OPC_BEQL ... OPC_BGTZL:
9397 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2);
9398 *is_branch = 1;
9399 break;
9400 case OPC_LB ... OPC_LWR: /* Load and stores */
9401 case OPC_SB ... OPC_SW:
9402 case OPC_SWR:
9403 case OPC_LL:
9404 gen_ldst(ctx, op, rt, rs, imm);
9405 break;
9406 case OPC_SC:
9407 gen_st_cond(ctx, op, rt, rs, imm);
9408 break;
9409 case OPC_CACHE:
9410 check_insn(env, ctx, ISA_MIPS3 | ISA_MIPS32);
9411 /* Treat as NOP. */
9412 break;
9413 case OPC_PREF:
9414 check_insn(env, ctx, ISA_MIPS4 | ISA_MIPS32);
9415 /* Treat as NOP. */
9416 break;
9418 /* Floating point (COP1). */
9419 case OPC_LWC1:
9420 case OPC_LDC1:
9421 case OPC_SWC1:
9422 case OPC_SDC1:
9423 gen_cop1_ldst(env, ctx, op, rt, rs, imm);
9424 break;
9426 case OPC_CP1:
9427 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
9428 check_cp1_enabled(ctx);
9429 op1 = MASK_CP1(ctx->opcode);
9430 switch (op1) {
9431 case OPC_MFHC1:
9432 case OPC_MTHC1:
9433 check_insn(env, ctx, ISA_MIPS32R2);
9434 case OPC_MFC1:
9435 case OPC_CFC1:
9436 case OPC_MTC1:
9437 case OPC_CTC1:
9438 gen_cp1(ctx, op1, rt, rd);
9439 break;
9440 #if defined(TARGET_MIPS64)
9441 case OPC_DMFC1:
9442 case OPC_DMTC1:
9443 check_insn(env, ctx, ISA_MIPS3);
9444 gen_cp1(ctx, op1, rt, rd);
9445 break;
9446 #endif
9447 case OPC_BC1ANY2:
9448 case OPC_BC1ANY4:
9449 check_cop1x(ctx);
9450 check_insn(env, ctx, ASE_MIPS3D);
9451 /* fall through */
9452 case OPC_BC1:
9453 gen_compute_branch1(env, ctx, MASK_BC1(ctx->opcode),
9454 (rt >> 2) & 0x7, imm << 2);
9455 *is_branch = 1;
9456 break;
9457 case OPC_S_FMT:
9458 case OPC_D_FMT:
9459 case OPC_W_FMT:
9460 case OPC_L_FMT:
9461 case OPC_PS_FMT:
9462 gen_farith(ctx, ctx->opcode & FOP(0x3f, 0x1f), rt, rd, sa,
9463 (imm >> 8) & 0x7);
9464 break;
9465 default:
9466 MIPS_INVAL("cp1");
9467 generate_exception (ctx, EXCP_RI);
9468 break;
9470 } else {
9471 generate_exception_err(ctx, EXCP_CpU, 1);
9473 break;
9475 /* COP2. */
9476 case OPC_LWC2:
9477 case OPC_LDC2:
9478 case OPC_SWC2:
9479 case OPC_SDC2:
9480 case OPC_CP2:
9481 /* COP2: Not implemented. */
9482 generate_exception_err(ctx, EXCP_CpU, 2);
9483 break;
9485 case OPC_CP3:
9486 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
9487 check_cp1_enabled(ctx);
9488 op1 = MASK_CP3(ctx->opcode);
9489 switch (op1) {
9490 case OPC_LWXC1:
9491 case OPC_LDXC1:
9492 case OPC_LUXC1:
9493 case OPC_SWXC1:
9494 case OPC_SDXC1:
9495 case OPC_SUXC1:
9496 gen_flt3_ldst(ctx, op1, sa, rd, rs, rt);
9497 break;
9498 case OPC_PREFX:
9499 /* Treat as NOP. */
9500 break;
9501 case OPC_ALNV_PS:
9502 case OPC_MADD_S:
9503 case OPC_MADD_D:
9504 case OPC_MADD_PS:
9505 case OPC_MSUB_S:
9506 case OPC_MSUB_D:
9507 case OPC_MSUB_PS:
9508 case OPC_NMADD_S:
9509 case OPC_NMADD_D:
9510 case OPC_NMADD_PS:
9511 case OPC_NMSUB_S:
9512 case OPC_NMSUB_D:
9513 case OPC_NMSUB_PS:
9514 gen_flt3_arith(ctx, op1, sa, rs, rd, rt);
9515 break;
9516 default:
9517 MIPS_INVAL("cp3");
9518 generate_exception (ctx, EXCP_RI);
9519 break;
9521 } else {
9522 generate_exception_err(ctx, EXCP_CpU, 1);
9524 break;
9526 #if defined(TARGET_MIPS64)
9527 /* MIPS64 opcodes */
9528 case OPC_LWU:
9529 case OPC_LDL ... OPC_LDR:
9530 case OPC_SDL ... OPC_SDR:
9531 case OPC_LLD:
9532 case OPC_LD:
9533 case OPC_SD:
9534 check_insn(env, ctx, ISA_MIPS3);
9535 check_mips_64(ctx);
9536 gen_ldst(ctx, op, rt, rs, imm);
9537 break;
9538 case OPC_SCD:
9539 check_insn(env, ctx, ISA_MIPS3);
9540 check_mips_64(ctx);
9541 gen_st_cond(ctx, op, rt, rs, imm);
9542 break;
9543 case OPC_DADDI:
9544 case OPC_DADDIU:
9545 check_insn(env, ctx, ISA_MIPS3);
9546 check_mips_64(ctx);
9547 gen_arith_imm(env, ctx, op, rt, rs, imm);
9548 break;
9549 #endif
9550 case OPC_JALX:
9551 check_insn(env, ctx, ASE_MIPS16);
9552 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2;
9553 gen_compute_branch(ctx, op, 4, rs, rt, offset);
9554 *is_branch = 1;
9555 break;
9556 case OPC_MDMX:
9557 check_insn(env, ctx, ASE_MDMX);
9558 /* MDMX: Not implemented. */
9559 default: /* Invalid */
9560 MIPS_INVAL("major opcode");
9561 generate_exception(ctx, EXCP_RI);
9562 break;
9566 static inline void
9567 gen_intermediate_code_internal (CPUState *env, TranslationBlock *tb,
9568 int search_pc)
9570 DisasContext ctx;
9571 target_ulong pc_start;
9572 uint16_t *gen_opc_end;
9573 CPUBreakpoint *bp;
9574 int j, lj = -1;
9575 int num_insns;
9576 int max_insns;
9577 int insn_bytes;
9578 int is_branch;
9580 if (search_pc)
9581 qemu_log("search pc %d\n", search_pc);
9583 pc_start = tb->pc;
9584 gen_opc_end = gen_opc_buf + OPC_MAX_SIZE;
9585 ctx.pc = pc_start;
9586 ctx.saved_pc = -1;
9587 ctx.singlestep_enabled = env->singlestep_enabled;
9588 ctx.tb = tb;
9589 ctx.bstate = BS_NONE;
9590 /* Restore delay slot state from the tb context. */
9591 ctx.hflags = (uint32_t)tb->flags; /* FIXME: maybe use 64 bits here? */
9592 restore_cpu_state(env, &ctx);
9593 #ifdef CONFIG_USER_ONLY
9594 ctx.mem_idx = MIPS_HFLAG_UM;
9595 #else
9596 ctx.mem_idx = ctx.hflags & MIPS_HFLAG_KSU;
9597 #endif
9598 num_insns = 0;
9599 max_insns = tb->cflags & CF_COUNT_MASK;
9600 if (max_insns == 0)
9601 max_insns = CF_COUNT_MASK;
9602 LOG_DISAS("\ntb %p idx %d hflags %04x\n", tb, ctx.mem_idx, ctx.hflags);
9603 gen_icount_start();
9604 while (ctx.bstate == BS_NONE) {
9605 if (unlikely(!QTAILQ_EMPTY(&env->breakpoints))) {
9606 QTAILQ_FOREACH(bp, &env->breakpoints, entry) {
9607 if (bp->pc == ctx.pc) {
9608 save_cpu_state(&ctx, 1);
9609 ctx.bstate = BS_BRANCH;
9610 gen_helper_0i(raise_exception, EXCP_DEBUG);
9611 /* Include the breakpoint location or the tb won't
9612 * be flushed when it must be. */
9613 ctx.pc += 4;
9614 goto done_generating;
9619 if (search_pc) {
9620 j = gen_opc_ptr - gen_opc_buf;
9621 if (lj < j) {
9622 lj++;
9623 while (lj < j)
9624 gen_opc_instr_start[lj++] = 0;
9626 gen_opc_pc[lj] = ctx.pc;
9627 gen_opc_hflags[lj] = ctx.hflags & MIPS_HFLAG_BMASK;
9628 gen_opc_instr_start[lj] = 1;
9629 gen_opc_icount[lj] = num_insns;
9631 if (num_insns + 1 == max_insns && (tb->cflags & CF_LAST_IO))
9632 gen_io_start();
9634 is_branch = 0;
9635 if (!(ctx.hflags & MIPS_HFLAG_M16)) {
9636 ctx.opcode = ldl_code(ctx.pc);
9637 insn_bytes = 4;
9638 decode_opc(env, &ctx, &is_branch);
9639 } else if (env->insn_flags & ASE_MIPS16) {
9640 ctx.opcode = lduw_code(ctx.pc);
9641 insn_bytes = decode_mips16_opc(env, &ctx, &is_branch);
9642 } else {
9643 generate_exception(&ctx, EXCP_RI);
9644 break;
9646 if (!is_branch) {
9647 handle_delay_slot(env, &ctx, insn_bytes);
9649 ctx.pc += insn_bytes;
9651 num_insns++;
9653 /* Execute a branch and its delay slot as a single instruction.
9654 This is what GDB expects and is consistent with what the
9655 hardware does (e.g. if a delay slot instruction faults, the
9656 reported PC is the PC of the branch). */
9657 if (env->singlestep_enabled && (ctx.hflags & MIPS_HFLAG_BMASK) == 0)
9658 break;
9660 if ((ctx.pc & (TARGET_PAGE_SIZE - 1)) == 0)
9661 break;
9663 if (gen_opc_ptr >= gen_opc_end)
9664 break;
9666 if (num_insns >= max_insns)
9667 break;
9669 if (singlestep)
9670 break;
9672 if (tb->cflags & CF_LAST_IO)
9673 gen_io_end();
9674 if (env->singlestep_enabled && ctx.bstate != BS_BRANCH) {
9675 save_cpu_state(&ctx, ctx.bstate == BS_NONE);
9676 gen_helper_0i(raise_exception, EXCP_DEBUG);
9677 } else {
9678 switch (ctx.bstate) {
9679 case BS_STOP:
9680 gen_helper_interrupt_restart();
9681 gen_goto_tb(&ctx, 0, ctx.pc);
9682 break;
9683 case BS_NONE:
9684 save_cpu_state(&ctx, 0);
9685 gen_goto_tb(&ctx, 0, ctx.pc);
9686 break;
9687 case BS_EXCP:
9688 gen_helper_interrupt_restart();
9689 tcg_gen_exit_tb(0);
9690 break;
9691 case BS_BRANCH:
9692 default:
9693 break;
9696 done_generating:
9697 gen_icount_end(tb, num_insns);
9698 *gen_opc_ptr = INDEX_op_end;
9699 if (search_pc) {
9700 j = gen_opc_ptr - gen_opc_buf;
9701 lj++;
9702 while (lj <= j)
9703 gen_opc_instr_start[lj++] = 0;
9704 } else {
9705 tb->size = ctx.pc - pc_start;
9706 tb->icount = num_insns;
9708 #ifdef DEBUG_DISAS
9709 LOG_DISAS("\n");
9710 if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) {
9711 qemu_log("IN: %s\n", lookup_symbol(pc_start));
9712 log_target_disas(pc_start, ctx.pc - pc_start, 0);
9713 qemu_log("\n");
9715 #endif
9718 void gen_intermediate_code (CPUState *env, struct TranslationBlock *tb)
9720 gen_intermediate_code_internal(env, tb, 0);
9723 void gen_intermediate_code_pc (CPUState *env, struct TranslationBlock *tb)
9725 gen_intermediate_code_internal(env, tb, 1);
9728 static void fpu_dump_state(CPUState *env, FILE *f,
9729 int (*fpu_fprintf)(FILE *f, const char *fmt, ...),
9730 int flags)
9732 int i;
9733 int is_fpu64 = !!(env->hflags & MIPS_HFLAG_F64);
9735 #define printfpr(fp) \
9736 do { \
9737 if (is_fpu64) \
9738 fpu_fprintf(f, "w:%08x d:%016" PRIx64 \
9739 " fd:%13g fs:%13g psu: %13g\n", \
9740 (fp)->w[FP_ENDIAN_IDX], (fp)->d, \
9741 (double)(fp)->fd, \
9742 (double)(fp)->fs[FP_ENDIAN_IDX], \
9743 (double)(fp)->fs[!FP_ENDIAN_IDX]); \
9744 else { \
9745 fpr_t tmp; \
9746 tmp.w[FP_ENDIAN_IDX] = (fp)->w[FP_ENDIAN_IDX]; \
9747 tmp.w[!FP_ENDIAN_IDX] = ((fp) + 1)->w[FP_ENDIAN_IDX]; \
9748 fpu_fprintf(f, "w:%08x d:%016" PRIx64 \
9749 " fd:%13g fs:%13g psu:%13g\n", \
9750 tmp.w[FP_ENDIAN_IDX], tmp.d, \
9751 (double)tmp.fd, \
9752 (double)tmp.fs[FP_ENDIAN_IDX], \
9753 (double)tmp.fs[!FP_ENDIAN_IDX]); \
9755 } while(0)
9758 fpu_fprintf(f, "CP1 FCR0 0x%08x FCR31 0x%08x SR.FR %d fp_status 0x%08x(0x%02x)\n",
9759 env->active_fpu.fcr0, env->active_fpu.fcr31, is_fpu64, env->active_fpu.fp_status,
9760 get_float_exception_flags(&env->active_fpu.fp_status));
9761 for (i = 0; i < 32; (is_fpu64) ? i++ : (i += 2)) {
9762 fpu_fprintf(f, "%3s: ", fregnames[i]);
9763 printfpr(&env->active_fpu.fpr[i]);
9766 #undef printfpr
9769 #if defined(TARGET_MIPS64) && defined(MIPS_DEBUG_SIGN_EXTENSIONS)
9770 /* Debug help: The architecture requires 32bit code to maintain proper
9771 sign-extended values on 64bit machines. */
9773 #define SIGN_EXT_P(val) ((((val) & ~0x7fffffff) == 0) || (((val) & ~0x7fffffff) == ~0x7fffffff))
9775 static void
9776 cpu_mips_check_sign_extensions (CPUState *env, FILE *f,
9777 int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
9778 int flags)
9780 int i;
9782 if (!SIGN_EXT_P(env->active_tc.PC))
9783 cpu_fprintf(f, "BROKEN: pc=0x" TARGET_FMT_lx "\n", env->active_tc.PC);
9784 if (!SIGN_EXT_P(env->active_tc.HI[0]))
9785 cpu_fprintf(f, "BROKEN: HI=0x" TARGET_FMT_lx "\n", env->active_tc.HI[0]);
9786 if (!SIGN_EXT_P(env->active_tc.LO[0]))
9787 cpu_fprintf(f, "BROKEN: LO=0x" TARGET_FMT_lx "\n", env->active_tc.LO[0]);
9788 if (!SIGN_EXT_P(env->btarget))
9789 cpu_fprintf(f, "BROKEN: btarget=0x" TARGET_FMT_lx "\n", env->btarget);
9791 for (i = 0; i < 32; i++) {
9792 if (!SIGN_EXT_P(env->active_tc.gpr[i]))
9793 cpu_fprintf(f, "BROKEN: %s=0x" TARGET_FMT_lx "\n", regnames[i], env->active_tc.gpr[i]);
9796 if (!SIGN_EXT_P(env->CP0_EPC))
9797 cpu_fprintf(f, "BROKEN: EPC=0x" TARGET_FMT_lx "\n", env->CP0_EPC);
9798 if (!SIGN_EXT_P(env->lladdr))
9799 cpu_fprintf(f, "BROKEN: LLAddr=0x" TARGET_FMT_lx "\n", env->lladdr);
9801 #endif
9803 void cpu_dump_state (CPUState *env, FILE *f,
9804 int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
9805 int flags)
9807 int i;
9809 cpu_fprintf(f, "pc=0x" TARGET_FMT_lx " HI=0x" TARGET_FMT_lx
9810 " LO=0x" TARGET_FMT_lx " ds %04x "
9811 TARGET_FMT_lx " " TARGET_FMT_ld "\n",
9812 env->active_tc.PC, env->active_tc.HI[0], env->active_tc.LO[0],
9813 env->hflags, env->btarget, env->bcond);
9814 for (i = 0; i < 32; i++) {
9815 if ((i & 3) == 0)
9816 cpu_fprintf(f, "GPR%02d:", i);
9817 cpu_fprintf(f, " %s " TARGET_FMT_lx, regnames[i], env->active_tc.gpr[i]);
9818 if ((i & 3) == 3)
9819 cpu_fprintf(f, "\n");
9822 cpu_fprintf(f, "CP0 Status 0x%08x Cause 0x%08x EPC 0x" TARGET_FMT_lx "\n",
9823 env->CP0_Status, env->CP0_Cause, env->CP0_EPC);
9824 cpu_fprintf(f, " Config0 0x%08x Config1 0x%08x LLAddr 0x" TARGET_FMT_lx "\n",
9825 env->CP0_Config0, env->CP0_Config1, env->lladdr);
9826 if (env->hflags & MIPS_HFLAG_FPU)
9827 fpu_dump_state(env, f, cpu_fprintf, flags);
9828 #if defined(TARGET_MIPS64) && defined(MIPS_DEBUG_SIGN_EXTENSIONS)
9829 cpu_mips_check_sign_extensions(env, f, cpu_fprintf, flags);
9830 #endif
9833 static void mips_tcg_init(void)
9835 int i;
9836 static int inited;
9838 /* Initialize various static tables. */
9839 if (inited)
9840 return;
9842 cpu_env = tcg_global_reg_new_ptr(TCG_AREG0, "env");
9843 TCGV_UNUSED(cpu_gpr[0]);
9844 for (i = 1; i < 32; i++)
9845 cpu_gpr[i] = tcg_global_mem_new(TCG_AREG0,
9846 offsetof(CPUState, active_tc.gpr[i]),
9847 regnames[i]);
9848 cpu_PC = tcg_global_mem_new(TCG_AREG0,
9849 offsetof(CPUState, active_tc.PC), "PC");
9850 for (i = 0; i < MIPS_DSP_ACC; i++) {
9851 cpu_HI[i] = tcg_global_mem_new(TCG_AREG0,
9852 offsetof(CPUState, active_tc.HI[i]),
9853 regnames_HI[i]);
9854 cpu_LO[i] = tcg_global_mem_new(TCG_AREG0,
9855 offsetof(CPUState, active_tc.LO[i]),
9856 regnames_LO[i]);
9857 cpu_ACX[i] = tcg_global_mem_new(TCG_AREG0,
9858 offsetof(CPUState, active_tc.ACX[i]),
9859 regnames_ACX[i]);
9861 cpu_dspctrl = tcg_global_mem_new(TCG_AREG0,
9862 offsetof(CPUState, active_tc.DSPControl),
9863 "DSPControl");
9864 bcond = tcg_global_mem_new(TCG_AREG0,
9865 offsetof(CPUState, bcond), "bcond");
9866 btarget = tcg_global_mem_new(TCG_AREG0,
9867 offsetof(CPUState, btarget), "btarget");
9868 hflags = tcg_global_mem_new_i32(TCG_AREG0,
9869 offsetof(CPUState, hflags), "hflags");
9871 fpu_fcr0 = tcg_global_mem_new_i32(TCG_AREG0,
9872 offsetof(CPUState, active_fpu.fcr0),
9873 "fcr0");
9874 fpu_fcr31 = tcg_global_mem_new_i32(TCG_AREG0,
9875 offsetof(CPUState, active_fpu.fcr31),
9876 "fcr31");
9878 /* register helpers */
9879 #define GEN_HELPER 2
9880 #include "helper.h"
9882 inited = 1;
9885 #include "translate_init.c"
9887 CPUMIPSState *cpu_mips_init (const char *cpu_model)
9889 CPUMIPSState *env;
9890 const mips_def_t *def;
9892 def = cpu_mips_find_by_name(cpu_model);
9893 if (!def)
9894 return NULL;
9895 env = qemu_mallocz(sizeof(CPUMIPSState));
9896 env->cpu_model = def;
9897 env->cpu_model_str = cpu_model;
9899 cpu_exec_init(env);
9900 #ifndef CONFIG_USER_ONLY
9901 mmu_init(env, def);
9902 #endif
9903 fpu_init(env, def);
9904 mvp_init(env, def);
9905 mips_tcg_init();
9906 cpu_reset(env);
9907 qemu_init_vcpu(env);
9908 return env;
9911 void cpu_reset (CPUMIPSState *env)
9913 if (qemu_loglevel_mask(CPU_LOG_RESET)) {
9914 qemu_log("CPU Reset (CPU %d)\n", env->cpu_index);
9915 log_cpu_state(env, 0);
9918 memset(env, 0, offsetof(CPUMIPSState, breakpoints));
9919 tlb_flush(env, 1);
9921 /* Reset registers to their default values */
9922 env->CP0_PRid = env->cpu_model->CP0_PRid;
9923 env->CP0_Config0 = env->cpu_model->CP0_Config0;
9924 #ifdef TARGET_WORDS_BIGENDIAN
9925 env->CP0_Config0 |= (1 << CP0C0_BE);
9926 #endif
9927 env->CP0_Config1 = env->cpu_model->CP0_Config1;
9928 env->CP0_Config2 = env->cpu_model->CP0_Config2;
9929 env->CP0_Config3 = env->cpu_model->CP0_Config3;
9930 env->CP0_Config6 = env->cpu_model->CP0_Config6;
9931 env->CP0_Config7 = env->cpu_model->CP0_Config7;
9932 env->CP0_LLAddr_rw_bitmask = env->cpu_model->CP0_LLAddr_rw_bitmask
9933 << env->cpu_model->CP0_LLAddr_shift;
9934 env->CP0_LLAddr_shift = env->cpu_model->CP0_LLAddr_shift;
9935 env->SYNCI_Step = env->cpu_model->SYNCI_Step;
9936 env->CCRes = env->cpu_model->CCRes;
9937 env->CP0_Status_rw_bitmask = env->cpu_model->CP0_Status_rw_bitmask;
9938 env->CP0_TCStatus_rw_bitmask = env->cpu_model->CP0_TCStatus_rw_bitmask;
9939 env->CP0_SRSCtl = env->cpu_model->CP0_SRSCtl;
9940 env->current_tc = 0;
9941 env->SEGBITS = env->cpu_model->SEGBITS;
9942 env->SEGMask = (target_ulong)((1ULL << env->cpu_model->SEGBITS) - 1);
9943 #if defined(TARGET_MIPS64)
9944 if (env->cpu_model->insn_flags & ISA_MIPS3) {
9945 env->SEGMask |= 3ULL << 62;
9947 #endif
9948 env->PABITS = env->cpu_model->PABITS;
9949 env->PAMask = (target_ulong)((1ULL << env->cpu_model->PABITS) - 1);
9950 env->CP0_SRSConf0_rw_bitmask = env->cpu_model->CP0_SRSConf0_rw_bitmask;
9951 env->CP0_SRSConf0 = env->cpu_model->CP0_SRSConf0;
9952 env->CP0_SRSConf1_rw_bitmask = env->cpu_model->CP0_SRSConf1_rw_bitmask;
9953 env->CP0_SRSConf1 = env->cpu_model->CP0_SRSConf1;
9954 env->CP0_SRSConf2_rw_bitmask = env->cpu_model->CP0_SRSConf2_rw_bitmask;
9955 env->CP0_SRSConf2 = env->cpu_model->CP0_SRSConf2;
9956 env->CP0_SRSConf3_rw_bitmask = env->cpu_model->CP0_SRSConf3_rw_bitmask;
9957 env->CP0_SRSConf3 = env->cpu_model->CP0_SRSConf3;
9958 env->CP0_SRSConf4_rw_bitmask = env->cpu_model->CP0_SRSConf4_rw_bitmask;
9959 env->CP0_SRSConf4 = env->cpu_model->CP0_SRSConf4;
9960 env->insn_flags = env->cpu_model->insn_flags;
9962 #if defined(CONFIG_USER_ONLY)
9963 env->hflags = MIPS_HFLAG_UM;
9964 /* Enable access to the SYNCI_Step register. */
9965 env->CP0_HWREna |= (1 << 1);
9966 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
9967 env->hflags |= MIPS_HFLAG_FPU;
9969 #ifdef TARGET_MIPS64
9970 if (env->active_fpu.fcr0 & (1 << FCR0_F64)) {
9971 env->hflags |= MIPS_HFLAG_F64;
9973 #endif
9974 #else
9975 if (env->hflags & MIPS_HFLAG_BMASK) {
9976 /* If the exception was raised from a delay slot,
9977 come back to the jump. */
9978 env->CP0_ErrorEPC = env->active_tc.PC - 4;
9979 } else {
9980 env->CP0_ErrorEPC = env->active_tc.PC;
9982 env->active_tc.PC = (int32_t)0xBFC00000;
9983 env->CP0_Random = env->tlb->nb_tlb - 1;
9984 env->tlb->tlb_in_use = env->tlb->nb_tlb;
9985 env->CP0_Wired = 0;
9986 /* SMP not implemented */
9987 env->CP0_EBase = 0x80000000;
9988 env->CP0_Status = (1 << CP0St_BEV) | (1 << CP0St_ERL);
9989 /* vectored interrupts not implemented, timer on int 7,
9990 no performance counters. */
9991 env->CP0_IntCtl = 0xe0000000;
9993 int i;
9995 for (i = 0; i < 7; i++) {
9996 env->CP0_WatchLo[i] = 0;
9997 env->CP0_WatchHi[i] = 0x80000000;
9999 env->CP0_WatchLo[7] = 0;
10000 env->CP0_WatchHi[7] = 0;
10002 /* Count register increments in debug mode, EJTAG version 1 */
10003 env->CP0_Debug = (1 << CP0DB_CNT) | (0x1 << CP0DB_VER);
10004 env->hflags = MIPS_HFLAG_CP0;
10005 #endif
10006 #if defined(TARGET_MIPS64)
10007 if (env->cpu_model->insn_flags & ISA_MIPS3) {
10008 env->hflags |= MIPS_HFLAG_64;
10010 #endif
10011 env->exception_index = EXCP_NONE;
10014 void gen_pc_load(CPUState *env, TranslationBlock *tb,
10015 unsigned long searched_pc, int pc_pos, void *puc)
10017 env->active_tc.PC = gen_opc_pc[pc_pos];
10018 env->hflags &= ~MIPS_HFLAG_BMASK;
10019 env->hflags |= gen_opc_hflags[pc_pos];