pcnet: switch to symbolic names for pci registers
[qemu/aliguori-queue.git] / target-mips / translate.c
blobdfea6f6e3490cb4063beee72445524c3bab54f40
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 #define OP_COND(name, cond) \
699 static inline void glue(gen_op_, name) (TCGv ret, TCGv t0, TCGv t1) \
701 int l1 = gen_new_label(); \
702 int l2 = gen_new_label(); \
704 tcg_gen_brcond_tl(cond, t0, t1, l1); \
705 tcg_gen_movi_tl(ret, 0); \
706 tcg_gen_br(l2); \
707 gen_set_label(l1); \
708 tcg_gen_movi_tl(ret, 1); \
709 gen_set_label(l2); \
711 OP_COND(eq, TCG_COND_EQ);
712 OP_COND(ne, TCG_COND_NE);
713 OP_COND(ge, TCG_COND_GE);
714 OP_COND(geu, TCG_COND_GEU);
715 OP_COND(lt, TCG_COND_LT);
716 OP_COND(ltu, TCG_COND_LTU);
717 #undef OP_COND
719 #define OP_CONDI(name, cond) \
720 static inline void glue(gen_op_, name) (TCGv ret, TCGv t0, target_ulong val) \
722 int l1 = gen_new_label(); \
723 int l2 = gen_new_label(); \
725 tcg_gen_brcondi_tl(cond, t0, val, l1); \
726 tcg_gen_movi_tl(ret, 0); \
727 tcg_gen_br(l2); \
728 gen_set_label(l1); \
729 tcg_gen_movi_tl(ret, 1); \
730 gen_set_label(l2); \
732 OP_CONDI(lti, TCG_COND_LT);
733 OP_CONDI(ltiu, TCG_COND_LTU);
734 #undef OP_CONDI
736 #define OP_CONDZ(name, cond) \
737 static inline void glue(gen_op_, name) (TCGv ret, TCGv t0) \
739 int l1 = gen_new_label(); \
740 int l2 = gen_new_label(); \
742 tcg_gen_brcondi_tl(cond, t0, 0, l1); \
743 tcg_gen_movi_tl(ret, 0); \
744 tcg_gen_br(l2); \
745 gen_set_label(l1); \
746 tcg_gen_movi_tl(ret, 1); \
747 gen_set_label(l2); \
749 OP_CONDZ(gez, TCG_COND_GE);
750 OP_CONDZ(gtz, TCG_COND_GT);
751 OP_CONDZ(lez, TCG_COND_LE);
752 OP_CONDZ(ltz, TCG_COND_LT);
753 #undef OP_CONDZ
755 static inline void gen_save_pc(target_ulong pc)
757 tcg_gen_movi_tl(cpu_PC, pc);
760 static inline void save_cpu_state (DisasContext *ctx, int do_save_pc)
762 LOG_DISAS("hflags %08x saved %08x\n", ctx->hflags, ctx->saved_hflags);
763 if (do_save_pc && ctx->pc != ctx->saved_pc) {
764 gen_save_pc(ctx->pc);
765 ctx->saved_pc = ctx->pc;
767 if (ctx->hflags != ctx->saved_hflags) {
768 tcg_gen_movi_i32(hflags, ctx->hflags);
769 ctx->saved_hflags = ctx->hflags;
770 switch (ctx->hflags & MIPS_HFLAG_BMASK_BASE) {
771 case MIPS_HFLAG_BR:
772 break;
773 case MIPS_HFLAG_BC:
774 case MIPS_HFLAG_BL:
775 case MIPS_HFLAG_B:
776 tcg_gen_movi_tl(btarget, ctx->btarget);
777 break;
782 static inline void restore_cpu_state (CPUState *env, DisasContext *ctx)
784 ctx->saved_hflags = ctx->hflags;
785 switch (ctx->hflags & MIPS_HFLAG_BMASK_BASE) {
786 case MIPS_HFLAG_BR:
787 break;
788 case MIPS_HFLAG_BC:
789 case MIPS_HFLAG_BL:
790 case MIPS_HFLAG_B:
791 ctx->btarget = env->btarget;
792 break;
796 static inline void
797 generate_exception_err (DisasContext *ctx, int excp, int err)
799 TCGv_i32 texcp = tcg_const_i32(excp);
800 TCGv_i32 terr = tcg_const_i32(err);
801 save_cpu_state(ctx, 1);
802 gen_helper_raise_exception_err(texcp, terr);
803 tcg_temp_free_i32(terr);
804 tcg_temp_free_i32(texcp);
807 static inline void
808 generate_exception (DisasContext *ctx, int excp)
810 save_cpu_state(ctx, 1);
811 gen_helper_0i(raise_exception, excp);
814 /* Addresses computation */
815 static inline void gen_op_addr_add (DisasContext *ctx, TCGv ret, TCGv arg0, TCGv arg1)
817 tcg_gen_add_tl(ret, arg0, arg1);
819 #if defined(TARGET_MIPS64)
820 /* For compatibility with 32-bit code, data reference in user mode
821 with Status_UX = 0 should be casted to 32-bit and sign extended.
822 See the MIPS64 PRA manual, section 4.10. */
823 if (((ctx->hflags & MIPS_HFLAG_KSU) == MIPS_HFLAG_UM) &&
824 !(ctx->hflags & MIPS_HFLAG_UX)) {
825 tcg_gen_ext32s_i64(ret, ret);
827 #endif
830 static inline void check_cp0_enabled(DisasContext *ctx)
832 if (unlikely(!(ctx->hflags & MIPS_HFLAG_CP0)))
833 generate_exception_err(ctx, EXCP_CpU, 1);
836 static inline void check_cp1_enabled(DisasContext *ctx)
838 if (unlikely(!(ctx->hflags & MIPS_HFLAG_FPU)))
839 generate_exception_err(ctx, EXCP_CpU, 1);
842 /* Verify that the processor is running with COP1X instructions enabled.
843 This is associated with the nabla symbol in the MIPS32 and MIPS64
844 opcode tables. */
846 static inline void check_cop1x(DisasContext *ctx)
848 if (unlikely(!(ctx->hflags & MIPS_HFLAG_COP1X)))
849 generate_exception(ctx, EXCP_RI);
852 /* Verify that the processor is running with 64-bit floating-point
853 operations enabled. */
855 static inline void check_cp1_64bitmode(DisasContext *ctx)
857 if (unlikely(~ctx->hflags & (MIPS_HFLAG_F64 | MIPS_HFLAG_COP1X)))
858 generate_exception(ctx, EXCP_RI);
862 * Verify if floating point register is valid; an operation is not defined
863 * if bit 0 of any register specification is set and the FR bit in the
864 * Status register equals zero, since the register numbers specify an
865 * even-odd pair of adjacent coprocessor general registers. When the FR bit
866 * in the Status register equals one, both even and odd register numbers
867 * are valid. This limitation exists only for 64 bit wide (d,l,ps) registers.
869 * Multiple 64 bit wide registers can be checked by calling
870 * gen_op_cp1_registers(freg1 | freg2 | ... | fregN);
872 static inline void check_cp1_registers(DisasContext *ctx, int regs)
874 if (unlikely(!(ctx->hflags & MIPS_HFLAG_F64) && (regs & 1)))
875 generate_exception(ctx, EXCP_RI);
878 /* This code generates a "reserved instruction" exception if the
879 CPU does not support the instruction set corresponding to flags. */
880 static inline void check_insn(CPUState *env, DisasContext *ctx, int flags)
882 if (unlikely(!(env->insn_flags & flags)))
883 generate_exception(ctx, EXCP_RI);
886 /* This code generates a "reserved instruction" exception if 64-bit
887 instructions are not enabled. */
888 static inline void check_mips_64(DisasContext *ctx)
890 if (unlikely(!(ctx->hflags & MIPS_HFLAG_64)))
891 generate_exception(ctx, EXCP_RI);
894 /* load/store instructions. */
895 #define OP_LD(insn,fname) \
896 static inline void op_ldst_##insn(TCGv ret, TCGv arg1, DisasContext *ctx) \
898 tcg_gen_qemu_##fname(ret, arg1, ctx->mem_idx); \
900 OP_LD(lb,ld8s);
901 OP_LD(lbu,ld8u);
902 OP_LD(lh,ld16s);
903 OP_LD(lhu,ld16u);
904 OP_LD(lw,ld32s);
905 #if defined(TARGET_MIPS64)
906 OP_LD(lwu,ld32u);
907 OP_LD(ld,ld64);
908 #endif
909 #undef OP_LD
911 #define OP_ST(insn,fname) \
912 static inline void op_ldst_##insn(TCGv arg1, TCGv arg2, DisasContext *ctx) \
914 tcg_gen_qemu_##fname(arg1, arg2, ctx->mem_idx); \
916 OP_ST(sb,st8);
917 OP_ST(sh,st16);
918 OP_ST(sw,st32);
919 #if defined(TARGET_MIPS64)
920 OP_ST(sd,st64);
921 #endif
922 #undef OP_ST
924 #ifdef CONFIG_USER_ONLY
925 #define OP_LD_ATOMIC(insn,fname) \
926 static inline void op_ldst_##insn(TCGv ret, TCGv arg1, DisasContext *ctx) \
928 TCGv t0 = tcg_temp_new(); \
929 tcg_gen_mov_tl(t0, arg1); \
930 tcg_gen_qemu_##fname(ret, arg1, ctx->mem_idx); \
931 tcg_gen_st_tl(t0, cpu_env, offsetof(CPUState, lladdr)); \
932 tcg_gen_st_tl(ret, cpu_env, offsetof(CPUState, llval)); \
933 tcg_temp_free(t0); \
935 #else
936 #define OP_LD_ATOMIC(insn,fname) \
937 static inline void op_ldst_##insn(TCGv ret, TCGv arg1, DisasContext *ctx) \
939 gen_helper_2i(insn, ret, arg1, ctx->mem_idx); \
941 #endif
942 OP_LD_ATOMIC(ll,ld32s);
943 #if defined(TARGET_MIPS64)
944 OP_LD_ATOMIC(lld,ld64);
945 #endif
946 #undef OP_LD_ATOMIC
948 #ifdef CONFIG_USER_ONLY
949 #define OP_ST_ATOMIC(insn,fname,ldname,almask) \
950 static inline void op_ldst_##insn(TCGv arg1, TCGv arg2, int rt, DisasContext *ctx) \
952 TCGv t0 = tcg_temp_new(); \
953 int l1 = gen_new_label(); \
954 int l2 = gen_new_label(); \
956 tcg_gen_andi_tl(t0, arg2, almask); \
957 tcg_gen_brcondi_tl(TCG_COND_EQ, t0, 0, l1); \
958 tcg_gen_st_tl(arg2, cpu_env, offsetof(CPUState, CP0_BadVAddr)); \
959 generate_exception(ctx, EXCP_AdES); \
960 gen_set_label(l1); \
961 tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUState, lladdr)); \
962 tcg_gen_brcond_tl(TCG_COND_NE, arg2, t0, l2); \
963 tcg_gen_movi_tl(t0, rt | ((almask << 3) & 0x20)); \
964 tcg_gen_st_tl(t0, cpu_env, offsetof(CPUState, llreg)); \
965 tcg_gen_st_tl(arg1, cpu_env, offsetof(CPUState, llnewval)); \
966 gen_helper_0i(raise_exception, EXCP_SC); \
967 gen_set_label(l2); \
968 tcg_gen_movi_tl(t0, 0); \
969 gen_store_gpr(t0, rt); \
970 tcg_temp_free(t0); \
972 #else
973 #define OP_ST_ATOMIC(insn,fname,ldname,almask) \
974 static inline void op_ldst_##insn(TCGv arg1, TCGv arg2, int rt, DisasContext *ctx) \
976 TCGv t0 = tcg_temp_new(); \
977 gen_helper_3i(insn, t0, arg1, arg2, ctx->mem_idx); \
978 gen_store_gpr(t0, rt); \
979 tcg_temp_free(t0); \
981 #endif
982 OP_ST_ATOMIC(sc,st32,ld32s,0x3);
983 #if defined(TARGET_MIPS64)
984 OP_ST_ATOMIC(scd,st64,ld64,0x7);
985 #endif
986 #undef OP_ST_ATOMIC
988 static void gen_base_offset_addr (DisasContext *ctx, TCGv addr,
989 int base, int16_t offset)
991 if (base == 0) {
992 tcg_gen_movi_tl(addr, offset);
993 } else if (offset == 0) {
994 gen_load_gpr(addr, base);
995 } else {
996 tcg_gen_movi_tl(addr, offset);
997 gen_op_addr_add(ctx, addr, cpu_gpr[base], addr);
1001 static target_ulong pc_relative_pc (DisasContext *ctx)
1003 target_ulong pc = ctx->pc;
1005 if (ctx->hflags & MIPS_HFLAG_BMASK) {
1006 int branch_bytes = ctx->hflags & MIPS_HFLAG_BDS16 ? 2 : 4;
1008 pc -= branch_bytes;
1011 pc &= ~(target_ulong)3;
1012 return pc;
1015 /* Load and store */
1016 static void gen_ldst (DisasContext *ctx, uint32_t opc, int rt,
1017 int base, int16_t offset)
1019 const char *opn = "ldst";
1020 TCGv t0 = tcg_temp_new();
1021 TCGv t1 = tcg_temp_new();
1023 gen_base_offset_addr(ctx, t0, base, offset);
1024 /* Don't do NOP if destination is zero: we must perform the actual
1025 memory access. */
1026 switch (opc) {
1027 #if defined(TARGET_MIPS64)
1028 case OPC_LWU:
1029 save_cpu_state(ctx, 0);
1030 op_ldst_lwu(t0, t0, ctx);
1031 gen_store_gpr(t0, rt);
1032 opn = "lwu";
1033 break;
1034 case OPC_LD:
1035 save_cpu_state(ctx, 0);
1036 op_ldst_ld(t0, t0, ctx);
1037 gen_store_gpr(t0, rt);
1038 opn = "ld";
1039 break;
1040 case OPC_LLD:
1041 save_cpu_state(ctx, 0);
1042 op_ldst_lld(t0, t0, ctx);
1043 gen_store_gpr(t0, rt);
1044 opn = "lld";
1045 break;
1046 case OPC_SD:
1047 save_cpu_state(ctx, 0);
1048 gen_load_gpr(t1, rt);
1049 op_ldst_sd(t1, t0, ctx);
1050 opn = "sd";
1051 break;
1052 case OPC_LDL:
1053 save_cpu_state(ctx, 1);
1054 gen_load_gpr(t1, rt);
1055 gen_helper_3i(ldl, t1, t1, t0, ctx->mem_idx);
1056 gen_store_gpr(t1, rt);
1057 opn = "ldl";
1058 break;
1059 case OPC_SDL:
1060 save_cpu_state(ctx, 1);
1061 gen_load_gpr(t1, rt);
1062 gen_helper_2i(sdl, t1, t0, ctx->mem_idx);
1063 opn = "sdl";
1064 break;
1065 case OPC_LDR:
1066 save_cpu_state(ctx, 1);
1067 gen_load_gpr(t1, rt);
1068 gen_helper_3i(ldr, t1, t1, t0, ctx->mem_idx);
1069 gen_store_gpr(t1, rt);
1070 opn = "ldr";
1071 break;
1072 case OPC_SDR:
1073 save_cpu_state(ctx, 1);
1074 gen_load_gpr(t1, rt);
1075 gen_helper_2i(sdr, t1, t0, ctx->mem_idx);
1076 opn = "sdr";
1077 break;
1078 case OPC_LDPC:
1079 save_cpu_state(ctx, 1);
1080 tcg_gen_movi_tl(t1, pc_relative_pc(ctx));
1081 gen_op_addr_add(ctx, t0, t0, t1);
1082 op_ldst_ld(t0, t0, ctx);
1083 gen_store_gpr(t0, rt);
1084 break;
1085 #endif
1086 case OPC_LWPC:
1087 save_cpu_state(ctx, 1);
1088 tcg_gen_movi_tl(t1, pc_relative_pc(ctx));
1089 gen_op_addr_add(ctx, t0, t0, t1);
1090 op_ldst_lw(t0, t0, ctx);
1091 gen_store_gpr(t0, rt);
1092 break;
1093 case OPC_LW:
1094 save_cpu_state(ctx, 0);
1095 op_ldst_lw(t0, t0, ctx);
1096 gen_store_gpr(t0, rt);
1097 opn = "lw";
1098 break;
1099 case OPC_SW:
1100 save_cpu_state(ctx, 0);
1101 gen_load_gpr(t1, rt);
1102 op_ldst_sw(t1, t0, ctx);
1103 opn = "sw";
1104 break;
1105 case OPC_LH:
1106 save_cpu_state(ctx, 0);
1107 op_ldst_lh(t0, t0, ctx);
1108 gen_store_gpr(t0, rt);
1109 opn = "lh";
1110 break;
1111 case OPC_SH:
1112 save_cpu_state(ctx, 0);
1113 gen_load_gpr(t1, rt);
1114 op_ldst_sh(t1, t0, ctx);
1115 opn = "sh";
1116 break;
1117 case OPC_LHU:
1118 save_cpu_state(ctx, 0);
1119 op_ldst_lhu(t0, t0, ctx);
1120 gen_store_gpr(t0, rt);
1121 opn = "lhu";
1122 break;
1123 case OPC_LB:
1124 save_cpu_state(ctx, 0);
1125 op_ldst_lb(t0, t0, ctx);
1126 gen_store_gpr(t0, rt);
1127 opn = "lb";
1128 break;
1129 case OPC_SB:
1130 save_cpu_state(ctx, 0);
1131 gen_load_gpr(t1, rt);
1132 op_ldst_sb(t1, t0, ctx);
1133 opn = "sb";
1134 break;
1135 case OPC_LBU:
1136 save_cpu_state(ctx, 0);
1137 op_ldst_lbu(t0, t0, ctx);
1138 gen_store_gpr(t0, rt);
1139 opn = "lbu";
1140 break;
1141 case OPC_LWL:
1142 save_cpu_state(ctx, 1);
1143 gen_load_gpr(t1, rt);
1144 gen_helper_3i(lwl, t1, t1, t0, ctx->mem_idx);
1145 gen_store_gpr(t1, rt);
1146 opn = "lwl";
1147 break;
1148 case OPC_SWL:
1149 save_cpu_state(ctx, 1);
1150 gen_load_gpr(t1, rt);
1151 gen_helper_2i(swl, t1, t0, ctx->mem_idx);
1152 opn = "swr";
1153 break;
1154 case OPC_LWR:
1155 save_cpu_state(ctx, 1);
1156 gen_load_gpr(t1, rt);
1157 gen_helper_3i(lwr, t1, t1, t0, ctx->mem_idx);
1158 gen_store_gpr(t1, rt);
1159 opn = "lwr";
1160 break;
1161 case OPC_SWR:
1162 save_cpu_state(ctx, 1);
1163 gen_load_gpr(t1, rt);
1164 gen_helper_2i(swr, t1, t0, ctx->mem_idx);
1165 opn = "swr";
1166 break;
1167 case OPC_LL:
1168 save_cpu_state(ctx, 1);
1169 op_ldst_ll(t0, t0, ctx);
1170 gen_store_gpr(t0, rt);
1171 opn = "ll";
1172 break;
1174 MIPS_DEBUG("%s %s, %d(%s)", opn, regnames[rt], offset, regnames[base]);
1175 tcg_temp_free(t0);
1176 tcg_temp_free(t1);
1179 /* Store conditional */
1180 static void gen_st_cond (DisasContext *ctx, uint32_t opc, int rt,
1181 int base, int16_t offset)
1183 const char *opn = "st_cond";
1184 TCGv t0, t1;
1186 t0 = tcg_temp_local_new();
1188 gen_base_offset_addr(ctx, t0, base, offset);
1189 /* Don't do NOP if destination is zero: we must perform the actual
1190 memory access. */
1192 t1 = tcg_temp_local_new();
1193 gen_load_gpr(t1, rt);
1194 switch (opc) {
1195 #if defined(TARGET_MIPS64)
1196 case OPC_SCD:
1197 save_cpu_state(ctx, 0);
1198 op_ldst_scd(t1, t0, rt, ctx);
1199 opn = "scd";
1200 break;
1201 #endif
1202 case OPC_SC:
1203 save_cpu_state(ctx, 1);
1204 op_ldst_sc(t1, t0, rt, ctx);
1205 opn = "sc";
1206 break;
1208 MIPS_DEBUG("%s %s, %d(%s)", opn, regnames[rt], offset, regnames[base]);
1209 tcg_temp_free(t1);
1210 tcg_temp_free(t0);
1213 /* Load and store */
1214 static void gen_flt_ldst (DisasContext *ctx, uint32_t opc, int ft,
1215 int base, int16_t offset)
1217 const char *opn = "flt_ldst";
1218 TCGv t0 = tcg_temp_new();
1220 gen_base_offset_addr(ctx, t0, base, offset);
1221 /* Don't do NOP if destination is zero: we must perform the actual
1222 memory access. */
1223 switch (opc) {
1224 case OPC_LWC1:
1226 TCGv_i32 fp0 = tcg_temp_new_i32();
1228 tcg_gen_qemu_ld32s(t0, t0, ctx->mem_idx);
1229 tcg_gen_trunc_tl_i32(fp0, t0);
1230 gen_store_fpr32(fp0, ft);
1231 tcg_temp_free_i32(fp0);
1233 opn = "lwc1";
1234 break;
1235 case OPC_SWC1:
1237 TCGv_i32 fp0 = tcg_temp_new_i32();
1238 TCGv t1 = tcg_temp_new();
1240 gen_load_fpr32(fp0, ft);
1241 tcg_gen_extu_i32_tl(t1, fp0);
1242 tcg_gen_qemu_st32(t1, t0, ctx->mem_idx);
1243 tcg_temp_free(t1);
1244 tcg_temp_free_i32(fp0);
1246 opn = "swc1";
1247 break;
1248 case OPC_LDC1:
1250 TCGv_i64 fp0 = tcg_temp_new_i64();
1252 tcg_gen_qemu_ld64(fp0, t0, ctx->mem_idx);
1253 gen_store_fpr64(ctx, fp0, ft);
1254 tcg_temp_free_i64(fp0);
1256 opn = "ldc1";
1257 break;
1258 case OPC_SDC1:
1260 TCGv_i64 fp0 = tcg_temp_new_i64();
1262 gen_load_fpr64(ctx, fp0, ft);
1263 tcg_gen_qemu_st64(fp0, t0, ctx->mem_idx);
1264 tcg_temp_free_i64(fp0);
1266 opn = "sdc1";
1267 break;
1268 default:
1269 MIPS_INVAL(opn);
1270 generate_exception(ctx, EXCP_RI);
1271 goto out;
1273 MIPS_DEBUG("%s %s, %d(%s)", opn, fregnames[ft], offset, regnames[base]);
1274 out:
1275 tcg_temp_free(t0);
1278 /* Arithmetic with immediate operand */
1279 static void gen_arith_imm (CPUState *env, DisasContext *ctx, uint32_t opc,
1280 int rt, int rs, int16_t imm)
1282 target_ulong uimm = (target_long)imm; /* Sign extend to 32/64 bits */
1283 const char *opn = "imm arith";
1285 if (rt == 0 && opc != OPC_ADDI && opc != OPC_DADDI) {
1286 /* If no destination, treat it as a NOP.
1287 For addi, we must generate the overflow exception when needed. */
1288 MIPS_DEBUG("NOP");
1289 return;
1291 switch (opc) {
1292 case OPC_ADDI:
1294 TCGv t0 = tcg_temp_local_new();
1295 TCGv t1 = tcg_temp_new();
1296 TCGv t2 = tcg_temp_new();
1297 int l1 = gen_new_label();
1299 gen_load_gpr(t1, rs);
1300 tcg_gen_addi_tl(t0, t1, uimm);
1301 tcg_gen_ext32s_tl(t0, t0);
1303 tcg_gen_xori_tl(t1, t1, ~uimm);
1304 tcg_gen_xori_tl(t2, t0, uimm);
1305 tcg_gen_and_tl(t1, t1, t2);
1306 tcg_temp_free(t2);
1307 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
1308 tcg_temp_free(t1);
1309 /* operands of same sign, result different sign */
1310 generate_exception(ctx, EXCP_OVERFLOW);
1311 gen_set_label(l1);
1312 tcg_gen_ext32s_tl(t0, t0);
1313 gen_store_gpr(t0, rt);
1314 tcg_temp_free(t0);
1316 opn = "addi";
1317 break;
1318 case OPC_ADDIU:
1319 if (rs != 0) {
1320 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
1321 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
1322 } else {
1323 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
1325 opn = "addiu";
1326 break;
1327 #if defined(TARGET_MIPS64)
1328 case OPC_DADDI:
1330 TCGv t0 = tcg_temp_local_new();
1331 TCGv t1 = tcg_temp_new();
1332 TCGv t2 = tcg_temp_new();
1333 int l1 = gen_new_label();
1335 gen_load_gpr(t1, rs);
1336 tcg_gen_addi_tl(t0, t1, uimm);
1338 tcg_gen_xori_tl(t1, t1, ~uimm);
1339 tcg_gen_xori_tl(t2, t0, uimm);
1340 tcg_gen_and_tl(t1, t1, t2);
1341 tcg_temp_free(t2);
1342 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
1343 tcg_temp_free(t1);
1344 /* operands of same sign, result different sign */
1345 generate_exception(ctx, EXCP_OVERFLOW);
1346 gen_set_label(l1);
1347 gen_store_gpr(t0, rt);
1348 tcg_temp_free(t0);
1350 opn = "daddi";
1351 break;
1352 case OPC_DADDIU:
1353 if (rs != 0) {
1354 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
1355 } else {
1356 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
1358 opn = "daddiu";
1359 break;
1360 #endif
1362 MIPS_DEBUG("%s %s, %s, " TARGET_FMT_lx, opn, regnames[rt], regnames[rs], uimm);
1365 /* Logic with immediate operand */
1366 static void gen_logic_imm (CPUState *env, uint32_t opc, int rt, int rs, int16_t imm)
1368 target_ulong uimm;
1369 const char *opn = "imm logic";
1371 if (rt == 0) {
1372 /* If no destination, treat it as a NOP. */
1373 MIPS_DEBUG("NOP");
1374 return;
1376 uimm = (uint16_t)imm;
1377 switch (opc) {
1378 case OPC_ANDI:
1379 if (likely(rs != 0))
1380 tcg_gen_andi_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
1381 else
1382 tcg_gen_movi_tl(cpu_gpr[rt], 0);
1383 opn = "andi";
1384 break;
1385 case OPC_ORI:
1386 if (rs != 0)
1387 tcg_gen_ori_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
1388 else
1389 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
1390 opn = "ori";
1391 break;
1392 case OPC_XORI:
1393 if (likely(rs != 0))
1394 tcg_gen_xori_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
1395 else
1396 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
1397 opn = "xori";
1398 break;
1399 case OPC_LUI:
1400 tcg_gen_movi_tl(cpu_gpr[rt], imm << 16);
1401 opn = "lui";
1402 break;
1404 MIPS_DEBUG("%s %s, %s, " TARGET_FMT_lx, opn, regnames[rt], regnames[rs], uimm);
1407 /* Set on less than with immediate operand */
1408 static void gen_slt_imm (CPUState *env, uint32_t opc, int rt, int rs, int16_t imm)
1410 target_ulong uimm = (target_long)imm; /* Sign extend to 32/64 bits */
1411 const char *opn = "imm arith";
1412 TCGv t0;
1414 if (rt == 0) {
1415 /* If no destination, treat it as a NOP. */
1416 MIPS_DEBUG("NOP");
1417 return;
1419 t0 = tcg_temp_new();
1420 gen_load_gpr(t0, rs);
1421 switch (opc) {
1422 case OPC_SLTI:
1423 gen_op_lti(cpu_gpr[rt], t0, uimm);
1424 opn = "slti";
1425 break;
1426 case OPC_SLTIU:
1427 gen_op_ltiu(cpu_gpr[rt], t0, uimm);
1428 opn = "sltiu";
1429 break;
1431 MIPS_DEBUG("%s %s, %s, " TARGET_FMT_lx, opn, regnames[rt], regnames[rs], uimm);
1432 tcg_temp_free(t0);
1435 /* Shifts with immediate operand */
1436 static void gen_shift_imm(CPUState *env, DisasContext *ctx, uint32_t opc,
1437 int rt, int rs, int16_t imm)
1439 target_ulong uimm = ((uint16_t)imm) & 0x1f;
1440 const char *opn = "imm shift";
1441 TCGv t0;
1443 if (rt == 0) {
1444 /* If no destination, treat it as a NOP. */
1445 MIPS_DEBUG("NOP");
1446 return;
1449 t0 = tcg_temp_new();
1450 gen_load_gpr(t0, rs);
1451 switch (opc) {
1452 case OPC_SLL:
1453 tcg_gen_shli_tl(t0, t0, uimm);
1454 tcg_gen_ext32s_tl(cpu_gpr[rt], t0);
1455 opn = "sll";
1456 break;
1457 case OPC_SRA:
1458 tcg_gen_ext32s_tl(t0, t0);
1459 tcg_gen_sari_tl(cpu_gpr[rt], t0, uimm);
1460 opn = "sra";
1461 break;
1462 case OPC_SRL:
1463 if (uimm != 0) {
1464 tcg_gen_ext32u_tl(t0, t0);
1465 tcg_gen_shri_tl(cpu_gpr[rt], t0, uimm);
1466 } else {
1467 tcg_gen_ext32s_tl(cpu_gpr[rt], t0);
1469 opn = "srl";
1470 break;
1471 case OPC_ROTR:
1472 if (uimm != 0) {
1473 TCGv_i32 t1 = tcg_temp_new_i32();
1475 tcg_gen_trunc_tl_i32(t1, t0);
1476 tcg_gen_rotri_i32(t1, t1, uimm);
1477 tcg_gen_ext_i32_tl(cpu_gpr[rt], t1);
1478 tcg_temp_free_i32(t1);
1480 opn = "rotr";
1481 break;
1482 #if defined(TARGET_MIPS64)
1483 case OPC_DSLL:
1484 tcg_gen_shli_tl(cpu_gpr[rt], t0, uimm);
1485 opn = "dsll";
1486 break;
1487 case OPC_DSRA:
1488 tcg_gen_sari_tl(cpu_gpr[rt], t0, uimm);
1489 opn = "dsra";
1490 break;
1491 case OPC_DSRL:
1492 tcg_gen_shri_tl(cpu_gpr[rt], t0, uimm);
1493 opn = "dsrl";
1494 break;
1495 case OPC_DROTR:
1496 if (uimm != 0) {
1497 tcg_gen_rotri_tl(cpu_gpr[rt], t0, uimm);
1499 opn = "drotr";
1500 break;
1501 case OPC_DSLL32:
1502 tcg_gen_shli_tl(cpu_gpr[rt], t0, uimm + 32);
1503 opn = "dsll32";
1504 break;
1505 case OPC_DSRA32:
1506 tcg_gen_sari_tl(cpu_gpr[rt], t0, uimm + 32);
1507 opn = "dsra32";
1508 break;
1509 case OPC_DSRL32:
1510 tcg_gen_shri_tl(cpu_gpr[rt], t0, uimm + 32);
1511 opn = "dsrl32";
1512 break;
1513 case OPC_DROTR32:
1514 tcg_gen_rotri_tl(cpu_gpr[rt], t0, uimm + 32);
1515 opn = "drotr32";
1516 break;
1517 #endif
1519 MIPS_DEBUG("%s %s, %s, " TARGET_FMT_lx, opn, regnames[rt], regnames[rs], uimm);
1520 tcg_temp_free(t0);
1523 /* Arithmetic */
1524 static void gen_arith (CPUState *env, DisasContext *ctx, uint32_t opc,
1525 int rd, int rs, int rt)
1527 const char *opn = "arith";
1529 if (rd == 0 && opc != OPC_ADD && opc != OPC_SUB
1530 && opc != OPC_DADD && opc != OPC_DSUB) {
1531 /* If no destination, treat it as a NOP.
1532 For add & sub, we must generate the overflow exception when needed. */
1533 MIPS_DEBUG("NOP");
1534 return;
1537 switch (opc) {
1538 case OPC_ADD:
1540 TCGv t0 = tcg_temp_local_new();
1541 TCGv t1 = tcg_temp_new();
1542 TCGv t2 = tcg_temp_new();
1543 int l1 = gen_new_label();
1545 gen_load_gpr(t1, rs);
1546 gen_load_gpr(t2, rt);
1547 tcg_gen_add_tl(t0, t1, t2);
1548 tcg_gen_ext32s_tl(t0, t0);
1549 tcg_gen_xor_tl(t1, t1, t2);
1550 tcg_gen_not_tl(t1, t1);
1551 tcg_gen_xor_tl(t2, t0, t2);
1552 tcg_gen_and_tl(t1, t1, t2);
1553 tcg_temp_free(t2);
1554 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
1555 tcg_temp_free(t1);
1556 /* operands of same sign, result different sign */
1557 generate_exception(ctx, EXCP_OVERFLOW);
1558 gen_set_label(l1);
1559 gen_store_gpr(t0, rd);
1560 tcg_temp_free(t0);
1562 opn = "add";
1563 break;
1564 case OPC_ADDU:
1565 if (rs != 0 && rt != 0) {
1566 tcg_gen_add_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
1567 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
1568 } else if (rs == 0 && rt != 0) {
1569 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
1570 } else if (rs != 0 && rt == 0) {
1571 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
1572 } else {
1573 tcg_gen_movi_tl(cpu_gpr[rd], 0);
1575 opn = "addu";
1576 break;
1577 case OPC_SUB:
1579 TCGv t0 = tcg_temp_local_new();
1580 TCGv t1 = tcg_temp_new();
1581 TCGv t2 = tcg_temp_new();
1582 int l1 = gen_new_label();
1584 gen_load_gpr(t1, rs);
1585 gen_load_gpr(t2, rt);
1586 tcg_gen_sub_tl(t0, t1, t2);
1587 tcg_gen_ext32s_tl(t0, t0);
1588 tcg_gen_xor_tl(t2, t1, t2);
1589 tcg_gen_xor_tl(t1, t0, t1);
1590 tcg_gen_and_tl(t1, t1, t2);
1591 tcg_temp_free(t2);
1592 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
1593 tcg_temp_free(t1);
1594 /* operands of different sign, first operand and result different sign */
1595 generate_exception(ctx, EXCP_OVERFLOW);
1596 gen_set_label(l1);
1597 gen_store_gpr(t0, rd);
1598 tcg_temp_free(t0);
1600 opn = "sub";
1601 break;
1602 case OPC_SUBU:
1603 if (rs != 0 && rt != 0) {
1604 tcg_gen_sub_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
1605 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
1606 } else if (rs == 0 && rt != 0) {
1607 tcg_gen_neg_tl(cpu_gpr[rd], cpu_gpr[rt]);
1608 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
1609 } else if (rs != 0 && rt == 0) {
1610 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
1611 } else {
1612 tcg_gen_movi_tl(cpu_gpr[rd], 0);
1614 opn = "subu";
1615 break;
1616 #if defined(TARGET_MIPS64)
1617 case OPC_DADD:
1619 TCGv t0 = tcg_temp_local_new();
1620 TCGv t1 = tcg_temp_new();
1621 TCGv t2 = tcg_temp_new();
1622 int l1 = gen_new_label();
1624 gen_load_gpr(t1, rs);
1625 gen_load_gpr(t2, rt);
1626 tcg_gen_add_tl(t0, t1, t2);
1627 tcg_gen_xor_tl(t1, t1, t2);
1628 tcg_gen_not_tl(t1, t1);
1629 tcg_gen_xor_tl(t2, t0, t2);
1630 tcg_gen_and_tl(t1, t1, t2);
1631 tcg_temp_free(t2);
1632 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
1633 tcg_temp_free(t1);
1634 /* operands of same sign, result different sign */
1635 generate_exception(ctx, EXCP_OVERFLOW);
1636 gen_set_label(l1);
1637 gen_store_gpr(t0, rd);
1638 tcg_temp_free(t0);
1640 opn = "dadd";
1641 break;
1642 case OPC_DADDU:
1643 if (rs != 0 && rt != 0) {
1644 tcg_gen_add_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
1645 } else if (rs == 0 && rt != 0) {
1646 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
1647 } else if (rs != 0 && rt == 0) {
1648 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
1649 } else {
1650 tcg_gen_movi_tl(cpu_gpr[rd], 0);
1652 opn = "daddu";
1653 break;
1654 case OPC_DSUB:
1656 TCGv t0 = tcg_temp_local_new();
1657 TCGv t1 = tcg_temp_new();
1658 TCGv t2 = tcg_temp_new();
1659 int l1 = gen_new_label();
1661 gen_load_gpr(t1, rs);
1662 gen_load_gpr(t2, rt);
1663 tcg_gen_sub_tl(t0, t1, t2);
1664 tcg_gen_xor_tl(t2, t1, t2);
1665 tcg_gen_xor_tl(t1, t0, t1);
1666 tcg_gen_and_tl(t1, t1, t2);
1667 tcg_temp_free(t2);
1668 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
1669 tcg_temp_free(t1);
1670 /* operands of different sign, first operand and result different sign */
1671 generate_exception(ctx, EXCP_OVERFLOW);
1672 gen_set_label(l1);
1673 gen_store_gpr(t0, rd);
1674 tcg_temp_free(t0);
1676 opn = "dsub";
1677 break;
1678 case OPC_DSUBU:
1679 if (rs != 0 && rt != 0) {
1680 tcg_gen_sub_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
1681 } else if (rs == 0 && rt != 0) {
1682 tcg_gen_neg_tl(cpu_gpr[rd], cpu_gpr[rt]);
1683 } else if (rs != 0 && rt == 0) {
1684 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
1685 } else {
1686 tcg_gen_movi_tl(cpu_gpr[rd], 0);
1688 opn = "dsubu";
1689 break;
1690 #endif
1691 case OPC_MUL:
1692 if (likely(rs != 0 && rt != 0)) {
1693 tcg_gen_mul_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
1694 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
1695 } else {
1696 tcg_gen_movi_tl(cpu_gpr[rd], 0);
1698 opn = "mul";
1699 break;
1701 MIPS_DEBUG("%s %s, %s, %s", opn, regnames[rd], regnames[rs], regnames[rt]);
1704 /* Conditional move */
1705 static void gen_cond_move (CPUState *env, uint32_t opc, int rd, int rs, int rt)
1707 const char *opn = "cond move";
1708 int l1;
1710 if (rd == 0) {
1711 /* If no destination, treat it as a NOP.
1712 For add & sub, we must generate the overflow exception when needed. */
1713 MIPS_DEBUG("NOP");
1714 return;
1717 l1 = gen_new_label();
1718 switch (opc) {
1719 case OPC_MOVN:
1720 if (likely(rt != 0))
1721 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[rt], 0, l1);
1722 else
1723 tcg_gen_br(l1);
1724 opn = "movn";
1725 break;
1726 case OPC_MOVZ:
1727 if (likely(rt != 0))
1728 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[rt], 0, l1);
1729 opn = "movz";
1730 break;
1732 if (rs != 0)
1733 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
1734 else
1735 tcg_gen_movi_tl(cpu_gpr[rd], 0);
1736 gen_set_label(l1);
1738 MIPS_DEBUG("%s %s, %s, %s", opn, regnames[rd], regnames[rs], regnames[rt]);
1741 /* Logic */
1742 static void gen_logic (CPUState *env, uint32_t opc, int rd, int rs, int rt)
1744 const char *opn = "logic";
1746 if (rd == 0) {
1747 /* If no destination, treat it as a NOP. */
1748 MIPS_DEBUG("NOP");
1749 return;
1752 switch (opc) {
1753 case OPC_AND:
1754 if (likely(rs != 0 && rt != 0)) {
1755 tcg_gen_and_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
1756 } else {
1757 tcg_gen_movi_tl(cpu_gpr[rd], 0);
1759 opn = "and";
1760 break;
1761 case OPC_NOR:
1762 if (rs != 0 && rt != 0) {
1763 tcg_gen_nor_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
1764 } else if (rs == 0 && rt != 0) {
1765 tcg_gen_not_tl(cpu_gpr[rd], cpu_gpr[rt]);
1766 } else if (rs != 0 && rt == 0) {
1767 tcg_gen_not_tl(cpu_gpr[rd], cpu_gpr[rs]);
1768 } else {
1769 tcg_gen_movi_tl(cpu_gpr[rd], ~((target_ulong)0));
1771 opn = "nor";
1772 break;
1773 case OPC_OR:
1774 if (likely(rs != 0 && rt != 0)) {
1775 tcg_gen_or_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
1776 } else if (rs == 0 && rt != 0) {
1777 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
1778 } else if (rs != 0 && rt == 0) {
1779 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
1780 } else {
1781 tcg_gen_movi_tl(cpu_gpr[rd], 0);
1783 opn = "or";
1784 break;
1785 case OPC_XOR:
1786 if (likely(rs != 0 && rt != 0)) {
1787 tcg_gen_xor_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
1788 } else if (rs == 0 && rt != 0) {
1789 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
1790 } else if (rs != 0 && rt == 0) {
1791 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
1792 } else {
1793 tcg_gen_movi_tl(cpu_gpr[rd], 0);
1795 opn = "xor";
1796 break;
1798 MIPS_DEBUG("%s %s, %s, %s", opn, regnames[rd], regnames[rs], regnames[rt]);
1801 /* Set on lower than */
1802 static void gen_slt (CPUState *env, uint32_t opc, int rd, int rs, int rt)
1804 const char *opn = "slt";
1805 TCGv t0, t1;
1807 if (rd == 0) {
1808 /* If no destination, treat it as a NOP. */
1809 MIPS_DEBUG("NOP");
1810 return;
1813 t0 = tcg_temp_new();
1814 t1 = tcg_temp_new();
1815 gen_load_gpr(t0, rs);
1816 gen_load_gpr(t1, rt);
1817 switch (opc) {
1818 case OPC_SLT:
1819 gen_op_lt(cpu_gpr[rd], t0, t1);
1820 opn = "slt";
1821 break;
1822 case OPC_SLTU:
1823 gen_op_ltu(cpu_gpr[rd], t0, t1);
1824 opn = "sltu";
1825 break;
1827 MIPS_DEBUG("%s %s, %s, %s", opn, regnames[rd], regnames[rs], regnames[rt]);
1828 tcg_temp_free(t0);
1829 tcg_temp_free(t1);
1832 /* Shifts */
1833 static void gen_shift (CPUState *env, DisasContext *ctx, uint32_t opc,
1834 int rd, int rs, int rt)
1836 const char *opn = "shifts";
1837 TCGv t0, t1;
1839 if (rd == 0) {
1840 /* If no destination, treat it as a NOP.
1841 For add & sub, we must generate the overflow exception when needed. */
1842 MIPS_DEBUG("NOP");
1843 return;
1846 t0 = tcg_temp_new();
1847 t1 = tcg_temp_new();
1848 gen_load_gpr(t0, rs);
1849 gen_load_gpr(t1, rt);
1850 switch (opc) {
1851 case OPC_SLLV:
1852 tcg_gen_andi_tl(t0, t0, 0x1f);
1853 tcg_gen_shl_tl(t0, t1, t0);
1854 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
1855 opn = "sllv";
1856 break;
1857 case OPC_SRAV:
1858 tcg_gen_ext32s_tl(t1, t1);
1859 tcg_gen_andi_tl(t0, t0, 0x1f);
1860 tcg_gen_sar_tl(cpu_gpr[rd], t1, t0);
1861 opn = "srav";
1862 break;
1863 case OPC_SRLV:
1864 tcg_gen_ext32u_tl(t1, t1);
1865 tcg_gen_andi_tl(t0, t0, 0x1f);
1866 tcg_gen_shr_tl(t0, t1, t0);
1867 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
1868 opn = "srlv";
1869 break;
1870 case OPC_ROTRV:
1872 TCGv_i32 t2 = tcg_temp_new_i32();
1873 TCGv_i32 t3 = tcg_temp_new_i32();
1875 tcg_gen_trunc_tl_i32(t2, t0);
1876 tcg_gen_trunc_tl_i32(t3, t1);
1877 tcg_gen_andi_i32(t2, t2, 0x1f);
1878 tcg_gen_rotr_i32(t2, t3, t2);
1879 tcg_gen_ext_i32_tl(cpu_gpr[rd], t2);
1880 tcg_temp_free_i32(t2);
1881 tcg_temp_free_i32(t3);
1882 opn = "rotrv";
1884 break;
1885 #if defined(TARGET_MIPS64)
1886 case OPC_DSLLV:
1887 tcg_gen_andi_tl(t0, t0, 0x3f);
1888 tcg_gen_shl_tl(cpu_gpr[rd], t1, t0);
1889 opn = "dsllv";
1890 break;
1891 case OPC_DSRAV:
1892 tcg_gen_andi_tl(t0, t0, 0x3f);
1893 tcg_gen_sar_tl(cpu_gpr[rd], t1, t0);
1894 opn = "dsrav";
1895 break;
1896 case OPC_DSRLV:
1897 tcg_gen_andi_tl(t0, t0, 0x3f);
1898 tcg_gen_shr_tl(cpu_gpr[rd], t1, t0);
1899 opn = "dsrlv";
1900 break;
1901 case OPC_DROTRV:
1902 tcg_gen_andi_tl(t0, t0, 0x3f);
1903 tcg_gen_rotr_tl(cpu_gpr[rd], t1, t0);
1904 opn = "drotrv";
1905 break;
1906 #endif
1908 MIPS_DEBUG("%s %s, %s, %s", opn, regnames[rd], regnames[rs], regnames[rt]);
1909 tcg_temp_free(t0);
1910 tcg_temp_free(t1);
1913 /* Arithmetic on HI/LO registers */
1914 static void gen_HILO (DisasContext *ctx, uint32_t opc, int reg)
1916 const char *opn = "hilo";
1918 if (reg == 0 && (opc == OPC_MFHI || opc == OPC_MFLO)) {
1919 /* Treat as NOP. */
1920 MIPS_DEBUG("NOP");
1921 return;
1923 switch (opc) {
1924 case OPC_MFHI:
1925 tcg_gen_mov_tl(cpu_gpr[reg], cpu_HI[0]);
1926 opn = "mfhi";
1927 break;
1928 case OPC_MFLO:
1929 tcg_gen_mov_tl(cpu_gpr[reg], cpu_LO[0]);
1930 opn = "mflo";
1931 break;
1932 case OPC_MTHI:
1933 if (reg != 0)
1934 tcg_gen_mov_tl(cpu_HI[0], cpu_gpr[reg]);
1935 else
1936 tcg_gen_movi_tl(cpu_HI[0], 0);
1937 opn = "mthi";
1938 break;
1939 case OPC_MTLO:
1940 if (reg != 0)
1941 tcg_gen_mov_tl(cpu_LO[0], cpu_gpr[reg]);
1942 else
1943 tcg_gen_movi_tl(cpu_LO[0], 0);
1944 opn = "mtlo";
1945 break;
1947 MIPS_DEBUG("%s %s", opn, regnames[reg]);
1950 static void gen_muldiv (DisasContext *ctx, uint32_t opc,
1951 int rs, int rt)
1953 const char *opn = "mul/div";
1954 TCGv t0, t1;
1956 switch (opc) {
1957 case OPC_DIV:
1958 case OPC_DIVU:
1959 #if defined(TARGET_MIPS64)
1960 case OPC_DDIV:
1961 case OPC_DDIVU:
1962 #endif
1963 t0 = tcg_temp_local_new();
1964 t1 = tcg_temp_local_new();
1965 break;
1966 default:
1967 t0 = tcg_temp_new();
1968 t1 = tcg_temp_new();
1969 break;
1972 gen_load_gpr(t0, rs);
1973 gen_load_gpr(t1, rt);
1974 switch (opc) {
1975 case OPC_DIV:
1977 int l1 = gen_new_label();
1978 int l2 = gen_new_label();
1980 tcg_gen_ext32s_tl(t0, t0);
1981 tcg_gen_ext32s_tl(t1, t1);
1982 tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
1983 tcg_gen_brcondi_tl(TCG_COND_NE, t0, INT_MIN, l2);
1984 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1, l2);
1986 tcg_gen_mov_tl(cpu_LO[0], t0);
1987 tcg_gen_movi_tl(cpu_HI[0], 0);
1988 tcg_gen_br(l1);
1989 gen_set_label(l2);
1990 tcg_gen_div_tl(cpu_LO[0], t0, t1);
1991 tcg_gen_rem_tl(cpu_HI[0], t0, t1);
1992 tcg_gen_ext32s_tl(cpu_LO[0], cpu_LO[0]);
1993 tcg_gen_ext32s_tl(cpu_HI[0], cpu_HI[0]);
1994 gen_set_label(l1);
1996 opn = "div";
1997 break;
1998 case OPC_DIVU:
2000 int l1 = gen_new_label();
2002 tcg_gen_ext32u_tl(t0, t0);
2003 tcg_gen_ext32u_tl(t1, t1);
2004 tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
2005 tcg_gen_divu_tl(cpu_LO[0], t0, t1);
2006 tcg_gen_remu_tl(cpu_HI[0], t0, t1);
2007 tcg_gen_ext32s_tl(cpu_LO[0], cpu_LO[0]);
2008 tcg_gen_ext32s_tl(cpu_HI[0], cpu_HI[0]);
2009 gen_set_label(l1);
2011 opn = "divu";
2012 break;
2013 case OPC_MULT:
2015 TCGv_i64 t2 = tcg_temp_new_i64();
2016 TCGv_i64 t3 = tcg_temp_new_i64();
2018 tcg_gen_ext_tl_i64(t2, t0);
2019 tcg_gen_ext_tl_i64(t3, t1);
2020 tcg_gen_mul_i64(t2, t2, t3);
2021 tcg_temp_free_i64(t3);
2022 tcg_gen_trunc_i64_tl(t0, t2);
2023 tcg_gen_shri_i64(t2, t2, 32);
2024 tcg_gen_trunc_i64_tl(t1, t2);
2025 tcg_temp_free_i64(t2);
2026 tcg_gen_ext32s_tl(cpu_LO[0], t0);
2027 tcg_gen_ext32s_tl(cpu_HI[0], t1);
2029 opn = "mult";
2030 break;
2031 case OPC_MULTU:
2033 TCGv_i64 t2 = tcg_temp_new_i64();
2034 TCGv_i64 t3 = tcg_temp_new_i64();
2036 tcg_gen_ext32u_tl(t0, t0);
2037 tcg_gen_ext32u_tl(t1, t1);
2038 tcg_gen_extu_tl_i64(t2, t0);
2039 tcg_gen_extu_tl_i64(t3, t1);
2040 tcg_gen_mul_i64(t2, t2, t3);
2041 tcg_temp_free_i64(t3);
2042 tcg_gen_trunc_i64_tl(t0, t2);
2043 tcg_gen_shri_i64(t2, t2, 32);
2044 tcg_gen_trunc_i64_tl(t1, t2);
2045 tcg_temp_free_i64(t2);
2046 tcg_gen_ext32s_tl(cpu_LO[0], t0);
2047 tcg_gen_ext32s_tl(cpu_HI[0], t1);
2049 opn = "multu";
2050 break;
2051 #if defined(TARGET_MIPS64)
2052 case OPC_DDIV:
2054 int l1 = gen_new_label();
2055 int l2 = gen_new_label();
2057 tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
2058 tcg_gen_brcondi_tl(TCG_COND_NE, t0, -1LL << 63, l2);
2059 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1LL, l2);
2060 tcg_gen_mov_tl(cpu_LO[0], t0);
2061 tcg_gen_movi_tl(cpu_HI[0], 0);
2062 tcg_gen_br(l1);
2063 gen_set_label(l2);
2064 tcg_gen_div_i64(cpu_LO[0], t0, t1);
2065 tcg_gen_rem_i64(cpu_HI[0], t0, t1);
2066 gen_set_label(l1);
2068 opn = "ddiv";
2069 break;
2070 case OPC_DDIVU:
2072 int l1 = gen_new_label();
2074 tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
2075 tcg_gen_divu_i64(cpu_LO[0], t0, t1);
2076 tcg_gen_remu_i64(cpu_HI[0], t0, t1);
2077 gen_set_label(l1);
2079 opn = "ddivu";
2080 break;
2081 case OPC_DMULT:
2082 gen_helper_dmult(t0, t1);
2083 opn = "dmult";
2084 break;
2085 case OPC_DMULTU:
2086 gen_helper_dmultu(t0, t1);
2087 opn = "dmultu";
2088 break;
2089 #endif
2090 case OPC_MADD:
2092 TCGv_i64 t2 = tcg_temp_new_i64();
2093 TCGv_i64 t3 = tcg_temp_new_i64();
2095 tcg_gen_ext_tl_i64(t2, t0);
2096 tcg_gen_ext_tl_i64(t3, t1);
2097 tcg_gen_mul_i64(t2, t2, t3);
2098 tcg_gen_concat_tl_i64(t3, cpu_LO[0], cpu_HI[0]);
2099 tcg_gen_add_i64(t2, t2, t3);
2100 tcg_temp_free_i64(t3);
2101 tcg_gen_trunc_i64_tl(t0, t2);
2102 tcg_gen_shri_i64(t2, t2, 32);
2103 tcg_gen_trunc_i64_tl(t1, t2);
2104 tcg_temp_free_i64(t2);
2105 tcg_gen_ext32s_tl(cpu_LO[0], t0);
2106 tcg_gen_ext32s_tl(cpu_HI[0], t1);
2108 opn = "madd";
2109 break;
2110 case OPC_MADDU:
2112 TCGv_i64 t2 = tcg_temp_new_i64();
2113 TCGv_i64 t3 = tcg_temp_new_i64();
2115 tcg_gen_ext32u_tl(t0, t0);
2116 tcg_gen_ext32u_tl(t1, t1);
2117 tcg_gen_extu_tl_i64(t2, t0);
2118 tcg_gen_extu_tl_i64(t3, t1);
2119 tcg_gen_mul_i64(t2, t2, t3);
2120 tcg_gen_concat_tl_i64(t3, cpu_LO[0], cpu_HI[0]);
2121 tcg_gen_add_i64(t2, t2, t3);
2122 tcg_temp_free_i64(t3);
2123 tcg_gen_trunc_i64_tl(t0, t2);
2124 tcg_gen_shri_i64(t2, t2, 32);
2125 tcg_gen_trunc_i64_tl(t1, t2);
2126 tcg_temp_free_i64(t2);
2127 tcg_gen_ext32s_tl(cpu_LO[0], t0);
2128 tcg_gen_ext32s_tl(cpu_HI[0], t1);
2130 opn = "maddu";
2131 break;
2132 case OPC_MSUB:
2134 TCGv_i64 t2 = tcg_temp_new_i64();
2135 TCGv_i64 t3 = tcg_temp_new_i64();
2137 tcg_gen_ext_tl_i64(t2, t0);
2138 tcg_gen_ext_tl_i64(t3, t1);
2139 tcg_gen_mul_i64(t2, t2, t3);
2140 tcg_gen_concat_tl_i64(t3, cpu_LO[0], cpu_HI[0]);
2141 tcg_gen_sub_i64(t2, t3, t2);
2142 tcg_temp_free_i64(t3);
2143 tcg_gen_trunc_i64_tl(t0, t2);
2144 tcg_gen_shri_i64(t2, t2, 32);
2145 tcg_gen_trunc_i64_tl(t1, t2);
2146 tcg_temp_free_i64(t2);
2147 tcg_gen_ext32s_tl(cpu_LO[0], t0);
2148 tcg_gen_ext32s_tl(cpu_HI[0], t1);
2150 opn = "msub";
2151 break;
2152 case OPC_MSUBU:
2154 TCGv_i64 t2 = tcg_temp_new_i64();
2155 TCGv_i64 t3 = tcg_temp_new_i64();
2157 tcg_gen_ext32u_tl(t0, t0);
2158 tcg_gen_ext32u_tl(t1, t1);
2159 tcg_gen_extu_tl_i64(t2, t0);
2160 tcg_gen_extu_tl_i64(t3, t1);
2161 tcg_gen_mul_i64(t2, t2, t3);
2162 tcg_gen_concat_tl_i64(t3, cpu_LO[0], cpu_HI[0]);
2163 tcg_gen_sub_i64(t2, t3, t2);
2164 tcg_temp_free_i64(t3);
2165 tcg_gen_trunc_i64_tl(t0, t2);
2166 tcg_gen_shri_i64(t2, t2, 32);
2167 tcg_gen_trunc_i64_tl(t1, t2);
2168 tcg_temp_free_i64(t2);
2169 tcg_gen_ext32s_tl(cpu_LO[0], t0);
2170 tcg_gen_ext32s_tl(cpu_HI[0], t1);
2172 opn = "msubu";
2173 break;
2174 default:
2175 MIPS_INVAL(opn);
2176 generate_exception(ctx, EXCP_RI);
2177 goto out;
2179 MIPS_DEBUG("%s %s %s", opn, regnames[rs], regnames[rt]);
2180 out:
2181 tcg_temp_free(t0);
2182 tcg_temp_free(t1);
2185 static void gen_mul_vr54xx (DisasContext *ctx, uint32_t opc,
2186 int rd, int rs, int rt)
2188 const char *opn = "mul vr54xx";
2189 TCGv t0 = tcg_temp_new();
2190 TCGv t1 = tcg_temp_new();
2192 gen_load_gpr(t0, rs);
2193 gen_load_gpr(t1, rt);
2195 switch (opc) {
2196 case OPC_VR54XX_MULS:
2197 gen_helper_muls(t0, t0, t1);
2198 opn = "muls";
2199 break;
2200 case OPC_VR54XX_MULSU:
2201 gen_helper_mulsu(t0, t0, t1);
2202 opn = "mulsu";
2203 break;
2204 case OPC_VR54XX_MACC:
2205 gen_helper_macc(t0, t0, t1);
2206 opn = "macc";
2207 break;
2208 case OPC_VR54XX_MACCU:
2209 gen_helper_maccu(t0, t0, t1);
2210 opn = "maccu";
2211 break;
2212 case OPC_VR54XX_MSAC:
2213 gen_helper_msac(t0, t0, t1);
2214 opn = "msac";
2215 break;
2216 case OPC_VR54XX_MSACU:
2217 gen_helper_msacu(t0, t0, t1);
2218 opn = "msacu";
2219 break;
2220 case OPC_VR54XX_MULHI:
2221 gen_helper_mulhi(t0, t0, t1);
2222 opn = "mulhi";
2223 break;
2224 case OPC_VR54XX_MULHIU:
2225 gen_helper_mulhiu(t0, t0, t1);
2226 opn = "mulhiu";
2227 break;
2228 case OPC_VR54XX_MULSHI:
2229 gen_helper_mulshi(t0, t0, t1);
2230 opn = "mulshi";
2231 break;
2232 case OPC_VR54XX_MULSHIU:
2233 gen_helper_mulshiu(t0, t0, t1);
2234 opn = "mulshiu";
2235 break;
2236 case OPC_VR54XX_MACCHI:
2237 gen_helper_macchi(t0, t0, t1);
2238 opn = "macchi";
2239 break;
2240 case OPC_VR54XX_MACCHIU:
2241 gen_helper_macchiu(t0, t0, t1);
2242 opn = "macchiu";
2243 break;
2244 case OPC_VR54XX_MSACHI:
2245 gen_helper_msachi(t0, t0, t1);
2246 opn = "msachi";
2247 break;
2248 case OPC_VR54XX_MSACHIU:
2249 gen_helper_msachiu(t0, t0, t1);
2250 opn = "msachiu";
2251 break;
2252 default:
2253 MIPS_INVAL("mul vr54xx");
2254 generate_exception(ctx, EXCP_RI);
2255 goto out;
2257 gen_store_gpr(t0, rd);
2258 MIPS_DEBUG("%s %s, %s, %s", opn, regnames[rd], regnames[rs], regnames[rt]);
2260 out:
2261 tcg_temp_free(t0);
2262 tcg_temp_free(t1);
2265 static void gen_cl (DisasContext *ctx, uint32_t opc,
2266 int rd, int rs)
2268 const char *opn = "CLx";
2269 TCGv t0;
2271 if (rd == 0) {
2272 /* Treat as NOP. */
2273 MIPS_DEBUG("NOP");
2274 return;
2276 t0 = tcg_temp_new();
2277 gen_load_gpr(t0, rs);
2278 switch (opc) {
2279 case OPC_CLO:
2280 gen_helper_clo(cpu_gpr[rd], t0);
2281 opn = "clo";
2282 break;
2283 case OPC_CLZ:
2284 gen_helper_clz(cpu_gpr[rd], t0);
2285 opn = "clz";
2286 break;
2287 #if defined(TARGET_MIPS64)
2288 case OPC_DCLO:
2289 gen_helper_dclo(cpu_gpr[rd], t0);
2290 opn = "dclo";
2291 break;
2292 case OPC_DCLZ:
2293 gen_helper_dclz(cpu_gpr[rd], t0);
2294 opn = "dclz";
2295 break;
2296 #endif
2298 MIPS_DEBUG("%s %s, %s", opn, regnames[rd], regnames[rs]);
2299 tcg_temp_free(t0);
2302 /* Traps */
2303 static void gen_trap (DisasContext *ctx, uint32_t opc,
2304 int rs, int rt, int16_t imm)
2306 int cond;
2307 TCGv t0 = tcg_temp_new();
2308 TCGv t1 = tcg_temp_new();
2310 cond = 0;
2311 /* Load needed operands */
2312 switch (opc) {
2313 case OPC_TEQ:
2314 case OPC_TGE:
2315 case OPC_TGEU:
2316 case OPC_TLT:
2317 case OPC_TLTU:
2318 case OPC_TNE:
2319 /* Compare two registers */
2320 if (rs != rt) {
2321 gen_load_gpr(t0, rs);
2322 gen_load_gpr(t1, rt);
2323 cond = 1;
2325 break;
2326 case OPC_TEQI:
2327 case OPC_TGEI:
2328 case OPC_TGEIU:
2329 case OPC_TLTI:
2330 case OPC_TLTIU:
2331 case OPC_TNEI:
2332 /* Compare register to immediate */
2333 if (rs != 0 || imm != 0) {
2334 gen_load_gpr(t0, rs);
2335 tcg_gen_movi_tl(t1, (int32_t)imm);
2336 cond = 1;
2338 break;
2340 if (cond == 0) {
2341 switch (opc) {
2342 case OPC_TEQ: /* rs == rs */
2343 case OPC_TEQI: /* r0 == 0 */
2344 case OPC_TGE: /* rs >= rs */
2345 case OPC_TGEI: /* r0 >= 0 */
2346 case OPC_TGEU: /* rs >= rs unsigned */
2347 case OPC_TGEIU: /* r0 >= 0 unsigned */
2348 /* Always trap */
2349 generate_exception(ctx, EXCP_TRAP);
2350 break;
2351 case OPC_TLT: /* rs < rs */
2352 case OPC_TLTI: /* r0 < 0 */
2353 case OPC_TLTU: /* rs < rs unsigned */
2354 case OPC_TLTIU: /* r0 < 0 unsigned */
2355 case OPC_TNE: /* rs != rs */
2356 case OPC_TNEI: /* r0 != 0 */
2357 /* Never trap: treat as NOP. */
2358 break;
2360 } else {
2361 int l1 = gen_new_label();
2363 switch (opc) {
2364 case OPC_TEQ:
2365 case OPC_TEQI:
2366 tcg_gen_brcond_tl(TCG_COND_NE, t0, t1, l1);
2367 break;
2368 case OPC_TGE:
2369 case OPC_TGEI:
2370 tcg_gen_brcond_tl(TCG_COND_LT, t0, t1, l1);
2371 break;
2372 case OPC_TGEU:
2373 case OPC_TGEIU:
2374 tcg_gen_brcond_tl(TCG_COND_LTU, t0, t1, l1);
2375 break;
2376 case OPC_TLT:
2377 case OPC_TLTI:
2378 tcg_gen_brcond_tl(TCG_COND_GE, t0, t1, l1);
2379 break;
2380 case OPC_TLTU:
2381 case OPC_TLTIU:
2382 tcg_gen_brcond_tl(TCG_COND_GEU, t0, t1, l1);
2383 break;
2384 case OPC_TNE:
2385 case OPC_TNEI:
2386 tcg_gen_brcond_tl(TCG_COND_EQ, t0, t1, l1);
2387 break;
2389 generate_exception(ctx, EXCP_TRAP);
2390 gen_set_label(l1);
2392 tcg_temp_free(t0);
2393 tcg_temp_free(t1);
2396 static inline void gen_goto_tb(DisasContext *ctx, int n, target_ulong dest)
2398 TranslationBlock *tb;
2399 tb = ctx->tb;
2400 if ((tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK) &&
2401 likely(!ctx->singlestep_enabled)) {
2402 tcg_gen_goto_tb(n);
2403 gen_save_pc(dest);
2404 tcg_gen_exit_tb((long)tb + n);
2405 } else {
2406 gen_save_pc(dest);
2407 if (ctx->singlestep_enabled) {
2408 save_cpu_state(ctx, 0);
2409 gen_helper_0i(raise_exception, EXCP_DEBUG);
2411 tcg_gen_exit_tb(0);
2415 /* Branches (before delay slot) */
2416 static void gen_compute_branch (DisasContext *ctx, uint32_t opc,
2417 int insn_bytes,
2418 int rs, int rt, int32_t offset)
2420 target_ulong btgt = -1;
2421 int blink = 0;
2422 int bcond_compute = 0;
2423 TCGv t0 = tcg_temp_new();
2424 TCGv t1 = tcg_temp_new();
2426 if (ctx->hflags & MIPS_HFLAG_BMASK) {
2427 #ifdef MIPS_DEBUG_DISAS
2428 LOG_DISAS("Branch in delay slot at PC 0x" TARGET_FMT_lx "\n", ctx->pc);
2429 #endif
2430 generate_exception(ctx, EXCP_RI);
2431 goto out;
2434 /* Load needed operands */
2435 switch (opc) {
2436 case OPC_BEQ:
2437 case OPC_BEQL:
2438 case OPC_BNE:
2439 case OPC_BNEL:
2440 /* Compare two registers */
2441 if (rs != rt) {
2442 gen_load_gpr(t0, rs);
2443 gen_load_gpr(t1, rt);
2444 bcond_compute = 1;
2446 btgt = ctx->pc + insn_bytes + offset;
2447 break;
2448 case OPC_BGEZ:
2449 case OPC_BGEZAL:
2450 case OPC_BGEZALL:
2451 case OPC_BGEZL:
2452 case OPC_BGTZ:
2453 case OPC_BGTZL:
2454 case OPC_BLEZ:
2455 case OPC_BLEZL:
2456 case OPC_BLTZ:
2457 case OPC_BLTZAL:
2458 case OPC_BLTZALL:
2459 case OPC_BLTZL:
2460 /* Compare to zero */
2461 if (rs != 0) {
2462 gen_load_gpr(t0, rs);
2463 bcond_compute = 1;
2465 btgt = ctx->pc + insn_bytes + offset;
2466 break;
2467 case OPC_J:
2468 case OPC_JAL:
2469 case OPC_JALX:
2470 /* Jump to immediate */
2471 btgt = ((ctx->pc + insn_bytes) & (int32_t)0xF0000000) | (uint32_t)offset;
2472 break;
2473 case OPC_JR:
2474 case OPC_JALR:
2475 case OPC_JALRC:
2476 /* Jump to register */
2477 if (offset != 0 && offset != 16) {
2478 /* Hint = 0 is JR/JALR, hint 16 is JR.HB/JALR.HB, the
2479 others are reserved. */
2480 MIPS_INVAL("jump hint");
2481 generate_exception(ctx, EXCP_RI);
2482 goto out;
2484 gen_load_gpr(btarget, rs);
2485 break;
2486 default:
2487 MIPS_INVAL("branch/jump");
2488 generate_exception(ctx, EXCP_RI);
2489 goto out;
2491 if (bcond_compute == 0) {
2492 /* No condition to be computed */
2493 switch (opc) {
2494 case OPC_BEQ: /* rx == rx */
2495 case OPC_BEQL: /* rx == rx likely */
2496 case OPC_BGEZ: /* 0 >= 0 */
2497 case OPC_BGEZL: /* 0 >= 0 likely */
2498 case OPC_BLEZ: /* 0 <= 0 */
2499 case OPC_BLEZL: /* 0 <= 0 likely */
2500 /* Always take */
2501 ctx->hflags |= MIPS_HFLAG_B;
2502 MIPS_DEBUG("balways");
2503 break;
2504 case OPC_BGEZAL: /* 0 >= 0 */
2505 case OPC_BGEZALL: /* 0 >= 0 likely */
2506 /* Always take and link */
2507 blink = 31;
2508 ctx->hflags |= MIPS_HFLAG_B;
2509 MIPS_DEBUG("balways and link");
2510 break;
2511 case OPC_BNE: /* rx != rx */
2512 case OPC_BGTZ: /* 0 > 0 */
2513 case OPC_BLTZ: /* 0 < 0 */
2514 /* Treat as NOP. */
2515 MIPS_DEBUG("bnever (NOP)");
2516 goto out;
2517 case OPC_BLTZAL: /* 0 < 0 */
2518 tcg_gen_movi_tl(cpu_gpr[31], ctx->pc + 8);
2519 MIPS_DEBUG("bnever and link");
2520 goto out;
2521 case OPC_BLTZALL: /* 0 < 0 likely */
2522 tcg_gen_movi_tl(cpu_gpr[31], ctx->pc + 8);
2523 /* Skip the instruction in the delay slot */
2524 MIPS_DEBUG("bnever, link and skip");
2525 ctx->pc += 4;
2526 goto out;
2527 case OPC_BNEL: /* rx != rx likely */
2528 case OPC_BGTZL: /* 0 > 0 likely */
2529 case OPC_BLTZL: /* 0 < 0 likely */
2530 /* Skip the instruction in the delay slot */
2531 MIPS_DEBUG("bnever and skip");
2532 ctx->pc += 4;
2533 goto out;
2534 case OPC_J:
2535 ctx->hflags |= MIPS_HFLAG_B;
2536 MIPS_DEBUG("j " TARGET_FMT_lx, btgt);
2537 break;
2538 case OPC_JALX:
2539 ctx->hflags |= MIPS_HFLAG_BX;
2540 /* Fallthrough */
2541 case OPC_JAL:
2542 blink = 31;
2543 ctx->hflags |= MIPS_HFLAG_B;
2544 ctx->hflags |= (ctx->hflags & MIPS_HFLAG_M16
2545 ? MIPS_HFLAG_BDS16
2546 : MIPS_HFLAG_BDS32);
2547 MIPS_DEBUG("jal " TARGET_FMT_lx, btgt);
2548 break;
2549 case OPC_JR:
2550 ctx->hflags |= MIPS_HFLAG_BR;
2551 if (ctx->hflags & MIPS_HFLAG_M16)
2552 ctx->hflags |= MIPS_HFLAG_BDS16;
2553 MIPS_DEBUG("jr %s", regnames[rs]);
2554 break;
2555 case OPC_JALR:
2556 case OPC_JALRC:
2557 blink = rt;
2558 ctx->hflags |= MIPS_HFLAG_BR;
2559 if (ctx->hflags & MIPS_HFLAG_M16)
2560 ctx->hflags |= MIPS_HFLAG_BDS16;
2561 MIPS_DEBUG("jalr %s, %s", regnames[rt], regnames[rs]);
2562 break;
2563 default:
2564 MIPS_INVAL("branch/jump");
2565 generate_exception(ctx, EXCP_RI);
2566 goto out;
2568 } else {
2569 switch (opc) {
2570 case OPC_BEQ:
2571 gen_op_eq(bcond, t0, t1);
2572 MIPS_DEBUG("beq %s, %s, " TARGET_FMT_lx,
2573 regnames[rs], regnames[rt], btgt);
2574 goto not_likely;
2575 case OPC_BEQL:
2576 gen_op_eq(bcond, t0, t1);
2577 MIPS_DEBUG("beql %s, %s, " TARGET_FMT_lx,
2578 regnames[rs], regnames[rt], btgt);
2579 goto likely;
2580 case OPC_BNE:
2581 gen_op_ne(bcond, t0, t1);
2582 MIPS_DEBUG("bne %s, %s, " TARGET_FMT_lx,
2583 regnames[rs], regnames[rt], btgt);
2584 goto not_likely;
2585 case OPC_BNEL:
2586 gen_op_ne(bcond, t0, t1);
2587 MIPS_DEBUG("bnel %s, %s, " TARGET_FMT_lx,
2588 regnames[rs], regnames[rt], btgt);
2589 goto likely;
2590 case OPC_BGEZ:
2591 gen_op_gez(bcond, t0);
2592 MIPS_DEBUG("bgez %s, " TARGET_FMT_lx, regnames[rs], btgt);
2593 goto not_likely;
2594 case OPC_BGEZL:
2595 gen_op_gez(bcond, t0);
2596 MIPS_DEBUG("bgezl %s, " TARGET_FMT_lx, regnames[rs], btgt);
2597 goto likely;
2598 case OPC_BGEZAL:
2599 gen_op_gez(bcond, t0);
2600 MIPS_DEBUG("bgezal %s, " TARGET_FMT_lx, regnames[rs], btgt);
2601 blink = 31;
2602 goto not_likely;
2603 case OPC_BGEZALL:
2604 gen_op_gez(bcond, t0);
2605 blink = 31;
2606 MIPS_DEBUG("bgezall %s, " TARGET_FMT_lx, regnames[rs], btgt);
2607 goto likely;
2608 case OPC_BGTZ:
2609 gen_op_gtz(bcond, t0);
2610 MIPS_DEBUG("bgtz %s, " TARGET_FMT_lx, regnames[rs], btgt);
2611 goto not_likely;
2612 case OPC_BGTZL:
2613 gen_op_gtz(bcond, t0);
2614 MIPS_DEBUG("bgtzl %s, " TARGET_FMT_lx, regnames[rs], btgt);
2615 goto likely;
2616 case OPC_BLEZ:
2617 gen_op_lez(bcond, t0);
2618 MIPS_DEBUG("blez %s, " TARGET_FMT_lx, regnames[rs], btgt);
2619 goto not_likely;
2620 case OPC_BLEZL:
2621 gen_op_lez(bcond, t0);
2622 MIPS_DEBUG("blezl %s, " TARGET_FMT_lx, regnames[rs], btgt);
2623 goto likely;
2624 case OPC_BLTZ:
2625 gen_op_ltz(bcond, t0);
2626 MIPS_DEBUG("bltz %s, " TARGET_FMT_lx, regnames[rs], btgt);
2627 goto not_likely;
2628 case OPC_BLTZL:
2629 gen_op_ltz(bcond, t0);
2630 MIPS_DEBUG("bltzl %s, " TARGET_FMT_lx, regnames[rs], btgt);
2631 goto likely;
2632 case OPC_BLTZAL:
2633 gen_op_ltz(bcond, t0);
2634 blink = 31;
2635 MIPS_DEBUG("bltzal %s, " TARGET_FMT_lx, regnames[rs], btgt);
2636 not_likely:
2637 ctx->hflags |= MIPS_HFLAG_BC;
2638 break;
2639 case OPC_BLTZALL:
2640 gen_op_ltz(bcond, t0);
2641 blink = 31;
2642 MIPS_DEBUG("bltzall %s, " TARGET_FMT_lx, regnames[rs], btgt);
2643 likely:
2644 ctx->hflags |= MIPS_HFLAG_BL;
2645 break;
2646 default:
2647 MIPS_INVAL("conditional branch/jump");
2648 generate_exception(ctx, EXCP_RI);
2649 goto out;
2652 MIPS_DEBUG("enter ds: link %d cond %02x target " TARGET_FMT_lx,
2653 blink, ctx->hflags, btgt);
2655 ctx->btarget = btgt;
2656 if (blink > 0) {
2657 int post_delay = insn_bytes;
2658 int lowbit = !!(ctx->hflags & MIPS_HFLAG_M16);
2660 if (opc != OPC_JALRC)
2661 post_delay += ((ctx->hflags & MIPS_HFLAG_BDS16) ? 2 : 4);
2663 tcg_gen_movi_tl(cpu_gpr[blink], ctx->pc + post_delay + lowbit);
2666 out:
2667 if (insn_bytes == 2)
2668 ctx->hflags |= MIPS_HFLAG_B16;
2669 tcg_temp_free(t0);
2670 tcg_temp_free(t1);
2673 /* special3 bitfield operations */
2674 static void gen_bitops (DisasContext *ctx, uint32_t opc, int rt,
2675 int rs, int lsb, int msb)
2677 TCGv t0 = tcg_temp_new();
2678 TCGv t1 = tcg_temp_new();
2679 target_ulong mask;
2681 gen_load_gpr(t1, rs);
2682 switch (opc) {
2683 case OPC_EXT:
2684 if (lsb + msb > 31)
2685 goto fail;
2686 tcg_gen_shri_tl(t0, t1, lsb);
2687 if (msb != 31) {
2688 tcg_gen_andi_tl(t0, t0, (1 << (msb + 1)) - 1);
2689 } else {
2690 tcg_gen_ext32s_tl(t0, t0);
2692 break;
2693 #if defined(TARGET_MIPS64)
2694 case OPC_DEXTM:
2695 tcg_gen_shri_tl(t0, t1, lsb);
2696 if (msb != 31) {
2697 tcg_gen_andi_tl(t0, t0, (1ULL << (msb + 1 + 32)) - 1);
2699 break;
2700 case OPC_DEXTU:
2701 tcg_gen_shri_tl(t0, t1, lsb + 32);
2702 tcg_gen_andi_tl(t0, t0, (1ULL << (msb + 1)) - 1);
2703 break;
2704 case OPC_DEXT:
2705 tcg_gen_shri_tl(t0, t1, lsb);
2706 tcg_gen_andi_tl(t0, t0, (1ULL << (msb + 1)) - 1);
2707 break;
2708 #endif
2709 case OPC_INS:
2710 if (lsb > msb)
2711 goto fail;
2712 mask = ((msb - lsb + 1 < 32) ? ((1 << (msb - lsb + 1)) - 1) : ~0) << lsb;
2713 gen_load_gpr(t0, rt);
2714 tcg_gen_andi_tl(t0, t0, ~mask);
2715 tcg_gen_shli_tl(t1, t1, lsb);
2716 tcg_gen_andi_tl(t1, t1, mask);
2717 tcg_gen_or_tl(t0, t0, t1);
2718 tcg_gen_ext32s_tl(t0, t0);
2719 break;
2720 #if defined(TARGET_MIPS64)
2721 case OPC_DINSM:
2722 if (lsb > msb)
2723 goto fail;
2724 mask = ((msb - lsb + 1 + 32 < 64) ? ((1ULL << (msb - lsb + 1 + 32)) - 1) : ~0ULL) << lsb;
2725 gen_load_gpr(t0, rt);
2726 tcg_gen_andi_tl(t0, t0, ~mask);
2727 tcg_gen_shli_tl(t1, t1, lsb);
2728 tcg_gen_andi_tl(t1, t1, mask);
2729 tcg_gen_or_tl(t0, t0, t1);
2730 break;
2731 case OPC_DINSU:
2732 if (lsb > msb)
2733 goto fail;
2734 mask = ((1ULL << (msb - lsb + 1)) - 1) << lsb;
2735 gen_load_gpr(t0, rt);
2736 tcg_gen_andi_tl(t0, t0, ~mask);
2737 tcg_gen_shli_tl(t1, t1, lsb + 32);
2738 tcg_gen_andi_tl(t1, t1, mask);
2739 tcg_gen_or_tl(t0, t0, t1);
2740 break;
2741 case OPC_DINS:
2742 if (lsb > msb)
2743 goto fail;
2744 gen_load_gpr(t0, rt);
2745 mask = ((1ULL << (msb - lsb + 1)) - 1) << lsb;
2746 gen_load_gpr(t0, rt);
2747 tcg_gen_andi_tl(t0, t0, ~mask);
2748 tcg_gen_shli_tl(t1, t1, lsb);
2749 tcg_gen_andi_tl(t1, t1, mask);
2750 tcg_gen_or_tl(t0, t0, t1);
2751 break;
2752 #endif
2753 default:
2754 fail:
2755 MIPS_INVAL("bitops");
2756 generate_exception(ctx, EXCP_RI);
2757 tcg_temp_free(t0);
2758 tcg_temp_free(t1);
2759 return;
2761 gen_store_gpr(t0, rt);
2762 tcg_temp_free(t0);
2763 tcg_temp_free(t1);
2766 static void gen_bshfl (DisasContext *ctx, uint32_t op2, int rt, int rd)
2768 TCGv t0;
2770 if (rd == 0) {
2771 /* If no destination, treat it as a NOP. */
2772 MIPS_DEBUG("NOP");
2773 return;
2776 t0 = tcg_temp_new();
2777 gen_load_gpr(t0, rt);
2778 switch (op2) {
2779 case OPC_WSBH:
2781 TCGv t1 = tcg_temp_new();
2783 tcg_gen_shri_tl(t1, t0, 8);
2784 tcg_gen_andi_tl(t1, t1, 0x00FF00FF);
2785 tcg_gen_shli_tl(t0, t0, 8);
2786 tcg_gen_andi_tl(t0, t0, ~0x00FF00FF);
2787 tcg_gen_or_tl(t0, t0, t1);
2788 tcg_temp_free(t1);
2789 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
2791 break;
2792 case OPC_SEB:
2793 tcg_gen_ext8s_tl(cpu_gpr[rd], t0);
2794 break;
2795 case OPC_SEH:
2796 tcg_gen_ext16s_tl(cpu_gpr[rd], t0);
2797 break;
2798 #if defined(TARGET_MIPS64)
2799 case OPC_DSBH:
2801 TCGv t1 = tcg_temp_new();
2803 tcg_gen_shri_tl(t1, t0, 8);
2804 tcg_gen_andi_tl(t1, t1, 0x00FF00FF00FF00FFULL);
2805 tcg_gen_shli_tl(t0, t0, 8);
2806 tcg_gen_andi_tl(t0, t0, ~0x00FF00FF00FF00FFULL);
2807 tcg_gen_or_tl(cpu_gpr[rd], t0, t1);
2808 tcg_temp_free(t1);
2810 break;
2811 case OPC_DSHD:
2813 TCGv t1 = tcg_temp_new();
2815 tcg_gen_shri_tl(t1, t0, 16);
2816 tcg_gen_andi_tl(t1, t1, 0x0000FFFF0000FFFFULL);
2817 tcg_gen_shli_tl(t0, t0, 16);
2818 tcg_gen_andi_tl(t0, t0, ~0x0000FFFF0000FFFFULL);
2819 tcg_gen_or_tl(t0, t0, t1);
2820 tcg_gen_shri_tl(t1, t0, 32);
2821 tcg_gen_shli_tl(t0, t0, 32);
2822 tcg_gen_or_tl(cpu_gpr[rd], t0, t1);
2823 tcg_temp_free(t1);
2825 break;
2826 #endif
2827 default:
2828 MIPS_INVAL("bsfhl");
2829 generate_exception(ctx, EXCP_RI);
2830 tcg_temp_free(t0);
2831 return;
2833 tcg_temp_free(t0);
2836 #ifndef CONFIG_USER_ONLY
2837 /* CP0 (MMU and control) */
2838 static inline void gen_mfc0_load32 (TCGv arg, target_ulong off)
2840 TCGv_i32 t0 = tcg_temp_new_i32();
2842 tcg_gen_ld_i32(t0, cpu_env, off);
2843 tcg_gen_ext_i32_tl(arg, t0);
2844 tcg_temp_free_i32(t0);
2847 static inline void gen_mfc0_load64 (TCGv arg, target_ulong off)
2849 tcg_gen_ld_tl(arg, cpu_env, off);
2850 tcg_gen_ext32s_tl(arg, arg);
2853 static inline void gen_mtc0_store32 (TCGv arg, target_ulong off)
2855 TCGv_i32 t0 = tcg_temp_new_i32();
2857 tcg_gen_trunc_tl_i32(t0, arg);
2858 tcg_gen_st_i32(t0, cpu_env, off);
2859 tcg_temp_free_i32(t0);
2862 static inline void gen_mtc0_store64 (TCGv arg, target_ulong off)
2864 tcg_gen_ext32s_tl(arg, arg);
2865 tcg_gen_st_tl(arg, cpu_env, off);
2868 static void gen_mfc0 (CPUState *env, DisasContext *ctx, TCGv arg, int reg, int sel)
2870 const char *rn = "invalid";
2872 if (sel != 0)
2873 check_insn(env, ctx, ISA_MIPS32);
2875 switch (reg) {
2876 case 0:
2877 switch (sel) {
2878 case 0:
2879 gen_mfc0_load32(arg, offsetof(CPUState, CP0_Index));
2880 rn = "Index";
2881 break;
2882 case 1:
2883 check_insn(env, ctx, ASE_MT);
2884 gen_helper_mfc0_mvpcontrol(arg);
2885 rn = "MVPControl";
2886 break;
2887 case 2:
2888 check_insn(env, ctx, ASE_MT);
2889 gen_helper_mfc0_mvpconf0(arg);
2890 rn = "MVPConf0";
2891 break;
2892 case 3:
2893 check_insn(env, ctx, ASE_MT);
2894 gen_helper_mfc0_mvpconf1(arg);
2895 rn = "MVPConf1";
2896 break;
2897 default:
2898 goto die;
2900 break;
2901 case 1:
2902 switch (sel) {
2903 case 0:
2904 gen_helper_mfc0_random(arg);
2905 rn = "Random";
2906 break;
2907 case 1:
2908 check_insn(env, ctx, ASE_MT);
2909 gen_mfc0_load32(arg, offsetof(CPUState, CP0_VPEControl));
2910 rn = "VPEControl";
2911 break;
2912 case 2:
2913 check_insn(env, ctx, ASE_MT);
2914 gen_mfc0_load32(arg, offsetof(CPUState, CP0_VPEConf0));
2915 rn = "VPEConf0";
2916 break;
2917 case 3:
2918 check_insn(env, ctx, ASE_MT);
2919 gen_mfc0_load32(arg, offsetof(CPUState, CP0_VPEConf1));
2920 rn = "VPEConf1";
2921 break;
2922 case 4:
2923 check_insn(env, ctx, ASE_MT);
2924 gen_mfc0_load64(arg, offsetof(CPUState, CP0_YQMask));
2925 rn = "YQMask";
2926 break;
2927 case 5:
2928 check_insn(env, ctx, ASE_MT);
2929 gen_mfc0_load64(arg, offsetof(CPUState, CP0_VPESchedule));
2930 rn = "VPESchedule";
2931 break;
2932 case 6:
2933 check_insn(env, ctx, ASE_MT);
2934 gen_mfc0_load64(arg, offsetof(CPUState, CP0_VPEScheFBack));
2935 rn = "VPEScheFBack";
2936 break;
2937 case 7:
2938 check_insn(env, ctx, ASE_MT);
2939 gen_mfc0_load32(arg, offsetof(CPUState, CP0_VPEOpt));
2940 rn = "VPEOpt";
2941 break;
2942 default:
2943 goto die;
2945 break;
2946 case 2:
2947 switch (sel) {
2948 case 0:
2949 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_EntryLo0));
2950 tcg_gen_ext32s_tl(arg, arg);
2951 rn = "EntryLo0";
2952 break;
2953 case 1:
2954 check_insn(env, ctx, ASE_MT);
2955 gen_helper_mfc0_tcstatus(arg);
2956 rn = "TCStatus";
2957 break;
2958 case 2:
2959 check_insn(env, ctx, ASE_MT);
2960 gen_helper_mfc0_tcbind(arg);
2961 rn = "TCBind";
2962 break;
2963 case 3:
2964 check_insn(env, ctx, ASE_MT);
2965 gen_helper_mfc0_tcrestart(arg);
2966 rn = "TCRestart";
2967 break;
2968 case 4:
2969 check_insn(env, ctx, ASE_MT);
2970 gen_helper_mfc0_tchalt(arg);
2971 rn = "TCHalt";
2972 break;
2973 case 5:
2974 check_insn(env, ctx, ASE_MT);
2975 gen_helper_mfc0_tccontext(arg);
2976 rn = "TCContext";
2977 break;
2978 case 6:
2979 check_insn(env, ctx, ASE_MT);
2980 gen_helper_mfc0_tcschedule(arg);
2981 rn = "TCSchedule";
2982 break;
2983 case 7:
2984 check_insn(env, ctx, ASE_MT);
2985 gen_helper_mfc0_tcschefback(arg);
2986 rn = "TCScheFBack";
2987 break;
2988 default:
2989 goto die;
2991 break;
2992 case 3:
2993 switch (sel) {
2994 case 0:
2995 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_EntryLo1));
2996 tcg_gen_ext32s_tl(arg, arg);
2997 rn = "EntryLo1";
2998 break;
2999 default:
3000 goto die;
3002 break;
3003 case 4:
3004 switch (sel) {
3005 case 0:
3006 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_Context));
3007 tcg_gen_ext32s_tl(arg, arg);
3008 rn = "Context";
3009 break;
3010 case 1:
3011 // gen_helper_mfc0_contextconfig(arg); /* SmartMIPS ASE */
3012 rn = "ContextConfig";
3013 // break;
3014 default:
3015 goto die;
3017 break;
3018 case 5:
3019 switch (sel) {
3020 case 0:
3021 gen_mfc0_load32(arg, offsetof(CPUState, CP0_PageMask));
3022 rn = "PageMask";
3023 break;
3024 case 1:
3025 check_insn(env, ctx, ISA_MIPS32R2);
3026 gen_mfc0_load32(arg, offsetof(CPUState, CP0_PageGrain));
3027 rn = "PageGrain";
3028 break;
3029 default:
3030 goto die;
3032 break;
3033 case 6:
3034 switch (sel) {
3035 case 0:
3036 gen_mfc0_load32(arg, offsetof(CPUState, CP0_Wired));
3037 rn = "Wired";
3038 break;
3039 case 1:
3040 check_insn(env, ctx, ISA_MIPS32R2);
3041 gen_mfc0_load32(arg, offsetof(CPUState, CP0_SRSConf0));
3042 rn = "SRSConf0";
3043 break;
3044 case 2:
3045 check_insn(env, ctx, ISA_MIPS32R2);
3046 gen_mfc0_load32(arg, offsetof(CPUState, CP0_SRSConf1));
3047 rn = "SRSConf1";
3048 break;
3049 case 3:
3050 check_insn(env, ctx, ISA_MIPS32R2);
3051 gen_mfc0_load32(arg, offsetof(CPUState, CP0_SRSConf2));
3052 rn = "SRSConf2";
3053 break;
3054 case 4:
3055 check_insn(env, ctx, ISA_MIPS32R2);
3056 gen_mfc0_load32(arg, offsetof(CPUState, CP0_SRSConf3));
3057 rn = "SRSConf3";
3058 break;
3059 case 5:
3060 check_insn(env, ctx, ISA_MIPS32R2);
3061 gen_mfc0_load32(arg, offsetof(CPUState, CP0_SRSConf4));
3062 rn = "SRSConf4";
3063 break;
3064 default:
3065 goto die;
3067 break;
3068 case 7:
3069 switch (sel) {
3070 case 0:
3071 check_insn(env, ctx, ISA_MIPS32R2);
3072 gen_mfc0_load32(arg, offsetof(CPUState, CP0_HWREna));
3073 rn = "HWREna";
3074 break;
3075 default:
3076 goto die;
3078 break;
3079 case 8:
3080 switch (sel) {
3081 case 0:
3082 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_BadVAddr));
3083 tcg_gen_ext32s_tl(arg, arg);
3084 rn = "BadVAddr";
3085 break;
3086 default:
3087 goto die;
3089 break;
3090 case 9:
3091 switch (sel) {
3092 case 0:
3093 /* Mark as an IO operation because we read the time. */
3094 if (use_icount)
3095 gen_io_start();
3096 gen_helper_mfc0_count(arg);
3097 if (use_icount) {
3098 gen_io_end();
3099 ctx->bstate = BS_STOP;
3101 rn = "Count";
3102 break;
3103 /* 6,7 are implementation dependent */
3104 default:
3105 goto die;
3107 break;
3108 case 10:
3109 switch (sel) {
3110 case 0:
3111 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_EntryHi));
3112 tcg_gen_ext32s_tl(arg, arg);
3113 rn = "EntryHi";
3114 break;
3115 default:
3116 goto die;
3118 break;
3119 case 11:
3120 switch (sel) {
3121 case 0:
3122 gen_mfc0_load32(arg, offsetof(CPUState, CP0_Compare));
3123 rn = "Compare";
3124 break;
3125 /* 6,7 are implementation dependent */
3126 default:
3127 goto die;
3129 break;
3130 case 12:
3131 switch (sel) {
3132 case 0:
3133 gen_mfc0_load32(arg, offsetof(CPUState, CP0_Status));
3134 rn = "Status";
3135 break;
3136 case 1:
3137 check_insn(env, ctx, ISA_MIPS32R2);
3138 gen_mfc0_load32(arg, offsetof(CPUState, CP0_IntCtl));
3139 rn = "IntCtl";
3140 break;
3141 case 2:
3142 check_insn(env, ctx, ISA_MIPS32R2);
3143 gen_mfc0_load32(arg, offsetof(CPUState, CP0_SRSCtl));
3144 rn = "SRSCtl";
3145 break;
3146 case 3:
3147 check_insn(env, ctx, ISA_MIPS32R2);
3148 gen_mfc0_load32(arg, offsetof(CPUState, CP0_SRSMap));
3149 rn = "SRSMap";
3150 break;
3151 default:
3152 goto die;
3154 break;
3155 case 13:
3156 switch (sel) {
3157 case 0:
3158 gen_mfc0_load32(arg, offsetof(CPUState, CP0_Cause));
3159 rn = "Cause";
3160 break;
3161 default:
3162 goto die;
3164 break;
3165 case 14:
3166 switch (sel) {
3167 case 0:
3168 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_EPC));
3169 tcg_gen_ext32s_tl(arg, arg);
3170 rn = "EPC";
3171 break;
3172 default:
3173 goto die;
3175 break;
3176 case 15:
3177 switch (sel) {
3178 case 0:
3179 gen_mfc0_load32(arg, offsetof(CPUState, CP0_PRid));
3180 rn = "PRid";
3181 break;
3182 case 1:
3183 check_insn(env, ctx, ISA_MIPS32R2);
3184 gen_mfc0_load32(arg, offsetof(CPUState, CP0_EBase));
3185 rn = "EBase";
3186 break;
3187 default:
3188 goto die;
3190 break;
3191 case 16:
3192 switch (sel) {
3193 case 0:
3194 gen_mfc0_load32(arg, offsetof(CPUState, CP0_Config0));
3195 rn = "Config";
3196 break;
3197 case 1:
3198 gen_mfc0_load32(arg, offsetof(CPUState, CP0_Config1));
3199 rn = "Config1";
3200 break;
3201 case 2:
3202 gen_mfc0_load32(arg, offsetof(CPUState, CP0_Config2));
3203 rn = "Config2";
3204 break;
3205 case 3:
3206 gen_mfc0_load32(arg, offsetof(CPUState, CP0_Config3));
3207 rn = "Config3";
3208 break;
3209 /* 4,5 are reserved */
3210 /* 6,7 are implementation dependent */
3211 case 6:
3212 gen_mfc0_load32(arg, offsetof(CPUState, CP0_Config6));
3213 rn = "Config6";
3214 break;
3215 case 7:
3216 gen_mfc0_load32(arg, offsetof(CPUState, CP0_Config7));
3217 rn = "Config7";
3218 break;
3219 default:
3220 goto die;
3222 break;
3223 case 17:
3224 switch (sel) {
3225 case 0:
3226 gen_helper_mfc0_lladdr(arg);
3227 rn = "LLAddr";
3228 break;
3229 default:
3230 goto die;
3232 break;
3233 case 18:
3234 switch (sel) {
3235 case 0 ... 7:
3236 gen_helper_1i(mfc0_watchlo, arg, sel);
3237 rn = "WatchLo";
3238 break;
3239 default:
3240 goto die;
3242 break;
3243 case 19:
3244 switch (sel) {
3245 case 0 ...7:
3246 gen_helper_1i(mfc0_watchhi, arg, sel);
3247 rn = "WatchHi";
3248 break;
3249 default:
3250 goto die;
3252 break;
3253 case 20:
3254 switch (sel) {
3255 case 0:
3256 #if defined(TARGET_MIPS64)
3257 check_insn(env, ctx, ISA_MIPS3);
3258 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_XContext));
3259 tcg_gen_ext32s_tl(arg, arg);
3260 rn = "XContext";
3261 break;
3262 #endif
3263 default:
3264 goto die;
3266 break;
3267 case 21:
3268 /* Officially reserved, but sel 0 is used for R1x000 framemask */
3269 switch (sel) {
3270 case 0:
3271 gen_mfc0_load32(arg, offsetof(CPUState, CP0_Framemask));
3272 rn = "Framemask";
3273 break;
3274 default:
3275 goto die;
3277 break;
3278 case 22:
3279 tcg_gen_movi_tl(arg, 0); /* unimplemented */
3280 rn = "'Diagnostic"; /* implementation dependent */
3281 break;
3282 case 23:
3283 switch (sel) {
3284 case 0:
3285 gen_helper_mfc0_debug(arg); /* EJTAG support */
3286 rn = "Debug";
3287 break;
3288 case 1:
3289 // gen_helper_mfc0_tracecontrol(arg); /* PDtrace support */
3290 rn = "TraceControl";
3291 // break;
3292 case 2:
3293 // gen_helper_mfc0_tracecontrol2(arg); /* PDtrace support */
3294 rn = "TraceControl2";
3295 // break;
3296 case 3:
3297 // gen_helper_mfc0_usertracedata(arg); /* PDtrace support */
3298 rn = "UserTraceData";
3299 // break;
3300 case 4:
3301 // gen_helper_mfc0_tracebpc(arg); /* PDtrace support */
3302 rn = "TraceBPC";
3303 // break;
3304 default:
3305 goto die;
3307 break;
3308 case 24:
3309 switch (sel) {
3310 case 0:
3311 /* EJTAG support */
3312 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_DEPC));
3313 tcg_gen_ext32s_tl(arg, arg);
3314 rn = "DEPC";
3315 break;
3316 default:
3317 goto die;
3319 break;
3320 case 25:
3321 switch (sel) {
3322 case 0:
3323 gen_mfc0_load32(arg, offsetof(CPUState, CP0_Performance0));
3324 rn = "Performance0";
3325 break;
3326 case 1:
3327 // gen_helper_mfc0_performance1(arg);
3328 rn = "Performance1";
3329 // break;
3330 case 2:
3331 // gen_helper_mfc0_performance2(arg);
3332 rn = "Performance2";
3333 // break;
3334 case 3:
3335 // gen_helper_mfc0_performance3(arg);
3336 rn = "Performance3";
3337 // break;
3338 case 4:
3339 // gen_helper_mfc0_performance4(arg);
3340 rn = "Performance4";
3341 // break;
3342 case 5:
3343 // gen_helper_mfc0_performance5(arg);
3344 rn = "Performance5";
3345 // break;
3346 case 6:
3347 // gen_helper_mfc0_performance6(arg);
3348 rn = "Performance6";
3349 // break;
3350 case 7:
3351 // gen_helper_mfc0_performance7(arg);
3352 rn = "Performance7";
3353 // break;
3354 default:
3355 goto die;
3357 break;
3358 case 26:
3359 tcg_gen_movi_tl(arg, 0); /* unimplemented */
3360 rn = "ECC";
3361 break;
3362 case 27:
3363 switch (sel) {
3364 case 0 ... 3:
3365 tcg_gen_movi_tl(arg, 0); /* unimplemented */
3366 rn = "CacheErr";
3367 break;
3368 default:
3369 goto die;
3371 break;
3372 case 28:
3373 switch (sel) {
3374 case 0:
3375 case 2:
3376 case 4:
3377 case 6:
3378 gen_mfc0_load32(arg, offsetof(CPUState, CP0_TagLo));
3379 rn = "TagLo";
3380 break;
3381 case 1:
3382 case 3:
3383 case 5:
3384 case 7:
3385 gen_mfc0_load32(arg, offsetof(CPUState, CP0_DataLo));
3386 rn = "DataLo";
3387 break;
3388 default:
3389 goto die;
3391 break;
3392 case 29:
3393 switch (sel) {
3394 case 0:
3395 case 2:
3396 case 4:
3397 case 6:
3398 gen_mfc0_load32(arg, offsetof(CPUState, CP0_TagHi));
3399 rn = "TagHi";
3400 break;
3401 case 1:
3402 case 3:
3403 case 5:
3404 case 7:
3405 gen_mfc0_load32(arg, offsetof(CPUState, CP0_DataHi));
3406 rn = "DataHi";
3407 break;
3408 default:
3409 goto die;
3411 break;
3412 case 30:
3413 switch (sel) {
3414 case 0:
3415 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_ErrorEPC));
3416 tcg_gen_ext32s_tl(arg, arg);
3417 rn = "ErrorEPC";
3418 break;
3419 default:
3420 goto die;
3422 break;
3423 case 31:
3424 switch (sel) {
3425 case 0:
3426 /* EJTAG support */
3427 gen_mfc0_load32(arg, offsetof(CPUState, CP0_DESAVE));
3428 rn = "DESAVE";
3429 break;
3430 default:
3431 goto die;
3433 break;
3434 default:
3435 goto die;
3437 LOG_DISAS("mfc0 %s (reg %d sel %d)\n", rn, reg, sel);
3438 return;
3440 die:
3441 LOG_DISAS("mfc0 %s (reg %d sel %d)\n", rn, reg, sel);
3442 generate_exception(ctx, EXCP_RI);
3445 static void gen_mtc0 (CPUState *env, DisasContext *ctx, TCGv arg, int reg, int sel)
3447 const char *rn = "invalid";
3449 if (sel != 0)
3450 check_insn(env, ctx, ISA_MIPS32);
3452 if (use_icount)
3453 gen_io_start();
3455 switch (reg) {
3456 case 0:
3457 switch (sel) {
3458 case 0:
3459 gen_helper_mtc0_index(arg);
3460 rn = "Index";
3461 break;
3462 case 1:
3463 check_insn(env, ctx, ASE_MT);
3464 gen_helper_mtc0_mvpcontrol(arg);
3465 rn = "MVPControl";
3466 break;
3467 case 2:
3468 check_insn(env, ctx, ASE_MT);
3469 /* ignored */
3470 rn = "MVPConf0";
3471 break;
3472 case 3:
3473 check_insn(env, ctx, ASE_MT);
3474 /* ignored */
3475 rn = "MVPConf1";
3476 break;
3477 default:
3478 goto die;
3480 break;
3481 case 1:
3482 switch (sel) {
3483 case 0:
3484 /* ignored */
3485 rn = "Random";
3486 break;
3487 case 1:
3488 check_insn(env, ctx, ASE_MT);
3489 gen_helper_mtc0_vpecontrol(arg);
3490 rn = "VPEControl";
3491 break;
3492 case 2:
3493 check_insn(env, ctx, ASE_MT);
3494 gen_helper_mtc0_vpeconf0(arg);
3495 rn = "VPEConf0";
3496 break;
3497 case 3:
3498 check_insn(env, ctx, ASE_MT);
3499 gen_helper_mtc0_vpeconf1(arg);
3500 rn = "VPEConf1";
3501 break;
3502 case 4:
3503 check_insn(env, ctx, ASE_MT);
3504 gen_helper_mtc0_yqmask(arg);
3505 rn = "YQMask";
3506 break;
3507 case 5:
3508 check_insn(env, ctx, ASE_MT);
3509 gen_mtc0_store64(arg, offsetof(CPUState, CP0_VPESchedule));
3510 rn = "VPESchedule";
3511 break;
3512 case 6:
3513 check_insn(env, ctx, ASE_MT);
3514 gen_mtc0_store64(arg, offsetof(CPUState, CP0_VPEScheFBack));
3515 rn = "VPEScheFBack";
3516 break;
3517 case 7:
3518 check_insn(env, ctx, ASE_MT);
3519 gen_helper_mtc0_vpeopt(arg);
3520 rn = "VPEOpt";
3521 break;
3522 default:
3523 goto die;
3525 break;
3526 case 2:
3527 switch (sel) {
3528 case 0:
3529 gen_helper_mtc0_entrylo0(arg);
3530 rn = "EntryLo0";
3531 break;
3532 case 1:
3533 check_insn(env, ctx, ASE_MT);
3534 gen_helper_mtc0_tcstatus(arg);
3535 rn = "TCStatus";
3536 break;
3537 case 2:
3538 check_insn(env, ctx, ASE_MT);
3539 gen_helper_mtc0_tcbind(arg);
3540 rn = "TCBind";
3541 break;
3542 case 3:
3543 check_insn(env, ctx, ASE_MT);
3544 gen_helper_mtc0_tcrestart(arg);
3545 rn = "TCRestart";
3546 break;
3547 case 4:
3548 check_insn(env, ctx, ASE_MT);
3549 gen_helper_mtc0_tchalt(arg);
3550 rn = "TCHalt";
3551 break;
3552 case 5:
3553 check_insn(env, ctx, ASE_MT);
3554 gen_helper_mtc0_tccontext(arg);
3555 rn = "TCContext";
3556 break;
3557 case 6:
3558 check_insn(env, ctx, ASE_MT);
3559 gen_helper_mtc0_tcschedule(arg);
3560 rn = "TCSchedule";
3561 break;
3562 case 7:
3563 check_insn(env, ctx, ASE_MT);
3564 gen_helper_mtc0_tcschefback(arg);
3565 rn = "TCScheFBack";
3566 break;
3567 default:
3568 goto die;
3570 break;
3571 case 3:
3572 switch (sel) {
3573 case 0:
3574 gen_helper_mtc0_entrylo1(arg);
3575 rn = "EntryLo1";
3576 break;
3577 default:
3578 goto die;
3580 break;
3581 case 4:
3582 switch (sel) {
3583 case 0:
3584 gen_helper_mtc0_context(arg);
3585 rn = "Context";
3586 break;
3587 case 1:
3588 // gen_helper_mtc0_contextconfig(arg); /* SmartMIPS ASE */
3589 rn = "ContextConfig";
3590 // break;
3591 default:
3592 goto die;
3594 break;
3595 case 5:
3596 switch (sel) {
3597 case 0:
3598 gen_helper_mtc0_pagemask(arg);
3599 rn = "PageMask";
3600 break;
3601 case 1:
3602 check_insn(env, ctx, ISA_MIPS32R2);
3603 gen_helper_mtc0_pagegrain(arg);
3604 rn = "PageGrain";
3605 break;
3606 default:
3607 goto die;
3609 break;
3610 case 6:
3611 switch (sel) {
3612 case 0:
3613 gen_helper_mtc0_wired(arg);
3614 rn = "Wired";
3615 break;
3616 case 1:
3617 check_insn(env, ctx, ISA_MIPS32R2);
3618 gen_helper_mtc0_srsconf0(arg);
3619 rn = "SRSConf0";
3620 break;
3621 case 2:
3622 check_insn(env, ctx, ISA_MIPS32R2);
3623 gen_helper_mtc0_srsconf1(arg);
3624 rn = "SRSConf1";
3625 break;
3626 case 3:
3627 check_insn(env, ctx, ISA_MIPS32R2);
3628 gen_helper_mtc0_srsconf2(arg);
3629 rn = "SRSConf2";
3630 break;
3631 case 4:
3632 check_insn(env, ctx, ISA_MIPS32R2);
3633 gen_helper_mtc0_srsconf3(arg);
3634 rn = "SRSConf3";
3635 break;
3636 case 5:
3637 check_insn(env, ctx, ISA_MIPS32R2);
3638 gen_helper_mtc0_srsconf4(arg);
3639 rn = "SRSConf4";
3640 break;
3641 default:
3642 goto die;
3644 break;
3645 case 7:
3646 switch (sel) {
3647 case 0:
3648 check_insn(env, ctx, ISA_MIPS32R2);
3649 gen_helper_mtc0_hwrena(arg);
3650 rn = "HWREna";
3651 break;
3652 default:
3653 goto die;
3655 break;
3656 case 8:
3657 /* ignored */
3658 rn = "BadVAddr";
3659 break;
3660 case 9:
3661 switch (sel) {
3662 case 0:
3663 gen_helper_mtc0_count(arg);
3664 rn = "Count";
3665 break;
3666 /* 6,7 are implementation dependent */
3667 default:
3668 goto die;
3670 break;
3671 case 10:
3672 switch (sel) {
3673 case 0:
3674 gen_helper_mtc0_entryhi(arg);
3675 rn = "EntryHi";
3676 break;
3677 default:
3678 goto die;
3680 break;
3681 case 11:
3682 switch (sel) {
3683 case 0:
3684 gen_helper_mtc0_compare(arg);
3685 rn = "Compare";
3686 break;
3687 /* 6,7 are implementation dependent */
3688 default:
3689 goto die;
3691 break;
3692 case 12:
3693 switch (sel) {
3694 case 0:
3695 save_cpu_state(ctx, 1);
3696 gen_helper_mtc0_status(arg);
3697 /* BS_STOP isn't good enough here, hflags may have changed. */
3698 gen_save_pc(ctx->pc + 4);
3699 ctx->bstate = BS_EXCP;
3700 rn = "Status";
3701 break;
3702 case 1:
3703 check_insn(env, ctx, ISA_MIPS32R2);
3704 gen_helper_mtc0_intctl(arg);
3705 /* Stop translation as we may have switched the execution mode */
3706 ctx->bstate = BS_STOP;
3707 rn = "IntCtl";
3708 break;
3709 case 2:
3710 check_insn(env, ctx, ISA_MIPS32R2);
3711 gen_helper_mtc0_srsctl(arg);
3712 /* Stop translation as we may have switched the execution mode */
3713 ctx->bstate = BS_STOP;
3714 rn = "SRSCtl";
3715 break;
3716 case 3:
3717 check_insn(env, ctx, ISA_MIPS32R2);
3718 gen_mtc0_store32(arg, offsetof(CPUState, CP0_SRSMap));
3719 /* Stop translation as we may have switched the execution mode */
3720 ctx->bstate = BS_STOP;
3721 rn = "SRSMap";
3722 break;
3723 default:
3724 goto die;
3726 break;
3727 case 13:
3728 switch (sel) {
3729 case 0:
3730 save_cpu_state(ctx, 1);
3731 gen_helper_mtc0_cause(arg);
3732 rn = "Cause";
3733 break;
3734 default:
3735 goto die;
3737 break;
3738 case 14:
3739 switch (sel) {
3740 case 0:
3741 gen_mtc0_store64(arg, offsetof(CPUState, CP0_EPC));
3742 rn = "EPC";
3743 break;
3744 default:
3745 goto die;
3747 break;
3748 case 15:
3749 switch (sel) {
3750 case 0:
3751 /* ignored */
3752 rn = "PRid";
3753 break;
3754 case 1:
3755 check_insn(env, ctx, ISA_MIPS32R2);
3756 gen_helper_mtc0_ebase(arg);
3757 rn = "EBase";
3758 break;
3759 default:
3760 goto die;
3762 break;
3763 case 16:
3764 switch (sel) {
3765 case 0:
3766 gen_helper_mtc0_config0(arg);
3767 rn = "Config";
3768 /* Stop translation as we may have switched the execution mode */
3769 ctx->bstate = BS_STOP;
3770 break;
3771 case 1:
3772 /* ignored, read only */
3773 rn = "Config1";
3774 break;
3775 case 2:
3776 gen_helper_mtc0_config2(arg);
3777 rn = "Config2";
3778 /* Stop translation as we may have switched the execution mode */
3779 ctx->bstate = BS_STOP;
3780 break;
3781 case 3:
3782 /* ignored, read only */
3783 rn = "Config3";
3784 break;
3785 /* 4,5 are reserved */
3786 /* 6,7 are implementation dependent */
3787 case 6:
3788 /* ignored */
3789 rn = "Config6";
3790 break;
3791 case 7:
3792 /* ignored */
3793 rn = "Config7";
3794 break;
3795 default:
3796 rn = "Invalid config selector";
3797 goto die;
3799 break;
3800 case 17:
3801 switch (sel) {
3802 case 0:
3803 gen_helper_mtc0_lladdr(arg);
3804 rn = "LLAddr";
3805 break;
3806 default:
3807 goto die;
3809 break;
3810 case 18:
3811 switch (sel) {
3812 case 0 ... 7:
3813 gen_helper_1i(mtc0_watchlo, arg, sel);
3814 rn = "WatchLo";
3815 break;
3816 default:
3817 goto die;
3819 break;
3820 case 19:
3821 switch (sel) {
3822 case 0 ... 7:
3823 gen_helper_1i(mtc0_watchhi, arg, sel);
3824 rn = "WatchHi";
3825 break;
3826 default:
3827 goto die;
3829 break;
3830 case 20:
3831 switch (sel) {
3832 case 0:
3833 #if defined(TARGET_MIPS64)
3834 check_insn(env, ctx, ISA_MIPS3);
3835 gen_helper_mtc0_xcontext(arg);
3836 rn = "XContext";
3837 break;
3838 #endif
3839 default:
3840 goto die;
3842 break;
3843 case 21:
3844 /* Officially reserved, but sel 0 is used for R1x000 framemask */
3845 switch (sel) {
3846 case 0:
3847 gen_helper_mtc0_framemask(arg);
3848 rn = "Framemask";
3849 break;
3850 default:
3851 goto die;
3853 break;
3854 case 22:
3855 /* ignored */
3856 rn = "Diagnostic"; /* implementation dependent */
3857 break;
3858 case 23:
3859 switch (sel) {
3860 case 0:
3861 gen_helper_mtc0_debug(arg); /* EJTAG support */
3862 /* BS_STOP isn't good enough here, hflags may have changed. */
3863 gen_save_pc(ctx->pc + 4);
3864 ctx->bstate = BS_EXCP;
3865 rn = "Debug";
3866 break;
3867 case 1:
3868 // gen_helper_mtc0_tracecontrol(arg); /* PDtrace support */
3869 rn = "TraceControl";
3870 /* Stop translation as we may have switched the execution mode */
3871 ctx->bstate = BS_STOP;
3872 // break;
3873 case 2:
3874 // gen_helper_mtc0_tracecontrol2(arg); /* PDtrace support */
3875 rn = "TraceControl2";
3876 /* Stop translation as we may have switched the execution mode */
3877 ctx->bstate = BS_STOP;
3878 // break;
3879 case 3:
3880 /* Stop translation as we may have switched the execution mode */
3881 ctx->bstate = BS_STOP;
3882 // gen_helper_mtc0_usertracedata(arg); /* PDtrace support */
3883 rn = "UserTraceData";
3884 /* Stop translation as we may have switched the execution mode */
3885 ctx->bstate = BS_STOP;
3886 // break;
3887 case 4:
3888 // gen_helper_mtc0_tracebpc(arg); /* PDtrace support */
3889 /* Stop translation as we may have switched the execution mode */
3890 ctx->bstate = BS_STOP;
3891 rn = "TraceBPC";
3892 // break;
3893 default:
3894 goto die;
3896 break;
3897 case 24:
3898 switch (sel) {
3899 case 0:
3900 /* EJTAG support */
3901 gen_mtc0_store64(arg, offsetof(CPUState, CP0_DEPC));
3902 rn = "DEPC";
3903 break;
3904 default:
3905 goto die;
3907 break;
3908 case 25:
3909 switch (sel) {
3910 case 0:
3911 gen_helper_mtc0_performance0(arg);
3912 rn = "Performance0";
3913 break;
3914 case 1:
3915 // gen_helper_mtc0_performance1(arg);
3916 rn = "Performance1";
3917 // break;
3918 case 2:
3919 // gen_helper_mtc0_performance2(arg);
3920 rn = "Performance2";
3921 // break;
3922 case 3:
3923 // gen_helper_mtc0_performance3(arg);
3924 rn = "Performance3";
3925 // break;
3926 case 4:
3927 // gen_helper_mtc0_performance4(arg);
3928 rn = "Performance4";
3929 // break;
3930 case 5:
3931 // gen_helper_mtc0_performance5(arg);
3932 rn = "Performance5";
3933 // break;
3934 case 6:
3935 // gen_helper_mtc0_performance6(arg);
3936 rn = "Performance6";
3937 // break;
3938 case 7:
3939 // gen_helper_mtc0_performance7(arg);
3940 rn = "Performance7";
3941 // break;
3942 default:
3943 goto die;
3945 break;
3946 case 26:
3947 /* ignored */
3948 rn = "ECC";
3949 break;
3950 case 27:
3951 switch (sel) {
3952 case 0 ... 3:
3953 /* ignored */
3954 rn = "CacheErr";
3955 break;
3956 default:
3957 goto die;
3959 break;
3960 case 28:
3961 switch (sel) {
3962 case 0:
3963 case 2:
3964 case 4:
3965 case 6:
3966 gen_helper_mtc0_taglo(arg);
3967 rn = "TagLo";
3968 break;
3969 case 1:
3970 case 3:
3971 case 5:
3972 case 7:
3973 gen_helper_mtc0_datalo(arg);
3974 rn = "DataLo";
3975 break;
3976 default:
3977 goto die;
3979 break;
3980 case 29:
3981 switch (sel) {
3982 case 0:
3983 case 2:
3984 case 4:
3985 case 6:
3986 gen_helper_mtc0_taghi(arg);
3987 rn = "TagHi";
3988 break;
3989 case 1:
3990 case 3:
3991 case 5:
3992 case 7:
3993 gen_helper_mtc0_datahi(arg);
3994 rn = "DataHi";
3995 break;
3996 default:
3997 rn = "invalid sel";
3998 goto die;
4000 break;
4001 case 30:
4002 switch (sel) {
4003 case 0:
4004 gen_mtc0_store64(arg, offsetof(CPUState, CP0_ErrorEPC));
4005 rn = "ErrorEPC";
4006 break;
4007 default:
4008 goto die;
4010 break;
4011 case 31:
4012 switch (sel) {
4013 case 0:
4014 /* EJTAG support */
4015 gen_mtc0_store32(arg, offsetof(CPUState, CP0_DESAVE));
4016 rn = "DESAVE";
4017 break;
4018 default:
4019 goto die;
4021 /* Stop translation as we may have switched the execution mode */
4022 ctx->bstate = BS_STOP;
4023 break;
4024 default:
4025 goto die;
4027 LOG_DISAS("mtc0 %s (reg %d sel %d)\n", rn, reg, sel);
4028 /* For simplicity assume that all writes can cause interrupts. */
4029 if (use_icount) {
4030 gen_io_end();
4031 ctx->bstate = BS_STOP;
4033 return;
4035 die:
4036 LOG_DISAS("mtc0 %s (reg %d sel %d)\n", rn, reg, sel);
4037 generate_exception(ctx, EXCP_RI);
4040 #if defined(TARGET_MIPS64)
4041 static void gen_dmfc0 (CPUState *env, DisasContext *ctx, TCGv arg, int reg, int sel)
4043 const char *rn = "invalid";
4045 if (sel != 0)
4046 check_insn(env, ctx, ISA_MIPS64);
4048 switch (reg) {
4049 case 0:
4050 switch (sel) {
4051 case 0:
4052 gen_mfc0_load32(arg, offsetof(CPUState, CP0_Index));
4053 rn = "Index";
4054 break;
4055 case 1:
4056 check_insn(env, ctx, ASE_MT);
4057 gen_helper_mfc0_mvpcontrol(arg);
4058 rn = "MVPControl";
4059 break;
4060 case 2:
4061 check_insn(env, ctx, ASE_MT);
4062 gen_helper_mfc0_mvpconf0(arg);
4063 rn = "MVPConf0";
4064 break;
4065 case 3:
4066 check_insn(env, ctx, ASE_MT);
4067 gen_helper_mfc0_mvpconf1(arg);
4068 rn = "MVPConf1";
4069 break;
4070 default:
4071 goto die;
4073 break;
4074 case 1:
4075 switch (sel) {
4076 case 0:
4077 gen_helper_mfc0_random(arg);
4078 rn = "Random";
4079 break;
4080 case 1:
4081 check_insn(env, ctx, ASE_MT);
4082 gen_mfc0_load32(arg, offsetof(CPUState, CP0_VPEControl));
4083 rn = "VPEControl";
4084 break;
4085 case 2:
4086 check_insn(env, ctx, ASE_MT);
4087 gen_mfc0_load32(arg, offsetof(CPUState, CP0_VPEConf0));
4088 rn = "VPEConf0";
4089 break;
4090 case 3:
4091 check_insn(env, ctx, ASE_MT);
4092 gen_mfc0_load32(arg, offsetof(CPUState, CP0_VPEConf1));
4093 rn = "VPEConf1";
4094 break;
4095 case 4:
4096 check_insn(env, ctx, ASE_MT);
4097 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_YQMask));
4098 rn = "YQMask";
4099 break;
4100 case 5:
4101 check_insn(env, ctx, ASE_MT);
4102 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_VPESchedule));
4103 rn = "VPESchedule";
4104 break;
4105 case 6:
4106 check_insn(env, ctx, ASE_MT);
4107 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_VPEScheFBack));
4108 rn = "VPEScheFBack";
4109 break;
4110 case 7:
4111 check_insn(env, ctx, ASE_MT);
4112 gen_mfc0_load32(arg, offsetof(CPUState, CP0_VPEOpt));
4113 rn = "VPEOpt";
4114 break;
4115 default:
4116 goto die;
4118 break;
4119 case 2:
4120 switch (sel) {
4121 case 0:
4122 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_EntryLo0));
4123 rn = "EntryLo0";
4124 break;
4125 case 1:
4126 check_insn(env, ctx, ASE_MT);
4127 gen_helper_mfc0_tcstatus(arg);
4128 rn = "TCStatus";
4129 break;
4130 case 2:
4131 check_insn(env, ctx, ASE_MT);
4132 gen_helper_mfc0_tcbind(arg);
4133 rn = "TCBind";
4134 break;
4135 case 3:
4136 check_insn(env, ctx, ASE_MT);
4137 gen_helper_dmfc0_tcrestart(arg);
4138 rn = "TCRestart";
4139 break;
4140 case 4:
4141 check_insn(env, ctx, ASE_MT);
4142 gen_helper_dmfc0_tchalt(arg);
4143 rn = "TCHalt";
4144 break;
4145 case 5:
4146 check_insn(env, ctx, ASE_MT);
4147 gen_helper_dmfc0_tccontext(arg);
4148 rn = "TCContext";
4149 break;
4150 case 6:
4151 check_insn(env, ctx, ASE_MT);
4152 gen_helper_dmfc0_tcschedule(arg);
4153 rn = "TCSchedule";
4154 break;
4155 case 7:
4156 check_insn(env, ctx, ASE_MT);
4157 gen_helper_dmfc0_tcschefback(arg);
4158 rn = "TCScheFBack";
4159 break;
4160 default:
4161 goto die;
4163 break;
4164 case 3:
4165 switch (sel) {
4166 case 0:
4167 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_EntryLo1));
4168 rn = "EntryLo1";
4169 break;
4170 default:
4171 goto die;
4173 break;
4174 case 4:
4175 switch (sel) {
4176 case 0:
4177 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_Context));
4178 rn = "Context";
4179 break;
4180 case 1:
4181 // gen_helper_dmfc0_contextconfig(arg); /* SmartMIPS ASE */
4182 rn = "ContextConfig";
4183 // break;
4184 default:
4185 goto die;
4187 break;
4188 case 5:
4189 switch (sel) {
4190 case 0:
4191 gen_mfc0_load32(arg, offsetof(CPUState, CP0_PageMask));
4192 rn = "PageMask";
4193 break;
4194 case 1:
4195 check_insn(env, ctx, ISA_MIPS32R2);
4196 gen_mfc0_load32(arg, offsetof(CPUState, CP0_PageGrain));
4197 rn = "PageGrain";
4198 break;
4199 default:
4200 goto die;
4202 break;
4203 case 6:
4204 switch (sel) {
4205 case 0:
4206 gen_mfc0_load32(arg, offsetof(CPUState, CP0_Wired));
4207 rn = "Wired";
4208 break;
4209 case 1:
4210 check_insn(env, ctx, ISA_MIPS32R2);
4211 gen_mfc0_load32(arg, offsetof(CPUState, CP0_SRSConf0));
4212 rn = "SRSConf0";
4213 break;
4214 case 2:
4215 check_insn(env, ctx, ISA_MIPS32R2);
4216 gen_mfc0_load32(arg, offsetof(CPUState, CP0_SRSConf1));
4217 rn = "SRSConf1";
4218 break;
4219 case 3:
4220 check_insn(env, ctx, ISA_MIPS32R2);
4221 gen_mfc0_load32(arg, offsetof(CPUState, CP0_SRSConf2));
4222 rn = "SRSConf2";
4223 break;
4224 case 4:
4225 check_insn(env, ctx, ISA_MIPS32R2);
4226 gen_mfc0_load32(arg, offsetof(CPUState, CP0_SRSConf3));
4227 rn = "SRSConf3";
4228 break;
4229 case 5:
4230 check_insn(env, ctx, ISA_MIPS32R2);
4231 gen_mfc0_load32(arg, offsetof(CPUState, CP0_SRSConf4));
4232 rn = "SRSConf4";
4233 break;
4234 default:
4235 goto die;
4237 break;
4238 case 7:
4239 switch (sel) {
4240 case 0:
4241 check_insn(env, ctx, ISA_MIPS32R2);
4242 gen_mfc0_load32(arg, offsetof(CPUState, CP0_HWREna));
4243 rn = "HWREna";
4244 break;
4245 default:
4246 goto die;
4248 break;
4249 case 8:
4250 switch (sel) {
4251 case 0:
4252 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_BadVAddr));
4253 rn = "BadVAddr";
4254 break;
4255 default:
4256 goto die;
4258 break;
4259 case 9:
4260 switch (sel) {
4261 case 0:
4262 /* Mark as an IO operation because we read the time. */
4263 if (use_icount)
4264 gen_io_start();
4265 gen_helper_mfc0_count(arg);
4266 if (use_icount) {
4267 gen_io_end();
4268 ctx->bstate = BS_STOP;
4270 rn = "Count";
4271 break;
4272 /* 6,7 are implementation dependent */
4273 default:
4274 goto die;
4276 break;
4277 case 10:
4278 switch (sel) {
4279 case 0:
4280 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_EntryHi));
4281 rn = "EntryHi";
4282 break;
4283 default:
4284 goto die;
4286 break;
4287 case 11:
4288 switch (sel) {
4289 case 0:
4290 gen_mfc0_load32(arg, offsetof(CPUState, CP0_Compare));
4291 rn = "Compare";
4292 break;
4293 /* 6,7 are implementation dependent */
4294 default:
4295 goto die;
4297 break;
4298 case 12:
4299 switch (sel) {
4300 case 0:
4301 gen_mfc0_load32(arg, offsetof(CPUState, CP0_Status));
4302 rn = "Status";
4303 break;
4304 case 1:
4305 check_insn(env, ctx, ISA_MIPS32R2);
4306 gen_mfc0_load32(arg, offsetof(CPUState, CP0_IntCtl));
4307 rn = "IntCtl";
4308 break;
4309 case 2:
4310 check_insn(env, ctx, ISA_MIPS32R2);
4311 gen_mfc0_load32(arg, offsetof(CPUState, CP0_SRSCtl));
4312 rn = "SRSCtl";
4313 break;
4314 case 3:
4315 check_insn(env, ctx, ISA_MIPS32R2);
4316 gen_mfc0_load32(arg, offsetof(CPUState, CP0_SRSMap));
4317 rn = "SRSMap";
4318 break;
4319 default:
4320 goto die;
4322 break;
4323 case 13:
4324 switch (sel) {
4325 case 0:
4326 gen_mfc0_load32(arg, offsetof(CPUState, CP0_Cause));
4327 rn = "Cause";
4328 break;
4329 default:
4330 goto die;
4332 break;
4333 case 14:
4334 switch (sel) {
4335 case 0:
4336 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_EPC));
4337 rn = "EPC";
4338 break;
4339 default:
4340 goto die;
4342 break;
4343 case 15:
4344 switch (sel) {
4345 case 0:
4346 gen_mfc0_load32(arg, offsetof(CPUState, CP0_PRid));
4347 rn = "PRid";
4348 break;
4349 case 1:
4350 check_insn(env, ctx, ISA_MIPS32R2);
4351 gen_mfc0_load32(arg, offsetof(CPUState, CP0_EBase));
4352 rn = "EBase";
4353 break;
4354 default:
4355 goto die;
4357 break;
4358 case 16:
4359 switch (sel) {
4360 case 0:
4361 gen_mfc0_load32(arg, offsetof(CPUState, CP0_Config0));
4362 rn = "Config";
4363 break;
4364 case 1:
4365 gen_mfc0_load32(arg, offsetof(CPUState, CP0_Config1));
4366 rn = "Config1";
4367 break;
4368 case 2:
4369 gen_mfc0_load32(arg, offsetof(CPUState, CP0_Config2));
4370 rn = "Config2";
4371 break;
4372 case 3:
4373 gen_mfc0_load32(arg, offsetof(CPUState, CP0_Config3));
4374 rn = "Config3";
4375 break;
4376 /* 6,7 are implementation dependent */
4377 case 6:
4378 gen_mfc0_load32(arg, offsetof(CPUState, CP0_Config6));
4379 rn = "Config6";
4380 break;
4381 case 7:
4382 gen_mfc0_load32(arg, offsetof(CPUState, CP0_Config7));
4383 rn = "Config7";
4384 break;
4385 default:
4386 goto die;
4388 break;
4389 case 17:
4390 switch (sel) {
4391 case 0:
4392 gen_helper_dmfc0_lladdr(arg);
4393 rn = "LLAddr";
4394 break;
4395 default:
4396 goto die;
4398 break;
4399 case 18:
4400 switch (sel) {
4401 case 0 ... 7:
4402 gen_helper_1i(dmfc0_watchlo, arg, sel);
4403 rn = "WatchLo";
4404 break;
4405 default:
4406 goto die;
4408 break;
4409 case 19:
4410 switch (sel) {
4411 case 0 ... 7:
4412 gen_helper_1i(mfc0_watchhi, arg, sel);
4413 rn = "WatchHi";
4414 break;
4415 default:
4416 goto die;
4418 break;
4419 case 20:
4420 switch (sel) {
4421 case 0:
4422 check_insn(env, ctx, ISA_MIPS3);
4423 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_XContext));
4424 rn = "XContext";
4425 break;
4426 default:
4427 goto die;
4429 break;
4430 case 21:
4431 /* Officially reserved, but sel 0 is used for R1x000 framemask */
4432 switch (sel) {
4433 case 0:
4434 gen_mfc0_load32(arg, offsetof(CPUState, CP0_Framemask));
4435 rn = "Framemask";
4436 break;
4437 default:
4438 goto die;
4440 break;
4441 case 22:
4442 tcg_gen_movi_tl(arg, 0); /* unimplemented */
4443 rn = "'Diagnostic"; /* implementation dependent */
4444 break;
4445 case 23:
4446 switch (sel) {
4447 case 0:
4448 gen_helper_mfc0_debug(arg); /* EJTAG support */
4449 rn = "Debug";
4450 break;
4451 case 1:
4452 // gen_helper_dmfc0_tracecontrol(arg); /* PDtrace support */
4453 rn = "TraceControl";
4454 // break;
4455 case 2:
4456 // gen_helper_dmfc0_tracecontrol2(arg); /* PDtrace support */
4457 rn = "TraceControl2";
4458 // break;
4459 case 3:
4460 // gen_helper_dmfc0_usertracedata(arg); /* PDtrace support */
4461 rn = "UserTraceData";
4462 // break;
4463 case 4:
4464 // gen_helper_dmfc0_tracebpc(arg); /* PDtrace support */
4465 rn = "TraceBPC";
4466 // break;
4467 default:
4468 goto die;
4470 break;
4471 case 24:
4472 switch (sel) {
4473 case 0:
4474 /* EJTAG support */
4475 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_DEPC));
4476 rn = "DEPC";
4477 break;
4478 default:
4479 goto die;
4481 break;
4482 case 25:
4483 switch (sel) {
4484 case 0:
4485 gen_mfc0_load32(arg, offsetof(CPUState, CP0_Performance0));
4486 rn = "Performance0";
4487 break;
4488 case 1:
4489 // gen_helper_dmfc0_performance1(arg);
4490 rn = "Performance1";
4491 // break;
4492 case 2:
4493 // gen_helper_dmfc0_performance2(arg);
4494 rn = "Performance2";
4495 // break;
4496 case 3:
4497 // gen_helper_dmfc0_performance3(arg);
4498 rn = "Performance3";
4499 // break;
4500 case 4:
4501 // gen_helper_dmfc0_performance4(arg);
4502 rn = "Performance4";
4503 // break;
4504 case 5:
4505 // gen_helper_dmfc0_performance5(arg);
4506 rn = "Performance5";
4507 // break;
4508 case 6:
4509 // gen_helper_dmfc0_performance6(arg);
4510 rn = "Performance6";
4511 // break;
4512 case 7:
4513 // gen_helper_dmfc0_performance7(arg);
4514 rn = "Performance7";
4515 // break;
4516 default:
4517 goto die;
4519 break;
4520 case 26:
4521 tcg_gen_movi_tl(arg, 0); /* unimplemented */
4522 rn = "ECC";
4523 break;
4524 case 27:
4525 switch (sel) {
4526 /* ignored */
4527 case 0 ... 3:
4528 tcg_gen_movi_tl(arg, 0); /* unimplemented */
4529 rn = "CacheErr";
4530 break;
4531 default:
4532 goto die;
4534 break;
4535 case 28:
4536 switch (sel) {
4537 case 0:
4538 case 2:
4539 case 4:
4540 case 6:
4541 gen_mfc0_load32(arg, offsetof(CPUState, CP0_TagLo));
4542 rn = "TagLo";
4543 break;
4544 case 1:
4545 case 3:
4546 case 5:
4547 case 7:
4548 gen_mfc0_load32(arg, offsetof(CPUState, CP0_DataLo));
4549 rn = "DataLo";
4550 break;
4551 default:
4552 goto die;
4554 break;
4555 case 29:
4556 switch (sel) {
4557 case 0:
4558 case 2:
4559 case 4:
4560 case 6:
4561 gen_mfc0_load32(arg, offsetof(CPUState, CP0_TagHi));
4562 rn = "TagHi";
4563 break;
4564 case 1:
4565 case 3:
4566 case 5:
4567 case 7:
4568 gen_mfc0_load32(arg, offsetof(CPUState, CP0_DataHi));
4569 rn = "DataHi";
4570 break;
4571 default:
4572 goto die;
4574 break;
4575 case 30:
4576 switch (sel) {
4577 case 0:
4578 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_ErrorEPC));
4579 rn = "ErrorEPC";
4580 break;
4581 default:
4582 goto die;
4584 break;
4585 case 31:
4586 switch (sel) {
4587 case 0:
4588 /* EJTAG support */
4589 gen_mfc0_load32(arg, offsetof(CPUState, CP0_DESAVE));
4590 rn = "DESAVE";
4591 break;
4592 default:
4593 goto die;
4595 break;
4596 default:
4597 goto die;
4599 LOG_DISAS("dmfc0 %s (reg %d sel %d)\n", rn, reg, sel);
4600 return;
4602 die:
4603 LOG_DISAS("dmfc0 %s (reg %d sel %d)\n", rn, reg, sel);
4604 generate_exception(ctx, EXCP_RI);
4607 static void gen_dmtc0 (CPUState *env, DisasContext *ctx, TCGv arg, int reg, int sel)
4609 const char *rn = "invalid";
4611 if (sel != 0)
4612 check_insn(env, ctx, ISA_MIPS64);
4614 if (use_icount)
4615 gen_io_start();
4617 switch (reg) {
4618 case 0:
4619 switch (sel) {
4620 case 0:
4621 gen_helper_mtc0_index(arg);
4622 rn = "Index";
4623 break;
4624 case 1:
4625 check_insn(env, ctx, ASE_MT);
4626 gen_helper_mtc0_mvpcontrol(arg);
4627 rn = "MVPControl";
4628 break;
4629 case 2:
4630 check_insn(env, ctx, ASE_MT);
4631 /* ignored */
4632 rn = "MVPConf0";
4633 break;
4634 case 3:
4635 check_insn(env, ctx, ASE_MT);
4636 /* ignored */
4637 rn = "MVPConf1";
4638 break;
4639 default:
4640 goto die;
4642 break;
4643 case 1:
4644 switch (sel) {
4645 case 0:
4646 /* ignored */
4647 rn = "Random";
4648 break;
4649 case 1:
4650 check_insn(env, ctx, ASE_MT);
4651 gen_helper_mtc0_vpecontrol(arg);
4652 rn = "VPEControl";
4653 break;
4654 case 2:
4655 check_insn(env, ctx, ASE_MT);
4656 gen_helper_mtc0_vpeconf0(arg);
4657 rn = "VPEConf0";
4658 break;
4659 case 3:
4660 check_insn(env, ctx, ASE_MT);
4661 gen_helper_mtc0_vpeconf1(arg);
4662 rn = "VPEConf1";
4663 break;
4664 case 4:
4665 check_insn(env, ctx, ASE_MT);
4666 gen_helper_mtc0_yqmask(arg);
4667 rn = "YQMask";
4668 break;
4669 case 5:
4670 check_insn(env, ctx, ASE_MT);
4671 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUState, CP0_VPESchedule));
4672 rn = "VPESchedule";
4673 break;
4674 case 6:
4675 check_insn(env, ctx, ASE_MT);
4676 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUState, CP0_VPEScheFBack));
4677 rn = "VPEScheFBack";
4678 break;
4679 case 7:
4680 check_insn(env, ctx, ASE_MT);
4681 gen_helper_mtc0_vpeopt(arg);
4682 rn = "VPEOpt";
4683 break;
4684 default:
4685 goto die;
4687 break;
4688 case 2:
4689 switch (sel) {
4690 case 0:
4691 gen_helper_mtc0_entrylo0(arg);
4692 rn = "EntryLo0";
4693 break;
4694 case 1:
4695 check_insn(env, ctx, ASE_MT);
4696 gen_helper_mtc0_tcstatus(arg);
4697 rn = "TCStatus";
4698 break;
4699 case 2:
4700 check_insn(env, ctx, ASE_MT);
4701 gen_helper_mtc0_tcbind(arg);
4702 rn = "TCBind";
4703 break;
4704 case 3:
4705 check_insn(env, ctx, ASE_MT);
4706 gen_helper_mtc0_tcrestart(arg);
4707 rn = "TCRestart";
4708 break;
4709 case 4:
4710 check_insn(env, ctx, ASE_MT);
4711 gen_helper_mtc0_tchalt(arg);
4712 rn = "TCHalt";
4713 break;
4714 case 5:
4715 check_insn(env, ctx, ASE_MT);
4716 gen_helper_mtc0_tccontext(arg);
4717 rn = "TCContext";
4718 break;
4719 case 6:
4720 check_insn(env, ctx, ASE_MT);
4721 gen_helper_mtc0_tcschedule(arg);
4722 rn = "TCSchedule";
4723 break;
4724 case 7:
4725 check_insn(env, ctx, ASE_MT);
4726 gen_helper_mtc0_tcschefback(arg);
4727 rn = "TCScheFBack";
4728 break;
4729 default:
4730 goto die;
4732 break;
4733 case 3:
4734 switch (sel) {
4735 case 0:
4736 gen_helper_mtc0_entrylo1(arg);
4737 rn = "EntryLo1";
4738 break;
4739 default:
4740 goto die;
4742 break;
4743 case 4:
4744 switch (sel) {
4745 case 0:
4746 gen_helper_mtc0_context(arg);
4747 rn = "Context";
4748 break;
4749 case 1:
4750 // gen_helper_mtc0_contextconfig(arg); /* SmartMIPS ASE */
4751 rn = "ContextConfig";
4752 // break;
4753 default:
4754 goto die;
4756 break;
4757 case 5:
4758 switch (sel) {
4759 case 0:
4760 gen_helper_mtc0_pagemask(arg);
4761 rn = "PageMask";
4762 break;
4763 case 1:
4764 check_insn(env, ctx, ISA_MIPS32R2);
4765 gen_helper_mtc0_pagegrain(arg);
4766 rn = "PageGrain";
4767 break;
4768 default:
4769 goto die;
4771 break;
4772 case 6:
4773 switch (sel) {
4774 case 0:
4775 gen_helper_mtc0_wired(arg);
4776 rn = "Wired";
4777 break;
4778 case 1:
4779 check_insn(env, ctx, ISA_MIPS32R2);
4780 gen_helper_mtc0_srsconf0(arg);
4781 rn = "SRSConf0";
4782 break;
4783 case 2:
4784 check_insn(env, ctx, ISA_MIPS32R2);
4785 gen_helper_mtc0_srsconf1(arg);
4786 rn = "SRSConf1";
4787 break;
4788 case 3:
4789 check_insn(env, ctx, ISA_MIPS32R2);
4790 gen_helper_mtc0_srsconf2(arg);
4791 rn = "SRSConf2";
4792 break;
4793 case 4:
4794 check_insn(env, ctx, ISA_MIPS32R2);
4795 gen_helper_mtc0_srsconf3(arg);
4796 rn = "SRSConf3";
4797 break;
4798 case 5:
4799 check_insn(env, ctx, ISA_MIPS32R2);
4800 gen_helper_mtc0_srsconf4(arg);
4801 rn = "SRSConf4";
4802 break;
4803 default:
4804 goto die;
4806 break;
4807 case 7:
4808 switch (sel) {
4809 case 0:
4810 check_insn(env, ctx, ISA_MIPS32R2);
4811 gen_helper_mtc0_hwrena(arg);
4812 rn = "HWREna";
4813 break;
4814 default:
4815 goto die;
4817 break;
4818 case 8:
4819 /* ignored */
4820 rn = "BadVAddr";
4821 break;
4822 case 9:
4823 switch (sel) {
4824 case 0:
4825 gen_helper_mtc0_count(arg);
4826 rn = "Count";
4827 break;
4828 /* 6,7 are implementation dependent */
4829 default:
4830 goto die;
4832 /* Stop translation as we may have switched the execution mode */
4833 ctx->bstate = BS_STOP;
4834 break;
4835 case 10:
4836 switch (sel) {
4837 case 0:
4838 gen_helper_mtc0_entryhi(arg);
4839 rn = "EntryHi";
4840 break;
4841 default:
4842 goto die;
4844 break;
4845 case 11:
4846 switch (sel) {
4847 case 0:
4848 gen_helper_mtc0_compare(arg);
4849 rn = "Compare";
4850 break;
4851 /* 6,7 are implementation dependent */
4852 default:
4853 goto die;
4855 /* Stop translation as we may have switched the execution mode */
4856 ctx->bstate = BS_STOP;
4857 break;
4858 case 12:
4859 switch (sel) {
4860 case 0:
4861 save_cpu_state(ctx, 1);
4862 gen_helper_mtc0_status(arg);
4863 /* BS_STOP isn't good enough here, hflags may have changed. */
4864 gen_save_pc(ctx->pc + 4);
4865 ctx->bstate = BS_EXCP;
4866 rn = "Status";
4867 break;
4868 case 1:
4869 check_insn(env, ctx, ISA_MIPS32R2);
4870 gen_helper_mtc0_intctl(arg);
4871 /* Stop translation as we may have switched the execution mode */
4872 ctx->bstate = BS_STOP;
4873 rn = "IntCtl";
4874 break;
4875 case 2:
4876 check_insn(env, ctx, ISA_MIPS32R2);
4877 gen_helper_mtc0_srsctl(arg);
4878 /* Stop translation as we may have switched the execution mode */
4879 ctx->bstate = BS_STOP;
4880 rn = "SRSCtl";
4881 break;
4882 case 3:
4883 check_insn(env, ctx, ISA_MIPS32R2);
4884 gen_mtc0_store32(arg, offsetof(CPUState, CP0_SRSMap));
4885 /* Stop translation as we may have switched the execution mode */
4886 ctx->bstate = BS_STOP;
4887 rn = "SRSMap";
4888 break;
4889 default:
4890 goto die;
4892 break;
4893 case 13:
4894 switch (sel) {
4895 case 0:
4896 save_cpu_state(ctx, 1);
4897 gen_helper_mtc0_cause(arg);
4898 rn = "Cause";
4899 break;
4900 default:
4901 goto die;
4903 break;
4904 case 14:
4905 switch (sel) {
4906 case 0:
4907 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUState, CP0_EPC));
4908 rn = "EPC";
4909 break;
4910 default:
4911 goto die;
4913 break;
4914 case 15:
4915 switch (sel) {
4916 case 0:
4917 /* ignored */
4918 rn = "PRid";
4919 break;
4920 case 1:
4921 check_insn(env, ctx, ISA_MIPS32R2);
4922 gen_helper_mtc0_ebase(arg);
4923 rn = "EBase";
4924 break;
4925 default:
4926 goto die;
4928 break;
4929 case 16:
4930 switch (sel) {
4931 case 0:
4932 gen_helper_mtc0_config0(arg);
4933 rn = "Config";
4934 /* Stop translation as we may have switched the execution mode */
4935 ctx->bstate = BS_STOP;
4936 break;
4937 case 1:
4938 /* ignored, read only */
4939 rn = "Config1";
4940 break;
4941 case 2:
4942 gen_helper_mtc0_config2(arg);
4943 rn = "Config2";
4944 /* Stop translation as we may have switched the execution mode */
4945 ctx->bstate = BS_STOP;
4946 break;
4947 case 3:
4948 /* ignored */
4949 rn = "Config3";
4950 break;
4951 /* 6,7 are implementation dependent */
4952 default:
4953 rn = "Invalid config selector";
4954 goto die;
4956 break;
4957 case 17:
4958 switch (sel) {
4959 case 0:
4960 gen_helper_mtc0_lladdr(arg);
4961 rn = "LLAddr";
4962 break;
4963 default:
4964 goto die;
4966 break;
4967 case 18:
4968 switch (sel) {
4969 case 0 ... 7:
4970 gen_helper_1i(mtc0_watchlo, arg, sel);
4971 rn = "WatchLo";
4972 break;
4973 default:
4974 goto die;
4976 break;
4977 case 19:
4978 switch (sel) {
4979 case 0 ... 7:
4980 gen_helper_1i(mtc0_watchhi, arg, sel);
4981 rn = "WatchHi";
4982 break;
4983 default:
4984 goto die;
4986 break;
4987 case 20:
4988 switch (sel) {
4989 case 0:
4990 check_insn(env, ctx, ISA_MIPS3);
4991 gen_helper_mtc0_xcontext(arg);
4992 rn = "XContext";
4993 break;
4994 default:
4995 goto die;
4997 break;
4998 case 21:
4999 /* Officially reserved, but sel 0 is used for R1x000 framemask */
5000 switch (sel) {
5001 case 0:
5002 gen_helper_mtc0_framemask(arg);
5003 rn = "Framemask";
5004 break;
5005 default:
5006 goto die;
5008 break;
5009 case 22:
5010 /* ignored */
5011 rn = "Diagnostic"; /* implementation dependent */
5012 break;
5013 case 23:
5014 switch (sel) {
5015 case 0:
5016 gen_helper_mtc0_debug(arg); /* EJTAG support */
5017 /* BS_STOP isn't good enough here, hflags may have changed. */
5018 gen_save_pc(ctx->pc + 4);
5019 ctx->bstate = BS_EXCP;
5020 rn = "Debug";
5021 break;
5022 case 1:
5023 // gen_helper_mtc0_tracecontrol(arg); /* PDtrace support */
5024 /* Stop translation as we may have switched the execution mode */
5025 ctx->bstate = BS_STOP;
5026 rn = "TraceControl";
5027 // break;
5028 case 2:
5029 // gen_helper_mtc0_tracecontrol2(arg); /* PDtrace support */
5030 /* Stop translation as we may have switched the execution mode */
5031 ctx->bstate = BS_STOP;
5032 rn = "TraceControl2";
5033 // break;
5034 case 3:
5035 // gen_helper_mtc0_usertracedata(arg); /* PDtrace support */
5036 /* Stop translation as we may have switched the execution mode */
5037 ctx->bstate = BS_STOP;
5038 rn = "UserTraceData";
5039 // break;
5040 case 4:
5041 // gen_helper_mtc0_tracebpc(arg); /* PDtrace support */
5042 /* Stop translation as we may have switched the execution mode */
5043 ctx->bstate = BS_STOP;
5044 rn = "TraceBPC";
5045 // break;
5046 default:
5047 goto die;
5049 break;
5050 case 24:
5051 switch (sel) {
5052 case 0:
5053 /* EJTAG support */
5054 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUState, CP0_DEPC));
5055 rn = "DEPC";
5056 break;
5057 default:
5058 goto die;
5060 break;
5061 case 25:
5062 switch (sel) {
5063 case 0:
5064 gen_helper_mtc0_performance0(arg);
5065 rn = "Performance0";
5066 break;
5067 case 1:
5068 // gen_helper_mtc0_performance1(arg);
5069 rn = "Performance1";
5070 // break;
5071 case 2:
5072 // gen_helper_mtc0_performance2(arg);
5073 rn = "Performance2";
5074 // break;
5075 case 3:
5076 // gen_helper_mtc0_performance3(arg);
5077 rn = "Performance3";
5078 // break;
5079 case 4:
5080 // gen_helper_mtc0_performance4(arg);
5081 rn = "Performance4";
5082 // break;
5083 case 5:
5084 // gen_helper_mtc0_performance5(arg);
5085 rn = "Performance5";
5086 // break;
5087 case 6:
5088 // gen_helper_mtc0_performance6(arg);
5089 rn = "Performance6";
5090 // break;
5091 case 7:
5092 // gen_helper_mtc0_performance7(arg);
5093 rn = "Performance7";
5094 // break;
5095 default:
5096 goto die;
5098 break;
5099 case 26:
5100 /* ignored */
5101 rn = "ECC";
5102 break;
5103 case 27:
5104 switch (sel) {
5105 case 0 ... 3:
5106 /* ignored */
5107 rn = "CacheErr";
5108 break;
5109 default:
5110 goto die;
5112 break;
5113 case 28:
5114 switch (sel) {
5115 case 0:
5116 case 2:
5117 case 4:
5118 case 6:
5119 gen_helper_mtc0_taglo(arg);
5120 rn = "TagLo";
5121 break;
5122 case 1:
5123 case 3:
5124 case 5:
5125 case 7:
5126 gen_helper_mtc0_datalo(arg);
5127 rn = "DataLo";
5128 break;
5129 default:
5130 goto die;
5132 break;
5133 case 29:
5134 switch (sel) {
5135 case 0:
5136 case 2:
5137 case 4:
5138 case 6:
5139 gen_helper_mtc0_taghi(arg);
5140 rn = "TagHi";
5141 break;
5142 case 1:
5143 case 3:
5144 case 5:
5145 case 7:
5146 gen_helper_mtc0_datahi(arg);
5147 rn = "DataHi";
5148 break;
5149 default:
5150 rn = "invalid sel";
5151 goto die;
5153 break;
5154 case 30:
5155 switch (sel) {
5156 case 0:
5157 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUState, CP0_ErrorEPC));
5158 rn = "ErrorEPC";
5159 break;
5160 default:
5161 goto die;
5163 break;
5164 case 31:
5165 switch (sel) {
5166 case 0:
5167 /* EJTAG support */
5168 gen_mtc0_store32(arg, offsetof(CPUState, CP0_DESAVE));
5169 rn = "DESAVE";
5170 break;
5171 default:
5172 goto die;
5174 /* Stop translation as we may have switched the execution mode */
5175 ctx->bstate = BS_STOP;
5176 break;
5177 default:
5178 goto die;
5180 LOG_DISAS("dmtc0 %s (reg %d sel %d)\n", rn, reg, sel);
5181 /* For simplicity assume that all writes can cause interrupts. */
5182 if (use_icount) {
5183 gen_io_end();
5184 ctx->bstate = BS_STOP;
5186 return;
5188 die:
5189 LOG_DISAS("dmtc0 %s (reg %d sel %d)\n", rn, reg, sel);
5190 generate_exception(ctx, EXCP_RI);
5192 #endif /* TARGET_MIPS64 */
5194 static void gen_mftr(CPUState *env, DisasContext *ctx, int rt, int rd,
5195 int u, int sel, int h)
5197 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
5198 TCGv t0 = tcg_temp_local_new();
5200 if ((env->CP0_VPEConf0 & (1 << CP0VPEC0_MVP)) == 0 &&
5201 ((env->tcs[other_tc].CP0_TCBind & (0xf << CP0TCBd_CurVPE)) !=
5202 (env->active_tc.CP0_TCBind & (0xf << CP0TCBd_CurVPE))))
5203 tcg_gen_movi_tl(t0, -1);
5204 else if ((env->CP0_VPEControl & (0xff << CP0VPECo_TargTC)) >
5205 (env->mvp->CP0_MVPConf0 & (0xff << CP0MVPC0_PTC)))
5206 tcg_gen_movi_tl(t0, -1);
5207 else if (u == 0) {
5208 switch (rt) {
5209 case 2:
5210 switch (sel) {
5211 case 1:
5212 gen_helper_mftc0_tcstatus(t0);
5213 break;
5214 case 2:
5215 gen_helper_mftc0_tcbind(t0);
5216 break;
5217 case 3:
5218 gen_helper_mftc0_tcrestart(t0);
5219 break;
5220 case 4:
5221 gen_helper_mftc0_tchalt(t0);
5222 break;
5223 case 5:
5224 gen_helper_mftc0_tccontext(t0);
5225 break;
5226 case 6:
5227 gen_helper_mftc0_tcschedule(t0);
5228 break;
5229 case 7:
5230 gen_helper_mftc0_tcschefback(t0);
5231 break;
5232 default:
5233 gen_mfc0(env, ctx, t0, rt, sel);
5234 break;
5236 break;
5237 case 10:
5238 switch (sel) {
5239 case 0:
5240 gen_helper_mftc0_entryhi(t0);
5241 break;
5242 default:
5243 gen_mfc0(env, ctx, t0, rt, sel);
5244 break;
5246 case 12:
5247 switch (sel) {
5248 case 0:
5249 gen_helper_mftc0_status(t0);
5250 break;
5251 default:
5252 gen_mfc0(env, ctx, t0, rt, sel);
5253 break;
5255 case 23:
5256 switch (sel) {
5257 case 0:
5258 gen_helper_mftc0_debug(t0);
5259 break;
5260 default:
5261 gen_mfc0(env, ctx, t0, rt, sel);
5262 break;
5264 break;
5265 default:
5266 gen_mfc0(env, ctx, t0, rt, sel);
5268 } else switch (sel) {
5269 /* GPR registers. */
5270 case 0:
5271 gen_helper_1i(mftgpr, t0, rt);
5272 break;
5273 /* Auxiliary CPU registers */
5274 case 1:
5275 switch (rt) {
5276 case 0:
5277 gen_helper_1i(mftlo, t0, 0);
5278 break;
5279 case 1:
5280 gen_helper_1i(mfthi, t0, 0);
5281 break;
5282 case 2:
5283 gen_helper_1i(mftacx, t0, 0);
5284 break;
5285 case 4:
5286 gen_helper_1i(mftlo, t0, 1);
5287 break;
5288 case 5:
5289 gen_helper_1i(mfthi, t0, 1);
5290 break;
5291 case 6:
5292 gen_helper_1i(mftacx, t0, 1);
5293 break;
5294 case 8:
5295 gen_helper_1i(mftlo, t0, 2);
5296 break;
5297 case 9:
5298 gen_helper_1i(mfthi, t0, 2);
5299 break;
5300 case 10:
5301 gen_helper_1i(mftacx, t0, 2);
5302 break;
5303 case 12:
5304 gen_helper_1i(mftlo, t0, 3);
5305 break;
5306 case 13:
5307 gen_helper_1i(mfthi, t0, 3);
5308 break;
5309 case 14:
5310 gen_helper_1i(mftacx, t0, 3);
5311 break;
5312 case 16:
5313 gen_helper_mftdsp(t0);
5314 break;
5315 default:
5316 goto die;
5318 break;
5319 /* Floating point (COP1). */
5320 case 2:
5321 /* XXX: For now we support only a single FPU context. */
5322 if (h == 0) {
5323 TCGv_i32 fp0 = tcg_temp_new_i32();
5325 gen_load_fpr32(fp0, rt);
5326 tcg_gen_ext_i32_tl(t0, fp0);
5327 tcg_temp_free_i32(fp0);
5328 } else {
5329 TCGv_i32 fp0 = tcg_temp_new_i32();
5331 gen_load_fpr32h(fp0, rt);
5332 tcg_gen_ext_i32_tl(t0, fp0);
5333 tcg_temp_free_i32(fp0);
5335 break;
5336 case 3:
5337 /* XXX: For now we support only a single FPU context. */
5338 gen_helper_1i(cfc1, t0, rt);
5339 break;
5340 /* COP2: Not implemented. */
5341 case 4:
5342 case 5:
5343 /* fall through */
5344 default:
5345 goto die;
5347 LOG_DISAS("mftr (reg %d u %d sel %d h %d)\n", rt, u, sel, h);
5348 gen_store_gpr(t0, rd);
5349 tcg_temp_free(t0);
5350 return;
5352 die:
5353 tcg_temp_free(t0);
5354 LOG_DISAS("mftr (reg %d u %d sel %d h %d)\n", rt, u, sel, h);
5355 generate_exception(ctx, EXCP_RI);
5358 static void gen_mttr(CPUState *env, DisasContext *ctx, int rd, int rt,
5359 int u, int sel, int h)
5361 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
5362 TCGv t0 = tcg_temp_local_new();
5364 gen_load_gpr(t0, rt);
5365 if ((env->CP0_VPEConf0 & (1 << CP0VPEC0_MVP)) == 0 &&
5366 ((env->tcs[other_tc].CP0_TCBind & (0xf << CP0TCBd_CurVPE)) !=
5367 (env->active_tc.CP0_TCBind & (0xf << CP0TCBd_CurVPE))))
5368 /* NOP */ ;
5369 else if ((env->CP0_VPEControl & (0xff << CP0VPECo_TargTC)) >
5370 (env->mvp->CP0_MVPConf0 & (0xff << CP0MVPC0_PTC)))
5371 /* NOP */ ;
5372 else if (u == 0) {
5373 switch (rd) {
5374 case 2:
5375 switch (sel) {
5376 case 1:
5377 gen_helper_mttc0_tcstatus(t0);
5378 break;
5379 case 2:
5380 gen_helper_mttc0_tcbind(t0);
5381 break;
5382 case 3:
5383 gen_helper_mttc0_tcrestart(t0);
5384 break;
5385 case 4:
5386 gen_helper_mttc0_tchalt(t0);
5387 break;
5388 case 5:
5389 gen_helper_mttc0_tccontext(t0);
5390 break;
5391 case 6:
5392 gen_helper_mttc0_tcschedule(t0);
5393 break;
5394 case 7:
5395 gen_helper_mttc0_tcschefback(t0);
5396 break;
5397 default:
5398 gen_mtc0(env, ctx, t0, rd, sel);
5399 break;
5401 break;
5402 case 10:
5403 switch (sel) {
5404 case 0:
5405 gen_helper_mttc0_entryhi(t0);
5406 break;
5407 default:
5408 gen_mtc0(env, ctx, t0, rd, sel);
5409 break;
5411 case 12:
5412 switch (sel) {
5413 case 0:
5414 gen_helper_mttc0_status(t0);
5415 break;
5416 default:
5417 gen_mtc0(env, ctx, t0, rd, sel);
5418 break;
5420 case 23:
5421 switch (sel) {
5422 case 0:
5423 gen_helper_mttc0_debug(t0);
5424 break;
5425 default:
5426 gen_mtc0(env, ctx, t0, rd, sel);
5427 break;
5429 break;
5430 default:
5431 gen_mtc0(env, ctx, t0, rd, sel);
5433 } else switch (sel) {
5434 /* GPR registers. */
5435 case 0:
5436 gen_helper_1i(mttgpr, t0, rd);
5437 break;
5438 /* Auxiliary CPU registers */
5439 case 1:
5440 switch (rd) {
5441 case 0:
5442 gen_helper_1i(mttlo, t0, 0);
5443 break;
5444 case 1:
5445 gen_helper_1i(mtthi, t0, 0);
5446 break;
5447 case 2:
5448 gen_helper_1i(mttacx, t0, 0);
5449 break;
5450 case 4:
5451 gen_helper_1i(mttlo, t0, 1);
5452 break;
5453 case 5:
5454 gen_helper_1i(mtthi, t0, 1);
5455 break;
5456 case 6:
5457 gen_helper_1i(mttacx, t0, 1);
5458 break;
5459 case 8:
5460 gen_helper_1i(mttlo, t0, 2);
5461 break;
5462 case 9:
5463 gen_helper_1i(mtthi, t0, 2);
5464 break;
5465 case 10:
5466 gen_helper_1i(mttacx, t0, 2);
5467 break;
5468 case 12:
5469 gen_helper_1i(mttlo, t0, 3);
5470 break;
5471 case 13:
5472 gen_helper_1i(mtthi, t0, 3);
5473 break;
5474 case 14:
5475 gen_helper_1i(mttacx, t0, 3);
5476 break;
5477 case 16:
5478 gen_helper_mttdsp(t0);
5479 break;
5480 default:
5481 goto die;
5483 break;
5484 /* Floating point (COP1). */
5485 case 2:
5486 /* XXX: For now we support only a single FPU context. */
5487 if (h == 0) {
5488 TCGv_i32 fp0 = tcg_temp_new_i32();
5490 tcg_gen_trunc_tl_i32(fp0, t0);
5491 gen_store_fpr32(fp0, rd);
5492 tcg_temp_free_i32(fp0);
5493 } else {
5494 TCGv_i32 fp0 = tcg_temp_new_i32();
5496 tcg_gen_trunc_tl_i32(fp0, t0);
5497 gen_store_fpr32h(fp0, rd);
5498 tcg_temp_free_i32(fp0);
5500 break;
5501 case 3:
5502 /* XXX: For now we support only a single FPU context. */
5503 gen_helper_1i(ctc1, t0, rd);
5504 break;
5505 /* COP2: Not implemented. */
5506 case 4:
5507 case 5:
5508 /* fall through */
5509 default:
5510 goto die;
5512 LOG_DISAS("mttr (reg %d u %d sel %d h %d)\n", rd, u, sel, h);
5513 tcg_temp_free(t0);
5514 return;
5516 die:
5517 tcg_temp_free(t0);
5518 LOG_DISAS("mttr (reg %d u %d sel %d h %d)\n", rd, u, sel, h);
5519 generate_exception(ctx, EXCP_RI);
5522 static void gen_cp0 (CPUState *env, DisasContext *ctx, uint32_t opc, int rt, int rd)
5524 const char *opn = "ldst";
5526 switch (opc) {
5527 case OPC_MFC0:
5528 if (rt == 0) {
5529 /* Treat as NOP. */
5530 return;
5532 gen_mfc0(env, ctx, cpu_gpr[rt], rd, ctx->opcode & 0x7);
5533 opn = "mfc0";
5534 break;
5535 case OPC_MTC0:
5537 TCGv t0 = tcg_temp_new();
5539 gen_load_gpr(t0, rt);
5540 gen_mtc0(env, ctx, t0, rd, ctx->opcode & 0x7);
5541 tcg_temp_free(t0);
5543 opn = "mtc0";
5544 break;
5545 #if defined(TARGET_MIPS64)
5546 case OPC_DMFC0:
5547 check_insn(env, ctx, ISA_MIPS3);
5548 if (rt == 0) {
5549 /* Treat as NOP. */
5550 return;
5552 gen_dmfc0(env, ctx, cpu_gpr[rt], rd, ctx->opcode & 0x7);
5553 opn = "dmfc0";
5554 break;
5555 case OPC_DMTC0:
5556 check_insn(env, ctx, ISA_MIPS3);
5558 TCGv t0 = tcg_temp_new();
5560 gen_load_gpr(t0, rt);
5561 gen_dmtc0(env, ctx, t0, rd, ctx->opcode & 0x7);
5562 tcg_temp_free(t0);
5564 opn = "dmtc0";
5565 break;
5566 #endif
5567 case OPC_MFTR:
5568 check_insn(env, ctx, ASE_MT);
5569 if (rd == 0) {
5570 /* Treat as NOP. */
5571 return;
5573 gen_mftr(env, ctx, rt, rd, (ctx->opcode >> 5) & 1,
5574 ctx->opcode & 0x7, (ctx->opcode >> 4) & 1);
5575 opn = "mftr";
5576 break;
5577 case OPC_MTTR:
5578 check_insn(env, ctx, ASE_MT);
5579 gen_mttr(env, ctx, rd, rt, (ctx->opcode >> 5) & 1,
5580 ctx->opcode & 0x7, (ctx->opcode >> 4) & 1);
5581 opn = "mttr";
5582 break;
5583 case OPC_TLBWI:
5584 opn = "tlbwi";
5585 if (!env->tlb->helper_tlbwi)
5586 goto die;
5587 gen_helper_tlbwi();
5588 break;
5589 case OPC_TLBWR:
5590 opn = "tlbwr";
5591 if (!env->tlb->helper_tlbwr)
5592 goto die;
5593 gen_helper_tlbwr();
5594 break;
5595 case OPC_TLBP:
5596 opn = "tlbp";
5597 if (!env->tlb->helper_tlbp)
5598 goto die;
5599 gen_helper_tlbp();
5600 break;
5601 case OPC_TLBR:
5602 opn = "tlbr";
5603 if (!env->tlb->helper_tlbr)
5604 goto die;
5605 gen_helper_tlbr();
5606 break;
5607 case OPC_ERET:
5608 opn = "eret";
5609 check_insn(env, ctx, ISA_MIPS2);
5610 gen_helper_eret();
5611 ctx->bstate = BS_EXCP;
5612 break;
5613 case OPC_DERET:
5614 opn = "deret";
5615 check_insn(env, ctx, ISA_MIPS32);
5616 if (!(ctx->hflags & MIPS_HFLAG_DM)) {
5617 MIPS_INVAL(opn);
5618 generate_exception(ctx, EXCP_RI);
5619 } else {
5620 gen_helper_deret();
5621 ctx->bstate = BS_EXCP;
5623 break;
5624 case OPC_WAIT:
5625 opn = "wait";
5626 check_insn(env, ctx, ISA_MIPS3 | ISA_MIPS32);
5627 /* If we get an exception, we want to restart at next instruction */
5628 ctx->pc += 4;
5629 save_cpu_state(ctx, 1);
5630 ctx->pc -= 4;
5631 gen_helper_wait();
5632 ctx->bstate = BS_EXCP;
5633 break;
5634 default:
5635 die:
5636 MIPS_INVAL(opn);
5637 generate_exception(ctx, EXCP_RI);
5638 return;
5640 MIPS_DEBUG("%s %s %d", opn, regnames[rt], rd);
5642 #endif /* !CONFIG_USER_ONLY */
5644 /* CP1 Branches (before delay slot) */
5645 static void gen_compute_branch1 (CPUState *env, DisasContext *ctx, uint32_t op,
5646 int32_t cc, int32_t offset)
5648 target_ulong btarget;
5649 const char *opn = "cp1 cond branch";
5650 TCGv_i32 t0 = tcg_temp_new_i32();
5652 if (cc != 0)
5653 check_insn(env, ctx, ISA_MIPS4 | ISA_MIPS32);
5655 btarget = ctx->pc + 4 + offset;
5657 switch (op) {
5658 case OPC_BC1F:
5659 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
5660 tcg_gen_not_i32(t0, t0);
5661 tcg_gen_andi_i32(t0, t0, 1);
5662 tcg_gen_extu_i32_tl(bcond, t0);
5663 opn = "bc1f";
5664 goto not_likely;
5665 case OPC_BC1FL:
5666 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
5667 tcg_gen_not_i32(t0, t0);
5668 tcg_gen_andi_i32(t0, t0, 1);
5669 tcg_gen_extu_i32_tl(bcond, t0);
5670 opn = "bc1fl";
5671 goto likely;
5672 case OPC_BC1T:
5673 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
5674 tcg_gen_andi_i32(t0, t0, 1);
5675 tcg_gen_extu_i32_tl(bcond, t0);
5676 opn = "bc1t";
5677 goto not_likely;
5678 case OPC_BC1TL:
5679 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
5680 tcg_gen_andi_i32(t0, t0, 1);
5681 tcg_gen_extu_i32_tl(bcond, t0);
5682 opn = "bc1tl";
5683 likely:
5684 ctx->hflags |= MIPS_HFLAG_BL;
5685 break;
5686 case OPC_BC1FANY2:
5688 TCGv_i32 t1 = tcg_temp_new_i32();
5689 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
5690 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+1));
5691 tcg_gen_or_i32(t0, t0, t1);
5692 tcg_temp_free_i32(t1);
5693 tcg_gen_not_i32(t0, t0);
5694 tcg_gen_andi_i32(t0, t0, 1);
5695 tcg_gen_extu_i32_tl(bcond, t0);
5697 opn = "bc1any2f";
5698 goto not_likely;
5699 case OPC_BC1TANY2:
5701 TCGv_i32 t1 = tcg_temp_new_i32();
5702 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
5703 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+1));
5704 tcg_gen_or_i32(t0, t0, t1);
5705 tcg_temp_free_i32(t1);
5706 tcg_gen_andi_i32(t0, t0, 1);
5707 tcg_gen_extu_i32_tl(bcond, t0);
5709 opn = "bc1any2t";
5710 goto not_likely;
5711 case OPC_BC1FANY4:
5713 TCGv_i32 t1 = tcg_temp_new_i32();
5714 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
5715 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+1));
5716 tcg_gen_or_i32(t0, t0, t1);
5717 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+2));
5718 tcg_gen_or_i32(t0, t0, t1);
5719 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+3));
5720 tcg_gen_or_i32(t0, t0, t1);
5721 tcg_temp_free_i32(t1);
5722 tcg_gen_not_i32(t0, t0);
5723 tcg_gen_andi_i32(t0, t0, 1);
5724 tcg_gen_extu_i32_tl(bcond, t0);
5726 opn = "bc1any4f";
5727 goto not_likely;
5728 case OPC_BC1TANY4:
5730 TCGv_i32 t1 = tcg_temp_new_i32();
5731 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
5732 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+1));
5733 tcg_gen_or_i32(t0, t0, t1);
5734 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+2));
5735 tcg_gen_or_i32(t0, t0, t1);
5736 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+3));
5737 tcg_gen_or_i32(t0, t0, t1);
5738 tcg_temp_free_i32(t1);
5739 tcg_gen_andi_i32(t0, t0, 1);
5740 tcg_gen_extu_i32_tl(bcond, t0);
5742 opn = "bc1any4t";
5743 not_likely:
5744 ctx->hflags |= MIPS_HFLAG_BC;
5745 break;
5746 default:
5747 MIPS_INVAL(opn);
5748 generate_exception (ctx, EXCP_RI);
5749 goto out;
5751 MIPS_DEBUG("%s: cond %02x target " TARGET_FMT_lx, opn,
5752 ctx->hflags, btarget);
5753 ctx->btarget = btarget;
5755 out:
5756 tcg_temp_free_i32(t0);
5759 /* Coprocessor 1 (FPU) */
5761 #define FOP(func, fmt) (((fmt) << 21) | (func))
5763 static void gen_cp1 (DisasContext *ctx, uint32_t opc, int rt, int fs)
5765 const char *opn = "cp1 move";
5766 TCGv t0 = tcg_temp_new();
5768 switch (opc) {
5769 case OPC_MFC1:
5771 TCGv_i32 fp0 = tcg_temp_new_i32();
5773 gen_load_fpr32(fp0, fs);
5774 tcg_gen_ext_i32_tl(t0, fp0);
5775 tcg_temp_free_i32(fp0);
5777 gen_store_gpr(t0, rt);
5778 opn = "mfc1";
5779 break;
5780 case OPC_MTC1:
5781 gen_load_gpr(t0, rt);
5783 TCGv_i32 fp0 = tcg_temp_new_i32();
5785 tcg_gen_trunc_tl_i32(fp0, t0);
5786 gen_store_fpr32(fp0, fs);
5787 tcg_temp_free_i32(fp0);
5789 opn = "mtc1";
5790 break;
5791 case OPC_CFC1:
5792 gen_helper_1i(cfc1, t0, fs);
5793 gen_store_gpr(t0, rt);
5794 opn = "cfc1";
5795 break;
5796 case OPC_CTC1:
5797 gen_load_gpr(t0, rt);
5798 gen_helper_1i(ctc1, t0, fs);
5799 opn = "ctc1";
5800 break;
5801 #if defined(TARGET_MIPS64)
5802 case OPC_DMFC1:
5803 gen_load_fpr64(ctx, t0, fs);
5804 gen_store_gpr(t0, rt);
5805 opn = "dmfc1";
5806 break;
5807 case OPC_DMTC1:
5808 gen_load_gpr(t0, rt);
5809 gen_store_fpr64(ctx, t0, fs);
5810 opn = "dmtc1";
5811 break;
5812 #endif
5813 case OPC_MFHC1:
5815 TCGv_i32 fp0 = tcg_temp_new_i32();
5817 gen_load_fpr32h(fp0, fs);
5818 tcg_gen_ext_i32_tl(t0, fp0);
5819 tcg_temp_free_i32(fp0);
5821 gen_store_gpr(t0, rt);
5822 opn = "mfhc1";
5823 break;
5824 case OPC_MTHC1:
5825 gen_load_gpr(t0, rt);
5827 TCGv_i32 fp0 = tcg_temp_new_i32();
5829 tcg_gen_trunc_tl_i32(fp0, t0);
5830 gen_store_fpr32h(fp0, fs);
5831 tcg_temp_free_i32(fp0);
5833 opn = "mthc1";
5834 break;
5835 default:
5836 MIPS_INVAL(opn);
5837 generate_exception (ctx, EXCP_RI);
5838 goto out;
5840 MIPS_DEBUG("%s %s %s", opn, regnames[rt], fregnames[fs]);
5842 out:
5843 tcg_temp_free(t0);
5846 static void gen_movci (DisasContext *ctx, int rd, int rs, int cc, int tf)
5848 int l1;
5849 TCGCond cond;
5850 TCGv_i32 t0;
5852 if (rd == 0) {
5853 /* Treat as NOP. */
5854 return;
5857 if (tf)
5858 cond = TCG_COND_EQ;
5859 else
5860 cond = TCG_COND_NE;
5862 l1 = gen_new_label();
5863 t0 = tcg_temp_new_i32();
5864 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
5865 tcg_gen_brcondi_i32(cond, t0, 0, l1);
5866 tcg_temp_free_i32(t0);
5867 if (rs == 0) {
5868 tcg_gen_movi_tl(cpu_gpr[rd], 0);
5869 } else {
5870 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
5872 gen_set_label(l1);
5875 static inline void gen_movcf_s (int fs, int fd, int cc, int tf)
5877 int cond;
5878 TCGv_i32 t0 = tcg_temp_new_i32();
5879 int l1 = gen_new_label();
5881 if (tf)
5882 cond = TCG_COND_EQ;
5883 else
5884 cond = TCG_COND_NE;
5886 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
5887 tcg_gen_brcondi_i32(cond, t0, 0, l1);
5888 gen_load_fpr32(t0, fs);
5889 gen_store_fpr32(t0, fd);
5890 gen_set_label(l1);
5891 tcg_temp_free_i32(t0);
5894 static inline void gen_movcf_d (DisasContext *ctx, int fs, int fd, int cc, int tf)
5896 int cond;
5897 TCGv_i32 t0 = tcg_temp_new_i32();
5898 TCGv_i64 fp0;
5899 int l1 = gen_new_label();
5901 if (tf)
5902 cond = TCG_COND_EQ;
5903 else
5904 cond = TCG_COND_NE;
5906 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
5907 tcg_gen_brcondi_i32(cond, t0, 0, l1);
5908 tcg_temp_free_i32(t0);
5909 fp0 = tcg_temp_new_i64();
5910 gen_load_fpr64(ctx, fp0, fs);
5911 gen_store_fpr64(ctx, fp0, fd);
5912 tcg_temp_free_i64(fp0);
5913 gen_set_label(l1);
5916 static inline void gen_movcf_ps (int fs, int fd, int cc, int tf)
5918 int cond;
5919 TCGv_i32 t0 = tcg_temp_new_i32();
5920 int l1 = gen_new_label();
5921 int l2 = gen_new_label();
5923 if (tf)
5924 cond = TCG_COND_EQ;
5925 else
5926 cond = TCG_COND_NE;
5928 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
5929 tcg_gen_brcondi_i32(cond, t0, 0, l1);
5930 gen_load_fpr32(t0, fs);
5931 gen_store_fpr32(t0, fd);
5932 gen_set_label(l1);
5934 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc+1));
5935 tcg_gen_brcondi_i32(cond, t0, 0, l2);
5936 gen_load_fpr32h(t0, fs);
5937 gen_store_fpr32h(t0, fd);
5938 tcg_temp_free_i32(t0);
5939 gen_set_label(l2);
5943 static void gen_farith (DisasContext *ctx, uint32_t op1,
5944 int ft, int fs, int fd, int cc)
5946 const char *opn = "farith";
5947 const char *condnames[] = {
5948 "c.f",
5949 "c.un",
5950 "c.eq",
5951 "c.ueq",
5952 "c.olt",
5953 "c.ult",
5954 "c.ole",
5955 "c.ule",
5956 "c.sf",
5957 "c.ngle",
5958 "c.seq",
5959 "c.ngl",
5960 "c.lt",
5961 "c.nge",
5962 "c.le",
5963 "c.ngt",
5965 const char *condnames_abs[] = {
5966 "cabs.f",
5967 "cabs.un",
5968 "cabs.eq",
5969 "cabs.ueq",
5970 "cabs.olt",
5971 "cabs.ult",
5972 "cabs.ole",
5973 "cabs.ule",
5974 "cabs.sf",
5975 "cabs.ngle",
5976 "cabs.seq",
5977 "cabs.ngl",
5978 "cabs.lt",
5979 "cabs.nge",
5980 "cabs.le",
5981 "cabs.ngt",
5983 enum { BINOP, CMPOP, OTHEROP } optype = OTHEROP;
5984 uint32_t func = ctx->opcode & 0x3f;
5986 switch (ctx->opcode & FOP(0x3f, 0x1f)) {
5987 case FOP(0, 16):
5989 TCGv_i32 fp0 = tcg_temp_new_i32();
5990 TCGv_i32 fp1 = tcg_temp_new_i32();
5992 gen_load_fpr32(fp0, fs);
5993 gen_load_fpr32(fp1, ft);
5994 gen_helper_float_add_s(fp0, fp0, fp1);
5995 tcg_temp_free_i32(fp1);
5996 gen_store_fpr32(fp0, fd);
5997 tcg_temp_free_i32(fp0);
5999 opn = "add.s";
6000 optype = BINOP;
6001 break;
6002 case FOP(1, 16):
6004 TCGv_i32 fp0 = tcg_temp_new_i32();
6005 TCGv_i32 fp1 = tcg_temp_new_i32();
6007 gen_load_fpr32(fp0, fs);
6008 gen_load_fpr32(fp1, ft);
6009 gen_helper_float_sub_s(fp0, fp0, fp1);
6010 tcg_temp_free_i32(fp1);
6011 gen_store_fpr32(fp0, fd);
6012 tcg_temp_free_i32(fp0);
6014 opn = "sub.s";
6015 optype = BINOP;
6016 break;
6017 case FOP(2, 16):
6019 TCGv_i32 fp0 = tcg_temp_new_i32();
6020 TCGv_i32 fp1 = tcg_temp_new_i32();
6022 gen_load_fpr32(fp0, fs);
6023 gen_load_fpr32(fp1, ft);
6024 gen_helper_float_mul_s(fp0, fp0, fp1);
6025 tcg_temp_free_i32(fp1);
6026 gen_store_fpr32(fp0, fd);
6027 tcg_temp_free_i32(fp0);
6029 opn = "mul.s";
6030 optype = BINOP;
6031 break;
6032 case FOP(3, 16):
6034 TCGv_i32 fp0 = tcg_temp_new_i32();
6035 TCGv_i32 fp1 = tcg_temp_new_i32();
6037 gen_load_fpr32(fp0, fs);
6038 gen_load_fpr32(fp1, ft);
6039 gen_helper_float_div_s(fp0, fp0, fp1);
6040 tcg_temp_free_i32(fp1);
6041 gen_store_fpr32(fp0, fd);
6042 tcg_temp_free_i32(fp0);
6044 opn = "div.s";
6045 optype = BINOP;
6046 break;
6047 case FOP(4, 16):
6049 TCGv_i32 fp0 = tcg_temp_new_i32();
6051 gen_load_fpr32(fp0, fs);
6052 gen_helper_float_sqrt_s(fp0, fp0);
6053 gen_store_fpr32(fp0, fd);
6054 tcg_temp_free_i32(fp0);
6056 opn = "sqrt.s";
6057 break;
6058 case FOP(5, 16):
6060 TCGv_i32 fp0 = tcg_temp_new_i32();
6062 gen_load_fpr32(fp0, fs);
6063 gen_helper_float_abs_s(fp0, fp0);
6064 gen_store_fpr32(fp0, fd);
6065 tcg_temp_free_i32(fp0);
6067 opn = "abs.s";
6068 break;
6069 case FOP(6, 16):
6071 TCGv_i32 fp0 = tcg_temp_new_i32();
6073 gen_load_fpr32(fp0, fs);
6074 gen_store_fpr32(fp0, fd);
6075 tcg_temp_free_i32(fp0);
6077 opn = "mov.s";
6078 break;
6079 case FOP(7, 16):
6081 TCGv_i32 fp0 = tcg_temp_new_i32();
6083 gen_load_fpr32(fp0, fs);
6084 gen_helper_float_chs_s(fp0, fp0);
6085 gen_store_fpr32(fp0, fd);
6086 tcg_temp_free_i32(fp0);
6088 opn = "neg.s";
6089 break;
6090 case FOP(8, 16):
6091 check_cp1_64bitmode(ctx);
6093 TCGv_i32 fp32 = tcg_temp_new_i32();
6094 TCGv_i64 fp64 = tcg_temp_new_i64();
6096 gen_load_fpr32(fp32, fs);
6097 gen_helper_float_roundl_s(fp64, fp32);
6098 tcg_temp_free_i32(fp32);
6099 gen_store_fpr64(ctx, fp64, fd);
6100 tcg_temp_free_i64(fp64);
6102 opn = "round.l.s";
6103 break;
6104 case FOP(9, 16):
6105 check_cp1_64bitmode(ctx);
6107 TCGv_i32 fp32 = tcg_temp_new_i32();
6108 TCGv_i64 fp64 = tcg_temp_new_i64();
6110 gen_load_fpr32(fp32, fs);
6111 gen_helper_float_truncl_s(fp64, fp32);
6112 tcg_temp_free_i32(fp32);
6113 gen_store_fpr64(ctx, fp64, fd);
6114 tcg_temp_free_i64(fp64);
6116 opn = "trunc.l.s";
6117 break;
6118 case FOP(10, 16):
6119 check_cp1_64bitmode(ctx);
6121 TCGv_i32 fp32 = tcg_temp_new_i32();
6122 TCGv_i64 fp64 = tcg_temp_new_i64();
6124 gen_load_fpr32(fp32, fs);
6125 gen_helper_float_ceill_s(fp64, fp32);
6126 tcg_temp_free_i32(fp32);
6127 gen_store_fpr64(ctx, fp64, fd);
6128 tcg_temp_free_i64(fp64);
6130 opn = "ceil.l.s";
6131 break;
6132 case FOP(11, 16):
6133 check_cp1_64bitmode(ctx);
6135 TCGv_i32 fp32 = tcg_temp_new_i32();
6136 TCGv_i64 fp64 = tcg_temp_new_i64();
6138 gen_load_fpr32(fp32, fs);
6139 gen_helper_float_floorl_s(fp64, fp32);
6140 tcg_temp_free_i32(fp32);
6141 gen_store_fpr64(ctx, fp64, fd);
6142 tcg_temp_free_i64(fp64);
6144 opn = "floor.l.s";
6145 break;
6146 case FOP(12, 16):
6148 TCGv_i32 fp0 = tcg_temp_new_i32();
6150 gen_load_fpr32(fp0, fs);
6151 gen_helper_float_roundw_s(fp0, fp0);
6152 gen_store_fpr32(fp0, fd);
6153 tcg_temp_free_i32(fp0);
6155 opn = "round.w.s";
6156 break;
6157 case FOP(13, 16):
6159 TCGv_i32 fp0 = tcg_temp_new_i32();
6161 gen_load_fpr32(fp0, fs);
6162 gen_helper_float_truncw_s(fp0, fp0);
6163 gen_store_fpr32(fp0, fd);
6164 tcg_temp_free_i32(fp0);
6166 opn = "trunc.w.s";
6167 break;
6168 case FOP(14, 16):
6170 TCGv_i32 fp0 = tcg_temp_new_i32();
6172 gen_load_fpr32(fp0, fs);
6173 gen_helper_float_ceilw_s(fp0, fp0);
6174 gen_store_fpr32(fp0, fd);
6175 tcg_temp_free_i32(fp0);
6177 opn = "ceil.w.s";
6178 break;
6179 case FOP(15, 16):
6181 TCGv_i32 fp0 = tcg_temp_new_i32();
6183 gen_load_fpr32(fp0, fs);
6184 gen_helper_float_floorw_s(fp0, fp0);
6185 gen_store_fpr32(fp0, fd);
6186 tcg_temp_free_i32(fp0);
6188 opn = "floor.w.s";
6189 break;
6190 case FOP(17, 16):
6191 gen_movcf_s(fs, fd, (ft >> 2) & 0x7, ft & 0x1);
6192 opn = "movcf.s";
6193 break;
6194 case FOP(18, 16):
6196 int l1 = gen_new_label();
6197 TCGv_i32 fp0;
6199 if (ft != 0) {
6200 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[ft], 0, l1);
6202 fp0 = tcg_temp_new_i32();
6203 gen_load_fpr32(fp0, fs);
6204 gen_store_fpr32(fp0, fd);
6205 tcg_temp_free_i32(fp0);
6206 gen_set_label(l1);
6208 opn = "movz.s";
6209 break;
6210 case FOP(19, 16):
6212 int l1 = gen_new_label();
6213 TCGv_i32 fp0;
6215 if (ft != 0) {
6216 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[ft], 0, l1);
6217 fp0 = tcg_temp_new_i32();
6218 gen_load_fpr32(fp0, fs);
6219 gen_store_fpr32(fp0, fd);
6220 tcg_temp_free_i32(fp0);
6221 gen_set_label(l1);
6224 opn = "movn.s";
6225 break;
6226 case FOP(21, 16):
6227 check_cop1x(ctx);
6229 TCGv_i32 fp0 = tcg_temp_new_i32();
6231 gen_load_fpr32(fp0, fs);
6232 gen_helper_float_recip_s(fp0, fp0);
6233 gen_store_fpr32(fp0, fd);
6234 tcg_temp_free_i32(fp0);
6236 opn = "recip.s";
6237 break;
6238 case FOP(22, 16):
6239 check_cop1x(ctx);
6241 TCGv_i32 fp0 = tcg_temp_new_i32();
6243 gen_load_fpr32(fp0, fs);
6244 gen_helper_float_rsqrt_s(fp0, fp0);
6245 gen_store_fpr32(fp0, fd);
6246 tcg_temp_free_i32(fp0);
6248 opn = "rsqrt.s";
6249 break;
6250 case FOP(28, 16):
6251 check_cp1_64bitmode(ctx);
6253 TCGv_i32 fp0 = tcg_temp_new_i32();
6254 TCGv_i32 fp1 = tcg_temp_new_i32();
6256 gen_load_fpr32(fp0, fs);
6257 gen_load_fpr32(fp1, fd);
6258 gen_helper_float_recip2_s(fp0, fp0, fp1);
6259 tcg_temp_free_i32(fp1);
6260 gen_store_fpr32(fp0, fd);
6261 tcg_temp_free_i32(fp0);
6263 opn = "recip2.s";
6264 break;
6265 case FOP(29, 16):
6266 check_cp1_64bitmode(ctx);
6268 TCGv_i32 fp0 = tcg_temp_new_i32();
6270 gen_load_fpr32(fp0, fs);
6271 gen_helper_float_recip1_s(fp0, fp0);
6272 gen_store_fpr32(fp0, fd);
6273 tcg_temp_free_i32(fp0);
6275 opn = "recip1.s";
6276 break;
6277 case FOP(30, 16):
6278 check_cp1_64bitmode(ctx);
6280 TCGv_i32 fp0 = tcg_temp_new_i32();
6282 gen_load_fpr32(fp0, fs);
6283 gen_helper_float_rsqrt1_s(fp0, fp0);
6284 gen_store_fpr32(fp0, fd);
6285 tcg_temp_free_i32(fp0);
6287 opn = "rsqrt1.s";
6288 break;
6289 case FOP(31, 16):
6290 check_cp1_64bitmode(ctx);
6292 TCGv_i32 fp0 = tcg_temp_new_i32();
6293 TCGv_i32 fp1 = tcg_temp_new_i32();
6295 gen_load_fpr32(fp0, fs);
6296 gen_load_fpr32(fp1, ft);
6297 gen_helper_float_rsqrt2_s(fp0, fp0, fp1);
6298 tcg_temp_free_i32(fp1);
6299 gen_store_fpr32(fp0, fd);
6300 tcg_temp_free_i32(fp0);
6302 opn = "rsqrt2.s";
6303 break;
6304 case FOP(33, 16):
6305 check_cp1_registers(ctx, fd);
6307 TCGv_i32 fp32 = tcg_temp_new_i32();
6308 TCGv_i64 fp64 = tcg_temp_new_i64();
6310 gen_load_fpr32(fp32, fs);
6311 gen_helper_float_cvtd_s(fp64, fp32);
6312 tcg_temp_free_i32(fp32);
6313 gen_store_fpr64(ctx, fp64, fd);
6314 tcg_temp_free_i64(fp64);
6316 opn = "cvt.d.s";
6317 break;
6318 case FOP(36, 16):
6320 TCGv_i32 fp0 = tcg_temp_new_i32();
6322 gen_load_fpr32(fp0, fs);
6323 gen_helper_float_cvtw_s(fp0, fp0);
6324 gen_store_fpr32(fp0, fd);
6325 tcg_temp_free_i32(fp0);
6327 opn = "cvt.w.s";
6328 break;
6329 case FOP(37, 16):
6330 check_cp1_64bitmode(ctx);
6332 TCGv_i32 fp32 = tcg_temp_new_i32();
6333 TCGv_i64 fp64 = tcg_temp_new_i64();
6335 gen_load_fpr32(fp32, fs);
6336 gen_helper_float_cvtl_s(fp64, fp32);
6337 tcg_temp_free_i32(fp32);
6338 gen_store_fpr64(ctx, fp64, fd);
6339 tcg_temp_free_i64(fp64);
6341 opn = "cvt.l.s";
6342 break;
6343 case FOP(38, 16):
6344 check_cp1_64bitmode(ctx);
6346 TCGv_i64 fp64 = tcg_temp_new_i64();
6347 TCGv_i32 fp32_0 = tcg_temp_new_i32();
6348 TCGv_i32 fp32_1 = tcg_temp_new_i32();
6350 gen_load_fpr32(fp32_0, fs);
6351 gen_load_fpr32(fp32_1, ft);
6352 tcg_gen_concat_i32_i64(fp64, fp32_0, fp32_1);
6353 tcg_temp_free_i32(fp32_1);
6354 tcg_temp_free_i32(fp32_0);
6355 gen_store_fpr64(ctx, fp64, fd);
6356 tcg_temp_free_i64(fp64);
6358 opn = "cvt.ps.s";
6359 break;
6360 case FOP(48, 16):
6361 case FOP(49, 16):
6362 case FOP(50, 16):
6363 case FOP(51, 16):
6364 case FOP(52, 16):
6365 case FOP(53, 16):
6366 case FOP(54, 16):
6367 case FOP(55, 16):
6368 case FOP(56, 16):
6369 case FOP(57, 16):
6370 case FOP(58, 16):
6371 case FOP(59, 16):
6372 case FOP(60, 16):
6373 case FOP(61, 16):
6374 case FOP(62, 16):
6375 case FOP(63, 16):
6377 TCGv_i32 fp0 = tcg_temp_new_i32();
6378 TCGv_i32 fp1 = tcg_temp_new_i32();
6380 gen_load_fpr32(fp0, fs);
6381 gen_load_fpr32(fp1, ft);
6382 if (ctx->opcode & (1 << 6)) {
6383 check_cop1x(ctx);
6384 gen_cmpabs_s(func-48, fp0, fp1, cc);
6385 opn = condnames_abs[func-48];
6386 } else {
6387 gen_cmp_s(func-48, fp0, fp1, cc);
6388 opn = condnames[func-48];
6390 tcg_temp_free_i32(fp0);
6391 tcg_temp_free_i32(fp1);
6393 break;
6394 case FOP(0, 17):
6395 check_cp1_registers(ctx, fs | ft | fd);
6397 TCGv_i64 fp0 = tcg_temp_new_i64();
6398 TCGv_i64 fp1 = tcg_temp_new_i64();
6400 gen_load_fpr64(ctx, fp0, fs);
6401 gen_load_fpr64(ctx, fp1, ft);
6402 gen_helper_float_add_d(fp0, fp0, fp1);
6403 tcg_temp_free_i64(fp1);
6404 gen_store_fpr64(ctx, fp0, fd);
6405 tcg_temp_free_i64(fp0);
6407 opn = "add.d";
6408 optype = BINOP;
6409 break;
6410 case FOP(1, 17):
6411 check_cp1_registers(ctx, fs | ft | fd);
6413 TCGv_i64 fp0 = tcg_temp_new_i64();
6414 TCGv_i64 fp1 = tcg_temp_new_i64();
6416 gen_load_fpr64(ctx, fp0, fs);
6417 gen_load_fpr64(ctx, fp1, ft);
6418 gen_helper_float_sub_d(fp0, fp0, fp1);
6419 tcg_temp_free_i64(fp1);
6420 gen_store_fpr64(ctx, fp0, fd);
6421 tcg_temp_free_i64(fp0);
6423 opn = "sub.d";
6424 optype = BINOP;
6425 break;
6426 case FOP(2, 17):
6427 check_cp1_registers(ctx, fs | ft | fd);
6429 TCGv_i64 fp0 = tcg_temp_new_i64();
6430 TCGv_i64 fp1 = tcg_temp_new_i64();
6432 gen_load_fpr64(ctx, fp0, fs);
6433 gen_load_fpr64(ctx, fp1, ft);
6434 gen_helper_float_mul_d(fp0, fp0, fp1);
6435 tcg_temp_free_i64(fp1);
6436 gen_store_fpr64(ctx, fp0, fd);
6437 tcg_temp_free_i64(fp0);
6439 opn = "mul.d";
6440 optype = BINOP;
6441 break;
6442 case FOP(3, 17):
6443 check_cp1_registers(ctx, fs | ft | fd);
6445 TCGv_i64 fp0 = tcg_temp_new_i64();
6446 TCGv_i64 fp1 = tcg_temp_new_i64();
6448 gen_load_fpr64(ctx, fp0, fs);
6449 gen_load_fpr64(ctx, fp1, ft);
6450 gen_helper_float_div_d(fp0, fp0, fp1);
6451 tcg_temp_free_i64(fp1);
6452 gen_store_fpr64(ctx, fp0, fd);
6453 tcg_temp_free_i64(fp0);
6455 opn = "div.d";
6456 optype = BINOP;
6457 break;
6458 case FOP(4, 17):
6459 check_cp1_registers(ctx, fs | fd);
6461 TCGv_i64 fp0 = tcg_temp_new_i64();
6463 gen_load_fpr64(ctx, fp0, fs);
6464 gen_helper_float_sqrt_d(fp0, fp0);
6465 gen_store_fpr64(ctx, fp0, fd);
6466 tcg_temp_free_i64(fp0);
6468 opn = "sqrt.d";
6469 break;
6470 case FOP(5, 17):
6471 check_cp1_registers(ctx, fs | fd);
6473 TCGv_i64 fp0 = tcg_temp_new_i64();
6475 gen_load_fpr64(ctx, fp0, fs);
6476 gen_helper_float_abs_d(fp0, fp0);
6477 gen_store_fpr64(ctx, fp0, fd);
6478 tcg_temp_free_i64(fp0);
6480 opn = "abs.d";
6481 break;
6482 case FOP(6, 17):
6483 check_cp1_registers(ctx, fs | fd);
6485 TCGv_i64 fp0 = tcg_temp_new_i64();
6487 gen_load_fpr64(ctx, fp0, fs);
6488 gen_store_fpr64(ctx, fp0, fd);
6489 tcg_temp_free_i64(fp0);
6491 opn = "mov.d";
6492 break;
6493 case FOP(7, 17):
6494 check_cp1_registers(ctx, fs | fd);
6496 TCGv_i64 fp0 = tcg_temp_new_i64();
6498 gen_load_fpr64(ctx, fp0, fs);
6499 gen_helper_float_chs_d(fp0, fp0);
6500 gen_store_fpr64(ctx, fp0, fd);
6501 tcg_temp_free_i64(fp0);
6503 opn = "neg.d";
6504 break;
6505 case FOP(8, 17):
6506 check_cp1_64bitmode(ctx);
6508 TCGv_i64 fp0 = tcg_temp_new_i64();
6510 gen_load_fpr64(ctx, fp0, fs);
6511 gen_helper_float_roundl_d(fp0, fp0);
6512 gen_store_fpr64(ctx, fp0, fd);
6513 tcg_temp_free_i64(fp0);
6515 opn = "round.l.d";
6516 break;
6517 case FOP(9, 17):
6518 check_cp1_64bitmode(ctx);
6520 TCGv_i64 fp0 = tcg_temp_new_i64();
6522 gen_load_fpr64(ctx, fp0, fs);
6523 gen_helper_float_truncl_d(fp0, fp0);
6524 gen_store_fpr64(ctx, fp0, fd);
6525 tcg_temp_free_i64(fp0);
6527 opn = "trunc.l.d";
6528 break;
6529 case FOP(10, 17):
6530 check_cp1_64bitmode(ctx);
6532 TCGv_i64 fp0 = tcg_temp_new_i64();
6534 gen_load_fpr64(ctx, fp0, fs);
6535 gen_helper_float_ceill_d(fp0, fp0);
6536 gen_store_fpr64(ctx, fp0, fd);
6537 tcg_temp_free_i64(fp0);
6539 opn = "ceil.l.d";
6540 break;
6541 case FOP(11, 17):
6542 check_cp1_64bitmode(ctx);
6544 TCGv_i64 fp0 = tcg_temp_new_i64();
6546 gen_load_fpr64(ctx, fp0, fs);
6547 gen_helper_float_floorl_d(fp0, fp0);
6548 gen_store_fpr64(ctx, fp0, fd);
6549 tcg_temp_free_i64(fp0);
6551 opn = "floor.l.d";
6552 break;
6553 case FOP(12, 17):
6554 check_cp1_registers(ctx, fs);
6556 TCGv_i32 fp32 = tcg_temp_new_i32();
6557 TCGv_i64 fp64 = tcg_temp_new_i64();
6559 gen_load_fpr64(ctx, fp64, fs);
6560 gen_helper_float_roundw_d(fp32, fp64);
6561 tcg_temp_free_i64(fp64);
6562 gen_store_fpr32(fp32, fd);
6563 tcg_temp_free_i32(fp32);
6565 opn = "round.w.d";
6566 break;
6567 case FOP(13, 17):
6568 check_cp1_registers(ctx, fs);
6570 TCGv_i32 fp32 = tcg_temp_new_i32();
6571 TCGv_i64 fp64 = tcg_temp_new_i64();
6573 gen_load_fpr64(ctx, fp64, fs);
6574 gen_helper_float_truncw_d(fp32, fp64);
6575 tcg_temp_free_i64(fp64);
6576 gen_store_fpr32(fp32, fd);
6577 tcg_temp_free_i32(fp32);
6579 opn = "trunc.w.d";
6580 break;
6581 case FOP(14, 17):
6582 check_cp1_registers(ctx, fs);
6584 TCGv_i32 fp32 = tcg_temp_new_i32();
6585 TCGv_i64 fp64 = tcg_temp_new_i64();
6587 gen_load_fpr64(ctx, fp64, fs);
6588 gen_helper_float_ceilw_d(fp32, fp64);
6589 tcg_temp_free_i64(fp64);
6590 gen_store_fpr32(fp32, fd);
6591 tcg_temp_free_i32(fp32);
6593 opn = "ceil.w.d";
6594 break;
6595 case FOP(15, 17):
6596 check_cp1_registers(ctx, fs);
6598 TCGv_i32 fp32 = tcg_temp_new_i32();
6599 TCGv_i64 fp64 = tcg_temp_new_i64();
6601 gen_load_fpr64(ctx, fp64, fs);
6602 gen_helper_float_floorw_d(fp32, fp64);
6603 tcg_temp_free_i64(fp64);
6604 gen_store_fpr32(fp32, fd);
6605 tcg_temp_free_i32(fp32);
6607 opn = "floor.w.d";
6608 break;
6609 case FOP(17, 17):
6610 gen_movcf_d(ctx, fs, fd, (ft >> 2) & 0x7, ft & 0x1);
6611 opn = "movcf.d";
6612 break;
6613 case FOP(18, 17):
6615 int l1 = gen_new_label();
6616 TCGv_i64 fp0;
6618 if (ft != 0) {
6619 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[ft], 0, l1);
6621 fp0 = tcg_temp_new_i64();
6622 gen_load_fpr64(ctx, fp0, fs);
6623 gen_store_fpr64(ctx, fp0, fd);
6624 tcg_temp_free_i64(fp0);
6625 gen_set_label(l1);
6627 opn = "movz.d";
6628 break;
6629 case FOP(19, 17):
6631 int l1 = gen_new_label();
6632 TCGv_i64 fp0;
6634 if (ft != 0) {
6635 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[ft], 0, l1);
6636 fp0 = tcg_temp_new_i64();
6637 gen_load_fpr64(ctx, fp0, fs);
6638 gen_store_fpr64(ctx, fp0, fd);
6639 tcg_temp_free_i64(fp0);
6640 gen_set_label(l1);
6643 opn = "movn.d";
6644 break;
6645 case FOP(21, 17):
6646 check_cp1_64bitmode(ctx);
6648 TCGv_i64 fp0 = tcg_temp_new_i64();
6650 gen_load_fpr64(ctx, fp0, fs);
6651 gen_helper_float_recip_d(fp0, fp0);
6652 gen_store_fpr64(ctx, fp0, fd);
6653 tcg_temp_free_i64(fp0);
6655 opn = "recip.d";
6656 break;
6657 case FOP(22, 17):
6658 check_cp1_64bitmode(ctx);
6660 TCGv_i64 fp0 = tcg_temp_new_i64();
6662 gen_load_fpr64(ctx, fp0, fs);
6663 gen_helper_float_rsqrt_d(fp0, fp0);
6664 gen_store_fpr64(ctx, fp0, fd);
6665 tcg_temp_free_i64(fp0);
6667 opn = "rsqrt.d";
6668 break;
6669 case FOP(28, 17):
6670 check_cp1_64bitmode(ctx);
6672 TCGv_i64 fp0 = tcg_temp_new_i64();
6673 TCGv_i64 fp1 = tcg_temp_new_i64();
6675 gen_load_fpr64(ctx, fp0, fs);
6676 gen_load_fpr64(ctx, fp1, ft);
6677 gen_helper_float_recip2_d(fp0, fp0, fp1);
6678 tcg_temp_free_i64(fp1);
6679 gen_store_fpr64(ctx, fp0, fd);
6680 tcg_temp_free_i64(fp0);
6682 opn = "recip2.d";
6683 break;
6684 case FOP(29, 17):
6685 check_cp1_64bitmode(ctx);
6687 TCGv_i64 fp0 = tcg_temp_new_i64();
6689 gen_load_fpr64(ctx, fp0, fs);
6690 gen_helper_float_recip1_d(fp0, fp0);
6691 gen_store_fpr64(ctx, fp0, fd);
6692 tcg_temp_free_i64(fp0);
6694 opn = "recip1.d";
6695 break;
6696 case FOP(30, 17):
6697 check_cp1_64bitmode(ctx);
6699 TCGv_i64 fp0 = tcg_temp_new_i64();
6701 gen_load_fpr64(ctx, fp0, fs);
6702 gen_helper_float_rsqrt1_d(fp0, fp0);
6703 gen_store_fpr64(ctx, fp0, fd);
6704 tcg_temp_free_i64(fp0);
6706 opn = "rsqrt1.d";
6707 break;
6708 case FOP(31, 17):
6709 check_cp1_64bitmode(ctx);
6711 TCGv_i64 fp0 = tcg_temp_new_i64();
6712 TCGv_i64 fp1 = tcg_temp_new_i64();
6714 gen_load_fpr64(ctx, fp0, fs);
6715 gen_load_fpr64(ctx, fp1, ft);
6716 gen_helper_float_rsqrt2_d(fp0, fp0, fp1);
6717 tcg_temp_free_i64(fp1);
6718 gen_store_fpr64(ctx, fp0, fd);
6719 tcg_temp_free_i64(fp0);
6721 opn = "rsqrt2.d";
6722 break;
6723 case FOP(48, 17):
6724 case FOP(49, 17):
6725 case FOP(50, 17):
6726 case FOP(51, 17):
6727 case FOP(52, 17):
6728 case FOP(53, 17):
6729 case FOP(54, 17):
6730 case FOP(55, 17):
6731 case FOP(56, 17):
6732 case FOP(57, 17):
6733 case FOP(58, 17):
6734 case FOP(59, 17):
6735 case FOP(60, 17):
6736 case FOP(61, 17):
6737 case FOP(62, 17):
6738 case FOP(63, 17):
6740 TCGv_i64 fp0 = tcg_temp_new_i64();
6741 TCGv_i64 fp1 = tcg_temp_new_i64();
6743 gen_load_fpr64(ctx, fp0, fs);
6744 gen_load_fpr64(ctx, fp1, ft);
6745 if (ctx->opcode & (1 << 6)) {
6746 check_cop1x(ctx);
6747 check_cp1_registers(ctx, fs | ft);
6748 gen_cmpabs_d(func-48, fp0, fp1, cc);
6749 opn = condnames_abs[func-48];
6750 } else {
6751 check_cp1_registers(ctx, fs | ft);
6752 gen_cmp_d(func-48, fp0, fp1, cc);
6753 opn = condnames[func-48];
6755 tcg_temp_free_i64(fp0);
6756 tcg_temp_free_i64(fp1);
6758 break;
6759 case FOP(32, 17):
6760 check_cp1_registers(ctx, fs);
6762 TCGv_i32 fp32 = tcg_temp_new_i32();
6763 TCGv_i64 fp64 = tcg_temp_new_i64();
6765 gen_load_fpr64(ctx, fp64, fs);
6766 gen_helper_float_cvts_d(fp32, fp64);
6767 tcg_temp_free_i64(fp64);
6768 gen_store_fpr32(fp32, fd);
6769 tcg_temp_free_i32(fp32);
6771 opn = "cvt.s.d";
6772 break;
6773 case FOP(36, 17):
6774 check_cp1_registers(ctx, fs);
6776 TCGv_i32 fp32 = tcg_temp_new_i32();
6777 TCGv_i64 fp64 = tcg_temp_new_i64();
6779 gen_load_fpr64(ctx, fp64, fs);
6780 gen_helper_float_cvtw_d(fp32, fp64);
6781 tcg_temp_free_i64(fp64);
6782 gen_store_fpr32(fp32, fd);
6783 tcg_temp_free_i32(fp32);
6785 opn = "cvt.w.d";
6786 break;
6787 case FOP(37, 17):
6788 check_cp1_64bitmode(ctx);
6790 TCGv_i64 fp0 = tcg_temp_new_i64();
6792 gen_load_fpr64(ctx, fp0, fs);
6793 gen_helper_float_cvtl_d(fp0, fp0);
6794 gen_store_fpr64(ctx, fp0, fd);
6795 tcg_temp_free_i64(fp0);
6797 opn = "cvt.l.d";
6798 break;
6799 case FOP(32, 20):
6801 TCGv_i32 fp0 = tcg_temp_new_i32();
6803 gen_load_fpr32(fp0, fs);
6804 gen_helper_float_cvts_w(fp0, fp0);
6805 gen_store_fpr32(fp0, fd);
6806 tcg_temp_free_i32(fp0);
6808 opn = "cvt.s.w";
6809 break;
6810 case FOP(33, 20):
6811 check_cp1_registers(ctx, fd);
6813 TCGv_i32 fp32 = tcg_temp_new_i32();
6814 TCGv_i64 fp64 = tcg_temp_new_i64();
6816 gen_load_fpr32(fp32, fs);
6817 gen_helper_float_cvtd_w(fp64, fp32);
6818 tcg_temp_free_i32(fp32);
6819 gen_store_fpr64(ctx, fp64, fd);
6820 tcg_temp_free_i64(fp64);
6822 opn = "cvt.d.w";
6823 break;
6824 case FOP(32, 21):
6825 check_cp1_64bitmode(ctx);
6827 TCGv_i32 fp32 = tcg_temp_new_i32();
6828 TCGv_i64 fp64 = tcg_temp_new_i64();
6830 gen_load_fpr64(ctx, fp64, fs);
6831 gen_helper_float_cvts_l(fp32, fp64);
6832 tcg_temp_free_i64(fp64);
6833 gen_store_fpr32(fp32, fd);
6834 tcg_temp_free_i32(fp32);
6836 opn = "cvt.s.l";
6837 break;
6838 case FOP(33, 21):
6839 check_cp1_64bitmode(ctx);
6841 TCGv_i64 fp0 = tcg_temp_new_i64();
6843 gen_load_fpr64(ctx, fp0, fs);
6844 gen_helper_float_cvtd_l(fp0, fp0);
6845 gen_store_fpr64(ctx, fp0, fd);
6846 tcg_temp_free_i64(fp0);
6848 opn = "cvt.d.l";
6849 break;
6850 case FOP(38, 20):
6851 check_cp1_64bitmode(ctx);
6853 TCGv_i64 fp0 = tcg_temp_new_i64();
6855 gen_load_fpr64(ctx, fp0, fs);
6856 gen_helper_float_cvtps_pw(fp0, fp0);
6857 gen_store_fpr64(ctx, fp0, fd);
6858 tcg_temp_free_i64(fp0);
6860 opn = "cvt.ps.pw";
6861 break;
6862 case FOP(0, 22):
6863 check_cp1_64bitmode(ctx);
6865 TCGv_i64 fp0 = tcg_temp_new_i64();
6866 TCGv_i64 fp1 = tcg_temp_new_i64();
6868 gen_load_fpr64(ctx, fp0, fs);
6869 gen_load_fpr64(ctx, fp1, ft);
6870 gen_helper_float_add_ps(fp0, fp0, fp1);
6871 tcg_temp_free_i64(fp1);
6872 gen_store_fpr64(ctx, fp0, fd);
6873 tcg_temp_free_i64(fp0);
6875 opn = "add.ps";
6876 break;
6877 case FOP(1, 22):
6878 check_cp1_64bitmode(ctx);
6880 TCGv_i64 fp0 = tcg_temp_new_i64();
6881 TCGv_i64 fp1 = tcg_temp_new_i64();
6883 gen_load_fpr64(ctx, fp0, fs);
6884 gen_load_fpr64(ctx, fp1, ft);
6885 gen_helper_float_sub_ps(fp0, fp0, fp1);
6886 tcg_temp_free_i64(fp1);
6887 gen_store_fpr64(ctx, fp0, fd);
6888 tcg_temp_free_i64(fp0);
6890 opn = "sub.ps";
6891 break;
6892 case FOP(2, 22):
6893 check_cp1_64bitmode(ctx);
6895 TCGv_i64 fp0 = tcg_temp_new_i64();
6896 TCGv_i64 fp1 = tcg_temp_new_i64();
6898 gen_load_fpr64(ctx, fp0, fs);
6899 gen_load_fpr64(ctx, fp1, ft);
6900 gen_helper_float_mul_ps(fp0, fp0, fp1);
6901 tcg_temp_free_i64(fp1);
6902 gen_store_fpr64(ctx, fp0, fd);
6903 tcg_temp_free_i64(fp0);
6905 opn = "mul.ps";
6906 break;
6907 case FOP(5, 22):
6908 check_cp1_64bitmode(ctx);
6910 TCGv_i64 fp0 = tcg_temp_new_i64();
6912 gen_load_fpr64(ctx, fp0, fs);
6913 gen_helper_float_abs_ps(fp0, fp0);
6914 gen_store_fpr64(ctx, fp0, fd);
6915 tcg_temp_free_i64(fp0);
6917 opn = "abs.ps";
6918 break;
6919 case FOP(6, 22):
6920 check_cp1_64bitmode(ctx);
6922 TCGv_i64 fp0 = tcg_temp_new_i64();
6924 gen_load_fpr64(ctx, fp0, fs);
6925 gen_store_fpr64(ctx, fp0, fd);
6926 tcg_temp_free_i64(fp0);
6928 opn = "mov.ps";
6929 break;
6930 case FOP(7, 22):
6931 check_cp1_64bitmode(ctx);
6933 TCGv_i64 fp0 = tcg_temp_new_i64();
6935 gen_load_fpr64(ctx, fp0, fs);
6936 gen_helper_float_chs_ps(fp0, fp0);
6937 gen_store_fpr64(ctx, fp0, fd);
6938 tcg_temp_free_i64(fp0);
6940 opn = "neg.ps";
6941 break;
6942 case FOP(17, 22):
6943 check_cp1_64bitmode(ctx);
6944 gen_movcf_ps(fs, fd, (ft >> 2) & 0x7, ft & 0x1);
6945 opn = "movcf.ps";
6946 break;
6947 case FOP(18, 22):
6948 check_cp1_64bitmode(ctx);
6950 int l1 = gen_new_label();
6951 TCGv_i64 fp0;
6953 if (ft != 0)
6954 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[ft], 0, l1);
6955 fp0 = tcg_temp_new_i64();
6956 gen_load_fpr64(ctx, fp0, fs);
6957 gen_store_fpr64(ctx, fp0, fd);
6958 tcg_temp_free_i64(fp0);
6959 gen_set_label(l1);
6961 opn = "movz.ps";
6962 break;
6963 case FOP(19, 22):
6964 check_cp1_64bitmode(ctx);
6966 int l1 = gen_new_label();
6967 TCGv_i64 fp0;
6969 if (ft != 0) {
6970 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[ft], 0, l1);
6971 fp0 = tcg_temp_new_i64();
6972 gen_load_fpr64(ctx, fp0, fs);
6973 gen_store_fpr64(ctx, fp0, fd);
6974 tcg_temp_free_i64(fp0);
6975 gen_set_label(l1);
6978 opn = "movn.ps";
6979 break;
6980 case FOP(24, 22):
6981 check_cp1_64bitmode(ctx);
6983 TCGv_i64 fp0 = tcg_temp_new_i64();
6984 TCGv_i64 fp1 = tcg_temp_new_i64();
6986 gen_load_fpr64(ctx, fp0, ft);
6987 gen_load_fpr64(ctx, fp1, fs);
6988 gen_helper_float_addr_ps(fp0, fp0, fp1);
6989 tcg_temp_free_i64(fp1);
6990 gen_store_fpr64(ctx, fp0, fd);
6991 tcg_temp_free_i64(fp0);
6993 opn = "addr.ps";
6994 break;
6995 case FOP(26, 22):
6996 check_cp1_64bitmode(ctx);
6998 TCGv_i64 fp0 = tcg_temp_new_i64();
6999 TCGv_i64 fp1 = tcg_temp_new_i64();
7001 gen_load_fpr64(ctx, fp0, ft);
7002 gen_load_fpr64(ctx, fp1, fs);
7003 gen_helper_float_mulr_ps(fp0, fp0, fp1);
7004 tcg_temp_free_i64(fp1);
7005 gen_store_fpr64(ctx, fp0, fd);
7006 tcg_temp_free_i64(fp0);
7008 opn = "mulr.ps";
7009 break;
7010 case FOP(28, 22):
7011 check_cp1_64bitmode(ctx);
7013 TCGv_i64 fp0 = tcg_temp_new_i64();
7014 TCGv_i64 fp1 = tcg_temp_new_i64();
7016 gen_load_fpr64(ctx, fp0, fs);
7017 gen_load_fpr64(ctx, fp1, fd);
7018 gen_helper_float_recip2_ps(fp0, fp0, fp1);
7019 tcg_temp_free_i64(fp1);
7020 gen_store_fpr64(ctx, fp0, fd);
7021 tcg_temp_free_i64(fp0);
7023 opn = "recip2.ps";
7024 break;
7025 case FOP(29, 22):
7026 check_cp1_64bitmode(ctx);
7028 TCGv_i64 fp0 = tcg_temp_new_i64();
7030 gen_load_fpr64(ctx, fp0, fs);
7031 gen_helper_float_recip1_ps(fp0, fp0);
7032 gen_store_fpr64(ctx, fp0, fd);
7033 tcg_temp_free_i64(fp0);
7035 opn = "recip1.ps";
7036 break;
7037 case FOP(30, 22):
7038 check_cp1_64bitmode(ctx);
7040 TCGv_i64 fp0 = tcg_temp_new_i64();
7042 gen_load_fpr64(ctx, fp0, fs);
7043 gen_helper_float_rsqrt1_ps(fp0, fp0);
7044 gen_store_fpr64(ctx, fp0, fd);
7045 tcg_temp_free_i64(fp0);
7047 opn = "rsqrt1.ps";
7048 break;
7049 case FOP(31, 22):
7050 check_cp1_64bitmode(ctx);
7052 TCGv_i64 fp0 = tcg_temp_new_i64();
7053 TCGv_i64 fp1 = tcg_temp_new_i64();
7055 gen_load_fpr64(ctx, fp0, fs);
7056 gen_load_fpr64(ctx, fp1, ft);
7057 gen_helper_float_rsqrt2_ps(fp0, fp0, fp1);
7058 tcg_temp_free_i64(fp1);
7059 gen_store_fpr64(ctx, fp0, fd);
7060 tcg_temp_free_i64(fp0);
7062 opn = "rsqrt2.ps";
7063 break;
7064 case FOP(32, 22):
7065 check_cp1_64bitmode(ctx);
7067 TCGv_i32 fp0 = tcg_temp_new_i32();
7069 gen_load_fpr32h(fp0, fs);
7070 gen_helper_float_cvts_pu(fp0, fp0);
7071 gen_store_fpr32(fp0, fd);
7072 tcg_temp_free_i32(fp0);
7074 opn = "cvt.s.pu";
7075 break;
7076 case FOP(36, 22):
7077 check_cp1_64bitmode(ctx);
7079 TCGv_i64 fp0 = tcg_temp_new_i64();
7081 gen_load_fpr64(ctx, fp0, fs);
7082 gen_helper_float_cvtpw_ps(fp0, fp0);
7083 gen_store_fpr64(ctx, fp0, fd);
7084 tcg_temp_free_i64(fp0);
7086 opn = "cvt.pw.ps";
7087 break;
7088 case FOP(40, 22):
7089 check_cp1_64bitmode(ctx);
7091 TCGv_i32 fp0 = tcg_temp_new_i32();
7093 gen_load_fpr32(fp0, fs);
7094 gen_helper_float_cvts_pl(fp0, fp0);
7095 gen_store_fpr32(fp0, fd);
7096 tcg_temp_free_i32(fp0);
7098 opn = "cvt.s.pl";
7099 break;
7100 case FOP(44, 22):
7101 check_cp1_64bitmode(ctx);
7103 TCGv_i32 fp0 = tcg_temp_new_i32();
7104 TCGv_i32 fp1 = tcg_temp_new_i32();
7106 gen_load_fpr32(fp0, fs);
7107 gen_load_fpr32(fp1, ft);
7108 gen_store_fpr32h(fp0, fd);
7109 gen_store_fpr32(fp1, fd);
7110 tcg_temp_free_i32(fp0);
7111 tcg_temp_free_i32(fp1);
7113 opn = "pll.ps";
7114 break;
7115 case FOP(45, 22):
7116 check_cp1_64bitmode(ctx);
7118 TCGv_i32 fp0 = tcg_temp_new_i32();
7119 TCGv_i32 fp1 = tcg_temp_new_i32();
7121 gen_load_fpr32(fp0, fs);
7122 gen_load_fpr32h(fp1, ft);
7123 gen_store_fpr32(fp1, fd);
7124 gen_store_fpr32h(fp0, fd);
7125 tcg_temp_free_i32(fp0);
7126 tcg_temp_free_i32(fp1);
7128 opn = "plu.ps";
7129 break;
7130 case FOP(46, 22):
7131 check_cp1_64bitmode(ctx);
7133 TCGv_i32 fp0 = tcg_temp_new_i32();
7134 TCGv_i32 fp1 = tcg_temp_new_i32();
7136 gen_load_fpr32h(fp0, fs);
7137 gen_load_fpr32(fp1, ft);
7138 gen_store_fpr32(fp1, fd);
7139 gen_store_fpr32h(fp0, fd);
7140 tcg_temp_free_i32(fp0);
7141 tcg_temp_free_i32(fp1);
7143 opn = "pul.ps";
7144 break;
7145 case FOP(47, 22):
7146 check_cp1_64bitmode(ctx);
7148 TCGv_i32 fp0 = tcg_temp_new_i32();
7149 TCGv_i32 fp1 = tcg_temp_new_i32();
7151 gen_load_fpr32h(fp0, fs);
7152 gen_load_fpr32h(fp1, ft);
7153 gen_store_fpr32(fp1, fd);
7154 gen_store_fpr32h(fp0, fd);
7155 tcg_temp_free_i32(fp0);
7156 tcg_temp_free_i32(fp1);
7158 opn = "puu.ps";
7159 break;
7160 case FOP(48, 22):
7161 case FOP(49, 22):
7162 case FOP(50, 22):
7163 case FOP(51, 22):
7164 case FOP(52, 22):
7165 case FOP(53, 22):
7166 case FOP(54, 22):
7167 case FOP(55, 22):
7168 case FOP(56, 22):
7169 case FOP(57, 22):
7170 case FOP(58, 22):
7171 case FOP(59, 22):
7172 case FOP(60, 22):
7173 case FOP(61, 22):
7174 case FOP(62, 22):
7175 case FOP(63, 22):
7176 check_cp1_64bitmode(ctx);
7178 TCGv_i64 fp0 = tcg_temp_new_i64();
7179 TCGv_i64 fp1 = tcg_temp_new_i64();
7181 gen_load_fpr64(ctx, fp0, fs);
7182 gen_load_fpr64(ctx, fp1, ft);
7183 if (ctx->opcode & (1 << 6)) {
7184 gen_cmpabs_ps(func-48, fp0, fp1, cc);
7185 opn = condnames_abs[func-48];
7186 } else {
7187 gen_cmp_ps(func-48, fp0, fp1, cc);
7188 opn = condnames[func-48];
7190 tcg_temp_free_i64(fp0);
7191 tcg_temp_free_i64(fp1);
7193 break;
7194 default:
7195 MIPS_INVAL(opn);
7196 generate_exception (ctx, EXCP_RI);
7197 return;
7199 switch (optype) {
7200 case BINOP:
7201 MIPS_DEBUG("%s %s, %s, %s", opn, fregnames[fd], fregnames[fs], fregnames[ft]);
7202 break;
7203 case CMPOP:
7204 MIPS_DEBUG("%s %s,%s", opn, fregnames[fs], fregnames[ft]);
7205 break;
7206 default:
7207 MIPS_DEBUG("%s %s,%s", opn, fregnames[fd], fregnames[fs]);
7208 break;
7212 /* Coprocessor 3 (FPU) */
7213 static void gen_flt3_ldst (DisasContext *ctx, uint32_t opc,
7214 int fd, int fs, int base, int index)
7216 const char *opn = "extended float load/store";
7217 int store = 0;
7218 TCGv t0 = tcg_temp_new();
7220 if (base == 0) {
7221 gen_load_gpr(t0, index);
7222 } else if (index == 0) {
7223 gen_load_gpr(t0, base);
7224 } else {
7225 gen_load_gpr(t0, index);
7226 gen_op_addr_add(ctx, t0, cpu_gpr[base], t0);
7228 /* Don't do NOP if destination is zero: we must perform the actual
7229 memory access. */
7230 save_cpu_state(ctx, 0);
7231 switch (opc) {
7232 case OPC_LWXC1:
7233 check_cop1x(ctx);
7235 TCGv_i32 fp0 = tcg_temp_new_i32();
7237 tcg_gen_qemu_ld32s(t0, t0, ctx->mem_idx);
7238 tcg_gen_trunc_tl_i32(fp0, t0);
7239 gen_store_fpr32(fp0, fd);
7240 tcg_temp_free_i32(fp0);
7242 opn = "lwxc1";
7243 break;
7244 case OPC_LDXC1:
7245 check_cop1x(ctx);
7246 check_cp1_registers(ctx, fd);
7248 TCGv_i64 fp0 = tcg_temp_new_i64();
7250 tcg_gen_qemu_ld64(fp0, t0, ctx->mem_idx);
7251 gen_store_fpr64(ctx, fp0, fd);
7252 tcg_temp_free_i64(fp0);
7254 opn = "ldxc1";
7255 break;
7256 case OPC_LUXC1:
7257 check_cp1_64bitmode(ctx);
7258 tcg_gen_andi_tl(t0, t0, ~0x7);
7260 TCGv_i64 fp0 = tcg_temp_new_i64();
7262 tcg_gen_qemu_ld64(fp0, t0, ctx->mem_idx);
7263 gen_store_fpr64(ctx, fp0, fd);
7264 tcg_temp_free_i64(fp0);
7266 opn = "luxc1";
7267 break;
7268 case OPC_SWXC1:
7269 check_cop1x(ctx);
7271 TCGv_i32 fp0 = tcg_temp_new_i32();
7272 TCGv t1 = tcg_temp_new();
7274 gen_load_fpr32(fp0, fs);
7275 tcg_gen_extu_i32_tl(t1, fp0);
7276 tcg_gen_qemu_st32(t1, t0, ctx->mem_idx);
7277 tcg_temp_free_i32(fp0);
7278 tcg_temp_free(t1);
7280 opn = "swxc1";
7281 store = 1;
7282 break;
7283 case OPC_SDXC1:
7284 check_cop1x(ctx);
7285 check_cp1_registers(ctx, fs);
7287 TCGv_i64 fp0 = tcg_temp_new_i64();
7289 gen_load_fpr64(ctx, fp0, fs);
7290 tcg_gen_qemu_st64(fp0, t0, ctx->mem_idx);
7291 tcg_temp_free_i64(fp0);
7293 opn = "sdxc1";
7294 store = 1;
7295 break;
7296 case OPC_SUXC1:
7297 check_cp1_64bitmode(ctx);
7298 tcg_gen_andi_tl(t0, t0, ~0x7);
7300 TCGv_i64 fp0 = tcg_temp_new_i64();
7302 gen_load_fpr64(ctx, fp0, fs);
7303 tcg_gen_qemu_st64(fp0, t0, ctx->mem_idx);
7304 tcg_temp_free_i64(fp0);
7306 opn = "suxc1";
7307 store = 1;
7308 break;
7310 tcg_temp_free(t0);
7311 MIPS_DEBUG("%s %s, %s(%s)", opn, fregnames[store ? fs : fd],
7312 regnames[index], regnames[base]);
7315 static void gen_flt3_arith (DisasContext *ctx, uint32_t opc,
7316 int fd, int fr, int fs, int ft)
7318 const char *opn = "flt3_arith";
7320 switch (opc) {
7321 case OPC_ALNV_PS:
7322 check_cp1_64bitmode(ctx);
7324 TCGv t0 = tcg_temp_local_new();
7325 TCGv_i32 fp = tcg_temp_new_i32();
7326 TCGv_i32 fph = tcg_temp_new_i32();
7327 int l1 = gen_new_label();
7328 int l2 = gen_new_label();
7330 gen_load_gpr(t0, fr);
7331 tcg_gen_andi_tl(t0, t0, 0x7);
7333 tcg_gen_brcondi_tl(TCG_COND_NE, t0, 0, l1);
7334 gen_load_fpr32(fp, fs);
7335 gen_load_fpr32h(fph, fs);
7336 gen_store_fpr32(fp, fd);
7337 gen_store_fpr32h(fph, fd);
7338 tcg_gen_br(l2);
7339 gen_set_label(l1);
7340 tcg_gen_brcondi_tl(TCG_COND_NE, t0, 4, l2);
7341 tcg_temp_free(t0);
7342 #ifdef TARGET_WORDS_BIGENDIAN
7343 gen_load_fpr32(fp, fs);
7344 gen_load_fpr32h(fph, ft);
7345 gen_store_fpr32h(fp, fd);
7346 gen_store_fpr32(fph, fd);
7347 #else
7348 gen_load_fpr32h(fph, fs);
7349 gen_load_fpr32(fp, ft);
7350 gen_store_fpr32(fph, fd);
7351 gen_store_fpr32h(fp, fd);
7352 #endif
7353 gen_set_label(l2);
7354 tcg_temp_free_i32(fp);
7355 tcg_temp_free_i32(fph);
7357 opn = "alnv.ps";
7358 break;
7359 case OPC_MADD_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_muladd_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 = "madd.s";
7376 break;
7377 case OPC_MADD_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_muladd_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 = "madd.d";
7395 break;
7396 case OPC_MADD_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_muladd_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 = "madd.ps";
7413 break;
7414 case OPC_MSUB_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_mulsub_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 = "msub.s";
7431 break;
7432 case OPC_MSUB_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_mulsub_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 = "msub.d";
7450 break;
7451 case OPC_MSUB_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_mulsub_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 = "msub.ps";
7468 break;
7469 case OPC_NMADD_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_nmuladd_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 = "nmadd.s";
7486 break;
7487 case OPC_NMADD_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_nmuladd_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 = "nmadd.d";
7505 break;
7506 case OPC_NMADD_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_nmuladd_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 = "nmadd.ps";
7523 break;
7524 case OPC_NMSUB_S:
7525 check_cop1x(ctx);
7527 TCGv_i32 fp0 = tcg_temp_new_i32();
7528 TCGv_i32 fp1 = tcg_temp_new_i32();
7529 TCGv_i32 fp2 = tcg_temp_new_i32();
7531 gen_load_fpr32(fp0, fs);
7532 gen_load_fpr32(fp1, ft);
7533 gen_load_fpr32(fp2, fr);
7534 gen_helper_float_nmulsub_s(fp2, fp0, fp1, fp2);
7535 tcg_temp_free_i32(fp0);
7536 tcg_temp_free_i32(fp1);
7537 gen_store_fpr32(fp2, fd);
7538 tcg_temp_free_i32(fp2);
7540 opn = "nmsub.s";
7541 break;
7542 case OPC_NMSUB_D:
7543 check_cop1x(ctx);
7544 check_cp1_registers(ctx, fd | fs | ft | fr);
7546 TCGv_i64 fp0 = tcg_temp_new_i64();
7547 TCGv_i64 fp1 = tcg_temp_new_i64();
7548 TCGv_i64 fp2 = tcg_temp_new_i64();
7550 gen_load_fpr64(ctx, fp0, fs);
7551 gen_load_fpr64(ctx, fp1, ft);
7552 gen_load_fpr64(ctx, fp2, fr);
7553 gen_helper_float_nmulsub_d(fp2, fp0, fp1, fp2);
7554 tcg_temp_free_i64(fp0);
7555 tcg_temp_free_i64(fp1);
7556 gen_store_fpr64(ctx, fp2, fd);
7557 tcg_temp_free_i64(fp2);
7559 opn = "nmsub.d";
7560 break;
7561 case OPC_NMSUB_PS:
7562 check_cp1_64bitmode(ctx);
7564 TCGv_i64 fp0 = tcg_temp_new_i64();
7565 TCGv_i64 fp1 = tcg_temp_new_i64();
7566 TCGv_i64 fp2 = tcg_temp_new_i64();
7568 gen_load_fpr64(ctx, fp0, fs);
7569 gen_load_fpr64(ctx, fp1, ft);
7570 gen_load_fpr64(ctx, fp2, fr);
7571 gen_helper_float_nmulsub_ps(fp2, fp0, fp1, fp2);
7572 tcg_temp_free_i64(fp0);
7573 tcg_temp_free_i64(fp1);
7574 gen_store_fpr64(ctx, fp2, fd);
7575 tcg_temp_free_i64(fp2);
7577 opn = "nmsub.ps";
7578 break;
7579 default:
7580 MIPS_INVAL(opn);
7581 generate_exception (ctx, EXCP_RI);
7582 return;
7584 MIPS_DEBUG("%s %s, %s, %s, %s", opn, fregnames[fd], fregnames[fr],
7585 fregnames[fs], fregnames[ft]);
7588 static void handle_delay_slot (CPUState *env, DisasContext *ctx,
7589 int insn_bytes)
7591 if (ctx->hflags & MIPS_HFLAG_BMASK) {
7592 int proc_hflags = ctx->hflags & MIPS_HFLAG_BMASK;
7593 /* Branches completion */
7594 ctx->hflags &= ~MIPS_HFLAG_BMASK;
7595 ctx->bstate = BS_BRANCH;
7596 save_cpu_state(ctx, 0);
7597 /* FIXME: Need to clear can_do_io. */
7598 switch (proc_hflags & MIPS_HFLAG_BMASK_BASE) {
7599 case MIPS_HFLAG_B:
7600 /* unconditional branch */
7601 MIPS_DEBUG("unconditional branch");
7602 if (proc_hflags & MIPS_HFLAG_BX) {
7603 tcg_gen_xori_i32(hflags, hflags, MIPS_HFLAG_M16);
7605 gen_goto_tb(ctx, 0, ctx->btarget);
7606 break;
7607 case MIPS_HFLAG_BL:
7608 /* blikely taken case */
7609 MIPS_DEBUG("blikely branch taken");
7610 gen_goto_tb(ctx, 0, ctx->btarget);
7611 break;
7612 case MIPS_HFLAG_BC:
7613 /* Conditional branch */
7614 MIPS_DEBUG("conditional branch");
7616 int l1 = gen_new_label();
7618 tcg_gen_brcondi_tl(TCG_COND_NE, bcond, 0, l1);
7619 gen_goto_tb(ctx, 1, ctx->pc + insn_bytes);
7620 gen_set_label(l1);
7621 gen_goto_tb(ctx, 0, ctx->btarget);
7623 break;
7624 case MIPS_HFLAG_BR:
7625 /* unconditional branch to register */
7626 MIPS_DEBUG("branch to register");
7627 if (env->insn_flags & ASE_MIPS16) {
7628 TCGv t0 = tcg_temp_new();
7629 TCGv_i32 t1 = tcg_temp_new_i32();
7631 tcg_gen_andi_tl(t0, btarget, 0x1);
7632 tcg_gen_trunc_tl_i32(t1, t0);
7633 tcg_temp_free(t0);
7634 tcg_gen_andi_i32(hflags, hflags, ~(uint32_t)MIPS_HFLAG_M16);
7635 tcg_gen_shli_i32(t1, t1, MIPS_HFLAG_M16_SHIFT);
7636 tcg_gen_or_i32(hflags, hflags, t1);
7637 tcg_temp_free_i32(t1);
7639 tcg_gen_andi_tl(cpu_PC, btarget, ~(target_ulong)0x1);
7640 } else {
7641 tcg_gen_mov_tl(cpu_PC, btarget);
7643 if (ctx->singlestep_enabled) {
7644 save_cpu_state(ctx, 0);
7645 gen_helper_0i(raise_exception, EXCP_DEBUG);
7647 tcg_gen_exit_tb(0);
7648 break;
7649 default:
7650 MIPS_DEBUG("unknown branch");
7651 break;
7656 /* ISA extensions (ASEs) */
7657 /* MIPS16 extension to MIPS32 */
7659 /* MIPS16 major opcodes */
7660 enum {
7661 M16_OPC_ADDIUSP = 0x00,
7662 M16_OPC_ADDIUPC = 0x01,
7663 M16_OPC_B = 0x02,
7664 M16_OPC_JAL = 0x03,
7665 M16_OPC_BEQZ = 0x04,
7666 M16_OPC_BNEQZ = 0x05,
7667 M16_OPC_SHIFT = 0x06,
7668 M16_OPC_LD = 0x07,
7669 M16_OPC_RRIA = 0x08,
7670 M16_OPC_ADDIU8 = 0x09,
7671 M16_OPC_SLTI = 0x0a,
7672 M16_OPC_SLTIU = 0x0b,
7673 M16_OPC_I8 = 0x0c,
7674 M16_OPC_LI = 0x0d,
7675 M16_OPC_CMPI = 0x0e,
7676 M16_OPC_SD = 0x0f,
7677 M16_OPC_LB = 0x10,
7678 M16_OPC_LH = 0x11,
7679 M16_OPC_LWSP = 0x12,
7680 M16_OPC_LW = 0x13,
7681 M16_OPC_LBU = 0x14,
7682 M16_OPC_LHU = 0x15,
7683 M16_OPC_LWPC = 0x16,
7684 M16_OPC_LWU = 0x17,
7685 M16_OPC_SB = 0x18,
7686 M16_OPC_SH = 0x19,
7687 M16_OPC_SWSP = 0x1a,
7688 M16_OPC_SW = 0x1b,
7689 M16_OPC_RRR = 0x1c,
7690 M16_OPC_RR = 0x1d,
7691 M16_OPC_EXTEND = 0x1e,
7692 M16_OPC_I64 = 0x1f
7695 /* I8 funct field */
7696 enum {
7697 I8_BTEQZ = 0x0,
7698 I8_BTNEZ = 0x1,
7699 I8_SWRASP = 0x2,
7700 I8_ADJSP = 0x3,
7701 I8_SVRS = 0x4,
7702 I8_MOV32R = 0x5,
7703 I8_MOVR32 = 0x7
7706 /* RRR f field */
7707 enum {
7708 RRR_DADDU = 0x0,
7709 RRR_ADDU = 0x1,
7710 RRR_DSUBU = 0x2,
7711 RRR_SUBU = 0x3
7714 /* RR funct field */
7715 enum {
7716 RR_JR = 0x00,
7717 RR_SDBBP = 0x01,
7718 RR_SLT = 0x02,
7719 RR_SLTU = 0x03,
7720 RR_SLLV = 0x04,
7721 RR_BREAK = 0x05,
7722 RR_SRLV = 0x06,
7723 RR_SRAV = 0x07,
7724 RR_DSRL = 0x08,
7725 RR_CMP = 0x0a,
7726 RR_NEG = 0x0b,
7727 RR_AND = 0x0c,
7728 RR_OR = 0x0d,
7729 RR_XOR = 0x0e,
7730 RR_NOT = 0x0f,
7731 RR_MFHI = 0x10,
7732 RR_CNVT = 0x11,
7733 RR_MFLO = 0x12,
7734 RR_DSRA = 0x13,
7735 RR_DSLLV = 0x14,
7736 RR_DSRLV = 0x16,
7737 RR_DSRAV = 0x17,
7738 RR_MULT = 0x18,
7739 RR_MULTU = 0x19,
7740 RR_DIV = 0x1a,
7741 RR_DIVU = 0x1b,
7742 RR_DMULT = 0x1c,
7743 RR_DMULTU = 0x1d,
7744 RR_DDIV = 0x1e,
7745 RR_DDIVU = 0x1f
7748 /* I64 funct field */
7749 enum {
7750 I64_LDSP = 0x0,
7751 I64_SDSP = 0x1,
7752 I64_SDRASP = 0x2,
7753 I64_DADJSP = 0x3,
7754 I64_LDPC = 0x4,
7755 I64_DADDIU5 = 0x5,
7756 I64_DADDIUPC = 0x6,
7757 I64_DADDIUSP = 0x7
7760 /* RR ry field for CNVT */
7761 enum {
7762 RR_RY_CNVT_ZEB = 0x0,
7763 RR_RY_CNVT_ZEH = 0x1,
7764 RR_RY_CNVT_ZEW = 0x2,
7765 RR_RY_CNVT_SEB = 0x4,
7766 RR_RY_CNVT_SEH = 0x5,
7767 RR_RY_CNVT_SEW = 0x6,
7770 static int xlat (int r)
7772 static int map[] = { 16, 17, 2, 3, 4, 5, 6, 7 };
7774 return map[r];
7777 static void gen_mips16_save (DisasContext *ctx,
7778 int xsregs, int aregs,
7779 int do_ra, int do_s0, int do_s1,
7780 int framesize)
7782 TCGv t0 = tcg_temp_new();
7783 TCGv t1 = tcg_temp_new();
7784 int args, astatic;
7786 switch (aregs) {
7787 case 0:
7788 case 1:
7789 case 2:
7790 case 3:
7791 case 11:
7792 args = 0;
7793 break;
7794 case 4:
7795 case 5:
7796 case 6:
7797 case 7:
7798 args = 1;
7799 break;
7800 case 8:
7801 case 9:
7802 case 10:
7803 args = 2;
7804 break;
7805 case 12:
7806 case 13:
7807 args = 3;
7808 break;
7809 case 14:
7810 args = 4;
7811 break;
7812 default:
7813 generate_exception(ctx, EXCP_RI);
7814 return;
7817 switch (args) {
7818 case 4:
7819 gen_base_offset_addr(ctx, t0, 29, 12);
7820 gen_load_gpr(t1, 7);
7821 op_ldst_sw(t1, t0, ctx);
7822 /* Fall through */
7823 case 3:
7824 gen_base_offset_addr(ctx, t0, 29, 8);
7825 gen_load_gpr(t1, 6);
7826 op_ldst_sw(t1, t0, ctx);
7827 /* Fall through */
7828 case 2:
7829 gen_base_offset_addr(ctx, t0, 29, 4);
7830 gen_load_gpr(t1, 5);
7831 op_ldst_sw(t1, t0, ctx);
7832 /* Fall through */
7833 case 1:
7834 gen_base_offset_addr(ctx, t0, 29, 0);
7835 gen_load_gpr(t1, 4);
7836 op_ldst_sw(t1, t0, ctx);
7839 gen_load_gpr(t0, 29);
7841 #define DECR_AND_STORE(reg) do { \
7842 tcg_gen_subi_tl(t0, t0, 4); \
7843 gen_load_gpr(t1, reg); \
7844 op_ldst_sw(t1, t0, ctx); \
7845 } while (0)
7847 if (do_ra) {
7848 DECR_AND_STORE(31);
7851 switch (xsregs) {
7852 case 7:
7853 DECR_AND_STORE(30);
7854 /* Fall through */
7855 case 6:
7856 DECR_AND_STORE(23);
7857 /* Fall through */
7858 case 5:
7859 DECR_AND_STORE(22);
7860 /* Fall through */
7861 case 4:
7862 DECR_AND_STORE(21);
7863 /* Fall through */
7864 case 3:
7865 DECR_AND_STORE(20);
7866 /* Fall through */
7867 case 2:
7868 DECR_AND_STORE(19);
7869 /* Fall through */
7870 case 1:
7871 DECR_AND_STORE(18);
7874 if (do_s1) {
7875 DECR_AND_STORE(17);
7877 if (do_s0) {
7878 DECR_AND_STORE(16);
7881 switch (aregs) {
7882 case 0:
7883 case 4:
7884 case 8:
7885 case 12:
7886 case 14:
7887 astatic = 0;
7888 break;
7889 case 1:
7890 case 5:
7891 case 9:
7892 case 13:
7893 astatic = 1;
7894 break;
7895 case 2:
7896 case 6:
7897 case 10:
7898 astatic = 2;
7899 break;
7900 case 3:
7901 case 7:
7902 astatic = 3;
7903 break;
7904 case 11:
7905 astatic = 4;
7906 break;
7907 default:
7908 generate_exception(ctx, EXCP_RI);
7909 return;
7912 if (astatic > 0) {
7913 DECR_AND_STORE(7);
7914 if (astatic > 1) {
7915 DECR_AND_STORE(6);
7916 if (astatic > 2) {
7917 DECR_AND_STORE(5);
7918 if (astatic > 3) {
7919 DECR_AND_STORE(4);
7924 #undef DECR_AND_STORE
7926 tcg_gen_subi_tl(cpu_gpr[29], cpu_gpr[29], framesize);
7927 tcg_temp_free(t0);
7928 tcg_temp_free(t1);
7931 static void gen_mips16_restore (DisasContext *ctx,
7932 int xsregs, int aregs,
7933 int do_ra, int do_s0, int do_s1,
7934 int framesize)
7936 int astatic;
7937 TCGv t0 = tcg_temp_new();
7938 TCGv t1 = tcg_temp_new();
7940 tcg_gen_addi_tl(t0, cpu_gpr[29], framesize);
7942 #define DECR_AND_LOAD(reg) do { \
7943 tcg_gen_subi_tl(t0, t0, 4); \
7944 op_ldst_lw(t1, t0, ctx); \
7945 gen_store_gpr(t1, reg); \
7946 } while (0)
7948 if (do_ra) {
7949 DECR_AND_LOAD(31);
7952 switch (xsregs) {
7953 case 7:
7954 DECR_AND_LOAD(30);
7955 /* Fall through */
7956 case 6:
7957 DECR_AND_LOAD(23);
7958 /* Fall through */
7959 case 5:
7960 DECR_AND_LOAD(22);
7961 /* Fall through */
7962 case 4:
7963 DECR_AND_LOAD(21);
7964 /* Fall through */
7965 case 3:
7966 DECR_AND_LOAD(20);
7967 /* Fall through */
7968 case 2:
7969 DECR_AND_LOAD(19);
7970 /* Fall through */
7971 case 1:
7972 DECR_AND_LOAD(18);
7975 if (do_s1) {
7976 DECR_AND_LOAD(17);
7978 if (do_s0) {
7979 DECR_AND_LOAD(16);
7982 switch (aregs) {
7983 case 0:
7984 case 4:
7985 case 8:
7986 case 12:
7987 case 14:
7988 astatic = 0;
7989 break;
7990 case 1:
7991 case 5:
7992 case 9:
7993 case 13:
7994 astatic = 1;
7995 break;
7996 case 2:
7997 case 6:
7998 case 10:
7999 astatic = 2;
8000 break;
8001 case 3:
8002 case 7:
8003 astatic = 3;
8004 break;
8005 case 11:
8006 astatic = 4;
8007 break;
8008 default:
8009 generate_exception(ctx, EXCP_RI);
8010 return;
8013 if (astatic > 0) {
8014 DECR_AND_LOAD(7);
8015 if (astatic > 1) {
8016 DECR_AND_LOAD(6);
8017 if (astatic > 2) {
8018 DECR_AND_LOAD(5);
8019 if (astatic > 3) {
8020 DECR_AND_LOAD(4);
8025 #undef DECR_AND_LOAD
8027 tcg_gen_addi_tl(cpu_gpr[29], cpu_gpr[29], framesize);
8028 tcg_temp_free(t0);
8029 tcg_temp_free(t1);
8032 static void gen_addiupc (DisasContext *ctx, int rx, int imm,
8033 int is_64_bit, int extended)
8035 TCGv t0;
8037 if (extended && (ctx->hflags & MIPS_HFLAG_BMASK)) {
8038 generate_exception(ctx, EXCP_RI);
8039 return;
8042 t0 = tcg_temp_new();
8044 tcg_gen_movi_tl(t0, pc_relative_pc(ctx));
8045 tcg_gen_addi_tl(cpu_gpr[rx], t0, imm);
8046 if (!is_64_bit) {
8047 tcg_gen_ext32s_tl(cpu_gpr[rx], cpu_gpr[rx]);
8050 tcg_temp_free(t0);
8053 #if defined(TARGET_MIPS64)
8054 static void decode_i64_mips16 (CPUState *env, DisasContext *ctx,
8055 int ry, int funct, int16_t offset,
8056 int extended)
8058 switch (funct) {
8059 case I64_LDSP:
8060 check_mips_64(ctx);
8061 offset = extended ? offset : offset << 3;
8062 gen_ldst(ctx, OPC_LD, ry, 29, offset);
8063 break;
8064 case I64_SDSP:
8065 check_mips_64(ctx);
8066 offset = extended ? offset : offset << 3;
8067 gen_ldst(ctx, OPC_SD, ry, 29, offset);
8068 break;
8069 case I64_SDRASP:
8070 check_mips_64(ctx);
8071 offset = extended ? offset : (ctx->opcode & 0xff) << 3;
8072 gen_ldst(ctx, OPC_SD, 31, 29, offset);
8073 break;
8074 case I64_DADJSP:
8075 check_mips_64(ctx);
8076 offset = extended ? offset : ((int8_t)ctx->opcode) << 3;
8077 gen_arith_imm(env, ctx, OPC_DADDIU, 29, 29, offset);
8078 break;
8079 case I64_LDPC:
8080 if (extended && (ctx->hflags & MIPS_HFLAG_BMASK)) {
8081 generate_exception(ctx, EXCP_RI);
8082 } else {
8083 offset = extended ? offset : offset << 3;
8084 gen_ldst(ctx, OPC_LDPC, ry, 0, offset);
8086 break;
8087 case I64_DADDIU5:
8088 check_mips_64(ctx);
8089 offset = extended ? offset : ((int8_t)(offset << 3)) >> 3;
8090 gen_arith_imm(env, ctx, OPC_DADDIU, ry, ry, offset);
8091 break;
8092 case I64_DADDIUPC:
8093 check_mips_64(ctx);
8094 offset = extended ? offset : offset << 2;
8095 gen_addiupc(ctx, ry, offset, 1, extended);
8096 break;
8097 case I64_DADDIUSP:
8098 check_mips_64(ctx);
8099 offset = extended ? offset : offset << 2;
8100 gen_arith_imm(env, ctx, OPC_DADDIU, ry, 29, offset);
8101 break;
8104 #endif
8106 static int decode_extended_mips16_opc (CPUState *env, DisasContext *ctx,
8107 int *is_branch)
8109 int extend = lduw_code(ctx->pc + 2);
8110 int op, rx, ry, funct, sa;
8111 int16_t imm, offset;
8113 ctx->opcode = (ctx->opcode << 16) | extend;
8114 op = (ctx->opcode >> 11) & 0x1f;
8115 sa = (ctx->opcode >> 22) & 0x1f;
8116 funct = (ctx->opcode >> 8) & 0x7;
8117 rx = xlat((ctx->opcode >> 8) & 0x7);
8118 ry = xlat((ctx->opcode >> 5) & 0x7);
8119 offset = imm = (int16_t) (((ctx->opcode >> 16) & 0x1f) << 11
8120 | ((ctx->opcode >> 21) & 0x3f) << 5
8121 | (ctx->opcode & 0x1f));
8123 /* The extended opcodes cleverly reuse the opcodes from their 16-bit
8124 counterparts. */
8125 switch (op) {
8126 case M16_OPC_ADDIUSP:
8127 gen_arith_imm(env, ctx, OPC_ADDIU, rx, 29, imm);
8128 break;
8129 case M16_OPC_ADDIUPC:
8130 gen_addiupc(ctx, rx, imm, 0, 1);
8131 break;
8132 case M16_OPC_B:
8133 gen_compute_branch(ctx, OPC_BEQ, 4, 0, 0, offset << 1);
8134 /* No delay slot, so just process as a normal instruction */
8135 break;
8136 case M16_OPC_BEQZ:
8137 gen_compute_branch(ctx, OPC_BEQ, 4, rx, 0, offset << 1);
8138 /* No delay slot, so just process as a normal instruction */
8139 break;
8140 case M16_OPC_BNEQZ:
8141 gen_compute_branch(ctx, OPC_BNE, 4, rx, 0, offset << 1);
8142 /* No delay slot, so just process as a normal instruction */
8143 break;
8144 case M16_OPC_SHIFT:
8145 switch (ctx->opcode & 0x3) {
8146 case 0x0:
8147 gen_shift_imm(env, ctx, OPC_SLL, rx, ry, sa);
8148 break;
8149 case 0x1:
8150 #if defined(TARGET_MIPS64)
8151 check_mips_64(ctx);
8152 gen_shift_imm(env, ctx, OPC_DSLL, rx, ry, sa);
8153 #else
8154 generate_exception(ctx, EXCP_RI);
8155 #endif
8156 break;
8157 case 0x2:
8158 gen_shift_imm(env, ctx, OPC_SRL, rx, ry, sa);
8159 break;
8160 case 0x3:
8161 gen_shift_imm(env, ctx, OPC_SRA, rx, ry, sa);
8162 break;
8164 break;
8165 #if defined(TARGET_MIPS64)
8166 case M16_OPC_LD:
8167 check_mips_64(ctx);
8168 gen_ldst(ctx, OPC_LD, ry, rx, offset);
8169 break;
8170 #endif
8171 case M16_OPC_RRIA:
8172 imm = ctx->opcode & 0xf;
8173 imm = imm | ((ctx->opcode >> 20) & 0x7f) << 4;
8174 imm = imm | ((ctx->opcode >> 16) & 0xf) << 11;
8175 imm = (int16_t) (imm << 1) >> 1;
8176 if ((ctx->opcode >> 4) & 0x1) {
8177 #if defined(TARGET_MIPS64)
8178 check_mips_64(ctx);
8179 gen_arith_imm(env, ctx, OPC_DADDIU, ry, rx, imm);
8180 #else
8181 generate_exception(ctx, EXCP_RI);
8182 #endif
8183 } else {
8184 gen_arith_imm(env, ctx, OPC_ADDIU, ry, rx, imm);
8186 break;
8187 case M16_OPC_ADDIU8:
8188 gen_arith_imm(env, ctx, OPC_ADDIU, rx, rx, imm);
8189 break;
8190 case M16_OPC_SLTI:
8191 gen_slt_imm(env, OPC_SLTI, 24, rx, imm);
8192 break;
8193 case M16_OPC_SLTIU:
8194 gen_slt_imm(env, OPC_SLTIU, 24, rx, imm);
8195 break;
8196 case M16_OPC_I8:
8197 switch (funct) {
8198 case I8_BTEQZ:
8199 gen_compute_branch(ctx, OPC_BEQ, 4, 24, 0, offset << 1);
8200 break;
8201 case I8_BTNEZ:
8202 gen_compute_branch(ctx, OPC_BNE, 4, 24, 0, offset << 1);
8203 break;
8204 case I8_SWRASP:
8205 gen_ldst(ctx, OPC_SW, 31, 29, imm);
8206 break;
8207 case I8_ADJSP:
8208 gen_arith_imm(env, ctx, OPC_ADDIU, 29, 29, imm);
8209 break;
8210 case I8_SVRS:
8212 int xsregs = (ctx->opcode >> 24) & 0x7;
8213 int aregs = (ctx->opcode >> 16) & 0xf;
8214 int do_ra = (ctx->opcode >> 6) & 0x1;
8215 int do_s0 = (ctx->opcode >> 5) & 0x1;
8216 int do_s1 = (ctx->opcode >> 4) & 0x1;
8217 int framesize = (((ctx->opcode >> 20) & 0xf) << 4
8218 | (ctx->opcode & 0xf)) << 3;
8220 if (ctx->opcode & (1 << 7)) {
8221 gen_mips16_save(ctx, xsregs, aregs,
8222 do_ra, do_s0, do_s1,
8223 framesize);
8224 } else {
8225 gen_mips16_restore(ctx, xsregs, aregs,
8226 do_ra, do_s0, do_s1,
8227 framesize);
8230 break;
8231 default:
8232 generate_exception(ctx, EXCP_RI);
8233 break;
8235 break;
8236 case M16_OPC_LI:
8237 tcg_gen_movi_tl(cpu_gpr[rx], (uint16_t) imm);
8238 break;
8239 case M16_OPC_CMPI:
8240 tcg_gen_xori_tl(cpu_gpr[24], cpu_gpr[rx], (uint16_t) imm);
8241 break;
8242 #if defined(TARGET_MIPS64)
8243 case M16_OPC_SD:
8244 gen_ldst(ctx, OPC_SD, ry, rx, offset);
8245 break;
8246 #endif
8247 case M16_OPC_LB:
8248 gen_ldst(ctx, OPC_LB, ry, rx, offset);
8249 break;
8250 case M16_OPC_LH:
8251 gen_ldst(ctx, OPC_LH, ry, rx, offset);
8252 break;
8253 case M16_OPC_LWSP:
8254 gen_ldst(ctx, OPC_LW, rx, 29, offset);
8255 break;
8256 case M16_OPC_LW:
8257 gen_ldst(ctx, OPC_LW, ry, rx, offset);
8258 break;
8259 case M16_OPC_LBU:
8260 gen_ldst(ctx, OPC_LBU, ry, rx, offset);
8261 break;
8262 case M16_OPC_LHU:
8263 gen_ldst(ctx, OPC_LHU, ry, rx, offset);
8264 break;
8265 case M16_OPC_LWPC:
8266 gen_ldst(ctx, OPC_LWPC, rx, 0, offset);
8267 break;
8268 #if defined(TARGET_MIPS64)
8269 case M16_OPC_LWU:
8270 gen_ldst(ctx, OPC_LWU, ry, rx, offset);
8271 break;
8272 #endif
8273 case M16_OPC_SB:
8274 gen_ldst(ctx, OPC_SB, ry, rx, offset);
8275 break;
8276 case M16_OPC_SH:
8277 gen_ldst(ctx, OPC_SH, ry, rx, offset);
8278 break;
8279 case M16_OPC_SWSP:
8280 gen_ldst(ctx, OPC_SW, rx, 29, offset);
8281 break;
8282 case M16_OPC_SW:
8283 gen_ldst(ctx, OPC_SW, ry, rx, offset);
8284 break;
8285 #if defined(TARGET_MIPS64)
8286 case M16_OPC_I64:
8287 decode_i64_mips16(env, ctx, ry, funct, offset, 1);
8288 break;
8289 #endif
8290 default:
8291 generate_exception(ctx, EXCP_RI);
8292 break;
8295 return 4;
8298 static int decode_mips16_opc (CPUState *env, DisasContext *ctx,
8299 int *is_branch)
8301 int rx, ry;
8302 int sa;
8303 int op, cnvt_op, op1, offset;
8304 int funct;
8305 int n_bytes;
8307 op = (ctx->opcode >> 11) & 0x1f;
8308 sa = (ctx->opcode >> 2) & 0x7;
8309 sa = sa == 0 ? 8 : sa;
8310 rx = xlat((ctx->opcode >> 8) & 0x7);
8311 cnvt_op = (ctx->opcode >> 5) & 0x7;
8312 ry = xlat((ctx->opcode >> 5) & 0x7);
8313 op1 = offset = ctx->opcode & 0x1f;
8315 n_bytes = 2;
8317 switch (op) {
8318 case M16_OPC_ADDIUSP:
8320 int16_t imm = ((uint8_t) ctx->opcode) << 2;
8322 gen_arith_imm(env, ctx, OPC_ADDIU, rx, 29, imm);
8324 break;
8325 case M16_OPC_ADDIUPC:
8326 gen_addiupc(ctx, rx, ((uint8_t) ctx->opcode) << 2, 0, 0);
8327 break;
8328 case M16_OPC_B:
8329 offset = (ctx->opcode & 0x7ff) << 1;
8330 offset = (int16_t)(offset << 4) >> 4;
8331 gen_compute_branch(ctx, OPC_BEQ, 2, 0, 0, offset);
8332 /* No delay slot, so just process as a normal instruction */
8333 break;
8334 case M16_OPC_JAL:
8335 offset = lduw_code(ctx->pc + 2);
8336 offset = (((ctx->opcode & 0x1f) << 21)
8337 | ((ctx->opcode >> 5) & 0x1f) << 16
8338 | offset) << 2;
8339 op = ((ctx->opcode >> 10) & 0x1) ? OPC_JALX : OPC_JAL;
8340 gen_compute_branch(ctx, op, 4, rx, ry, offset);
8341 n_bytes = 4;
8342 *is_branch = 1;
8343 break;
8344 case M16_OPC_BEQZ:
8345 gen_compute_branch(ctx, OPC_BEQ, 2, rx, 0, ((int8_t)ctx->opcode) << 1);
8346 /* No delay slot, so just process as a normal instruction */
8347 break;
8348 case M16_OPC_BNEQZ:
8349 gen_compute_branch(ctx, OPC_BNE, 2, rx, 0, ((int8_t)ctx->opcode) << 1);
8350 /* No delay slot, so just process as a normal instruction */
8351 break;
8352 case M16_OPC_SHIFT:
8353 switch (ctx->opcode & 0x3) {
8354 case 0x0:
8355 gen_shift_imm(env, ctx, OPC_SLL, rx, ry, sa);
8356 break;
8357 case 0x1:
8358 #if defined(TARGET_MIPS64)
8359 check_mips_64(ctx);
8360 gen_shift_imm(env, ctx, OPC_DSLL, rx, ry, sa);
8361 #else
8362 generate_exception(ctx, EXCP_RI);
8363 #endif
8364 break;
8365 case 0x2:
8366 gen_shift_imm(env, ctx, OPC_SRL, rx, ry, sa);
8367 break;
8368 case 0x3:
8369 gen_shift_imm(env, ctx, OPC_SRA, rx, ry, sa);
8370 break;
8372 break;
8373 #if defined(TARGET_MIPS64)
8374 case M16_OPC_LD:
8375 check_mips_64(ctx);
8376 gen_ldst(ctx, OPC_LD, ry, rx, offset << 3);
8377 break;
8378 #endif
8379 case M16_OPC_RRIA:
8381 int16_t imm = (int8_t)((ctx->opcode & 0xf) << 4) >> 4;
8383 if ((ctx->opcode >> 4) & 1) {
8384 #if defined(TARGET_MIPS64)
8385 check_mips_64(ctx);
8386 gen_arith_imm(env, ctx, OPC_DADDIU, ry, rx, imm);
8387 #else
8388 generate_exception(ctx, EXCP_RI);
8389 #endif
8390 } else {
8391 gen_arith_imm(env, ctx, OPC_ADDIU, ry, rx, imm);
8394 break;
8395 case M16_OPC_ADDIU8:
8397 int16_t imm = (int8_t) ctx->opcode;
8399 gen_arith_imm(env, ctx, OPC_ADDIU, rx, rx, imm);
8401 break;
8402 case M16_OPC_SLTI:
8404 int16_t imm = (uint8_t) ctx->opcode;
8406 gen_slt_imm(env, OPC_SLTI, 24, rx, imm);
8408 break;
8409 case M16_OPC_SLTIU:
8411 int16_t imm = (uint8_t) ctx->opcode;
8413 gen_slt_imm(env, OPC_SLTIU, 24, rx, imm);
8415 break;
8416 case M16_OPC_I8:
8418 int reg32;
8420 funct = (ctx->opcode >> 8) & 0x7;
8421 switch (funct) {
8422 case I8_BTEQZ:
8423 gen_compute_branch(ctx, OPC_BEQ, 2, 24, 0,
8424 ((int8_t)ctx->opcode) << 1);
8425 break;
8426 case I8_BTNEZ:
8427 gen_compute_branch(ctx, OPC_BNE, 2, 24, 0,
8428 ((int8_t)ctx->opcode) << 1);
8429 break;
8430 case I8_SWRASP:
8431 gen_ldst(ctx, OPC_SW, 31, 29, (ctx->opcode & 0xff) << 2);
8432 break;
8433 case I8_ADJSP:
8434 gen_arith_imm(env, ctx, OPC_ADDIU, 29, 29,
8435 ((int8_t)ctx->opcode) << 3);
8436 break;
8437 case I8_SVRS:
8439 int do_ra = ctx->opcode & (1 << 6);
8440 int do_s0 = ctx->opcode & (1 << 5);
8441 int do_s1 = ctx->opcode & (1 << 4);
8442 int framesize = ctx->opcode & 0xf;
8444 if (framesize == 0) {
8445 framesize = 128;
8446 } else {
8447 framesize = framesize << 3;
8450 if (ctx->opcode & (1 << 7)) {
8451 gen_mips16_save(ctx, 0, 0,
8452 do_ra, do_s0, do_s1, framesize);
8453 } else {
8454 gen_mips16_restore(ctx, 0, 0,
8455 do_ra, do_s0, do_s1, framesize);
8458 break;
8459 case I8_MOV32R:
8461 int rz = xlat(ctx->opcode & 0x7);
8463 reg32 = (((ctx->opcode >> 3) & 0x3) << 3) |
8464 ((ctx->opcode >> 5) & 0x7);
8465 gen_arith(env, ctx, OPC_ADDU, reg32, rz, 0);
8467 break;
8468 case I8_MOVR32:
8469 reg32 = ctx->opcode & 0x1f;
8470 gen_arith(env, ctx, OPC_ADDU, ry, reg32, 0);
8471 break;
8472 default:
8473 generate_exception(ctx, EXCP_RI);
8474 break;
8477 break;
8478 case M16_OPC_LI:
8480 int16_t imm = (uint8_t) ctx->opcode;
8482 gen_arith_imm(env, ctx, OPC_ADDIU, rx, 0, imm);
8484 break;
8485 case M16_OPC_CMPI:
8487 int16_t imm = (uint8_t) ctx->opcode;
8489 gen_logic_imm(env, OPC_XORI, 24, rx, imm);
8491 break;
8492 #if defined(TARGET_MIPS64)
8493 case M16_OPC_SD:
8494 check_mips_64(ctx);
8495 gen_ldst(ctx, OPC_SD, ry, rx, offset << 3);
8496 break;
8497 #endif
8498 case M16_OPC_LB:
8499 gen_ldst(ctx, OPC_LB, ry, rx, offset);
8500 break;
8501 case M16_OPC_LH:
8502 gen_ldst(ctx, OPC_LH, ry, rx, offset << 1);
8503 break;
8504 case M16_OPC_LWSP:
8505 gen_ldst(ctx, OPC_LW, rx, 29, ((uint8_t)ctx->opcode) << 2);
8506 break;
8507 case M16_OPC_LW:
8508 gen_ldst(ctx, OPC_LW, ry, rx, offset << 2);
8509 break;
8510 case M16_OPC_LBU:
8511 gen_ldst(ctx, OPC_LBU, ry, rx, offset);
8512 break;
8513 case M16_OPC_LHU:
8514 gen_ldst(ctx, OPC_LHU, ry, rx, offset << 1);
8515 break;
8516 case M16_OPC_LWPC:
8517 gen_ldst(ctx, OPC_LWPC, rx, 0, ((uint8_t)ctx->opcode) << 2);
8518 break;
8519 #if defined (TARGET_MIPS64)
8520 case M16_OPC_LWU:
8521 check_mips_64(ctx);
8522 gen_ldst(ctx, OPC_LWU, ry, rx, offset << 2);
8523 break;
8524 #endif
8525 case M16_OPC_SB:
8526 gen_ldst(ctx, OPC_SB, ry, rx, offset);
8527 break;
8528 case M16_OPC_SH:
8529 gen_ldst(ctx, OPC_SH, ry, rx, offset << 1);
8530 break;
8531 case M16_OPC_SWSP:
8532 gen_ldst(ctx, OPC_SW, rx, 29, ((uint8_t)ctx->opcode) << 2);
8533 break;
8534 case M16_OPC_SW:
8535 gen_ldst(ctx, OPC_SW, ry, rx, offset << 2);
8536 break;
8537 case M16_OPC_RRR:
8539 int rz = xlat((ctx->opcode >> 2) & 0x7);
8540 int mips32_op;
8542 switch (ctx->opcode & 0x3) {
8543 case RRR_ADDU:
8544 mips32_op = OPC_ADDU;
8545 break;
8546 case RRR_SUBU:
8547 mips32_op = OPC_SUBU;
8548 break;
8549 #if defined(TARGET_MIPS64)
8550 case RRR_DADDU:
8551 mips32_op = OPC_DADDU;
8552 check_mips_64(ctx);
8553 break;
8554 case RRR_DSUBU:
8555 mips32_op = OPC_DSUBU;
8556 check_mips_64(ctx);
8557 break;
8558 #endif
8559 default:
8560 generate_exception(ctx, EXCP_RI);
8561 goto done;
8564 gen_arith(env, ctx, mips32_op, rz, rx, ry);
8565 done:
8568 break;
8569 case M16_OPC_RR:
8570 switch (op1) {
8571 case RR_JR:
8573 int nd = (ctx->opcode >> 7) & 0x1;
8574 int link = (ctx->opcode >> 6) & 0x1;
8575 int ra = (ctx->opcode >> 5) & 0x1;
8577 if (link) {
8578 op = nd ? OPC_JALRC : OPC_JALR;
8579 } else {
8580 op = OPC_JR;
8583 gen_compute_branch(ctx, op, 2, ra ? 31 : rx, 31, 0);
8584 if (!nd) {
8585 *is_branch = 1;
8588 break;
8589 case RR_SDBBP:
8590 /* XXX: not clear which exception should be raised
8591 * when in debug mode...
8593 check_insn(env, ctx, ISA_MIPS32);
8594 if (!(ctx->hflags & MIPS_HFLAG_DM)) {
8595 generate_exception(ctx, EXCP_DBp);
8596 } else {
8597 generate_exception(ctx, EXCP_DBp);
8599 break;
8600 case RR_SLT:
8601 gen_slt(env, OPC_SLT, 24, rx, ry);
8602 break;
8603 case RR_SLTU:
8604 gen_slt(env, OPC_SLTU, 24, rx, ry);
8605 break;
8606 case RR_BREAK:
8607 generate_exception(ctx, EXCP_BREAK);
8608 break;
8609 case RR_SLLV:
8610 gen_shift(env, ctx, OPC_SLLV, ry, rx, ry);
8611 break;
8612 case RR_SRLV:
8613 gen_shift(env, ctx, OPC_SRLV, ry, rx, ry);
8614 break;
8615 case RR_SRAV:
8616 gen_shift(env, ctx, OPC_SRAV, ry, rx, ry);
8617 break;
8618 #if defined (TARGET_MIPS64)
8619 case RR_DSRL:
8620 check_mips_64(ctx);
8621 gen_shift_imm(env, ctx, OPC_DSRL, ry, ry, sa);
8622 break;
8623 #endif
8624 case RR_CMP:
8625 gen_logic(env, OPC_XOR, 24, rx, ry);
8626 break;
8627 case RR_NEG:
8628 gen_arith(env, ctx, OPC_SUBU, rx, 0, ry);
8629 break;
8630 case RR_AND:
8631 gen_logic(env, OPC_AND, rx, rx, ry);
8632 break;
8633 case RR_OR:
8634 gen_logic(env, OPC_OR, rx, rx, ry);
8635 break;
8636 case RR_XOR:
8637 gen_logic(env, OPC_XOR, rx, rx, ry);
8638 break;
8639 case RR_NOT:
8640 gen_logic(env, OPC_NOR, rx, ry, 0);
8641 break;
8642 case RR_MFHI:
8643 gen_HILO(ctx, OPC_MFHI, rx);
8644 break;
8645 case RR_CNVT:
8646 switch (cnvt_op) {
8647 case RR_RY_CNVT_ZEB:
8648 tcg_gen_ext8u_tl(cpu_gpr[rx], cpu_gpr[rx]);
8649 break;
8650 case RR_RY_CNVT_ZEH:
8651 tcg_gen_ext16u_tl(cpu_gpr[rx], cpu_gpr[rx]);
8652 break;
8653 case RR_RY_CNVT_SEB:
8654 tcg_gen_ext8s_tl(cpu_gpr[rx], cpu_gpr[rx]);
8655 break;
8656 case RR_RY_CNVT_SEH:
8657 tcg_gen_ext16s_tl(cpu_gpr[rx], cpu_gpr[rx]);
8658 break;
8659 #if defined (TARGET_MIPS64)
8660 case RR_RY_CNVT_ZEW:
8661 check_mips_64(ctx);
8662 tcg_gen_ext32u_tl(cpu_gpr[rx], cpu_gpr[rx]);
8663 break;
8664 case RR_RY_CNVT_SEW:
8665 check_mips_64(ctx);
8666 tcg_gen_ext32s_tl(cpu_gpr[rx], cpu_gpr[rx]);
8667 break;
8668 #endif
8669 default:
8670 generate_exception(ctx, EXCP_RI);
8671 break;
8673 break;
8674 case RR_MFLO:
8675 gen_HILO(ctx, OPC_MFLO, rx);
8676 break;
8677 #if defined (TARGET_MIPS64)
8678 case RR_DSRA:
8679 check_mips_64(ctx);
8680 gen_shift_imm(env, ctx, OPC_DSRA, ry, ry, sa);
8681 break;
8682 case RR_DSLLV:
8683 check_mips_64(ctx);
8684 gen_shift(env, ctx, OPC_DSLLV, ry, rx, ry);
8685 break;
8686 case RR_DSRLV:
8687 check_mips_64(ctx);
8688 gen_shift(env, ctx, OPC_DSRLV, ry, rx, ry);
8689 break;
8690 case RR_DSRAV:
8691 check_mips_64(ctx);
8692 gen_shift(env, ctx, OPC_DSRAV, ry, rx, ry);
8693 break;
8694 #endif
8695 case RR_MULT:
8696 gen_muldiv(ctx, OPC_MULT, rx, ry);
8697 break;
8698 case RR_MULTU:
8699 gen_muldiv(ctx, OPC_MULTU, rx, ry);
8700 break;
8701 case RR_DIV:
8702 gen_muldiv(ctx, OPC_DIV, rx, ry);
8703 break;
8704 case RR_DIVU:
8705 gen_muldiv(ctx, OPC_DIVU, rx, ry);
8706 break;
8707 #if defined (TARGET_MIPS64)
8708 case RR_DMULT:
8709 check_mips_64(ctx);
8710 gen_muldiv(ctx, OPC_DMULT, rx, ry);
8711 break;
8712 case RR_DMULTU:
8713 check_mips_64(ctx);
8714 gen_muldiv(ctx, OPC_DMULTU, rx, ry);
8715 break;
8716 case RR_DDIV:
8717 check_mips_64(ctx);
8718 gen_muldiv(ctx, OPC_DDIV, rx, ry);
8719 break;
8720 case RR_DDIVU:
8721 check_mips_64(ctx);
8722 gen_muldiv(ctx, OPC_DDIVU, rx, ry);
8723 break;
8724 #endif
8725 default:
8726 generate_exception(ctx, EXCP_RI);
8727 break;
8729 break;
8730 case M16_OPC_EXTEND:
8731 decode_extended_mips16_opc(env, ctx, is_branch);
8732 n_bytes = 4;
8733 break;
8734 #if defined(TARGET_MIPS64)
8735 case M16_OPC_I64:
8736 funct = (ctx->opcode >> 8) & 0x7;
8737 decode_i64_mips16(env, ctx, ry, funct, offset, 0);
8738 break;
8739 #endif
8740 default:
8741 generate_exception(ctx, EXCP_RI);
8742 break;
8745 return n_bytes;
8748 /* SmartMIPS extension to MIPS32 */
8750 #if defined(TARGET_MIPS64)
8752 /* MDMX extension to MIPS64 */
8754 #endif
8756 static void decode_opc (CPUState *env, DisasContext *ctx, int *is_branch)
8758 int32_t offset;
8759 int rs, rt, rd, sa;
8760 uint32_t op, op1, op2;
8761 int16_t imm;
8763 /* make sure instructions are on a word boundary */
8764 if (ctx->pc & 0x3) {
8765 env->CP0_BadVAddr = ctx->pc;
8766 generate_exception(ctx, EXCP_AdEL);
8767 return;
8770 /* Handle blikely not taken case */
8771 if ((ctx->hflags & MIPS_HFLAG_BMASK_BASE) == MIPS_HFLAG_BL) {
8772 int l1 = gen_new_label();
8774 MIPS_DEBUG("blikely condition (" TARGET_FMT_lx ")", ctx->pc + 4);
8775 tcg_gen_brcondi_tl(TCG_COND_NE, bcond, 0, l1);
8776 tcg_gen_movi_i32(hflags, ctx->hflags & ~MIPS_HFLAG_BMASK);
8777 gen_goto_tb(ctx, 1, ctx->pc + 4);
8778 gen_set_label(l1);
8781 if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP)))
8782 tcg_gen_debug_insn_start(ctx->pc);
8784 op = MASK_OP_MAJOR(ctx->opcode);
8785 rs = (ctx->opcode >> 21) & 0x1f;
8786 rt = (ctx->opcode >> 16) & 0x1f;
8787 rd = (ctx->opcode >> 11) & 0x1f;
8788 sa = (ctx->opcode >> 6) & 0x1f;
8789 imm = (int16_t)ctx->opcode;
8790 switch (op) {
8791 case OPC_SPECIAL:
8792 op1 = MASK_SPECIAL(ctx->opcode);
8793 switch (op1) {
8794 case OPC_SLL: /* Shift with immediate */
8795 case OPC_SRA:
8796 gen_shift_imm(env, ctx, op1, rd, rt, sa);
8797 break;
8798 case OPC_SRL:
8799 switch ((ctx->opcode >> 21) & 0x1f) {
8800 case 1:
8801 /* rotr is decoded as srl on non-R2 CPUs */
8802 if (env->insn_flags & ISA_MIPS32R2) {
8803 op1 = OPC_ROTR;
8805 /* Fallthrough */
8806 case 0:
8807 gen_shift_imm(env, ctx, op1, rd, rt, sa);
8808 break;
8809 default:
8810 generate_exception(ctx, EXCP_RI);
8811 break;
8813 break;
8814 case OPC_MOVN: /* Conditional move */
8815 case OPC_MOVZ:
8816 check_insn(env, ctx, ISA_MIPS4 | ISA_MIPS32);
8817 gen_cond_move(env, op1, rd, rs, rt);
8818 break;
8819 case OPC_ADD ... OPC_SUBU:
8820 gen_arith(env, ctx, op1, rd, rs, rt);
8821 break;
8822 case OPC_SLLV: /* Shifts */
8823 case OPC_SRAV:
8824 gen_shift(env, ctx, op1, rd, rs, rt);
8825 break;
8826 case OPC_SRLV:
8827 switch ((ctx->opcode >> 6) & 0x1f) {
8828 case 1:
8829 /* rotrv is decoded as srlv on non-R2 CPUs */
8830 if (env->insn_flags & ISA_MIPS32R2) {
8831 op1 = OPC_ROTRV;
8833 /* Fallthrough */
8834 case 0:
8835 gen_shift(env, ctx, op1, rd, rs, rt);
8836 break;
8837 default:
8838 generate_exception(ctx, EXCP_RI);
8839 break;
8841 break;
8842 case OPC_SLT: /* Set on less than */
8843 case OPC_SLTU:
8844 gen_slt(env, op1, rd, rs, rt);
8845 break;
8846 case OPC_AND: /* Logic*/
8847 case OPC_OR:
8848 case OPC_NOR:
8849 case OPC_XOR:
8850 gen_logic(env, op1, rd, rs, rt);
8851 break;
8852 case OPC_MULT ... OPC_DIVU:
8853 if (sa) {
8854 check_insn(env, ctx, INSN_VR54XX);
8855 op1 = MASK_MUL_VR54XX(ctx->opcode);
8856 gen_mul_vr54xx(ctx, op1, rd, rs, rt);
8857 } else
8858 gen_muldiv(ctx, op1, rs, rt);
8859 break;
8860 case OPC_JR ... OPC_JALR:
8861 gen_compute_branch(ctx, op1, 4, rs, rd, sa);
8862 *is_branch = 1;
8863 break;
8864 case OPC_TGE ... OPC_TEQ: /* Traps */
8865 case OPC_TNE:
8866 gen_trap(ctx, op1, rs, rt, -1);
8867 break;
8868 case OPC_MFHI: /* Move from HI/LO */
8869 case OPC_MFLO:
8870 gen_HILO(ctx, op1, rd);
8871 break;
8872 case OPC_MTHI:
8873 case OPC_MTLO: /* Move to HI/LO */
8874 gen_HILO(ctx, op1, rs);
8875 break;
8876 case OPC_PMON: /* Pmon entry point, also R4010 selsl */
8877 #ifdef MIPS_STRICT_STANDARD
8878 MIPS_INVAL("PMON / selsl");
8879 generate_exception(ctx, EXCP_RI);
8880 #else
8881 gen_helper_0i(pmon, sa);
8882 #endif
8883 break;
8884 case OPC_SYSCALL:
8885 generate_exception(ctx, EXCP_SYSCALL);
8886 ctx->bstate = BS_STOP;
8887 break;
8888 case OPC_BREAK:
8889 generate_exception(ctx, EXCP_BREAK);
8890 break;
8891 case OPC_SPIM:
8892 #ifdef MIPS_STRICT_STANDARD
8893 MIPS_INVAL("SPIM");
8894 generate_exception(ctx, EXCP_RI);
8895 #else
8896 /* Implemented as RI exception for now. */
8897 MIPS_INVAL("spim (unofficial)");
8898 generate_exception(ctx, EXCP_RI);
8899 #endif
8900 break;
8901 case OPC_SYNC:
8902 /* Treat as NOP. */
8903 break;
8905 case OPC_MOVCI:
8906 check_insn(env, ctx, ISA_MIPS4 | ISA_MIPS32);
8907 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
8908 check_cp1_enabled(ctx);
8909 gen_movci(ctx, rd, rs, (ctx->opcode >> 18) & 0x7,
8910 (ctx->opcode >> 16) & 1);
8911 } else {
8912 generate_exception_err(ctx, EXCP_CpU, 1);
8914 break;
8916 #if defined(TARGET_MIPS64)
8917 /* MIPS64 specific opcodes */
8918 case OPC_DSLL:
8919 case OPC_DSRA:
8920 case OPC_DSLL32:
8921 case OPC_DSRA32:
8922 check_insn(env, ctx, ISA_MIPS3);
8923 check_mips_64(ctx);
8924 gen_shift_imm(env, ctx, op1, rd, rt, sa);
8925 break;
8926 case OPC_DSRL:
8927 switch ((ctx->opcode >> 21) & 0x1f) {
8928 case 1:
8929 /* drotr is decoded as dsrl on non-R2 CPUs */
8930 if (env->insn_flags & ISA_MIPS32R2) {
8931 op1 = OPC_DROTR;
8933 /* Fallthrough */
8934 case 0:
8935 check_insn(env, ctx, ISA_MIPS3);
8936 check_mips_64(ctx);
8937 gen_shift_imm(env, ctx, op1, rd, rt, sa);
8938 break;
8939 default:
8940 generate_exception(ctx, EXCP_RI);
8941 break;
8943 break;
8944 case OPC_DSRL32:
8945 switch ((ctx->opcode >> 21) & 0x1f) {
8946 case 1:
8947 /* drotr32 is decoded as dsrl32 on non-R2 CPUs */
8948 if (env->insn_flags & ISA_MIPS32R2) {
8949 op1 = OPC_DROTR32;
8951 /* Fallthrough */
8952 case 0:
8953 check_insn(env, ctx, ISA_MIPS3);
8954 check_mips_64(ctx);
8955 gen_shift_imm(env, ctx, op1, rd, rt, sa);
8956 break;
8957 default:
8958 generate_exception(ctx, EXCP_RI);
8959 break;
8961 break;
8962 case OPC_DADD ... OPC_DSUBU:
8963 check_insn(env, ctx, ISA_MIPS3);
8964 check_mips_64(ctx);
8965 gen_arith(env, ctx, op1, rd, rs, rt);
8966 break;
8967 case OPC_DSLLV:
8968 case OPC_DSRAV:
8969 check_insn(env, ctx, ISA_MIPS3);
8970 check_mips_64(ctx);
8971 gen_shift(env, ctx, op1, rd, rs, rt);
8972 break;
8973 case OPC_DSRLV:
8974 switch ((ctx->opcode >> 6) & 0x1f) {
8975 case 1:
8976 /* drotrv is decoded as dsrlv on non-R2 CPUs */
8977 if (env->insn_flags & ISA_MIPS32R2) {
8978 op1 = OPC_DROTRV;
8980 /* Fallthrough */
8981 case 0:
8982 check_insn(env, ctx, ISA_MIPS3);
8983 check_mips_64(ctx);
8984 gen_shift(env, ctx, op1, rd, rs, rt);
8985 break;
8986 default:
8987 generate_exception(ctx, EXCP_RI);
8988 break;
8990 break;
8991 case OPC_DMULT ... OPC_DDIVU:
8992 check_insn(env, ctx, ISA_MIPS3);
8993 check_mips_64(ctx);
8994 gen_muldiv(ctx, op1, rs, rt);
8995 break;
8996 #endif
8997 default: /* Invalid */
8998 MIPS_INVAL("special");
8999 generate_exception(ctx, EXCP_RI);
9000 break;
9002 break;
9003 case OPC_SPECIAL2:
9004 op1 = MASK_SPECIAL2(ctx->opcode);
9005 switch (op1) {
9006 case OPC_MADD ... OPC_MADDU: /* Multiply and add/sub */
9007 case OPC_MSUB ... OPC_MSUBU:
9008 check_insn(env, ctx, ISA_MIPS32);
9009 gen_muldiv(ctx, op1, rs, rt);
9010 break;
9011 case OPC_MUL:
9012 gen_arith(env, ctx, op1, rd, rs, rt);
9013 break;
9014 case OPC_CLO:
9015 case OPC_CLZ:
9016 check_insn(env, ctx, ISA_MIPS32);
9017 gen_cl(ctx, op1, rd, rs);
9018 break;
9019 case OPC_SDBBP:
9020 /* XXX: not clear which exception should be raised
9021 * when in debug mode...
9023 check_insn(env, ctx, ISA_MIPS32);
9024 if (!(ctx->hflags & MIPS_HFLAG_DM)) {
9025 generate_exception(ctx, EXCP_DBp);
9026 } else {
9027 generate_exception(ctx, EXCP_DBp);
9029 /* Treat as NOP. */
9030 break;
9031 #if defined(TARGET_MIPS64)
9032 case OPC_DCLO:
9033 case OPC_DCLZ:
9034 check_insn(env, ctx, ISA_MIPS64);
9035 check_mips_64(ctx);
9036 gen_cl(ctx, op1, rd, rs);
9037 break;
9038 #endif
9039 default: /* Invalid */
9040 MIPS_INVAL("special2");
9041 generate_exception(ctx, EXCP_RI);
9042 break;
9044 break;
9045 case OPC_SPECIAL3:
9046 op1 = MASK_SPECIAL3(ctx->opcode);
9047 switch (op1) {
9048 case OPC_EXT:
9049 case OPC_INS:
9050 check_insn(env, ctx, ISA_MIPS32R2);
9051 gen_bitops(ctx, op1, rt, rs, sa, rd);
9052 break;
9053 case OPC_BSHFL:
9054 check_insn(env, ctx, ISA_MIPS32R2);
9055 op2 = MASK_BSHFL(ctx->opcode);
9056 gen_bshfl(ctx, op2, rt, rd);
9057 break;
9058 case OPC_RDHWR:
9059 check_insn(env, ctx, ISA_MIPS32R2);
9061 TCGv t0 = tcg_temp_new();
9063 switch (rd) {
9064 case 0:
9065 save_cpu_state(ctx, 1);
9066 gen_helper_rdhwr_cpunum(t0);
9067 gen_store_gpr(t0, rt);
9068 break;
9069 case 1:
9070 save_cpu_state(ctx, 1);
9071 gen_helper_rdhwr_synci_step(t0);
9072 gen_store_gpr(t0, rt);
9073 break;
9074 case 2:
9075 save_cpu_state(ctx, 1);
9076 gen_helper_rdhwr_cc(t0);
9077 gen_store_gpr(t0, rt);
9078 break;
9079 case 3:
9080 save_cpu_state(ctx, 1);
9081 gen_helper_rdhwr_ccres(t0);
9082 gen_store_gpr(t0, rt);
9083 break;
9084 case 29:
9085 #if defined(CONFIG_USER_ONLY)
9086 tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUState, tls_value));
9087 gen_store_gpr(t0, rt);
9088 break;
9089 #else
9090 /* XXX: Some CPUs implement this in hardware.
9091 Not supported yet. */
9092 #endif
9093 default: /* Invalid */
9094 MIPS_INVAL("rdhwr");
9095 generate_exception(ctx, EXCP_RI);
9096 break;
9098 tcg_temp_free(t0);
9100 break;
9101 case OPC_FORK:
9102 check_insn(env, ctx, ASE_MT);
9104 TCGv t0 = tcg_temp_new();
9105 TCGv t1 = tcg_temp_new();
9107 gen_load_gpr(t0, rt);
9108 gen_load_gpr(t1, rs);
9109 gen_helper_fork(t0, t1);
9110 tcg_temp_free(t0);
9111 tcg_temp_free(t1);
9113 break;
9114 case OPC_YIELD:
9115 check_insn(env, ctx, ASE_MT);
9117 TCGv t0 = tcg_temp_new();
9119 save_cpu_state(ctx, 1);
9120 gen_load_gpr(t0, rs);
9121 gen_helper_yield(t0, t0);
9122 gen_store_gpr(t0, rd);
9123 tcg_temp_free(t0);
9125 break;
9126 #if defined(TARGET_MIPS64)
9127 case OPC_DEXTM ... OPC_DEXT:
9128 case OPC_DINSM ... OPC_DINS:
9129 check_insn(env, ctx, ISA_MIPS64R2);
9130 check_mips_64(ctx);
9131 gen_bitops(ctx, op1, rt, rs, sa, rd);
9132 break;
9133 case OPC_DBSHFL:
9134 check_insn(env, ctx, ISA_MIPS64R2);
9135 check_mips_64(ctx);
9136 op2 = MASK_DBSHFL(ctx->opcode);
9137 gen_bshfl(ctx, op2, rt, rd);
9138 break;
9139 #endif
9140 default: /* Invalid */
9141 MIPS_INVAL("special3");
9142 generate_exception(ctx, EXCP_RI);
9143 break;
9145 break;
9146 case OPC_REGIMM:
9147 op1 = MASK_REGIMM(ctx->opcode);
9148 switch (op1) {
9149 case OPC_BLTZ ... OPC_BGEZL: /* REGIMM branches */
9150 case OPC_BLTZAL ... OPC_BGEZALL:
9151 gen_compute_branch(ctx, op1, 4, rs, -1, imm << 2);
9152 *is_branch = 1;
9153 break;
9154 case OPC_TGEI ... OPC_TEQI: /* REGIMM traps */
9155 case OPC_TNEI:
9156 gen_trap(ctx, op1, rs, -1, imm);
9157 break;
9158 case OPC_SYNCI:
9159 check_insn(env, ctx, ISA_MIPS32R2);
9160 /* Treat as NOP. */
9161 break;
9162 default: /* Invalid */
9163 MIPS_INVAL("regimm");
9164 generate_exception(ctx, EXCP_RI);
9165 break;
9167 break;
9168 case OPC_CP0:
9169 check_cp0_enabled(ctx);
9170 op1 = MASK_CP0(ctx->opcode);
9171 switch (op1) {
9172 case OPC_MFC0:
9173 case OPC_MTC0:
9174 case OPC_MFTR:
9175 case OPC_MTTR:
9176 #if defined(TARGET_MIPS64)
9177 case OPC_DMFC0:
9178 case OPC_DMTC0:
9179 #endif
9180 #ifndef CONFIG_USER_ONLY
9181 gen_cp0(env, ctx, op1, rt, rd);
9182 #endif /* !CONFIG_USER_ONLY */
9183 break;
9184 case OPC_C0_FIRST ... OPC_C0_LAST:
9185 #ifndef CONFIG_USER_ONLY
9186 gen_cp0(env, ctx, MASK_C0(ctx->opcode), rt, rd);
9187 #endif /* !CONFIG_USER_ONLY */
9188 break;
9189 case OPC_MFMC0:
9190 #ifndef CONFIG_USER_ONLY
9192 TCGv t0 = tcg_temp_new();
9194 op2 = MASK_MFMC0(ctx->opcode);
9195 switch (op2) {
9196 case OPC_DMT:
9197 check_insn(env, ctx, ASE_MT);
9198 gen_helper_dmt(t0, t0);
9199 gen_store_gpr(t0, rt);
9200 break;
9201 case OPC_EMT:
9202 check_insn(env, ctx, ASE_MT);
9203 gen_helper_emt(t0, t0);
9204 gen_store_gpr(t0, rt);
9205 break;
9206 case OPC_DVPE:
9207 check_insn(env, ctx, ASE_MT);
9208 gen_helper_dvpe(t0, t0);
9209 gen_store_gpr(t0, rt);
9210 break;
9211 case OPC_EVPE:
9212 check_insn(env, ctx, ASE_MT);
9213 gen_helper_evpe(t0, t0);
9214 gen_store_gpr(t0, rt);
9215 break;
9216 case OPC_DI:
9217 check_insn(env, ctx, ISA_MIPS32R2);
9218 save_cpu_state(ctx, 1);
9219 gen_helper_di(t0);
9220 gen_store_gpr(t0, rt);
9221 /* Stop translation as we may have switched the execution mode */
9222 ctx->bstate = BS_STOP;
9223 break;
9224 case OPC_EI:
9225 check_insn(env, ctx, ISA_MIPS32R2);
9226 save_cpu_state(ctx, 1);
9227 gen_helper_ei(t0);
9228 gen_store_gpr(t0, rt);
9229 /* Stop translation as we may have switched the execution mode */
9230 ctx->bstate = BS_STOP;
9231 break;
9232 default: /* Invalid */
9233 MIPS_INVAL("mfmc0");
9234 generate_exception(ctx, EXCP_RI);
9235 break;
9237 tcg_temp_free(t0);
9239 #endif /* !CONFIG_USER_ONLY */
9240 break;
9241 case OPC_RDPGPR:
9242 check_insn(env, ctx, ISA_MIPS32R2);
9243 gen_load_srsgpr(rt, rd);
9244 break;
9245 case OPC_WRPGPR:
9246 check_insn(env, ctx, ISA_MIPS32R2);
9247 gen_store_srsgpr(rt, rd);
9248 break;
9249 default:
9250 MIPS_INVAL("cp0");
9251 generate_exception(ctx, EXCP_RI);
9252 break;
9254 break;
9255 case OPC_ADDI: /* Arithmetic with immediate opcode */
9256 case OPC_ADDIU:
9257 gen_arith_imm(env, ctx, op, rt, rs, imm);
9258 break;
9259 case OPC_SLTI: /* Set on less than with immediate opcode */
9260 case OPC_SLTIU:
9261 gen_slt_imm(env, op, rt, rs, imm);
9262 break;
9263 case OPC_ANDI: /* Arithmetic with immediate opcode */
9264 case OPC_LUI:
9265 case OPC_ORI:
9266 case OPC_XORI:
9267 gen_logic_imm(env, op, rt, rs, imm);
9268 break;
9269 case OPC_J ... OPC_JAL: /* Jump */
9270 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2;
9271 gen_compute_branch(ctx, op, 4, rs, rt, offset);
9272 *is_branch = 1;
9273 break;
9274 case OPC_BEQ ... OPC_BGTZ: /* Branch */
9275 case OPC_BEQL ... OPC_BGTZL:
9276 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2);
9277 *is_branch = 1;
9278 break;
9279 case OPC_LB ... OPC_LWR: /* Load and stores */
9280 case OPC_SB ... OPC_SW:
9281 case OPC_SWR:
9282 case OPC_LL:
9283 gen_ldst(ctx, op, rt, rs, imm);
9284 break;
9285 case OPC_SC:
9286 gen_st_cond(ctx, op, rt, rs, imm);
9287 break;
9288 case OPC_CACHE:
9289 check_insn(env, ctx, ISA_MIPS3 | ISA_MIPS32);
9290 /* Treat as NOP. */
9291 break;
9292 case OPC_PREF:
9293 check_insn(env, ctx, ISA_MIPS4 | ISA_MIPS32);
9294 /* Treat as NOP. */
9295 break;
9297 /* Floating point (COP1). */
9298 case OPC_LWC1:
9299 case OPC_LDC1:
9300 case OPC_SWC1:
9301 case OPC_SDC1:
9302 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
9303 check_cp1_enabled(ctx);
9304 gen_flt_ldst(ctx, op, rt, rs, imm);
9305 } else {
9306 generate_exception_err(ctx, EXCP_CpU, 1);
9308 break;
9310 case OPC_CP1:
9311 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
9312 check_cp1_enabled(ctx);
9313 op1 = MASK_CP1(ctx->opcode);
9314 switch (op1) {
9315 case OPC_MFHC1:
9316 case OPC_MTHC1:
9317 check_insn(env, ctx, ISA_MIPS32R2);
9318 case OPC_MFC1:
9319 case OPC_CFC1:
9320 case OPC_MTC1:
9321 case OPC_CTC1:
9322 gen_cp1(ctx, op1, rt, rd);
9323 break;
9324 #if defined(TARGET_MIPS64)
9325 case OPC_DMFC1:
9326 case OPC_DMTC1:
9327 check_insn(env, ctx, ISA_MIPS3);
9328 gen_cp1(ctx, op1, rt, rd);
9329 break;
9330 #endif
9331 case OPC_BC1ANY2:
9332 case OPC_BC1ANY4:
9333 check_cop1x(ctx);
9334 check_insn(env, ctx, ASE_MIPS3D);
9335 /* fall through */
9336 case OPC_BC1:
9337 gen_compute_branch1(env, ctx, MASK_BC1(ctx->opcode),
9338 (rt >> 2) & 0x7, imm << 2);
9339 *is_branch = 1;
9340 break;
9341 case OPC_S_FMT:
9342 case OPC_D_FMT:
9343 case OPC_W_FMT:
9344 case OPC_L_FMT:
9345 case OPC_PS_FMT:
9346 gen_farith(ctx, MASK_CP1_FUNC(ctx->opcode), rt, rd, sa,
9347 (imm >> 8) & 0x7);
9348 break;
9349 default:
9350 MIPS_INVAL("cp1");
9351 generate_exception (ctx, EXCP_RI);
9352 break;
9354 } else {
9355 generate_exception_err(ctx, EXCP_CpU, 1);
9357 break;
9359 /* COP2. */
9360 case OPC_LWC2:
9361 case OPC_LDC2:
9362 case OPC_SWC2:
9363 case OPC_SDC2:
9364 case OPC_CP2:
9365 /* COP2: Not implemented. */
9366 generate_exception_err(ctx, EXCP_CpU, 2);
9367 break;
9369 case OPC_CP3:
9370 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
9371 check_cp1_enabled(ctx);
9372 op1 = MASK_CP3(ctx->opcode);
9373 switch (op1) {
9374 case OPC_LWXC1:
9375 case OPC_LDXC1:
9376 case OPC_LUXC1:
9377 case OPC_SWXC1:
9378 case OPC_SDXC1:
9379 case OPC_SUXC1:
9380 gen_flt3_ldst(ctx, op1, sa, rd, rs, rt);
9381 break;
9382 case OPC_PREFX:
9383 /* Treat as NOP. */
9384 break;
9385 case OPC_ALNV_PS:
9386 case OPC_MADD_S:
9387 case OPC_MADD_D:
9388 case OPC_MADD_PS:
9389 case OPC_MSUB_S:
9390 case OPC_MSUB_D:
9391 case OPC_MSUB_PS:
9392 case OPC_NMADD_S:
9393 case OPC_NMADD_D:
9394 case OPC_NMADD_PS:
9395 case OPC_NMSUB_S:
9396 case OPC_NMSUB_D:
9397 case OPC_NMSUB_PS:
9398 gen_flt3_arith(ctx, op1, sa, rs, rd, rt);
9399 break;
9400 default:
9401 MIPS_INVAL("cp3");
9402 generate_exception (ctx, EXCP_RI);
9403 break;
9405 } else {
9406 generate_exception_err(ctx, EXCP_CpU, 1);
9408 break;
9410 #if defined(TARGET_MIPS64)
9411 /* MIPS64 opcodes */
9412 case OPC_LWU:
9413 case OPC_LDL ... OPC_LDR:
9414 case OPC_SDL ... OPC_SDR:
9415 case OPC_LLD:
9416 case OPC_LD:
9417 case OPC_SD:
9418 check_insn(env, ctx, ISA_MIPS3);
9419 check_mips_64(ctx);
9420 gen_ldst(ctx, op, rt, rs, imm);
9421 break;
9422 case OPC_SCD:
9423 check_insn(env, ctx, ISA_MIPS3);
9424 check_mips_64(ctx);
9425 gen_st_cond(ctx, op, rt, rs, imm);
9426 break;
9427 case OPC_DADDI:
9428 case OPC_DADDIU:
9429 check_insn(env, ctx, ISA_MIPS3);
9430 check_mips_64(ctx);
9431 gen_arith_imm(env, ctx, op, rt, rs, imm);
9432 break;
9433 #endif
9434 case OPC_JALX:
9435 check_insn(env, ctx, ASE_MIPS16);
9436 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2;
9437 gen_compute_branch(ctx, op, 4, rs, rt, offset);
9438 *is_branch = 1;
9439 break;
9440 case OPC_MDMX:
9441 check_insn(env, ctx, ASE_MDMX);
9442 /* MDMX: Not implemented. */
9443 default: /* Invalid */
9444 MIPS_INVAL("major opcode");
9445 generate_exception(ctx, EXCP_RI);
9446 break;
9450 static inline void
9451 gen_intermediate_code_internal (CPUState *env, TranslationBlock *tb,
9452 int search_pc)
9454 DisasContext ctx;
9455 target_ulong pc_start;
9456 uint16_t *gen_opc_end;
9457 CPUBreakpoint *bp;
9458 int j, lj = -1;
9459 int num_insns;
9460 int max_insns;
9461 int insn_bytes;
9462 int is_branch;
9464 if (search_pc)
9465 qemu_log("search pc %d\n", search_pc);
9467 pc_start = tb->pc;
9468 gen_opc_end = gen_opc_buf + OPC_MAX_SIZE;
9469 ctx.pc = pc_start;
9470 ctx.saved_pc = -1;
9471 ctx.singlestep_enabled = env->singlestep_enabled;
9472 ctx.tb = tb;
9473 ctx.bstate = BS_NONE;
9474 /* Restore delay slot state from the tb context. */
9475 ctx.hflags = (uint32_t)tb->flags; /* FIXME: maybe use 64 bits here? */
9476 restore_cpu_state(env, &ctx);
9477 #ifdef CONFIG_USER_ONLY
9478 ctx.mem_idx = MIPS_HFLAG_UM;
9479 #else
9480 ctx.mem_idx = ctx.hflags & MIPS_HFLAG_KSU;
9481 #endif
9482 num_insns = 0;
9483 max_insns = tb->cflags & CF_COUNT_MASK;
9484 if (max_insns == 0)
9485 max_insns = CF_COUNT_MASK;
9486 #ifdef DEBUG_DISAS
9487 qemu_log_mask(CPU_LOG_TB_CPU, "------------------------------------------------\n");
9488 /* FIXME: This may print out stale hflags from env... */
9489 log_cpu_state_mask(CPU_LOG_TB_CPU, env, 0);
9490 #endif
9491 LOG_DISAS("\ntb %p idx %d hflags %04x\n", tb, ctx.mem_idx, ctx.hflags);
9492 gen_icount_start();
9493 while (ctx.bstate == BS_NONE) {
9494 if (unlikely(!QTAILQ_EMPTY(&env->breakpoints))) {
9495 QTAILQ_FOREACH(bp, &env->breakpoints, entry) {
9496 if (bp->pc == ctx.pc) {
9497 save_cpu_state(&ctx, 1);
9498 ctx.bstate = BS_BRANCH;
9499 gen_helper_0i(raise_exception, EXCP_DEBUG);
9500 /* Include the breakpoint location or the tb won't
9501 * be flushed when it must be. */
9502 ctx.pc += 4;
9503 goto done_generating;
9508 if (search_pc) {
9509 j = gen_opc_ptr - gen_opc_buf;
9510 if (lj < j) {
9511 lj++;
9512 while (lj < j)
9513 gen_opc_instr_start[lj++] = 0;
9515 gen_opc_pc[lj] = ctx.pc;
9516 gen_opc_hflags[lj] = ctx.hflags & MIPS_HFLAG_BMASK;
9517 gen_opc_instr_start[lj] = 1;
9518 gen_opc_icount[lj] = num_insns;
9520 if (num_insns + 1 == max_insns && (tb->cflags & CF_LAST_IO))
9521 gen_io_start();
9523 is_branch = 0;
9524 if (!(ctx.hflags & MIPS_HFLAG_M16)) {
9525 ctx.opcode = ldl_code(ctx.pc);
9526 insn_bytes = 4;
9527 decode_opc(env, &ctx, &is_branch);
9528 } else if (env->insn_flags & ASE_MIPS16) {
9529 ctx.opcode = lduw_code(ctx.pc);
9530 insn_bytes = decode_mips16_opc(env, &ctx, &is_branch);
9531 } else {
9532 generate_exception(&ctx, EXCP_RI);
9533 break;
9535 if (!is_branch) {
9536 handle_delay_slot(env, &ctx, insn_bytes);
9538 ctx.pc += insn_bytes;
9540 num_insns++;
9542 /* Execute a branch and its delay slot as a single instruction.
9543 This is what GDB expects and is consistent with what the
9544 hardware does (e.g. if a delay slot instruction faults, the
9545 reported PC is the PC of the branch). */
9546 if (env->singlestep_enabled && (ctx.hflags & MIPS_HFLAG_BMASK) == 0)
9547 break;
9549 if ((ctx.pc & (TARGET_PAGE_SIZE - 1)) == 0)
9550 break;
9552 if (gen_opc_ptr >= gen_opc_end)
9553 break;
9555 if (num_insns >= max_insns)
9556 break;
9558 if (singlestep)
9559 break;
9561 if (tb->cflags & CF_LAST_IO)
9562 gen_io_end();
9563 if (env->singlestep_enabled && ctx.bstate != BS_BRANCH) {
9564 save_cpu_state(&ctx, ctx.bstate == BS_NONE);
9565 gen_helper_0i(raise_exception, EXCP_DEBUG);
9566 } else {
9567 switch (ctx.bstate) {
9568 case BS_STOP:
9569 gen_helper_interrupt_restart();
9570 gen_goto_tb(&ctx, 0, ctx.pc);
9571 break;
9572 case BS_NONE:
9573 save_cpu_state(&ctx, 0);
9574 gen_goto_tb(&ctx, 0, ctx.pc);
9575 break;
9576 case BS_EXCP:
9577 gen_helper_interrupt_restart();
9578 tcg_gen_exit_tb(0);
9579 break;
9580 case BS_BRANCH:
9581 default:
9582 break;
9585 done_generating:
9586 gen_icount_end(tb, num_insns);
9587 *gen_opc_ptr = INDEX_op_end;
9588 if (search_pc) {
9589 j = gen_opc_ptr - gen_opc_buf;
9590 lj++;
9591 while (lj <= j)
9592 gen_opc_instr_start[lj++] = 0;
9593 } else {
9594 tb->size = ctx.pc - pc_start;
9595 tb->icount = num_insns;
9597 #ifdef DEBUG_DISAS
9598 LOG_DISAS("\n");
9599 if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) {
9600 qemu_log("IN: %s\n", lookup_symbol(pc_start));
9601 log_target_disas(pc_start, ctx.pc - pc_start, 0);
9602 qemu_log("\n");
9604 qemu_log_mask(CPU_LOG_TB_CPU, "---------------- %d %08x\n", ctx.bstate, ctx.hflags);
9605 #endif
9608 void gen_intermediate_code (CPUState *env, struct TranslationBlock *tb)
9610 gen_intermediate_code_internal(env, tb, 0);
9613 void gen_intermediate_code_pc (CPUState *env, struct TranslationBlock *tb)
9615 gen_intermediate_code_internal(env, tb, 1);
9618 static void fpu_dump_state(CPUState *env, FILE *f,
9619 int (*fpu_fprintf)(FILE *f, const char *fmt, ...),
9620 int flags)
9622 int i;
9623 int is_fpu64 = !!(env->hflags & MIPS_HFLAG_F64);
9625 #define printfpr(fp) \
9626 do { \
9627 if (is_fpu64) \
9628 fpu_fprintf(f, "w:%08x d:%016lx fd:%13g fs:%13g psu: %13g\n", \
9629 (fp)->w[FP_ENDIAN_IDX], (fp)->d, (fp)->fd, \
9630 (fp)->fs[FP_ENDIAN_IDX], (fp)->fs[!FP_ENDIAN_IDX]); \
9631 else { \
9632 fpr_t tmp; \
9633 tmp.w[FP_ENDIAN_IDX] = (fp)->w[FP_ENDIAN_IDX]; \
9634 tmp.w[!FP_ENDIAN_IDX] = ((fp) + 1)->w[FP_ENDIAN_IDX]; \
9635 fpu_fprintf(f, "w:%08x d:%016lx fd:%13g fs:%13g psu:%13g\n", \
9636 tmp.w[FP_ENDIAN_IDX], tmp.d, tmp.fd, \
9637 tmp.fs[FP_ENDIAN_IDX], tmp.fs[!FP_ENDIAN_IDX]); \
9639 } while(0)
9642 fpu_fprintf(f, "CP1 FCR0 0x%08x FCR31 0x%08x SR.FR %d fp_status 0x%08x(0x%02x)\n",
9643 env->active_fpu.fcr0, env->active_fpu.fcr31, is_fpu64, env->active_fpu.fp_status,
9644 get_float_exception_flags(&env->active_fpu.fp_status));
9645 for (i = 0; i < 32; (is_fpu64) ? i++ : (i += 2)) {
9646 fpu_fprintf(f, "%3s: ", fregnames[i]);
9647 printfpr(&env->active_fpu.fpr[i]);
9650 #undef printfpr
9653 #if defined(TARGET_MIPS64) && defined(MIPS_DEBUG_SIGN_EXTENSIONS)
9654 /* Debug help: The architecture requires 32bit code to maintain proper
9655 sign-extended values on 64bit machines. */
9657 #define SIGN_EXT_P(val) ((((val) & ~0x7fffffff) == 0) || (((val) & ~0x7fffffff) == ~0x7fffffff))
9659 static void
9660 cpu_mips_check_sign_extensions (CPUState *env, FILE *f,
9661 int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
9662 int flags)
9664 int i;
9666 if (!SIGN_EXT_P(env->active_tc.PC))
9667 cpu_fprintf(f, "BROKEN: pc=0x" TARGET_FMT_lx "\n", env->active_tc.PC);
9668 if (!SIGN_EXT_P(env->active_tc.HI[0]))
9669 cpu_fprintf(f, "BROKEN: HI=0x" TARGET_FMT_lx "\n", env->active_tc.HI[0]);
9670 if (!SIGN_EXT_P(env->active_tc.LO[0]))
9671 cpu_fprintf(f, "BROKEN: LO=0x" TARGET_FMT_lx "\n", env->active_tc.LO[0]);
9672 if (!SIGN_EXT_P(env->btarget))
9673 cpu_fprintf(f, "BROKEN: btarget=0x" TARGET_FMT_lx "\n", env->btarget);
9675 for (i = 0; i < 32; i++) {
9676 if (!SIGN_EXT_P(env->active_tc.gpr[i]))
9677 cpu_fprintf(f, "BROKEN: %s=0x" TARGET_FMT_lx "\n", regnames[i], env->active_tc.gpr[i]);
9680 if (!SIGN_EXT_P(env->CP0_EPC))
9681 cpu_fprintf(f, "BROKEN: EPC=0x" TARGET_FMT_lx "\n", env->CP0_EPC);
9682 if (!SIGN_EXT_P(env->lladdr))
9683 cpu_fprintf(f, "BROKEN: LLAddr=0x" TARGET_FMT_lx "\n", env->lladdr);
9685 #endif
9687 void cpu_dump_state (CPUState *env, FILE *f,
9688 int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
9689 int flags)
9691 int i;
9693 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",
9694 env->active_tc.PC, env->active_tc.HI[0], env->active_tc.LO[0],
9695 env->hflags, env->btarget, env->bcond);
9696 for (i = 0; i < 32; i++) {
9697 if ((i & 3) == 0)
9698 cpu_fprintf(f, "GPR%02d:", i);
9699 cpu_fprintf(f, " %s " TARGET_FMT_lx, regnames[i], env->active_tc.gpr[i]);
9700 if ((i & 3) == 3)
9701 cpu_fprintf(f, "\n");
9704 cpu_fprintf(f, "CP0 Status 0x%08x Cause 0x%08x EPC 0x" TARGET_FMT_lx "\n",
9705 env->CP0_Status, env->CP0_Cause, env->CP0_EPC);
9706 cpu_fprintf(f, " Config0 0x%08x Config1 0x%08x LLAddr 0x" TARGET_FMT_lx "\n",
9707 env->CP0_Config0, env->CP0_Config1, env->lladdr);
9708 if (env->hflags & MIPS_HFLAG_FPU)
9709 fpu_dump_state(env, f, cpu_fprintf, flags);
9710 #if defined(TARGET_MIPS64) && defined(MIPS_DEBUG_SIGN_EXTENSIONS)
9711 cpu_mips_check_sign_extensions(env, f, cpu_fprintf, flags);
9712 #endif
9715 static void mips_tcg_init(void)
9717 int i;
9718 static int inited;
9720 /* Initialize various static tables. */
9721 if (inited)
9722 return;
9724 cpu_env = tcg_global_reg_new_ptr(TCG_AREG0, "env");
9725 TCGV_UNUSED(cpu_gpr[0]);
9726 for (i = 1; i < 32; i++)
9727 cpu_gpr[i] = tcg_global_mem_new(TCG_AREG0,
9728 offsetof(CPUState, active_tc.gpr[i]),
9729 regnames[i]);
9730 cpu_PC = tcg_global_mem_new(TCG_AREG0,
9731 offsetof(CPUState, active_tc.PC), "PC");
9732 for (i = 0; i < MIPS_DSP_ACC; i++) {
9733 cpu_HI[i] = tcg_global_mem_new(TCG_AREG0,
9734 offsetof(CPUState, active_tc.HI[i]),
9735 regnames_HI[i]);
9736 cpu_LO[i] = tcg_global_mem_new(TCG_AREG0,
9737 offsetof(CPUState, active_tc.LO[i]),
9738 regnames_LO[i]);
9739 cpu_ACX[i] = tcg_global_mem_new(TCG_AREG0,
9740 offsetof(CPUState, active_tc.ACX[i]),
9741 regnames_ACX[i]);
9743 cpu_dspctrl = tcg_global_mem_new(TCG_AREG0,
9744 offsetof(CPUState, active_tc.DSPControl),
9745 "DSPControl");
9746 bcond = tcg_global_mem_new(TCG_AREG0,
9747 offsetof(CPUState, bcond), "bcond");
9748 btarget = tcg_global_mem_new(TCG_AREG0,
9749 offsetof(CPUState, btarget), "btarget");
9750 hflags = tcg_global_mem_new_i32(TCG_AREG0,
9751 offsetof(CPUState, hflags), "hflags");
9753 fpu_fcr0 = tcg_global_mem_new_i32(TCG_AREG0,
9754 offsetof(CPUState, active_fpu.fcr0),
9755 "fcr0");
9756 fpu_fcr31 = tcg_global_mem_new_i32(TCG_AREG0,
9757 offsetof(CPUState, active_fpu.fcr31),
9758 "fcr31");
9760 /* register helpers */
9761 #define GEN_HELPER 2
9762 #include "helper.h"
9764 inited = 1;
9767 #include "translate_init.c"
9769 CPUMIPSState *cpu_mips_init (const char *cpu_model)
9771 CPUMIPSState *env;
9772 const mips_def_t *def;
9774 def = cpu_mips_find_by_name(cpu_model);
9775 if (!def)
9776 return NULL;
9777 env = qemu_mallocz(sizeof(CPUMIPSState));
9778 env->cpu_model = def;
9779 env->cpu_model_str = cpu_model;
9781 cpu_exec_init(env);
9782 #ifndef CONFIG_USER_ONLY
9783 mmu_init(env, def);
9784 #endif
9785 fpu_init(env, def);
9786 mvp_init(env, def);
9787 mips_tcg_init();
9788 cpu_reset(env);
9789 qemu_init_vcpu(env);
9790 return env;
9793 void cpu_reset (CPUMIPSState *env)
9795 if (qemu_loglevel_mask(CPU_LOG_RESET)) {
9796 qemu_log("CPU Reset (CPU %d)\n", env->cpu_index);
9797 log_cpu_state(env, 0);
9800 memset(env, 0, offsetof(CPUMIPSState, breakpoints));
9801 tlb_flush(env, 1);
9803 /* Reset registers to their default values */
9804 env->CP0_PRid = env->cpu_model->CP0_PRid;
9805 env->CP0_Config0 = env->cpu_model->CP0_Config0;
9806 #ifdef TARGET_WORDS_BIGENDIAN
9807 env->CP0_Config0 |= (1 << CP0C0_BE);
9808 #endif
9809 env->CP0_Config1 = env->cpu_model->CP0_Config1;
9810 env->CP0_Config2 = env->cpu_model->CP0_Config2;
9811 env->CP0_Config3 = env->cpu_model->CP0_Config3;
9812 env->CP0_Config6 = env->cpu_model->CP0_Config6;
9813 env->CP0_Config7 = env->cpu_model->CP0_Config7;
9814 env->CP0_LLAddr_rw_bitmask = env->cpu_model->CP0_LLAddr_rw_bitmask
9815 << env->cpu_model->CP0_LLAddr_shift;
9816 env->CP0_LLAddr_shift = env->cpu_model->CP0_LLAddr_shift;
9817 env->SYNCI_Step = env->cpu_model->SYNCI_Step;
9818 env->CCRes = env->cpu_model->CCRes;
9819 env->CP0_Status_rw_bitmask = env->cpu_model->CP0_Status_rw_bitmask;
9820 env->CP0_TCStatus_rw_bitmask = env->cpu_model->CP0_TCStatus_rw_bitmask;
9821 env->CP0_SRSCtl = env->cpu_model->CP0_SRSCtl;
9822 env->current_tc = 0;
9823 env->SEGBITS = env->cpu_model->SEGBITS;
9824 env->SEGMask = (target_ulong)((1ULL << env->cpu_model->SEGBITS) - 1);
9825 #if defined(TARGET_MIPS64)
9826 if (env->cpu_model->insn_flags & ISA_MIPS3) {
9827 env->SEGMask |= 3ULL << 62;
9829 #endif
9830 env->PABITS = env->cpu_model->PABITS;
9831 env->PAMask = (target_ulong)((1ULL << env->cpu_model->PABITS) - 1);
9832 env->CP0_SRSConf0_rw_bitmask = env->cpu_model->CP0_SRSConf0_rw_bitmask;
9833 env->CP0_SRSConf0 = env->cpu_model->CP0_SRSConf0;
9834 env->CP0_SRSConf1_rw_bitmask = env->cpu_model->CP0_SRSConf1_rw_bitmask;
9835 env->CP0_SRSConf1 = env->cpu_model->CP0_SRSConf1;
9836 env->CP0_SRSConf2_rw_bitmask = env->cpu_model->CP0_SRSConf2_rw_bitmask;
9837 env->CP0_SRSConf2 = env->cpu_model->CP0_SRSConf2;
9838 env->CP0_SRSConf3_rw_bitmask = env->cpu_model->CP0_SRSConf3_rw_bitmask;
9839 env->CP0_SRSConf3 = env->cpu_model->CP0_SRSConf3;
9840 env->CP0_SRSConf4_rw_bitmask = env->cpu_model->CP0_SRSConf4_rw_bitmask;
9841 env->CP0_SRSConf4 = env->cpu_model->CP0_SRSConf4;
9842 env->insn_flags = env->cpu_model->insn_flags;
9844 #if defined(CONFIG_USER_ONLY)
9845 env->hflags = MIPS_HFLAG_UM;
9846 /* Enable access to the SYNCI_Step register. */
9847 env->CP0_HWREna |= (1 << 1);
9848 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
9849 env->hflags |= MIPS_HFLAG_FPU;
9851 #ifdef TARGET_MIPS64
9852 if (env->active_fpu.fcr0 & (1 << FCR0_F64)) {
9853 env->hflags |= MIPS_HFLAG_F64;
9855 #endif
9856 #else
9857 if (env->hflags & MIPS_HFLAG_BMASK) {
9858 /* If the exception was raised from a delay slot,
9859 come back to the jump. */
9860 env->CP0_ErrorEPC = env->active_tc.PC - 4;
9861 } else {
9862 env->CP0_ErrorEPC = env->active_tc.PC;
9864 env->active_tc.PC = (int32_t)0xBFC00000;
9865 env->CP0_Random = env->tlb->nb_tlb - 1;
9866 env->tlb->tlb_in_use = env->tlb->nb_tlb;
9867 env->CP0_Wired = 0;
9868 /* SMP not implemented */
9869 env->CP0_EBase = 0x80000000;
9870 env->CP0_Status = (1 << CP0St_BEV) | (1 << CP0St_ERL);
9871 /* vectored interrupts not implemented, timer on int 7,
9872 no performance counters. */
9873 env->CP0_IntCtl = 0xe0000000;
9875 int i;
9877 for (i = 0; i < 7; i++) {
9878 env->CP0_WatchLo[i] = 0;
9879 env->CP0_WatchHi[i] = 0x80000000;
9881 env->CP0_WatchLo[7] = 0;
9882 env->CP0_WatchHi[7] = 0;
9884 /* Count register increments in debug mode, EJTAG version 1 */
9885 env->CP0_Debug = (1 << CP0DB_CNT) | (0x1 << CP0DB_VER);
9886 env->hflags = MIPS_HFLAG_CP0;
9887 #endif
9888 #if defined(TARGET_MIPS64)
9889 if (env->cpu_model->insn_flags & ISA_MIPS3) {
9890 env->hflags |= MIPS_HFLAG_64;
9892 #endif
9893 env->exception_index = EXCP_NONE;
9896 void gen_pc_load(CPUState *env, TranslationBlock *tb,
9897 unsigned long searched_pc, int pc_pos, void *puc)
9899 env->active_tc.PC = gen_opc_pc[pc_pos];
9900 env->hflags &= ~MIPS_HFLAG_BMASK;
9901 env->hflags |= gen_opc_hflags[pc_pos];