Remove env->ready_for_interrupt_injection
[qemu-kvm/fedora.git] / target-mips / translate.c
blobf0dc14d82891cb397d3df5b8c8709f95c4ca2104
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)
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2 of the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
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 "helper.h"
33 #include "tcg-op.h"
34 #include "qemu-common.h"
36 //#define MIPS_DEBUG_DISAS
37 //#define MIPS_DEBUG_SIGN_EXTENSIONS
38 //#define MIPS_SINGLE_STEP
40 /* MIPS major opcodes */
41 #define MASK_OP_MAJOR(op) (op & (0x3F << 26))
43 enum {
44 /* indirect opcode tables */
45 OPC_SPECIAL = (0x00 << 26),
46 OPC_REGIMM = (0x01 << 26),
47 OPC_CP0 = (0x10 << 26),
48 OPC_CP1 = (0x11 << 26),
49 OPC_CP2 = (0x12 << 26),
50 OPC_CP3 = (0x13 << 26),
51 OPC_SPECIAL2 = (0x1C << 26),
52 OPC_SPECIAL3 = (0x1F << 26),
53 /* arithmetic with immediate */
54 OPC_ADDI = (0x08 << 26),
55 OPC_ADDIU = (0x09 << 26),
56 OPC_SLTI = (0x0A << 26),
57 OPC_SLTIU = (0x0B << 26),
58 OPC_ANDI = (0x0C << 26),
59 OPC_ORI = (0x0D << 26),
60 OPC_XORI = (0x0E << 26),
61 OPC_LUI = (0x0F << 26),
62 OPC_DADDI = (0x18 << 26),
63 OPC_DADDIU = (0x19 << 26),
64 /* Jump and branches */
65 OPC_J = (0x02 << 26),
66 OPC_JAL = (0x03 << 26),
67 OPC_BEQ = (0x04 << 26), /* Unconditional if rs = rt = 0 (B) */
68 OPC_BEQL = (0x14 << 26),
69 OPC_BNE = (0x05 << 26),
70 OPC_BNEL = (0x15 << 26),
71 OPC_BLEZ = (0x06 << 26),
72 OPC_BLEZL = (0x16 << 26),
73 OPC_BGTZ = (0x07 << 26),
74 OPC_BGTZL = (0x17 << 26),
75 OPC_JALX = (0x1D << 26), /* MIPS 16 only */
76 /* Load and stores */
77 OPC_LDL = (0x1A << 26),
78 OPC_LDR = (0x1B << 26),
79 OPC_LB = (0x20 << 26),
80 OPC_LH = (0x21 << 26),
81 OPC_LWL = (0x22 << 26),
82 OPC_LW = (0x23 << 26),
83 OPC_LBU = (0x24 << 26),
84 OPC_LHU = (0x25 << 26),
85 OPC_LWR = (0x26 << 26),
86 OPC_LWU = (0x27 << 26),
87 OPC_SB = (0x28 << 26),
88 OPC_SH = (0x29 << 26),
89 OPC_SWL = (0x2A << 26),
90 OPC_SW = (0x2B << 26),
91 OPC_SDL = (0x2C << 26),
92 OPC_SDR = (0x2D << 26),
93 OPC_SWR = (0x2E << 26),
94 OPC_LL = (0x30 << 26),
95 OPC_LLD = (0x34 << 26),
96 OPC_LD = (0x37 << 26),
97 OPC_SC = (0x38 << 26),
98 OPC_SCD = (0x3C << 26),
99 OPC_SD = (0x3F << 26),
100 /* Floating point load/store */
101 OPC_LWC1 = (0x31 << 26),
102 OPC_LWC2 = (0x32 << 26),
103 OPC_LDC1 = (0x35 << 26),
104 OPC_LDC2 = (0x36 << 26),
105 OPC_SWC1 = (0x39 << 26),
106 OPC_SWC2 = (0x3A << 26),
107 OPC_SDC1 = (0x3D << 26),
108 OPC_SDC2 = (0x3E << 26),
109 /* MDMX ASE specific */
110 OPC_MDMX = (0x1E << 26),
111 /* Cache and prefetch */
112 OPC_CACHE = (0x2F << 26),
113 OPC_PREF = (0x33 << 26),
114 /* Reserved major opcode */
115 OPC_MAJOR3B_RESERVED = (0x3B << 26),
118 /* MIPS special opcodes */
119 #define MASK_SPECIAL(op) MASK_OP_MAJOR(op) | (op & 0x3F)
121 enum {
122 /* Shifts */
123 OPC_SLL = 0x00 | OPC_SPECIAL,
124 /* NOP is SLL r0, r0, 0 */
125 /* SSNOP is SLL r0, r0, 1 */
126 /* EHB is SLL r0, r0, 3 */
127 OPC_SRL = 0x02 | OPC_SPECIAL, /* also ROTR */
128 OPC_SRA = 0x03 | OPC_SPECIAL,
129 OPC_SLLV = 0x04 | OPC_SPECIAL,
130 OPC_SRLV = 0x06 | OPC_SPECIAL, /* also ROTRV */
131 OPC_SRAV = 0x07 | OPC_SPECIAL,
132 OPC_DSLLV = 0x14 | OPC_SPECIAL,
133 OPC_DSRLV = 0x16 | OPC_SPECIAL, /* also DROTRV */
134 OPC_DSRAV = 0x17 | OPC_SPECIAL,
135 OPC_DSLL = 0x38 | OPC_SPECIAL,
136 OPC_DSRL = 0x3A | OPC_SPECIAL, /* also DROTR */
137 OPC_DSRA = 0x3B | OPC_SPECIAL,
138 OPC_DSLL32 = 0x3C | OPC_SPECIAL,
139 OPC_DSRL32 = 0x3E | OPC_SPECIAL, /* also DROTR32 */
140 OPC_DSRA32 = 0x3F | OPC_SPECIAL,
141 /* Multiplication / division */
142 OPC_MULT = 0x18 | OPC_SPECIAL,
143 OPC_MULTU = 0x19 | OPC_SPECIAL,
144 OPC_DIV = 0x1A | OPC_SPECIAL,
145 OPC_DIVU = 0x1B | OPC_SPECIAL,
146 OPC_DMULT = 0x1C | OPC_SPECIAL,
147 OPC_DMULTU = 0x1D | OPC_SPECIAL,
148 OPC_DDIV = 0x1E | OPC_SPECIAL,
149 OPC_DDIVU = 0x1F | OPC_SPECIAL,
150 /* 2 registers arithmetic / logic */
151 OPC_ADD = 0x20 | OPC_SPECIAL,
152 OPC_ADDU = 0x21 | OPC_SPECIAL,
153 OPC_SUB = 0x22 | OPC_SPECIAL,
154 OPC_SUBU = 0x23 | OPC_SPECIAL,
155 OPC_AND = 0x24 | OPC_SPECIAL,
156 OPC_OR = 0x25 | OPC_SPECIAL,
157 OPC_XOR = 0x26 | OPC_SPECIAL,
158 OPC_NOR = 0x27 | OPC_SPECIAL,
159 OPC_SLT = 0x2A | OPC_SPECIAL,
160 OPC_SLTU = 0x2B | OPC_SPECIAL,
161 OPC_DADD = 0x2C | OPC_SPECIAL,
162 OPC_DADDU = 0x2D | OPC_SPECIAL,
163 OPC_DSUB = 0x2E | OPC_SPECIAL,
164 OPC_DSUBU = 0x2F | OPC_SPECIAL,
165 /* Jumps */
166 OPC_JR = 0x08 | OPC_SPECIAL, /* Also JR.HB */
167 OPC_JALR = 0x09 | OPC_SPECIAL, /* Also JALR.HB */
168 /* Traps */
169 OPC_TGE = 0x30 | OPC_SPECIAL,
170 OPC_TGEU = 0x31 | OPC_SPECIAL,
171 OPC_TLT = 0x32 | OPC_SPECIAL,
172 OPC_TLTU = 0x33 | OPC_SPECIAL,
173 OPC_TEQ = 0x34 | OPC_SPECIAL,
174 OPC_TNE = 0x36 | OPC_SPECIAL,
175 /* HI / LO registers load & stores */
176 OPC_MFHI = 0x10 | OPC_SPECIAL,
177 OPC_MTHI = 0x11 | OPC_SPECIAL,
178 OPC_MFLO = 0x12 | OPC_SPECIAL,
179 OPC_MTLO = 0x13 | OPC_SPECIAL,
180 /* Conditional moves */
181 OPC_MOVZ = 0x0A | OPC_SPECIAL,
182 OPC_MOVN = 0x0B | OPC_SPECIAL,
184 OPC_MOVCI = 0x01 | OPC_SPECIAL,
186 /* Special */
187 OPC_PMON = 0x05 | OPC_SPECIAL, /* inofficial */
188 OPC_SYSCALL = 0x0C | OPC_SPECIAL,
189 OPC_BREAK = 0x0D | OPC_SPECIAL,
190 OPC_SPIM = 0x0E | OPC_SPECIAL, /* inofficial */
191 OPC_SYNC = 0x0F | OPC_SPECIAL,
193 OPC_SPECIAL15_RESERVED = 0x15 | OPC_SPECIAL,
194 OPC_SPECIAL28_RESERVED = 0x28 | OPC_SPECIAL,
195 OPC_SPECIAL29_RESERVED = 0x29 | OPC_SPECIAL,
196 OPC_SPECIAL35_RESERVED = 0x35 | OPC_SPECIAL,
197 OPC_SPECIAL37_RESERVED = 0x37 | OPC_SPECIAL,
198 OPC_SPECIAL39_RESERVED = 0x39 | OPC_SPECIAL,
199 OPC_SPECIAL3D_RESERVED = 0x3D | OPC_SPECIAL,
202 /* Multiplication variants of the vr54xx. */
203 #define MASK_MUL_VR54XX(op) MASK_SPECIAL(op) | (op & (0x1F << 6))
205 enum {
206 OPC_VR54XX_MULS = (0x03 << 6) | OPC_MULT,
207 OPC_VR54XX_MULSU = (0x03 << 6) | OPC_MULTU,
208 OPC_VR54XX_MACC = (0x05 << 6) | OPC_MULT,
209 OPC_VR54XX_MACCU = (0x05 << 6) | OPC_MULTU,
210 OPC_VR54XX_MSAC = (0x07 << 6) | OPC_MULT,
211 OPC_VR54XX_MSACU = (0x07 << 6) | OPC_MULTU,
212 OPC_VR54XX_MULHI = (0x09 << 6) | OPC_MULT,
213 OPC_VR54XX_MULHIU = (0x09 << 6) | OPC_MULTU,
214 OPC_VR54XX_MULSHI = (0x0B << 6) | OPC_MULT,
215 OPC_VR54XX_MULSHIU = (0x0B << 6) | OPC_MULTU,
216 OPC_VR54XX_MACCHI = (0x0D << 6) | OPC_MULT,
217 OPC_VR54XX_MACCHIU = (0x0D << 6) | OPC_MULTU,
218 OPC_VR54XX_MSACHI = (0x0F << 6) | OPC_MULT,
219 OPC_VR54XX_MSACHIU = (0x0F << 6) | OPC_MULTU,
222 /* REGIMM (rt field) opcodes */
223 #define MASK_REGIMM(op) MASK_OP_MAJOR(op) | (op & (0x1F << 16))
225 enum {
226 OPC_BLTZ = (0x00 << 16) | OPC_REGIMM,
227 OPC_BLTZL = (0x02 << 16) | OPC_REGIMM,
228 OPC_BGEZ = (0x01 << 16) | OPC_REGIMM,
229 OPC_BGEZL = (0x03 << 16) | OPC_REGIMM,
230 OPC_BLTZAL = (0x10 << 16) | OPC_REGIMM,
231 OPC_BLTZALL = (0x12 << 16) | OPC_REGIMM,
232 OPC_BGEZAL = (0x11 << 16) | OPC_REGIMM,
233 OPC_BGEZALL = (0x13 << 16) | OPC_REGIMM,
234 OPC_TGEI = (0x08 << 16) | OPC_REGIMM,
235 OPC_TGEIU = (0x09 << 16) | OPC_REGIMM,
236 OPC_TLTI = (0x0A << 16) | OPC_REGIMM,
237 OPC_TLTIU = (0x0B << 16) | OPC_REGIMM,
238 OPC_TEQI = (0x0C << 16) | OPC_REGIMM,
239 OPC_TNEI = (0x0E << 16) | OPC_REGIMM,
240 OPC_SYNCI = (0x1F << 16) | OPC_REGIMM,
243 /* Special2 opcodes */
244 #define MASK_SPECIAL2(op) MASK_OP_MAJOR(op) | (op & 0x3F)
246 enum {
247 /* Multiply & xxx operations */
248 OPC_MADD = 0x00 | OPC_SPECIAL2,
249 OPC_MADDU = 0x01 | OPC_SPECIAL2,
250 OPC_MUL = 0x02 | OPC_SPECIAL2,
251 OPC_MSUB = 0x04 | OPC_SPECIAL2,
252 OPC_MSUBU = 0x05 | OPC_SPECIAL2,
253 /* Misc */
254 OPC_CLZ = 0x20 | OPC_SPECIAL2,
255 OPC_CLO = 0x21 | OPC_SPECIAL2,
256 OPC_DCLZ = 0x24 | OPC_SPECIAL2,
257 OPC_DCLO = 0x25 | OPC_SPECIAL2,
258 /* Special */
259 OPC_SDBBP = 0x3F | OPC_SPECIAL2,
262 /* Special3 opcodes */
263 #define MASK_SPECIAL3(op) MASK_OP_MAJOR(op) | (op & 0x3F)
265 enum {
266 OPC_EXT = 0x00 | OPC_SPECIAL3,
267 OPC_DEXTM = 0x01 | OPC_SPECIAL3,
268 OPC_DEXTU = 0x02 | OPC_SPECIAL3,
269 OPC_DEXT = 0x03 | OPC_SPECIAL3,
270 OPC_INS = 0x04 | OPC_SPECIAL3,
271 OPC_DINSM = 0x05 | OPC_SPECIAL3,
272 OPC_DINSU = 0x06 | OPC_SPECIAL3,
273 OPC_DINS = 0x07 | OPC_SPECIAL3,
274 OPC_FORK = 0x08 | OPC_SPECIAL3,
275 OPC_YIELD = 0x09 | OPC_SPECIAL3,
276 OPC_BSHFL = 0x20 | OPC_SPECIAL3,
277 OPC_DBSHFL = 0x24 | OPC_SPECIAL3,
278 OPC_RDHWR = 0x3B | OPC_SPECIAL3,
281 /* BSHFL opcodes */
282 #define MASK_BSHFL(op) MASK_SPECIAL3(op) | (op & (0x1F << 6))
284 enum {
285 OPC_WSBH = (0x02 << 6) | OPC_BSHFL,
286 OPC_SEB = (0x10 << 6) | OPC_BSHFL,
287 OPC_SEH = (0x18 << 6) | OPC_BSHFL,
290 /* DBSHFL opcodes */
291 #define MASK_DBSHFL(op) MASK_SPECIAL3(op) | (op & (0x1F << 6))
293 enum {
294 OPC_DSBH = (0x02 << 6) | OPC_DBSHFL,
295 OPC_DSHD = (0x05 << 6) | OPC_DBSHFL,
298 /* Coprocessor 0 (rs field) */
299 #define MASK_CP0(op) MASK_OP_MAJOR(op) | (op & (0x1F << 21))
301 enum {
302 OPC_MFC0 = (0x00 << 21) | OPC_CP0,
303 OPC_DMFC0 = (0x01 << 21) | OPC_CP0,
304 OPC_MTC0 = (0x04 << 21) | OPC_CP0,
305 OPC_DMTC0 = (0x05 << 21) | OPC_CP0,
306 OPC_MFTR = (0x08 << 21) | OPC_CP0,
307 OPC_RDPGPR = (0x0A << 21) | OPC_CP0,
308 OPC_MFMC0 = (0x0B << 21) | OPC_CP0,
309 OPC_MTTR = (0x0C << 21) | OPC_CP0,
310 OPC_WRPGPR = (0x0E << 21) | OPC_CP0,
311 OPC_C0 = (0x10 << 21) | OPC_CP0,
312 OPC_C0_FIRST = (0x10 << 21) | OPC_CP0,
313 OPC_C0_LAST = (0x1F << 21) | OPC_CP0,
316 /* MFMC0 opcodes */
317 #define MASK_MFMC0(op) MASK_CP0(op) | (op & 0xFFFF)
319 enum {
320 OPC_DMT = 0x01 | (0 << 5) | (0x0F << 6) | (0x01 << 11) | OPC_MFMC0,
321 OPC_EMT = 0x01 | (1 << 5) | (0x0F << 6) | (0x01 << 11) | OPC_MFMC0,
322 OPC_DVPE = 0x01 | (0 << 5) | OPC_MFMC0,
323 OPC_EVPE = 0x01 | (1 << 5) | OPC_MFMC0,
324 OPC_DI = (0 << 5) | (0x0C << 11) | OPC_MFMC0,
325 OPC_EI = (1 << 5) | (0x0C << 11) | OPC_MFMC0,
328 /* Coprocessor 0 (with rs == C0) */
329 #define MASK_C0(op) MASK_CP0(op) | (op & 0x3F)
331 enum {
332 OPC_TLBR = 0x01 | OPC_C0,
333 OPC_TLBWI = 0x02 | OPC_C0,
334 OPC_TLBWR = 0x06 | OPC_C0,
335 OPC_TLBP = 0x08 | OPC_C0,
336 OPC_RFE = 0x10 | OPC_C0,
337 OPC_ERET = 0x18 | OPC_C0,
338 OPC_DERET = 0x1F | OPC_C0,
339 OPC_WAIT = 0x20 | OPC_C0,
342 /* Coprocessor 1 (rs field) */
343 #define MASK_CP1(op) MASK_OP_MAJOR(op) | (op & (0x1F << 21))
345 enum {
346 OPC_MFC1 = (0x00 << 21) | OPC_CP1,
347 OPC_DMFC1 = (0x01 << 21) | OPC_CP1,
348 OPC_CFC1 = (0x02 << 21) | OPC_CP1,
349 OPC_MFHC1 = (0x03 << 21) | OPC_CP1,
350 OPC_MTC1 = (0x04 << 21) | OPC_CP1,
351 OPC_DMTC1 = (0x05 << 21) | OPC_CP1,
352 OPC_CTC1 = (0x06 << 21) | OPC_CP1,
353 OPC_MTHC1 = (0x07 << 21) | OPC_CP1,
354 OPC_BC1 = (0x08 << 21) | OPC_CP1, /* bc */
355 OPC_BC1ANY2 = (0x09 << 21) | OPC_CP1,
356 OPC_BC1ANY4 = (0x0A << 21) | OPC_CP1,
357 OPC_S_FMT = (0x10 << 21) | OPC_CP1, /* 16: fmt=single fp */
358 OPC_D_FMT = (0x11 << 21) | OPC_CP1, /* 17: fmt=double fp */
359 OPC_E_FMT = (0x12 << 21) | OPC_CP1, /* 18: fmt=extended fp */
360 OPC_Q_FMT = (0x13 << 21) | OPC_CP1, /* 19: fmt=quad fp */
361 OPC_W_FMT = (0x14 << 21) | OPC_CP1, /* 20: fmt=32bit fixed */
362 OPC_L_FMT = (0x15 << 21) | OPC_CP1, /* 21: fmt=64bit fixed */
363 OPC_PS_FMT = (0x16 << 21) | OPC_CP1, /* 22: fmt=paired single fp */
366 #define MASK_CP1_FUNC(op) MASK_CP1(op) | (op & 0x3F)
367 #define MASK_BC1(op) MASK_CP1(op) | (op & (0x3 << 16))
369 enum {
370 OPC_BC1F = (0x00 << 16) | OPC_BC1,
371 OPC_BC1T = (0x01 << 16) | OPC_BC1,
372 OPC_BC1FL = (0x02 << 16) | OPC_BC1,
373 OPC_BC1TL = (0x03 << 16) | OPC_BC1,
376 enum {
377 OPC_BC1FANY2 = (0x00 << 16) | OPC_BC1ANY2,
378 OPC_BC1TANY2 = (0x01 << 16) | OPC_BC1ANY2,
381 enum {
382 OPC_BC1FANY4 = (0x00 << 16) | OPC_BC1ANY4,
383 OPC_BC1TANY4 = (0x01 << 16) | OPC_BC1ANY4,
386 #define MASK_CP2(op) MASK_OP_MAJOR(op) | (op & (0x1F << 21))
388 enum {
389 OPC_MFC2 = (0x00 << 21) | OPC_CP2,
390 OPC_DMFC2 = (0x01 << 21) | OPC_CP2,
391 OPC_CFC2 = (0x02 << 21) | OPC_CP2,
392 OPC_MFHC2 = (0x03 << 21) | OPC_CP2,
393 OPC_MTC2 = (0x04 << 21) | OPC_CP2,
394 OPC_DMTC2 = (0x05 << 21) | OPC_CP2,
395 OPC_CTC2 = (0x06 << 21) | OPC_CP2,
396 OPC_MTHC2 = (0x07 << 21) | OPC_CP2,
397 OPC_BC2 = (0x08 << 21) | OPC_CP2,
400 #define MASK_CP3(op) MASK_OP_MAJOR(op) | (op & 0x3F)
402 enum {
403 OPC_LWXC1 = 0x00 | OPC_CP3,
404 OPC_LDXC1 = 0x01 | OPC_CP3,
405 OPC_LUXC1 = 0x05 | OPC_CP3,
406 OPC_SWXC1 = 0x08 | OPC_CP3,
407 OPC_SDXC1 = 0x09 | OPC_CP3,
408 OPC_SUXC1 = 0x0D | OPC_CP3,
409 OPC_PREFX = 0x0F | OPC_CP3,
410 OPC_ALNV_PS = 0x1E | OPC_CP3,
411 OPC_MADD_S = 0x20 | OPC_CP3,
412 OPC_MADD_D = 0x21 | OPC_CP3,
413 OPC_MADD_PS = 0x26 | OPC_CP3,
414 OPC_MSUB_S = 0x28 | OPC_CP3,
415 OPC_MSUB_D = 0x29 | OPC_CP3,
416 OPC_MSUB_PS = 0x2E | OPC_CP3,
417 OPC_NMADD_S = 0x30 | OPC_CP3,
418 OPC_NMADD_D = 0x31 | OPC_CP3,
419 OPC_NMADD_PS= 0x36 | OPC_CP3,
420 OPC_NMSUB_S = 0x38 | OPC_CP3,
421 OPC_NMSUB_D = 0x39 | OPC_CP3,
422 OPC_NMSUB_PS= 0x3E | OPC_CP3,
425 /* global register indices */
426 static TCGv cpu_env, current_tc_gprs, current_tc_hi, cpu_T[2];
428 static inline void tcg_gen_helper_0_1i(void *func, TCGv arg)
430 TCGv t = tcg_const_i32(arg);
432 tcg_gen_helper_0_1(func, t);
433 tcg_temp_free(t);
436 static inline void tcg_gen_helper_0_2ii(void *func, TCGv arg1, TCGv arg2)
438 TCGv t1 = tcg_const_i32(arg1);
439 TCGv t2 = tcg_const_i32(arg2);
441 tcg_gen_helper_0_2(func, t1, t2);
442 tcg_temp_free(t1);
443 tcg_temp_free(t2);
446 typedef struct DisasContext {
447 struct TranslationBlock *tb;
448 target_ulong pc, saved_pc;
449 uint32_t opcode;
450 uint32_t fp_status;
451 /* Routine used to access memory */
452 int mem_idx;
453 uint32_t hflags, saved_hflags;
454 int bstate;
455 target_ulong btarget;
456 } DisasContext;
458 enum {
459 BS_NONE = 0, /* We go out of the TB without reaching a branch or an
460 * exception condition
462 BS_STOP = 1, /* We want to stop translation for any reason */
463 BS_BRANCH = 2, /* We reached a branch condition */
464 BS_EXCP = 3, /* We reached an exception condition */
467 static const char *regnames[] =
468 { "r0", "at", "v0", "v1", "a0", "a1", "a2", "a3",
469 "t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7",
470 "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7",
471 "t8", "t9", "k0", "k1", "gp", "sp", "s8", "ra", };
473 static const char *fregnames[] =
474 { "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7",
475 "f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15",
476 "f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23",
477 "f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31", };
479 #ifdef MIPS_DEBUG_DISAS
480 #define MIPS_DEBUG(fmt, args...) \
481 do { \
482 if (loglevel & CPU_LOG_TB_IN_ASM) { \
483 fprintf(logfile, TARGET_FMT_lx ": %08x " fmt "\n", \
484 ctx->pc, ctx->opcode , ##args); \
486 } while (0)
487 #else
488 #define MIPS_DEBUG(fmt, args...) do { } while(0)
489 #endif
491 #define MIPS_INVAL(op) \
492 do { \
493 MIPS_DEBUG("Invalid %s %03x %03x %03x", op, ctx->opcode >> 26, \
494 ctx->opcode & 0x3F, ((ctx->opcode >> 16) & 0x1F)); \
495 } while (0)
497 /* General purpose registers moves. */
498 static inline void gen_load_gpr (TCGv t, int reg)
500 if (reg == 0)
501 tcg_gen_movi_tl(t, 0);
502 else
503 tcg_gen_ld_tl(t, current_tc_gprs, sizeof(target_ulong) * reg);
506 static inline void gen_store_gpr (TCGv t, int reg)
508 if (reg != 0)
509 tcg_gen_st_tl(t, current_tc_gprs, sizeof(target_ulong) * reg);
512 /* Moves to/from HI and LO registers. */
513 static inline void gen_load_LO (TCGv t, int reg)
515 tcg_gen_ld_tl(t, current_tc_hi,
516 offsetof(CPUState, LO)
517 - offsetof(CPUState, HI)
518 + sizeof(target_ulong) * reg);
521 static inline void gen_store_LO (TCGv t, int reg)
523 tcg_gen_st_tl(t, current_tc_hi,
524 offsetof(CPUState, LO)
525 - offsetof(CPUState, HI)
526 + sizeof(target_ulong) * reg);
529 static inline void gen_load_HI (TCGv t, int reg)
531 tcg_gen_ld_tl(t, current_tc_hi, sizeof(target_ulong) * reg);
534 static inline void gen_store_HI (TCGv t, int reg)
536 tcg_gen_st_tl(t, current_tc_hi, sizeof(target_ulong) * reg);
539 /* Moves to/from shadow registers. */
540 static inline void gen_load_srsgpr (TCGv t, int reg)
542 if (reg == 0)
543 tcg_gen_movi_tl(t, 0);
544 else {
545 TCGv r_tmp = tcg_temp_new(TCG_TYPE_I32);
547 tcg_gen_ld_i32(r_tmp, cpu_env, offsetof(CPUState, CP0_SRSCtl));
548 tcg_gen_shri_i32(r_tmp, r_tmp, CP0SRSCtl_PSS);
549 tcg_gen_andi_i32(r_tmp, r_tmp, 0xf);
550 tcg_gen_muli_i32(r_tmp, r_tmp, sizeof(target_ulong) * 32);
551 tcg_gen_add_i32(r_tmp, cpu_env, r_tmp);
553 tcg_gen_ld_tl(t, r_tmp, sizeof(target_ulong) * reg);
554 tcg_temp_free(r_tmp);
558 static inline void gen_store_srsgpr (TCGv t, int reg)
560 if (reg != 0) {
561 TCGv r_tmp = tcg_temp_new(TCG_TYPE_I32);
563 tcg_gen_ld_i32(r_tmp, cpu_env, offsetof(CPUState, CP0_SRSCtl));
564 tcg_gen_shri_i32(r_tmp, r_tmp, CP0SRSCtl_PSS);
565 tcg_gen_andi_i32(r_tmp, r_tmp, 0xf);
566 tcg_gen_muli_i32(r_tmp, r_tmp, sizeof(target_ulong) * 32);
567 tcg_gen_add_i32(r_tmp, cpu_env, r_tmp);
569 tcg_gen_st_tl(t, r_tmp, sizeof(target_ulong) * reg);
570 tcg_temp_free(r_tmp);
574 /* Floating point register moves. */
575 #define FGEN32(func, NAME) \
576 static GenOpFunc *NAME ## _table [32] = { \
577 NAME ## 0, NAME ## 1, NAME ## 2, NAME ## 3, \
578 NAME ## 4, NAME ## 5, NAME ## 6, NAME ## 7, \
579 NAME ## 8, NAME ## 9, NAME ## 10, NAME ## 11, \
580 NAME ## 12, NAME ## 13, NAME ## 14, NAME ## 15, \
581 NAME ## 16, NAME ## 17, NAME ## 18, NAME ## 19, \
582 NAME ## 20, NAME ## 21, NAME ## 22, NAME ## 23, \
583 NAME ## 24, NAME ## 25, NAME ## 26, NAME ## 27, \
584 NAME ## 28, NAME ## 29, NAME ## 30, NAME ## 31, \
585 }; \
586 static always_inline void func(int n) \
588 NAME ## _table[n](); \
591 FGEN32(gen_op_load_fpr_WT0, gen_op_load_fpr_WT0_fpr);
592 FGEN32(gen_op_store_fpr_WT0, gen_op_store_fpr_WT0_fpr);
594 FGEN32(gen_op_load_fpr_WT1, gen_op_load_fpr_WT1_fpr);
595 FGEN32(gen_op_store_fpr_WT1, gen_op_store_fpr_WT1_fpr);
597 FGEN32(gen_op_load_fpr_WT2, gen_op_load_fpr_WT2_fpr);
598 FGEN32(gen_op_store_fpr_WT2, gen_op_store_fpr_WT2_fpr);
600 FGEN32(gen_op_load_fpr_DT0, gen_op_load_fpr_DT0_fpr);
601 FGEN32(gen_op_store_fpr_DT0, gen_op_store_fpr_DT0_fpr);
603 FGEN32(gen_op_load_fpr_DT1, gen_op_load_fpr_DT1_fpr);
604 FGEN32(gen_op_store_fpr_DT1, gen_op_store_fpr_DT1_fpr);
606 FGEN32(gen_op_load_fpr_DT2, gen_op_load_fpr_DT2_fpr);
607 FGEN32(gen_op_store_fpr_DT2, gen_op_store_fpr_DT2_fpr);
609 FGEN32(gen_op_load_fpr_WTH0, gen_op_load_fpr_WTH0_fpr);
610 FGEN32(gen_op_store_fpr_WTH0, gen_op_store_fpr_WTH0_fpr);
612 FGEN32(gen_op_load_fpr_WTH1, gen_op_load_fpr_WTH1_fpr);
613 FGEN32(gen_op_store_fpr_WTH1, gen_op_store_fpr_WTH1_fpr);
615 FGEN32(gen_op_load_fpr_WTH2, gen_op_load_fpr_WTH2_fpr);
616 FGEN32(gen_op_store_fpr_WTH2, gen_op_store_fpr_WTH2_fpr);
618 #define GEN_LOAD_FREG_FTN(FTn, Fn) \
619 do { \
620 glue(gen_op_load_fpr_, FTn)(Fn); \
621 } while (0)
623 #define GEN_STORE_FTN_FREG(Fn, FTn) \
624 do { \
625 glue(gen_op_store_fpr_, FTn)(Fn); \
626 } while (0)
628 #define FOP_CONDS(type, fmt) \
629 static GenOpFunc1 * gen_op_cmp ## type ## _ ## fmt ## _table[16] = { \
630 gen_op_cmp ## type ## _ ## fmt ## _f, \
631 gen_op_cmp ## type ## _ ## fmt ## _un, \
632 gen_op_cmp ## type ## _ ## fmt ## _eq, \
633 gen_op_cmp ## type ## _ ## fmt ## _ueq, \
634 gen_op_cmp ## type ## _ ## fmt ## _olt, \
635 gen_op_cmp ## type ## _ ## fmt ## _ult, \
636 gen_op_cmp ## type ## _ ## fmt ## _ole, \
637 gen_op_cmp ## type ## _ ## fmt ## _ule, \
638 gen_op_cmp ## type ## _ ## fmt ## _sf, \
639 gen_op_cmp ## type ## _ ## fmt ## _ngle, \
640 gen_op_cmp ## type ## _ ## fmt ## _seq, \
641 gen_op_cmp ## type ## _ ## fmt ## _ngl, \
642 gen_op_cmp ## type ## _ ## fmt ## _lt, \
643 gen_op_cmp ## type ## _ ## fmt ## _nge, \
644 gen_op_cmp ## type ## _ ## fmt ## _le, \
645 gen_op_cmp ## type ## _ ## fmt ## _ngt, \
646 }; \
647 static always_inline void gen_cmp ## type ## _ ## fmt(int n, long cc) \
649 gen_op_cmp ## type ## _ ## fmt ## _table[n](cc); \
652 FOP_CONDS(, d)
653 FOP_CONDS(abs, d)
654 FOP_CONDS(, s)
655 FOP_CONDS(abs, s)
656 FOP_CONDS(, ps)
657 FOP_CONDS(abs, ps)
659 /* Tests */
660 #define OP_COND(name, cond) \
661 void glue(gen_op_, name) (void) \
663 int l1 = gen_new_label(); \
664 int l2 = gen_new_label(); \
666 tcg_gen_brcond_tl(cond, cpu_T[0], cpu_T[1], l1); \
667 tcg_gen_movi_tl(cpu_T[0], 0); \
668 tcg_gen_br(l2); \
669 gen_set_label(l1); \
670 tcg_gen_movi_tl(cpu_T[0], 1); \
671 gen_set_label(l2); \
673 OP_COND(eq, TCG_COND_EQ);
674 OP_COND(ne, TCG_COND_NE);
675 OP_COND(ge, TCG_COND_GE);
676 OP_COND(geu, TCG_COND_GEU);
677 OP_COND(lt, TCG_COND_LT);
678 OP_COND(ltu, TCG_COND_LTU);
679 #undef OP_COND
681 #define OP_CONDI(name, cond) \
682 void glue(gen_op_, name) (target_ulong val) \
684 int l1 = gen_new_label(); \
685 int l2 = gen_new_label(); \
687 tcg_gen_brcondi_tl(cond, cpu_T[0], val, l1); \
688 tcg_gen_movi_tl(cpu_T[0], 0); \
689 tcg_gen_br(l2); \
690 gen_set_label(l1); \
691 tcg_gen_movi_tl(cpu_T[0], 1); \
692 gen_set_label(l2); \
694 OP_CONDI(lti, TCG_COND_LT);
695 OP_CONDI(ltiu, TCG_COND_LTU);
696 #undef OP_CONDI
698 #define OP_CONDZ(name, cond) \
699 void glue(gen_op_, name) (void) \
701 int l1 = gen_new_label(); \
702 int l2 = gen_new_label(); \
704 tcg_gen_brcondi_tl(cond, cpu_T[0], 0, l1); \
705 tcg_gen_movi_tl(cpu_T[0], 0); \
706 tcg_gen_br(l2); \
707 gen_set_label(l1); \
708 tcg_gen_movi_tl(cpu_T[0], 1); \
709 gen_set_label(l2); \
711 OP_CONDZ(gez, TCG_COND_GE);
712 OP_CONDZ(gtz, TCG_COND_GT);
713 OP_CONDZ(lez, TCG_COND_LE);
714 OP_CONDZ(ltz, TCG_COND_LT);
715 #undef OP_CONDZ
717 static inline void gen_save_pc(target_ulong pc)
719 TCGv r_tmp = tcg_temp_new(TCG_TYPE_TL);
720 TCGv r_tc_off = tcg_temp_new(TCG_TYPE_I32);
721 TCGv r_tc_off_ptr = tcg_temp_new(TCG_TYPE_PTR);
722 TCGv r_ptr = tcg_temp_new(TCG_TYPE_PTR);
724 tcg_gen_movi_tl(r_tmp, pc);
725 tcg_gen_ld_i32(r_tc_off, cpu_env, offsetof(CPUState, current_tc));
726 tcg_gen_muli_i32(r_tc_off, r_tc_off, sizeof(target_ulong));
727 tcg_gen_ext_i32_ptr(r_tc_off_ptr, r_tc_off);
728 tcg_gen_add_ptr(r_ptr, cpu_env, r_tc_off_ptr);
729 tcg_gen_st_tl(r_tmp, r_ptr, offsetof(CPUState, PC));
730 tcg_temp_free(r_tc_off);
731 tcg_temp_free(r_tc_off_ptr);
732 tcg_temp_free(r_ptr);
733 tcg_temp_free(r_tmp);
736 static inline void gen_breg_pc(void)
738 TCGv r_tmp = tcg_temp_new(TCG_TYPE_TL);
739 TCGv r_tc_off = tcg_temp_new(TCG_TYPE_I32);
740 TCGv r_tc_off_ptr = tcg_temp_new(TCG_TYPE_PTR);
741 TCGv r_ptr = tcg_temp_new(TCG_TYPE_PTR);
743 tcg_gen_ld_tl(r_tmp, cpu_env, offsetof(CPUState, btarget));
744 tcg_gen_ld_i32(r_tc_off, cpu_env, offsetof(CPUState, current_tc));
745 tcg_gen_muli_i32(r_tc_off, r_tc_off, sizeof(target_ulong));
746 tcg_gen_ext_i32_ptr(r_tc_off_ptr, r_tc_off);
747 tcg_gen_add_ptr(r_ptr, cpu_env, r_tc_off_ptr);
748 tcg_gen_st_tl(r_tmp, r_ptr, offsetof(CPUState, PC));
749 tcg_temp_free(r_tc_off);
750 tcg_temp_free(r_tc_off_ptr);
751 tcg_temp_free(r_ptr);
752 tcg_temp_free(r_tmp);
755 static inline void gen_save_btarget(target_ulong btarget)
757 TCGv r_tmp = tcg_temp_new(TCG_TYPE_TL);
759 tcg_gen_movi_tl(r_tmp, btarget);
760 tcg_gen_st_tl(r_tmp, cpu_env, offsetof(CPUState, btarget));
761 tcg_temp_free(r_tmp);
764 static always_inline void gen_save_breg_target(int reg)
766 TCGv r_tmp = tcg_temp_new(TCG_TYPE_TL);
768 gen_load_gpr(r_tmp, reg);
769 tcg_gen_st_tl(r_tmp, cpu_env, offsetof(CPUState, btarget));
770 tcg_temp_free(r_tmp);
773 static always_inline void save_cpu_state (DisasContext *ctx, int do_save_pc)
775 #if defined MIPS_DEBUG_DISAS
776 if (loglevel & CPU_LOG_TB_IN_ASM) {
777 fprintf(logfile, "hflags %08x saved %08x\n",
778 ctx->hflags, ctx->saved_hflags);
780 #endif
781 if (do_save_pc && ctx->pc != ctx->saved_pc) {
782 gen_save_pc(ctx->pc);
783 ctx->saved_pc = ctx->pc;
785 if (ctx->hflags != ctx->saved_hflags) {
786 gen_op_save_state(ctx->hflags);
787 ctx->saved_hflags = ctx->hflags;
788 switch (ctx->hflags & MIPS_HFLAG_BMASK) {
789 case MIPS_HFLAG_BR:
790 break;
791 case MIPS_HFLAG_BC:
792 case MIPS_HFLAG_BL:
793 case MIPS_HFLAG_B:
794 gen_save_btarget(ctx->btarget);
795 break;
800 static always_inline void restore_cpu_state (CPUState *env, DisasContext *ctx)
802 ctx->saved_hflags = ctx->hflags;
803 switch (ctx->hflags & MIPS_HFLAG_BMASK) {
804 case MIPS_HFLAG_BR:
805 break;
806 case MIPS_HFLAG_BC:
807 case MIPS_HFLAG_BL:
808 case MIPS_HFLAG_B:
809 ctx->btarget = env->btarget;
810 break;
814 static always_inline void
815 generate_exception_err (DisasContext *ctx, int excp, int err)
817 save_cpu_state(ctx, 1);
818 tcg_gen_helper_0_2ii(do_raise_exception_err, excp, err);
819 tcg_gen_helper_0_0(do_interrupt_restart);
820 tcg_gen_exit_tb(0);
823 static always_inline void
824 generate_exception (DisasContext *ctx, int excp)
826 save_cpu_state(ctx, 1);
827 tcg_gen_helper_0_1i(do_raise_exception, excp);
828 tcg_gen_helper_0_0(do_interrupt_restart);
829 tcg_gen_exit_tb(0);
832 /* Addresses computation */
833 static inline void gen_op_addr_add (void)
835 tcg_gen_add_tl(cpu_T[0], cpu_T[0], cpu_T[1]);
837 #if defined(TARGET_MIPS64)
838 /* For compatibility with 32-bit code, data reference in user mode
839 with Status_UX = 0 should be casted to 32-bit and sign extended.
840 See the MIPS64 PRA manual, section 4.10. */
842 int l1 = gen_new_label();
845 TCGv r_tmp = tcg_temp_new(TCG_TYPE_I32);
847 tcg_gen_ld_i32(r_tmp, cpu_env, offsetof(CPUState, hflags));
848 tcg_gen_andi_i32(r_tmp, r_tmp, MIPS_HFLAG_KSU);
849 tcg_gen_brcondi_i32(TCG_COND_NE, r_tmp, MIPS_HFLAG_UM, l1);
852 TCGv r_tmp = tcg_temp_new(TCG_TYPE_I32);
854 tcg_gen_ld_i32(r_tmp, cpu_env, offsetof(CPUState, CP0_Status));
855 tcg_gen_andi_i32(r_tmp, r_tmp, (1 << CP0St_UX));
856 tcg_gen_brcondi_i32(TCG_COND_NE, r_tmp, 0, l1);
858 tcg_gen_ext32s_i64(cpu_T[0], cpu_T[0]);
859 gen_set_label(l1);
861 #endif
864 static always_inline void check_cp0_enabled(DisasContext *ctx)
866 if (unlikely(!(ctx->hflags & MIPS_HFLAG_CP0)))
867 generate_exception_err(ctx, EXCP_CpU, 1);
870 static always_inline void check_cp1_enabled(DisasContext *ctx)
872 if (unlikely(!(ctx->hflags & MIPS_HFLAG_FPU)))
873 generate_exception_err(ctx, EXCP_CpU, 1);
876 /* Verify that the processor is running with COP1X instructions enabled.
877 This is associated with the nabla symbol in the MIPS32 and MIPS64
878 opcode tables. */
880 static always_inline void check_cop1x(DisasContext *ctx)
882 if (unlikely(!(ctx->hflags & MIPS_HFLAG_COP1X)))
883 generate_exception(ctx, EXCP_RI);
886 /* Verify that the processor is running with 64-bit floating-point
887 operations enabled. */
889 static always_inline void check_cp1_64bitmode(DisasContext *ctx)
891 if (unlikely(~ctx->hflags & (MIPS_HFLAG_F64 | MIPS_HFLAG_COP1X)))
892 generate_exception(ctx, EXCP_RI);
896 * Verify if floating point register is valid; an operation is not defined
897 * if bit 0 of any register specification is set and the FR bit in the
898 * Status register equals zero, since the register numbers specify an
899 * even-odd pair of adjacent coprocessor general registers. When the FR bit
900 * in the Status register equals one, both even and odd register numbers
901 * are valid. This limitation exists only for 64 bit wide (d,l,ps) registers.
903 * Multiple 64 bit wide registers can be checked by calling
904 * gen_op_cp1_registers(freg1 | freg2 | ... | fregN);
906 void check_cp1_registers(DisasContext *ctx, int regs)
908 if (unlikely(!(ctx->hflags & MIPS_HFLAG_F64) && (regs & 1)))
909 generate_exception(ctx, EXCP_RI);
912 /* This code generates a "reserved instruction" exception if the
913 CPU does not support the instruction set corresponding to flags. */
914 static always_inline void check_insn(CPUState *env, DisasContext *ctx, int flags)
916 if (unlikely(!(env->insn_flags & flags)))
917 generate_exception(ctx, EXCP_RI);
920 /* This code generates a "reserved instruction" exception if 64-bit
921 instructions are not enabled. */
922 static always_inline void check_mips_64(DisasContext *ctx)
924 if (unlikely(!(ctx->hflags & MIPS_HFLAG_64)))
925 generate_exception(ctx, EXCP_RI);
928 /* load/store instructions. */
929 #if defined(CONFIG_USER_ONLY)
930 #define op_ldst(name) gen_op_##name##_raw()
931 #define OP_LD_TABLE(width)
932 #define OP_ST_TABLE(width)
933 #else
934 #define op_ldst(name) (*gen_op_##name[ctx->mem_idx])()
935 #define OP_LD_TABLE(width) \
936 static GenOpFunc *gen_op_l##width[] = { \
937 &gen_op_l##width##_kernel, \
938 &gen_op_l##width##_super, \
939 &gen_op_l##width##_user, \
941 #define OP_ST_TABLE(width) \
942 static GenOpFunc *gen_op_s##width[] = { \
943 &gen_op_s##width##_kernel, \
944 &gen_op_s##width##_super, \
945 &gen_op_s##width##_user, \
947 #endif
949 #if defined(TARGET_MIPS64)
950 OP_LD_TABLE(dl);
951 OP_LD_TABLE(dr);
952 OP_ST_TABLE(dl);
953 OP_ST_TABLE(dr);
954 #endif
955 OP_LD_TABLE(wl);
956 OP_LD_TABLE(wr);
957 OP_ST_TABLE(wl);
958 OP_ST_TABLE(wr);
959 OP_LD_TABLE(wc1);
960 OP_ST_TABLE(wc1);
961 OP_LD_TABLE(dc1);
962 OP_ST_TABLE(dc1);
963 OP_LD_TABLE(uxc1);
964 OP_ST_TABLE(uxc1);
966 #define OP_LD(insn,fname) \
967 void inline op_ldst_##insn(DisasContext *ctx) \
969 tcg_gen_qemu_##fname(cpu_T[0], cpu_T[0], ctx->mem_idx); \
971 OP_LD(lb,ld8s);
972 OP_LD(lbu,ld8u);
973 OP_LD(lh,ld16s);
974 OP_LD(lhu,ld16u);
975 OP_LD(lw,ld32s);
976 #if defined(TARGET_MIPS64)
977 OP_LD(lwu,ld32u);
978 OP_LD(ld,ld64);
979 #endif
980 #undef OP_LD
982 #define OP_ST(insn,fname) \
983 void inline op_ldst_##insn(DisasContext *ctx) \
985 tcg_gen_qemu_##fname(cpu_T[1], cpu_T[0], ctx->mem_idx); \
987 OP_ST(sb,st8);
988 OP_ST(sh,st16);
989 OP_ST(sw,st32);
990 #if defined(TARGET_MIPS64)
991 OP_ST(sd,st64);
992 #endif
993 #undef OP_ST
995 #define OP_LD_ATOMIC(insn,fname) \
996 void inline op_ldst_##insn(DisasContext *ctx) \
998 tcg_gen_mov_tl(cpu_T[1], cpu_T[0]); \
999 tcg_gen_qemu_##fname(cpu_T[0], cpu_T[0], ctx->mem_idx); \
1000 tcg_gen_st_tl(cpu_T[1], cpu_env, offsetof(CPUState, CP0_LLAddr)); \
1002 OP_LD_ATOMIC(ll,ld32s);
1003 #if defined(TARGET_MIPS64)
1004 OP_LD_ATOMIC(lld,ld64);
1005 #endif
1006 #undef OP_LD_ATOMIC
1008 #define OP_ST_ATOMIC(insn,fname,almask) \
1009 void inline op_ldst_##insn(DisasContext *ctx) \
1011 TCGv r_tmp = tcg_temp_local_new(TCG_TYPE_TL); \
1012 int l1 = gen_new_label(); \
1013 int l2 = gen_new_label(); \
1014 int l3 = gen_new_label(); \
1016 tcg_gen_andi_tl(r_tmp, cpu_T[0], almask); \
1017 tcg_gen_brcondi_tl(TCG_COND_EQ, r_tmp, 0, l1); \
1018 tcg_gen_st_tl(cpu_T[0], cpu_env, offsetof(CPUState, CP0_BadVAddr)); \
1019 generate_exception(ctx, EXCP_AdES); \
1020 gen_set_label(l1); \
1021 tcg_gen_ld_tl(r_tmp, cpu_env, offsetof(CPUState, CP0_LLAddr)); \
1022 tcg_gen_brcond_tl(TCG_COND_NE, cpu_T[0], r_tmp, l2); \
1023 tcg_temp_free(r_tmp); \
1024 tcg_gen_qemu_##fname(cpu_T[1], cpu_T[0], ctx->mem_idx); \
1025 tcg_gen_movi_tl(cpu_T[0], 1); \
1026 tcg_gen_br(l3); \
1027 gen_set_label(l2); \
1028 tcg_gen_movi_tl(cpu_T[0], 0); \
1029 gen_set_label(l3); \
1031 OP_ST_ATOMIC(sc,st32,0x3);
1032 #if defined(TARGET_MIPS64)
1033 OP_ST_ATOMIC(scd,st64,0x7);
1034 #endif
1035 #undef OP_ST_ATOMIC
1037 void inline op_ldst_lwc1(DisasContext *ctx)
1039 op_ldst(lwc1);
1042 void inline op_ldst_ldc1(DisasContext *ctx)
1044 op_ldst(ldc1);
1047 void inline op_ldst_swc1(DisasContext *ctx)
1049 op_ldst(swc1);
1052 void inline op_ldst_sdc1(DisasContext *ctx)
1054 op_ldst(sdc1);
1057 /* Load and store */
1058 static void gen_ldst (DisasContext *ctx, uint32_t opc, int rt,
1059 int base, int16_t offset)
1061 const char *opn = "ldst";
1063 if (base == 0) {
1064 tcg_gen_movi_tl(cpu_T[0], offset);
1065 } else if (offset == 0) {
1066 gen_load_gpr(cpu_T[0], base);
1067 } else {
1068 gen_load_gpr(cpu_T[0], base);
1069 tcg_gen_movi_tl(cpu_T[1], offset);
1070 gen_op_addr_add();
1072 /* Don't do NOP if destination is zero: we must perform the actual
1073 memory access. */
1074 switch (opc) {
1075 #if defined(TARGET_MIPS64)
1076 case OPC_LWU:
1077 op_ldst_lwu(ctx);
1078 gen_store_gpr(cpu_T[0], rt);
1079 opn = "lwu";
1080 break;
1081 case OPC_LD:
1082 op_ldst_ld(ctx);
1083 gen_store_gpr(cpu_T[0], rt);
1084 opn = "ld";
1085 break;
1086 case OPC_LLD:
1087 op_ldst_lld(ctx);
1088 gen_store_gpr(cpu_T[0], rt);
1089 opn = "lld";
1090 break;
1091 case OPC_SD:
1092 gen_load_gpr(cpu_T[1], rt);
1093 op_ldst_sd(ctx);
1094 opn = "sd";
1095 break;
1096 case OPC_SCD:
1097 save_cpu_state(ctx, 1);
1098 gen_load_gpr(cpu_T[1], rt);
1099 op_ldst_scd(ctx);
1100 gen_store_gpr(cpu_T[0], rt);
1101 opn = "scd";
1102 break;
1103 case OPC_LDL:
1104 gen_load_gpr(cpu_T[1], rt);
1105 op_ldst(ldl);
1106 gen_store_gpr(cpu_T[1], rt);
1107 opn = "ldl";
1108 break;
1109 case OPC_SDL:
1110 gen_load_gpr(cpu_T[1], rt);
1111 op_ldst(sdl);
1112 opn = "sdl";
1113 break;
1114 case OPC_LDR:
1115 gen_load_gpr(cpu_T[1], rt);
1116 op_ldst(ldr);
1117 gen_store_gpr(cpu_T[1], rt);
1118 opn = "ldr";
1119 break;
1120 case OPC_SDR:
1121 gen_load_gpr(cpu_T[1], rt);
1122 op_ldst(sdr);
1123 opn = "sdr";
1124 break;
1125 #endif
1126 case OPC_LW:
1127 op_ldst_lw(ctx);
1128 gen_store_gpr(cpu_T[0], rt);
1129 opn = "lw";
1130 break;
1131 case OPC_SW:
1132 gen_load_gpr(cpu_T[1], rt);
1133 op_ldst_sw(ctx);
1134 opn = "sw";
1135 break;
1136 case OPC_LH:
1137 op_ldst_lh(ctx);
1138 gen_store_gpr(cpu_T[0], rt);
1139 opn = "lh";
1140 break;
1141 case OPC_SH:
1142 gen_load_gpr(cpu_T[1], rt);
1143 op_ldst_sh(ctx);
1144 opn = "sh";
1145 break;
1146 case OPC_LHU:
1147 op_ldst_lhu(ctx);
1148 gen_store_gpr(cpu_T[0], rt);
1149 opn = "lhu";
1150 break;
1151 case OPC_LB:
1152 op_ldst_lb(ctx);
1153 gen_store_gpr(cpu_T[0], rt);
1154 opn = "lb";
1155 break;
1156 case OPC_SB:
1157 gen_load_gpr(cpu_T[1], rt);
1158 op_ldst_sb(ctx);
1159 opn = "sb";
1160 break;
1161 case OPC_LBU:
1162 op_ldst_lbu(ctx);
1163 gen_store_gpr(cpu_T[0], rt);
1164 opn = "lbu";
1165 break;
1166 case OPC_LWL:
1167 gen_load_gpr(cpu_T[1], rt);
1168 op_ldst(lwl);
1169 gen_store_gpr(cpu_T[1], rt);
1170 opn = "lwl";
1171 break;
1172 case OPC_SWL:
1173 gen_load_gpr(cpu_T[1], rt);
1174 op_ldst(swl);
1175 opn = "swr";
1176 break;
1177 case OPC_LWR:
1178 gen_load_gpr(cpu_T[1], rt);
1179 op_ldst(lwr);
1180 gen_store_gpr(cpu_T[1], rt);
1181 opn = "lwr";
1182 break;
1183 case OPC_SWR:
1184 gen_load_gpr(cpu_T[1], rt);
1185 op_ldst(swr);
1186 opn = "swr";
1187 break;
1188 case OPC_LL:
1189 op_ldst_ll(ctx);
1190 gen_store_gpr(cpu_T[0], rt);
1191 opn = "ll";
1192 break;
1193 case OPC_SC:
1194 save_cpu_state(ctx, 1);
1195 gen_load_gpr(cpu_T[1], rt);
1196 op_ldst_sc(ctx);
1197 gen_store_gpr(cpu_T[0], rt);
1198 opn = "sc";
1199 break;
1200 default:
1201 MIPS_INVAL(opn);
1202 generate_exception(ctx, EXCP_RI);
1203 return;
1205 MIPS_DEBUG("%s %s, %d(%s)", opn, regnames[rt], offset, regnames[base]);
1208 /* Load and store */
1209 static void gen_flt_ldst (DisasContext *ctx, uint32_t opc, int ft,
1210 int base, int16_t offset)
1212 const char *opn = "flt_ldst";
1214 if (base == 0) {
1215 tcg_gen_movi_tl(cpu_T[0], offset);
1216 } else if (offset == 0) {
1217 gen_load_gpr(cpu_T[0], base);
1218 } else {
1219 gen_load_gpr(cpu_T[0], base);
1220 tcg_gen_movi_tl(cpu_T[1], offset);
1221 gen_op_addr_add();
1223 /* Don't do NOP if destination is zero: we must perform the actual
1224 memory access. */
1225 switch (opc) {
1226 case OPC_LWC1:
1227 op_ldst_lwc1(ctx);
1228 GEN_STORE_FTN_FREG(ft, WT0);
1229 opn = "lwc1";
1230 break;
1231 case OPC_SWC1:
1232 GEN_LOAD_FREG_FTN(WT0, ft);
1233 op_ldst_swc1(ctx);
1234 opn = "swc1";
1235 break;
1236 case OPC_LDC1:
1237 op_ldst_ldc1(ctx);
1238 GEN_STORE_FTN_FREG(ft, DT0);
1239 opn = "ldc1";
1240 break;
1241 case OPC_SDC1:
1242 GEN_LOAD_FREG_FTN(DT0, ft);
1243 op_ldst_sdc1(ctx);
1244 opn = "sdc1";
1245 break;
1246 default:
1247 MIPS_INVAL(opn);
1248 generate_exception(ctx, EXCP_RI);
1249 return;
1251 MIPS_DEBUG("%s %s, %d(%s)", opn, fregnames[ft], offset, regnames[base]);
1254 /* Arithmetic with immediate operand */
1255 static void gen_arith_imm (CPUState *env, DisasContext *ctx, uint32_t opc,
1256 int rt, int rs, int16_t imm)
1258 target_ulong uimm;
1259 const char *opn = "imm arith";
1261 if (rt == 0 && opc != OPC_ADDI && opc != OPC_DADDI) {
1262 /* If no destination, treat it as a NOP.
1263 For addi, we must generate the overflow exception when needed. */
1264 MIPS_DEBUG("NOP");
1265 return;
1267 uimm = (uint16_t)imm;
1268 switch (opc) {
1269 case OPC_ADDI:
1270 case OPC_ADDIU:
1271 #if defined(TARGET_MIPS64)
1272 case OPC_DADDI:
1273 case OPC_DADDIU:
1274 #endif
1275 case OPC_SLTI:
1276 case OPC_SLTIU:
1277 uimm = (target_long)imm; /* Sign extend to 32/64 bits */
1278 tcg_gen_movi_tl(cpu_T[1], uimm);
1279 /* Fall through. */
1280 case OPC_ANDI:
1281 case OPC_ORI:
1282 case OPC_XORI:
1283 gen_load_gpr(cpu_T[0], rs);
1284 break;
1285 case OPC_LUI:
1286 tcg_gen_movi_tl(cpu_T[0], imm << 16);
1287 break;
1288 case OPC_SLL:
1289 case OPC_SRA:
1290 case OPC_SRL:
1291 #if defined(TARGET_MIPS64)
1292 case OPC_DSLL:
1293 case OPC_DSRA:
1294 case OPC_DSRL:
1295 case OPC_DSLL32:
1296 case OPC_DSRA32:
1297 case OPC_DSRL32:
1298 #endif
1299 uimm &= 0x1f;
1300 gen_load_gpr(cpu_T[0], rs);
1301 break;
1303 switch (opc) {
1304 case OPC_ADDI:
1306 TCGv r_tmp1 = tcg_temp_local_new(TCG_TYPE_TL);
1307 TCGv r_tmp2 = tcg_temp_new(TCG_TYPE_TL);
1308 int l1 = gen_new_label();
1310 save_cpu_state(ctx, 1);
1311 tcg_gen_ext32s_tl(r_tmp1, cpu_T[0]);
1312 tcg_gen_addi_tl(cpu_T[0], r_tmp1, uimm);
1314 tcg_gen_xori_tl(r_tmp1, r_tmp1, uimm);
1315 tcg_gen_xori_tl(r_tmp1, r_tmp1, -1);
1316 tcg_gen_xori_tl(r_tmp2, cpu_T[0], uimm);
1317 tcg_gen_and_tl(r_tmp1, r_tmp1, r_tmp2);
1318 tcg_temp_free(r_tmp2);
1319 tcg_gen_shri_tl(r_tmp1, r_tmp1, 31);
1320 tcg_gen_brcondi_tl(TCG_COND_EQ, r_tmp1, 0, l1);
1321 tcg_temp_free(r_tmp1);
1322 /* operands of same sign, result different sign */
1323 generate_exception(ctx, EXCP_OVERFLOW);
1324 gen_set_label(l1);
1326 tcg_gen_ext32s_tl(cpu_T[0], cpu_T[0]);
1328 opn = "addi";
1329 break;
1330 case OPC_ADDIU:
1331 tcg_gen_ext32s_tl(cpu_T[0], cpu_T[0]);
1332 tcg_gen_addi_tl(cpu_T[0], cpu_T[0], uimm);
1333 tcg_gen_ext32s_tl(cpu_T[0], cpu_T[0]);
1334 opn = "addiu";
1335 break;
1336 #if defined(TARGET_MIPS64)
1337 case OPC_DADDI:
1339 TCGv r_tmp1 = tcg_temp_local_new(TCG_TYPE_TL);
1340 TCGv r_tmp2 = tcg_temp_new(TCG_TYPE_TL);
1341 int l1 = gen_new_label();
1343 save_cpu_state(ctx, 1);
1344 tcg_gen_mov_tl(r_tmp1, cpu_T[0]);
1345 tcg_gen_addi_tl(cpu_T[0], cpu_T[0], uimm);
1347 tcg_gen_xori_tl(r_tmp1, r_tmp1, uimm);
1348 tcg_gen_xori_tl(r_tmp1, r_tmp1, -1);
1349 tcg_gen_xori_tl(r_tmp2, cpu_T[0], uimm);
1350 tcg_gen_and_tl(r_tmp1, r_tmp1, r_tmp2);
1351 tcg_temp_free(r_tmp2);
1352 tcg_gen_shri_tl(r_tmp1, r_tmp1, 63);
1353 tcg_gen_brcondi_tl(TCG_COND_EQ, r_tmp1, 0, l1);
1354 tcg_temp_free(r_tmp1);
1355 /* operands of same sign, result different sign */
1356 generate_exception(ctx, EXCP_OVERFLOW);
1357 gen_set_label(l1);
1359 opn = "daddi";
1360 break;
1361 case OPC_DADDIU:
1362 tcg_gen_addi_tl(cpu_T[0], cpu_T[0], uimm);
1363 opn = "daddiu";
1364 break;
1365 #endif
1366 case OPC_SLTI:
1367 gen_op_lti(uimm);
1368 opn = "slti";
1369 break;
1370 case OPC_SLTIU:
1371 gen_op_ltiu(uimm);
1372 opn = "sltiu";
1373 break;
1374 case OPC_ANDI:
1375 tcg_gen_andi_tl(cpu_T[0], cpu_T[0], uimm);
1376 opn = "andi";
1377 break;
1378 case OPC_ORI:
1379 tcg_gen_ori_tl(cpu_T[0], cpu_T[0], uimm);
1380 opn = "ori";
1381 break;
1382 case OPC_XORI:
1383 tcg_gen_xori_tl(cpu_T[0], cpu_T[0], uimm);
1384 opn = "xori";
1385 break;
1386 case OPC_LUI:
1387 opn = "lui";
1388 break;
1389 case OPC_SLL:
1390 tcg_gen_ext32u_tl(cpu_T[0], cpu_T[0]);
1391 tcg_gen_shli_tl(cpu_T[0], cpu_T[0], uimm);
1392 tcg_gen_ext32s_tl(cpu_T[0], cpu_T[0]);
1393 opn = "sll";
1394 break;
1395 case OPC_SRA:
1396 tcg_gen_ext32s_tl(cpu_T[0], cpu_T[0]);
1397 tcg_gen_sari_tl(cpu_T[0], cpu_T[0], uimm);
1398 tcg_gen_ext32s_tl(cpu_T[0], cpu_T[0]);
1399 opn = "sra";
1400 break;
1401 case OPC_SRL:
1402 switch ((ctx->opcode >> 21) & 0x1f) {
1403 case 0:
1404 tcg_gen_ext32u_tl(cpu_T[0], cpu_T[0]);
1405 tcg_gen_shri_tl(cpu_T[0], cpu_T[0], uimm);
1406 tcg_gen_ext32s_tl(cpu_T[0], cpu_T[0]);
1407 opn = "srl";
1408 break;
1409 case 1:
1410 /* rotr is decoded as srl on non-R2 CPUs */
1411 if (env->insn_flags & ISA_MIPS32R2) {
1412 if (uimm != 0) {
1413 TCGv r_tmp1 = tcg_temp_new(TCG_TYPE_I32);
1414 TCGv r_tmp2 = tcg_temp_new(TCG_TYPE_I32);
1416 tcg_gen_trunc_tl_i32(r_tmp1, cpu_T[0]);
1417 tcg_gen_movi_i32(r_tmp2, 0x20);
1418 tcg_gen_subi_i32(r_tmp2, r_tmp2, uimm);
1419 tcg_gen_shl_i32(r_tmp2, r_tmp1, r_tmp2);
1420 tcg_gen_shri_i32(r_tmp1, r_tmp1, uimm);
1421 tcg_gen_or_i32(r_tmp1, r_tmp1, r_tmp2);
1422 tcg_gen_ext_i32_tl(cpu_T[0], r_tmp1);
1423 tcg_temp_free(r_tmp1);
1424 tcg_temp_free(r_tmp2);
1426 opn = "rotr";
1427 } else {
1428 tcg_gen_ext32u_tl(cpu_T[0], cpu_T[0]);
1429 tcg_gen_shri_tl(cpu_T[0], cpu_T[0], uimm);
1430 tcg_gen_ext32s_tl(cpu_T[0], cpu_T[0]);
1431 opn = "srl";
1433 break;
1434 default:
1435 MIPS_INVAL("invalid srl flag");
1436 generate_exception(ctx, EXCP_RI);
1437 break;
1439 break;
1440 #if defined(TARGET_MIPS64)
1441 case OPC_DSLL:
1442 tcg_gen_shli_tl(cpu_T[0], cpu_T[0], uimm);
1443 opn = "dsll";
1444 break;
1445 case OPC_DSRA:
1446 tcg_gen_sari_tl(cpu_T[0], cpu_T[0], uimm);
1447 opn = "dsra";
1448 break;
1449 case OPC_DSRL:
1450 switch ((ctx->opcode >> 21) & 0x1f) {
1451 case 0:
1452 tcg_gen_shri_tl(cpu_T[0], cpu_T[0], uimm);
1453 opn = "dsrl";
1454 break;
1455 case 1:
1456 /* drotr is decoded as dsrl on non-R2 CPUs */
1457 if (env->insn_flags & ISA_MIPS32R2) {
1458 if (uimm != 0) {
1459 TCGv r_tmp1 = tcg_temp_new(TCG_TYPE_TL);
1461 tcg_gen_movi_tl(r_tmp1, 0x40);
1462 tcg_gen_subi_tl(r_tmp1, r_tmp1, uimm);
1463 tcg_gen_shl_tl(r_tmp1, cpu_T[0], r_tmp1);
1464 tcg_gen_shri_tl(cpu_T[0], cpu_T[0], uimm);
1465 tcg_gen_or_tl(cpu_T[0], cpu_T[0], r_tmp1);
1466 tcg_temp_free(r_tmp1);
1468 opn = "drotr";
1469 } else {
1470 tcg_gen_shri_tl(cpu_T[0], cpu_T[0], uimm);
1471 opn = "dsrl";
1473 break;
1474 default:
1475 MIPS_INVAL("invalid dsrl flag");
1476 generate_exception(ctx, EXCP_RI);
1477 break;
1479 break;
1480 case OPC_DSLL32:
1481 tcg_gen_shli_tl(cpu_T[0], cpu_T[0], uimm + 32);
1482 opn = "dsll32";
1483 break;
1484 case OPC_DSRA32:
1485 tcg_gen_sari_tl(cpu_T[0], cpu_T[0], uimm + 32);
1486 opn = "dsra32";
1487 break;
1488 case OPC_DSRL32:
1489 switch ((ctx->opcode >> 21) & 0x1f) {
1490 case 0:
1491 tcg_gen_shri_tl(cpu_T[0], cpu_T[0], uimm + 32);
1492 opn = "dsrl32";
1493 break;
1494 case 1:
1495 /* drotr32 is decoded as dsrl32 on non-R2 CPUs */
1496 if (env->insn_flags & ISA_MIPS32R2) {
1497 TCGv r_tmp1 = tcg_temp_new(TCG_TYPE_TL);
1498 TCGv r_tmp2 = tcg_temp_new(TCG_TYPE_TL);
1500 tcg_gen_movi_tl(r_tmp1, 0x40);
1501 tcg_gen_movi_tl(r_tmp2, 32);
1502 tcg_gen_addi_tl(r_tmp2, r_tmp2, uimm);
1503 tcg_gen_sub_tl(r_tmp1, r_tmp1, r_tmp2);
1504 tcg_gen_shl_tl(r_tmp1, cpu_T[0], r_tmp1);
1505 tcg_gen_shr_tl(cpu_T[0], cpu_T[0], r_tmp2);
1506 tcg_gen_or_tl(cpu_T[0], cpu_T[0], r_tmp1);
1507 tcg_temp_free(r_tmp1);
1508 tcg_temp_free(r_tmp2);
1509 opn = "drotr32";
1510 } else {
1511 tcg_gen_shri_tl(cpu_T[0], cpu_T[0], uimm + 32);
1512 opn = "dsrl32";
1514 break;
1515 default:
1516 MIPS_INVAL("invalid dsrl32 flag");
1517 generate_exception(ctx, EXCP_RI);
1518 break;
1520 break;
1521 #endif
1522 default:
1523 MIPS_INVAL(opn);
1524 generate_exception(ctx, EXCP_RI);
1525 return;
1527 gen_store_gpr(cpu_T[0], rt);
1528 MIPS_DEBUG("%s %s, %s, " TARGET_FMT_lx, opn, regnames[rt], regnames[rs], uimm);
1531 /* Arithmetic */
1532 static void gen_arith (CPUState *env, DisasContext *ctx, uint32_t opc,
1533 int rd, int rs, int rt)
1535 const char *opn = "arith";
1537 if (rd == 0 && opc != OPC_ADD && opc != OPC_SUB
1538 && opc != OPC_DADD && opc != OPC_DSUB) {
1539 /* If no destination, treat it as a NOP.
1540 For add & sub, we must generate the overflow exception when needed. */
1541 MIPS_DEBUG("NOP");
1542 return;
1544 gen_load_gpr(cpu_T[0], rs);
1545 /* Specialcase the conventional move operation. */
1546 if (rt == 0 && (opc == OPC_ADDU || opc == OPC_DADDU
1547 || opc == OPC_SUBU || opc == OPC_DSUBU)) {
1548 gen_store_gpr(cpu_T[0], rd);
1549 return;
1551 gen_load_gpr(cpu_T[1], rt);
1552 switch (opc) {
1553 case OPC_ADD:
1555 TCGv r_tmp1 = tcg_temp_local_new(TCG_TYPE_TL);
1556 TCGv r_tmp2 = tcg_temp_new(TCG_TYPE_TL);
1557 int l1 = gen_new_label();
1559 save_cpu_state(ctx, 1);
1560 tcg_gen_ext32s_tl(r_tmp1, cpu_T[0]);
1561 tcg_gen_ext32s_tl(r_tmp2, cpu_T[1]);
1562 tcg_gen_add_tl(cpu_T[0], r_tmp1, r_tmp2);
1564 tcg_gen_xor_tl(r_tmp1, r_tmp1, cpu_T[1]);
1565 tcg_gen_xori_tl(r_tmp1, r_tmp1, -1);
1566 tcg_gen_xor_tl(r_tmp2, cpu_T[0], cpu_T[1]);
1567 tcg_gen_and_tl(r_tmp1, r_tmp1, r_tmp2);
1568 tcg_temp_free(r_tmp2);
1569 tcg_gen_shri_tl(r_tmp1, r_tmp1, 31);
1570 tcg_gen_brcondi_tl(TCG_COND_EQ, r_tmp1, 0, l1);
1571 tcg_temp_free(r_tmp1);
1572 /* operands of same sign, result different sign */
1573 generate_exception(ctx, EXCP_OVERFLOW);
1574 gen_set_label(l1);
1576 tcg_gen_ext32s_tl(cpu_T[0], cpu_T[0]);
1578 opn = "add";
1579 break;
1580 case OPC_ADDU:
1581 tcg_gen_ext32s_tl(cpu_T[0], cpu_T[0]);
1582 tcg_gen_ext32s_tl(cpu_T[1], cpu_T[1]);
1583 tcg_gen_add_tl(cpu_T[0], cpu_T[0], cpu_T[1]);
1584 tcg_gen_ext32s_tl(cpu_T[0], cpu_T[0]);
1585 opn = "addu";
1586 break;
1587 case OPC_SUB:
1589 TCGv r_tmp1 = tcg_temp_local_new(TCG_TYPE_TL);
1590 TCGv r_tmp2 = tcg_temp_new(TCG_TYPE_TL);
1591 int l1 = gen_new_label();
1593 save_cpu_state(ctx, 1);
1594 tcg_gen_ext32s_tl(r_tmp1, cpu_T[0]);
1595 tcg_gen_ext32s_tl(r_tmp2, cpu_T[1]);
1596 tcg_gen_sub_tl(cpu_T[0], r_tmp1, r_tmp2);
1598 tcg_gen_xor_tl(r_tmp2, r_tmp1, cpu_T[1]);
1599 tcg_gen_xor_tl(r_tmp1, r_tmp1, cpu_T[0]);
1600 tcg_gen_and_tl(r_tmp1, r_tmp1, r_tmp2);
1601 tcg_temp_free(r_tmp2);
1602 tcg_gen_shri_tl(r_tmp1, r_tmp1, 31);
1603 tcg_gen_brcondi_tl(TCG_COND_EQ, r_tmp1, 0, l1);
1604 tcg_temp_free(r_tmp1);
1605 /* operands of different sign, first operand and result different sign */
1606 generate_exception(ctx, EXCP_OVERFLOW);
1607 gen_set_label(l1);
1609 tcg_gen_ext32s_tl(cpu_T[0], cpu_T[0]);
1611 opn = "sub";
1612 break;
1613 case OPC_SUBU:
1614 tcg_gen_ext32s_tl(cpu_T[0], cpu_T[0]);
1615 tcg_gen_ext32s_tl(cpu_T[1], cpu_T[1]);
1616 tcg_gen_sub_tl(cpu_T[0], cpu_T[0], cpu_T[1]);
1617 tcg_gen_ext32s_tl(cpu_T[0], cpu_T[0]);
1618 opn = "subu";
1619 break;
1620 #if defined(TARGET_MIPS64)
1621 case OPC_DADD:
1623 TCGv r_tmp1 = tcg_temp_local_new(TCG_TYPE_TL);
1624 TCGv r_tmp2 = tcg_temp_new(TCG_TYPE_TL);
1625 int l1 = gen_new_label();
1627 save_cpu_state(ctx, 1);
1628 tcg_gen_mov_tl(r_tmp1, cpu_T[0]);
1629 tcg_gen_add_tl(cpu_T[0], cpu_T[0], cpu_T[1]);
1631 tcg_gen_xor_tl(r_tmp1, r_tmp1, cpu_T[1]);
1632 tcg_gen_xori_tl(r_tmp1, r_tmp1, -1);
1633 tcg_gen_xor_tl(r_tmp2, cpu_T[0], cpu_T[1]);
1634 tcg_gen_and_tl(r_tmp1, r_tmp1, r_tmp2);
1635 tcg_temp_free(r_tmp2);
1636 tcg_gen_shri_tl(r_tmp1, r_tmp1, 63);
1637 tcg_gen_brcondi_tl(TCG_COND_EQ, r_tmp1, 0, l1);
1638 tcg_temp_free(r_tmp1);
1639 /* operands of same sign, result different sign */
1640 generate_exception(ctx, EXCP_OVERFLOW);
1641 gen_set_label(l1);
1643 opn = "dadd";
1644 break;
1645 case OPC_DADDU:
1646 tcg_gen_add_tl(cpu_T[0], cpu_T[0], cpu_T[1]);
1647 opn = "daddu";
1648 break;
1649 case OPC_DSUB:
1651 TCGv r_tmp1 = tcg_temp_local_new(TCG_TYPE_TL);
1652 TCGv r_tmp2 = tcg_temp_new(TCG_TYPE_TL);
1653 int l1 = gen_new_label();
1655 save_cpu_state(ctx, 1);
1656 tcg_gen_mov_tl(r_tmp1, cpu_T[0]);
1657 tcg_gen_sub_tl(cpu_T[0], cpu_T[0], cpu_T[1]);
1659 tcg_gen_xor_tl(r_tmp2, r_tmp1, cpu_T[1]);
1660 tcg_gen_xor_tl(r_tmp1, r_tmp1, cpu_T[0]);
1661 tcg_gen_and_tl(r_tmp1, r_tmp1, r_tmp2);
1662 tcg_temp_free(r_tmp2);
1663 tcg_gen_shri_tl(r_tmp1, r_tmp1, 63);
1664 tcg_gen_brcondi_tl(TCG_COND_EQ, r_tmp1, 0, l1);
1665 tcg_temp_free(r_tmp1);
1666 /* operands of different sign, first operand and result different sign */
1667 generate_exception(ctx, EXCP_OVERFLOW);
1668 gen_set_label(l1);
1670 opn = "dsub";
1671 break;
1672 case OPC_DSUBU:
1673 tcg_gen_sub_tl(cpu_T[0], cpu_T[0], cpu_T[1]);
1674 opn = "dsubu";
1675 break;
1676 #endif
1677 case OPC_SLT:
1678 gen_op_lt();
1679 opn = "slt";
1680 break;
1681 case OPC_SLTU:
1682 gen_op_ltu();
1683 opn = "sltu";
1684 break;
1685 case OPC_AND:
1686 tcg_gen_and_tl(cpu_T[0], cpu_T[0], cpu_T[1]);
1687 opn = "and";
1688 break;
1689 case OPC_NOR:
1690 tcg_gen_or_tl(cpu_T[0], cpu_T[0], cpu_T[1]);
1691 tcg_gen_not_tl(cpu_T[0], cpu_T[0]);
1692 opn = "nor";
1693 break;
1694 case OPC_OR:
1695 tcg_gen_or_tl(cpu_T[0], cpu_T[0], cpu_T[1]);
1696 opn = "or";
1697 break;
1698 case OPC_XOR:
1699 tcg_gen_xor_tl(cpu_T[0], cpu_T[0], cpu_T[1]);
1700 opn = "xor";
1701 break;
1702 case OPC_MUL:
1703 tcg_gen_ext32s_tl(cpu_T[0], cpu_T[0]);
1704 tcg_gen_ext32s_tl(cpu_T[1], cpu_T[1]);
1705 tcg_gen_mul_tl(cpu_T[0], cpu_T[0], cpu_T[1]);
1706 tcg_gen_ext32s_tl(cpu_T[0], cpu_T[0]);
1707 opn = "mul";
1708 break;
1709 case OPC_MOVN:
1711 int l1 = gen_new_label();
1713 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_T[1], 0, l1);
1714 gen_store_gpr(cpu_T[0], rd);
1715 gen_set_label(l1);
1717 opn = "movn";
1718 goto print;
1719 case OPC_MOVZ:
1721 int l1 = gen_new_label();
1723 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_T[1], 0, l1);
1724 gen_store_gpr(cpu_T[0], rd);
1725 gen_set_label(l1);
1727 opn = "movz";
1728 goto print;
1729 case OPC_SLLV:
1730 tcg_gen_ext32u_tl(cpu_T[0], cpu_T[0]);
1731 tcg_gen_ext32u_tl(cpu_T[1], cpu_T[1]);
1732 tcg_gen_andi_tl(cpu_T[0], cpu_T[0], 0x1f);
1733 tcg_gen_shl_tl(cpu_T[0], cpu_T[1], cpu_T[0]);
1734 tcg_gen_ext32s_tl(cpu_T[0], cpu_T[0]);
1735 opn = "sllv";
1736 break;
1737 case OPC_SRAV:
1738 tcg_gen_ext32s_tl(cpu_T[1], cpu_T[1]);
1739 tcg_gen_andi_tl(cpu_T[0], cpu_T[0], 0x1f);
1740 tcg_gen_sar_tl(cpu_T[0], cpu_T[1], cpu_T[0]);
1741 tcg_gen_ext32s_tl(cpu_T[0], cpu_T[0]);
1742 opn = "srav";
1743 break;
1744 case OPC_SRLV:
1745 switch ((ctx->opcode >> 6) & 0x1f) {
1746 case 0:
1747 tcg_gen_ext32u_tl(cpu_T[1], cpu_T[1]);
1748 tcg_gen_andi_tl(cpu_T[0], cpu_T[0], 0x1f);
1749 tcg_gen_shr_tl(cpu_T[0], cpu_T[1], cpu_T[0]);
1750 tcg_gen_ext32s_tl(cpu_T[0], cpu_T[0]);
1751 opn = "srlv";
1752 break;
1753 case 1:
1754 /* rotrv is decoded as srlv on non-R2 CPUs */
1755 if (env->insn_flags & ISA_MIPS32R2) {
1756 int l1 = gen_new_label();
1757 int l2 = gen_new_label();
1759 tcg_gen_andi_tl(cpu_T[0], cpu_T[0], 0x1f);
1760 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_T[0], 0, l1);
1762 TCGv r_tmp1 = tcg_temp_new(TCG_TYPE_I32);
1763 TCGv r_tmp2 = tcg_temp_new(TCG_TYPE_I32);
1764 TCGv r_tmp3 = tcg_temp_new(TCG_TYPE_I32);
1766 tcg_gen_trunc_tl_i32(r_tmp1, cpu_T[0]);
1767 tcg_gen_trunc_tl_i32(r_tmp2, cpu_T[1]);
1768 tcg_gen_movi_i32(r_tmp3, 0x20);
1769 tcg_gen_sub_i32(r_tmp3, r_tmp3, r_tmp1);
1770 tcg_gen_shl_i32(r_tmp3, r_tmp2, r_tmp3);
1771 tcg_gen_shr_i32(r_tmp1, r_tmp2, r_tmp1);
1772 tcg_gen_or_i32(r_tmp1, r_tmp1, r_tmp3);
1773 tcg_gen_ext_i32_tl(cpu_T[0], r_tmp1);
1774 tcg_temp_free(r_tmp1);
1775 tcg_temp_free(r_tmp2);
1776 tcg_temp_free(r_tmp3);
1777 tcg_gen_br(l2);
1779 gen_set_label(l1);
1780 tcg_gen_mov_tl(cpu_T[0], cpu_T[1]);
1781 gen_set_label(l2);
1782 opn = "rotrv";
1783 } else {
1784 tcg_gen_ext32u_tl(cpu_T[1], cpu_T[1]);
1785 tcg_gen_andi_tl(cpu_T[0], cpu_T[0], 0x1f);
1786 tcg_gen_shr_tl(cpu_T[0], cpu_T[1], cpu_T[0]);
1787 tcg_gen_ext32s_tl(cpu_T[0], cpu_T[0]);
1788 opn = "srlv";
1790 break;
1791 default:
1792 MIPS_INVAL("invalid srlv flag");
1793 generate_exception(ctx, EXCP_RI);
1794 break;
1796 break;
1797 #if defined(TARGET_MIPS64)
1798 case OPC_DSLLV:
1799 tcg_gen_andi_tl(cpu_T[0], cpu_T[0], 0x3f);
1800 tcg_gen_shl_tl(cpu_T[0], cpu_T[1], cpu_T[0]);
1801 opn = "dsllv";
1802 break;
1803 case OPC_DSRAV:
1804 tcg_gen_andi_tl(cpu_T[0], cpu_T[0], 0x3f);
1805 tcg_gen_sar_tl(cpu_T[0], cpu_T[1], cpu_T[0]);
1806 opn = "dsrav";
1807 break;
1808 case OPC_DSRLV:
1809 switch ((ctx->opcode >> 6) & 0x1f) {
1810 case 0:
1811 tcg_gen_andi_tl(cpu_T[0], cpu_T[0], 0x3f);
1812 tcg_gen_shr_tl(cpu_T[0], cpu_T[1], cpu_T[0]);
1813 opn = "dsrlv";
1814 break;
1815 case 1:
1816 /* drotrv is decoded as dsrlv on non-R2 CPUs */
1817 if (env->insn_flags & ISA_MIPS32R2) {
1818 int l1 = gen_new_label();
1819 int l2 = gen_new_label();
1821 tcg_gen_andi_tl(cpu_T[0], cpu_T[0], 0x3f);
1822 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_T[0], 0, l1);
1824 TCGv r_tmp1 = tcg_temp_new(TCG_TYPE_TL);
1826 tcg_gen_movi_tl(r_tmp1, 0x40);
1827 tcg_gen_sub_tl(r_tmp1, r_tmp1, cpu_T[0]);
1828 tcg_gen_shl_tl(r_tmp1, cpu_T[1], r_tmp1);
1829 tcg_gen_shr_tl(cpu_T[0], cpu_T[1], cpu_T[0]);
1830 tcg_gen_or_tl(cpu_T[0], cpu_T[0], r_tmp1);
1831 tcg_temp_free(r_tmp1);
1832 tcg_gen_br(l2);
1834 gen_set_label(l1);
1835 tcg_gen_mov_tl(cpu_T[0], cpu_T[1]);
1836 gen_set_label(l2);
1837 opn = "drotrv";
1838 } else {
1839 tcg_gen_andi_tl(cpu_T[0], cpu_T[0], 0x3f);
1840 tcg_gen_shr_tl(cpu_T[0], cpu_T[1], cpu_T[0]);
1841 opn = "dsrlv";
1843 break;
1844 default:
1845 MIPS_INVAL("invalid dsrlv flag");
1846 generate_exception(ctx, EXCP_RI);
1847 break;
1849 break;
1850 #endif
1851 default:
1852 MIPS_INVAL(opn);
1853 generate_exception(ctx, EXCP_RI);
1854 return;
1856 gen_store_gpr(cpu_T[0], rd);
1857 print:
1858 MIPS_DEBUG("%s %s, %s, %s", opn, regnames[rd], regnames[rs], regnames[rt]);
1861 /* Arithmetic on HI/LO registers */
1862 static void gen_HILO (DisasContext *ctx, uint32_t opc, int reg)
1864 const char *opn = "hilo";
1866 if (reg == 0 && (opc == OPC_MFHI || opc == OPC_MFLO)) {
1867 /* Treat as NOP. */
1868 MIPS_DEBUG("NOP");
1869 return;
1871 switch (opc) {
1872 case OPC_MFHI:
1873 gen_load_HI(cpu_T[0], 0);
1874 gen_store_gpr(cpu_T[0], reg);
1875 opn = "mfhi";
1876 break;
1877 case OPC_MFLO:
1878 gen_load_LO(cpu_T[0], 0);
1879 gen_store_gpr(cpu_T[0], reg);
1880 opn = "mflo";
1881 break;
1882 case OPC_MTHI:
1883 gen_load_gpr(cpu_T[0], reg);
1884 gen_store_HI(cpu_T[0], 0);
1885 opn = "mthi";
1886 break;
1887 case OPC_MTLO:
1888 gen_load_gpr(cpu_T[0], reg);
1889 gen_store_LO(cpu_T[0], 0);
1890 opn = "mtlo";
1891 break;
1892 default:
1893 MIPS_INVAL(opn);
1894 generate_exception(ctx, EXCP_RI);
1895 return;
1897 MIPS_DEBUG("%s %s", opn, regnames[reg]);
1900 static void gen_muldiv (DisasContext *ctx, uint32_t opc,
1901 int rs, int rt)
1903 const char *opn = "mul/div";
1905 gen_load_gpr(cpu_T[0], rs);
1906 gen_load_gpr(cpu_T[1], rt);
1907 switch (opc) {
1908 case OPC_DIV:
1910 int l1 = gen_new_label();
1912 tcg_gen_ext32s_tl(cpu_T[0], cpu_T[0]);
1913 tcg_gen_ext32s_tl(cpu_T[1], cpu_T[1]);
1914 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_T[1], 0, l1);
1916 TCGv r_tmp1 = tcg_temp_new(TCG_TYPE_I64);
1917 TCGv r_tmp2 = tcg_temp_new(TCG_TYPE_I64);
1918 TCGv r_tmp3 = tcg_temp_new(TCG_TYPE_I64);
1920 tcg_gen_ext_tl_i64(r_tmp1, cpu_T[0]);
1921 tcg_gen_ext_tl_i64(r_tmp2, cpu_T[1]);
1922 tcg_gen_div_i64(r_tmp3, r_tmp1, r_tmp2);
1923 tcg_gen_rem_i64(r_tmp2, r_tmp1, r_tmp2);
1924 tcg_gen_trunc_i64_tl(cpu_T[0], r_tmp3);
1925 tcg_gen_trunc_i64_tl(cpu_T[1], r_tmp2);
1926 tcg_temp_free(r_tmp1);
1927 tcg_temp_free(r_tmp2);
1928 tcg_temp_free(r_tmp3);
1929 tcg_gen_ext32s_tl(cpu_T[0], cpu_T[0]);
1930 tcg_gen_ext32s_tl(cpu_T[1], cpu_T[1]);
1931 gen_store_LO(cpu_T[0], 0);
1932 gen_store_HI(cpu_T[1], 0);
1934 gen_set_label(l1);
1936 opn = "div";
1937 break;
1938 case OPC_DIVU:
1940 int l1 = gen_new_label();
1942 tcg_gen_ext32s_tl(cpu_T[1], cpu_T[1]);
1943 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_T[1], 0, l1);
1945 TCGv r_tmp1 = tcg_temp_new(TCG_TYPE_I32);
1946 TCGv r_tmp2 = tcg_temp_new(TCG_TYPE_I32);
1947 TCGv r_tmp3 = tcg_temp_new(TCG_TYPE_I32);
1949 tcg_gen_trunc_tl_i32(r_tmp1, cpu_T[0]);
1950 tcg_gen_trunc_tl_i32(r_tmp2, cpu_T[1]);
1951 tcg_gen_divu_i32(r_tmp3, r_tmp1, r_tmp2);
1952 tcg_gen_remu_i32(r_tmp1, r_tmp1, r_tmp2);
1953 tcg_gen_ext_i32_tl(cpu_T[0], r_tmp3);
1954 tcg_gen_ext_i32_tl(cpu_T[1], r_tmp1);
1955 tcg_temp_free(r_tmp1);
1956 tcg_temp_free(r_tmp2);
1957 tcg_temp_free(r_tmp3);
1958 gen_store_LO(cpu_T[0], 0);
1959 gen_store_HI(cpu_T[1], 0);
1961 gen_set_label(l1);
1963 opn = "divu";
1964 break;
1965 case OPC_MULT:
1966 gen_op_mult();
1967 opn = "mult";
1968 break;
1969 case OPC_MULTU:
1970 gen_op_multu();
1971 opn = "multu";
1972 break;
1973 #if defined(TARGET_MIPS64)
1974 case OPC_DDIV:
1976 int l1 = gen_new_label();
1978 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_T[1], 0, l1);
1980 int l2 = gen_new_label();
1982 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_T[0], -1LL << 63, l2);
1983 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_T[1], -1LL, l2);
1985 tcg_gen_movi_tl(cpu_T[1], 0);
1986 gen_store_LO(cpu_T[0], 0);
1987 gen_store_HI(cpu_T[1], 0);
1988 tcg_gen_br(l1);
1990 gen_set_label(l2);
1992 TCGv r_tmp1 = tcg_temp_new(TCG_TYPE_I64);
1993 TCGv r_tmp2 = tcg_temp_new(TCG_TYPE_I64);
1995 tcg_gen_div_i64(r_tmp1, cpu_T[0], cpu_T[1]);
1996 tcg_gen_rem_i64(r_tmp2, cpu_T[0], cpu_T[1]);
1997 gen_store_LO(r_tmp1, 0);
1998 gen_store_HI(r_tmp2, 0);
1999 tcg_temp_free(r_tmp1);
2000 tcg_temp_free(r_tmp2);
2003 gen_set_label(l1);
2005 opn = "ddiv";
2006 break;
2007 case OPC_DDIVU:
2009 int l1 = gen_new_label();
2011 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_T[1], 0, l1);
2013 TCGv r_tmp1 = tcg_temp_new(TCG_TYPE_I64);
2014 TCGv r_tmp2 = tcg_temp_new(TCG_TYPE_I64);
2016 tcg_gen_divu_i64(r_tmp1, cpu_T[0], cpu_T[1]);
2017 tcg_gen_remu_i64(r_tmp2, cpu_T[0], cpu_T[1]);
2018 tcg_temp_free(r_tmp1);
2019 tcg_temp_free(r_tmp2);
2020 gen_store_LO(r_tmp1, 0);
2021 gen_store_HI(r_tmp2, 0);
2023 gen_set_label(l1);
2025 opn = "ddivu";
2026 break;
2027 case OPC_DMULT:
2028 gen_op_dmult();
2029 opn = "dmult";
2030 break;
2031 case OPC_DMULTU:
2032 gen_op_dmultu();
2033 opn = "dmultu";
2034 break;
2035 #endif
2036 case OPC_MADD:
2037 gen_op_madd();
2038 opn = "madd";
2039 break;
2040 case OPC_MADDU:
2041 gen_op_maddu();
2042 opn = "maddu";
2043 break;
2044 case OPC_MSUB:
2045 gen_op_msub();
2046 opn = "msub";
2047 break;
2048 case OPC_MSUBU:
2049 gen_op_msubu();
2050 opn = "msubu";
2051 break;
2052 default:
2053 MIPS_INVAL(opn);
2054 generate_exception(ctx, EXCP_RI);
2055 return;
2057 MIPS_DEBUG("%s %s %s", opn, regnames[rs], regnames[rt]);
2060 static void gen_mul_vr54xx (DisasContext *ctx, uint32_t opc,
2061 int rd, int rs, int rt)
2063 const char *opn = "mul vr54xx";
2065 gen_load_gpr(cpu_T[0], rs);
2066 gen_load_gpr(cpu_T[1], rt);
2068 switch (opc) {
2069 case OPC_VR54XX_MULS:
2070 gen_op_muls();
2071 opn = "muls";
2072 break;
2073 case OPC_VR54XX_MULSU:
2074 gen_op_mulsu();
2075 opn = "mulsu";
2076 break;
2077 case OPC_VR54XX_MACC:
2078 gen_op_macc();
2079 opn = "macc";
2080 break;
2081 case OPC_VR54XX_MACCU:
2082 gen_op_maccu();
2083 opn = "maccu";
2084 break;
2085 case OPC_VR54XX_MSAC:
2086 gen_op_msac();
2087 opn = "msac";
2088 break;
2089 case OPC_VR54XX_MSACU:
2090 gen_op_msacu();
2091 opn = "msacu";
2092 break;
2093 case OPC_VR54XX_MULHI:
2094 gen_op_mulhi();
2095 opn = "mulhi";
2096 break;
2097 case OPC_VR54XX_MULHIU:
2098 gen_op_mulhiu();
2099 opn = "mulhiu";
2100 break;
2101 case OPC_VR54XX_MULSHI:
2102 gen_op_mulshi();
2103 opn = "mulshi";
2104 break;
2105 case OPC_VR54XX_MULSHIU:
2106 gen_op_mulshiu();
2107 opn = "mulshiu";
2108 break;
2109 case OPC_VR54XX_MACCHI:
2110 gen_op_macchi();
2111 opn = "macchi";
2112 break;
2113 case OPC_VR54XX_MACCHIU:
2114 gen_op_macchiu();
2115 opn = "macchiu";
2116 break;
2117 case OPC_VR54XX_MSACHI:
2118 gen_op_msachi();
2119 opn = "msachi";
2120 break;
2121 case OPC_VR54XX_MSACHIU:
2122 gen_op_msachiu();
2123 opn = "msachiu";
2124 break;
2125 default:
2126 MIPS_INVAL("mul vr54xx");
2127 generate_exception(ctx, EXCP_RI);
2128 return;
2130 gen_store_gpr(cpu_T[0], rd);
2131 MIPS_DEBUG("%s %s, %s, %s", opn, regnames[rd], regnames[rs], regnames[rt]);
2134 static void gen_cl (DisasContext *ctx, uint32_t opc,
2135 int rd, int rs)
2137 const char *opn = "CLx";
2138 if (rd == 0) {
2139 /* Treat as NOP. */
2140 MIPS_DEBUG("NOP");
2141 return;
2143 gen_load_gpr(cpu_T[0], rs);
2144 switch (opc) {
2145 case OPC_CLO:
2146 tcg_gen_helper_0_0(do_clo);
2147 opn = "clo";
2148 break;
2149 case OPC_CLZ:
2150 tcg_gen_helper_0_0(do_clz);
2151 opn = "clz";
2152 break;
2153 #if defined(TARGET_MIPS64)
2154 case OPC_DCLO:
2155 tcg_gen_helper_0_0(do_dclo);
2156 opn = "dclo";
2157 break;
2158 case OPC_DCLZ:
2159 tcg_gen_helper_0_0(do_dclz);
2160 opn = "dclz";
2161 break;
2162 #endif
2163 default:
2164 MIPS_INVAL(opn);
2165 generate_exception(ctx, EXCP_RI);
2166 return;
2168 gen_store_gpr(cpu_T[0], rd);
2169 MIPS_DEBUG("%s %s, %s", opn, regnames[rd], regnames[rs]);
2172 /* Traps */
2173 static void gen_trap (DisasContext *ctx, uint32_t opc,
2174 int rs, int rt, int16_t imm)
2176 int cond;
2178 cond = 0;
2179 /* Load needed operands */
2180 switch (opc) {
2181 case OPC_TEQ:
2182 case OPC_TGE:
2183 case OPC_TGEU:
2184 case OPC_TLT:
2185 case OPC_TLTU:
2186 case OPC_TNE:
2187 /* Compare two registers */
2188 if (rs != rt) {
2189 gen_load_gpr(cpu_T[0], rs);
2190 gen_load_gpr(cpu_T[1], rt);
2191 cond = 1;
2193 break;
2194 case OPC_TEQI:
2195 case OPC_TGEI:
2196 case OPC_TGEIU:
2197 case OPC_TLTI:
2198 case OPC_TLTIU:
2199 case OPC_TNEI:
2200 /* Compare register to immediate */
2201 if (rs != 0 || imm != 0) {
2202 gen_load_gpr(cpu_T[0], rs);
2203 tcg_gen_movi_tl(cpu_T[1], (int32_t)imm);
2204 cond = 1;
2206 break;
2208 if (cond == 0) {
2209 switch (opc) {
2210 case OPC_TEQ: /* rs == rs */
2211 case OPC_TEQI: /* r0 == 0 */
2212 case OPC_TGE: /* rs >= rs */
2213 case OPC_TGEI: /* r0 >= 0 */
2214 case OPC_TGEU: /* rs >= rs unsigned */
2215 case OPC_TGEIU: /* r0 >= 0 unsigned */
2216 /* Always trap */
2217 tcg_gen_movi_tl(cpu_T[0], 1);
2218 break;
2219 case OPC_TLT: /* rs < rs */
2220 case OPC_TLTI: /* r0 < 0 */
2221 case OPC_TLTU: /* rs < rs unsigned */
2222 case OPC_TLTIU: /* r0 < 0 unsigned */
2223 case OPC_TNE: /* rs != rs */
2224 case OPC_TNEI: /* r0 != 0 */
2225 /* Never trap: treat as NOP. */
2226 return;
2227 default:
2228 MIPS_INVAL("trap");
2229 generate_exception(ctx, EXCP_RI);
2230 return;
2232 } else {
2233 switch (opc) {
2234 case OPC_TEQ:
2235 case OPC_TEQI:
2236 gen_op_eq();
2237 break;
2238 case OPC_TGE:
2239 case OPC_TGEI:
2240 gen_op_ge();
2241 break;
2242 case OPC_TGEU:
2243 case OPC_TGEIU:
2244 gen_op_geu();
2245 break;
2246 case OPC_TLT:
2247 case OPC_TLTI:
2248 gen_op_lt();
2249 break;
2250 case OPC_TLTU:
2251 case OPC_TLTIU:
2252 gen_op_ltu();
2253 break;
2254 case OPC_TNE:
2255 case OPC_TNEI:
2256 gen_op_ne();
2257 break;
2258 default:
2259 MIPS_INVAL("trap");
2260 generate_exception(ctx, EXCP_RI);
2261 return;
2264 save_cpu_state(ctx, 1);
2265 gen_op_trap();
2266 ctx->bstate = BS_STOP;
2269 static always_inline void gen_goto_tb(DisasContext *ctx, int n, target_ulong dest)
2271 TranslationBlock *tb;
2272 tb = ctx->tb;
2273 if ((tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK)) {
2274 tcg_gen_goto_tb(n);
2275 gen_save_pc(dest);
2276 tcg_gen_exit_tb((long)tb + n);
2277 } else {
2278 gen_save_pc(dest);
2279 tcg_gen_exit_tb(0);
2283 /* Branches (before delay slot) */
2284 static void gen_compute_branch (DisasContext *ctx, uint32_t opc,
2285 int rs, int rt, int32_t offset)
2287 target_ulong btarget = -1;
2288 int blink = 0;
2289 int bcond = 0;
2291 if (ctx->hflags & MIPS_HFLAG_BMASK) {
2292 #ifdef MIPS_DEBUG_DISAS
2293 if (loglevel & CPU_LOG_TB_IN_ASM) {
2294 fprintf(logfile,
2295 "Branch in delay slot at PC 0x" TARGET_FMT_lx "\n",
2296 ctx->pc);
2298 #endif
2299 generate_exception(ctx, EXCP_RI);
2300 return;
2303 /* Load needed operands */
2304 switch (opc) {
2305 case OPC_BEQ:
2306 case OPC_BEQL:
2307 case OPC_BNE:
2308 case OPC_BNEL:
2309 /* Compare two registers */
2310 if (rs != rt) {
2311 gen_load_gpr(cpu_T[0], rs);
2312 gen_load_gpr(cpu_T[1], rt);
2313 bcond = 1;
2315 btarget = ctx->pc + 4 + offset;
2316 break;
2317 case OPC_BGEZ:
2318 case OPC_BGEZAL:
2319 case OPC_BGEZALL:
2320 case OPC_BGEZL:
2321 case OPC_BGTZ:
2322 case OPC_BGTZL:
2323 case OPC_BLEZ:
2324 case OPC_BLEZL:
2325 case OPC_BLTZ:
2326 case OPC_BLTZAL:
2327 case OPC_BLTZALL:
2328 case OPC_BLTZL:
2329 /* Compare to zero */
2330 if (rs != 0) {
2331 gen_load_gpr(cpu_T[0], rs);
2332 bcond = 1;
2334 btarget = ctx->pc + 4 + offset;
2335 break;
2336 case OPC_J:
2337 case OPC_JAL:
2338 /* Jump to immediate */
2339 btarget = ((ctx->pc + 4) & (int32_t)0xF0000000) | (uint32_t)offset;
2340 break;
2341 case OPC_JR:
2342 case OPC_JALR:
2343 /* Jump to register */
2344 if (offset != 0 && offset != 16) {
2345 /* Hint = 0 is JR/JALR, hint 16 is JR.HB/JALR.HB, the
2346 others are reserved. */
2347 MIPS_INVAL("jump hint");
2348 generate_exception(ctx, EXCP_RI);
2349 return;
2351 gen_save_breg_target(rs);
2352 break;
2353 default:
2354 MIPS_INVAL("branch/jump");
2355 generate_exception(ctx, EXCP_RI);
2356 return;
2358 if (bcond == 0) {
2359 /* No condition to be computed */
2360 switch (opc) {
2361 case OPC_BEQ: /* rx == rx */
2362 case OPC_BEQL: /* rx == rx likely */
2363 case OPC_BGEZ: /* 0 >= 0 */
2364 case OPC_BGEZL: /* 0 >= 0 likely */
2365 case OPC_BLEZ: /* 0 <= 0 */
2366 case OPC_BLEZL: /* 0 <= 0 likely */
2367 /* Always take */
2368 ctx->hflags |= MIPS_HFLAG_B;
2369 MIPS_DEBUG("balways");
2370 break;
2371 case OPC_BGEZAL: /* 0 >= 0 */
2372 case OPC_BGEZALL: /* 0 >= 0 likely */
2373 /* Always take and link */
2374 blink = 31;
2375 ctx->hflags |= MIPS_HFLAG_B;
2376 MIPS_DEBUG("balways and link");
2377 break;
2378 case OPC_BNE: /* rx != rx */
2379 case OPC_BGTZ: /* 0 > 0 */
2380 case OPC_BLTZ: /* 0 < 0 */
2381 /* Treat as NOP. */
2382 MIPS_DEBUG("bnever (NOP)");
2383 return;
2384 case OPC_BLTZAL: /* 0 < 0 */
2385 tcg_gen_movi_tl(cpu_T[0], ctx->pc + 8);
2386 gen_store_gpr(cpu_T[0], 31);
2387 MIPS_DEBUG("bnever and link");
2388 return;
2389 case OPC_BLTZALL: /* 0 < 0 likely */
2390 tcg_gen_movi_tl(cpu_T[0], ctx->pc + 8);
2391 gen_store_gpr(cpu_T[0], 31);
2392 /* Skip the instruction in the delay slot */
2393 MIPS_DEBUG("bnever, link and skip");
2394 ctx->pc += 4;
2395 return;
2396 case OPC_BNEL: /* rx != rx likely */
2397 case OPC_BGTZL: /* 0 > 0 likely */
2398 case OPC_BLTZL: /* 0 < 0 likely */
2399 /* Skip the instruction in the delay slot */
2400 MIPS_DEBUG("bnever and skip");
2401 ctx->pc += 4;
2402 return;
2403 case OPC_J:
2404 ctx->hflags |= MIPS_HFLAG_B;
2405 MIPS_DEBUG("j " TARGET_FMT_lx, btarget);
2406 break;
2407 case OPC_JAL:
2408 blink = 31;
2409 ctx->hflags |= MIPS_HFLAG_B;
2410 MIPS_DEBUG("jal " TARGET_FMT_lx, btarget);
2411 break;
2412 case OPC_JR:
2413 ctx->hflags |= MIPS_HFLAG_BR;
2414 MIPS_DEBUG("jr %s", regnames[rs]);
2415 break;
2416 case OPC_JALR:
2417 blink = rt;
2418 ctx->hflags |= MIPS_HFLAG_BR;
2419 MIPS_DEBUG("jalr %s, %s", regnames[rt], regnames[rs]);
2420 break;
2421 default:
2422 MIPS_INVAL("branch/jump");
2423 generate_exception(ctx, EXCP_RI);
2424 return;
2426 } else {
2427 switch (opc) {
2428 case OPC_BEQ:
2429 gen_op_eq();
2430 MIPS_DEBUG("beq %s, %s, " TARGET_FMT_lx,
2431 regnames[rs], regnames[rt], btarget);
2432 goto not_likely;
2433 case OPC_BEQL:
2434 gen_op_eq();
2435 MIPS_DEBUG("beql %s, %s, " TARGET_FMT_lx,
2436 regnames[rs], regnames[rt], btarget);
2437 goto likely;
2438 case OPC_BNE:
2439 gen_op_ne();
2440 MIPS_DEBUG("bne %s, %s, " TARGET_FMT_lx,
2441 regnames[rs], regnames[rt], btarget);
2442 goto not_likely;
2443 case OPC_BNEL:
2444 gen_op_ne();
2445 MIPS_DEBUG("bnel %s, %s, " TARGET_FMT_lx,
2446 regnames[rs], regnames[rt], btarget);
2447 goto likely;
2448 case OPC_BGEZ:
2449 gen_op_gez();
2450 MIPS_DEBUG("bgez %s, " TARGET_FMT_lx, regnames[rs], btarget);
2451 goto not_likely;
2452 case OPC_BGEZL:
2453 gen_op_gez();
2454 MIPS_DEBUG("bgezl %s, " TARGET_FMT_lx, regnames[rs], btarget);
2455 goto likely;
2456 case OPC_BGEZAL:
2457 gen_op_gez();
2458 MIPS_DEBUG("bgezal %s, " TARGET_FMT_lx, regnames[rs], btarget);
2459 blink = 31;
2460 goto not_likely;
2461 case OPC_BGEZALL:
2462 gen_op_gez();
2463 blink = 31;
2464 MIPS_DEBUG("bgezall %s, " TARGET_FMT_lx, regnames[rs], btarget);
2465 goto likely;
2466 case OPC_BGTZ:
2467 gen_op_gtz();
2468 MIPS_DEBUG("bgtz %s, " TARGET_FMT_lx, regnames[rs], btarget);
2469 goto not_likely;
2470 case OPC_BGTZL:
2471 gen_op_gtz();
2472 MIPS_DEBUG("bgtzl %s, " TARGET_FMT_lx, regnames[rs], btarget);
2473 goto likely;
2474 case OPC_BLEZ:
2475 gen_op_lez();
2476 MIPS_DEBUG("blez %s, " TARGET_FMT_lx, regnames[rs], btarget);
2477 goto not_likely;
2478 case OPC_BLEZL:
2479 gen_op_lez();
2480 MIPS_DEBUG("blezl %s, " TARGET_FMT_lx, regnames[rs], btarget);
2481 goto likely;
2482 case OPC_BLTZ:
2483 gen_op_ltz();
2484 MIPS_DEBUG("bltz %s, " TARGET_FMT_lx, regnames[rs], btarget);
2485 goto not_likely;
2486 case OPC_BLTZL:
2487 gen_op_ltz();
2488 MIPS_DEBUG("bltzl %s, " TARGET_FMT_lx, regnames[rs], btarget);
2489 goto likely;
2490 case OPC_BLTZAL:
2491 gen_op_ltz();
2492 blink = 31;
2493 MIPS_DEBUG("bltzal %s, " TARGET_FMT_lx, regnames[rs], btarget);
2494 not_likely:
2495 ctx->hflags |= MIPS_HFLAG_BC;
2496 tcg_gen_st_tl(cpu_T[0], cpu_env, offsetof(CPUState, bcond));
2497 break;
2498 case OPC_BLTZALL:
2499 gen_op_ltz();
2500 blink = 31;
2501 MIPS_DEBUG("bltzall %s, " TARGET_FMT_lx, regnames[rs], btarget);
2502 likely:
2503 ctx->hflags |= MIPS_HFLAG_BL;
2504 tcg_gen_st_tl(cpu_T[0], cpu_env, offsetof(CPUState, bcond));
2505 break;
2506 default:
2507 MIPS_INVAL("conditional branch/jump");
2508 generate_exception(ctx, EXCP_RI);
2509 return;
2512 MIPS_DEBUG("enter ds: link %d cond %02x target " TARGET_FMT_lx,
2513 blink, ctx->hflags, btarget);
2515 ctx->btarget = btarget;
2516 if (blink > 0) {
2517 tcg_gen_movi_tl(cpu_T[0], ctx->pc + 8);
2518 gen_store_gpr(cpu_T[0], blink);
2522 /* special3 bitfield operations */
2523 static void gen_bitops (DisasContext *ctx, uint32_t opc, int rt,
2524 int rs, int lsb, int msb)
2526 gen_load_gpr(cpu_T[1], rs);
2527 switch (opc) {
2528 case OPC_EXT:
2529 if (lsb + msb > 31)
2530 goto fail;
2531 gen_op_ext(lsb, msb + 1);
2532 break;
2533 #if defined(TARGET_MIPS64)
2534 case OPC_DEXTM:
2535 if (lsb + msb > 63)
2536 goto fail;
2537 gen_op_dext(lsb, msb + 1 + 32);
2538 break;
2539 case OPC_DEXTU:
2540 if (lsb + msb > 63)
2541 goto fail;
2542 gen_op_dext(lsb + 32, msb + 1);
2543 break;
2544 case OPC_DEXT:
2545 if (lsb + msb > 63)
2546 goto fail;
2547 gen_op_dext(lsb, msb + 1);
2548 break;
2549 #endif
2550 case OPC_INS:
2551 if (lsb > msb)
2552 goto fail;
2553 gen_load_gpr(cpu_T[0], rt);
2554 gen_op_ins(lsb, msb - lsb + 1);
2555 break;
2556 #if defined(TARGET_MIPS64)
2557 case OPC_DINSM:
2558 if (lsb > msb)
2559 goto fail;
2560 gen_load_gpr(cpu_T[0], rt);
2561 gen_op_dins(lsb, msb - lsb + 1 + 32);
2562 break;
2563 case OPC_DINSU:
2564 if (lsb > msb)
2565 goto fail;
2566 gen_load_gpr(cpu_T[0], rt);
2567 gen_op_dins(lsb + 32, msb - lsb + 1);
2568 break;
2569 case OPC_DINS:
2570 if (lsb > msb)
2571 goto fail;
2572 gen_load_gpr(cpu_T[0], rt);
2573 gen_op_dins(lsb, msb - lsb + 1);
2574 break;
2575 #endif
2576 default:
2577 fail:
2578 MIPS_INVAL("bitops");
2579 generate_exception(ctx, EXCP_RI);
2580 return;
2582 gen_store_gpr(cpu_T[0], rt);
2585 /* CP0 (MMU and control) */
2586 static inline void gen_mfc0_load32 (TCGv t, target_ulong off)
2588 TCGv r_tmp = tcg_temp_new(TCG_TYPE_I32);
2590 tcg_gen_ld_i32(r_tmp, cpu_env, off);
2591 tcg_gen_ext_i32_tl(t, r_tmp);
2592 tcg_temp_free(r_tmp);
2595 static inline void gen_mfc0_load64 (TCGv t, target_ulong off)
2597 TCGv r_tmp = tcg_temp_new(TCG_TYPE_I64);
2599 tcg_gen_ld_i64(r_tmp, cpu_env, off);
2600 tcg_gen_trunc_i64_tl(t, r_tmp);
2601 tcg_temp_free(r_tmp);
2604 static void gen_mfc0 (CPUState *env, DisasContext *ctx, int reg, int sel)
2606 const char *rn = "invalid";
2608 if (sel != 0)
2609 check_insn(env, ctx, ISA_MIPS32);
2611 switch (reg) {
2612 case 0:
2613 switch (sel) {
2614 case 0:
2615 gen_mfc0_load32(cpu_T[0], offsetof(CPUState, CP0_Index));
2616 rn = "Index";
2617 break;
2618 case 1:
2619 check_insn(env, ctx, ASE_MT);
2620 gen_op_mfc0_mvpcontrol();
2621 rn = "MVPControl";
2622 break;
2623 case 2:
2624 check_insn(env, ctx, ASE_MT);
2625 gen_op_mfc0_mvpconf0();
2626 rn = "MVPConf0";
2627 break;
2628 case 3:
2629 check_insn(env, ctx, ASE_MT);
2630 gen_op_mfc0_mvpconf1();
2631 rn = "MVPConf1";
2632 break;
2633 default:
2634 goto die;
2636 break;
2637 case 1:
2638 switch (sel) {
2639 case 0:
2640 gen_op_mfc0_random();
2641 rn = "Random";
2642 break;
2643 case 1:
2644 check_insn(env, ctx, ASE_MT);
2645 gen_mfc0_load32(cpu_T[0], offsetof(CPUState, CP0_VPEControl));
2646 rn = "VPEControl";
2647 break;
2648 case 2:
2649 check_insn(env, ctx, ASE_MT);
2650 gen_mfc0_load32(cpu_T[0], offsetof(CPUState, CP0_VPEConf0));
2651 rn = "VPEConf0";
2652 break;
2653 case 3:
2654 check_insn(env, ctx, ASE_MT);
2655 gen_mfc0_load32(cpu_T[0], offsetof(CPUState, CP0_VPEConf1));
2656 rn = "VPEConf1";
2657 break;
2658 case 4:
2659 check_insn(env, ctx, ASE_MT);
2660 gen_mfc0_load64(cpu_T[0], offsetof(CPUState, CP0_YQMask));
2661 rn = "YQMask";
2662 break;
2663 case 5:
2664 check_insn(env, ctx, ASE_MT);
2665 gen_mfc0_load64(cpu_T[0], offsetof(CPUState, CP0_VPESchedule));
2666 rn = "VPESchedule";
2667 break;
2668 case 6:
2669 check_insn(env, ctx, ASE_MT);
2670 gen_mfc0_load64(cpu_T[0], offsetof(CPUState, CP0_VPEScheFBack));
2671 rn = "VPEScheFBack";
2672 break;
2673 case 7:
2674 check_insn(env, ctx, ASE_MT);
2675 gen_mfc0_load32(cpu_T[0], offsetof(CPUState, CP0_VPEOpt));
2676 rn = "VPEOpt";
2677 break;
2678 default:
2679 goto die;
2681 break;
2682 case 2:
2683 switch (sel) {
2684 case 0:
2685 tcg_gen_ld_tl(cpu_T[0], cpu_env, offsetof(CPUState, CP0_EntryLo0));
2686 tcg_gen_ext32s_tl(cpu_T[0], cpu_T[0]);
2687 rn = "EntryLo0";
2688 break;
2689 case 1:
2690 check_insn(env, ctx, ASE_MT);
2691 gen_op_mfc0_tcstatus();
2692 rn = "TCStatus";
2693 break;
2694 case 2:
2695 check_insn(env, ctx, ASE_MT);
2696 gen_op_mfc0_tcbind();
2697 rn = "TCBind";
2698 break;
2699 case 3:
2700 check_insn(env, ctx, ASE_MT);
2701 gen_op_mfc0_tcrestart();
2702 rn = "TCRestart";
2703 break;
2704 case 4:
2705 check_insn(env, ctx, ASE_MT);
2706 gen_op_mfc0_tchalt();
2707 rn = "TCHalt";
2708 break;
2709 case 5:
2710 check_insn(env, ctx, ASE_MT);
2711 gen_op_mfc0_tccontext();
2712 rn = "TCContext";
2713 break;
2714 case 6:
2715 check_insn(env, ctx, ASE_MT);
2716 gen_op_mfc0_tcschedule();
2717 rn = "TCSchedule";
2718 break;
2719 case 7:
2720 check_insn(env, ctx, ASE_MT);
2721 gen_op_mfc0_tcschefback();
2722 rn = "TCScheFBack";
2723 break;
2724 default:
2725 goto die;
2727 break;
2728 case 3:
2729 switch (sel) {
2730 case 0:
2731 tcg_gen_ld_tl(cpu_T[0], cpu_env, offsetof(CPUState, CP0_EntryLo1));
2732 tcg_gen_ext32s_tl(cpu_T[0], cpu_T[0]);
2733 rn = "EntryLo1";
2734 break;
2735 default:
2736 goto die;
2738 break;
2739 case 4:
2740 switch (sel) {
2741 case 0:
2742 tcg_gen_ld_tl(cpu_T[0], cpu_env, offsetof(CPUState, CP0_Context));
2743 tcg_gen_ext32s_tl(cpu_T[0], cpu_T[0]);
2744 rn = "Context";
2745 break;
2746 case 1:
2747 // gen_op_mfc0_contextconfig(); /* SmartMIPS ASE */
2748 rn = "ContextConfig";
2749 // break;
2750 default:
2751 goto die;
2753 break;
2754 case 5:
2755 switch (sel) {
2756 case 0:
2757 gen_mfc0_load32(cpu_T[0], offsetof(CPUState, CP0_PageMask));
2758 rn = "PageMask";
2759 break;
2760 case 1:
2761 check_insn(env, ctx, ISA_MIPS32R2);
2762 gen_mfc0_load32(cpu_T[0], offsetof(CPUState, CP0_PageGrain));
2763 rn = "PageGrain";
2764 break;
2765 default:
2766 goto die;
2768 break;
2769 case 6:
2770 switch (sel) {
2771 case 0:
2772 gen_mfc0_load32(cpu_T[0], offsetof(CPUState, CP0_Wired));
2773 rn = "Wired";
2774 break;
2775 case 1:
2776 check_insn(env, ctx, ISA_MIPS32R2);
2777 gen_mfc0_load32(cpu_T[0], offsetof(CPUState, CP0_SRSConf0));
2778 rn = "SRSConf0";
2779 break;
2780 case 2:
2781 check_insn(env, ctx, ISA_MIPS32R2);
2782 gen_mfc0_load32(cpu_T[0], offsetof(CPUState, CP0_SRSConf1));
2783 rn = "SRSConf1";
2784 break;
2785 case 3:
2786 check_insn(env, ctx, ISA_MIPS32R2);
2787 gen_mfc0_load32(cpu_T[0], offsetof(CPUState, CP0_SRSConf2));
2788 rn = "SRSConf2";
2789 break;
2790 case 4:
2791 check_insn(env, ctx, ISA_MIPS32R2);
2792 gen_mfc0_load32(cpu_T[0], offsetof(CPUState, CP0_SRSConf3));
2793 rn = "SRSConf3";
2794 break;
2795 case 5:
2796 check_insn(env, ctx, ISA_MIPS32R2);
2797 gen_mfc0_load32(cpu_T[0], offsetof(CPUState, CP0_SRSConf4));
2798 rn = "SRSConf4";
2799 break;
2800 default:
2801 goto die;
2803 break;
2804 case 7:
2805 switch (sel) {
2806 case 0:
2807 check_insn(env, ctx, ISA_MIPS32R2);
2808 gen_mfc0_load32(cpu_T[0], offsetof(CPUState, CP0_HWREna));
2809 rn = "HWREna";
2810 break;
2811 default:
2812 goto die;
2814 break;
2815 case 8:
2816 switch (sel) {
2817 case 0:
2818 tcg_gen_ld_tl(cpu_T[0], cpu_env, offsetof(CPUState, CP0_BadVAddr));
2819 tcg_gen_ext32s_tl(cpu_T[0], cpu_T[0]);
2820 rn = "BadVAddr";
2821 break;
2822 default:
2823 goto die;
2825 break;
2826 case 9:
2827 switch (sel) {
2828 case 0:
2829 gen_op_mfc0_count();
2830 rn = "Count";
2831 break;
2832 /* 6,7 are implementation dependent */
2833 default:
2834 goto die;
2836 break;
2837 case 10:
2838 switch (sel) {
2839 case 0:
2840 tcg_gen_ld_tl(cpu_T[0], cpu_env, offsetof(CPUState, CP0_EntryHi));
2841 tcg_gen_ext32s_tl(cpu_T[0], cpu_T[0]);
2842 rn = "EntryHi";
2843 break;
2844 default:
2845 goto die;
2847 break;
2848 case 11:
2849 switch (sel) {
2850 case 0:
2851 gen_mfc0_load32(cpu_T[0], offsetof(CPUState, CP0_Compare));
2852 rn = "Compare";
2853 break;
2854 /* 6,7 are implementation dependent */
2855 default:
2856 goto die;
2858 break;
2859 case 12:
2860 switch (sel) {
2861 case 0:
2862 gen_mfc0_load32(cpu_T[0], offsetof(CPUState, CP0_Status));
2863 rn = "Status";
2864 break;
2865 case 1:
2866 check_insn(env, ctx, ISA_MIPS32R2);
2867 gen_mfc0_load32(cpu_T[0], offsetof(CPUState, CP0_IntCtl));
2868 rn = "IntCtl";
2869 break;
2870 case 2:
2871 check_insn(env, ctx, ISA_MIPS32R2);
2872 gen_mfc0_load32(cpu_T[0], offsetof(CPUState, CP0_SRSCtl));
2873 rn = "SRSCtl";
2874 break;
2875 case 3:
2876 check_insn(env, ctx, ISA_MIPS32R2);
2877 gen_mfc0_load32(cpu_T[0], offsetof(CPUState, CP0_SRSMap));
2878 rn = "SRSMap";
2879 break;
2880 default:
2881 goto die;
2883 break;
2884 case 13:
2885 switch (sel) {
2886 case 0:
2887 gen_mfc0_load32(cpu_T[0], offsetof(CPUState, CP0_Cause));
2888 rn = "Cause";
2889 break;
2890 default:
2891 goto die;
2893 break;
2894 case 14:
2895 switch (sel) {
2896 case 0:
2897 tcg_gen_ld_tl(cpu_T[0], cpu_env, offsetof(CPUState, CP0_EPC));
2898 tcg_gen_ext32s_tl(cpu_T[0], cpu_T[0]);
2899 rn = "EPC";
2900 break;
2901 default:
2902 goto die;
2904 break;
2905 case 15:
2906 switch (sel) {
2907 case 0:
2908 gen_mfc0_load32(cpu_T[0], offsetof(CPUState, CP0_PRid));
2909 rn = "PRid";
2910 break;
2911 case 1:
2912 check_insn(env, ctx, ISA_MIPS32R2);
2913 gen_mfc0_load32(cpu_T[0], offsetof(CPUState, CP0_EBase));
2914 rn = "EBase";
2915 break;
2916 default:
2917 goto die;
2919 break;
2920 case 16:
2921 switch (sel) {
2922 case 0:
2923 gen_mfc0_load32(cpu_T[0], offsetof(CPUState, CP0_Config0));
2924 rn = "Config";
2925 break;
2926 case 1:
2927 gen_mfc0_load32(cpu_T[0], offsetof(CPUState, CP0_Config1));
2928 rn = "Config1";
2929 break;
2930 case 2:
2931 gen_mfc0_load32(cpu_T[0], offsetof(CPUState, CP0_Config2));
2932 rn = "Config2";
2933 break;
2934 case 3:
2935 gen_mfc0_load32(cpu_T[0], offsetof(CPUState, CP0_Config3));
2936 rn = "Config3";
2937 break;
2938 /* 4,5 are reserved */
2939 /* 6,7 are implementation dependent */
2940 case 6:
2941 gen_mfc0_load32(cpu_T[0], offsetof(CPUState, CP0_Config6));
2942 rn = "Config6";
2943 break;
2944 case 7:
2945 gen_mfc0_load32(cpu_T[0], offsetof(CPUState, CP0_Config7));
2946 rn = "Config7";
2947 break;
2948 default:
2949 goto die;
2951 break;
2952 case 17:
2953 switch (sel) {
2954 case 0:
2955 gen_op_mfc0_lladdr();
2956 rn = "LLAddr";
2957 break;
2958 default:
2959 goto die;
2961 break;
2962 case 18:
2963 switch (sel) {
2964 case 0 ... 7:
2965 gen_op_mfc0_watchlo(sel);
2966 rn = "WatchLo";
2967 break;
2968 default:
2969 goto die;
2971 break;
2972 case 19:
2973 switch (sel) {
2974 case 0 ...7:
2975 gen_op_mfc0_watchhi(sel);
2976 rn = "WatchHi";
2977 break;
2978 default:
2979 goto die;
2981 break;
2982 case 20:
2983 switch (sel) {
2984 case 0:
2985 #if defined(TARGET_MIPS64)
2986 check_insn(env, ctx, ISA_MIPS3);
2987 tcg_gen_ld_tl(cpu_T[0], cpu_env, offsetof(CPUState, CP0_XContext));
2988 tcg_gen_ext32s_tl(cpu_T[0], cpu_T[0]);
2989 rn = "XContext";
2990 break;
2991 #endif
2992 default:
2993 goto die;
2995 break;
2996 case 21:
2997 /* Officially reserved, but sel 0 is used for R1x000 framemask */
2998 switch (sel) {
2999 case 0:
3000 gen_mfc0_load32(cpu_T[0], offsetof(CPUState, CP0_Framemask));
3001 rn = "Framemask";
3002 break;
3003 default:
3004 goto die;
3006 break;
3007 case 22:
3008 /* ignored */
3009 rn = "'Diagnostic"; /* implementation dependent */
3010 break;
3011 case 23:
3012 switch (sel) {
3013 case 0:
3014 gen_op_mfc0_debug(); /* EJTAG support */
3015 rn = "Debug";
3016 break;
3017 case 1:
3018 // gen_op_mfc0_tracecontrol(); /* PDtrace support */
3019 rn = "TraceControl";
3020 // break;
3021 case 2:
3022 // gen_op_mfc0_tracecontrol2(); /* PDtrace support */
3023 rn = "TraceControl2";
3024 // break;
3025 case 3:
3026 // gen_op_mfc0_usertracedata(); /* PDtrace support */
3027 rn = "UserTraceData";
3028 // break;
3029 case 4:
3030 // gen_op_mfc0_debug(); /* PDtrace support */
3031 rn = "TraceBPC";
3032 // break;
3033 default:
3034 goto die;
3036 break;
3037 case 24:
3038 switch (sel) {
3039 case 0:
3040 /* EJTAG support */
3041 tcg_gen_ld_tl(cpu_T[0], cpu_env, offsetof(CPUState, CP0_DEPC));
3042 tcg_gen_ext32s_tl(cpu_T[0], cpu_T[0]);
3043 rn = "DEPC";
3044 break;
3045 default:
3046 goto die;
3048 break;
3049 case 25:
3050 switch (sel) {
3051 case 0:
3052 gen_mfc0_load32(cpu_T[0], offsetof(CPUState, CP0_Performance0));
3053 rn = "Performance0";
3054 break;
3055 case 1:
3056 // gen_op_mfc0_performance1();
3057 rn = "Performance1";
3058 // break;
3059 case 2:
3060 // gen_op_mfc0_performance2();
3061 rn = "Performance2";
3062 // break;
3063 case 3:
3064 // gen_op_mfc0_performance3();
3065 rn = "Performance3";
3066 // break;
3067 case 4:
3068 // gen_op_mfc0_performance4();
3069 rn = "Performance4";
3070 // break;
3071 case 5:
3072 // gen_op_mfc0_performance5();
3073 rn = "Performance5";
3074 // break;
3075 case 6:
3076 // gen_op_mfc0_performance6();
3077 rn = "Performance6";
3078 // break;
3079 case 7:
3080 // gen_op_mfc0_performance7();
3081 rn = "Performance7";
3082 // break;
3083 default:
3084 goto die;
3086 break;
3087 case 26:
3088 rn = "ECC";
3089 break;
3090 case 27:
3091 switch (sel) {
3092 /* ignored */
3093 case 0 ... 3:
3094 rn = "CacheErr";
3095 break;
3096 default:
3097 goto die;
3099 break;
3100 case 28:
3101 switch (sel) {
3102 case 0:
3103 case 2:
3104 case 4:
3105 case 6:
3106 gen_mfc0_load32(cpu_T[0], offsetof(CPUState, CP0_TagLo));
3107 rn = "TagLo";
3108 break;
3109 case 1:
3110 case 3:
3111 case 5:
3112 case 7:
3113 gen_mfc0_load32(cpu_T[0], offsetof(CPUState, CP0_DataLo));
3114 rn = "DataLo";
3115 break;
3116 default:
3117 goto die;
3119 break;
3120 case 29:
3121 switch (sel) {
3122 case 0:
3123 case 2:
3124 case 4:
3125 case 6:
3126 gen_mfc0_load32(cpu_T[0], offsetof(CPUState, CP0_TagHi));
3127 rn = "TagHi";
3128 break;
3129 case 1:
3130 case 3:
3131 case 5:
3132 case 7:
3133 gen_mfc0_load32(cpu_T[0], offsetof(CPUState, CP0_DataHi));
3134 rn = "DataHi";
3135 break;
3136 default:
3137 goto die;
3139 break;
3140 case 30:
3141 switch (sel) {
3142 case 0:
3143 tcg_gen_ld_tl(cpu_T[0], cpu_env, offsetof(CPUState, CP0_ErrorEPC));
3144 tcg_gen_ext32s_tl(cpu_T[0], cpu_T[0]);
3145 rn = "ErrorEPC";
3146 break;
3147 default:
3148 goto die;
3150 break;
3151 case 31:
3152 switch (sel) {
3153 case 0:
3154 /* EJTAG support */
3155 gen_mfc0_load32(cpu_T[0], offsetof(CPUState, CP0_DESAVE));
3156 rn = "DESAVE";
3157 break;
3158 default:
3159 goto die;
3161 break;
3162 default:
3163 goto die;
3165 #if defined MIPS_DEBUG_DISAS
3166 if (loglevel & CPU_LOG_TB_IN_ASM) {
3167 fprintf(logfile, "mfc0 %s (reg %d sel %d)\n",
3168 rn, reg, sel);
3170 #endif
3171 return;
3173 die:
3174 #if defined MIPS_DEBUG_DISAS
3175 if (loglevel & CPU_LOG_TB_IN_ASM) {
3176 fprintf(logfile, "mfc0 %s (reg %d sel %d)\n",
3177 rn, reg, sel);
3179 #endif
3180 generate_exception(ctx, EXCP_RI);
3183 static void gen_mtc0 (CPUState *env, DisasContext *ctx, int reg, int sel)
3185 const char *rn = "invalid";
3187 if (sel != 0)
3188 check_insn(env, ctx, ISA_MIPS32);
3190 switch (reg) {
3191 case 0:
3192 switch (sel) {
3193 case 0:
3194 gen_op_mtc0_index();
3195 rn = "Index";
3196 break;
3197 case 1:
3198 check_insn(env, ctx, ASE_MT);
3199 gen_op_mtc0_mvpcontrol();
3200 rn = "MVPControl";
3201 break;
3202 case 2:
3203 check_insn(env, ctx, ASE_MT);
3204 /* ignored */
3205 rn = "MVPConf0";
3206 break;
3207 case 3:
3208 check_insn(env, ctx, ASE_MT);
3209 /* ignored */
3210 rn = "MVPConf1";
3211 break;
3212 default:
3213 goto die;
3215 break;
3216 case 1:
3217 switch (sel) {
3218 case 0:
3219 /* ignored */
3220 rn = "Random";
3221 break;
3222 case 1:
3223 check_insn(env, ctx, ASE_MT);
3224 gen_op_mtc0_vpecontrol();
3225 rn = "VPEControl";
3226 break;
3227 case 2:
3228 check_insn(env, ctx, ASE_MT);
3229 gen_op_mtc0_vpeconf0();
3230 rn = "VPEConf0";
3231 break;
3232 case 3:
3233 check_insn(env, ctx, ASE_MT);
3234 gen_op_mtc0_vpeconf1();
3235 rn = "VPEConf1";
3236 break;
3237 case 4:
3238 check_insn(env, ctx, ASE_MT);
3239 gen_op_mtc0_yqmask();
3240 rn = "YQMask";
3241 break;
3242 case 5:
3243 check_insn(env, ctx, ASE_MT);
3244 gen_op_mtc0_vpeschedule();
3245 rn = "VPESchedule";
3246 break;
3247 case 6:
3248 check_insn(env, ctx, ASE_MT);
3249 gen_op_mtc0_vpeschefback();
3250 rn = "VPEScheFBack";
3251 break;
3252 case 7:
3253 check_insn(env, ctx, ASE_MT);
3254 gen_op_mtc0_vpeopt();
3255 rn = "VPEOpt";
3256 break;
3257 default:
3258 goto die;
3260 break;
3261 case 2:
3262 switch (sel) {
3263 case 0:
3264 gen_op_mtc0_entrylo0();
3265 rn = "EntryLo0";
3266 break;
3267 case 1:
3268 check_insn(env, ctx, ASE_MT);
3269 gen_op_mtc0_tcstatus();
3270 rn = "TCStatus";
3271 break;
3272 case 2:
3273 check_insn(env, ctx, ASE_MT);
3274 gen_op_mtc0_tcbind();
3275 rn = "TCBind";
3276 break;
3277 case 3:
3278 check_insn(env, ctx, ASE_MT);
3279 gen_op_mtc0_tcrestart();
3280 rn = "TCRestart";
3281 break;
3282 case 4:
3283 check_insn(env, ctx, ASE_MT);
3284 gen_op_mtc0_tchalt();
3285 rn = "TCHalt";
3286 break;
3287 case 5:
3288 check_insn(env, ctx, ASE_MT);
3289 gen_op_mtc0_tccontext();
3290 rn = "TCContext";
3291 break;
3292 case 6:
3293 check_insn(env, ctx, ASE_MT);
3294 gen_op_mtc0_tcschedule();
3295 rn = "TCSchedule";
3296 break;
3297 case 7:
3298 check_insn(env, ctx, ASE_MT);
3299 gen_op_mtc0_tcschefback();
3300 rn = "TCScheFBack";
3301 break;
3302 default:
3303 goto die;
3305 break;
3306 case 3:
3307 switch (sel) {
3308 case 0:
3309 gen_op_mtc0_entrylo1();
3310 rn = "EntryLo1";
3311 break;
3312 default:
3313 goto die;
3315 break;
3316 case 4:
3317 switch (sel) {
3318 case 0:
3319 gen_op_mtc0_context();
3320 rn = "Context";
3321 break;
3322 case 1:
3323 // gen_op_mtc0_contextconfig(); /* SmartMIPS ASE */
3324 rn = "ContextConfig";
3325 // break;
3326 default:
3327 goto die;
3329 break;
3330 case 5:
3331 switch (sel) {
3332 case 0:
3333 gen_op_mtc0_pagemask();
3334 rn = "PageMask";
3335 break;
3336 case 1:
3337 check_insn(env, ctx, ISA_MIPS32R2);
3338 gen_op_mtc0_pagegrain();
3339 rn = "PageGrain";
3340 break;
3341 default:
3342 goto die;
3344 break;
3345 case 6:
3346 switch (sel) {
3347 case 0:
3348 gen_op_mtc0_wired();
3349 rn = "Wired";
3350 break;
3351 case 1:
3352 check_insn(env, ctx, ISA_MIPS32R2);
3353 gen_op_mtc0_srsconf0();
3354 rn = "SRSConf0";
3355 break;
3356 case 2:
3357 check_insn(env, ctx, ISA_MIPS32R2);
3358 gen_op_mtc0_srsconf1();
3359 rn = "SRSConf1";
3360 break;
3361 case 3:
3362 check_insn(env, ctx, ISA_MIPS32R2);
3363 gen_op_mtc0_srsconf2();
3364 rn = "SRSConf2";
3365 break;
3366 case 4:
3367 check_insn(env, ctx, ISA_MIPS32R2);
3368 gen_op_mtc0_srsconf3();
3369 rn = "SRSConf3";
3370 break;
3371 case 5:
3372 check_insn(env, ctx, ISA_MIPS32R2);
3373 gen_op_mtc0_srsconf4();
3374 rn = "SRSConf4";
3375 break;
3376 default:
3377 goto die;
3379 break;
3380 case 7:
3381 switch (sel) {
3382 case 0:
3383 check_insn(env, ctx, ISA_MIPS32R2);
3384 gen_op_mtc0_hwrena();
3385 rn = "HWREna";
3386 break;
3387 default:
3388 goto die;
3390 break;
3391 case 8:
3392 /* ignored */
3393 rn = "BadVAddr";
3394 break;
3395 case 9:
3396 switch (sel) {
3397 case 0:
3398 gen_op_mtc0_count();
3399 rn = "Count";
3400 break;
3401 /* 6,7 are implementation dependent */
3402 default:
3403 goto die;
3405 /* Stop translation as we may have switched the execution mode */
3406 ctx->bstate = BS_STOP;
3407 break;
3408 case 10:
3409 switch (sel) {
3410 case 0:
3411 gen_op_mtc0_entryhi();
3412 rn = "EntryHi";
3413 break;
3414 default:
3415 goto die;
3417 break;
3418 case 11:
3419 switch (sel) {
3420 case 0:
3421 gen_op_mtc0_compare();
3422 rn = "Compare";
3423 break;
3424 /* 6,7 are implementation dependent */
3425 default:
3426 goto die;
3428 /* Stop translation as we may have switched the execution mode */
3429 ctx->bstate = BS_STOP;
3430 break;
3431 case 12:
3432 switch (sel) {
3433 case 0:
3434 gen_op_mtc0_status();
3435 /* BS_STOP isn't good enough here, hflags may have changed. */
3436 gen_save_pc(ctx->pc + 4);
3437 ctx->bstate = BS_EXCP;
3438 rn = "Status";
3439 break;
3440 case 1:
3441 check_insn(env, ctx, ISA_MIPS32R2);
3442 gen_op_mtc0_intctl();
3443 /* Stop translation as we may have switched the execution mode */
3444 ctx->bstate = BS_STOP;
3445 rn = "IntCtl";
3446 break;
3447 case 2:
3448 check_insn(env, ctx, ISA_MIPS32R2);
3449 gen_op_mtc0_srsctl();
3450 /* Stop translation as we may have switched the execution mode */
3451 ctx->bstate = BS_STOP;
3452 rn = "SRSCtl";
3453 break;
3454 case 3:
3455 check_insn(env, ctx, ISA_MIPS32R2);
3456 gen_op_mtc0_srsmap();
3457 /* Stop translation as we may have switched the execution mode */
3458 ctx->bstate = BS_STOP;
3459 rn = "SRSMap";
3460 break;
3461 default:
3462 goto die;
3464 break;
3465 case 13:
3466 switch (sel) {
3467 case 0:
3468 gen_op_mtc0_cause();
3469 rn = "Cause";
3470 break;
3471 default:
3472 goto die;
3474 /* Stop translation as we may have switched the execution mode */
3475 ctx->bstate = BS_STOP;
3476 break;
3477 case 14:
3478 switch (sel) {
3479 case 0:
3480 gen_op_mtc0_epc();
3481 rn = "EPC";
3482 break;
3483 default:
3484 goto die;
3486 break;
3487 case 15:
3488 switch (sel) {
3489 case 0:
3490 /* ignored */
3491 rn = "PRid";
3492 break;
3493 case 1:
3494 check_insn(env, ctx, ISA_MIPS32R2);
3495 gen_op_mtc0_ebase();
3496 rn = "EBase";
3497 break;
3498 default:
3499 goto die;
3501 break;
3502 case 16:
3503 switch (sel) {
3504 case 0:
3505 gen_op_mtc0_config0();
3506 rn = "Config";
3507 /* Stop translation as we may have switched the execution mode */
3508 ctx->bstate = BS_STOP;
3509 break;
3510 case 1:
3511 /* ignored, read only */
3512 rn = "Config1";
3513 break;
3514 case 2:
3515 gen_op_mtc0_config2();
3516 rn = "Config2";
3517 /* Stop translation as we may have switched the execution mode */
3518 ctx->bstate = BS_STOP;
3519 break;
3520 case 3:
3521 /* ignored, read only */
3522 rn = "Config3";
3523 break;
3524 /* 4,5 are reserved */
3525 /* 6,7 are implementation dependent */
3526 case 6:
3527 /* ignored */
3528 rn = "Config6";
3529 break;
3530 case 7:
3531 /* ignored */
3532 rn = "Config7";
3533 break;
3534 default:
3535 rn = "Invalid config selector";
3536 goto die;
3538 break;
3539 case 17:
3540 switch (sel) {
3541 case 0:
3542 /* ignored */
3543 rn = "LLAddr";
3544 break;
3545 default:
3546 goto die;
3548 break;
3549 case 18:
3550 switch (sel) {
3551 case 0 ... 7:
3552 gen_op_mtc0_watchlo(sel);
3553 rn = "WatchLo";
3554 break;
3555 default:
3556 goto die;
3558 break;
3559 case 19:
3560 switch (sel) {
3561 case 0 ... 7:
3562 gen_op_mtc0_watchhi(sel);
3563 rn = "WatchHi";
3564 break;
3565 default:
3566 goto die;
3568 break;
3569 case 20:
3570 switch (sel) {
3571 case 0:
3572 #if defined(TARGET_MIPS64)
3573 check_insn(env, ctx, ISA_MIPS3);
3574 gen_op_mtc0_xcontext();
3575 rn = "XContext";
3576 break;
3577 #endif
3578 default:
3579 goto die;
3581 break;
3582 case 21:
3583 /* Officially reserved, but sel 0 is used for R1x000 framemask */
3584 switch (sel) {
3585 case 0:
3586 gen_op_mtc0_framemask();
3587 rn = "Framemask";
3588 break;
3589 default:
3590 goto die;
3592 break;
3593 case 22:
3594 /* ignored */
3595 rn = "Diagnostic"; /* implementation dependent */
3596 break;
3597 case 23:
3598 switch (sel) {
3599 case 0:
3600 gen_op_mtc0_debug(); /* EJTAG support */
3601 /* BS_STOP isn't good enough here, hflags may have changed. */
3602 gen_save_pc(ctx->pc + 4);
3603 ctx->bstate = BS_EXCP;
3604 rn = "Debug";
3605 break;
3606 case 1:
3607 // gen_op_mtc0_tracecontrol(); /* PDtrace support */
3608 rn = "TraceControl";
3609 /* Stop translation as we may have switched the execution mode */
3610 ctx->bstate = BS_STOP;
3611 // break;
3612 case 2:
3613 // gen_op_mtc0_tracecontrol2(); /* PDtrace support */
3614 rn = "TraceControl2";
3615 /* Stop translation as we may have switched the execution mode */
3616 ctx->bstate = BS_STOP;
3617 // break;
3618 case 3:
3619 /* Stop translation as we may have switched the execution mode */
3620 ctx->bstate = BS_STOP;
3621 // gen_op_mtc0_usertracedata(); /* PDtrace support */
3622 rn = "UserTraceData";
3623 /* Stop translation as we may have switched the execution mode */
3624 ctx->bstate = BS_STOP;
3625 // break;
3626 case 4:
3627 // gen_op_mtc0_debug(); /* PDtrace support */
3628 /* Stop translation as we may have switched the execution mode */
3629 ctx->bstate = BS_STOP;
3630 rn = "TraceBPC";
3631 // break;
3632 default:
3633 goto die;
3635 break;
3636 case 24:
3637 switch (sel) {
3638 case 0:
3639 gen_op_mtc0_depc(); /* EJTAG support */
3640 rn = "DEPC";
3641 break;
3642 default:
3643 goto die;
3645 break;
3646 case 25:
3647 switch (sel) {
3648 case 0:
3649 gen_op_mtc0_performance0();
3650 rn = "Performance0";
3651 break;
3652 case 1:
3653 // gen_op_mtc0_performance1();
3654 rn = "Performance1";
3655 // break;
3656 case 2:
3657 // gen_op_mtc0_performance2();
3658 rn = "Performance2";
3659 // break;
3660 case 3:
3661 // gen_op_mtc0_performance3();
3662 rn = "Performance3";
3663 // break;
3664 case 4:
3665 // gen_op_mtc0_performance4();
3666 rn = "Performance4";
3667 // break;
3668 case 5:
3669 // gen_op_mtc0_performance5();
3670 rn = "Performance5";
3671 // break;
3672 case 6:
3673 // gen_op_mtc0_performance6();
3674 rn = "Performance6";
3675 // break;
3676 case 7:
3677 // gen_op_mtc0_performance7();
3678 rn = "Performance7";
3679 // break;
3680 default:
3681 goto die;
3683 break;
3684 case 26:
3685 /* ignored */
3686 rn = "ECC";
3687 break;
3688 case 27:
3689 switch (sel) {
3690 case 0 ... 3:
3691 /* ignored */
3692 rn = "CacheErr";
3693 break;
3694 default:
3695 goto die;
3697 break;
3698 case 28:
3699 switch (sel) {
3700 case 0:
3701 case 2:
3702 case 4:
3703 case 6:
3704 gen_op_mtc0_taglo();
3705 rn = "TagLo";
3706 break;
3707 case 1:
3708 case 3:
3709 case 5:
3710 case 7:
3711 gen_op_mtc0_datalo();
3712 rn = "DataLo";
3713 break;
3714 default:
3715 goto die;
3717 break;
3718 case 29:
3719 switch (sel) {
3720 case 0:
3721 case 2:
3722 case 4:
3723 case 6:
3724 gen_op_mtc0_taghi();
3725 rn = "TagHi";
3726 break;
3727 case 1:
3728 case 3:
3729 case 5:
3730 case 7:
3731 gen_op_mtc0_datahi();
3732 rn = "DataHi";
3733 break;
3734 default:
3735 rn = "invalid sel";
3736 goto die;
3738 break;
3739 case 30:
3740 switch (sel) {
3741 case 0:
3742 gen_op_mtc0_errorepc();
3743 rn = "ErrorEPC";
3744 break;
3745 default:
3746 goto die;
3748 break;
3749 case 31:
3750 switch (sel) {
3751 case 0:
3752 gen_op_mtc0_desave(); /* EJTAG support */
3753 rn = "DESAVE";
3754 break;
3755 default:
3756 goto die;
3758 /* Stop translation as we may have switched the execution mode */
3759 ctx->bstate = BS_STOP;
3760 break;
3761 default:
3762 goto die;
3764 #if defined MIPS_DEBUG_DISAS
3765 if (loglevel & CPU_LOG_TB_IN_ASM) {
3766 fprintf(logfile, "mtc0 %s (reg %d sel %d)\n",
3767 rn, reg, sel);
3769 #endif
3770 return;
3772 die:
3773 #if defined MIPS_DEBUG_DISAS
3774 if (loglevel & CPU_LOG_TB_IN_ASM) {
3775 fprintf(logfile, "mtc0 %s (reg %d sel %d)\n",
3776 rn, reg, sel);
3778 #endif
3779 generate_exception(ctx, EXCP_RI);
3782 #if defined(TARGET_MIPS64)
3783 static void gen_dmfc0 (CPUState *env, DisasContext *ctx, int reg, int sel)
3785 const char *rn = "invalid";
3787 if (sel != 0)
3788 check_insn(env, ctx, ISA_MIPS64);
3790 switch (reg) {
3791 case 0:
3792 switch (sel) {
3793 case 0:
3794 gen_mfc0_load32(cpu_T[0], offsetof(CPUState, CP0_Index));
3795 rn = "Index";
3796 break;
3797 case 1:
3798 check_insn(env, ctx, ASE_MT);
3799 gen_op_mfc0_mvpcontrol();
3800 rn = "MVPControl";
3801 break;
3802 case 2:
3803 check_insn(env, ctx, ASE_MT);
3804 gen_op_mfc0_mvpconf0();
3805 rn = "MVPConf0";
3806 break;
3807 case 3:
3808 check_insn(env, ctx, ASE_MT);
3809 gen_op_mfc0_mvpconf1();
3810 rn = "MVPConf1";
3811 break;
3812 default:
3813 goto die;
3815 break;
3816 case 1:
3817 switch (sel) {
3818 case 0:
3819 gen_op_mfc0_random();
3820 rn = "Random";
3821 break;
3822 case 1:
3823 check_insn(env, ctx, ASE_MT);
3824 gen_mfc0_load32(cpu_T[0], offsetof(CPUState, CP0_VPEControl));
3825 rn = "VPEControl";
3826 break;
3827 case 2:
3828 check_insn(env, ctx, ASE_MT);
3829 gen_mfc0_load32(cpu_T[0], offsetof(CPUState, CP0_VPEConf0));
3830 rn = "VPEConf0";
3831 break;
3832 case 3:
3833 check_insn(env, ctx, ASE_MT);
3834 gen_mfc0_load32(cpu_T[0], offsetof(CPUState, CP0_VPEConf1));
3835 rn = "VPEConf1";
3836 break;
3837 case 4:
3838 check_insn(env, ctx, ASE_MT);
3839 tcg_gen_ld_tl(cpu_T[0], cpu_env, offsetof(CPUState, CP0_YQMask));
3840 rn = "YQMask";
3841 break;
3842 case 5:
3843 check_insn(env, ctx, ASE_MT);
3844 tcg_gen_ld_tl(cpu_T[0], cpu_env, offsetof(CPUState, CP0_VPESchedule));
3845 rn = "VPESchedule";
3846 break;
3847 case 6:
3848 check_insn(env, ctx, ASE_MT);
3849 tcg_gen_ld_tl(cpu_T[0], cpu_env, offsetof(CPUState, CP0_VPEScheFBack));
3850 rn = "VPEScheFBack";
3851 break;
3852 case 7:
3853 check_insn(env, ctx, ASE_MT);
3854 gen_mfc0_load32(cpu_T[0], offsetof(CPUState, CP0_VPEOpt));
3855 rn = "VPEOpt";
3856 break;
3857 default:
3858 goto die;
3860 break;
3861 case 2:
3862 switch (sel) {
3863 case 0:
3864 tcg_gen_ld_tl(cpu_T[0], cpu_env, offsetof(CPUState, CP0_EntryLo0));
3865 rn = "EntryLo0";
3866 break;
3867 case 1:
3868 check_insn(env, ctx, ASE_MT);
3869 gen_op_mfc0_tcstatus();
3870 rn = "TCStatus";
3871 break;
3872 case 2:
3873 check_insn(env, ctx, ASE_MT);
3874 gen_op_mfc0_tcbind();
3875 rn = "TCBind";
3876 break;
3877 case 3:
3878 check_insn(env, ctx, ASE_MT);
3879 gen_op_dmfc0_tcrestart();
3880 rn = "TCRestart";
3881 break;
3882 case 4:
3883 check_insn(env, ctx, ASE_MT);
3884 gen_op_dmfc0_tchalt();
3885 rn = "TCHalt";
3886 break;
3887 case 5:
3888 check_insn(env, ctx, ASE_MT);
3889 gen_op_dmfc0_tccontext();
3890 rn = "TCContext";
3891 break;
3892 case 6:
3893 check_insn(env, ctx, ASE_MT);
3894 gen_op_dmfc0_tcschedule();
3895 rn = "TCSchedule";
3896 break;
3897 case 7:
3898 check_insn(env, ctx, ASE_MT);
3899 gen_op_dmfc0_tcschefback();
3900 rn = "TCScheFBack";
3901 break;
3902 default:
3903 goto die;
3905 break;
3906 case 3:
3907 switch (sel) {
3908 case 0:
3909 tcg_gen_ld_tl(cpu_T[0], cpu_env, offsetof(CPUState, CP0_EntryLo1));
3910 rn = "EntryLo1";
3911 break;
3912 default:
3913 goto die;
3915 break;
3916 case 4:
3917 switch (sel) {
3918 case 0:
3919 tcg_gen_ld_tl(cpu_T[0], cpu_env, offsetof(CPUState, CP0_Context));
3920 rn = "Context";
3921 break;
3922 case 1:
3923 // gen_op_dmfc0_contextconfig(); /* SmartMIPS ASE */
3924 rn = "ContextConfig";
3925 // break;
3926 default:
3927 goto die;
3929 break;
3930 case 5:
3931 switch (sel) {
3932 case 0:
3933 gen_mfc0_load32(cpu_T[0], offsetof(CPUState, CP0_PageMask));
3934 rn = "PageMask";
3935 break;
3936 case 1:
3937 check_insn(env, ctx, ISA_MIPS32R2);
3938 gen_mfc0_load32(cpu_T[0], offsetof(CPUState, CP0_PageGrain));
3939 rn = "PageGrain";
3940 break;
3941 default:
3942 goto die;
3944 break;
3945 case 6:
3946 switch (sel) {
3947 case 0:
3948 gen_mfc0_load32(cpu_T[0], offsetof(CPUState, CP0_Wired));
3949 rn = "Wired";
3950 break;
3951 case 1:
3952 check_insn(env, ctx, ISA_MIPS32R2);
3953 gen_mfc0_load32(cpu_T[0], offsetof(CPUState, CP0_SRSConf0));
3954 rn = "SRSConf0";
3955 break;
3956 case 2:
3957 check_insn(env, ctx, ISA_MIPS32R2);
3958 gen_mfc0_load32(cpu_T[0], offsetof(CPUState, CP0_SRSConf1));
3959 rn = "SRSConf1";
3960 break;
3961 case 3:
3962 check_insn(env, ctx, ISA_MIPS32R2);
3963 gen_mfc0_load32(cpu_T[0], offsetof(CPUState, CP0_SRSConf2));
3964 rn = "SRSConf2";
3965 break;
3966 case 4:
3967 check_insn(env, ctx, ISA_MIPS32R2);
3968 gen_mfc0_load32(cpu_T[0], offsetof(CPUState, CP0_SRSConf3));
3969 rn = "SRSConf3";
3970 break;
3971 case 5:
3972 check_insn(env, ctx, ISA_MIPS32R2);
3973 gen_mfc0_load32(cpu_T[0], offsetof(CPUState, CP0_SRSConf4));
3974 rn = "SRSConf4";
3975 break;
3976 default:
3977 goto die;
3979 break;
3980 case 7:
3981 switch (sel) {
3982 case 0:
3983 check_insn(env, ctx, ISA_MIPS32R2);
3984 gen_mfc0_load32(cpu_T[0], offsetof(CPUState, CP0_HWREna));
3985 rn = "HWREna";
3986 break;
3987 default:
3988 goto die;
3990 break;
3991 case 8:
3992 switch (sel) {
3993 case 0:
3994 tcg_gen_ld_tl(cpu_T[0], cpu_env, offsetof(CPUState, CP0_BadVAddr));
3995 rn = "BadVAddr";
3996 break;
3997 default:
3998 goto die;
4000 break;
4001 case 9:
4002 switch (sel) {
4003 case 0:
4004 gen_op_mfc0_count();
4005 rn = "Count";
4006 break;
4007 /* 6,7 are implementation dependent */
4008 default:
4009 goto die;
4011 break;
4012 case 10:
4013 switch (sel) {
4014 case 0:
4015 tcg_gen_ld_tl(cpu_T[0], cpu_env, offsetof(CPUState, CP0_EntryHi));
4016 rn = "EntryHi";
4017 break;
4018 default:
4019 goto die;
4021 break;
4022 case 11:
4023 switch (sel) {
4024 case 0:
4025 gen_mfc0_load32(cpu_T[0], offsetof(CPUState, CP0_Compare));
4026 rn = "Compare";
4027 break;
4028 /* 6,7 are implementation dependent */
4029 default:
4030 goto die;
4032 break;
4033 case 12:
4034 switch (sel) {
4035 case 0:
4036 gen_mfc0_load32(cpu_T[0], offsetof(CPUState, CP0_Status));
4037 rn = "Status";
4038 break;
4039 case 1:
4040 check_insn(env, ctx, ISA_MIPS32R2);
4041 gen_mfc0_load32(cpu_T[0], offsetof(CPUState, CP0_IntCtl));
4042 rn = "IntCtl";
4043 break;
4044 case 2:
4045 check_insn(env, ctx, ISA_MIPS32R2);
4046 gen_mfc0_load32(cpu_T[0], offsetof(CPUState, CP0_SRSCtl));
4047 rn = "SRSCtl";
4048 break;
4049 case 3:
4050 check_insn(env, ctx, ISA_MIPS32R2);
4051 gen_mfc0_load32(cpu_T[0], offsetof(CPUState, CP0_SRSMap));
4052 rn = "SRSMap";
4053 break;
4054 default:
4055 goto die;
4057 break;
4058 case 13:
4059 switch (sel) {
4060 case 0:
4061 gen_mfc0_load32(cpu_T[0], offsetof(CPUState, CP0_Cause));
4062 rn = "Cause";
4063 break;
4064 default:
4065 goto die;
4067 break;
4068 case 14:
4069 switch (sel) {
4070 case 0:
4071 tcg_gen_ld_tl(cpu_T[0], cpu_env, offsetof(CPUState, CP0_EPC));
4072 rn = "EPC";
4073 break;
4074 default:
4075 goto die;
4077 break;
4078 case 15:
4079 switch (sel) {
4080 case 0:
4081 gen_mfc0_load32(cpu_T[0], offsetof(CPUState, CP0_PRid));
4082 rn = "PRid";
4083 break;
4084 case 1:
4085 check_insn(env, ctx, ISA_MIPS32R2);
4086 gen_mfc0_load32(cpu_T[0], offsetof(CPUState, CP0_EBase));
4087 rn = "EBase";
4088 break;
4089 default:
4090 goto die;
4092 break;
4093 case 16:
4094 switch (sel) {
4095 case 0:
4096 gen_mfc0_load32(cpu_T[0], offsetof(CPUState, CP0_Config0));
4097 rn = "Config";
4098 break;
4099 case 1:
4100 gen_mfc0_load32(cpu_T[0], offsetof(CPUState, CP0_Config1));
4101 rn = "Config1";
4102 break;
4103 case 2:
4104 gen_mfc0_load32(cpu_T[0], offsetof(CPUState, CP0_Config2));
4105 rn = "Config2";
4106 break;
4107 case 3:
4108 gen_mfc0_load32(cpu_T[0], offsetof(CPUState, CP0_Config3));
4109 rn = "Config3";
4110 break;
4111 /* 6,7 are implementation dependent */
4112 case 6:
4113 gen_mfc0_load32(cpu_T[0], offsetof(CPUState, CP0_Config6));
4114 rn = "Config6";
4115 break;
4116 case 7:
4117 gen_mfc0_load32(cpu_T[0], offsetof(CPUState, CP0_Config7));
4118 rn = "Config7";
4119 break;
4120 default:
4121 goto die;
4123 break;
4124 case 17:
4125 switch (sel) {
4126 case 0:
4127 gen_op_dmfc0_lladdr();
4128 rn = "LLAddr";
4129 break;
4130 default:
4131 goto die;
4133 break;
4134 case 18:
4135 switch (sel) {
4136 case 0 ... 7:
4137 gen_op_dmfc0_watchlo(sel);
4138 rn = "WatchLo";
4139 break;
4140 default:
4141 goto die;
4143 break;
4144 case 19:
4145 switch (sel) {
4146 case 0 ... 7:
4147 gen_op_mfc0_watchhi(sel);
4148 rn = "WatchHi";
4149 break;
4150 default:
4151 goto die;
4153 break;
4154 case 20:
4155 switch (sel) {
4156 case 0:
4157 check_insn(env, ctx, ISA_MIPS3);
4158 tcg_gen_ld_tl(cpu_T[0], cpu_env, offsetof(CPUState, CP0_XContext));
4159 rn = "XContext";
4160 break;
4161 default:
4162 goto die;
4164 break;
4165 case 21:
4166 /* Officially reserved, but sel 0 is used for R1x000 framemask */
4167 switch (sel) {
4168 case 0:
4169 gen_mfc0_load32(cpu_T[0], offsetof(CPUState, CP0_Framemask));
4170 rn = "Framemask";
4171 break;
4172 default:
4173 goto die;
4175 break;
4176 case 22:
4177 /* ignored */
4178 rn = "'Diagnostic"; /* implementation dependent */
4179 break;
4180 case 23:
4181 switch (sel) {
4182 case 0:
4183 gen_op_mfc0_debug(); /* EJTAG support */
4184 rn = "Debug";
4185 break;
4186 case 1:
4187 // gen_op_dmfc0_tracecontrol(); /* PDtrace support */
4188 rn = "TraceControl";
4189 // break;
4190 case 2:
4191 // gen_op_dmfc0_tracecontrol2(); /* PDtrace support */
4192 rn = "TraceControl2";
4193 // break;
4194 case 3:
4195 // gen_op_dmfc0_usertracedata(); /* PDtrace support */
4196 rn = "UserTraceData";
4197 // break;
4198 case 4:
4199 // gen_op_dmfc0_debug(); /* PDtrace support */
4200 rn = "TraceBPC";
4201 // break;
4202 default:
4203 goto die;
4205 break;
4206 case 24:
4207 switch (sel) {
4208 case 0:
4209 /* EJTAG support */
4210 tcg_gen_ld_tl(cpu_T[0], cpu_env, offsetof(CPUState, CP0_DEPC));
4211 rn = "DEPC";
4212 break;
4213 default:
4214 goto die;
4216 break;
4217 case 25:
4218 switch (sel) {
4219 case 0:
4220 gen_mfc0_load32(cpu_T[0], offsetof(CPUState, CP0_Performance0));
4221 rn = "Performance0";
4222 break;
4223 case 1:
4224 // gen_op_dmfc0_performance1();
4225 rn = "Performance1";
4226 // break;
4227 case 2:
4228 // gen_op_dmfc0_performance2();
4229 rn = "Performance2";
4230 // break;
4231 case 3:
4232 // gen_op_dmfc0_performance3();
4233 rn = "Performance3";
4234 // break;
4235 case 4:
4236 // gen_op_dmfc0_performance4();
4237 rn = "Performance4";
4238 // break;
4239 case 5:
4240 // gen_op_dmfc0_performance5();
4241 rn = "Performance5";
4242 // break;
4243 case 6:
4244 // gen_op_dmfc0_performance6();
4245 rn = "Performance6";
4246 // break;
4247 case 7:
4248 // gen_op_dmfc0_performance7();
4249 rn = "Performance7";
4250 // break;
4251 default:
4252 goto die;
4254 break;
4255 case 26:
4256 rn = "ECC";
4257 break;
4258 case 27:
4259 switch (sel) {
4260 /* ignored */
4261 case 0 ... 3:
4262 rn = "CacheErr";
4263 break;
4264 default:
4265 goto die;
4267 break;
4268 case 28:
4269 switch (sel) {
4270 case 0:
4271 case 2:
4272 case 4:
4273 case 6:
4274 gen_mfc0_load32(cpu_T[0], offsetof(CPUState, CP0_TagLo));
4275 rn = "TagLo";
4276 break;
4277 case 1:
4278 case 3:
4279 case 5:
4280 case 7:
4281 gen_mfc0_load32(cpu_T[0], offsetof(CPUState, CP0_DataLo));
4282 rn = "DataLo";
4283 break;
4284 default:
4285 goto die;
4287 break;
4288 case 29:
4289 switch (sel) {
4290 case 0:
4291 case 2:
4292 case 4:
4293 case 6:
4294 gen_mfc0_load32(cpu_T[0], offsetof(CPUState, CP0_TagHi));
4295 rn = "TagHi";
4296 break;
4297 case 1:
4298 case 3:
4299 case 5:
4300 case 7:
4301 gen_mfc0_load32(cpu_T[0], offsetof(CPUState, CP0_DataHi));
4302 rn = "DataHi";
4303 break;
4304 default:
4305 goto die;
4307 break;
4308 case 30:
4309 switch (sel) {
4310 case 0:
4311 tcg_gen_ld_tl(cpu_T[0], cpu_env, offsetof(CPUState, CP0_ErrorEPC));
4312 rn = "ErrorEPC";
4313 break;
4314 default:
4315 goto die;
4317 break;
4318 case 31:
4319 switch (sel) {
4320 case 0:
4321 /* EJTAG support */
4322 gen_mfc0_load32(cpu_T[0], offsetof(CPUState, CP0_DESAVE));
4323 rn = "DESAVE";
4324 break;
4325 default:
4326 goto die;
4328 break;
4329 default:
4330 goto die;
4332 #if defined MIPS_DEBUG_DISAS
4333 if (loglevel & CPU_LOG_TB_IN_ASM) {
4334 fprintf(logfile, "dmfc0 %s (reg %d sel %d)\n",
4335 rn, reg, sel);
4337 #endif
4338 return;
4340 die:
4341 #if defined MIPS_DEBUG_DISAS
4342 if (loglevel & CPU_LOG_TB_IN_ASM) {
4343 fprintf(logfile, "dmfc0 %s (reg %d sel %d)\n",
4344 rn, reg, sel);
4346 #endif
4347 generate_exception(ctx, EXCP_RI);
4350 static void gen_dmtc0 (CPUState *env, DisasContext *ctx, int reg, int sel)
4352 const char *rn = "invalid";
4354 if (sel != 0)
4355 check_insn(env, ctx, ISA_MIPS64);
4357 switch (reg) {
4358 case 0:
4359 switch (sel) {
4360 case 0:
4361 gen_op_mtc0_index();
4362 rn = "Index";
4363 break;
4364 case 1:
4365 check_insn(env, ctx, ASE_MT);
4366 gen_op_mtc0_mvpcontrol();
4367 rn = "MVPControl";
4368 break;
4369 case 2:
4370 check_insn(env, ctx, ASE_MT);
4371 /* ignored */
4372 rn = "MVPConf0";
4373 break;
4374 case 3:
4375 check_insn(env, ctx, ASE_MT);
4376 /* ignored */
4377 rn = "MVPConf1";
4378 break;
4379 default:
4380 goto die;
4382 break;
4383 case 1:
4384 switch (sel) {
4385 case 0:
4386 /* ignored */
4387 rn = "Random";
4388 break;
4389 case 1:
4390 check_insn(env, ctx, ASE_MT);
4391 gen_op_mtc0_vpecontrol();
4392 rn = "VPEControl";
4393 break;
4394 case 2:
4395 check_insn(env, ctx, ASE_MT);
4396 gen_op_mtc0_vpeconf0();
4397 rn = "VPEConf0";
4398 break;
4399 case 3:
4400 check_insn(env, ctx, ASE_MT);
4401 gen_op_mtc0_vpeconf1();
4402 rn = "VPEConf1";
4403 break;
4404 case 4:
4405 check_insn(env, ctx, ASE_MT);
4406 gen_op_mtc0_yqmask();
4407 rn = "YQMask";
4408 break;
4409 case 5:
4410 check_insn(env, ctx, ASE_MT);
4411 gen_op_mtc0_vpeschedule();
4412 rn = "VPESchedule";
4413 break;
4414 case 6:
4415 check_insn(env, ctx, ASE_MT);
4416 gen_op_mtc0_vpeschefback();
4417 rn = "VPEScheFBack";
4418 break;
4419 case 7:
4420 check_insn(env, ctx, ASE_MT);
4421 gen_op_mtc0_vpeopt();
4422 rn = "VPEOpt";
4423 break;
4424 default:
4425 goto die;
4427 break;
4428 case 2:
4429 switch (sel) {
4430 case 0:
4431 gen_op_mtc0_entrylo0();
4432 rn = "EntryLo0";
4433 break;
4434 case 1:
4435 check_insn(env, ctx, ASE_MT);
4436 gen_op_mtc0_tcstatus();
4437 rn = "TCStatus";
4438 break;
4439 case 2:
4440 check_insn(env, ctx, ASE_MT);
4441 gen_op_mtc0_tcbind();
4442 rn = "TCBind";
4443 break;
4444 case 3:
4445 check_insn(env, ctx, ASE_MT);
4446 gen_op_mtc0_tcrestart();
4447 rn = "TCRestart";
4448 break;
4449 case 4:
4450 check_insn(env, ctx, ASE_MT);
4451 gen_op_mtc0_tchalt();
4452 rn = "TCHalt";
4453 break;
4454 case 5:
4455 check_insn(env, ctx, ASE_MT);
4456 gen_op_mtc0_tccontext();
4457 rn = "TCContext";
4458 break;
4459 case 6:
4460 check_insn(env, ctx, ASE_MT);
4461 gen_op_mtc0_tcschedule();
4462 rn = "TCSchedule";
4463 break;
4464 case 7:
4465 check_insn(env, ctx, ASE_MT);
4466 gen_op_mtc0_tcschefback();
4467 rn = "TCScheFBack";
4468 break;
4469 default:
4470 goto die;
4472 break;
4473 case 3:
4474 switch (sel) {
4475 case 0:
4476 gen_op_mtc0_entrylo1();
4477 rn = "EntryLo1";
4478 break;
4479 default:
4480 goto die;
4482 break;
4483 case 4:
4484 switch (sel) {
4485 case 0:
4486 gen_op_mtc0_context();
4487 rn = "Context";
4488 break;
4489 case 1:
4490 // gen_op_mtc0_contextconfig(); /* SmartMIPS ASE */
4491 rn = "ContextConfig";
4492 // break;
4493 default:
4494 goto die;
4496 break;
4497 case 5:
4498 switch (sel) {
4499 case 0:
4500 gen_op_mtc0_pagemask();
4501 rn = "PageMask";
4502 break;
4503 case 1:
4504 check_insn(env, ctx, ISA_MIPS32R2);
4505 gen_op_mtc0_pagegrain();
4506 rn = "PageGrain";
4507 break;
4508 default:
4509 goto die;
4511 break;
4512 case 6:
4513 switch (sel) {
4514 case 0:
4515 gen_op_mtc0_wired();
4516 rn = "Wired";
4517 break;
4518 case 1:
4519 check_insn(env, ctx, ISA_MIPS32R2);
4520 gen_op_mtc0_srsconf0();
4521 rn = "SRSConf0";
4522 break;
4523 case 2:
4524 check_insn(env, ctx, ISA_MIPS32R2);
4525 gen_op_mtc0_srsconf1();
4526 rn = "SRSConf1";
4527 break;
4528 case 3:
4529 check_insn(env, ctx, ISA_MIPS32R2);
4530 gen_op_mtc0_srsconf2();
4531 rn = "SRSConf2";
4532 break;
4533 case 4:
4534 check_insn(env, ctx, ISA_MIPS32R2);
4535 gen_op_mtc0_srsconf3();
4536 rn = "SRSConf3";
4537 break;
4538 case 5:
4539 check_insn(env, ctx, ISA_MIPS32R2);
4540 gen_op_mtc0_srsconf4();
4541 rn = "SRSConf4";
4542 break;
4543 default:
4544 goto die;
4546 break;
4547 case 7:
4548 switch (sel) {
4549 case 0:
4550 check_insn(env, ctx, ISA_MIPS32R2);
4551 gen_op_mtc0_hwrena();
4552 rn = "HWREna";
4553 break;
4554 default:
4555 goto die;
4557 break;
4558 case 8:
4559 /* ignored */
4560 rn = "BadVAddr";
4561 break;
4562 case 9:
4563 switch (sel) {
4564 case 0:
4565 gen_op_mtc0_count();
4566 rn = "Count";
4567 break;
4568 /* 6,7 are implementation dependent */
4569 default:
4570 goto die;
4572 /* Stop translation as we may have switched the execution mode */
4573 ctx->bstate = BS_STOP;
4574 break;
4575 case 10:
4576 switch (sel) {
4577 case 0:
4578 gen_op_mtc0_entryhi();
4579 rn = "EntryHi";
4580 break;
4581 default:
4582 goto die;
4584 break;
4585 case 11:
4586 switch (sel) {
4587 case 0:
4588 gen_op_mtc0_compare();
4589 rn = "Compare";
4590 break;
4591 /* 6,7 are implementation dependent */
4592 default:
4593 goto die;
4595 /* Stop translation as we may have switched the execution mode */
4596 ctx->bstate = BS_STOP;
4597 break;
4598 case 12:
4599 switch (sel) {
4600 case 0:
4601 gen_op_mtc0_status();
4602 /* BS_STOP isn't good enough here, hflags may have changed. */
4603 gen_save_pc(ctx->pc + 4);
4604 ctx->bstate = BS_EXCP;
4605 rn = "Status";
4606 break;
4607 case 1:
4608 check_insn(env, ctx, ISA_MIPS32R2);
4609 gen_op_mtc0_intctl();
4610 /* Stop translation as we may have switched the execution mode */
4611 ctx->bstate = BS_STOP;
4612 rn = "IntCtl";
4613 break;
4614 case 2:
4615 check_insn(env, ctx, ISA_MIPS32R2);
4616 gen_op_mtc0_srsctl();
4617 /* Stop translation as we may have switched the execution mode */
4618 ctx->bstate = BS_STOP;
4619 rn = "SRSCtl";
4620 break;
4621 case 3:
4622 check_insn(env, ctx, ISA_MIPS32R2);
4623 gen_op_mtc0_srsmap();
4624 /* Stop translation as we may have switched the execution mode */
4625 ctx->bstate = BS_STOP;
4626 rn = "SRSMap";
4627 break;
4628 default:
4629 goto die;
4631 break;
4632 case 13:
4633 switch (sel) {
4634 case 0:
4635 gen_op_mtc0_cause();
4636 rn = "Cause";
4637 break;
4638 default:
4639 goto die;
4641 /* Stop translation as we may have switched the execution mode */
4642 ctx->bstate = BS_STOP;
4643 break;
4644 case 14:
4645 switch (sel) {
4646 case 0:
4647 gen_op_mtc0_epc();
4648 rn = "EPC";
4649 break;
4650 default:
4651 goto die;
4653 break;
4654 case 15:
4655 switch (sel) {
4656 case 0:
4657 /* ignored */
4658 rn = "PRid";
4659 break;
4660 case 1:
4661 check_insn(env, ctx, ISA_MIPS32R2);
4662 gen_op_mtc0_ebase();
4663 rn = "EBase";
4664 break;
4665 default:
4666 goto die;
4668 break;
4669 case 16:
4670 switch (sel) {
4671 case 0:
4672 gen_op_mtc0_config0();
4673 rn = "Config";
4674 /* Stop translation as we may have switched the execution mode */
4675 ctx->bstate = BS_STOP;
4676 break;
4677 case 1:
4678 /* ignored */
4679 rn = "Config1";
4680 break;
4681 case 2:
4682 gen_op_mtc0_config2();
4683 rn = "Config2";
4684 /* Stop translation as we may have switched the execution mode */
4685 ctx->bstate = BS_STOP;
4686 break;
4687 case 3:
4688 /* ignored */
4689 rn = "Config3";
4690 break;
4691 /* 6,7 are implementation dependent */
4692 default:
4693 rn = "Invalid config selector";
4694 goto die;
4696 break;
4697 case 17:
4698 switch (sel) {
4699 case 0:
4700 /* ignored */
4701 rn = "LLAddr";
4702 break;
4703 default:
4704 goto die;
4706 break;
4707 case 18:
4708 switch (sel) {
4709 case 0 ... 7:
4710 gen_op_mtc0_watchlo(sel);
4711 rn = "WatchLo";
4712 break;
4713 default:
4714 goto die;
4716 break;
4717 case 19:
4718 switch (sel) {
4719 case 0 ... 7:
4720 gen_op_mtc0_watchhi(sel);
4721 rn = "WatchHi";
4722 break;
4723 default:
4724 goto die;
4726 break;
4727 case 20:
4728 switch (sel) {
4729 case 0:
4730 check_insn(env, ctx, ISA_MIPS3);
4731 gen_op_mtc0_xcontext();
4732 rn = "XContext";
4733 break;
4734 default:
4735 goto die;
4737 break;
4738 case 21:
4739 /* Officially reserved, but sel 0 is used for R1x000 framemask */
4740 switch (sel) {
4741 case 0:
4742 gen_op_mtc0_framemask();
4743 rn = "Framemask";
4744 break;
4745 default:
4746 goto die;
4748 break;
4749 case 22:
4750 /* ignored */
4751 rn = "Diagnostic"; /* implementation dependent */
4752 break;
4753 case 23:
4754 switch (sel) {
4755 case 0:
4756 gen_op_mtc0_debug(); /* EJTAG support */
4757 /* BS_STOP isn't good enough here, hflags may have changed. */
4758 gen_save_pc(ctx->pc + 4);
4759 ctx->bstate = BS_EXCP;
4760 rn = "Debug";
4761 break;
4762 case 1:
4763 // gen_op_mtc0_tracecontrol(); /* PDtrace support */
4764 /* Stop translation as we may have switched the execution mode */
4765 ctx->bstate = BS_STOP;
4766 rn = "TraceControl";
4767 // break;
4768 case 2:
4769 // gen_op_mtc0_tracecontrol2(); /* PDtrace support */
4770 /* Stop translation as we may have switched the execution mode */
4771 ctx->bstate = BS_STOP;
4772 rn = "TraceControl2";
4773 // break;
4774 case 3:
4775 // gen_op_mtc0_usertracedata(); /* PDtrace support */
4776 /* Stop translation as we may have switched the execution mode */
4777 ctx->bstate = BS_STOP;
4778 rn = "UserTraceData";
4779 // break;
4780 case 4:
4781 // gen_op_mtc0_debug(); /* PDtrace support */
4782 /* Stop translation as we may have switched the execution mode */
4783 ctx->bstate = BS_STOP;
4784 rn = "TraceBPC";
4785 // break;
4786 default:
4787 goto die;
4789 break;
4790 case 24:
4791 switch (sel) {
4792 case 0:
4793 gen_op_mtc0_depc(); /* EJTAG support */
4794 rn = "DEPC";
4795 break;
4796 default:
4797 goto die;
4799 break;
4800 case 25:
4801 switch (sel) {
4802 case 0:
4803 gen_op_mtc0_performance0();
4804 rn = "Performance0";
4805 break;
4806 case 1:
4807 // gen_op_mtc0_performance1();
4808 rn = "Performance1";
4809 // break;
4810 case 2:
4811 // gen_op_mtc0_performance2();
4812 rn = "Performance2";
4813 // break;
4814 case 3:
4815 // gen_op_mtc0_performance3();
4816 rn = "Performance3";
4817 // break;
4818 case 4:
4819 // gen_op_mtc0_performance4();
4820 rn = "Performance4";
4821 // break;
4822 case 5:
4823 // gen_op_mtc0_performance5();
4824 rn = "Performance5";
4825 // break;
4826 case 6:
4827 // gen_op_mtc0_performance6();
4828 rn = "Performance6";
4829 // break;
4830 case 7:
4831 // gen_op_mtc0_performance7();
4832 rn = "Performance7";
4833 // break;
4834 default:
4835 goto die;
4837 break;
4838 case 26:
4839 /* ignored */
4840 rn = "ECC";
4841 break;
4842 case 27:
4843 switch (sel) {
4844 case 0 ... 3:
4845 /* ignored */
4846 rn = "CacheErr";
4847 break;
4848 default:
4849 goto die;
4851 break;
4852 case 28:
4853 switch (sel) {
4854 case 0:
4855 case 2:
4856 case 4:
4857 case 6:
4858 gen_op_mtc0_taglo();
4859 rn = "TagLo";
4860 break;
4861 case 1:
4862 case 3:
4863 case 5:
4864 case 7:
4865 gen_op_mtc0_datalo();
4866 rn = "DataLo";
4867 break;
4868 default:
4869 goto die;
4871 break;
4872 case 29:
4873 switch (sel) {
4874 case 0:
4875 case 2:
4876 case 4:
4877 case 6:
4878 gen_op_mtc0_taghi();
4879 rn = "TagHi";
4880 break;
4881 case 1:
4882 case 3:
4883 case 5:
4884 case 7:
4885 gen_op_mtc0_datahi();
4886 rn = "DataHi";
4887 break;
4888 default:
4889 rn = "invalid sel";
4890 goto die;
4892 break;
4893 case 30:
4894 switch (sel) {
4895 case 0:
4896 gen_op_mtc0_errorepc();
4897 rn = "ErrorEPC";
4898 break;
4899 default:
4900 goto die;
4902 break;
4903 case 31:
4904 switch (sel) {
4905 case 0:
4906 gen_op_mtc0_desave(); /* EJTAG support */
4907 rn = "DESAVE";
4908 break;
4909 default:
4910 goto die;
4912 /* Stop translation as we may have switched the execution mode */
4913 ctx->bstate = BS_STOP;
4914 break;
4915 default:
4916 goto die;
4918 #if defined MIPS_DEBUG_DISAS
4919 if (loglevel & CPU_LOG_TB_IN_ASM) {
4920 fprintf(logfile, "dmtc0 %s (reg %d sel %d)\n",
4921 rn, reg, sel);
4923 #endif
4924 return;
4926 die:
4927 #if defined MIPS_DEBUG_DISAS
4928 if (loglevel & CPU_LOG_TB_IN_ASM) {
4929 fprintf(logfile, "dmtc0 %s (reg %d sel %d)\n",
4930 rn, reg, sel);
4932 #endif
4933 generate_exception(ctx, EXCP_RI);
4935 #endif /* TARGET_MIPS64 */
4937 static void gen_mftr(CPUState *env, DisasContext *ctx, int rt,
4938 int u, int sel, int h)
4940 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
4942 if ((env->CP0_VPEConf0 & (1 << CP0VPEC0_MVP)) == 0 &&
4943 ((env->CP0_TCBind[other_tc] & (0xf << CP0TCBd_CurVPE)) !=
4944 (env->CP0_TCBind[env->current_tc] & (0xf << CP0TCBd_CurVPE))))
4945 tcg_gen_movi_tl(cpu_T[0], -1);
4946 else if ((env->CP0_VPEControl & (0xff << CP0VPECo_TargTC)) >
4947 (env->mvp->CP0_MVPConf0 & (0xff << CP0MVPC0_PTC)))
4948 tcg_gen_movi_tl(cpu_T[0], -1);
4949 else if (u == 0) {
4950 switch (rt) {
4951 case 2:
4952 switch (sel) {
4953 case 1:
4954 gen_op_mftc0_tcstatus();
4955 break;
4956 case 2:
4957 gen_op_mftc0_tcbind();
4958 break;
4959 case 3:
4960 gen_op_mftc0_tcrestart();
4961 break;
4962 case 4:
4963 gen_op_mftc0_tchalt();
4964 break;
4965 case 5:
4966 gen_op_mftc0_tccontext();
4967 break;
4968 case 6:
4969 gen_op_mftc0_tcschedule();
4970 break;
4971 case 7:
4972 gen_op_mftc0_tcschefback();
4973 break;
4974 default:
4975 gen_mfc0(env, ctx, rt, sel);
4976 break;
4978 break;
4979 case 10:
4980 switch (sel) {
4981 case 0:
4982 gen_op_mftc0_entryhi();
4983 break;
4984 default:
4985 gen_mfc0(env, ctx, rt, sel);
4986 break;
4988 case 12:
4989 switch (sel) {
4990 case 0:
4991 gen_op_mftc0_status();
4992 break;
4993 default:
4994 gen_mfc0(env, ctx, rt, sel);
4995 break;
4997 case 23:
4998 switch (sel) {
4999 case 0:
5000 gen_op_mftc0_debug();
5001 break;
5002 default:
5003 gen_mfc0(env, ctx, rt, sel);
5004 break;
5006 break;
5007 default:
5008 gen_mfc0(env, ctx, rt, sel);
5010 } else switch (sel) {
5011 /* GPR registers. */
5012 case 0:
5013 gen_op_mftgpr(rt);
5014 break;
5015 /* Auxiliary CPU registers */
5016 case 1:
5017 switch (rt) {
5018 case 0:
5019 gen_op_mftlo(0);
5020 break;
5021 case 1:
5022 gen_op_mfthi(0);
5023 break;
5024 case 2:
5025 gen_op_mftacx(0);
5026 break;
5027 case 4:
5028 gen_op_mftlo(1);
5029 break;
5030 case 5:
5031 gen_op_mfthi(1);
5032 break;
5033 case 6:
5034 gen_op_mftacx(1);
5035 break;
5036 case 8:
5037 gen_op_mftlo(2);
5038 break;
5039 case 9:
5040 gen_op_mfthi(2);
5041 break;
5042 case 10:
5043 gen_op_mftacx(2);
5044 break;
5045 case 12:
5046 gen_op_mftlo(3);
5047 break;
5048 case 13:
5049 gen_op_mfthi(3);
5050 break;
5051 case 14:
5052 gen_op_mftacx(3);
5053 break;
5054 case 16:
5055 gen_op_mftdsp();
5056 break;
5057 default:
5058 goto die;
5060 break;
5061 /* Floating point (COP1). */
5062 case 2:
5063 /* XXX: For now we support only a single FPU context. */
5064 if (h == 0) {
5065 GEN_LOAD_FREG_FTN(WT0, rt);
5066 gen_op_mfc1();
5067 } else {
5068 GEN_LOAD_FREG_FTN(WTH0, rt);
5069 gen_op_mfhc1();
5071 break;
5072 case 3:
5073 /* XXX: For now we support only a single FPU context. */
5074 gen_op_cfc1(rt);
5075 break;
5076 /* COP2: Not implemented. */
5077 case 4:
5078 case 5:
5079 /* fall through */
5080 default:
5081 goto die;
5083 #if defined MIPS_DEBUG_DISAS
5084 if (loglevel & CPU_LOG_TB_IN_ASM) {
5085 fprintf(logfile, "mftr (reg %d u %d sel %d h %d)\n",
5086 rt, u, sel, h);
5088 #endif
5089 return;
5091 die:
5092 #if defined MIPS_DEBUG_DISAS
5093 if (loglevel & CPU_LOG_TB_IN_ASM) {
5094 fprintf(logfile, "mftr (reg %d u %d sel %d h %d)\n",
5095 rt, u, sel, h);
5097 #endif
5098 generate_exception(ctx, EXCP_RI);
5101 static void gen_mttr(CPUState *env, DisasContext *ctx, int rd,
5102 int u, int sel, int h)
5104 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
5106 if ((env->CP0_VPEConf0 & (1 << CP0VPEC0_MVP)) == 0 &&
5107 ((env->CP0_TCBind[other_tc] & (0xf << CP0TCBd_CurVPE)) !=
5108 (env->CP0_TCBind[env->current_tc] & (0xf << CP0TCBd_CurVPE))))
5109 /* NOP */ ;
5110 else if ((env->CP0_VPEControl & (0xff << CP0VPECo_TargTC)) >
5111 (env->mvp->CP0_MVPConf0 & (0xff << CP0MVPC0_PTC)))
5112 /* NOP */ ;
5113 else if (u == 0) {
5114 switch (rd) {
5115 case 2:
5116 switch (sel) {
5117 case 1:
5118 gen_op_mttc0_tcstatus();
5119 break;
5120 case 2:
5121 gen_op_mttc0_tcbind();
5122 break;
5123 case 3:
5124 gen_op_mttc0_tcrestart();
5125 break;
5126 case 4:
5127 gen_op_mttc0_tchalt();
5128 break;
5129 case 5:
5130 gen_op_mttc0_tccontext();
5131 break;
5132 case 6:
5133 gen_op_mttc0_tcschedule();
5134 break;
5135 case 7:
5136 gen_op_mttc0_tcschefback();
5137 break;
5138 default:
5139 gen_mtc0(env, ctx, rd, sel);
5140 break;
5142 break;
5143 case 10:
5144 switch (sel) {
5145 case 0:
5146 gen_op_mttc0_entryhi();
5147 break;
5148 default:
5149 gen_mtc0(env, ctx, rd, sel);
5150 break;
5152 case 12:
5153 switch (sel) {
5154 case 0:
5155 gen_op_mttc0_status();
5156 break;
5157 default:
5158 gen_mtc0(env, ctx, rd, sel);
5159 break;
5161 case 23:
5162 switch (sel) {
5163 case 0:
5164 gen_op_mttc0_debug();
5165 break;
5166 default:
5167 gen_mtc0(env, ctx, rd, sel);
5168 break;
5170 break;
5171 default:
5172 gen_mtc0(env, ctx, rd, sel);
5174 } else switch (sel) {
5175 /* GPR registers. */
5176 case 0:
5177 gen_op_mttgpr(rd);
5178 break;
5179 /* Auxiliary CPU registers */
5180 case 1:
5181 switch (rd) {
5182 case 0:
5183 gen_op_mttlo(0);
5184 break;
5185 case 1:
5186 gen_op_mtthi(0);
5187 break;
5188 case 2:
5189 gen_op_mttacx(0);
5190 break;
5191 case 4:
5192 gen_op_mttlo(1);
5193 break;
5194 case 5:
5195 gen_op_mtthi(1);
5196 break;
5197 case 6:
5198 gen_op_mttacx(1);
5199 break;
5200 case 8:
5201 gen_op_mttlo(2);
5202 break;
5203 case 9:
5204 gen_op_mtthi(2);
5205 break;
5206 case 10:
5207 gen_op_mttacx(2);
5208 break;
5209 case 12:
5210 gen_op_mttlo(3);
5211 break;
5212 case 13:
5213 gen_op_mtthi(3);
5214 break;
5215 case 14:
5216 gen_op_mttacx(3);
5217 break;
5218 case 16:
5219 gen_op_mttdsp();
5220 break;
5221 default:
5222 goto die;
5224 break;
5225 /* Floating point (COP1). */
5226 case 2:
5227 /* XXX: For now we support only a single FPU context. */
5228 if (h == 0) {
5229 gen_op_mtc1();
5230 GEN_STORE_FTN_FREG(rd, WT0);
5231 } else {
5232 gen_op_mthc1();
5233 GEN_STORE_FTN_FREG(rd, WTH0);
5235 break;
5236 case 3:
5237 /* XXX: For now we support only a single FPU context. */
5238 gen_op_ctc1(rd);
5239 break;
5240 /* COP2: Not implemented. */
5241 case 4:
5242 case 5:
5243 /* fall through */
5244 default:
5245 goto die;
5247 #if defined MIPS_DEBUG_DISAS
5248 if (loglevel & CPU_LOG_TB_IN_ASM) {
5249 fprintf(logfile, "mttr (reg %d u %d sel %d h %d)\n",
5250 rd, u, sel, h);
5252 #endif
5253 return;
5255 die:
5256 #if defined MIPS_DEBUG_DISAS
5257 if (loglevel & CPU_LOG_TB_IN_ASM) {
5258 fprintf(logfile, "mttr (reg %d u %d sel %d h %d)\n",
5259 rd, u, sel, h);
5261 #endif
5262 generate_exception(ctx, EXCP_RI);
5265 static void gen_cp0 (CPUState *env, DisasContext *ctx, uint32_t opc, int rt, int rd)
5267 const char *opn = "ldst";
5269 switch (opc) {
5270 case OPC_MFC0:
5271 if (rt == 0) {
5272 /* Treat as NOP. */
5273 return;
5275 gen_mfc0(env, ctx, rd, ctx->opcode & 0x7);
5276 gen_store_gpr(cpu_T[0], rt);
5277 opn = "mfc0";
5278 break;
5279 case OPC_MTC0:
5280 gen_load_gpr(cpu_T[0], rt);
5281 save_cpu_state(ctx, 1);
5282 gen_mtc0(env, ctx, rd, ctx->opcode & 0x7);
5283 opn = "mtc0";
5284 break;
5285 #if defined(TARGET_MIPS64)
5286 case OPC_DMFC0:
5287 check_insn(env, ctx, ISA_MIPS3);
5288 if (rt == 0) {
5289 /* Treat as NOP. */
5290 return;
5292 gen_dmfc0(env, ctx, rd, ctx->opcode & 0x7);
5293 gen_store_gpr(cpu_T[0], rt);
5294 opn = "dmfc0";
5295 break;
5296 case OPC_DMTC0:
5297 check_insn(env, ctx, ISA_MIPS3);
5298 gen_load_gpr(cpu_T[0], rt);
5299 save_cpu_state(ctx, 1);
5300 gen_dmtc0(env, ctx, rd, ctx->opcode & 0x7);
5301 opn = "dmtc0";
5302 break;
5303 #endif
5304 case OPC_MFTR:
5305 check_insn(env, ctx, ASE_MT);
5306 if (rd == 0) {
5307 /* Treat as NOP. */
5308 return;
5310 gen_mftr(env, ctx, rt, (ctx->opcode >> 5) & 1,
5311 ctx->opcode & 0x7, (ctx->opcode >> 4) & 1);
5312 gen_store_gpr(cpu_T[0], rd);
5313 opn = "mftr";
5314 break;
5315 case OPC_MTTR:
5316 check_insn(env, ctx, ASE_MT);
5317 gen_load_gpr(cpu_T[0], rt);
5318 gen_mttr(env, ctx, rd, (ctx->opcode >> 5) & 1,
5319 ctx->opcode & 0x7, (ctx->opcode >> 4) & 1);
5320 opn = "mttr";
5321 break;
5322 case OPC_TLBWI:
5323 opn = "tlbwi";
5324 if (!env->tlb->do_tlbwi)
5325 goto die;
5326 gen_op_tlbwi();
5327 break;
5328 case OPC_TLBWR:
5329 opn = "tlbwr";
5330 if (!env->tlb->do_tlbwr)
5331 goto die;
5332 gen_op_tlbwr();
5333 break;
5334 case OPC_TLBP:
5335 opn = "tlbp";
5336 if (!env->tlb->do_tlbp)
5337 goto die;
5338 gen_op_tlbp();
5339 break;
5340 case OPC_TLBR:
5341 opn = "tlbr";
5342 if (!env->tlb->do_tlbr)
5343 goto die;
5344 gen_op_tlbr();
5345 break;
5346 case OPC_ERET:
5347 opn = "eret";
5348 check_insn(env, ctx, ISA_MIPS2);
5349 save_cpu_state(ctx, 1);
5350 gen_op_eret();
5351 ctx->bstate = BS_EXCP;
5352 break;
5353 case OPC_DERET:
5354 opn = "deret";
5355 check_insn(env, ctx, ISA_MIPS32);
5356 if (!(ctx->hflags & MIPS_HFLAG_DM)) {
5357 MIPS_INVAL(opn);
5358 generate_exception(ctx, EXCP_RI);
5359 } else {
5360 save_cpu_state(ctx, 1);
5361 gen_op_deret();
5362 ctx->bstate = BS_EXCP;
5364 break;
5365 case OPC_WAIT:
5366 opn = "wait";
5367 check_insn(env, ctx, ISA_MIPS3 | ISA_MIPS32);
5368 /* If we get an exception, we want to restart at next instruction */
5369 ctx->pc += 4;
5370 save_cpu_state(ctx, 1);
5371 ctx->pc -= 4;
5372 gen_op_wait();
5373 ctx->bstate = BS_EXCP;
5374 break;
5375 default:
5376 die:
5377 MIPS_INVAL(opn);
5378 generate_exception(ctx, EXCP_RI);
5379 return;
5381 MIPS_DEBUG("%s %s %d", opn, regnames[rt], rd);
5384 /* CP1 Branches (before delay slot) */
5385 static void gen_compute_branch1 (CPUState *env, DisasContext *ctx, uint32_t op,
5386 int32_t cc, int32_t offset)
5388 target_ulong btarget;
5389 const char *opn = "cp1 cond branch";
5391 if (cc != 0)
5392 check_insn(env, ctx, ISA_MIPS4 | ISA_MIPS32);
5394 btarget = ctx->pc + 4 + offset;
5396 switch (op) {
5397 case OPC_BC1F:
5398 gen_op_bc1f(cc);
5399 opn = "bc1f";
5400 goto not_likely;
5401 case OPC_BC1FL:
5402 gen_op_bc1f(cc);
5403 opn = "bc1fl";
5404 goto likely;
5405 case OPC_BC1T:
5406 gen_op_bc1t(cc);
5407 opn = "bc1t";
5408 goto not_likely;
5409 case OPC_BC1TL:
5410 gen_op_bc1t(cc);
5411 opn = "bc1tl";
5412 likely:
5413 ctx->hflags |= MIPS_HFLAG_BL;
5414 tcg_gen_st_tl(cpu_T[0], cpu_env, offsetof(CPUState, bcond));
5415 break;
5416 case OPC_BC1FANY2:
5417 gen_op_bc1any2f(cc);
5418 opn = "bc1any2f";
5419 goto not_likely;
5420 case OPC_BC1TANY2:
5421 gen_op_bc1any2t(cc);
5422 opn = "bc1any2t";
5423 goto not_likely;
5424 case OPC_BC1FANY4:
5425 gen_op_bc1any4f(cc);
5426 opn = "bc1any4f";
5427 goto not_likely;
5428 case OPC_BC1TANY4:
5429 gen_op_bc1any4t(cc);
5430 opn = "bc1any4t";
5431 not_likely:
5432 ctx->hflags |= MIPS_HFLAG_BC;
5433 tcg_gen_st_tl(cpu_T[0], cpu_env, offsetof(CPUState, bcond));
5434 break;
5435 default:
5436 MIPS_INVAL(opn);
5437 generate_exception (ctx, EXCP_RI);
5438 return;
5440 MIPS_DEBUG("%s: cond %02x target " TARGET_FMT_lx, opn,
5441 ctx->hflags, btarget);
5442 ctx->btarget = btarget;
5445 /* Coprocessor 1 (FPU) */
5447 #define FOP(func, fmt) (((fmt) << 21) | (func))
5449 static void gen_cp1 (DisasContext *ctx, uint32_t opc, int rt, int fs)
5451 const char *opn = "cp1 move";
5453 switch (opc) {
5454 case OPC_MFC1:
5455 GEN_LOAD_FREG_FTN(WT0, fs);
5456 gen_op_mfc1();
5457 gen_store_gpr(cpu_T[0], rt);
5458 opn = "mfc1";
5459 break;
5460 case OPC_MTC1:
5461 gen_load_gpr(cpu_T[0], rt);
5462 gen_op_mtc1();
5463 GEN_STORE_FTN_FREG(fs, WT0);
5464 opn = "mtc1";
5465 break;
5466 case OPC_CFC1:
5467 gen_op_cfc1(fs);
5468 gen_store_gpr(cpu_T[0], rt);
5469 opn = "cfc1";
5470 break;
5471 case OPC_CTC1:
5472 gen_load_gpr(cpu_T[0], rt);
5473 gen_op_ctc1(fs);
5474 opn = "ctc1";
5475 break;
5476 case OPC_DMFC1:
5477 GEN_LOAD_FREG_FTN(DT0, fs);
5478 gen_op_dmfc1();
5479 gen_store_gpr(cpu_T[0], rt);
5480 opn = "dmfc1";
5481 break;
5482 case OPC_DMTC1:
5483 gen_load_gpr(cpu_T[0], rt);
5484 gen_op_dmtc1();
5485 GEN_STORE_FTN_FREG(fs, DT0);
5486 opn = "dmtc1";
5487 break;
5488 case OPC_MFHC1:
5489 GEN_LOAD_FREG_FTN(WTH0, fs);
5490 gen_op_mfhc1();
5491 gen_store_gpr(cpu_T[0], rt);
5492 opn = "mfhc1";
5493 break;
5494 case OPC_MTHC1:
5495 gen_load_gpr(cpu_T[0], rt);
5496 gen_op_mthc1();
5497 GEN_STORE_FTN_FREG(fs, WTH0);
5498 opn = "mthc1";
5499 break;
5500 default:
5501 MIPS_INVAL(opn);
5502 generate_exception (ctx, EXCP_RI);
5503 return;
5505 MIPS_DEBUG("%s %s %s", opn, regnames[rt], fregnames[fs]);
5508 static void gen_movci (DisasContext *ctx, int rd, int rs, int cc, int tf)
5510 int l1 = gen_new_label();
5511 uint32_t ccbit;
5512 TCGCond cond;
5514 if (cc)
5515 ccbit = 1 << (24 + cc);
5516 else
5517 ccbit = 1 << 23;
5518 if (tf)
5519 cond = TCG_COND_EQ;
5520 else
5521 cond = TCG_COND_NE;
5523 gen_load_gpr(cpu_T[0], rd);
5524 gen_load_gpr(cpu_T[1], rs);
5526 TCGv r_ptr = tcg_temp_new(TCG_TYPE_PTR);
5527 TCGv r_tmp = tcg_temp_new(TCG_TYPE_I32);
5529 tcg_gen_ld_ptr(r_ptr, cpu_env, offsetof(CPUState, fpu));
5530 tcg_gen_ld_i32(r_tmp, r_ptr, offsetof(CPUMIPSFPUContext, fcr31));
5531 tcg_temp_free(r_ptr);
5532 tcg_gen_andi_i32(r_tmp, r_tmp, ccbit);
5533 tcg_gen_brcondi_i32(cond, r_tmp, 0, l1);
5535 tcg_gen_mov_tl(cpu_T[0], cpu_T[1]);
5537 gen_set_label(l1);
5538 gen_store_gpr(cpu_T[0], rd);
5541 #define GEN_MOVCF(fmt) \
5542 static void glue(gen_movcf_, fmt) (DisasContext *ctx, int cc, int tf) \
5544 uint32_t ccbit; \
5546 if (cc) { \
5547 ccbit = 1 << (24 + cc); \
5548 } else \
5549 ccbit = 1 << 23; \
5550 if (!tf) \
5551 glue(gen_op_float_movf_, fmt)(ccbit); \
5552 else \
5553 glue(gen_op_float_movt_, fmt)(ccbit); \
5555 GEN_MOVCF(d);
5556 GEN_MOVCF(s);
5557 #undef GEN_MOVCF
5559 static void gen_farith (DisasContext *ctx, uint32_t op1,
5560 int ft, int fs, int fd, int cc)
5562 const char *opn = "farith";
5563 const char *condnames[] = {
5564 "c.f",
5565 "c.un",
5566 "c.eq",
5567 "c.ueq",
5568 "c.olt",
5569 "c.ult",
5570 "c.ole",
5571 "c.ule",
5572 "c.sf",
5573 "c.ngle",
5574 "c.seq",
5575 "c.ngl",
5576 "c.lt",
5577 "c.nge",
5578 "c.le",
5579 "c.ngt",
5581 const char *condnames_abs[] = {
5582 "cabs.f",
5583 "cabs.un",
5584 "cabs.eq",
5585 "cabs.ueq",
5586 "cabs.olt",
5587 "cabs.ult",
5588 "cabs.ole",
5589 "cabs.ule",
5590 "cabs.sf",
5591 "cabs.ngle",
5592 "cabs.seq",
5593 "cabs.ngl",
5594 "cabs.lt",
5595 "cabs.nge",
5596 "cabs.le",
5597 "cabs.ngt",
5599 enum { BINOP, CMPOP, OTHEROP } optype = OTHEROP;
5600 uint32_t func = ctx->opcode & 0x3f;
5602 switch (ctx->opcode & FOP(0x3f, 0x1f)) {
5603 case FOP(0, 16):
5604 GEN_LOAD_FREG_FTN(WT0, fs);
5605 GEN_LOAD_FREG_FTN(WT1, ft);
5606 gen_op_float_add_s();
5607 GEN_STORE_FTN_FREG(fd, WT2);
5608 opn = "add.s";
5609 optype = BINOP;
5610 break;
5611 case FOP(1, 16):
5612 GEN_LOAD_FREG_FTN(WT0, fs);
5613 GEN_LOAD_FREG_FTN(WT1, ft);
5614 gen_op_float_sub_s();
5615 GEN_STORE_FTN_FREG(fd, WT2);
5616 opn = "sub.s";
5617 optype = BINOP;
5618 break;
5619 case FOP(2, 16):
5620 GEN_LOAD_FREG_FTN(WT0, fs);
5621 GEN_LOAD_FREG_FTN(WT1, ft);
5622 gen_op_float_mul_s();
5623 GEN_STORE_FTN_FREG(fd, WT2);
5624 opn = "mul.s";
5625 optype = BINOP;
5626 break;
5627 case FOP(3, 16):
5628 GEN_LOAD_FREG_FTN(WT0, fs);
5629 GEN_LOAD_FREG_FTN(WT1, ft);
5630 gen_op_float_div_s();
5631 GEN_STORE_FTN_FREG(fd, WT2);
5632 opn = "div.s";
5633 optype = BINOP;
5634 break;
5635 case FOP(4, 16):
5636 GEN_LOAD_FREG_FTN(WT0, fs);
5637 gen_op_float_sqrt_s();
5638 GEN_STORE_FTN_FREG(fd, WT2);
5639 opn = "sqrt.s";
5640 break;
5641 case FOP(5, 16):
5642 GEN_LOAD_FREG_FTN(WT0, fs);
5643 gen_op_float_abs_s();
5644 GEN_STORE_FTN_FREG(fd, WT2);
5645 opn = "abs.s";
5646 break;
5647 case FOP(6, 16):
5648 GEN_LOAD_FREG_FTN(WT0, fs);
5649 gen_op_float_mov_s();
5650 GEN_STORE_FTN_FREG(fd, WT2);
5651 opn = "mov.s";
5652 break;
5653 case FOP(7, 16):
5654 GEN_LOAD_FREG_FTN(WT0, fs);
5655 gen_op_float_chs_s();
5656 GEN_STORE_FTN_FREG(fd, WT2);
5657 opn = "neg.s";
5658 break;
5659 case FOP(8, 16):
5660 check_cp1_64bitmode(ctx);
5661 GEN_LOAD_FREG_FTN(WT0, fs);
5662 gen_op_float_roundl_s();
5663 GEN_STORE_FTN_FREG(fd, DT2);
5664 opn = "round.l.s";
5665 break;
5666 case FOP(9, 16):
5667 check_cp1_64bitmode(ctx);
5668 GEN_LOAD_FREG_FTN(WT0, fs);
5669 gen_op_float_truncl_s();
5670 GEN_STORE_FTN_FREG(fd, DT2);
5671 opn = "trunc.l.s";
5672 break;
5673 case FOP(10, 16):
5674 check_cp1_64bitmode(ctx);
5675 GEN_LOAD_FREG_FTN(WT0, fs);
5676 gen_op_float_ceill_s();
5677 GEN_STORE_FTN_FREG(fd, DT2);
5678 opn = "ceil.l.s";
5679 break;
5680 case FOP(11, 16):
5681 check_cp1_64bitmode(ctx);
5682 GEN_LOAD_FREG_FTN(WT0, fs);
5683 gen_op_float_floorl_s();
5684 GEN_STORE_FTN_FREG(fd, DT2);
5685 opn = "floor.l.s";
5686 break;
5687 case FOP(12, 16):
5688 GEN_LOAD_FREG_FTN(WT0, fs);
5689 gen_op_float_roundw_s();
5690 GEN_STORE_FTN_FREG(fd, WT2);
5691 opn = "round.w.s";
5692 break;
5693 case FOP(13, 16):
5694 GEN_LOAD_FREG_FTN(WT0, fs);
5695 gen_op_float_truncw_s();
5696 GEN_STORE_FTN_FREG(fd, WT2);
5697 opn = "trunc.w.s";
5698 break;
5699 case FOP(14, 16):
5700 GEN_LOAD_FREG_FTN(WT0, fs);
5701 gen_op_float_ceilw_s();
5702 GEN_STORE_FTN_FREG(fd, WT2);
5703 opn = "ceil.w.s";
5704 break;
5705 case FOP(15, 16):
5706 GEN_LOAD_FREG_FTN(WT0, fs);
5707 gen_op_float_floorw_s();
5708 GEN_STORE_FTN_FREG(fd, WT2);
5709 opn = "floor.w.s";
5710 break;
5711 case FOP(17, 16):
5712 gen_load_gpr(cpu_T[0], ft);
5713 GEN_LOAD_FREG_FTN(WT0, fs);
5714 GEN_LOAD_FREG_FTN(WT2, fd);
5715 gen_movcf_s(ctx, (ft >> 2) & 0x7, ft & 0x1);
5716 GEN_STORE_FTN_FREG(fd, WT2);
5717 opn = "movcf.s";
5718 break;
5719 case FOP(18, 16):
5720 gen_load_gpr(cpu_T[0], ft);
5721 GEN_LOAD_FREG_FTN(WT0, fs);
5722 GEN_LOAD_FREG_FTN(WT2, fd);
5723 gen_op_float_movz_s();
5724 GEN_STORE_FTN_FREG(fd, WT2);
5725 opn = "movz.s";
5726 break;
5727 case FOP(19, 16):
5728 gen_load_gpr(cpu_T[0], ft);
5729 GEN_LOAD_FREG_FTN(WT0, fs);
5730 GEN_LOAD_FREG_FTN(WT2, fd);
5731 gen_op_float_movn_s();
5732 GEN_STORE_FTN_FREG(fd, WT2);
5733 opn = "movn.s";
5734 break;
5735 case FOP(21, 16):
5736 check_cop1x(ctx);
5737 GEN_LOAD_FREG_FTN(WT0, fs);
5738 gen_op_float_recip_s();
5739 GEN_STORE_FTN_FREG(fd, WT2);
5740 opn = "recip.s";
5741 break;
5742 case FOP(22, 16):
5743 check_cop1x(ctx);
5744 GEN_LOAD_FREG_FTN(WT0, fs);
5745 gen_op_float_rsqrt_s();
5746 GEN_STORE_FTN_FREG(fd, WT2);
5747 opn = "rsqrt.s";
5748 break;
5749 case FOP(28, 16):
5750 check_cp1_64bitmode(ctx);
5751 GEN_LOAD_FREG_FTN(WT0, fs);
5752 GEN_LOAD_FREG_FTN(WT2, fd);
5753 gen_op_float_recip2_s();
5754 GEN_STORE_FTN_FREG(fd, WT2);
5755 opn = "recip2.s";
5756 break;
5757 case FOP(29, 16):
5758 check_cp1_64bitmode(ctx);
5759 GEN_LOAD_FREG_FTN(WT0, fs);
5760 gen_op_float_recip1_s();
5761 GEN_STORE_FTN_FREG(fd, WT2);
5762 opn = "recip1.s";
5763 break;
5764 case FOP(30, 16):
5765 check_cp1_64bitmode(ctx);
5766 GEN_LOAD_FREG_FTN(WT0, fs);
5767 gen_op_float_rsqrt1_s();
5768 GEN_STORE_FTN_FREG(fd, WT2);
5769 opn = "rsqrt1.s";
5770 break;
5771 case FOP(31, 16):
5772 check_cp1_64bitmode(ctx);
5773 GEN_LOAD_FREG_FTN(WT0, fs);
5774 GEN_LOAD_FREG_FTN(WT2, ft);
5775 gen_op_float_rsqrt2_s();
5776 GEN_STORE_FTN_FREG(fd, WT2);
5777 opn = "rsqrt2.s";
5778 break;
5779 case FOP(33, 16):
5780 check_cp1_registers(ctx, fd);
5781 GEN_LOAD_FREG_FTN(WT0, fs);
5782 gen_op_float_cvtd_s();
5783 GEN_STORE_FTN_FREG(fd, DT2);
5784 opn = "cvt.d.s";
5785 break;
5786 case FOP(36, 16):
5787 GEN_LOAD_FREG_FTN(WT0, fs);
5788 gen_op_float_cvtw_s();
5789 GEN_STORE_FTN_FREG(fd, WT2);
5790 opn = "cvt.w.s";
5791 break;
5792 case FOP(37, 16):
5793 check_cp1_64bitmode(ctx);
5794 GEN_LOAD_FREG_FTN(WT0, fs);
5795 gen_op_float_cvtl_s();
5796 GEN_STORE_FTN_FREG(fd, DT2);
5797 opn = "cvt.l.s";
5798 break;
5799 case FOP(38, 16):
5800 check_cp1_64bitmode(ctx);
5801 GEN_LOAD_FREG_FTN(WT1, fs);
5802 GEN_LOAD_FREG_FTN(WT0, ft);
5803 gen_op_float_cvtps_s();
5804 GEN_STORE_FTN_FREG(fd, DT2);
5805 opn = "cvt.ps.s";
5806 break;
5807 case FOP(48, 16):
5808 case FOP(49, 16):
5809 case FOP(50, 16):
5810 case FOP(51, 16):
5811 case FOP(52, 16):
5812 case FOP(53, 16):
5813 case FOP(54, 16):
5814 case FOP(55, 16):
5815 case FOP(56, 16):
5816 case FOP(57, 16):
5817 case FOP(58, 16):
5818 case FOP(59, 16):
5819 case FOP(60, 16):
5820 case FOP(61, 16):
5821 case FOP(62, 16):
5822 case FOP(63, 16):
5823 GEN_LOAD_FREG_FTN(WT0, fs);
5824 GEN_LOAD_FREG_FTN(WT1, ft);
5825 if (ctx->opcode & (1 << 6)) {
5826 check_cop1x(ctx);
5827 gen_cmpabs_s(func-48, cc);
5828 opn = condnames_abs[func-48];
5829 } else {
5830 gen_cmp_s(func-48, cc);
5831 opn = condnames[func-48];
5833 break;
5834 case FOP(0, 17):
5835 check_cp1_registers(ctx, fs | ft | fd);
5836 GEN_LOAD_FREG_FTN(DT0, fs);
5837 GEN_LOAD_FREG_FTN(DT1, ft);
5838 gen_op_float_add_d();
5839 GEN_STORE_FTN_FREG(fd, DT2);
5840 opn = "add.d";
5841 optype = BINOP;
5842 break;
5843 case FOP(1, 17):
5844 check_cp1_registers(ctx, fs | ft | fd);
5845 GEN_LOAD_FREG_FTN(DT0, fs);
5846 GEN_LOAD_FREG_FTN(DT1, ft);
5847 gen_op_float_sub_d();
5848 GEN_STORE_FTN_FREG(fd, DT2);
5849 opn = "sub.d";
5850 optype = BINOP;
5851 break;
5852 case FOP(2, 17):
5853 check_cp1_registers(ctx, fs | ft | fd);
5854 GEN_LOAD_FREG_FTN(DT0, fs);
5855 GEN_LOAD_FREG_FTN(DT1, ft);
5856 gen_op_float_mul_d();
5857 GEN_STORE_FTN_FREG(fd, DT2);
5858 opn = "mul.d";
5859 optype = BINOP;
5860 break;
5861 case FOP(3, 17):
5862 check_cp1_registers(ctx, fs | ft | fd);
5863 GEN_LOAD_FREG_FTN(DT0, fs);
5864 GEN_LOAD_FREG_FTN(DT1, ft);
5865 gen_op_float_div_d();
5866 GEN_STORE_FTN_FREG(fd, DT2);
5867 opn = "div.d";
5868 optype = BINOP;
5869 break;
5870 case FOP(4, 17):
5871 check_cp1_registers(ctx, fs | fd);
5872 GEN_LOAD_FREG_FTN(DT0, fs);
5873 gen_op_float_sqrt_d();
5874 GEN_STORE_FTN_FREG(fd, DT2);
5875 opn = "sqrt.d";
5876 break;
5877 case FOP(5, 17):
5878 check_cp1_registers(ctx, fs | fd);
5879 GEN_LOAD_FREG_FTN(DT0, fs);
5880 gen_op_float_abs_d();
5881 GEN_STORE_FTN_FREG(fd, DT2);
5882 opn = "abs.d";
5883 break;
5884 case FOP(6, 17):
5885 check_cp1_registers(ctx, fs | fd);
5886 GEN_LOAD_FREG_FTN(DT0, fs);
5887 gen_op_float_mov_d();
5888 GEN_STORE_FTN_FREG(fd, DT2);
5889 opn = "mov.d";
5890 break;
5891 case FOP(7, 17):
5892 check_cp1_registers(ctx, fs | fd);
5893 GEN_LOAD_FREG_FTN(DT0, fs);
5894 gen_op_float_chs_d();
5895 GEN_STORE_FTN_FREG(fd, DT2);
5896 opn = "neg.d";
5897 break;
5898 case FOP(8, 17):
5899 check_cp1_64bitmode(ctx);
5900 GEN_LOAD_FREG_FTN(DT0, fs);
5901 gen_op_float_roundl_d();
5902 GEN_STORE_FTN_FREG(fd, DT2);
5903 opn = "round.l.d";
5904 break;
5905 case FOP(9, 17):
5906 check_cp1_64bitmode(ctx);
5907 GEN_LOAD_FREG_FTN(DT0, fs);
5908 gen_op_float_truncl_d();
5909 GEN_STORE_FTN_FREG(fd, DT2);
5910 opn = "trunc.l.d";
5911 break;
5912 case FOP(10, 17):
5913 check_cp1_64bitmode(ctx);
5914 GEN_LOAD_FREG_FTN(DT0, fs);
5915 gen_op_float_ceill_d();
5916 GEN_STORE_FTN_FREG(fd, DT2);
5917 opn = "ceil.l.d";
5918 break;
5919 case FOP(11, 17):
5920 check_cp1_64bitmode(ctx);
5921 GEN_LOAD_FREG_FTN(DT0, fs);
5922 gen_op_float_floorl_d();
5923 GEN_STORE_FTN_FREG(fd, DT2);
5924 opn = "floor.l.d";
5925 break;
5926 case FOP(12, 17):
5927 check_cp1_registers(ctx, fs);
5928 GEN_LOAD_FREG_FTN(DT0, fs);
5929 gen_op_float_roundw_d();
5930 GEN_STORE_FTN_FREG(fd, WT2);
5931 opn = "round.w.d";
5932 break;
5933 case FOP(13, 17):
5934 check_cp1_registers(ctx, fs);
5935 GEN_LOAD_FREG_FTN(DT0, fs);
5936 gen_op_float_truncw_d();
5937 GEN_STORE_FTN_FREG(fd, WT2);
5938 opn = "trunc.w.d";
5939 break;
5940 case FOP(14, 17):
5941 check_cp1_registers(ctx, fs);
5942 GEN_LOAD_FREG_FTN(DT0, fs);
5943 gen_op_float_ceilw_d();
5944 GEN_STORE_FTN_FREG(fd, WT2);
5945 opn = "ceil.w.d";
5946 break;
5947 case FOP(15, 17):
5948 check_cp1_registers(ctx, fs);
5949 GEN_LOAD_FREG_FTN(DT0, fs);
5950 gen_op_float_floorw_d();
5951 GEN_STORE_FTN_FREG(fd, WT2);
5952 opn = "floor.w.d";
5953 break;
5954 case FOP(17, 17):
5955 gen_load_gpr(cpu_T[0], ft);
5956 GEN_LOAD_FREG_FTN(DT0, fs);
5957 GEN_LOAD_FREG_FTN(DT2, fd);
5958 gen_movcf_d(ctx, (ft >> 2) & 0x7, ft & 0x1);
5959 GEN_STORE_FTN_FREG(fd, DT2);
5960 opn = "movcf.d";
5961 break;
5962 case FOP(18, 17):
5963 gen_load_gpr(cpu_T[0], ft);
5964 GEN_LOAD_FREG_FTN(DT0, fs);
5965 GEN_LOAD_FREG_FTN(DT2, fd);
5966 gen_op_float_movz_d();
5967 GEN_STORE_FTN_FREG(fd, DT2);
5968 opn = "movz.d";
5969 break;
5970 case FOP(19, 17):
5971 gen_load_gpr(cpu_T[0], ft);
5972 GEN_LOAD_FREG_FTN(DT0, fs);
5973 GEN_LOAD_FREG_FTN(DT2, fd);
5974 gen_op_float_movn_d();
5975 GEN_STORE_FTN_FREG(fd, DT2);
5976 opn = "movn.d";
5977 break;
5978 case FOP(21, 17):
5979 check_cp1_64bitmode(ctx);
5980 GEN_LOAD_FREG_FTN(DT0, fs);
5981 gen_op_float_recip_d();
5982 GEN_STORE_FTN_FREG(fd, DT2);
5983 opn = "recip.d";
5984 break;
5985 case FOP(22, 17):
5986 check_cp1_64bitmode(ctx);
5987 GEN_LOAD_FREG_FTN(DT0, fs);
5988 gen_op_float_rsqrt_d();
5989 GEN_STORE_FTN_FREG(fd, DT2);
5990 opn = "rsqrt.d";
5991 break;
5992 case FOP(28, 17):
5993 check_cp1_64bitmode(ctx);
5994 GEN_LOAD_FREG_FTN(DT0, fs);
5995 GEN_LOAD_FREG_FTN(DT2, ft);
5996 gen_op_float_recip2_d();
5997 GEN_STORE_FTN_FREG(fd, DT2);
5998 opn = "recip2.d";
5999 break;
6000 case FOP(29, 17):
6001 check_cp1_64bitmode(ctx);
6002 GEN_LOAD_FREG_FTN(DT0, fs);
6003 gen_op_float_recip1_d();
6004 GEN_STORE_FTN_FREG(fd, DT2);
6005 opn = "recip1.d";
6006 break;
6007 case FOP(30, 17):
6008 check_cp1_64bitmode(ctx);
6009 GEN_LOAD_FREG_FTN(DT0, fs);
6010 gen_op_float_rsqrt1_d();
6011 GEN_STORE_FTN_FREG(fd, DT2);
6012 opn = "rsqrt1.d";
6013 break;
6014 case FOP(31, 17):
6015 check_cp1_64bitmode(ctx);
6016 GEN_LOAD_FREG_FTN(DT0, fs);
6017 GEN_LOAD_FREG_FTN(DT2, ft);
6018 gen_op_float_rsqrt2_d();
6019 GEN_STORE_FTN_FREG(fd, DT2);
6020 opn = "rsqrt2.d";
6021 break;
6022 case FOP(48, 17):
6023 case FOP(49, 17):
6024 case FOP(50, 17):
6025 case FOP(51, 17):
6026 case FOP(52, 17):
6027 case FOP(53, 17):
6028 case FOP(54, 17):
6029 case FOP(55, 17):
6030 case FOP(56, 17):
6031 case FOP(57, 17):
6032 case FOP(58, 17):
6033 case FOP(59, 17):
6034 case FOP(60, 17):
6035 case FOP(61, 17):
6036 case FOP(62, 17):
6037 case FOP(63, 17):
6038 GEN_LOAD_FREG_FTN(DT0, fs);
6039 GEN_LOAD_FREG_FTN(DT1, ft);
6040 if (ctx->opcode & (1 << 6)) {
6041 check_cop1x(ctx);
6042 check_cp1_registers(ctx, fs | ft);
6043 gen_cmpabs_d(func-48, cc);
6044 opn = condnames_abs[func-48];
6045 } else {
6046 check_cp1_registers(ctx, fs | ft);
6047 gen_cmp_d(func-48, cc);
6048 opn = condnames[func-48];
6050 break;
6051 case FOP(32, 17):
6052 check_cp1_registers(ctx, fs);
6053 GEN_LOAD_FREG_FTN(DT0, fs);
6054 gen_op_float_cvts_d();
6055 GEN_STORE_FTN_FREG(fd, WT2);
6056 opn = "cvt.s.d";
6057 break;
6058 case FOP(36, 17):
6059 check_cp1_registers(ctx, fs);
6060 GEN_LOAD_FREG_FTN(DT0, fs);
6061 gen_op_float_cvtw_d();
6062 GEN_STORE_FTN_FREG(fd, WT2);
6063 opn = "cvt.w.d";
6064 break;
6065 case FOP(37, 17):
6066 check_cp1_64bitmode(ctx);
6067 GEN_LOAD_FREG_FTN(DT0, fs);
6068 gen_op_float_cvtl_d();
6069 GEN_STORE_FTN_FREG(fd, DT2);
6070 opn = "cvt.l.d";
6071 break;
6072 case FOP(32, 20):
6073 GEN_LOAD_FREG_FTN(WT0, fs);
6074 gen_op_float_cvts_w();
6075 GEN_STORE_FTN_FREG(fd, WT2);
6076 opn = "cvt.s.w";
6077 break;
6078 case FOP(33, 20):
6079 check_cp1_registers(ctx, fd);
6080 GEN_LOAD_FREG_FTN(WT0, fs);
6081 gen_op_float_cvtd_w();
6082 GEN_STORE_FTN_FREG(fd, DT2);
6083 opn = "cvt.d.w";
6084 break;
6085 case FOP(32, 21):
6086 check_cp1_64bitmode(ctx);
6087 GEN_LOAD_FREG_FTN(DT0, fs);
6088 gen_op_float_cvts_l();
6089 GEN_STORE_FTN_FREG(fd, WT2);
6090 opn = "cvt.s.l";
6091 break;
6092 case FOP(33, 21):
6093 check_cp1_64bitmode(ctx);
6094 GEN_LOAD_FREG_FTN(DT0, fs);
6095 gen_op_float_cvtd_l();
6096 GEN_STORE_FTN_FREG(fd, DT2);
6097 opn = "cvt.d.l";
6098 break;
6099 case FOP(38, 20):
6100 check_cp1_64bitmode(ctx);
6101 GEN_LOAD_FREG_FTN(WT0, fs);
6102 GEN_LOAD_FREG_FTN(WTH0, fs);
6103 gen_op_float_cvtps_pw();
6104 GEN_STORE_FTN_FREG(fd, WT2);
6105 GEN_STORE_FTN_FREG(fd, WTH2);
6106 opn = "cvt.ps.pw";
6107 break;
6108 case FOP(0, 22):
6109 check_cp1_64bitmode(ctx);
6110 GEN_LOAD_FREG_FTN(WT0, fs);
6111 GEN_LOAD_FREG_FTN(WTH0, fs);
6112 GEN_LOAD_FREG_FTN(WT1, ft);
6113 GEN_LOAD_FREG_FTN(WTH1, ft);
6114 gen_op_float_add_ps();
6115 GEN_STORE_FTN_FREG(fd, WT2);
6116 GEN_STORE_FTN_FREG(fd, WTH2);
6117 opn = "add.ps";
6118 break;
6119 case FOP(1, 22):
6120 check_cp1_64bitmode(ctx);
6121 GEN_LOAD_FREG_FTN(WT0, fs);
6122 GEN_LOAD_FREG_FTN(WTH0, fs);
6123 GEN_LOAD_FREG_FTN(WT1, ft);
6124 GEN_LOAD_FREG_FTN(WTH1, ft);
6125 gen_op_float_sub_ps();
6126 GEN_STORE_FTN_FREG(fd, WT2);
6127 GEN_STORE_FTN_FREG(fd, WTH2);
6128 opn = "sub.ps";
6129 break;
6130 case FOP(2, 22):
6131 check_cp1_64bitmode(ctx);
6132 GEN_LOAD_FREG_FTN(WT0, fs);
6133 GEN_LOAD_FREG_FTN(WTH0, fs);
6134 GEN_LOAD_FREG_FTN(WT1, ft);
6135 GEN_LOAD_FREG_FTN(WTH1, ft);
6136 gen_op_float_mul_ps();
6137 GEN_STORE_FTN_FREG(fd, WT2);
6138 GEN_STORE_FTN_FREG(fd, WTH2);
6139 opn = "mul.ps";
6140 break;
6141 case FOP(5, 22):
6142 check_cp1_64bitmode(ctx);
6143 GEN_LOAD_FREG_FTN(WT0, fs);
6144 GEN_LOAD_FREG_FTN(WTH0, fs);
6145 gen_op_float_abs_ps();
6146 GEN_STORE_FTN_FREG(fd, WT2);
6147 GEN_STORE_FTN_FREG(fd, WTH2);
6148 opn = "abs.ps";
6149 break;
6150 case FOP(6, 22):
6151 check_cp1_64bitmode(ctx);
6152 GEN_LOAD_FREG_FTN(WT0, fs);
6153 GEN_LOAD_FREG_FTN(WTH0, fs);
6154 gen_op_float_mov_ps();
6155 GEN_STORE_FTN_FREG(fd, WT2);
6156 GEN_STORE_FTN_FREG(fd, WTH2);
6157 opn = "mov.ps";
6158 break;
6159 case FOP(7, 22):
6160 check_cp1_64bitmode(ctx);
6161 GEN_LOAD_FREG_FTN(WT0, fs);
6162 GEN_LOAD_FREG_FTN(WTH0, fs);
6163 gen_op_float_chs_ps();
6164 GEN_STORE_FTN_FREG(fd, WT2);
6165 GEN_STORE_FTN_FREG(fd, WTH2);
6166 opn = "neg.ps";
6167 break;
6168 case FOP(17, 22):
6169 check_cp1_64bitmode(ctx);
6170 gen_load_gpr(cpu_T[0], ft);
6171 GEN_LOAD_FREG_FTN(WT0, fs);
6172 GEN_LOAD_FREG_FTN(WTH0, fs);
6173 GEN_LOAD_FREG_FTN(WT2, fd);
6174 GEN_LOAD_FREG_FTN(WTH2, fd);
6175 if (ft & 0x1)
6176 gen_op_float_movt_ps ((ft >> 2) & 0x7);
6177 else
6178 gen_op_float_movf_ps ((ft >> 2) & 0x7);
6179 GEN_STORE_FTN_FREG(fd, WT2);
6180 GEN_STORE_FTN_FREG(fd, WTH2);
6181 opn = "movcf.ps";
6182 break;
6183 case FOP(18, 22):
6184 check_cp1_64bitmode(ctx);
6185 gen_load_gpr(cpu_T[0], ft);
6186 GEN_LOAD_FREG_FTN(WT0, fs);
6187 GEN_LOAD_FREG_FTN(WTH0, fs);
6188 GEN_LOAD_FREG_FTN(WT2, fd);
6189 GEN_LOAD_FREG_FTN(WTH2, fd);
6190 gen_op_float_movz_ps();
6191 GEN_STORE_FTN_FREG(fd, WT2);
6192 GEN_STORE_FTN_FREG(fd, WTH2);
6193 opn = "movz.ps";
6194 break;
6195 case FOP(19, 22):
6196 check_cp1_64bitmode(ctx);
6197 gen_load_gpr(cpu_T[0], ft);
6198 GEN_LOAD_FREG_FTN(WT0, fs);
6199 GEN_LOAD_FREG_FTN(WTH0, fs);
6200 GEN_LOAD_FREG_FTN(WT2, fd);
6201 GEN_LOAD_FREG_FTN(WTH2, fd);
6202 gen_op_float_movn_ps();
6203 GEN_STORE_FTN_FREG(fd, WT2);
6204 GEN_STORE_FTN_FREG(fd, WTH2);
6205 opn = "movn.ps";
6206 break;
6207 case FOP(24, 22):
6208 check_cp1_64bitmode(ctx);
6209 GEN_LOAD_FREG_FTN(WT0, ft);
6210 GEN_LOAD_FREG_FTN(WTH0, ft);
6211 GEN_LOAD_FREG_FTN(WT1, fs);
6212 GEN_LOAD_FREG_FTN(WTH1, fs);
6213 gen_op_float_addr_ps();
6214 GEN_STORE_FTN_FREG(fd, WT2);
6215 GEN_STORE_FTN_FREG(fd, WTH2);
6216 opn = "addr.ps";
6217 break;
6218 case FOP(26, 22):
6219 check_cp1_64bitmode(ctx);
6220 GEN_LOAD_FREG_FTN(WT0, ft);
6221 GEN_LOAD_FREG_FTN(WTH0, ft);
6222 GEN_LOAD_FREG_FTN(WT1, fs);
6223 GEN_LOAD_FREG_FTN(WTH1, fs);
6224 gen_op_float_mulr_ps();
6225 GEN_STORE_FTN_FREG(fd, WT2);
6226 GEN_STORE_FTN_FREG(fd, WTH2);
6227 opn = "mulr.ps";
6228 break;
6229 case FOP(28, 22):
6230 check_cp1_64bitmode(ctx);
6231 GEN_LOAD_FREG_FTN(WT0, fs);
6232 GEN_LOAD_FREG_FTN(WTH0, fs);
6233 GEN_LOAD_FREG_FTN(WT2, fd);
6234 GEN_LOAD_FREG_FTN(WTH2, fd);
6235 gen_op_float_recip2_ps();
6236 GEN_STORE_FTN_FREG(fd, WT2);
6237 GEN_STORE_FTN_FREG(fd, WTH2);
6238 opn = "recip2.ps";
6239 break;
6240 case FOP(29, 22):
6241 check_cp1_64bitmode(ctx);
6242 GEN_LOAD_FREG_FTN(WT0, fs);
6243 GEN_LOAD_FREG_FTN(WTH0, fs);
6244 gen_op_float_recip1_ps();
6245 GEN_STORE_FTN_FREG(fd, WT2);
6246 GEN_STORE_FTN_FREG(fd, WTH2);
6247 opn = "recip1.ps";
6248 break;
6249 case FOP(30, 22):
6250 check_cp1_64bitmode(ctx);
6251 GEN_LOAD_FREG_FTN(WT0, fs);
6252 GEN_LOAD_FREG_FTN(WTH0, fs);
6253 gen_op_float_rsqrt1_ps();
6254 GEN_STORE_FTN_FREG(fd, WT2);
6255 GEN_STORE_FTN_FREG(fd, WTH2);
6256 opn = "rsqrt1.ps";
6257 break;
6258 case FOP(31, 22):
6259 check_cp1_64bitmode(ctx);
6260 GEN_LOAD_FREG_FTN(WT0, fs);
6261 GEN_LOAD_FREG_FTN(WTH0, fs);
6262 GEN_LOAD_FREG_FTN(WT2, ft);
6263 GEN_LOAD_FREG_FTN(WTH2, ft);
6264 gen_op_float_rsqrt2_ps();
6265 GEN_STORE_FTN_FREG(fd, WT2);
6266 GEN_STORE_FTN_FREG(fd, WTH2);
6267 opn = "rsqrt2.ps";
6268 break;
6269 case FOP(32, 22):
6270 check_cp1_64bitmode(ctx);
6271 GEN_LOAD_FREG_FTN(WTH0, fs);
6272 gen_op_float_cvts_pu();
6273 GEN_STORE_FTN_FREG(fd, WT2);
6274 opn = "cvt.s.pu";
6275 break;
6276 case FOP(36, 22):
6277 check_cp1_64bitmode(ctx);
6278 GEN_LOAD_FREG_FTN(WT0, fs);
6279 GEN_LOAD_FREG_FTN(WTH0, fs);
6280 gen_op_float_cvtpw_ps();
6281 GEN_STORE_FTN_FREG(fd, WT2);
6282 GEN_STORE_FTN_FREG(fd, WTH2);
6283 opn = "cvt.pw.ps";
6284 break;
6285 case FOP(40, 22):
6286 check_cp1_64bitmode(ctx);
6287 GEN_LOAD_FREG_FTN(WT0, fs);
6288 gen_op_float_cvts_pl();
6289 GEN_STORE_FTN_FREG(fd, WT2);
6290 opn = "cvt.s.pl";
6291 break;
6292 case FOP(44, 22):
6293 check_cp1_64bitmode(ctx);
6294 GEN_LOAD_FREG_FTN(WT0, fs);
6295 GEN_LOAD_FREG_FTN(WT1, ft);
6296 gen_op_float_pll_ps();
6297 GEN_STORE_FTN_FREG(fd, DT2);
6298 opn = "pll.ps";
6299 break;
6300 case FOP(45, 22):
6301 check_cp1_64bitmode(ctx);
6302 GEN_LOAD_FREG_FTN(WT0, fs);
6303 GEN_LOAD_FREG_FTN(WTH1, ft);
6304 gen_op_float_plu_ps();
6305 GEN_STORE_FTN_FREG(fd, DT2);
6306 opn = "plu.ps";
6307 break;
6308 case FOP(46, 22):
6309 check_cp1_64bitmode(ctx);
6310 GEN_LOAD_FREG_FTN(WTH0, fs);
6311 GEN_LOAD_FREG_FTN(WT1, ft);
6312 gen_op_float_pul_ps();
6313 GEN_STORE_FTN_FREG(fd, DT2);
6314 opn = "pul.ps";
6315 break;
6316 case FOP(47, 22):
6317 check_cp1_64bitmode(ctx);
6318 GEN_LOAD_FREG_FTN(WTH0, fs);
6319 GEN_LOAD_FREG_FTN(WTH1, ft);
6320 gen_op_float_puu_ps();
6321 GEN_STORE_FTN_FREG(fd, DT2);
6322 opn = "puu.ps";
6323 break;
6324 case FOP(48, 22):
6325 case FOP(49, 22):
6326 case FOP(50, 22):
6327 case FOP(51, 22):
6328 case FOP(52, 22):
6329 case FOP(53, 22):
6330 case FOP(54, 22):
6331 case FOP(55, 22):
6332 case FOP(56, 22):
6333 case FOP(57, 22):
6334 case FOP(58, 22):
6335 case FOP(59, 22):
6336 case FOP(60, 22):
6337 case FOP(61, 22):
6338 case FOP(62, 22):
6339 case FOP(63, 22):
6340 check_cp1_64bitmode(ctx);
6341 GEN_LOAD_FREG_FTN(WT0, fs);
6342 GEN_LOAD_FREG_FTN(WTH0, fs);
6343 GEN_LOAD_FREG_FTN(WT1, ft);
6344 GEN_LOAD_FREG_FTN(WTH1, ft);
6345 if (ctx->opcode & (1 << 6)) {
6346 gen_cmpabs_ps(func-48, cc);
6347 opn = condnames_abs[func-48];
6348 } else {
6349 gen_cmp_ps(func-48, cc);
6350 opn = condnames[func-48];
6352 break;
6353 default:
6354 MIPS_INVAL(opn);
6355 generate_exception (ctx, EXCP_RI);
6356 return;
6358 switch (optype) {
6359 case BINOP:
6360 MIPS_DEBUG("%s %s, %s, %s", opn, fregnames[fd], fregnames[fs], fregnames[ft]);
6361 break;
6362 case CMPOP:
6363 MIPS_DEBUG("%s %s,%s", opn, fregnames[fs], fregnames[ft]);
6364 break;
6365 default:
6366 MIPS_DEBUG("%s %s,%s", opn, fregnames[fd], fregnames[fs]);
6367 break;
6371 /* Coprocessor 3 (FPU) */
6372 static void gen_flt3_ldst (DisasContext *ctx, uint32_t opc,
6373 int fd, int fs, int base, int index)
6375 const char *opn = "extended float load/store";
6376 int store = 0;
6378 if (base == 0) {
6379 gen_load_gpr(cpu_T[0], index);
6380 } else if (index == 0) {
6381 gen_load_gpr(cpu_T[0], base);
6382 } else {
6383 gen_load_gpr(cpu_T[0], base);
6384 gen_load_gpr(cpu_T[1], index);
6385 gen_op_addr_add();
6387 /* Don't do NOP if destination is zero: we must perform the actual
6388 memory access. */
6389 switch (opc) {
6390 case OPC_LWXC1:
6391 check_cop1x(ctx);
6392 op_ldst_lwc1(ctx);
6393 GEN_STORE_FTN_FREG(fd, WT0);
6394 opn = "lwxc1";
6395 break;
6396 case OPC_LDXC1:
6397 check_cop1x(ctx);
6398 check_cp1_registers(ctx, fd);
6399 op_ldst_ldc1(ctx);
6400 GEN_STORE_FTN_FREG(fd, DT0);
6401 opn = "ldxc1";
6402 break;
6403 case OPC_LUXC1:
6404 check_cp1_64bitmode(ctx);
6405 op_ldst(luxc1);
6406 GEN_STORE_FTN_FREG(fd, DT0);
6407 opn = "luxc1";
6408 break;
6409 case OPC_SWXC1:
6410 check_cop1x(ctx);
6411 GEN_LOAD_FREG_FTN(WT0, fs);
6412 op_ldst_swc1(ctx);
6413 opn = "swxc1";
6414 store = 1;
6415 break;
6416 case OPC_SDXC1:
6417 check_cop1x(ctx);
6418 check_cp1_registers(ctx, fs);
6419 GEN_LOAD_FREG_FTN(DT0, fs);
6420 op_ldst_sdc1(ctx);
6421 opn = "sdxc1";
6422 store = 1;
6423 break;
6424 case OPC_SUXC1:
6425 check_cp1_64bitmode(ctx);
6426 GEN_LOAD_FREG_FTN(DT0, fs);
6427 op_ldst(suxc1);
6428 opn = "suxc1";
6429 store = 1;
6430 break;
6431 default:
6432 MIPS_INVAL(opn);
6433 generate_exception(ctx, EXCP_RI);
6434 return;
6436 MIPS_DEBUG("%s %s, %s(%s)", opn, fregnames[store ? fs : fd],
6437 regnames[index], regnames[base]);
6440 static void gen_flt3_arith (DisasContext *ctx, uint32_t opc,
6441 int fd, int fr, int fs, int ft)
6443 const char *opn = "flt3_arith";
6445 switch (opc) {
6446 case OPC_ALNV_PS:
6447 check_cp1_64bitmode(ctx);
6448 gen_load_gpr(cpu_T[0], fr);
6449 GEN_LOAD_FREG_FTN(DT0, fs);
6450 GEN_LOAD_FREG_FTN(DT1, ft);
6451 gen_op_float_alnv_ps();
6452 GEN_STORE_FTN_FREG(fd, DT2);
6453 opn = "alnv.ps";
6454 break;
6455 case OPC_MADD_S:
6456 check_cop1x(ctx);
6457 GEN_LOAD_FREG_FTN(WT0, fs);
6458 GEN_LOAD_FREG_FTN(WT1, ft);
6459 GEN_LOAD_FREG_FTN(WT2, fr);
6460 gen_op_float_muladd_s();
6461 GEN_STORE_FTN_FREG(fd, WT2);
6462 opn = "madd.s";
6463 break;
6464 case OPC_MADD_D:
6465 check_cop1x(ctx);
6466 check_cp1_registers(ctx, fd | fs | ft | fr);
6467 GEN_LOAD_FREG_FTN(DT0, fs);
6468 GEN_LOAD_FREG_FTN(DT1, ft);
6469 GEN_LOAD_FREG_FTN(DT2, fr);
6470 gen_op_float_muladd_d();
6471 GEN_STORE_FTN_FREG(fd, DT2);
6472 opn = "madd.d";
6473 break;
6474 case OPC_MADD_PS:
6475 check_cp1_64bitmode(ctx);
6476 GEN_LOAD_FREG_FTN(WT0, fs);
6477 GEN_LOAD_FREG_FTN(WTH0, fs);
6478 GEN_LOAD_FREG_FTN(WT1, ft);
6479 GEN_LOAD_FREG_FTN(WTH1, ft);
6480 GEN_LOAD_FREG_FTN(WT2, fr);
6481 GEN_LOAD_FREG_FTN(WTH2, fr);
6482 gen_op_float_muladd_ps();
6483 GEN_STORE_FTN_FREG(fd, WT2);
6484 GEN_STORE_FTN_FREG(fd, WTH2);
6485 opn = "madd.ps";
6486 break;
6487 case OPC_MSUB_S:
6488 check_cop1x(ctx);
6489 GEN_LOAD_FREG_FTN(WT0, fs);
6490 GEN_LOAD_FREG_FTN(WT1, ft);
6491 GEN_LOAD_FREG_FTN(WT2, fr);
6492 gen_op_float_mulsub_s();
6493 GEN_STORE_FTN_FREG(fd, WT2);
6494 opn = "msub.s";
6495 break;
6496 case OPC_MSUB_D:
6497 check_cop1x(ctx);
6498 check_cp1_registers(ctx, fd | fs | ft | fr);
6499 GEN_LOAD_FREG_FTN(DT0, fs);
6500 GEN_LOAD_FREG_FTN(DT1, ft);
6501 GEN_LOAD_FREG_FTN(DT2, fr);
6502 gen_op_float_mulsub_d();
6503 GEN_STORE_FTN_FREG(fd, DT2);
6504 opn = "msub.d";
6505 break;
6506 case OPC_MSUB_PS:
6507 check_cp1_64bitmode(ctx);
6508 GEN_LOAD_FREG_FTN(WT0, fs);
6509 GEN_LOAD_FREG_FTN(WTH0, fs);
6510 GEN_LOAD_FREG_FTN(WT1, ft);
6511 GEN_LOAD_FREG_FTN(WTH1, ft);
6512 GEN_LOAD_FREG_FTN(WT2, fr);
6513 GEN_LOAD_FREG_FTN(WTH2, fr);
6514 gen_op_float_mulsub_ps();
6515 GEN_STORE_FTN_FREG(fd, WT2);
6516 GEN_STORE_FTN_FREG(fd, WTH2);
6517 opn = "msub.ps";
6518 break;
6519 case OPC_NMADD_S:
6520 check_cop1x(ctx);
6521 GEN_LOAD_FREG_FTN(WT0, fs);
6522 GEN_LOAD_FREG_FTN(WT1, ft);
6523 GEN_LOAD_FREG_FTN(WT2, fr);
6524 gen_op_float_nmuladd_s();
6525 GEN_STORE_FTN_FREG(fd, WT2);
6526 opn = "nmadd.s";
6527 break;
6528 case OPC_NMADD_D:
6529 check_cop1x(ctx);
6530 check_cp1_registers(ctx, fd | fs | ft | fr);
6531 GEN_LOAD_FREG_FTN(DT0, fs);
6532 GEN_LOAD_FREG_FTN(DT1, ft);
6533 GEN_LOAD_FREG_FTN(DT2, fr);
6534 gen_op_float_nmuladd_d();
6535 GEN_STORE_FTN_FREG(fd, DT2);
6536 opn = "nmadd.d";
6537 break;
6538 case OPC_NMADD_PS:
6539 check_cp1_64bitmode(ctx);
6540 GEN_LOAD_FREG_FTN(WT0, fs);
6541 GEN_LOAD_FREG_FTN(WTH0, fs);
6542 GEN_LOAD_FREG_FTN(WT1, ft);
6543 GEN_LOAD_FREG_FTN(WTH1, ft);
6544 GEN_LOAD_FREG_FTN(WT2, fr);
6545 GEN_LOAD_FREG_FTN(WTH2, fr);
6546 gen_op_float_nmuladd_ps();
6547 GEN_STORE_FTN_FREG(fd, WT2);
6548 GEN_STORE_FTN_FREG(fd, WTH2);
6549 opn = "nmadd.ps";
6550 break;
6551 case OPC_NMSUB_S:
6552 check_cop1x(ctx);
6553 GEN_LOAD_FREG_FTN(WT0, fs);
6554 GEN_LOAD_FREG_FTN(WT1, ft);
6555 GEN_LOAD_FREG_FTN(WT2, fr);
6556 gen_op_float_nmulsub_s();
6557 GEN_STORE_FTN_FREG(fd, WT2);
6558 opn = "nmsub.s";
6559 break;
6560 case OPC_NMSUB_D:
6561 check_cop1x(ctx);
6562 check_cp1_registers(ctx, fd | fs | ft | fr);
6563 GEN_LOAD_FREG_FTN(DT0, fs);
6564 GEN_LOAD_FREG_FTN(DT1, ft);
6565 GEN_LOAD_FREG_FTN(DT2, fr);
6566 gen_op_float_nmulsub_d();
6567 GEN_STORE_FTN_FREG(fd, DT2);
6568 opn = "nmsub.d";
6569 break;
6570 case OPC_NMSUB_PS:
6571 check_cp1_64bitmode(ctx);
6572 GEN_LOAD_FREG_FTN(WT0, fs);
6573 GEN_LOAD_FREG_FTN(WTH0, fs);
6574 GEN_LOAD_FREG_FTN(WT1, ft);
6575 GEN_LOAD_FREG_FTN(WTH1, ft);
6576 GEN_LOAD_FREG_FTN(WT2, fr);
6577 GEN_LOAD_FREG_FTN(WTH2, fr);
6578 gen_op_float_nmulsub_ps();
6579 GEN_STORE_FTN_FREG(fd, WT2);
6580 GEN_STORE_FTN_FREG(fd, WTH2);
6581 opn = "nmsub.ps";
6582 break;
6583 default:
6584 MIPS_INVAL(opn);
6585 generate_exception (ctx, EXCP_RI);
6586 return;
6588 MIPS_DEBUG("%s %s, %s, %s, %s", opn, fregnames[fd], fregnames[fr],
6589 fregnames[fs], fregnames[ft]);
6592 /* ISA extensions (ASEs) */
6593 /* MIPS16 extension to MIPS32 */
6594 /* SmartMIPS extension to MIPS32 */
6596 #if defined(TARGET_MIPS64)
6598 /* MDMX extension to MIPS64 */
6600 #endif
6602 static void decode_opc (CPUState *env, DisasContext *ctx)
6604 int32_t offset;
6605 int rs, rt, rd, sa;
6606 uint32_t op, op1, op2;
6607 int16_t imm;
6609 /* make sure instructions are on a word boundary */
6610 if (ctx->pc & 0x3) {
6611 env->CP0_BadVAddr = ctx->pc;
6612 generate_exception(ctx, EXCP_AdEL);
6613 return;
6616 /* Handle blikely not taken case */
6617 if ((ctx->hflags & MIPS_HFLAG_BMASK) == MIPS_HFLAG_BL) {
6618 TCGv r_tmp = tcg_temp_local_new(TCG_TYPE_TL);
6619 int l1 = gen_new_label();
6621 MIPS_DEBUG("blikely condition (" TARGET_FMT_lx ")", ctx->pc + 4);
6622 tcg_gen_ld_tl(r_tmp, cpu_env, offsetof(CPUState, bcond));
6623 tcg_gen_brcondi_tl(TCG_COND_NE, r_tmp, 0, l1);
6624 tcg_temp_free(r_tmp);
6625 gen_op_save_state(ctx->hflags & ~MIPS_HFLAG_BMASK);
6626 gen_goto_tb(ctx, 1, ctx->pc + 4);
6627 gen_set_label(l1);
6629 op = MASK_OP_MAJOR(ctx->opcode);
6630 rs = (ctx->opcode >> 21) & 0x1f;
6631 rt = (ctx->opcode >> 16) & 0x1f;
6632 rd = (ctx->opcode >> 11) & 0x1f;
6633 sa = (ctx->opcode >> 6) & 0x1f;
6634 imm = (int16_t)ctx->opcode;
6635 switch (op) {
6636 case OPC_SPECIAL:
6637 op1 = MASK_SPECIAL(ctx->opcode);
6638 switch (op1) {
6639 case OPC_SLL: /* Arithmetic with immediate */
6640 case OPC_SRL ... OPC_SRA:
6641 gen_arith_imm(env, ctx, op1, rd, rt, sa);
6642 break;
6643 case OPC_MOVZ ... OPC_MOVN:
6644 check_insn(env, ctx, ISA_MIPS4 | ISA_MIPS32);
6645 case OPC_SLLV: /* Arithmetic */
6646 case OPC_SRLV ... OPC_SRAV:
6647 case OPC_ADD ... OPC_NOR:
6648 case OPC_SLT ... OPC_SLTU:
6649 gen_arith(env, ctx, op1, rd, rs, rt);
6650 break;
6651 case OPC_MULT ... OPC_DIVU:
6652 if (sa) {
6653 check_insn(env, ctx, INSN_VR54XX);
6654 op1 = MASK_MUL_VR54XX(ctx->opcode);
6655 gen_mul_vr54xx(ctx, op1, rd, rs, rt);
6656 } else
6657 gen_muldiv(ctx, op1, rs, rt);
6658 break;
6659 case OPC_JR ... OPC_JALR:
6660 gen_compute_branch(ctx, op1, rs, rd, sa);
6661 return;
6662 case OPC_TGE ... OPC_TEQ: /* Traps */
6663 case OPC_TNE:
6664 gen_trap(ctx, op1, rs, rt, -1);
6665 break;
6666 case OPC_MFHI: /* Move from HI/LO */
6667 case OPC_MFLO:
6668 gen_HILO(ctx, op1, rd);
6669 break;
6670 case OPC_MTHI:
6671 case OPC_MTLO: /* Move to HI/LO */
6672 gen_HILO(ctx, op1, rs);
6673 break;
6674 case OPC_PMON: /* Pmon entry point, also R4010 selsl */
6675 #ifdef MIPS_STRICT_STANDARD
6676 MIPS_INVAL("PMON / selsl");
6677 generate_exception(ctx, EXCP_RI);
6678 #else
6679 gen_op_pmon(sa);
6680 #endif
6681 break;
6682 case OPC_SYSCALL:
6683 generate_exception(ctx, EXCP_SYSCALL);
6684 break;
6685 case OPC_BREAK:
6686 generate_exception(ctx, EXCP_BREAK);
6687 break;
6688 case OPC_SPIM:
6689 #ifdef MIPS_STRICT_STANDARD
6690 MIPS_INVAL("SPIM");
6691 generate_exception(ctx, EXCP_RI);
6692 #else
6693 /* Implemented as RI exception for now. */
6694 MIPS_INVAL("spim (unofficial)");
6695 generate_exception(ctx, EXCP_RI);
6696 #endif
6697 break;
6698 case OPC_SYNC:
6699 /* Treat as NOP. */
6700 break;
6702 case OPC_MOVCI:
6703 check_insn(env, ctx, ISA_MIPS4 | ISA_MIPS32);
6704 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
6705 save_cpu_state(ctx, 1);
6706 check_cp1_enabled(ctx);
6707 gen_movci(ctx, rd, rs, (ctx->opcode >> 18) & 0x7,
6708 (ctx->opcode >> 16) & 1);
6709 } else {
6710 generate_exception_err(ctx, EXCP_CpU, 1);
6712 break;
6714 #if defined(TARGET_MIPS64)
6715 /* MIPS64 specific opcodes */
6716 case OPC_DSLL:
6717 case OPC_DSRL ... OPC_DSRA:
6718 case OPC_DSLL32:
6719 case OPC_DSRL32 ... OPC_DSRA32:
6720 check_insn(env, ctx, ISA_MIPS3);
6721 check_mips_64(ctx);
6722 gen_arith_imm(env, ctx, op1, rd, rt, sa);
6723 break;
6724 case OPC_DSLLV:
6725 case OPC_DSRLV ... OPC_DSRAV:
6726 case OPC_DADD ... OPC_DSUBU:
6727 check_insn(env, ctx, ISA_MIPS3);
6728 check_mips_64(ctx);
6729 gen_arith(env, ctx, op1, rd, rs, rt);
6730 break;
6731 case OPC_DMULT ... OPC_DDIVU:
6732 check_insn(env, ctx, ISA_MIPS3);
6733 check_mips_64(ctx);
6734 gen_muldiv(ctx, op1, rs, rt);
6735 break;
6736 #endif
6737 default: /* Invalid */
6738 MIPS_INVAL("special");
6739 generate_exception(ctx, EXCP_RI);
6740 break;
6742 break;
6743 case OPC_SPECIAL2:
6744 op1 = MASK_SPECIAL2(ctx->opcode);
6745 switch (op1) {
6746 case OPC_MADD ... OPC_MADDU: /* Multiply and add/sub */
6747 case OPC_MSUB ... OPC_MSUBU:
6748 check_insn(env, ctx, ISA_MIPS32);
6749 gen_muldiv(ctx, op1, rs, rt);
6750 break;
6751 case OPC_MUL:
6752 gen_arith(env, ctx, op1, rd, rs, rt);
6753 break;
6754 case OPC_CLZ ... OPC_CLO:
6755 check_insn(env, ctx, ISA_MIPS32);
6756 gen_cl(ctx, op1, rd, rs);
6757 break;
6758 case OPC_SDBBP:
6759 /* XXX: not clear which exception should be raised
6760 * when in debug mode...
6762 check_insn(env, ctx, ISA_MIPS32);
6763 if (!(ctx->hflags & MIPS_HFLAG_DM)) {
6764 generate_exception(ctx, EXCP_DBp);
6765 } else {
6766 generate_exception(ctx, EXCP_DBp);
6768 /* Treat as NOP. */
6769 break;
6770 #if defined(TARGET_MIPS64)
6771 case OPC_DCLZ ... OPC_DCLO:
6772 check_insn(env, ctx, ISA_MIPS64);
6773 check_mips_64(ctx);
6774 gen_cl(ctx, op1, rd, rs);
6775 break;
6776 #endif
6777 default: /* Invalid */
6778 MIPS_INVAL("special2");
6779 generate_exception(ctx, EXCP_RI);
6780 break;
6782 break;
6783 case OPC_SPECIAL3:
6784 op1 = MASK_SPECIAL3(ctx->opcode);
6785 switch (op1) {
6786 case OPC_EXT:
6787 case OPC_INS:
6788 check_insn(env, ctx, ISA_MIPS32R2);
6789 gen_bitops(ctx, op1, rt, rs, sa, rd);
6790 break;
6791 case OPC_BSHFL:
6792 check_insn(env, ctx, ISA_MIPS32R2);
6793 op2 = MASK_BSHFL(ctx->opcode);
6794 switch (op2) {
6795 case OPC_WSBH:
6796 gen_load_gpr(cpu_T[1], rt);
6797 gen_op_wsbh();
6798 break;
6799 case OPC_SEB:
6800 gen_load_gpr(cpu_T[1], rt);
6801 tcg_gen_ext8s_tl(cpu_T[0], cpu_T[1]);
6802 break;
6803 case OPC_SEH:
6804 gen_load_gpr(cpu_T[1], rt);
6805 tcg_gen_ext16s_tl(cpu_T[0], cpu_T[1]);
6806 break;
6807 default: /* Invalid */
6808 MIPS_INVAL("bshfl");
6809 generate_exception(ctx, EXCP_RI);
6810 break;
6812 gen_store_gpr(cpu_T[0], rd);
6813 break;
6814 case OPC_RDHWR:
6815 check_insn(env, ctx, ISA_MIPS32R2);
6816 switch (rd) {
6817 case 0:
6818 save_cpu_state(ctx, 1);
6819 gen_op_rdhwr_cpunum();
6820 break;
6821 case 1:
6822 save_cpu_state(ctx, 1);
6823 gen_op_rdhwr_synci_step();
6824 break;
6825 case 2:
6826 save_cpu_state(ctx, 1);
6827 gen_op_rdhwr_cc();
6828 break;
6829 case 3:
6830 save_cpu_state(ctx, 1);
6831 gen_op_rdhwr_ccres();
6832 break;
6833 case 29:
6834 #if defined (CONFIG_USER_ONLY)
6835 gen_op_tls_value();
6836 break;
6837 #endif
6838 default: /* Invalid */
6839 MIPS_INVAL("rdhwr");
6840 generate_exception(ctx, EXCP_RI);
6841 break;
6843 gen_store_gpr(cpu_T[0], rt);
6844 break;
6845 case OPC_FORK:
6846 check_insn(env, ctx, ASE_MT);
6847 gen_load_gpr(cpu_T[0], rt);
6848 gen_load_gpr(cpu_T[1], rs);
6849 gen_op_fork();
6850 break;
6851 case OPC_YIELD:
6852 check_insn(env, ctx, ASE_MT);
6853 gen_load_gpr(cpu_T[0], rs);
6854 gen_op_yield();
6855 gen_store_gpr(cpu_T[0], rd);
6856 break;
6857 #if defined(TARGET_MIPS64)
6858 case OPC_DEXTM ... OPC_DEXT:
6859 case OPC_DINSM ... OPC_DINS:
6860 check_insn(env, ctx, ISA_MIPS64R2);
6861 check_mips_64(ctx);
6862 gen_bitops(ctx, op1, rt, rs, sa, rd);
6863 break;
6864 case OPC_DBSHFL:
6865 check_insn(env, ctx, ISA_MIPS64R2);
6866 check_mips_64(ctx);
6867 op2 = MASK_DBSHFL(ctx->opcode);
6868 switch (op2) {
6869 case OPC_DSBH:
6870 gen_load_gpr(cpu_T[1], rt);
6871 gen_op_dsbh();
6872 break;
6873 case OPC_DSHD:
6874 gen_load_gpr(cpu_T[1], rt);
6875 gen_op_dshd();
6876 break;
6877 default: /* Invalid */
6878 MIPS_INVAL("dbshfl");
6879 generate_exception(ctx, EXCP_RI);
6880 break;
6882 gen_store_gpr(cpu_T[0], rd);
6883 break;
6884 #endif
6885 default: /* Invalid */
6886 MIPS_INVAL("special3");
6887 generate_exception(ctx, EXCP_RI);
6888 break;
6890 break;
6891 case OPC_REGIMM:
6892 op1 = MASK_REGIMM(ctx->opcode);
6893 switch (op1) {
6894 case OPC_BLTZ ... OPC_BGEZL: /* REGIMM branches */
6895 case OPC_BLTZAL ... OPC_BGEZALL:
6896 gen_compute_branch(ctx, op1, rs, -1, imm << 2);
6897 return;
6898 case OPC_TGEI ... OPC_TEQI: /* REGIMM traps */
6899 case OPC_TNEI:
6900 gen_trap(ctx, op1, rs, -1, imm);
6901 break;
6902 case OPC_SYNCI:
6903 check_insn(env, ctx, ISA_MIPS32R2);
6904 /* Treat as NOP. */
6905 break;
6906 default: /* Invalid */
6907 MIPS_INVAL("regimm");
6908 generate_exception(ctx, EXCP_RI);
6909 break;
6911 break;
6912 case OPC_CP0:
6913 check_cp0_enabled(ctx);
6914 op1 = MASK_CP0(ctx->opcode);
6915 switch (op1) {
6916 case OPC_MFC0:
6917 case OPC_MTC0:
6918 case OPC_MFTR:
6919 case OPC_MTTR:
6920 #if defined(TARGET_MIPS64)
6921 case OPC_DMFC0:
6922 case OPC_DMTC0:
6923 #endif
6924 gen_cp0(env, ctx, op1, rt, rd);
6925 break;
6926 case OPC_C0_FIRST ... OPC_C0_LAST:
6927 gen_cp0(env, ctx, MASK_C0(ctx->opcode), rt, rd);
6928 break;
6929 case OPC_MFMC0:
6930 op2 = MASK_MFMC0(ctx->opcode);
6931 switch (op2) {
6932 case OPC_DMT:
6933 check_insn(env, ctx, ASE_MT);
6934 gen_op_dmt();
6935 break;
6936 case OPC_EMT:
6937 check_insn(env, ctx, ASE_MT);
6938 gen_op_emt();
6939 break;
6940 case OPC_DVPE:
6941 check_insn(env, ctx, ASE_MT);
6942 gen_op_dvpe();
6943 break;
6944 case OPC_EVPE:
6945 check_insn(env, ctx, ASE_MT);
6946 gen_op_evpe();
6947 break;
6948 case OPC_DI:
6949 check_insn(env, ctx, ISA_MIPS32R2);
6950 save_cpu_state(ctx, 1);
6951 gen_op_di();
6952 /* Stop translation as we may have switched the execution mode */
6953 ctx->bstate = BS_STOP;
6954 break;
6955 case OPC_EI:
6956 check_insn(env, ctx, ISA_MIPS32R2);
6957 save_cpu_state(ctx, 1);
6958 gen_op_ei();
6959 /* Stop translation as we may have switched the execution mode */
6960 ctx->bstate = BS_STOP;
6961 break;
6962 default: /* Invalid */
6963 MIPS_INVAL("mfmc0");
6964 generate_exception(ctx, EXCP_RI);
6965 break;
6967 gen_store_gpr(cpu_T[0], rt);
6968 break;
6969 case OPC_RDPGPR:
6970 check_insn(env, ctx, ISA_MIPS32R2);
6971 gen_load_srsgpr(cpu_T[0], rt);
6972 gen_store_gpr(cpu_T[0], rd);
6973 break;
6974 case OPC_WRPGPR:
6975 check_insn(env, ctx, ISA_MIPS32R2);
6976 gen_load_gpr(cpu_T[0], rt);
6977 gen_store_srsgpr(cpu_T[0], rd);
6978 break;
6979 default:
6980 MIPS_INVAL("cp0");
6981 generate_exception(ctx, EXCP_RI);
6982 break;
6984 break;
6985 case OPC_ADDI ... OPC_LUI: /* Arithmetic with immediate opcode */
6986 gen_arith_imm(env, ctx, op, rt, rs, imm);
6987 break;
6988 case OPC_J ... OPC_JAL: /* Jump */
6989 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2;
6990 gen_compute_branch(ctx, op, rs, rt, offset);
6991 return;
6992 case OPC_BEQ ... OPC_BGTZ: /* Branch */
6993 case OPC_BEQL ... OPC_BGTZL:
6994 gen_compute_branch(ctx, op, rs, rt, imm << 2);
6995 return;
6996 case OPC_LB ... OPC_LWR: /* Load and stores */
6997 case OPC_SB ... OPC_SW:
6998 case OPC_SWR:
6999 case OPC_LL:
7000 case OPC_SC:
7001 gen_ldst(ctx, op, rt, rs, imm);
7002 break;
7003 case OPC_CACHE:
7004 check_insn(env, ctx, ISA_MIPS3 | ISA_MIPS32);
7005 /* Treat as NOP. */
7006 break;
7007 case OPC_PREF:
7008 check_insn(env, ctx, ISA_MIPS4 | ISA_MIPS32);
7009 /* Treat as NOP. */
7010 break;
7012 /* Floating point (COP1). */
7013 case OPC_LWC1:
7014 case OPC_LDC1:
7015 case OPC_SWC1:
7016 case OPC_SDC1:
7017 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
7018 save_cpu_state(ctx, 1);
7019 check_cp1_enabled(ctx);
7020 gen_flt_ldst(ctx, op, rt, rs, imm);
7021 } else {
7022 generate_exception_err(ctx, EXCP_CpU, 1);
7024 break;
7026 case OPC_CP1:
7027 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
7028 save_cpu_state(ctx, 1);
7029 check_cp1_enabled(ctx);
7030 op1 = MASK_CP1(ctx->opcode);
7031 switch (op1) {
7032 case OPC_MFHC1:
7033 case OPC_MTHC1:
7034 check_insn(env, ctx, ISA_MIPS32R2);
7035 case OPC_MFC1:
7036 case OPC_CFC1:
7037 case OPC_MTC1:
7038 case OPC_CTC1:
7039 gen_cp1(ctx, op1, rt, rd);
7040 break;
7041 #if defined(TARGET_MIPS64)
7042 case OPC_DMFC1:
7043 case OPC_DMTC1:
7044 check_insn(env, ctx, ISA_MIPS3);
7045 gen_cp1(ctx, op1, rt, rd);
7046 break;
7047 #endif
7048 case OPC_BC1ANY2:
7049 case OPC_BC1ANY4:
7050 check_cop1x(ctx);
7051 check_insn(env, ctx, ASE_MIPS3D);
7052 /* fall through */
7053 case OPC_BC1:
7054 gen_compute_branch1(env, ctx, MASK_BC1(ctx->opcode),
7055 (rt >> 2) & 0x7, imm << 2);
7056 return;
7057 case OPC_S_FMT:
7058 case OPC_D_FMT:
7059 case OPC_W_FMT:
7060 case OPC_L_FMT:
7061 case OPC_PS_FMT:
7062 gen_farith(ctx, MASK_CP1_FUNC(ctx->opcode), rt, rd, sa,
7063 (imm >> 8) & 0x7);
7064 break;
7065 default:
7066 MIPS_INVAL("cp1");
7067 generate_exception (ctx, EXCP_RI);
7068 break;
7070 } else {
7071 generate_exception_err(ctx, EXCP_CpU, 1);
7073 break;
7075 /* COP2. */
7076 case OPC_LWC2:
7077 case OPC_LDC2:
7078 case OPC_SWC2:
7079 case OPC_SDC2:
7080 case OPC_CP2:
7081 /* COP2: Not implemented. */
7082 generate_exception_err(ctx, EXCP_CpU, 2);
7083 break;
7085 case OPC_CP3:
7086 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
7087 save_cpu_state(ctx, 1);
7088 check_cp1_enabled(ctx);
7089 op1 = MASK_CP3(ctx->opcode);
7090 switch (op1) {
7091 case OPC_LWXC1:
7092 case OPC_LDXC1:
7093 case OPC_LUXC1:
7094 case OPC_SWXC1:
7095 case OPC_SDXC1:
7096 case OPC_SUXC1:
7097 gen_flt3_ldst(ctx, op1, sa, rd, rs, rt);
7098 break;
7099 case OPC_PREFX:
7100 /* Treat as NOP. */
7101 break;
7102 case OPC_ALNV_PS:
7103 case OPC_MADD_S:
7104 case OPC_MADD_D:
7105 case OPC_MADD_PS:
7106 case OPC_MSUB_S:
7107 case OPC_MSUB_D:
7108 case OPC_MSUB_PS:
7109 case OPC_NMADD_S:
7110 case OPC_NMADD_D:
7111 case OPC_NMADD_PS:
7112 case OPC_NMSUB_S:
7113 case OPC_NMSUB_D:
7114 case OPC_NMSUB_PS:
7115 gen_flt3_arith(ctx, op1, sa, rs, rd, rt);
7116 break;
7117 default:
7118 MIPS_INVAL("cp3");
7119 generate_exception (ctx, EXCP_RI);
7120 break;
7122 } else {
7123 generate_exception_err(ctx, EXCP_CpU, 1);
7125 break;
7127 #if defined(TARGET_MIPS64)
7128 /* MIPS64 opcodes */
7129 case OPC_LWU:
7130 case OPC_LDL ... OPC_LDR:
7131 case OPC_SDL ... OPC_SDR:
7132 case OPC_LLD:
7133 case OPC_LD:
7134 case OPC_SCD:
7135 case OPC_SD:
7136 check_insn(env, ctx, ISA_MIPS3);
7137 check_mips_64(ctx);
7138 gen_ldst(ctx, op, rt, rs, imm);
7139 break;
7140 case OPC_DADDI ... OPC_DADDIU:
7141 check_insn(env, ctx, ISA_MIPS3);
7142 check_mips_64(ctx);
7143 gen_arith_imm(env, ctx, op, rt, rs, imm);
7144 break;
7145 #endif
7146 case OPC_JALX:
7147 check_insn(env, ctx, ASE_MIPS16);
7148 /* MIPS16: Not implemented. */
7149 case OPC_MDMX:
7150 check_insn(env, ctx, ASE_MDMX);
7151 /* MDMX: Not implemented. */
7152 default: /* Invalid */
7153 MIPS_INVAL("major opcode");
7154 generate_exception(ctx, EXCP_RI);
7155 break;
7157 if (ctx->hflags & MIPS_HFLAG_BMASK) {
7158 int hflags = ctx->hflags & MIPS_HFLAG_BMASK;
7159 /* Branches completion */
7160 ctx->hflags &= ~MIPS_HFLAG_BMASK;
7161 ctx->bstate = BS_BRANCH;
7162 save_cpu_state(ctx, 0);
7163 switch (hflags) {
7164 case MIPS_HFLAG_B:
7165 /* unconditional branch */
7166 MIPS_DEBUG("unconditional branch");
7167 gen_goto_tb(ctx, 0, ctx->btarget);
7168 break;
7169 case MIPS_HFLAG_BL:
7170 /* blikely taken case */
7171 MIPS_DEBUG("blikely branch taken");
7172 gen_goto_tb(ctx, 0, ctx->btarget);
7173 break;
7174 case MIPS_HFLAG_BC:
7175 /* Conditional branch */
7176 MIPS_DEBUG("conditional branch");
7178 TCGv r_tmp = tcg_temp_local_new(TCG_TYPE_TL);
7179 int l1 = gen_new_label();
7181 tcg_gen_ld_tl(r_tmp, cpu_env, offsetof(CPUState, bcond));
7182 tcg_gen_brcondi_tl(TCG_COND_NE, r_tmp, 0, l1);
7183 tcg_temp_free(r_tmp);
7184 gen_goto_tb(ctx, 1, ctx->pc + 4);
7185 gen_set_label(l1);
7186 gen_goto_tb(ctx, 0, ctx->btarget);
7188 break;
7189 case MIPS_HFLAG_BR:
7190 /* unconditional branch to register */
7191 MIPS_DEBUG("branch to register");
7192 gen_breg_pc();
7193 tcg_gen_exit_tb(0);
7194 break;
7195 default:
7196 MIPS_DEBUG("unknown branch");
7197 break;
7202 static always_inline int
7203 gen_intermediate_code_internal (CPUState *env, TranslationBlock *tb,
7204 int search_pc)
7206 DisasContext ctx;
7207 target_ulong pc_start;
7208 uint16_t *gen_opc_end;
7209 int j, lj = -1;
7211 if (search_pc && loglevel)
7212 fprintf (logfile, "search pc %d\n", search_pc);
7214 pc_start = tb->pc;
7215 gen_opc_end = gen_opc_buf + OPC_MAX_SIZE;
7216 ctx.pc = pc_start;
7217 ctx.saved_pc = -1;
7218 ctx.tb = tb;
7219 ctx.bstate = BS_NONE;
7220 /* Restore delay slot state from the tb context. */
7221 ctx.hflags = (uint32_t)tb->flags; /* FIXME: maybe use 64 bits here? */
7222 restore_cpu_state(env, &ctx);
7223 #if defined(CONFIG_USER_ONLY)
7224 ctx.mem_idx = MIPS_HFLAG_UM;
7225 #else
7226 ctx.mem_idx = ctx.hflags & MIPS_HFLAG_KSU;
7227 #endif
7228 #ifdef DEBUG_DISAS
7229 if (loglevel & CPU_LOG_TB_CPU) {
7230 fprintf(logfile, "------------------------------------------------\n");
7231 /* FIXME: This may print out stale hflags from env... */
7232 cpu_dump_state(env, logfile, fprintf, 0);
7234 #endif
7235 #ifdef MIPS_DEBUG_DISAS
7236 if (loglevel & CPU_LOG_TB_IN_ASM)
7237 fprintf(logfile, "\ntb %p idx %d hflags %04x\n",
7238 tb, ctx.mem_idx, ctx.hflags);
7239 #endif
7240 while (ctx.bstate == BS_NONE && gen_opc_ptr < gen_opc_end) {
7241 if (env->nb_breakpoints > 0) {
7242 for(j = 0; j < env->nb_breakpoints; j++) {
7243 if (env->breakpoints[j] == ctx.pc) {
7244 save_cpu_state(&ctx, 1);
7245 ctx.bstate = BS_BRANCH;
7246 gen_op_debug();
7247 /* Include the breakpoint location or the tb won't
7248 * be flushed when it must be. */
7249 ctx.pc += 4;
7250 goto done_generating;
7255 if (search_pc) {
7256 j = gen_opc_ptr - gen_opc_buf;
7257 if (lj < j) {
7258 lj++;
7259 while (lj < j)
7260 gen_opc_instr_start[lj++] = 0;
7262 gen_opc_pc[lj] = ctx.pc;
7263 gen_opc_hflags[lj] = ctx.hflags & MIPS_HFLAG_BMASK;
7264 gen_opc_instr_start[lj] = 1;
7266 ctx.opcode = ldl_code(ctx.pc);
7267 decode_opc(env, &ctx);
7268 ctx.pc += 4;
7270 if (env->singlestep_enabled)
7271 break;
7273 if ((ctx.pc & (TARGET_PAGE_SIZE - 1)) == 0)
7274 break;
7276 #if defined (MIPS_SINGLE_STEP)
7277 break;
7278 #endif
7280 if (env->singlestep_enabled) {
7281 save_cpu_state(&ctx, ctx.bstate == BS_NONE);
7282 gen_op_debug();
7283 } else {
7284 switch (ctx.bstate) {
7285 case BS_STOP:
7286 tcg_gen_helper_0_0(do_interrupt_restart);
7287 gen_goto_tb(&ctx, 0, ctx.pc);
7288 break;
7289 case BS_NONE:
7290 save_cpu_state(&ctx, 0);
7291 gen_goto_tb(&ctx, 0, ctx.pc);
7292 break;
7293 case BS_EXCP:
7294 tcg_gen_helper_0_0(do_interrupt_restart);
7295 tcg_gen_exit_tb(0);
7296 break;
7297 case BS_BRANCH:
7298 default:
7299 break;
7302 done_generating:
7303 *gen_opc_ptr = INDEX_op_end;
7304 if (search_pc) {
7305 j = gen_opc_ptr - gen_opc_buf;
7306 lj++;
7307 while (lj <= j)
7308 gen_opc_instr_start[lj++] = 0;
7309 } else {
7310 tb->size = ctx.pc - pc_start;
7312 #ifdef DEBUG_DISAS
7313 #if defined MIPS_DEBUG_DISAS
7314 if (loglevel & CPU_LOG_TB_IN_ASM)
7315 fprintf(logfile, "\n");
7316 #endif
7317 if (loglevel & CPU_LOG_TB_IN_ASM) {
7318 fprintf(logfile, "IN: %s\n", lookup_symbol(pc_start));
7319 target_disas(logfile, pc_start, ctx.pc - pc_start, 0);
7320 fprintf(logfile, "\n");
7322 if (loglevel & CPU_LOG_TB_CPU) {
7323 fprintf(logfile, "---------------- %d %08x\n", ctx.bstate, ctx.hflags);
7325 #endif
7327 return 0;
7330 int gen_intermediate_code (CPUState *env, struct TranslationBlock *tb)
7332 return gen_intermediate_code_internal(env, tb, 0);
7335 int gen_intermediate_code_pc (CPUState *env, struct TranslationBlock *tb)
7337 return gen_intermediate_code_internal(env, tb, 1);
7340 void fpu_dump_state(CPUState *env, FILE *f,
7341 int (*fpu_fprintf)(FILE *f, const char *fmt, ...),
7342 int flags)
7344 int i;
7345 int is_fpu64 = !!(env->hflags & MIPS_HFLAG_F64);
7347 #define printfpr(fp) \
7348 do { \
7349 if (is_fpu64) \
7350 fpu_fprintf(f, "w:%08x d:%016lx fd:%13g fs:%13g psu: %13g\n", \
7351 (fp)->w[FP_ENDIAN_IDX], (fp)->d, (fp)->fd, \
7352 (fp)->fs[FP_ENDIAN_IDX], (fp)->fs[!FP_ENDIAN_IDX]); \
7353 else { \
7354 fpr_t tmp; \
7355 tmp.w[FP_ENDIAN_IDX] = (fp)->w[FP_ENDIAN_IDX]; \
7356 tmp.w[!FP_ENDIAN_IDX] = ((fp) + 1)->w[FP_ENDIAN_IDX]; \
7357 fpu_fprintf(f, "w:%08x d:%016lx fd:%13g fs:%13g psu:%13g\n", \
7358 tmp.w[FP_ENDIAN_IDX], tmp.d, tmp.fd, \
7359 tmp.fs[FP_ENDIAN_IDX], tmp.fs[!FP_ENDIAN_IDX]); \
7361 } while(0)
7364 fpu_fprintf(f, "CP1 FCR0 0x%08x FCR31 0x%08x SR.FR %d fp_status 0x%08x(0x%02x)\n",
7365 env->fpu->fcr0, env->fpu->fcr31, is_fpu64, env->fpu->fp_status,
7366 get_float_exception_flags(&env->fpu->fp_status));
7367 fpu_fprintf(f, "FT0: "); printfpr(&env->fpu->ft0);
7368 fpu_fprintf(f, "FT1: "); printfpr(&env->fpu->ft1);
7369 fpu_fprintf(f, "FT2: "); printfpr(&env->fpu->ft2);
7370 for (i = 0; i < 32; (is_fpu64) ? i++ : (i += 2)) {
7371 fpu_fprintf(f, "%3s: ", fregnames[i]);
7372 printfpr(&env->fpu->fpr[i]);
7375 #undef printfpr
7378 void dump_fpu (CPUState *env)
7380 if (loglevel) {
7381 fprintf(logfile,
7382 "pc=0x" TARGET_FMT_lx " HI=0x" TARGET_FMT_lx
7383 " LO=0x" TARGET_FMT_lx " ds %04x " TARGET_FMT_lx
7384 " %04x\n",
7385 env->PC[env->current_tc], env->HI[env->current_tc][0],
7386 env->LO[env->current_tc][0], env->hflags, env->btarget,
7387 env->bcond);
7388 fpu_dump_state(env, logfile, fprintf, 0);
7392 #if defined(TARGET_MIPS64) && defined(MIPS_DEBUG_SIGN_EXTENSIONS)
7393 /* Debug help: The architecture requires 32bit code to maintain proper
7394 sign-extened values on 64bit machines. */
7396 #define SIGN_EXT_P(val) ((((val) & ~0x7fffffff) == 0) || (((val) & ~0x7fffffff) == ~0x7fffffff))
7398 void cpu_mips_check_sign_extensions (CPUState *env, FILE *f,
7399 int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
7400 int flags)
7402 int i;
7404 if (!SIGN_EXT_P(env->PC[env->current_tc]))
7405 cpu_fprintf(f, "BROKEN: pc=0x" TARGET_FMT_lx "\n", env->PC[env->current_tc]);
7406 if (!SIGN_EXT_P(env->HI[env->current_tc][0]))
7407 cpu_fprintf(f, "BROKEN: HI=0x" TARGET_FMT_lx "\n", env->HI[env->current_tc][0]);
7408 if (!SIGN_EXT_P(env->LO[env->current_tc][0]))
7409 cpu_fprintf(f, "BROKEN: LO=0x" TARGET_FMT_lx "\n", env->LO[env->current_tc][0]);
7410 if (!SIGN_EXT_P(env->btarget))
7411 cpu_fprintf(f, "BROKEN: btarget=0x" TARGET_FMT_lx "\n", env->btarget);
7413 for (i = 0; i < 32; i++) {
7414 if (!SIGN_EXT_P(env->gpr[env->current_tc][i]))
7415 cpu_fprintf(f, "BROKEN: %s=0x" TARGET_FMT_lx "\n", regnames[i], env->gpr[env->current_tc][i]);
7418 if (!SIGN_EXT_P(env->CP0_EPC))
7419 cpu_fprintf(f, "BROKEN: EPC=0x" TARGET_FMT_lx "\n", env->CP0_EPC);
7420 if (!SIGN_EXT_P(env->CP0_LLAddr))
7421 cpu_fprintf(f, "BROKEN: LLAddr=0x" TARGET_FMT_lx "\n", env->CP0_LLAddr);
7423 #endif
7425 void cpu_dump_state (CPUState *env, FILE *f,
7426 int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
7427 int flags)
7429 int i;
7431 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",
7432 env->PC[env->current_tc], env->HI[env->current_tc], env->LO[env->current_tc], env->hflags, env->btarget, env->bcond);
7433 for (i = 0; i < 32; i++) {
7434 if ((i & 3) == 0)
7435 cpu_fprintf(f, "GPR%02d:", i);
7436 cpu_fprintf(f, " %s " TARGET_FMT_lx, regnames[i], env->gpr[env->current_tc][i]);
7437 if ((i & 3) == 3)
7438 cpu_fprintf(f, "\n");
7441 cpu_fprintf(f, "CP0 Status 0x%08x Cause 0x%08x EPC 0x" TARGET_FMT_lx "\n",
7442 env->CP0_Status, env->CP0_Cause, env->CP0_EPC);
7443 cpu_fprintf(f, " Config0 0x%08x Config1 0x%08x LLAddr 0x" TARGET_FMT_lx "\n",
7444 env->CP0_Config0, env->CP0_Config1, env->CP0_LLAddr);
7445 if (env->hflags & MIPS_HFLAG_FPU)
7446 fpu_dump_state(env, f, cpu_fprintf, flags);
7447 #if defined(TARGET_MIPS64) && defined(MIPS_DEBUG_SIGN_EXTENSIONS)
7448 cpu_mips_check_sign_extensions(env, f, cpu_fprintf, flags);
7449 #endif
7452 static void mips_tcg_init(void)
7454 static int inited;
7456 /* Initialize various static tables. */
7457 if (inited)
7458 return;
7460 cpu_env = tcg_global_reg_new(TCG_TYPE_PTR, TCG_AREG0, "env");
7461 current_tc_gprs = tcg_global_mem_new(TCG_TYPE_PTR,
7462 TCG_AREG0,
7463 offsetof(CPUState, current_tc_gprs),
7464 "current_tc_gprs");
7465 current_tc_hi = tcg_global_mem_new(TCG_TYPE_PTR,
7466 TCG_AREG0,
7467 offsetof(CPUState, current_tc_hi),
7468 "current_tc_hi");
7469 #if TARGET_LONG_BITS > HOST_LONG_BITS
7470 cpu_T[0] = tcg_global_mem_new(TCG_TYPE_TL,
7471 TCG_AREG0, offsetof(CPUState, t0), "T0");
7472 cpu_T[1] = tcg_global_mem_new(TCG_TYPE_TL,
7473 TCG_AREG0, offsetof(CPUState, t1), "T1");
7474 #else
7475 cpu_T[0] = tcg_global_reg_new(TCG_TYPE_TL, TCG_AREG1, "T0");
7476 cpu_T[1] = tcg_global_reg_new(TCG_TYPE_TL, TCG_AREG2, "T1");
7477 #endif
7479 inited = 1;
7482 #include "translate_init.c"
7484 CPUMIPSState *cpu_mips_init (const char *cpu_model)
7486 CPUMIPSState *env;
7487 const mips_def_t *def;
7489 def = cpu_mips_find_by_name(cpu_model);
7490 if (!def)
7491 return NULL;
7492 env = qemu_mallocz(sizeof(CPUMIPSState));
7493 if (!env)
7494 return NULL;
7495 env->cpu_model = def;
7497 cpu_exec_init(env);
7498 env->cpu_model_str = cpu_model;
7499 mips_tcg_init();
7500 cpu_reset(env);
7501 return env;
7504 void cpu_reset (CPUMIPSState *env)
7506 memset(env, 0, offsetof(CPUMIPSState, breakpoints));
7508 tlb_flush(env, 1);
7510 /* Minimal init */
7511 #if !defined(CONFIG_USER_ONLY)
7512 if (env->hflags & MIPS_HFLAG_BMASK) {
7513 /* If the exception was raised from a delay slot,
7514 * come back to the jump. */
7515 env->CP0_ErrorEPC = env->PC[env->current_tc] - 4;
7516 } else {
7517 env->CP0_ErrorEPC = env->PC[env->current_tc];
7519 env->PC[env->current_tc] = (int32_t)0xBFC00000;
7520 env->CP0_Wired = 0;
7521 /* SMP not implemented */
7522 env->CP0_EBase = 0x80000000;
7523 env->CP0_Status = (1 << CP0St_BEV) | (1 << CP0St_ERL);
7524 /* vectored interrupts not implemented, timer on int 7,
7525 no performance counters. */
7526 env->CP0_IntCtl = 0xe0000000;
7528 int i;
7530 for (i = 0; i < 7; i++) {
7531 env->CP0_WatchLo[i] = 0;
7532 env->CP0_WatchHi[i] = 0x80000000;
7534 env->CP0_WatchLo[7] = 0;
7535 env->CP0_WatchHi[7] = 0;
7537 /* Count register increments in debug mode, EJTAG version 1 */
7538 env->CP0_Debug = (1 << CP0DB_CNT) | (0x1 << CP0DB_VER);
7539 #endif
7540 env->exception_index = EXCP_NONE;
7541 #if defined(CONFIG_USER_ONLY)
7542 env->hflags = MIPS_HFLAG_UM;
7543 env->user_mode_only = 1;
7544 #else
7545 env->hflags = MIPS_HFLAG_CP0;
7546 #endif
7547 cpu_mips_register(env, env->cpu_model);
7550 void gen_pc_load(CPUState *env, TranslationBlock *tb,
7551 unsigned long searched_pc, int pc_pos, void *puc)
7553 env->PC[env->current_tc] = gen_opc_pc[pc_pos];
7554 env->hflags &= ~MIPS_HFLAG_BMASK;
7555 env->hflags |= gen_opc_hflags[pc_pos];