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