qemu-img: Fix copy+paste bug in documentation
[qemu/qemu-dev-zwu.git] / target-mips / translate.c
blob7168273381fb4741cf7f1e0bad41508381208989
1 /*
2 * MIPS32 emulation for qemu: main translation routines.
4 * Copyright (c) 2004-2005 Jocelyn Mayer
5 * Copyright (c) 2006 Marius Groeger (FPU operations)
6 * Copyright (c) 2006 Thiemo Seufer (MIPS32R2 support)
7 * Copyright (c) 2009 CodeSourcery (MIPS16 and microMIPS support)
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation; either
12 * version 2 of the License, or (at your option) any later version.
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
23 #include <stdarg.h>
24 #include <stdlib.h>
25 #include <stdio.h>
26 #include <string.h>
27 #include <inttypes.h>
29 #include "cpu.h"
30 #include "exec-all.h"
31 #include "disas.h"
32 #include "tcg-op.h"
33 #include "qemu-common.h"
35 #include "helper.h"
36 #define GEN_HELPER 1
37 #include "helper.h"
39 //#define MIPS_DEBUG_DISAS
40 //#define MIPS_DEBUG_SIGN_EXTENSIONS
42 /* MIPS major opcodes */
43 #define MASK_OP_MAJOR(op) (op & (0x3F << 26))
45 enum {
46 /* indirect opcode tables */
47 OPC_SPECIAL = (0x00 << 26),
48 OPC_REGIMM = (0x01 << 26),
49 OPC_CP0 = (0x10 << 26),
50 OPC_CP1 = (0x11 << 26),
51 OPC_CP2 = (0x12 << 26),
52 OPC_CP3 = (0x13 << 26),
53 OPC_SPECIAL2 = (0x1C << 26),
54 OPC_SPECIAL3 = (0x1F << 26),
55 /* arithmetic with immediate */
56 OPC_ADDI = (0x08 << 26),
57 OPC_ADDIU = (0x09 << 26),
58 OPC_SLTI = (0x0A << 26),
59 OPC_SLTIU = (0x0B << 26),
60 /* logic with immediate */
61 OPC_ANDI = (0x0C << 26),
62 OPC_ORI = (0x0D << 26),
63 OPC_XORI = (0x0E << 26),
64 OPC_LUI = (0x0F << 26),
65 /* arithmetic with immediate */
66 OPC_DADDI = (0x18 << 26),
67 OPC_DADDIU = (0x19 << 26),
68 /* Jump and branches */
69 OPC_J = (0x02 << 26),
70 OPC_JAL = (0x03 << 26),
71 OPC_JALS = OPC_JAL | 0x5,
72 OPC_BEQ = (0x04 << 26), /* Unconditional if rs = rt = 0 (B) */
73 OPC_BEQL = (0x14 << 26),
74 OPC_BNE = (0x05 << 26),
75 OPC_BNEL = (0x15 << 26),
76 OPC_BLEZ = (0x06 << 26),
77 OPC_BLEZL = (0x16 << 26),
78 OPC_BGTZ = (0x07 << 26),
79 OPC_BGTZL = (0x17 << 26),
80 OPC_JALX = (0x1D << 26), /* MIPS 16 only */
81 OPC_JALXS = OPC_JALX | 0x5,
82 /* Load and stores */
83 OPC_LDL = (0x1A << 26),
84 OPC_LDR = (0x1B << 26),
85 OPC_LB = (0x20 << 26),
86 OPC_LH = (0x21 << 26),
87 OPC_LWL = (0x22 << 26),
88 OPC_LW = (0x23 << 26),
89 OPC_LWPC = OPC_LW | 0x5,
90 OPC_LBU = (0x24 << 26),
91 OPC_LHU = (0x25 << 26),
92 OPC_LWR = (0x26 << 26),
93 OPC_LWU = (0x27 << 26),
94 OPC_SB = (0x28 << 26),
95 OPC_SH = (0x29 << 26),
96 OPC_SWL = (0x2A << 26),
97 OPC_SW = (0x2B << 26),
98 OPC_SDL = (0x2C << 26),
99 OPC_SDR = (0x2D << 26),
100 OPC_SWR = (0x2E << 26),
101 OPC_LL = (0x30 << 26),
102 OPC_LLD = (0x34 << 26),
103 OPC_LD = (0x37 << 26),
104 OPC_LDPC = OPC_LD | 0x5,
105 OPC_SC = (0x38 << 26),
106 OPC_SCD = (0x3C << 26),
107 OPC_SD = (0x3F << 26),
108 /* Floating point load/store */
109 OPC_LWC1 = (0x31 << 26),
110 OPC_LWC2 = (0x32 << 26),
111 OPC_LDC1 = (0x35 << 26),
112 OPC_LDC2 = (0x36 << 26),
113 OPC_SWC1 = (0x39 << 26),
114 OPC_SWC2 = (0x3A << 26),
115 OPC_SDC1 = (0x3D << 26),
116 OPC_SDC2 = (0x3E << 26),
117 /* MDMX ASE specific */
118 OPC_MDMX = (0x1E << 26),
119 /* Cache and prefetch */
120 OPC_CACHE = (0x2F << 26),
121 OPC_PREF = (0x33 << 26),
122 /* Reserved major opcode */
123 OPC_MAJOR3B_RESERVED = (0x3B << 26),
126 /* MIPS special opcodes */
127 #define MASK_SPECIAL(op) MASK_OP_MAJOR(op) | (op & 0x3F)
129 enum {
130 /* Shifts */
131 OPC_SLL = 0x00 | OPC_SPECIAL,
132 /* NOP is SLL r0, r0, 0 */
133 /* SSNOP is SLL r0, r0, 1 */
134 /* EHB is SLL r0, r0, 3 */
135 OPC_SRL = 0x02 | OPC_SPECIAL, /* also ROTR */
136 OPC_ROTR = OPC_SRL | (1 << 21),
137 OPC_SRA = 0x03 | OPC_SPECIAL,
138 OPC_SLLV = 0x04 | OPC_SPECIAL,
139 OPC_SRLV = 0x06 | OPC_SPECIAL, /* also ROTRV */
140 OPC_ROTRV = OPC_SRLV | (1 << 6),
141 OPC_SRAV = 0x07 | OPC_SPECIAL,
142 OPC_DSLLV = 0x14 | OPC_SPECIAL,
143 OPC_DSRLV = 0x16 | OPC_SPECIAL, /* also DROTRV */
144 OPC_DROTRV = OPC_DSRLV | (1 << 6),
145 OPC_DSRAV = 0x17 | OPC_SPECIAL,
146 OPC_DSLL = 0x38 | OPC_SPECIAL,
147 OPC_DSRL = 0x3A | OPC_SPECIAL, /* also DROTR */
148 OPC_DROTR = OPC_DSRL | (1 << 21),
149 OPC_DSRA = 0x3B | OPC_SPECIAL,
150 OPC_DSLL32 = 0x3C | OPC_SPECIAL,
151 OPC_DSRL32 = 0x3E | OPC_SPECIAL, /* also DROTR32 */
152 OPC_DROTR32 = OPC_DSRL32 | (1 << 21),
153 OPC_DSRA32 = 0x3F | OPC_SPECIAL,
154 /* Multiplication / division */
155 OPC_MULT = 0x18 | OPC_SPECIAL,
156 OPC_MULTU = 0x19 | OPC_SPECIAL,
157 OPC_DIV = 0x1A | OPC_SPECIAL,
158 OPC_DIVU = 0x1B | OPC_SPECIAL,
159 OPC_DMULT = 0x1C | OPC_SPECIAL,
160 OPC_DMULTU = 0x1D | OPC_SPECIAL,
161 OPC_DDIV = 0x1E | OPC_SPECIAL,
162 OPC_DDIVU = 0x1F | OPC_SPECIAL,
163 /* 2 registers arithmetic / logic */
164 OPC_ADD = 0x20 | OPC_SPECIAL,
165 OPC_ADDU = 0x21 | OPC_SPECIAL,
166 OPC_SUB = 0x22 | OPC_SPECIAL,
167 OPC_SUBU = 0x23 | OPC_SPECIAL,
168 OPC_AND = 0x24 | OPC_SPECIAL,
169 OPC_OR = 0x25 | OPC_SPECIAL,
170 OPC_XOR = 0x26 | OPC_SPECIAL,
171 OPC_NOR = 0x27 | OPC_SPECIAL,
172 OPC_SLT = 0x2A | OPC_SPECIAL,
173 OPC_SLTU = 0x2B | OPC_SPECIAL,
174 OPC_DADD = 0x2C | OPC_SPECIAL,
175 OPC_DADDU = 0x2D | OPC_SPECIAL,
176 OPC_DSUB = 0x2E | OPC_SPECIAL,
177 OPC_DSUBU = 0x2F | OPC_SPECIAL,
178 /* Jumps */
179 OPC_JR = 0x08 | OPC_SPECIAL, /* Also JR.HB */
180 OPC_JALR = 0x09 | OPC_SPECIAL, /* Also JALR.HB */
181 OPC_JALRC = OPC_JALR | (0x5 << 6),
182 OPC_JALRS = 0x10 | OPC_SPECIAL | (0x5 << 6),
183 /* Traps */
184 OPC_TGE = 0x30 | OPC_SPECIAL,
185 OPC_TGEU = 0x31 | OPC_SPECIAL,
186 OPC_TLT = 0x32 | OPC_SPECIAL,
187 OPC_TLTU = 0x33 | OPC_SPECIAL,
188 OPC_TEQ = 0x34 | OPC_SPECIAL,
189 OPC_TNE = 0x36 | OPC_SPECIAL,
190 /* HI / LO registers load & stores */
191 OPC_MFHI = 0x10 | OPC_SPECIAL,
192 OPC_MTHI = 0x11 | OPC_SPECIAL,
193 OPC_MFLO = 0x12 | OPC_SPECIAL,
194 OPC_MTLO = 0x13 | OPC_SPECIAL,
195 /* Conditional moves */
196 OPC_MOVZ = 0x0A | OPC_SPECIAL,
197 OPC_MOVN = 0x0B | OPC_SPECIAL,
199 OPC_MOVCI = 0x01 | OPC_SPECIAL,
201 /* Special */
202 OPC_PMON = 0x05 | OPC_SPECIAL, /* unofficial */
203 OPC_SYSCALL = 0x0C | OPC_SPECIAL,
204 OPC_BREAK = 0x0D | OPC_SPECIAL,
205 OPC_SPIM = 0x0E | OPC_SPECIAL, /* unofficial */
206 OPC_SYNC = 0x0F | OPC_SPECIAL,
208 OPC_SPECIAL15_RESERVED = 0x15 | OPC_SPECIAL,
209 OPC_SPECIAL28_RESERVED = 0x28 | OPC_SPECIAL,
210 OPC_SPECIAL29_RESERVED = 0x29 | OPC_SPECIAL,
211 OPC_SPECIAL35_RESERVED = 0x35 | OPC_SPECIAL,
212 OPC_SPECIAL37_RESERVED = 0x37 | OPC_SPECIAL,
213 OPC_SPECIAL39_RESERVED = 0x39 | OPC_SPECIAL,
214 OPC_SPECIAL3D_RESERVED = 0x3D | OPC_SPECIAL,
217 /* Multiplication variants of the vr54xx. */
218 #define MASK_MUL_VR54XX(op) MASK_SPECIAL(op) | (op & (0x1F << 6))
220 enum {
221 OPC_VR54XX_MULS = (0x03 << 6) | OPC_MULT,
222 OPC_VR54XX_MULSU = (0x03 << 6) | OPC_MULTU,
223 OPC_VR54XX_MACC = (0x05 << 6) | OPC_MULT,
224 OPC_VR54XX_MACCU = (0x05 << 6) | OPC_MULTU,
225 OPC_VR54XX_MSAC = (0x07 << 6) | OPC_MULT,
226 OPC_VR54XX_MSACU = (0x07 << 6) | OPC_MULTU,
227 OPC_VR54XX_MULHI = (0x09 << 6) | OPC_MULT,
228 OPC_VR54XX_MULHIU = (0x09 << 6) | OPC_MULTU,
229 OPC_VR54XX_MULSHI = (0x0B << 6) | OPC_MULT,
230 OPC_VR54XX_MULSHIU = (0x0B << 6) | OPC_MULTU,
231 OPC_VR54XX_MACCHI = (0x0D << 6) | OPC_MULT,
232 OPC_VR54XX_MACCHIU = (0x0D << 6) | OPC_MULTU,
233 OPC_VR54XX_MSACHI = (0x0F << 6) | OPC_MULT,
234 OPC_VR54XX_MSACHIU = (0x0F << 6) | OPC_MULTU,
237 /* REGIMM (rt field) opcodes */
238 #define MASK_REGIMM(op) MASK_OP_MAJOR(op) | (op & (0x1F << 16))
240 enum {
241 OPC_BLTZ = (0x00 << 16) | OPC_REGIMM,
242 OPC_BLTZL = (0x02 << 16) | OPC_REGIMM,
243 OPC_BGEZ = (0x01 << 16) | OPC_REGIMM,
244 OPC_BGEZL = (0x03 << 16) | OPC_REGIMM,
245 OPC_BLTZAL = (0x10 << 16) | OPC_REGIMM,
246 OPC_BLTZALS = OPC_BLTZAL | 0x5, /* microMIPS */
247 OPC_BLTZALL = (0x12 << 16) | OPC_REGIMM,
248 OPC_BGEZAL = (0x11 << 16) | OPC_REGIMM,
249 OPC_BGEZALS = OPC_BGEZAL | 0x5, /* microMIPS */
250 OPC_BGEZALL = (0x13 << 16) | OPC_REGIMM,
251 OPC_TGEI = (0x08 << 16) | OPC_REGIMM,
252 OPC_TGEIU = (0x09 << 16) | OPC_REGIMM,
253 OPC_TLTI = (0x0A << 16) | OPC_REGIMM,
254 OPC_TLTIU = (0x0B << 16) | OPC_REGIMM,
255 OPC_TEQI = (0x0C << 16) | OPC_REGIMM,
256 OPC_TNEI = (0x0E << 16) | OPC_REGIMM,
257 OPC_SYNCI = (0x1F << 16) | OPC_REGIMM,
260 /* Special2 opcodes */
261 #define MASK_SPECIAL2(op) MASK_OP_MAJOR(op) | (op & 0x3F)
263 enum {
264 /* Multiply & xxx operations */
265 OPC_MADD = 0x00 | OPC_SPECIAL2,
266 OPC_MADDU = 0x01 | OPC_SPECIAL2,
267 OPC_MUL = 0x02 | OPC_SPECIAL2,
268 OPC_MSUB = 0x04 | OPC_SPECIAL2,
269 OPC_MSUBU = 0x05 | OPC_SPECIAL2,
270 /* Loongson 2F */
271 OPC_MULT_G_2F = 0x10 | OPC_SPECIAL2,
272 OPC_DMULT_G_2F = 0x11 | OPC_SPECIAL2,
273 OPC_MULTU_G_2F = 0x12 | OPC_SPECIAL2,
274 OPC_DMULTU_G_2F = 0x13 | OPC_SPECIAL2,
275 OPC_DIV_G_2F = 0x14 | OPC_SPECIAL2,
276 OPC_DDIV_G_2F = 0x15 | OPC_SPECIAL2,
277 OPC_DIVU_G_2F = 0x16 | OPC_SPECIAL2,
278 OPC_DDIVU_G_2F = 0x17 | OPC_SPECIAL2,
279 OPC_MOD_G_2F = 0x1c | OPC_SPECIAL2,
280 OPC_DMOD_G_2F = 0x1d | OPC_SPECIAL2,
281 OPC_MODU_G_2F = 0x1e | OPC_SPECIAL2,
282 OPC_DMODU_G_2F = 0x1f | OPC_SPECIAL2,
283 /* Misc */
284 OPC_CLZ = 0x20 | OPC_SPECIAL2,
285 OPC_CLO = 0x21 | OPC_SPECIAL2,
286 OPC_DCLZ = 0x24 | OPC_SPECIAL2,
287 OPC_DCLO = 0x25 | OPC_SPECIAL2,
288 /* Special */
289 OPC_SDBBP = 0x3F | OPC_SPECIAL2,
292 /* Special3 opcodes */
293 #define MASK_SPECIAL3(op) MASK_OP_MAJOR(op) | (op & 0x3F)
295 enum {
296 OPC_EXT = 0x00 | OPC_SPECIAL3,
297 OPC_DEXTM = 0x01 | OPC_SPECIAL3,
298 OPC_DEXTU = 0x02 | OPC_SPECIAL3,
299 OPC_DEXT = 0x03 | OPC_SPECIAL3,
300 OPC_INS = 0x04 | OPC_SPECIAL3,
301 OPC_DINSM = 0x05 | OPC_SPECIAL3,
302 OPC_DINSU = 0x06 | OPC_SPECIAL3,
303 OPC_DINS = 0x07 | OPC_SPECIAL3,
304 OPC_FORK = 0x08 | OPC_SPECIAL3,
305 OPC_YIELD = 0x09 | OPC_SPECIAL3,
306 OPC_BSHFL = 0x20 | OPC_SPECIAL3,
307 OPC_DBSHFL = 0x24 | OPC_SPECIAL3,
308 OPC_RDHWR = 0x3B | OPC_SPECIAL3,
310 /* Loongson 2E */
311 OPC_MULT_G_2E = 0x18 | OPC_SPECIAL3,
312 OPC_MULTU_G_2E = 0x19 | OPC_SPECIAL3,
313 OPC_DIV_G_2E = 0x1A | OPC_SPECIAL3,
314 OPC_DIVU_G_2E = 0x1B | OPC_SPECIAL3,
315 OPC_DMULT_G_2E = 0x1C | OPC_SPECIAL3,
316 OPC_DMULTU_G_2E = 0x1D | OPC_SPECIAL3,
317 OPC_DDIV_G_2E = 0x1E | OPC_SPECIAL3,
318 OPC_DDIVU_G_2E = 0x1F | OPC_SPECIAL3,
319 OPC_MOD_G_2E = 0x22 | OPC_SPECIAL3,
320 OPC_MODU_G_2E = 0x23 | OPC_SPECIAL3,
321 OPC_DMOD_G_2E = 0x26 | OPC_SPECIAL3,
322 OPC_DMODU_G_2E = 0x27 | OPC_SPECIAL3,
325 /* BSHFL opcodes */
326 #define MASK_BSHFL(op) MASK_SPECIAL3(op) | (op & (0x1F << 6))
328 enum {
329 OPC_WSBH = (0x02 << 6) | OPC_BSHFL,
330 OPC_SEB = (0x10 << 6) | OPC_BSHFL,
331 OPC_SEH = (0x18 << 6) | OPC_BSHFL,
334 /* DBSHFL opcodes */
335 #define MASK_DBSHFL(op) MASK_SPECIAL3(op) | (op & (0x1F << 6))
337 enum {
338 OPC_DSBH = (0x02 << 6) | OPC_DBSHFL,
339 OPC_DSHD = (0x05 << 6) | OPC_DBSHFL,
342 /* Coprocessor 0 (rs field) */
343 #define MASK_CP0(op) MASK_OP_MAJOR(op) | (op & (0x1F << 21))
345 enum {
346 OPC_MFC0 = (0x00 << 21) | OPC_CP0,
347 OPC_DMFC0 = (0x01 << 21) | OPC_CP0,
348 OPC_MTC0 = (0x04 << 21) | OPC_CP0,
349 OPC_DMTC0 = (0x05 << 21) | OPC_CP0,
350 OPC_MFTR = (0x08 << 21) | OPC_CP0,
351 OPC_RDPGPR = (0x0A << 21) | OPC_CP0,
352 OPC_MFMC0 = (0x0B << 21) | OPC_CP0,
353 OPC_MTTR = (0x0C << 21) | OPC_CP0,
354 OPC_WRPGPR = (0x0E << 21) | OPC_CP0,
355 OPC_C0 = (0x10 << 21) | OPC_CP0,
356 OPC_C0_FIRST = (0x10 << 21) | OPC_CP0,
357 OPC_C0_LAST = (0x1F << 21) | OPC_CP0,
360 /* MFMC0 opcodes */
361 #define MASK_MFMC0(op) MASK_CP0(op) | (op & 0xFFFF)
363 enum {
364 OPC_DMT = 0x01 | (0 << 5) | (0x0F << 6) | (0x01 << 11) | OPC_MFMC0,
365 OPC_EMT = 0x01 | (1 << 5) | (0x0F << 6) | (0x01 << 11) | OPC_MFMC0,
366 OPC_DVPE = 0x01 | (0 << 5) | OPC_MFMC0,
367 OPC_EVPE = 0x01 | (1 << 5) | OPC_MFMC0,
368 OPC_DI = (0 << 5) | (0x0C << 11) | OPC_MFMC0,
369 OPC_EI = (1 << 5) | (0x0C << 11) | OPC_MFMC0,
372 /* Coprocessor 0 (with rs == C0) */
373 #define MASK_C0(op) MASK_CP0(op) | (op & 0x3F)
375 enum {
376 OPC_TLBR = 0x01 | OPC_C0,
377 OPC_TLBWI = 0x02 | OPC_C0,
378 OPC_TLBWR = 0x06 | OPC_C0,
379 OPC_TLBP = 0x08 | OPC_C0,
380 OPC_RFE = 0x10 | OPC_C0,
381 OPC_ERET = 0x18 | OPC_C0,
382 OPC_DERET = 0x1F | OPC_C0,
383 OPC_WAIT = 0x20 | OPC_C0,
386 /* Coprocessor 1 (rs field) */
387 #define MASK_CP1(op) MASK_OP_MAJOR(op) | (op & (0x1F << 21))
389 /* Values for the fmt field in FP instructions */
390 enum {
391 /* 0 - 15 are reserved */
392 FMT_S = 16, /* single fp */
393 FMT_D = 17, /* double fp */
394 FMT_E = 18, /* extended fp */
395 FMT_Q = 19, /* quad fp */
396 FMT_W = 20, /* 32-bit fixed */
397 FMT_L = 21, /* 64-bit fixed */
398 FMT_PS = 22, /* paired single fp */
399 /* 23 - 31 are reserved */
402 enum {
403 OPC_MFC1 = (0x00 << 21) | OPC_CP1,
404 OPC_DMFC1 = (0x01 << 21) | OPC_CP1,
405 OPC_CFC1 = (0x02 << 21) | OPC_CP1,
406 OPC_MFHC1 = (0x03 << 21) | OPC_CP1,
407 OPC_MTC1 = (0x04 << 21) | OPC_CP1,
408 OPC_DMTC1 = (0x05 << 21) | OPC_CP1,
409 OPC_CTC1 = (0x06 << 21) | OPC_CP1,
410 OPC_MTHC1 = (0x07 << 21) | OPC_CP1,
411 OPC_BC1 = (0x08 << 21) | OPC_CP1, /* bc */
412 OPC_BC1ANY2 = (0x09 << 21) | OPC_CP1,
413 OPC_BC1ANY4 = (0x0A << 21) | OPC_CP1,
414 OPC_S_FMT = (FMT_S << 21) | OPC_CP1,
415 OPC_D_FMT = (FMT_D << 21) | OPC_CP1,
416 OPC_E_FMT = (FMT_E << 21) | OPC_CP1,
417 OPC_Q_FMT = (FMT_Q << 21) | OPC_CP1,
418 OPC_W_FMT = (FMT_W << 21) | OPC_CP1,
419 OPC_L_FMT = (FMT_L << 21) | OPC_CP1,
420 OPC_PS_FMT = (FMT_PS << 21) | OPC_CP1,
423 #define MASK_CP1_FUNC(op) MASK_CP1(op) | (op & 0x3F)
424 #define MASK_BC1(op) MASK_CP1(op) | (op & (0x3 << 16))
426 enum {
427 OPC_BC1F = (0x00 << 16) | OPC_BC1,
428 OPC_BC1T = (0x01 << 16) | OPC_BC1,
429 OPC_BC1FL = (0x02 << 16) | OPC_BC1,
430 OPC_BC1TL = (0x03 << 16) | OPC_BC1,
433 enum {
434 OPC_BC1FANY2 = (0x00 << 16) | OPC_BC1ANY2,
435 OPC_BC1TANY2 = (0x01 << 16) | OPC_BC1ANY2,
438 enum {
439 OPC_BC1FANY4 = (0x00 << 16) | OPC_BC1ANY4,
440 OPC_BC1TANY4 = (0x01 << 16) | OPC_BC1ANY4,
443 #define MASK_CP2(op) MASK_OP_MAJOR(op) | (op & (0x1F << 21))
445 enum {
446 OPC_MFC2 = (0x00 << 21) | OPC_CP2,
447 OPC_DMFC2 = (0x01 << 21) | OPC_CP2,
448 OPC_CFC2 = (0x02 << 21) | OPC_CP2,
449 OPC_MFHC2 = (0x03 << 21) | OPC_CP2,
450 OPC_MTC2 = (0x04 << 21) | OPC_CP2,
451 OPC_DMTC2 = (0x05 << 21) | OPC_CP2,
452 OPC_CTC2 = (0x06 << 21) | OPC_CP2,
453 OPC_MTHC2 = (0x07 << 21) | OPC_CP2,
454 OPC_BC2 = (0x08 << 21) | OPC_CP2,
457 #define MASK_CP3(op) MASK_OP_MAJOR(op) | (op & 0x3F)
459 enum {
460 OPC_LWXC1 = 0x00 | OPC_CP3,
461 OPC_LDXC1 = 0x01 | OPC_CP3,
462 OPC_LUXC1 = 0x05 | OPC_CP3,
463 OPC_SWXC1 = 0x08 | OPC_CP3,
464 OPC_SDXC1 = 0x09 | OPC_CP3,
465 OPC_SUXC1 = 0x0D | OPC_CP3,
466 OPC_PREFX = 0x0F | OPC_CP3,
467 OPC_ALNV_PS = 0x1E | OPC_CP3,
468 OPC_MADD_S = 0x20 | OPC_CP3,
469 OPC_MADD_D = 0x21 | OPC_CP3,
470 OPC_MADD_PS = 0x26 | OPC_CP3,
471 OPC_MSUB_S = 0x28 | OPC_CP3,
472 OPC_MSUB_D = 0x29 | OPC_CP3,
473 OPC_MSUB_PS = 0x2E | OPC_CP3,
474 OPC_NMADD_S = 0x30 | OPC_CP3,
475 OPC_NMADD_D = 0x31 | OPC_CP3,
476 OPC_NMADD_PS= 0x36 | OPC_CP3,
477 OPC_NMSUB_S = 0x38 | OPC_CP3,
478 OPC_NMSUB_D = 0x39 | OPC_CP3,
479 OPC_NMSUB_PS= 0x3E | OPC_CP3,
482 /* global register indices */
483 static TCGv_ptr cpu_env;
484 static TCGv cpu_gpr[32], cpu_PC;
485 static TCGv cpu_HI[MIPS_DSP_ACC], cpu_LO[MIPS_DSP_ACC], cpu_ACX[MIPS_DSP_ACC];
486 static TCGv cpu_dspctrl, btarget, bcond;
487 static TCGv_i32 hflags;
488 static TCGv_i32 fpu_fcr0, fpu_fcr31;
490 static uint32_t gen_opc_hflags[OPC_BUF_SIZE];
492 #include "gen-icount.h"
494 #define gen_helper_0i(name, arg) do { \
495 TCGv_i32 helper_tmp = tcg_const_i32(arg); \
496 gen_helper_##name(helper_tmp); \
497 tcg_temp_free_i32(helper_tmp); \
498 } while(0)
500 #define gen_helper_1i(name, arg1, arg2) do { \
501 TCGv_i32 helper_tmp = tcg_const_i32(arg2); \
502 gen_helper_##name(arg1, helper_tmp); \
503 tcg_temp_free_i32(helper_tmp); \
504 } while(0)
506 #define gen_helper_2i(name, arg1, arg2, arg3) do { \
507 TCGv_i32 helper_tmp = tcg_const_i32(arg3); \
508 gen_helper_##name(arg1, arg2, helper_tmp); \
509 tcg_temp_free_i32(helper_tmp); \
510 } while(0)
512 #define gen_helper_3i(name, arg1, arg2, arg3, arg4) do { \
513 TCGv_i32 helper_tmp = tcg_const_i32(arg4); \
514 gen_helper_##name(arg1, arg2, arg3, helper_tmp); \
515 tcg_temp_free_i32(helper_tmp); \
516 } while(0)
518 typedef struct DisasContext {
519 struct TranslationBlock *tb;
520 target_ulong pc, saved_pc;
521 uint32_t opcode;
522 int singlestep_enabled;
523 /* Routine used to access memory */
524 int mem_idx;
525 uint32_t hflags, saved_hflags;
526 int bstate;
527 target_ulong btarget;
528 } DisasContext;
530 enum {
531 BS_NONE = 0, /* We go out of the TB without reaching a branch or an
532 * exception condition */
533 BS_STOP = 1, /* We want to stop translation for any reason */
534 BS_BRANCH = 2, /* We reached a branch condition */
535 BS_EXCP = 3, /* We reached an exception condition */
538 static const char *regnames[] =
539 { "r0", "at", "v0", "v1", "a0", "a1", "a2", "a3",
540 "t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7",
541 "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7",
542 "t8", "t9", "k0", "k1", "gp", "sp", "s8", "ra", };
544 static const char *regnames_HI[] =
545 { "HI0", "HI1", "HI2", "HI3", };
547 static const char *regnames_LO[] =
548 { "LO0", "LO1", "LO2", "LO3", };
550 static const char *regnames_ACX[] =
551 { "ACX0", "ACX1", "ACX2", "ACX3", };
553 static const char *fregnames[] =
554 { "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7",
555 "f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15",
556 "f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23",
557 "f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31", };
559 #ifdef MIPS_DEBUG_DISAS
560 #define MIPS_DEBUG(fmt, ...) \
561 qemu_log_mask(CPU_LOG_TB_IN_ASM, \
562 TARGET_FMT_lx ": %08x " fmt "\n", \
563 ctx->pc, ctx->opcode , ## __VA_ARGS__)
564 #define LOG_DISAS(...) qemu_log_mask(CPU_LOG_TB_IN_ASM, ## __VA_ARGS__)
565 #else
566 #define MIPS_DEBUG(fmt, ...) do { } while(0)
567 #define LOG_DISAS(...) do { } while (0)
568 #endif
570 #define MIPS_INVAL(op) \
571 do { \
572 MIPS_DEBUG("Invalid %s %03x %03x %03x", op, ctx->opcode >> 26, \
573 ctx->opcode & 0x3F, ((ctx->opcode >> 16) & 0x1F)); \
574 } while (0)
576 /* General purpose registers moves. */
577 static inline void gen_load_gpr (TCGv t, int reg)
579 if (reg == 0)
580 tcg_gen_movi_tl(t, 0);
581 else
582 tcg_gen_mov_tl(t, cpu_gpr[reg]);
585 static inline void gen_store_gpr (TCGv t, int reg)
587 if (reg != 0)
588 tcg_gen_mov_tl(cpu_gpr[reg], t);
591 /* Moves to/from ACX register. */
592 static inline void gen_load_ACX (TCGv t, int reg)
594 tcg_gen_mov_tl(t, cpu_ACX[reg]);
597 static inline void gen_store_ACX (TCGv t, int reg)
599 tcg_gen_mov_tl(cpu_ACX[reg], t);
602 /* Moves to/from shadow registers. */
603 static inline void gen_load_srsgpr (int from, int to)
605 TCGv t0 = tcg_temp_new();
607 if (from == 0)
608 tcg_gen_movi_tl(t0, 0);
609 else {
610 TCGv_i32 t2 = tcg_temp_new_i32();
611 TCGv_ptr addr = tcg_temp_new_ptr();
613 tcg_gen_ld_i32(t2, cpu_env, offsetof(CPUState, CP0_SRSCtl));
614 tcg_gen_shri_i32(t2, t2, CP0SRSCtl_PSS);
615 tcg_gen_andi_i32(t2, t2, 0xf);
616 tcg_gen_muli_i32(t2, t2, sizeof(target_ulong) * 32);
617 tcg_gen_ext_i32_ptr(addr, t2);
618 tcg_gen_add_ptr(addr, cpu_env, addr);
620 tcg_gen_ld_tl(t0, addr, sizeof(target_ulong) * from);
621 tcg_temp_free_ptr(addr);
622 tcg_temp_free_i32(t2);
624 gen_store_gpr(t0, to);
625 tcg_temp_free(t0);
628 static inline void gen_store_srsgpr (int from, int to)
630 if (to != 0) {
631 TCGv t0 = tcg_temp_new();
632 TCGv_i32 t2 = tcg_temp_new_i32();
633 TCGv_ptr addr = tcg_temp_new_ptr();
635 gen_load_gpr(t0, from);
636 tcg_gen_ld_i32(t2, cpu_env, offsetof(CPUState, CP0_SRSCtl));
637 tcg_gen_shri_i32(t2, t2, CP0SRSCtl_PSS);
638 tcg_gen_andi_i32(t2, t2, 0xf);
639 tcg_gen_muli_i32(t2, t2, sizeof(target_ulong) * 32);
640 tcg_gen_ext_i32_ptr(addr, t2);
641 tcg_gen_add_ptr(addr, cpu_env, addr);
643 tcg_gen_st_tl(t0, addr, sizeof(target_ulong) * to);
644 tcg_temp_free_ptr(addr);
645 tcg_temp_free_i32(t2);
646 tcg_temp_free(t0);
650 /* Floating point register moves. */
651 static inline void gen_load_fpr32 (TCGv_i32 t, int reg)
653 tcg_gen_ld_i32(t, cpu_env, offsetof(CPUState, active_fpu.fpr[reg].w[FP_ENDIAN_IDX]));
656 static inline void gen_store_fpr32 (TCGv_i32 t, int reg)
658 tcg_gen_st_i32(t, cpu_env, offsetof(CPUState, active_fpu.fpr[reg].w[FP_ENDIAN_IDX]));
661 static inline void gen_load_fpr32h (TCGv_i32 t, int reg)
663 tcg_gen_ld_i32(t, cpu_env, offsetof(CPUState, active_fpu.fpr[reg].w[!FP_ENDIAN_IDX]));
666 static inline void gen_store_fpr32h (TCGv_i32 t, int reg)
668 tcg_gen_st_i32(t, cpu_env, offsetof(CPUState, active_fpu.fpr[reg].w[!FP_ENDIAN_IDX]));
671 static inline void gen_load_fpr64 (DisasContext *ctx, TCGv_i64 t, int reg)
673 if (ctx->hflags & MIPS_HFLAG_F64) {
674 tcg_gen_ld_i64(t, cpu_env, offsetof(CPUState, active_fpu.fpr[reg].d));
675 } else {
676 TCGv_i32 t0 = tcg_temp_new_i32();
677 TCGv_i32 t1 = tcg_temp_new_i32();
678 gen_load_fpr32(t0, reg & ~1);
679 gen_load_fpr32(t1, reg | 1);
680 tcg_gen_concat_i32_i64(t, t0, t1);
681 tcg_temp_free_i32(t0);
682 tcg_temp_free_i32(t1);
686 static inline void gen_store_fpr64 (DisasContext *ctx, TCGv_i64 t, int reg)
688 if (ctx->hflags & MIPS_HFLAG_F64) {
689 tcg_gen_st_i64(t, cpu_env, offsetof(CPUState, active_fpu.fpr[reg].d));
690 } else {
691 TCGv_i64 t0 = tcg_temp_new_i64();
692 TCGv_i32 t1 = tcg_temp_new_i32();
693 tcg_gen_trunc_i64_i32(t1, t);
694 gen_store_fpr32(t1, reg & ~1);
695 tcg_gen_shri_i64(t0, t, 32);
696 tcg_gen_trunc_i64_i32(t1, t0);
697 gen_store_fpr32(t1, reg | 1);
698 tcg_temp_free_i32(t1);
699 tcg_temp_free_i64(t0);
703 static inline int get_fp_bit (int cc)
705 if (cc)
706 return 24 + cc;
707 else
708 return 23;
711 /* Tests */
712 static inline void gen_save_pc(target_ulong pc)
714 tcg_gen_movi_tl(cpu_PC, pc);
717 static inline void save_cpu_state (DisasContext *ctx, int do_save_pc)
719 LOG_DISAS("hflags %08x saved %08x\n", ctx->hflags, ctx->saved_hflags);
720 if (do_save_pc && ctx->pc != ctx->saved_pc) {
721 gen_save_pc(ctx->pc);
722 ctx->saved_pc = ctx->pc;
724 if (ctx->hflags != ctx->saved_hflags) {
725 tcg_gen_movi_i32(hflags, ctx->hflags);
726 ctx->saved_hflags = ctx->hflags;
727 switch (ctx->hflags & MIPS_HFLAG_BMASK_BASE) {
728 case MIPS_HFLAG_BR:
729 break;
730 case MIPS_HFLAG_BC:
731 case MIPS_HFLAG_BL:
732 case MIPS_HFLAG_B:
733 tcg_gen_movi_tl(btarget, ctx->btarget);
734 break;
739 static inline void restore_cpu_state (CPUState *env, DisasContext *ctx)
741 ctx->saved_hflags = ctx->hflags;
742 switch (ctx->hflags & MIPS_HFLAG_BMASK_BASE) {
743 case MIPS_HFLAG_BR:
744 break;
745 case MIPS_HFLAG_BC:
746 case MIPS_HFLAG_BL:
747 case MIPS_HFLAG_B:
748 ctx->btarget = env->btarget;
749 break;
753 static inline void
754 generate_exception_err (DisasContext *ctx, int excp, int err)
756 TCGv_i32 texcp = tcg_const_i32(excp);
757 TCGv_i32 terr = tcg_const_i32(err);
758 save_cpu_state(ctx, 1);
759 gen_helper_raise_exception_err(texcp, terr);
760 tcg_temp_free_i32(terr);
761 tcg_temp_free_i32(texcp);
764 static inline void
765 generate_exception (DisasContext *ctx, int excp)
767 save_cpu_state(ctx, 1);
768 gen_helper_0i(raise_exception, excp);
771 /* Addresses computation */
772 static inline void gen_op_addr_add (DisasContext *ctx, TCGv ret, TCGv arg0, TCGv arg1)
774 tcg_gen_add_tl(ret, arg0, arg1);
776 #if defined(TARGET_MIPS64)
777 /* For compatibility with 32-bit code, data reference in user mode
778 with Status_UX = 0 should be casted to 32-bit and sign extended.
779 See the MIPS64 PRA manual, section 4.10. */
780 if (((ctx->hflags & MIPS_HFLAG_KSU) == MIPS_HFLAG_UM) &&
781 !(ctx->hflags & MIPS_HFLAG_UX)) {
782 tcg_gen_ext32s_i64(ret, ret);
784 #endif
787 static inline void check_cp0_enabled(DisasContext *ctx)
789 if (unlikely(!(ctx->hflags & MIPS_HFLAG_CP0)))
790 generate_exception_err(ctx, EXCP_CpU, 0);
793 static inline void check_cp1_enabled(DisasContext *ctx)
795 if (unlikely(!(ctx->hflags & MIPS_HFLAG_FPU)))
796 generate_exception_err(ctx, EXCP_CpU, 1);
799 /* Verify that the processor is running with COP1X instructions enabled.
800 This is associated with the nabla symbol in the MIPS32 and MIPS64
801 opcode tables. */
803 static inline void check_cop1x(DisasContext *ctx)
805 if (unlikely(!(ctx->hflags & MIPS_HFLAG_COP1X)))
806 generate_exception(ctx, EXCP_RI);
809 /* Verify that the processor is running with 64-bit floating-point
810 operations enabled. */
812 static inline void check_cp1_64bitmode(DisasContext *ctx)
814 if (unlikely(~ctx->hflags & (MIPS_HFLAG_F64 | MIPS_HFLAG_COP1X)))
815 generate_exception(ctx, EXCP_RI);
819 * Verify if floating point register is valid; an operation is not defined
820 * if bit 0 of any register specification is set and the FR bit in the
821 * Status register equals zero, since the register numbers specify an
822 * even-odd pair of adjacent coprocessor general registers. When the FR bit
823 * in the Status register equals one, both even and odd register numbers
824 * are valid. This limitation exists only for 64 bit wide (d,l,ps) registers.
826 * Multiple 64 bit wide registers can be checked by calling
827 * gen_op_cp1_registers(freg1 | freg2 | ... | fregN);
829 static inline void check_cp1_registers(DisasContext *ctx, int regs)
831 if (unlikely(!(ctx->hflags & MIPS_HFLAG_F64) && (regs & 1)))
832 generate_exception(ctx, EXCP_RI);
835 /* This code generates a "reserved instruction" exception if the
836 CPU does not support the instruction set corresponding to flags. */
837 static inline void check_insn(CPUState *env, DisasContext *ctx, int flags)
839 if (unlikely(!(env->insn_flags & flags)))
840 generate_exception(ctx, EXCP_RI);
843 /* This code generates a "reserved instruction" exception if 64-bit
844 instructions are not enabled. */
845 static inline void check_mips_64(DisasContext *ctx)
847 if (unlikely(!(ctx->hflags & MIPS_HFLAG_64)))
848 generate_exception(ctx, EXCP_RI);
851 /* Define small wrappers for gen_load_fpr* so that we have a uniform
852 calling interface for 32 and 64-bit FPRs. No sense in changing
853 all callers for gen_load_fpr32 when we need the CTX parameter for
854 this one use. */
855 #define gen_ldcmp_fpr32(ctx, x, y) gen_load_fpr32(x, y)
856 #define gen_ldcmp_fpr64(ctx, x, y) gen_load_fpr64(ctx, x, y)
857 #define FOP_CONDS(type, abs, fmt, ifmt, bits) \
858 static inline void gen_cmp ## type ## _ ## fmt(DisasContext *ctx, int n, \
859 int ft, int fs, int cc) \
861 TCGv_i##bits fp0 = tcg_temp_new_i##bits (); \
862 TCGv_i##bits fp1 = tcg_temp_new_i##bits (); \
863 switch (ifmt) { \
864 case FMT_PS: \
865 check_cp1_64bitmode(ctx); \
866 break; \
867 case FMT_D: \
868 if (abs) { \
869 check_cop1x(ctx); \
871 check_cp1_registers(ctx, fs | ft); \
872 break; \
873 case FMT_S: \
874 if (abs) { \
875 check_cop1x(ctx); \
877 break; \
879 gen_ldcmp_fpr##bits (ctx, fp0, fs); \
880 gen_ldcmp_fpr##bits (ctx, fp1, ft); \
881 switch (n) { \
882 case 0: gen_helper_2i(cmp ## type ## _ ## fmt ## _f, fp0, fp1, cc); break;\
883 case 1: gen_helper_2i(cmp ## type ## _ ## fmt ## _un, fp0, fp1, cc); break;\
884 case 2: gen_helper_2i(cmp ## type ## _ ## fmt ## _eq, fp0, fp1, cc); break;\
885 case 3: gen_helper_2i(cmp ## type ## _ ## fmt ## _ueq, fp0, fp1, cc); break;\
886 case 4: gen_helper_2i(cmp ## type ## _ ## fmt ## _olt, fp0, fp1, cc); break;\
887 case 5: gen_helper_2i(cmp ## type ## _ ## fmt ## _ult, fp0, fp1, cc); break;\
888 case 6: gen_helper_2i(cmp ## type ## _ ## fmt ## _ole, fp0, fp1, cc); break;\
889 case 7: gen_helper_2i(cmp ## type ## _ ## fmt ## _ule, fp0, fp1, cc); break;\
890 case 8: gen_helper_2i(cmp ## type ## _ ## fmt ## _sf, fp0, fp1, cc); break;\
891 case 9: gen_helper_2i(cmp ## type ## _ ## fmt ## _ngle, fp0, fp1, cc); break;\
892 case 10: gen_helper_2i(cmp ## type ## _ ## fmt ## _seq, fp0, fp1, cc); break;\
893 case 11: gen_helper_2i(cmp ## type ## _ ## fmt ## _ngl, fp0, fp1, cc); break;\
894 case 12: gen_helper_2i(cmp ## type ## _ ## fmt ## _lt, fp0, fp1, cc); break;\
895 case 13: gen_helper_2i(cmp ## type ## _ ## fmt ## _nge, fp0, fp1, cc); break;\
896 case 14: gen_helper_2i(cmp ## type ## _ ## fmt ## _le, fp0, fp1, cc); break;\
897 case 15: gen_helper_2i(cmp ## type ## _ ## fmt ## _ngt, fp0, fp1, cc); break;\
898 default: abort(); \
900 tcg_temp_free_i##bits (fp0); \
901 tcg_temp_free_i##bits (fp1); \
904 FOP_CONDS(, 0, d, FMT_D, 64)
905 FOP_CONDS(abs, 1, d, FMT_D, 64)
906 FOP_CONDS(, 0, s, FMT_S, 32)
907 FOP_CONDS(abs, 1, s, FMT_S, 32)
908 FOP_CONDS(, 0, ps, FMT_PS, 64)
909 FOP_CONDS(abs, 1, ps, FMT_PS, 64)
910 #undef FOP_CONDS
911 #undef gen_ldcmp_fpr32
912 #undef gen_ldcmp_fpr64
914 /* load/store instructions. */
915 #define OP_LD(insn,fname) \
916 static inline void op_ld_##insn(TCGv ret, TCGv arg1, DisasContext *ctx) \
918 tcg_gen_qemu_##fname(ret, arg1, ctx->mem_idx); \
920 OP_LD(lb,ld8s);
921 OP_LD(lbu,ld8u);
922 OP_LD(lh,ld16s);
923 OP_LD(lhu,ld16u);
924 OP_LD(lw,ld32s);
925 #if defined(TARGET_MIPS64)
926 OP_LD(lwu,ld32u);
927 OP_LD(ld,ld64);
928 #endif
929 #undef OP_LD
931 #define OP_ST(insn,fname) \
932 static inline void op_st_##insn(TCGv arg1, TCGv arg2, DisasContext *ctx) \
934 tcg_gen_qemu_##fname(arg1, arg2, ctx->mem_idx); \
936 OP_ST(sb,st8);
937 OP_ST(sh,st16);
938 OP_ST(sw,st32);
939 #if defined(TARGET_MIPS64)
940 OP_ST(sd,st64);
941 #endif
942 #undef OP_ST
944 #ifdef CONFIG_USER_ONLY
945 #define OP_LD_ATOMIC(insn,fname) \
946 static inline void op_ld_##insn(TCGv ret, TCGv arg1, DisasContext *ctx) \
948 TCGv t0 = tcg_temp_new(); \
949 tcg_gen_mov_tl(t0, arg1); \
950 tcg_gen_qemu_##fname(ret, arg1, ctx->mem_idx); \
951 tcg_gen_st_tl(t0, cpu_env, offsetof(CPUState, lladdr)); \
952 tcg_gen_st_tl(ret, cpu_env, offsetof(CPUState, llval)); \
953 tcg_temp_free(t0); \
955 #else
956 #define OP_LD_ATOMIC(insn,fname) \
957 static inline void op_ld_##insn(TCGv ret, TCGv arg1, DisasContext *ctx) \
959 gen_helper_2i(insn, ret, arg1, ctx->mem_idx); \
961 #endif
962 OP_LD_ATOMIC(ll,ld32s);
963 #if defined(TARGET_MIPS64)
964 OP_LD_ATOMIC(lld,ld64);
965 #endif
966 #undef OP_LD_ATOMIC
968 #ifdef CONFIG_USER_ONLY
969 #define OP_ST_ATOMIC(insn,fname,ldname,almask) \
970 static inline void op_st_##insn(TCGv arg1, TCGv arg2, int rt, DisasContext *ctx) \
972 TCGv t0 = tcg_temp_new(); \
973 int l1 = gen_new_label(); \
974 int l2 = gen_new_label(); \
976 tcg_gen_andi_tl(t0, arg2, almask); \
977 tcg_gen_brcondi_tl(TCG_COND_EQ, t0, 0, l1); \
978 tcg_gen_st_tl(arg2, cpu_env, offsetof(CPUState, CP0_BadVAddr)); \
979 generate_exception(ctx, EXCP_AdES); \
980 gen_set_label(l1); \
981 tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUState, lladdr)); \
982 tcg_gen_brcond_tl(TCG_COND_NE, arg2, t0, l2); \
983 tcg_gen_movi_tl(t0, rt | ((almask << 3) & 0x20)); \
984 tcg_gen_st_tl(t0, cpu_env, offsetof(CPUState, llreg)); \
985 tcg_gen_st_tl(arg1, cpu_env, offsetof(CPUState, llnewval)); \
986 gen_helper_0i(raise_exception, EXCP_SC); \
987 gen_set_label(l2); \
988 tcg_gen_movi_tl(t0, 0); \
989 gen_store_gpr(t0, rt); \
990 tcg_temp_free(t0); \
992 #else
993 #define OP_ST_ATOMIC(insn,fname,ldname,almask) \
994 static inline void op_st_##insn(TCGv arg1, TCGv arg2, int rt, DisasContext *ctx) \
996 TCGv t0 = tcg_temp_new(); \
997 gen_helper_3i(insn, t0, arg1, arg2, ctx->mem_idx); \
998 gen_store_gpr(t0, rt); \
999 tcg_temp_free(t0); \
1001 #endif
1002 OP_ST_ATOMIC(sc,st32,ld32s,0x3);
1003 #if defined(TARGET_MIPS64)
1004 OP_ST_ATOMIC(scd,st64,ld64,0x7);
1005 #endif
1006 #undef OP_ST_ATOMIC
1008 static void gen_base_offset_addr (DisasContext *ctx, TCGv addr,
1009 int base, int16_t offset)
1011 if (base == 0) {
1012 tcg_gen_movi_tl(addr, offset);
1013 } else if (offset == 0) {
1014 gen_load_gpr(addr, base);
1015 } else {
1016 tcg_gen_movi_tl(addr, offset);
1017 gen_op_addr_add(ctx, addr, cpu_gpr[base], addr);
1021 static target_ulong pc_relative_pc (DisasContext *ctx)
1023 target_ulong pc = ctx->pc;
1025 if (ctx->hflags & MIPS_HFLAG_BMASK) {
1026 int branch_bytes = ctx->hflags & MIPS_HFLAG_BDS16 ? 2 : 4;
1028 pc -= branch_bytes;
1031 pc &= ~(target_ulong)3;
1032 return pc;
1035 /* Load */
1036 static void gen_ld (CPUState *env, DisasContext *ctx, uint32_t opc,
1037 int rt, int base, int16_t offset)
1039 const char *opn = "ld";
1040 TCGv t0, t1;
1042 if (rt == 0 && env->insn_flags & (INSN_LOONGSON2E | INSN_LOONGSON2F)) {
1043 /* Loongson CPU uses a load to zero register for prefetch.
1044 We emulate it as a NOP. On other CPU we must perform the
1045 actual memory access. */
1046 MIPS_DEBUG("NOP");
1047 return;
1050 t0 = tcg_temp_new();
1051 t1 = tcg_temp_new();
1052 gen_base_offset_addr(ctx, t0, base, offset);
1054 switch (opc) {
1055 #if defined(TARGET_MIPS64)
1056 case OPC_LWU:
1057 save_cpu_state(ctx, 0);
1058 op_ld_lwu(t0, t0, ctx);
1059 gen_store_gpr(t0, rt);
1060 opn = "lwu";
1061 break;
1062 case OPC_LD:
1063 save_cpu_state(ctx, 0);
1064 op_ld_ld(t0, t0, ctx);
1065 gen_store_gpr(t0, rt);
1066 opn = "ld";
1067 break;
1068 case OPC_LLD:
1069 save_cpu_state(ctx, 0);
1070 op_ld_lld(t0, t0, ctx);
1071 gen_store_gpr(t0, rt);
1072 opn = "lld";
1073 break;
1074 case OPC_LDL:
1075 save_cpu_state(ctx, 1);
1076 gen_load_gpr(t1, rt);
1077 gen_helper_3i(ldl, t1, t1, t0, ctx->mem_idx);
1078 gen_store_gpr(t1, rt);
1079 opn = "ldl";
1080 break;
1081 case OPC_LDR:
1082 save_cpu_state(ctx, 1);
1083 gen_load_gpr(t1, rt);
1084 gen_helper_3i(ldr, t1, t1, t0, ctx->mem_idx);
1085 gen_store_gpr(t1, rt);
1086 opn = "ldr";
1087 break;
1088 case OPC_LDPC:
1089 save_cpu_state(ctx, 1);
1090 tcg_gen_movi_tl(t1, pc_relative_pc(ctx));
1091 gen_op_addr_add(ctx, t0, t0, t1);
1092 op_ld_ld(t0, t0, ctx);
1093 gen_store_gpr(t0, rt);
1094 opn = "ldpc";
1095 break;
1096 #endif
1097 case OPC_LWPC:
1098 save_cpu_state(ctx, 1);
1099 tcg_gen_movi_tl(t1, pc_relative_pc(ctx));
1100 gen_op_addr_add(ctx, t0, t0, t1);
1101 op_ld_lw(t0, t0, ctx);
1102 gen_store_gpr(t0, rt);
1103 opn = "lwpc";
1104 break;
1105 case OPC_LW:
1106 save_cpu_state(ctx, 0);
1107 op_ld_lw(t0, t0, ctx);
1108 gen_store_gpr(t0, rt);
1109 opn = "lw";
1110 break;
1111 case OPC_LH:
1112 save_cpu_state(ctx, 0);
1113 op_ld_lh(t0, t0, ctx);
1114 gen_store_gpr(t0, rt);
1115 opn = "lh";
1116 break;
1117 case OPC_LHU:
1118 save_cpu_state(ctx, 0);
1119 op_ld_lhu(t0, t0, ctx);
1120 gen_store_gpr(t0, rt);
1121 opn = "lhu";
1122 break;
1123 case OPC_LB:
1124 save_cpu_state(ctx, 0);
1125 op_ld_lb(t0, t0, ctx);
1126 gen_store_gpr(t0, rt);
1127 opn = "lb";
1128 break;
1129 case OPC_LBU:
1130 save_cpu_state(ctx, 0);
1131 op_ld_lbu(t0, t0, ctx);
1132 gen_store_gpr(t0, rt);
1133 opn = "lbu";
1134 break;
1135 case OPC_LWL:
1136 save_cpu_state(ctx, 1);
1137 gen_load_gpr(t1, rt);
1138 gen_helper_3i(lwl, t1, t1, t0, ctx->mem_idx);
1139 gen_store_gpr(t1, rt);
1140 opn = "lwl";
1141 break;
1142 case OPC_LWR:
1143 save_cpu_state(ctx, 1);
1144 gen_load_gpr(t1, rt);
1145 gen_helper_3i(lwr, t1, t1, t0, ctx->mem_idx);
1146 gen_store_gpr(t1, rt);
1147 opn = "lwr";
1148 break;
1149 case OPC_LL:
1150 save_cpu_state(ctx, 1);
1151 op_ld_ll(t0, t0, ctx);
1152 gen_store_gpr(t0, rt);
1153 opn = "ll";
1154 break;
1156 MIPS_DEBUG("%s %s, %d(%s)", opn, regnames[rt], offset, regnames[base]);
1157 tcg_temp_free(t0);
1158 tcg_temp_free(t1);
1161 /* Store */
1162 static void gen_st (DisasContext *ctx, uint32_t opc, int rt,
1163 int base, int16_t offset)
1165 const char *opn = "st";
1166 TCGv t0 = tcg_temp_new();
1167 TCGv t1 = tcg_temp_new();
1169 gen_base_offset_addr(ctx, t0, base, offset);
1170 gen_load_gpr(t1, rt);
1171 switch (opc) {
1172 #if defined(TARGET_MIPS64)
1173 case OPC_SD:
1174 save_cpu_state(ctx, 0);
1175 op_st_sd(t1, t0, ctx);
1176 opn = "sd";
1177 break;
1178 case OPC_SDL:
1179 save_cpu_state(ctx, 1);
1180 gen_helper_2i(sdl, t1, t0, ctx->mem_idx);
1181 opn = "sdl";
1182 break;
1183 case OPC_SDR:
1184 save_cpu_state(ctx, 1);
1185 gen_helper_2i(sdr, t1, t0, ctx->mem_idx);
1186 opn = "sdr";
1187 break;
1188 #endif
1189 case OPC_SW:
1190 save_cpu_state(ctx, 0);
1191 op_st_sw(t1, t0, ctx);
1192 opn = "sw";
1193 break;
1194 case OPC_SH:
1195 save_cpu_state(ctx, 0);
1196 op_st_sh(t1, t0, ctx);
1197 opn = "sh";
1198 break;
1199 case OPC_SB:
1200 save_cpu_state(ctx, 0);
1201 op_st_sb(t1, t0, ctx);
1202 opn = "sb";
1203 break;
1204 case OPC_SWL:
1205 save_cpu_state(ctx, 1);
1206 gen_helper_2i(swl, t1, t0, ctx->mem_idx);
1207 opn = "swl";
1208 break;
1209 case OPC_SWR:
1210 save_cpu_state(ctx, 1);
1211 gen_helper_2i(swr, t1, t0, ctx->mem_idx);
1212 opn = "swr";
1213 break;
1215 MIPS_DEBUG("%s %s, %d(%s)", opn, regnames[rt], offset, regnames[base]);
1216 tcg_temp_free(t0);
1217 tcg_temp_free(t1);
1221 /* Store conditional */
1222 static void gen_st_cond (DisasContext *ctx, uint32_t opc, int rt,
1223 int base, int16_t offset)
1225 const char *opn = "st_cond";
1226 TCGv t0, t1;
1228 t0 = tcg_temp_local_new();
1230 gen_base_offset_addr(ctx, t0, base, offset);
1231 /* Don't do NOP if destination is zero: we must perform the actual
1232 memory access. */
1234 t1 = tcg_temp_local_new();
1235 gen_load_gpr(t1, rt);
1236 switch (opc) {
1237 #if defined(TARGET_MIPS64)
1238 case OPC_SCD:
1239 save_cpu_state(ctx, 0);
1240 op_st_scd(t1, t0, rt, ctx);
1241 opn = "scd";
1242 break;
1243 #endif
1244 case OPC_SC:
1245 save_cpu_state(ctx, 1);
1246 op_st_sc(t1, t0, rt, ctx);
1247 opn = "sc";
1248 break;
1250 MIPS_DEBUG("%s %s, %d(%s)", opn, regnames[rt], offset, regnames[base]);
1251 tcg_temp_free(t1);
1252 tcg_temp_free(t0);
1255 /* Load and store */
1256 static void gen_flt_ldst (DisasContext *ctx, uint32_t opc, int ft,
1257 int base, int16_t offset)
1259 const char *opn = "flt_ldst";
1260 TCGv t0 = tcg_temp_new();
1262 gen_base_offset_addr(ctx, t0, base, offset);
1263 /* Don't do NOP if destination is zero: we must perform the actual
1264 memory access. */
1265 switch (opc) {
1266 case OPC_LWC1:
1268 TCGv_i32 fp0 = tcg_temp_new_i32();
1270 tcg_gen_qemu_ld32s(t0, t0, ctx->mem_idx);
1271 tcg_gen_trunc_tl_i32(fp0, t0);
1272 gen_store_fpr32(fp0, ft);
1273 tcg_temp_free_i32(fp0);
1275 opn = "lwc1";
1276 break;
1277 case OPC_SWC1:
1279 TCGv_i32 fp0 = tcg_temp_new_i32();
1280 TCGv t1 = tcg_temp_new();
1282 gen_load_fpr32(fp0, ft);
1283 tcg_gen_extu_i32_tl(t1, fp0);
1284 tcg_gen_qemu_st32(t1, t0, ctx->mem_idx);
1285 tcg_temp_free(t1);
1286 tcg_temp_free_i32(fp0);
1288 opn = "swc1";
1289 break;
1290 case OPC_LDC1:
1292 TCGv_i64 fp0 = tcg_temp_new_i64();
1294 tcg_gen_qemu_ld64(fp0, t0, ctx->mem_idx);
1295 gen_store_fpr64(ctx, fp0, ft);
1296 tcg_temp_free_i64(fp0);
1298 opn = "ldc1";
1299 break;
1300 case OPC_SDC1:
1302 TCGv_i64 fp0 = tcg_temp_new_i64();
1304 gen_load_fpr64(ctx, fp0, ft);
1305 tcg_gen_qemu_st64(fp0, t0, ctx->mem_idx);
1306 tcg_temp_free_i64(fp0);
1308 opn = "sdc1";
1309 break;
1310 default:
1311 MIPS_INVAL(opn);
1312 generate_exception(ctx, EXCP_RI);
1313 goto out;
1315 MIPS_DEBUG("%s %s, %d(%s)", opn, fregnames[ft], offset, regnames[base]);
1316 out:
1317 tcg_temp_free(t0);
1320 static void gen_cop1_ldst(CPUState *env, DisasContext *ctx,
1321 uint32_t op, int rt, int rs, int16_t imm)
1323 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
1324 check_cp1_enabled(ctx);
1325 gen_flt_ldst(ctx, op, rt, rs, imm);
1326 } else {
1327 generate_exception_err(ctx, EXCP_CpU, 1);
1331 /* Arithmetic with immediate operand */
1332 static void gen_arith_imm (CPUState *env, DisasContext *ctx, uint32_t opc,
1333 int rt, int rs, int16_t imm)
1335 target_ulong uimm = (target_long)imm; /* Sign extend to 32/64 bits */
1336 const char *opn = "imm arith";
1338 if (rt == 0 && opc != OPC_ADDI && opc != OPC_DADDI) {
1339 /* If no destination, treat it as a NOP.
1340 For addi, we must generate the overflow exception when needed. */
1341 MIPS_DEBUG("NOP");
1342 return;
1344 switch (opc) {
1345 case OPC_ADDI:
1347 TCGv t0 = tcg_temp_local_new();
1348 TCGv t1 = tcg_temp_new();
1349 TCGv t2 = tcg_temp_new();
1350 int l1 = gen_new_label();
1352 gen_load_gpr(t1, rs);
1353 tcg_gen_addi_tl(t0, t1, uimm);
1354 tcg_gen_ext32s_tl(t0, t0);
1356 tcg_gen_xori_tl(t1, t1, ~uimm);
1357 tcg_gen_xori_tl(t2, t0, uimm);
1358 tcg_gen_and_tl(t1, t1, t2);
1359 tcg_temp_free(t2);
1360 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
1361 tcg_temp_free(t1);
1362 /* operands of same sign, result different sign */
1363 generate_exception(ctx, EXCP_OVERFLOW);
1364 gen_set_label(l1);
1365 tcg_gen_ext32s_tl(t0, t0);
1366 gen_store_gpr(t0, rt);
1367 tcg_temp_free(t0);
1369 opn = "addi";
1370 break;
1371 case OPC_ADDIU:
1372 if (rs != 0) {
1373 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
1374 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
1375 } else {
1376 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
1378 opn = "addiu";
1379 break;
1380 #if defined(TARGET_MIPS64)
1381 case OPC_DADDI:
1383 TCGv t0 = tcg_temp_local_new();
1384 TCGv t1 = tcg_temp_new();
1385 TCGv t2 = tcg_temp_new();
1386 int l1 = gen_new_label();
1388 gen_load_gpr(t1, rs);
1389 tcg_gen_addi_tl(t0, t1, uimm);
1391 tcg_gen_xori_tl(t1, t1, ~uimm);
1392 tcg_gen_xori_tl(t2, t0, uimm);
1393 tcg_gen_and_tl(t1, t1, t2);
1394 tcg_temp_free(t2);
1395 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
1396 tcg_temp_free(t1);
1397 /* operands of same sign, result different sign */
1398 generate_exception(ctx, EXCP_OVERFLOW);
1399 gen_set_label(l1);
1400 gen_store_gpr(t0, rt);
1401 tcg_temp_free(t0);
1403 opn = "daddi";
1404 break;
1405 case OPC_DADDIU:
1406 if (rs != 0) {
1407 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
1408 } else {
1409 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
1411 opn = "daddiu";
1412 break;
1413 #endif
1415 MIPS_DEBUG("%s %s, %s, " TARGET_FMT_lx, opn, regnames[rt], regnames[rs], uimm);
1418 /* Logic with immediate operand */
1419 static void gen_logic_imm (CPUState *env, uint32_t opc, int rt, int rs, int16_t imm)
1421 target_ulong uimm;
1422 const char *opn = "imm logic";
1424 if (rt == 0) {
1425 /* If no destination, treat it as a NOP. */
1426 MIPS_DEBUG("NOP");
1427 return;
1429 uimm = (uint16_t)imm;
1430 switch (opc) {
1431 case OPC_ANDI:
1432 if (likely(rs != 0))
1433 tcg_gen_andi_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
1434 else
1435 tcg_gen_movi_tl(cpu_gpr[rt], 0);
1436 opn = "andi";
1437 break;
1438 case OPC_ORI:
1439 if (rs != 0)
1440 tcg_gen_ori_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
1441 else
1442 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
1443 opn = "ori";
1444 break;
1445 case OPC_XORI:
1446 if (likely(rs != 0))
1447 tcg_gen_xori_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
1448 else
1449 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
1450 opn = "xori";
1451 break;
1452 case OPC_LUI:
1453 tcg_gen_movi_tl(cpu_gpr[rt], imm << 16);
1454 opn = "lui";
1455 break;
1457 MIPS_DEBUG("%s %s, %s, " TARGET_FMT_lx, opn, regnames[rt], regnames[rs], uimm);
1460 /* Set on less than with immediate operand */
1461 static void gen_slt_imm (CPUState *env, uint32_t opc, int rt, int rs, int16_t imm)
1463 target_ulong uimm = (target_long)imm; /* Sign extend to 32/64 bits */
1464 const char *opn = "imm arith";
1465 TCGv t0;
1467 if (rt == 0) {
1468 /* If no destination, treat it as a NOP. */
1469 MIPS_DEBUG("NOP");
1470 return;
1472 t0 = tcg_temp_new();
1473 gen_load_gpr(t0, rs);
1474 switch (opc) {
1475 case OPC_SLTI:
1476 tcg_gen_setcondi_tl(TCG_COND_LT, cpu_gpr[rt], t0, uimm);
1477 opn = "slti";
1478 break;
1479 case OPC_SLTIU:
1480 tcg_gen_setcondi_tl(TCG_COND_LTU, cpu_gpr[rt], t0, uimm);
1481 opn = "sltiu";
1482 break;
1484 MIPS_DEBUG("%s %s, %s, " TARGET_FMT_lx, opn, regnames[rt], regnames[rs], uimm);
1485 tcg_temp_free(t0);
1488 /* Shifts with immediate operand */
1489 static void gen_shift_imm(CPUState *env, DisasContext *ctx, uint32_t opc,
1490 int rt, int rs, int16_t imm)
1492 target_ulong uimm = ((uint16_t)imm) & 0x1f;
1493 const char *opn = "imm shift";
1494 TCGv t0;
1496 if (rt == 0) {
1497 /* If no destination, treat it as a NOP. */
1498 MIPS_DEBUG("NOP");
1499 return;
1502 t0 = tcg_temp_new();
1503 gen_load_gpr(t0, rs);
1504 switch (opc) {
1505 case OPC_SLL:
1506 tcg_gen_shli_tl(t0, t0, uimm);
1507 tcg_gen_ext32s_tl(cpu_gpr[rt], t0);
1508 opn = "sll";
1509 break;
1510 case OPC_SRA:
1511 tcg_gen_sari_tl(cpu_gpr[rt], t0, uimm);
1512 opn = "sra";
1513 break;
1514 case OPC_SRL:
1515 if (uimm != 0) {
1516 tcg_gen_ext32u_tl(t0, t0);
1517 tcg_gen_shri_tl(cpu_gpr[rt], t0, uimm);
1518 } else {
1519 tcg_gen_ext32s_tl(cpu_gpr[rt], t0);
1521 opn = "srl";
1522 break;
1523 case OPC_ROTR:
1524 if (uimm != 0) {
1525 TCGv_i32 t1 = tcg_temp_new_i32();
1527 tcg_gen_trunc_tl_i32(t1, t0);
1528 tcg_gen_rotri_i32(t1, t1, uimm);
1529 tcg_gen_ext_i32_tl(cpu_gpr[rt], t1);
1530 tcg_temp_free_i32(t1);
1531 } else {
1532 tcg_gen_ext32s_tl(cpu_gpr[rt], t0);
1534 opn = "rotr";
1535 break;
1536 #if defined(TARGET_MIPS64)
1537 case OPC_DSLL:
1538 tcg_gen_shli_tl(cpu_gpr[rt], t0, uimm);
1539 opn = "dsll";
1540 break;
1541 case OPC_DSRA:
1542 tcg_gen_sari_tl(cpu_gpr[rt], t0, uimm);
1543 opn = "dsra";
1544 break;
1545 case OPC_DSRL:
1546 tcg_gen_shri_tl(cpu_gpr[rt], t0, uimm);
1547 opn = "dsrl";
1548 break;
1549 case OPC_DROTR:
1550 if (uimm != 0) {
1551 tcg_gen_rotri_tl(cpu_gpr[rt], t0, uimm);
1552 } else {
1553 tcg_gen_mov_tl(cpu_gpr[rt], t0);
1555 opn = "drotr";
1556 break;
1557 case OPC_DSLL32:
1558 tcg_gen_shli_tl(cpu_gpr[rt], t0, uimm + 32);
1559 opn = "dsll32";
1560 break;
1561 case OPC_DSRA32:
1562 tcg_gen_sari_tl(cpu_gpr[rt], t0, uimm + 32);
1563 opn = "dsra32";
1564 break;
1565 case OPC_DSRL32:
1566 tcg_gen_shri_tl(cpu_gpr[rt], t0, uimm + 32);
1567 opn = "dsrl32";
1568 break;
1569 case OPC_DROTR32:
1570 tcg_gen_rotri_tl(cpu_gpr[rt], t0, uimm + 32);
1571 opn = "drotr32";
1572 break;
1573 #endif
1575 MIPS_DEBUG("%s %s, %s, " TARGET_FMT_lx, opn, regnames[rt], regnames[rs], uimm);
1576 tcg_temp_free(t0);
1579 /* Arithmetic */
1580 static void gen_arith (CPUState *env, DisasContext *ctx, uint32_t opc,
1581 int rd, int rs, int rt)
1583 const char *opn = "arith";
1585 if (rd == 0 && opc != OPC_ADD && opc != OPC_SUB
1586 && opc != OPC_DADD && opc != OPC_DSUB) {
1587 /* If no destination, treat it as a NOP.
1588 For add & sub, we must generate the overflow exception when needed. */
1589 MIPS_DEBUG("NOP");
1590 return;
1593 switch (opc) {
1594 case OPC_ADD:
1596 TCGv t0 = tcg_temp_local_new();
1597 TCGv t1 = tcg_temp_new();
1598 TCGv t2 = tcg_temp_new();
1599 int l1 = gen_new_label();
1601 gen_load_gpr(t1, rs);
1602 gen_load_gpr(t2, rt);
1603 tcg_gen_add_tl(t0, t1, t2);
1604 tcg_gen_ext32s_tl(t0, t0);
1605 tcg_gen_xor_tl(t1, t1, t2);
1606 tcg_gen_xor_tl(t2, t0, t2);
1607 tcg_gen_andc_tl(t1, t2, t1);
1608 tcg_temp_free(t2);
1609 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
1610 tcg_temp_free(t1);
1611 /* operands of same sign, result different sign */
1612 generate_exception(ctx, EXCP_OVERFLOW);
1613 gen_set_label(l1);
1614 gen_store_gpr(t0, rd);
1615 tcg_temp_free(t0);
1617 opn = "add";
1618 break;
1619 case OPC_ADDU:
1620 if (rs != 0 && rt != 0) {
1621 tcg_gen_add_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
1622 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
1623 } else if (rs == 0 && rt != 0) {
1624 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
1625 } else if (rs != 0 && rt == 0) {
1626 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
1627 } else {
1628 tcg_gen_movi_tl(cpu_gpr[rd], 0);
1630 opn = "addu";
1631 break;
1632 case OPC_SUB:
1634 TCGv t0 = tcg_temp_local_new();
1635 TCGv t1 = tcg_temp_new();
1636 TCGv t2 = tcg_temp_new();
1637 int l1 = gen_new_label();
1639 gen_load_gpr(t1, rs);
1640 gen_load_gpr(t2, rt);
1641 tcg_gen_sub_tl(t0, t1, t2);
1642 tcg_gen_ext32s_tl(t0, t0);
1643 tcg_gen_xor_tl(t2, t1, t2);
1644 tcg_gen_xor_tl(t1, t0, t1);
1645 tcg_gen_and_tl(t1, t1, t2);
1646 tcg_temp_free(t2);
1647 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
1648 tcg_temp_free(t1);
1649 /* operands of different sign, first operand and result different sign */
1650 generate_exception(ctx, EXCP_OVERFLOW);
1651 gen_set_label(l1);
1652 gen_store_gpr(t0, rd);
1653 tcg_temp_free(t0);
1655 opn = "sub";
1656 break;
1657 case OPC_SUBU:
1658 if (rs != 0 && rt != 0) {
1659 tcg_gen_sub_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
1660 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
1661 } else if (rs == 0 && rt != 0) {
1662 tcg_gen_neg_tl(cpu_gpr[rd], cpu_gpr[rt]);
1663 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
1664 } else if (rs != 0 && rt == 0) {
1665 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
1666 } else {
1667 tcg_gen_movi_tl(cpu_gpr[rd], 0);
1669 opn = "subu";
1670 break;
1671 #if defined(TARGET_MIPS64)
1672 case OPC_DADD:
1674 TCGv t0 = tcg_temp_local_new();
1675 TCGv t1 = tcg_temp_new();
1676 TCGv t2 = tcg_temp_new();
1677 int l1 = gen_new_label();
1679 gen_load_gpr(t1, rs);
1680 gen_load_gpr(t2, rt);
1681 tcg_gen_add_tl(t0, t1, t2);
1682 tcg_gen_xor_tl(t1, t1, t2);
1683 tcg_gen_xor_tl(t2, t0, t2);
1684 tcg_gen_andc_tl(t1, t2, t1);
1685 tcg_temp_free(t2);
1686 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
1687 tcg_temp_free(t1);
1688 /* operands of same sign, result different sign */
1689 generate_exception(ctx, EXCP_OVERFLOW);
1690 gen_set_label(l1);
1691 gen_store_gpr(t0, rd);
1692 tcg_temp_free(t0);
1694 opn = "dadd";
1695 break;
1696 case OPC_DADDU:
1697 if (rs != 0 && rt != 0) {
1698 tcg_gen_add_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
1699 } else if (rs == 0 && rt != 0) {
1700 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
1701 } else if (rs != 0 && rt == 0) {
1702 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
1703 } else {
1704 tcg_gen_movi_tl(cpu_gpr[rd], 0);
1706 opn = "daddu";
1707 break;
1708 case OPC_DSUB:
1710 TCGv t0 = tcg_temp_local_new();
1711 TCGv t1 = tcg_temp_new();
1712 TCGv t2 = tcg_temp_new();
1713 int l1 = gen_new_label();
1715 gen_load_gpr(t1, rs);
1716 gen_load_gpr(t2, rt);
1717 tcg_gen_sub_tl(t0, t1, t2);
1718 tcg_gen_xor_tl(t2, t1, t2);
1719 tcg_gen_xor_tl(t1, t0, t1);
1720 tcg_gen_and_tl(t1, t1, t2);
1721 tcg_temp_free(t2);
1722 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
1723 tcg_temp_free(t1);
1724 /* operands of different sign, first operand and result different sign */
1725 generate_exception(ctx, EXCP_OVERFLOW);
1726 gen_set_label(l1);
1727 gen_store_gpr(t0, rd);
1728 tcg_temp_free(t0);
1730 opn = "dsub";
1731 break;
1732 case OPC_DSUBU:
1733 if (rs != 0 && rt != 0) {
1734 tcg_gen_sub_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
1735 } else if (rs == 0 && rt != 0) {
1736 tcg_gen_neg_tl(cpu_gpr[rd], cpu_gpr[rt]);
1737 } else if (rs != 0 && rt == 0) {
1738 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
1739 } else {
1740 tcg_gen_movi_tl(cpu_gpr[rd], 0);
1742 opn = "dsubu";
1743 break;
1744 #endif
1745 case OPC_MUL:
1746 if (likely(rs != 0 && rt != 0)) {
1747 tcg_gen_mul_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
1748 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
1749 } else {
1750 tcg_gen_movi_tl(cpu_gpr[rd], 0);
1752 opn = "mul";
1753 break;
1755 MIPS_DEBUG("%s %s, %s, %s", opn, regnames[rd], regnames[rs], regnames[rt]);
1758 /* Conditional move */
1759 static void gen_cond_move (CPUState *env, uint32_t opc, int rd, int rs, int rt)
1761 const char *opn = "cond move";
1762 int l1;
1764 if (rd == 0) {
1765 /* If no destination, treat it as a NOP.
1766 For add & sub, we must generate the overflow exception when needed. */
1767 MIPS_DEBUG("NOP");
1768 return;
1771 l1 = gen_new_label();
1772 switch (opc) {
1773 case OPC_MOVN:
1774 if (likely(rt != 0))
1775 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[rt], 0, l1);
1776 else
1777 tcg_gen_br(l1);
1778 opn = "movn";
1779 break;
1780 case OPC_MOVZ:
1781 if (likely(rt != 0))
1782 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[rt], 0, l1);
1783 opn = "movz";
1784 break;
1786 if (rs != 0)
1787 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
1788 else
1789 tcg_gen_movi_tl(cpu_gpr[rd], 0);
1790 gen_set_label(l1);
1792 MIPS_DEBUG("%s %s, %s, %s", opn, regnames[rd], regnames[rs], regnames[rt]);
1795 /* Logic */
1796 static void gen_logic (CPUState *env, uint32_t opc, int rd, int rs, int rt)
1798 const char *opn = "logic";
1800 if (rd == 0) {
1801 /* If no destination, treat it as a NOP. */
1802 MIPS_DEBUG("NOP");
1803 return;
1806 switch (opc) {
1807 case OPC_AND:
1808 if (likely(rs != 0 && rt != 0)) {
1809 tcg_gen_and_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
1810 } else {
1811 tcg_gen_movi_tl(cpu_gpr[rd], 0);
1813 opn = "and";
1814 break;
1815 case OPC_NOR:
1816 if (rs != 0 && rt != 0) {
1817 tcg_gen_nor_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
1818 } else if (rs == 0 && rt != 0) {
1819 tcg_gen_not_tl(cpu_gpr[rd], cpu_gpr[rt]);
1820 } else if (rs != 0 && rt == 0) {
1821 tcg_gen_not_tl(cpu_gpr[rd], cpu_gpr[rs]);
1822 } else {
1823 tcg_gen_movi_tl(cpu_gpr[rd], ~((target_ulong)0));
1825 opn = "nor";
1826 break;
1827 case OPC_OR:
1828 if (likely(rs != 0 && rt != 0)) {
1829 tcg_gen_or_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
1830 } else if (rs == 0 && rt != 0) {
1831 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
1832 } else if (rs != 0 && rt == 0) {
1833 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
1834 } else {
1835 tcg_gen_movi_tl(cpu_gpr[rd], 0);
1837 opn = "or";
1838 break;
1839 case OPC_XOR:
1840 if (likely(rs != 0 && rt != 0)) {
1841 tcg_gen_xor_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
1842 } else if (rs == 0 && rt != 0) {
1843 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
1844 } else if (rs != 0 && rt == 0) {
1845 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
1846 } else {
1847 tcg_gen_movi_tl(cpu_gpr[rd], 0);
1849 opn = "xor";
1850 break;
1852 MIPS_DEBUG("%s %s, %s, %s", opn, regnames[rd], regnames[rs], regnames[rt]);
1855 /* Set on lower than */
1856 static void gen_slt (CPUState *env, uint32_t opc, int rd, int rs, int rt)
1858 const char *opn = "slt";
1859 TCGv t0, t1;
1861 if (rd == 0) {
1862 /* If no destination, treat it as a NOP. */
1863 MIPS_DEBUG("NOP");
1864 return;
1867 t0 = tcg_temp_new();
1868 t1 = tcg_temp_new();
1869 gen_load_gpr(t0, rs);
1870 gen_load_gpr(t1, rt);
1871 switch (opc) {
1872 case OPC_SLT:
1873 tcg_gen_setcond_tl(TCG_COND_LT, cpu_gpr[rd], t0, t1);
1874 opn = "slt";
1875 break;
1876 case OPC_SLTU:
1877 tcg_gen_setcond_tl(TCG_COND_LTU, cpu_gpr[rd], t0, t1);
1878 opn = "sltu";
1879 break;
1881 MIPS_DEBUG("%s %s, %s, %s", opn, regnames[rd], regnames[rs], regnames[rt]);
1882 tcg_temp_free(t0);
1883 tcg_temp_free(t1);
1886 /* Shifts */
1887 static void gen_shift (CPUState *env, DisasContext *ctx, uint32_t opc,
1888 int rd, int rs, int rt)
1890 const char *opn = "shifts";
1891 TCGv t0, t1;
1893 if (rd == 0) {
1894 /* If no destination, treat it as a NOP.
1895 For add & sub, we must generate the overflow exception when needed. */
1896 MIPS_DEBUG("NOP");
1897 return;
1900 t0 = tcg_temp_new();
1901 t1 = tcg_temp_new();
1902 gen_load_gpr(t0, rs);
1903 gen_load_gpr(t1, rt);
1904 switch (opc) {
1905 case OPC_SLLV:
1906 tcg_gen_andi_tl(t0, t0, 0x1f);
1907 tcg_gen_shl_tl(t0, t1, t0);
1908 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
1909 opn = "sllv";
1910 break;
1911 case OPC_SRAV:
1912 tcg_gen_andi_tl(t0, t0, 0x1f);
1913 tcg_gen_sar_tl(cpu_gpr[rd], t1, t0);
1914 opn = "srav";
1915 break;
1916 case OPC_SRLV:
1917 tcg_gen_ext32u_tl(t1, t1);
1918 tcg_gen_andi_tl(t0, t0, 0x1f);
1919 tcg_gen_shr_tl(t0, t1, t0);
1920 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
1921 opn = "srlv";
1922 break;
1923 case OPC_ROTRV:
1925 TCGv_i32 t2 = tcg_temp_new_i32();
1926 TCGv_i32 t3 = tcg_temp_new_i32();
1928 tcg_gen_trunc_tl_i32(t2, t0);
1929 tcg_gen_trunc_tl_i32(t3, t1);
1930 tcg_gen_andi_i32(t2, t2, 0x1f);
1931 tcg_gen_rotr_i32(t2, t3, t2);
1932 tcg_gen_ext_i32_tl(cpu_gpr[rd], t2);
1933 tcg_temp_free_i32(t2);
1934 tcg_temp_free_i32(t3);
1935 opn = "rotrv";
1937 break;
1938 #if defined(TARGET_MIPS64)
1939 case OPC_DSLLV:
1940 tcg_gen_andi_tl(t0, t0, 0x3f);
1941 tcg_gen_shl_tl(cpu_gpr[rd], t1, t0);
1942 opn = "dsllv";
1943 break;
1944 case OPC_DSRAV:
1945 tcg_gen_andi_tl(t0, t0, 0x3f);
1946 tcg_gen_sar_tl(cpu_gpr[rd], t1, t0);
1947 opn = "dsrav";
1948 break;
1949 case OPC_DSRLV:
1950 tcg_gen_andi_tl(t0, t0, 0x3f);
1951 tcg_gen_shr_tl(cpu_gpr[rd], t1, t0);
1952 opn = "dsrlv";
1953 break;
1954 case OPC_DROTRV:
1955 tcg_gen_andi_tl(t0, t0, 0x3f);
1956 tcg_gen_rotr_tl(cpu_gpr[rd], t1, t0);
1957 opn = "drotrv";
1958 break;
1959 #endif
1961 MIPS_DEBUG("%s %s, %s, %s", opn, regnames[rd], regnames[rs], regnames[rt]);
1962 tcg_temp_free(t0);
1963 tcg_temp_free(t1);
1966 /* Arithmetic on HI/LO registers */
1967 static void gen_HILO (DisasContext *ctx, uint32_t opc, int reg)
1969 const char *opn = "hilo";
1971 if (reg == 0 && (opc == OPC_MFHI || opc == OPC_MFLO)) {
1972 /* Treat as NOP. */
1973 MIPS_DEBUG("NOP");
1974 return;
1976 switch (opc) {
1977 case OPC_MFHI:
1978 tcg_gen_mov_tl(cpu_gpr[reg], cpu_HI[0]);
1979 opn = "mfhi";
1980 break;
1981 case OPC_MFLO:
1982 tcg_gen_mov_tl(cpu_gpr[reg], cpu_LO[0]);
1983 opn = "mflo";
1984 break;
1985 case OPC_MTHI:
1986 if (reg != 0)
1987 tcg_gen_mov_tl(cpu_HI[0], cpu_gpr[reg]);
1988 else
1989 tcg_gen_movi_tl(cpu_HI[0], 0);
1990 opn = "mthi";
1991 break;
1992 case OPC_MTLO:
1993 if (reg != 0)
1994 tcg_gen_mov_tl(cpu_LO[0], cpu_gpr[reg]);
1995 else
1996 tcg_gen_movi_tl(cpu_LO[0], 0);
1997 opn = "mtlo";
1998 break;
2000 MIPS_DEBUG("%s %s", opn, regnames[reg]);
2003 static void gen_muldiv (DisasContext *ctx, uint32_t opc,
2004 int rs, int rt)
2006 const char *opn = "mul/div";
2007 TCGv t0, t1;
2009 switch (opc) {
2010 case OPC_DIV:
2011 case OPC_DIVU:
2012 #if defined(TARGET_MIPS64)
2013 case OPC_DDIV:
2014 case OPC_DDIVU:
2015 #endif
2016 t0 = tcg_temp_local_new();
2017 t1 = tcg_temp_local_new();
2018 break;
2019 default:
2020 t0 = tcg_temp_new();
2021 t1 = tcg_temp_new();
2022 break;
2025 gen_load_gpr(t0, rs);
2026 gen_load_gpr(t1, rt);
2027 switch (opc) {
2028 case OPC_DIV:
2030 int l1 = gen_new_label();
2031 int l2 = gen_new_label();
2033 tcg_gen_ext32s_tl(t0, t0);
2034 tcg_gen_ext32s_tl(t1, t1);
2035 tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
2036 tcg_gen_brcondi_tl(TCG_COND_NE, t0, INT_MIN, l2);
2037 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1, l2);
2039 tcg_gen_mov_tl(cpu_LO[0], t0);
2040 tcg_gen_movi_tl(cpu_HI[0], 0);
2041 tcg_gen_br(l1);
2042 gen_set_label(l2);
2043 tcg_gen_div_tl(cpu_LO[0], t0, t1);
2044 tcg_gen_rem_tl(cpu_HI[0], t0, t1);
2045 tcg_gen_ext32s_tl(cpu_LO[0], cpu_LO[0]);
2046 tcg_gen_ext32s_tl(cpu_HI[0], cpu_HI[0]);
2047 gen_set_label(l1);
2049 opn = "div";
2050 break;
2051 case OPC_DIVU:
2053 int l1 = gen_new_label();
2055 tcg_gen_ext32u_tl(t0, t0);
2056 tcg_gen_ext32u_tl(t1, t1);
2057 tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
2058 tcg_gen_divu_tl(cpu_LO[0], t0, t1);
2059 tcg_gen_remu_tl(cpu_HI[0], t0, t1);
2060 tcg_gen_ext32s_tl(cpu_LO[0], cpu_LO[0]);
2061 tcg_gen_ext32s_tl(cpu_HI[0], cpu_HI[0]);
2062 gen_set_label(l1);
2064 opn = "divu";
2065 break;
2066 case OPC_MULT:
2068 TCGv_i64 t2 = tcg_temp_new_i64();
2069 TCGv_i64 t3 = tcg_temp_new_i64();
2071 tcg_gen_ext_tl_i64(t2, t0);
2072 tcg_gen_ext_tl_i64(t3, t1);
2073 tcg_gen_mul_i64(t2, t2, t3);
2074 tcg_temp_free_i64(t3);
2075 tcg_gen_trunc_i64_tl(t0, t2);
2076 tcg_gen_shri_i64(t2, t2, 32);
2077 tcg_gen_trunc_i64_tl(t1, t2);
2078 tcg_temp_free_i64(t2);
2079 tcg_gen_ext32s_tl(cpu_LO[0], t0);
2080 tcg_gen_ext32s_tl(cpu_HI[0], t1);
2082 opn = "mult";
2083 break;
2084 case OPC_MULTU:
2086 TCGv_i64 t2 = tcg_temp_new_i64();
2087 TCGv_i64 t3 = tcg_temp_new_i64();
2089 tcg_gen_ext32u_tl(t0, t0);
2090 tcg_gen_ext32u_tl(t1, t1);
2091 tcg_gen_extu_tl_i64(t2, t0);
2092 tcg_gen_extu_tl_i64(t3, t1);
2093 tcg_gen_mul_i64(t2, t2, t3);
2094 tcg_temp_free_i64(t3);
2095 tcg_gen_trunc_i64_tl(t0, t2);
2096 tcg_gen_shri_i64(t2, t2, 32);
2097 tcg_gen_trunc_i64_tl(t1, t2);
2098 tcg_temp_free_i64(t2);
2099 tcg_gen_ext32s_tl(cpu_LO[0], t0);
2100 tcg_gen_ext32s_tl(cpu_HI[0], t1);
2102 opn = "multu";
2103 break;
2104 #if defined(TARGET_MIPS64)
2105 case OPC_DDIV:
2107 int l1 = gen_new_label();
2108 int l2 = gen_new_label();
2110 tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
2111 tcg_gen_brcondi_tl(TCG_COND_NE, t0, -1LL << 63, l2);
2112 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1LL, l2);
2113 tcg_gen_mov_tl(cpu_LO[0], t0);
2114 tcg_gen_movi_tl(cpu_HI[0], 0);
2115 tcg_gen_br(l1);
2116 gen_set_label(l2);
2117 tcg_gen_div_i64(cpu_LO[0], t0, t1);
2118 tcg_gen_rem_i64(cpu_HI[0], t0, t1);
2119 gen_set_label(l1);
2121 opn = "ddiv";
2122 break;
2123 case OPC_DDIVU:
2125 int l1 = gen_new_label();
2127 tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
2128 tcg_gen_divu_i64(cpu_LO[0], t0, t1);
2129 tcg_gen_remu_i64(cpu_HI[0], t0, t1);
2130 gen_set_label(l1);
2132 opn = "ddivu";
2133 break;
2134 case OPC_DMULT:
2135 gen_helper_dmult(t0, t1);
2136 opn = "dmult";
2137 break;
2138 case OPC_DMULTU:
2139 gen_helper_dmultu(t0, t1);
2140 opn = "dmultu";
2141 break;
2142 #endif
2143 case OPC_MADD:
2145 TCGv_i64 t2 = tcg_temp_new_i64();
2146 TCGv_i64 t3 = tcg_temp_new_i64();
2148 tcg_gen_ext_tl_i64(t2, t0);
2149 tcg_gen_ext_tl_i64(t3, t1);
2150 tcg_gen_mul_i64(t2, t2, t3);
2151 tcg_gen_concat_tl_i64(t3, cpu_LO[0], cpu_HI[0]);
2152 tcg_gen_add_i64(t2, t2, t3);
2153 tcg_temp_free_i64(t3);
2154 tcg_gen_trunc_i64_tl(t0, t2);
2155 tcg_gen_shri_i64(t2, t2, 32);
2156 tcg_gen_trunc_i64_tl(t1, t2);
2157 tcg_temp_free_i64(t2);
2158 tcg_gen_ext32s_tl(cpu_LO[0], t0);
2159 tcg_gen_ext32s_tl(cpu_HI[0], t1);
2161 opn = "madd";
2162 break;
2163 case OPC_MADDU:
2165 TCGv_i64 t2 = tcg_temp_new_i64();
2166 TCGv_i64 t3 = tcg_temp_new_i64();
2168 tcg_gen_ext32u_tl(t0, t0);
2169 tcg_gen_ext32u_tl(t1, t1);
2170 tcg_gen_extu_tl_i64(t2, t0);
2171 tcg_gen_extu_tl_i64(t3, t1);
2172 tcg_gen_mul_i64(t2, t2, t3);
2173 tcg_gen_concat_tl_i64(t3, cpu_LO[0], cpu_HI[0]);
2174 tcg_gen_add_i64(t2, t2, t3);
2175 tcg_temp_free_i64(t3);
2176 tcg_gen_trunc_i64_tl(t0, t2);
2177 tcg_gen_shri_i64(t2, t2, 32);
2178 tcg_gen_trunc_i64_tl(t1, t2);
2179 tcg_temp_free_i64(t2);
2180 tcg_gen_ext32s_tl(cpu_LO[0], t0);
2181 tcg_gen_ext32s_tl(cpu_HI[0], t1);
2183 opn = "maddu";
2184 break;
2185 case OPC_MSUB:
2187 TCGv_i64 t2 = tcg_temp_new_i64();
2188 TCGv_i64 t3 = tcg_temp_new_i64();
2190 tcg_gen_ext_tl_i64(t2, t0);
2191 tcg_gen_ext_tl_i64(t3, t1);
2192 tcg_gen_mul_i64(t2, t2, t3);
2193 tcg_gen_concat_tl_i64(t3, cpu_LO[0], cpu_HI[0]);
2194 tcg_gen_sub_i64(t2, t3, t2);
2195 tcg_temp_free_i64(t3);
2196 tcg_gen_trunc_i64_tl(t0, t2);
2197 tcg_gen_shri_i64(t2, t2, 32);
2198 tcg_gen_trunc_i64_tl(t1, t2);
2199 tcg_temp_free_i64(t2);
2200 tcg_gen_ext32s_tl(cpu_LO[0], t0);
2201 tcg_gen_ext32s_tl(cpu_HI[0], t1);
2203 opn = "msub";
2204 break;
2205 case OPC_MSUBU:
2207 TCGv_i64 t2 = tcg_temp_new_i64();
2208 TCGv_i64 t3 = tcg_temp_new_i64();
2210 tcg_gen_ext32u_tl(t0, t0);
2211 tcg_gen_ext32u_tl(t1, t1);
2212 tcg_gen_extu_tl_i64(t2, t0);
2213 tcg_gen_extu_tl_i64(t3, t1);
2214 tcg_gen_mul_i64(t2, t2, t3);
2215 tcg_gen_concat_tl_i64(t3, cpu_LO[0], cpu_HI[0]);
2216 tcg_gen_sub_i64(t2, t3, t2);
2217 tcg_temp_free_i64(t3);
2218 tcg_gen_trunc_i64_tl(t0, t2);
2219 tcg_gen_shri_i64(t2, t2, 32);
2220 tcg_gen_trunc_i64_tl(t1, t2);
2221 tcg_temp_free_i64(t2);
2222 tcg_gen_ext32s_tl(cpu_LO[0], t0);
2223 tcg_gen_ext32s_tl(cpu_HI[0], t1);
2225 opn = "msubu";
2226 break;
2227 default:
2228 MIPS_INVAL(opn);
2229 generate_exception(ctx, EXCP_RI);
2230 goto out;
2232 MIPS_DEBUG("%s %s %s", opn, regnames[rs], regnames[rt]);
2233 out:
2234 tcg_temp_free(t0);
2235 tcg_temp_free(t1);
2238 static void gen_mul_vr54xx (DisasContext *ctx, uint32_t opc,
2239 int rd, int rs, int rt)
2241 const char *opn = "mul vr54xx";
2242 TCGv t0 = tcg_temp_new();
2243 TCGv t1 = tcg_temp_new();
2245 gen_load_gpr(t0, rs);
2246 gen_load_gpr(t1, rt);
2248 switch (opc) {
2249 case OPC_VR54XX_MULS:
2250 gen_helper_muls(t0, t0, t1);
2251 opn = "muls";
2252 break;
2253 case OPC_VR54XX_MULSU:
2254 gen_helper_mulsu(t0, t0, t1);
2255 opn = "mulsu";
2256 break;
2257 case OPC_VR54XX_MACC:
2258 gen_helper_macc(t0, t0, t1);
2259 opn = "macc";
2260 break;
2261 case OPC_VR54XX_MACCU:
2262 gen_helper_maccu(t0, t0, t1);
2263 opn = "maccu";
2264 break;
2265 case OPC_VR54XX_MSAC:
2266 gen_helper_msac(t0, t0, t1);
2267 opn = "msac";
2268 break;
2269 case OPC_VR54XX_MSACU:
2270 gen_helper_msacu(t0, t0, t1);
2271 opn = "msacu";
2272 break;
2273 case OPC_VR54XX_MULHI:
2274 gen_helper_mulhi(t0, t0, t1);
2275 opn = "mulhi";
2276 break;
2277 case OPC_VR54XX_MULHIU:
2278 gen_helper_mulhiu(t0, t0, t1);
2279 opn = "mulhiu";
2280 break;
2281 case OPC_VR54XX_MULSHI:
2282 gen_helper_mulshi(t0, t0, t1);
2283 opn = "mulshi";
2284 break;
2285 case OPC_VR54XX_MULSHIU:
2286 gen_helper_mulshiu(t0, t0, t1);
2287 opn = "mulshiu";
2288 break;
2289 case OPC_VR54XX_MACCHI:
2290 gen_helper_macchi(t0, t0, t1);
2291 opn = "macchi";
2292 break;
2293 case OPC_VR54XX_MACCHIU:
2294 gen_helper_macchiu(t0, t0, t1);
2295 opn = "macchiu";
2296 break;
2297 case OPC_VR54XX_MSACHI:
2298 gen_helper_msachi(t0, t0, t1);
2299 opn = "msachi";
2300 break;
2301 case OPC_VR54XX_MSACHIU:
2302 gen_helper_msachiu(t0, t0, t1);
2303 opn = "msachiu";
2304 break;
2305 default:
2306 MIPS_INVAL("mul vr54xx");
2307 generate_exception(ctx, EXCP_RI);
2308 goto out;
2310 gen_store_gpr(t0, rd);
2311 MIPS_DEBUG("%s %s, %s, %s", opn, regnames[rd], regnames[rs], regnames[rt]);
2313 out:
2314 tcg_temp_free(t0);
2315 tcg_temp_free(t1);
2318 static void gen_cl (DisasContext *ctx, uint32_t opc,
2319 int rd, int rs)
2321 const char *opn = "CLx";
2322 TCGv t0;
2324 if (rd == 0) {
2325 /* Treat as NOP. */
2326 MIPS_DEBUG("NOP");
2327 return;
2329 t0 = tcg_temp_new();
2330 gen_load_gpr(t0, rs);
2331 switch (opc) {
2332 case OPC_CLO:
2333 gen_helper_clo(cpu_gpr[rd], t0);
2334 opn = "clo";
2335 break;
2336 case OPC_CLZ:
2337 gen_helper_clz(cpu_gpr[rd], t0);
2338 opn = "clz";
2339 break;
2340 #if defined(TARGET_MIPS64)
2341 case OPC_DCLO:
2342 gen_helper_dclo(cpu_gpr[rd], t0);
2343 opn = "dclo";
2344 break;
2345 case OPC_DCLZ:
2346 gen_helper_dclz(cpu_gpr[rd], t0);
2347 opn = "dclz";
2348 break;
2349 #endif
2351 MIPS_DEBUG("%s %s, %s", opn, regnames[rd], regnames[rs]);
2352 tcg_temp_free(t0);
2355 /* Godson integer instructions */
2356 static void gen_loongson_integer (DisasContext *ctx, uint32_t opc,
2357 int rd, int rs, int rt)
2359 const char *opn = "loongson";
2360 TCGv t0, t1;
2362 if (rd == 0) {
2363 /* Treat as NOP. */
2364 MIPS_DEBUG("NOP");
2365 return;
2368 switch (opc) {
2369 case OPC_MULT_G_2E:
2370 case OPC_MULT_G_2F:
2371 case OPC_MULTU_G_2E:
2372 case OPC_MULTU_G_2F:
2373 #if defined(TARGET_MIPS64)
2374 case OPC_DMULT_G_2E:
2375 case OPC_DMULT_G_2F:
2376 case OPC_DMULTU_G_2E:
2377 case OPC_DMULTU_G_2F:
2378 #endif
2379 t0 = tcg_temp_new();
2380 t1 = tcg_temp_new();
2381 break;
2382 default:
2383 t0 = tcg_temp_local_new();
2384 t1 = tcg_temp_local_new();
2385 break;
2388 gen_load_gpr(t0, rs);
2389 gen_load_gpr(t1, rt);
2391 switch (opc) {
2392 case OPC_MULT_G_2E:
2393 case OPC_MULT_G_2F:
2394 tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
2395 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
2396 opn = "mult.g";
2397 break;
2398 case OPC_MULTU_G_2E:
2399 case OPC_MULTU_G_2F:
2400 tcg_gen_ext32u_tl(t0, t0);
2401 tcg_gen_ext32u_tl(t1, t1);
2402 tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
2403 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
2404 opn = "multu.g";
2405 break;
2406 case OPC_DIV_G_2E:
2407 case OPC_DIV_G_2F:
2409 int l1 = gen_new_label();
2410 int l2 = gen_new_label();
2411 int l3 = gen_new_label();
2412 tcg_gen_ext32s_tl(t0, t0);
2413 tcg_gen_ext32s_tl(t1, t1);
2414 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
2415 tcg_gen_movi_tl(cpu_gpr[rd], 0);
2416 tcg_gen_br(l3);
2417 gen_set_label(l1);
2418 tcg_gen_brcondi_tl(TCG_COND_NE, t0, INT_MIN, l2);
2419 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1, l2);
2420 tcg_gen_mov_tl(cpu_gpr[rd], t0);
2421 tcg_gen_br(l3);
2422 gen_set_label(l2);
2423 tcg_gen_div_tl(cpu_gpr[rd], t0, t1);
2424 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
2425 gen_set_label(l3);
2427 opn = "div.g";
2428 break;
2429 case OPC_DIVU_G_2E:
2430 case OPC_DIVU_G_2F:
2432 int l1 = gen_new_label();
2433 int l2 = gen_new_label();
2434 tcg_gen_ext32u_tl(t0, t0);
2435 tcg_gen_ext32u_tl(t1, t1);
2436 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
2437 tcg_gen_movi_tl(cpu_gpr[rd], 0);
2438 tcg_gen_br(l2);
2439 gen_set_label(l1);
2440 tcg_gen_divu_tl(cpu_gpr[rd], t0, t1);
2441 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
2442 gen_set_label(l2);
2444 opn = "divu.g";
2445 break;
2446 case OPC_MOD_G_2E:
2447 case OPC_MOD_G_2F:
2449 int l1 = gen_new_label();
2450 int l2 = gen_new_label();
2451 int l3 = gen_new_label();
2452 tcg_gen_ext32u_tl(t0, t0);
2453 tcg_gen_ext32u_tl(t1, t1);
2454 tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
2455 tcg_gen_brcondi_tl(TCG_COND_NE, t0, INT_MIN, l2);
2456 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1, l2);
2457 gen_set_label(l1);
2458 tcg_gen_movi_tl(cpu_gpr[rd], 0);
2459 tcg_gen_br(l3);
2460 gen_set_label(l2);
2461 tcg_gen_rem_tl(cpu_gpr[rd], t0, t1);
2462 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
2463 gen_set_label(l3);
2465 opn = "mod.g";
2466 break;
2467 case OPC_MODU_G_2E:
2468 case OPC_MODU_G_2F:
2470 int l1 = gen_new_label();
2471 int l2 = gen_new_label();
2472 tcg_gen_ext32u_tl(t0, t0);
2473 tcg_gen_ext32u_tl(t1, t1);
2474 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
2475 tcg_gen_movi_tl(cpu_gpr[rd], 0);
2476 tcg_gen_br(l2);
2477 gen_set_label(l1);
2478 tcg_gen_remu_tl(cpu_gpr[rd], t0, t1);
2479 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
2480 gen_set_label(l2);
2482 opn = "modu.g";
2483 break;
2484 #if defined(TARGET_MIPS64)
2485 case OPC_DMULT_G_2E:
2486 case OPC_DMULT_G_2F:
2487 tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
2488 opn = "dmult.g";
2489 break;
2490 case OPC_DMULTU_G_2E:
2491 case OPC_DMULTU_G_2F:
2492 tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
2493 opn = "dmultu.g";
2494 break;
2495 case OPC_DDIV_G_2E:
2496 case OPC_DDIV_G_2F:
2498 int l1 = gen_new_label();
2499 int l2 = gen_new_label();
2500 int l3 = gen_new_label();
2501 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
2502 tcg_gen_movi_tl(cpu_gpr[rd], 0);
2503 tcg_gen_br(l3);
2504 gen_set_label(l1);
2505 tcg_gen_brcondi_tl(TCG_COND_NE, t0, -1LL << 63, l2);
2506 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1LL, l2);
2507 tcg_gen_mov_tl(cpu_gpr[rd], t0);
2508 tcg_gen_br(l3);
2509 gen_set_label(l2);
2510 tcg_gen_div_tl(cpu_gpr[rd], t0, t1);
2511 gen_set_label(l3);
2513 opn = "ddiv.g";
2514 break;
2515 case OPC_DDIVU_G_2E:
2516 case OPC_DDIVU_G_2F:
2518 int l1 = gen_new_label();
2519 int l2 = gen_new_label();
2520 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
2521 tcg_gen_movi_tl(cpu_gpr[rd], 0);
2522 tcg_gen_br(l2);
2523 gen_set_label(l1);
2524 tcg_gen_divu_tl(cpu_gpr[rd], t0, t1);
2525 gen_set_label(l2);
2527 opn = "ddivu.g";
2528 break;
2529 case OPC_DMOD_G_2E:
2530 case OPC_DMOD_G_2F:
2532 int l1 = gen_new_label();
2533 int l2 = gen_new_label();
2534 int l3 = gen_new_label();
2535 tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
2536 tcg_gen_brcondi_tl(TCG_COND_NE, t0, -1LL << 63, l2);
2537 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1LL, l2);
2538 gen_set_label(l1);
2539 tcg_gen_movi_tl(cpu_gpr[rd], 0);
2540 tcg_gen_br(l3);
2541 gen_set_label(l2);
2542 tcg_gen_rem_tl(cpu_gpr[rd], t0, t1);
2543 gen_set_label(l3);
2545 opn = "dmod.g";
2546 break;
2547 case OPC_DMODU_G_2E:
2548 case OPC_DMODU_G_2F:
2550 int l1 = gen_new_label();
2551 int l2 = gen_new_label();
2552 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
2553 tcg_gen_movi_tl(cpu_gpr[rd], 0);
2554 tcg_gen_br(l2);
2555 gen_set_label(l1);
2556 tcg_gen_remu_tl(cpu_gpr[rd], t0, t1);
2557 gen_set_label(l2);
2559 opn = "dmodu.g";
2560 break;
2561 #endif
2564 MIPS_DEBUG("%s %s, %s", opn, regnames[rd], regnames[rs]);
2565 tcg_temp_free(t0);
2566 tcg_temp_free(t1);
2569 /* Traps */
2570 static void gen_trap (DisasContext *ctx, uint32_t opc,
2571 int rs, int rt, int16_t imm)
2573 int cond;
2574 TCGv t0 = tcg_temp_new();
2575 TCGv t1 = tcg_temp_new();
2577 cond = 0;
2578 /* Load needed operands */
2579 switch (opc) {
2580 case OPC_TEQ:
2581 case OPC_TGE:
2582 case OPC_TGEU:
2583 case OPC_TLT:
2584 case OPC_TLTU:
2585 case OPC_TNE:
2586 /* Compare two registers */
2587 if (rs != rt) {
2588 gen_load_gpr(t0, rs);
2589 gen_load_gpr(t1, rt);
2590 cond = 1;
2592 break;
2593 case OPC_TEQI:
2594 case OPC_TGEI:
2595 case OPC_TGEIU:
2596 case OPC_TLTI:
2597 case OPC_TLTIU:
2598 case OPC_TNEI:
2599 /* Compare register to immediate */
2600 if (rs != 0 || imm != 0) {
2601 gen_load_gpr(t0, rs);
2602 tcg_gen_movi_tl(t1, (int32_t)imm);
2603 cond = 1;
2605 break;
2607 if (cond == 0) {
2608 switch (opc) {
2609 case OPC_TEQ: /* rs == rs */
2610 case OPC_TEQI: /* r0 == 0 */
2611 case OPC_TGE: /* rs >= rs */
2612 case OPC_TGEI: /* r0 >= 0 */
2613 case OPC_TGEU: /* rs >= rs unsigned */
2614 case OPC_TGEIU: /* r0 >= 0 unsigned */
2615 /* Always trap */
2616 generate_exception(ctx, EXCP_TRAP);
2617 break;
2618 case OPC_TLT: /* rs < rs */
2619 case OPC_TLTI: /* r0 < 0 */
2620 case OPC_TLTU: /* rs < rs unsigned */
2621 case OPC_TLTIU: /* r0 < 0 unsigned */
2622 case OPC_TNE: /* rs != rs */
2623 case OPC_TNEI: /* r0 != 0 */
2624 /* Never trap: treat as NOP. */
2625 break;
2627 } else {
2628 int l1 = gen_new_label();
2630 switch (opc) {
2631 case OPC_TEQ:
2632 case OPC_TEQI:
2633 tcg_gen_brcond_tl(TCG_COND_NE, t0, t1, l1);
2634 break;
2635 case OPC_TGE:
2636 case OPC_TGEI:
2637 tcg_gen_brcond_tl(TCG_COND_LT, t0, t1, l1);
2638 break;
2639 case OPC_TGEU:
2640 case OPC_TGEIU:
2641 tcg_gen_brcond_tl(TCG_COND_LTU, t0, t1, l1);
2642 break;
2643 case OPC_TLT:
2644 case OPC_TLTI:
2645 tcg_gen_brcond_tl(TCG_COND_GE, t0, t1, l1);
2646 break;
2647 case OPC_TLTU:
2648 case OPC_TLTIU:
2649 tcg_gen_brcond_tl(TCG_COND_GEU, t0, t1, l1);
2650 break;
2651 case OPC_TNE:
2652 case OPC_TNEI:
2653 tcg_gen_brcond_tl(TCG_COND_EQ, t0, t1, l1);
2654 break;
2656 generate_exception(ctx, EXCP_TRAP);
2657 gen_set_label(l1);
2659 tcg_temp_free(t0);
2660 tcg_temp_free(t1);
2663 static inline void gen_goto_tb(DisasContext *ctx, int n, target_ulong dest)
2665 TranslationBlock *tb;
2666 tb = ctx->tb;
2667 if ((tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK) &&
2668 likely(!ctx->singlestep_enabled)) {
2669 tcg_gen_goto_tb(n);
2670 gen_save_pc(dest);
2671 tcg_gen_exit_tb((long)tb + n);
2672 } else {
2673 gen_save_pc(dest);
2674 if (ctx->singlestep_enabled) {
2675 save_cpu_state(ctx, 0);
2676 gen_helper_0i(raise_exception, EXCP_DEBUG);
2678 tcg_gen_exit_tb(0);
2682 /* Branches (before delay slot) */
2683 static void gen_compute_branch (DisasContext *ctx, uint32_t opc,
2684 int insn_bytes,
2685 int rs, int rt, int32_t offset)
2687 target_ulong btgt = -1;
2688 int blink = 0;
2689 int bcond_compute = 0;
2690 TCGv t0 = tcg_temp_new();
2691 TCGv t1 = tcg_temp_new();
2693 if (ctx->hflags & MIPS_HFLAG_BMASK) {
2694 #ifdef MIPS_DEBUG_DISAS
2695 LOG_DISAS("Branch in delay slot at PC 0x" TARGET_FMT_lx "\n", ctx->pc);
2696 #endif
2697 generate_exception(ctx, EXCP_RI);
2698 goto out;
2701 /* Load needed operands */
2702 switch (opc) {
2703 case OPC_BEQ:
2704 case OPC_BEQL:
2705 case OPC_BNE:
2706 case OPC_BNEL:
2707 /* Compare two registers */
2708 if (rs != rt) {
2709 gen_load_gpr(t0, rs);
2710 gen_load_gpr(t1, rt);
2711 bcond_compute = 1;
2713 btgt = ctx->pc + insn_bytes + offset;
2714 break;
2715 case OPC_BGEZ:
2716 case OPC_BGEZAL:
2717 case OPC_BGEZALS:
2718 case OPC_BGEZALL:
2719 case OPC_BGEZL:
2720 case OPC_BGTZ:
2721 case OPC_BGTZL:
2722 case OPC_BLEZ:
2723 case OPC_BLEZL:
2724 case OPC_BLTZ:
2725 case OPC_BLTZAL:
2726 case OPC_BLTZALS:
2727 case OPC_BLTZALL:
2728 case OPC_BLTZL:
2729 /* Compare to zero */
2730 if (rs != 0) {
2731 gen_load_gpr(t0, rs);
2732 bcond_compute = 1;
2734 btgt = ctx->pc + insn_bytes + offset;
2735 break;
2736 case OPC_J:
2737 case OPC_JAL:
2738 case OPC_JALX:
2739 case OPC_JALS:
2740 case OPC_JALXS:
2741 /* Jump to immediate */
2742 btgt = ((ctx->pc + insn_bytes) & (int32_t)0xF0000000) | (uint32_t)offset;
2743 break;
2744 case OPC_JR:
2745 case OPC_JALR:
2746 case OPC_JALRC:
2747 case OPC_JALRS:
2748 /* Jump to register */
2749 if (offset != 0 && offset != 16) {
2750 /* Hint = 0 is JR/JALR, hint 16 is JR.HB/JALR.HB, the
2751 others are reserved. */
2752 MIPS_INVAL("jump hint");
2753 generate_exception(ctx, EXCP_RI);
2754 goto out;
2756 gen_load_gpr(btarget, rs);
2757 break;
2758 default:
2759 MIPS_INVAL("branch/jump");
2760 generate_exception(ctx, EXCP_RI);
2761 goto out;
2763 if (bcond_compute == 0) {
2764 /* No condition to be computed */
2765 switch (opc) {
2766 case OPC_BEQ: /* rx == rx */
2767 case OPC_BEQL: /* rx == rx likely */
2768 case OPC_BGEZ: /* 0 >= 0 */
2769 case OPC_BGEZL: /* 0 >= 0 likely */
2770 case OPC_BLEZ: /* 0 <= 0 */
2771 case OPC_BLEZL: /* 0 <= 0 likely */
2772 /* Always take */
2773 ctx->hflags |= MIPS_HFLAG_B;
2774 MIPS_DEBUG("balways");
2775 break;
2776 case OPC_BGEZALS:
2777 case OPC_BGEZAL: /* 0 >= 0 */
2778 case OPC_BGEZALL: /* 0 >= 0 likely */
2779 ctx->hflags |= (opc == OPC_BGEZALS
2780 ? MIPS_HFLAG_BDS16
2781 : MIPS_HFLAG_BDS32);
2782 /* Always take and link */
2783 blink = 31;
2784 ctx->hflags |= MIPS_HFLAG_B;
2785 MIPS_DEBUG("balways and link");
2786 break;
2787 case OPC_BNE: /* rx != rx */
2788 case OPC_BGTZ: /* 0 > 0 */
2789 case OPC_BLTZ: /* 0 < 0 */
2790 /* Treat as NOP. */
2791 MIPS_DEBUG("bnever (NOP)");
2792 goto out;
2793 case OPC_BLTZALS:
2794 case OPC_BLTZAL: /* 0 < 0 */
2795 ctx->hflags |= (opc == OPC_BLTZALS
2796 ? MIPS_HFLAG_BDS16
2797 : MIPS_HFLAG_BDS32);
2798 /* Handle as an unconditional branch to get correct delay
2799 slot checking. */
2800 blink = 31;
2801 btgt = ctx->pc + (opc == OPC_BLTZALS ? 6 : 8);
2802 ctx->hflags |= MIPS_HFLAG_B;
2803 MIPS_DEBUG("bnever and link");
2804 break;
2805 case OPC_BLTZALL: /* 0 < 0 likely */
2806 tcg_gen_movi_tl(cpu_gpr[31], ctx->pc + 8);
2807 /* Skip the instruction in the delay slot */
2808 MIPS_DEBUG("bnever, link and skip");
2809 ctx->pc += 4;
2810 goto out;
2811 case OPC_BNEL: /* rx != rx likely */
2812 case OPC_BGTZL: /* 0 > 0 likely */
2813 case OPC_BLTZL: /* 0 < 0 likely */
2814 /* Skip the instruction in the delay slot */
2815 MIPS_DEBUG("bnever and skip");
2816 ctx->pc += 4;
2817 goto out;
2818 case OPC_J:
2819 ctx->hflags |= MIPS_HFLAG_B;
2820 MIPS_DEBUG("j " TARGET_FMT_lx, btgt);
2821 break;
2822 case OPC_JALXS:
2823 case OPC_JALX:
2824 ctx->hflags |= MIPS_HFLAG_BX;
2825 /* Fallthrough */
2826 case OPC_JALS:
2827 case OPC_JAL:
2828 blink = 31;
2829 ctx->hflags |= MIPS_HFLAG_B;
2830 ctx->hflags |= ((opc == OPC_JALS || opc == OPC_JALXS)
2831 ? MIPS_HFLAG_BDS16
2832 : MIPS_HFLAG_BDS32);
2833 MIPS_DEBUG("jal " TARGET_FMT_lx, btgt);
2834 break;
2835 case OPC_JR:
2836 ctx->hflags |= MIPS_HFLAG_BR;
2837 if (insn_bytes == 4)
2838 ctx->hflags |= MIPS_HFLAG_BDS32;
2839 MIPS_DEBUG("jr %s", regnames[rs]);
2840 break;
2841 case OPC_JALRS:
2842 case OPC_JALR:
2843 case OPC_JALRC:
2844 blink = rt;
2845 ctx->hflags |= MIPS_HFLAG_BR;
2846 ctx->hflags |= (opc == OPC_JALRS
2847 ? MIPS_HFLAG_BDS16
2848 : MIPS_HFLAG_BDS32);
2849 MIPS_DEBUG("jalr %s, %s", regnames[rt], regnames[rs]);
2850 break;
2851 default:
2852 MIPS_INVAL("branch/jump");
2853 generate_exception(ctx, EXCP_RI);
2854 goto out;
2856 } else {
2857 switch (opc) {
2858 case OPC_BEQ:
2859 tcg_gen_setcond_tl(TCG_COND_EQ, bcond, t0, t1);
2860 MIPS_DEBUG("beq %s, %s, " TARGET_FMT_lx,
2861 regnames[rs], regnames[rt], btgt);
2862 goto not_likely;
2863 case OPC_BEQL:
2864 tcg_gen_setcond_tl(TCG_COND_EQ, bcond, t0, t1);
2865 MIPS_DEBUG("beql %s, %s, " TARGET_FMT_lx,
2866 regnames[rs], regnames[rt], btgt);
2867 goto likely;
2868 case OPC_BNE:
2869 tcg_gen_setcond_tl(TCG_COND_NE, bcond, t0, t1);
2870 MIPS_DEBUG("bne %s, %s, " TARGET_FMT_lx,
2871 regnames[rs], regnames[rt], btgt);
2872 goto not_likely;
2873 case OPC_BNEL:
2874 tcg_gen_setcond_tl(TCG_COND_NE, bcond, t0, t1);
2875 MIPS_DEBUG("bnel %s, %s, " TARGET_FMT_lx,
2876 regnames[rs], regnames[rt], btgt);
2877 goto likely;
2878 case OPC_BGEZ:
2879 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
2880 MIPS_DEBUG("bgez %s, " TARGET_FMT_lx, regnames[rs], btgt);
2881 goto not_likely;
2882 case OPC_BGEZL:
2883 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
2884 MIPS_DEBUG("bgezl %s, " TARGET_FMT_lx, regnames[rs], btgt);
2885 goto likely;
2886 case OPC_BGEZALS:
2887 case OPC_BGEZAL:
2888 ctx->hflags |= (opc == OPC_BGEZALS
2889 ? MIPS_HFLAG_BDS16
2890 : MIPS_HFLAG_BDS32);
2891 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
2892 MIPS_DEBUG("bgezal %s, " TARGET_FMT_lx, regnames[rs], btgt);
2893 blink = 31;
2894 goto not_likely;
2895 case OPC_BGEZALL:
2896 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
2897 blink = 31;
2898 MIPS_DEBUG("bgezall %s, " TARGET_FMT_lx, regnames[rs], btgt);
2899 goto likely;
2900 case OPC_BGTZ:
2901 tcg_gen_setcondi_tl(TCG_COND_GT, bcond, t0, 0);
2902 MIPS_DEBUG("bgtz %s, " TARGET_FMT_lx, regnames[rs], btgt);
2903 goto not_likely;
2904 case OPC_BGTZL:
2905 tcg_gen_setcondi_tl(TCG_COND_GT, bcond, t0, 0);
2906 MIPS_DEBUG("bgtzl %s, " TARGET_FMT_lx, regnames[rs], btgt);
2907 goto likely;
2908 case OPC_BLEZ:
2909 tcg_gen_setcondi_tl(TCG_COND_LE, bcond, t0, 0);
2910 MIPS_DEBUG("blez %s, " TARGET_FMT_lx, regnames[rs], btgt);
2911 goto not_likely;
2912 case OPC_BLEZL:
2913 tcg_gen_setcondi_tl(TCG_COND_LE, bcond, t0, 0);
2914 MIPS_DEBUG("blezl %s, " TARGET_FMT_lx, regnames[rs], btgt);
2915 goto likely;
2916 case OPC_BLTZ:
2917 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
2918 MIPS_DEBUG("bltz %s, " TARGET_FMT_lx, regnames[rs], btgt);
2919 goto not_likely;
2920 case OPC_BLTZL:
2921 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
2922 MIPS_DEBUG("bltzl %s, " TARGET_FMT_lx, regnames[rs], btgt);
2923 goto likely;
2924 case OPC_BLTZALS:
2925 case OPC_BLTZAL:
2926 ctx->hflags |= (opc == OPC_BLTZALS
2927 ? MIPS_HFLAG_BDS16
2928 : MIPS_HFLAG_BDS32);
2929 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
2930 blink = 31;
2931 MIPS_DEBUG("bltzal %s, " TARGET_FMT_lx, regnames[rs], btgt);
2932 not_likely:
2933 ctx->hflags |= MIPS_HFLAG_BC;
2934 break;
2935 case OPC_BLTZALL:
2936 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
2937 blink = 31;
2938 MIPS_DEBUG("bltzall %s, " TARGET_FMT_lx, regnames[rs], btgt);
2939 likely:
2940 ctx->hflags |= MIPS_HFLAG_BL;
2941 break;
2942 default:
2943 MIPS_INVAL("conditional branch/jump");
2944 generate_exception(ctx, EXCP_RI);
2945 goto out;
2948 MIPS_DEBUG("enter ds: link %d cond %02x target " TARGET_FMT_lx,
2949 blink, ctx->hflags, btgt);
2951 ctx->btarget = btgt;
2952 if (blink > 0) {
2953 int post_delay = insn_bytes;
2954 int lowbit = !!(ctx->hflags & MIPS_HFLAG_M16);
2956 if (opc != OPC_JALRC)
2957 post_delay += ((ctx->hflags & MIPS_HFLAG_BDS16) ? 2 : 4);
2959 tcg_gen_movi_tl(cpu_gpr[blink], ctx->pc + post_delay + lowbit);
2962 out:
2963 if (insn_bytes == 2)
2964 ctx->hflags |= MIPS_HFLAG_B16;
2965 tcg_temp_free(t0);
2966 tcg_temp_free(t1);
2969 /* special3 bitfield operations */
2970 static void gen_bitops (DisasContext *ctx, uint32_t opc, int rt,
2971 int rs, int lsb, int msb)
2973 TCGv t0 = tcg_temp_new();
2974 TCGv t1 = tcg_temp_new();
2975 target_ulong mask;
2977 gen_load_gpr(t1, rs);
2978 switch (opc) {
2979 case OPC_EXT:
2980 if (lsb + msb > 31)
2981 goto fail;
2982 tcg_gen_shri_tl(t0, t1, lsb);
2983 if (msb != 31) {
2984 tcg_gen_andi_tl(t0, t0, (1 << (msb + 1)) - 1);
2985 } else {
2986 tcg_gen_ext32s_tl(t0, t0);
2988 break;
2989 #if defined(TARGET_MIPS64)
2990 case OPC_DEXTM:
2991 tcg_gen_shri_tl(t0, t1, lsb);
2992 if (msb != 31) {
2993 tcg_gen_andi_tl(t0, t0, (1ULL << (msb + 1 + 32)) - 1);
2995 break;
2996 case OPC_DEXTU:
2997 tcg_gen_shri_tl(t0, t1, lsb + 32);
2998 tcg_gen_andi_tl(t0, t0, (1ULL << (msb + 1)) - 1);
2999 break;
3000 case OPC_DEXT:
3001 tcg_gen_shri_tl(t0, t1, lsb);
3002 tcg_gen_andi_tl(t0, t0, (1ULL << (msb + 1)) - 1);
3003 break;
3004 #endif
3005 case OPC_INS:
3006 if (lsb > msb)
3007 goto fail;
3008 mask = ((msb - lsb + 1 < 32) ? ((1 << (msb - lsb + 1)) - 1) : ~0) << lsb;
3009 gen_load_gpr(t0, rt);
3010 tcg_gen_andi_tl(t0, t0, ~mask);
3011 tcg_gen_shli_tl(t1, t1, lsb);
3012 tcg_gen_andi_tl(t1, t1, mask);
3013 tcg_gen_or_tl(t0, t0, t1);
3014 tcg_gen_ext32s_tl(t0, t0);
3015 break;
3016 #if defined(TARGET_MIPS64)
3017 case OPC_DINSM:
3018 if (lsb > msb)
3019 goto fail;
3020 mask = ((msb - lsb + 1 + 32 < 64) ? ((1ULL << (msb - lsb + 1 + 32)) - 1) : ~0ULL) << lsb;
3021 gen_load_gpr(t0, rt);
3022 tcg_gen_andi_tl(t0, t0, ~mask);
3023 tcg_gen_shli_tl(t1, t1, lsb);
3024 tcg_gen_andi_tl(t1, t1, mask);
3025 tcg_gen_or_tl(t0, t0, t1);
3026 break;
3027 case OPC_DINSU:
3028 if (lsb > msb)
3029 goto fail;
3030 mask = ((1ULL << (msb - lsb + 1)) - 1) << (lsb + 32);
3031 gen_load_gpr(t0, rt);
3032 tcg_gen_andi_tl(t0, t0, ~mask);
3033 tcg_gen_shli_tl(t1, t1, lsb + 32);
3034 tcg_gen_andi_tl(t1, t1, mask);
3035 tcg_gen_or_tl(t0, t0, t1);
3036 break;
3037 case OPC_DINS:
3038 if (lsb > msb)
3039 goto fail;
3040 gen_load_gpr(t0, rt);
3041 mask = ((1ULL << (msb - lsb + 1)) - 1) << lsb;
3042 gen_load_gpr(t0, rt);
3043 tcg_gen_andi_tl(t0, t0, ~mask);
3044 tcg_gen_shli_tl(t1, t1, lsb);
3045 tcg_gen_andi_tl(t1, t1, mask);
3046 tcg_gen_or_tl(t0, t0, t1);
3047 break;
3048 #endif
3049 default:
3050 fail:
3051 MIPS_INVAL("bitops");
3052 generate_exception(ctx, EXCP_RI);
3053 tcg_temp_free(t0);
3054 tcg_temp_free(t1);
3055 return;
3057 gen_store_gpr(t0, rt);
3058 tcg_temp_free(t0);
3059 tcg_temp_free(t1);
3062 static void gen_bshfl (DisasContext *ctx, uint32_t op2, int rt, int rd)
3064 TCGv t0;
3066 if (rd == 0) {
3067 /* If no destination, treat it as a NOP. */
3068 MIPS_DEBUG("NOP");
3069 return;
3072 t0 = tcg_temp_new();
3073 gen_load_gpr(t0, rt);
3074 switch (op2) {
3075 case OPC_WSBH:
3077 TCGv t1 = tcg_temp_new();
3079 tcg_gen_shri_tl(t1, t0, 8);
3080 tcg_gen_andi_tl(t1, t1, 0x00FF00FF);
3081 tcg_gen_shli_tl(t0, t0, 8);
3082 tcg_gen_andi_tl(t0, t0, ~0x00FF00FF);
3083 tcg_gen_or_tl(t0, t0, t1);
3084 tcg_temp_free(t1);
3085 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
3087 break;
3088 case OPC_SEB:
3089 tcg_gen_ext8s_tl(cpu_gpr[rd], t0);
3090 break;
3091 case OPC_SEH:
3092 tcg_gen_ext16s_tl(cpu_gpr[rd], t0);
3093 break;
3094 #if defined(TARGET_MIPS64)
3095 case OPC_DSBH:
3097 TCGv t1 = tcg_temp_new();
3099 tcg_gen_shri_tl(t1, t0, 8);
3100 tcg_gen_andi_tl(t1, t1, 0x00FF00FF00FF00FFULL);
3101 tcg_gen_shli_tl(t0, t0, 8);
3102 tcg_gen_andi_tl(t0, t0, ~0x00FF00FF00FF00FFULL);
3103 tcg_gen_or_tl(cpu_gpr[rd], t0, t1);
3104 tcg_temp_free(t1);
3106 break;
3107 case OPC_DSHD:
3109 TCGv t1 = tcg_temp_new();
3111 tcg_gen_shri_tl(t1, t0, 16);
3112 tcg_gen_andi_tl(t1, t1, 0x0000FFFF0000FFFFULL);
3113 tcg_gen_shli_tl(t0, t0, 16);
3114 tcg_gen_andi_tl(t0, t0, ~0x0000FFFF0000FFFFULL);
3115 tcg_gen_or_tl(t0, t0, t1);
3116 tcg_gen_shri_tl(t1, t0, 32);
3117 tcg_gen_shli_tl(t0, t0, 32);
3118 tcg_gen_or_tl(cpu_gpr[rd], t0, t1);
3119 tcg_temp_free(t1);
3121 break;
3122 #endif
3123 default:
3124 MIPS_INVAL("bsfhl");
3125 generate_exception(ctx, EXCP_RI);
3126 tcg_temp_free(t0);
3127 return;
3129 tcg_temp_free(t0);
3132 #ifndef CONFIG_USER_ONLY
3133 /* CP0 (MMU and control) */
3134 static inline void gen_mfc0_load32 (TCGv arg, target_ulong off)
3136 TCGv_i32 t0 = tcg_temp_new_i32();
3138 tcg_gen_ld_i32(t0, cpu_env, off);
3139 tcg_gen_ext_i32_tl(arg, t0);
3140 tcg_temp_free_i32(t0);
3143 static inline void gen_mfc0_load64 (TCGv arg, target_ulong off)
3145 tcg_gen_ld_tl(arg, cpu_env, off);
3146 tcg_gen_ext32s_tl(arg, arg);
3149 static inline void gen_mtc0_store32 (TCGv arg, target_ulong off)
3151 TCGv_i32 t0 = tcg_temp_new_i32();
3153 tcg_gen_trunc_tl_i32(t0, arg);
3154 tcg_gen_st_i32(t0, cpu_env, off);
3155 tcg_temp_free_i32(t0);
3158 static inline void gen_mtc0_store64 (TCGv arg, target_ulong off)
3160 tcg_gen_ext32s_tl(arg, arg);
3161 tcg_gen_st_tl(arg, cpu_env, off);
3164 static void gen_mfc0 (CPUState *env, DisasContext *ctx, TCGv arg, int reg, int sel)
3166 const char *rn = "invalid";
3168 if (sel != 0)
3169 check_insn(env, ctx, ISA_MIPS32);
3171 switch (reg) {
3172 case 0:
3173 switch (sel) {
3174 case 0:
3175 gen_mfc0_load32(arg, offsetof(CPUState, CP0_Index));
3176 rn = "Index";
3177 break;
3178 case 1:
3179 check_insn(env, ctx, ASE_MT);
3180 gen_helper_mfc0_mvpcontrol(arg);
3181 rn = "MVPControl";
3182 break;
3183 case 2:
3184 check_insn(env, ctx, ASE_MT);
3185 gen_helper_mfc0_mvpconf0(arg);
3186 rn = "MVPConf0";
3187 break;
3188 case 3:
3189 check_insn(env, ctx, ASE_MT);
3190 gen_helper_mfc0_mvpconf1(arg);
3191 rn = "MVPConf1";
3192 break;
3193 default:
3194 goto die;
3196 break;
3197 case 1:
3198 switch (sel) {
3199 case 0:
3200 gen_helper_mfc0_random(arg);
3201 rn = "Random";
3202 break;
3203 case 1:
3204 check_insn(env, ctx, ASE_MT);
3205 gen_mfc0_load32(arg, offsetof(CPUState, CP0_VPEControl));
3206 rn = "VPEControl";
3207 break;
3208 case 2:
3209 check_insn(env, ctx, ASE_MT);
3210 gen_mfc0_load32(arg, offsetof(CPUState, CP0_VPEConf0));
3211 rn = "VPEConf0";
3212 break;
3213 case 3:
3214 check_insn(env, ctx, ASE_MT);
3215 gen_mfc0_load32(arg, offsetof(CPUState, CP0_VPEConf1));
3216 rn = "VPEConf1";
3217 break;
3218 case 4:
3219 check_insn(env, ctx, ASE_MT);
3220 gen_mfc0_load64(arg, offsetof(CPUState, CP0_YQMask));
3221 rn = "YQMask";
3222 break;
3223 case 5:
3224 check_insn(env, ctx, ASE_MT);
3225 gen_mfc0_load64(arg, offsetof(CPUState, CP0_VPESchedule));
3226 rn = "VPESchedule";
3227 break;
3228 case 6:
3229 check_insn(env, ctx, ASE_MT);
3230 gen_mfc0_load64(arg, offsetof(CPUState, CP0_VPEScheFBack));
3231 rn = "VPEScheFBack";
3232 break;
3233 case 7:
3234 check_insn(env, ctx, ASE_MT);
3235 gen_mfc0_load32(arg, offsetof(CPUState, CP0_VPEOpt));
3236 rn = "VPEOpt";
3237 break;
3238 default:
3239 goto die;
3241 break;
3242 case 2:
3243 switch (sel) {
3244 case 0:
3245 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_EntryLo0));
3246 tcg_gen_ext32s_tl(arg, arg);
3247 rn = "EntryLo0";
3248 break;
3249 case 1:
3250 check_insn(env, ctx, ASE_MT);
3251 gen_helper_mfc0_tcstatus(arg);
3252 rn = "TCStatus";
3253 break;
3254 case 2:
3255 check_insn(env, ctx, ASE_MT);
3256 gen_helper_mfc0_tcbind(arg);
3257 rn = "TCBind";
3258 break;
3259 case 3:
3260 check_insn(env, ctx, ASE_MT);
3261 gen_helper_mfc0_tcrestart(arg);
3262 rn = "TCRestart";
3263 break;
3264 case 4:
3265 check_insn(env, ctx, ASE_MT);
3266 gen_helper_mfc0_tchalt(arg);
3267 rn = "TCHalt";
3268 break;
3269 case 5:
3270 check_insn(env, ctx, ASE_MT);
3271 gen_helper_mfc0_tccontext(arg);
3272 rn = "TCContext";
3273 break;
3274 case 6:
3275 check_insn(env, ctx, ASE_MT);
3276 gen_helper_mfc0_tcschedule(arg);
3277 rn = "TCSchedule";
3278 break;
3279 case 7:
3280 check_insn(env, ctx, ASE_MT);
3281 gen_helper_mfc0_tcschefback(arg);
3282 rn = "TCScheFBack";
3283 break;
3284 default:
3285 goto die;
3287 break;
3288 case 3:
3289 switch (sel) {
3290 case 0:
3291 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_EntryLo1));
3292 tcg_gen_ext32s_tl(arg, arg);
3293 rn = "EntryLo1";
3294 break;
3295 default:
3296 goto die;
3298 break;
3299 case 4:
3300 switch (sel) {
3301 case 0:
3302 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_Context));
3303 tcg_gen_ext32s_tl(arg, arg);
3304 rn = "Context";
3305 break;
3306 case 1:
3307 // gen_helper_mfc0_contextconfig(arg); /* SmartMIPS ASE */
3308 rn = "ContextConfig";
3309 // break;
3310 default:
3311 goto die;
3313 break;
3314 case 5:
3315 switch (sel) {
3316 case 0:
3317 gen_mfc0_load32(arg, offsetof(CPUState, CP0_PageMask));
3318 rn = "PageMask";
3319 break;
3320 case 1:
3321 check_insn(env, ctx, ISA_MIPS32R2);
3322 gen_mfc0_load32(arg, offsetof(CPUState, CP0_PageGrain));
3323 rn = "PageGrain";
3324 break;
3325 default:
3326 goto die;
3328 break;
3329 case 6:
3330 switch (sel) {
3331 case 0:
3332 gen_mfc0_load32(arg, offsetof(CPUState, CP0_Wired));
3333 rn = "Wired";
3334 break;
3335 case 1:
3336 check_insn(env, ctx, ISA_MIPS32R2);
3337 gen_mfc0_load32(arg, offsetof(CPUState, CP0_SRSConf0));
3338 rn = "SRSConf0";
3339 break;
3340 case 2:
3341 check_insn(env, ctx, ISA_MIPS32R2);
3342 gen_mfc0_load32(arg, offsetof(CPUState, CP0_SRSConf1));
3343 rn = "SRSConf1";
3344 break;
3345 case 3:
3346 check_insn(env, ctx, ISA_MIPS32R2);
3347 gen_mfc0_load32(arg, offsetof(CPUState, CP0_SRSConf2));
3348 rn = "SRSConf2";
3349 break;
3350 case 4:
3351 check_insn(env, ctx, ISA_MIPS32R2);
3352 gen_mfc0_load32(arg, offsetof(CPUState, CP0_SRSConf3));
3353 rn = "SRSConf3";
3354 break;
3355 case 5:
3356 check_insn(env, ctx, ISA_MIPS32R2);
3357 gen_mfc0_load32(arg, offsetof(CPUState, CP0_SRSConf4));
3358 rn = "SRSConf4";
3359 break;
3360 default:
3361 goto die;
3363 break;
3364 case 7:
3365 switch (sel) {
3366 case 0:
3367 check_insn(env, ctx, ISA_MIPS32R2);
3368 gen_mfc0_load32(arg, offsetof(CPUState, CP0_HWREna));
3369 rn = "HWREna";
3370 break;
3371 default:
3372 goto die;
3374 break;
3375 case 8:
3376 switch (sel) {
3377 case 0:
3378 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_BadVAddr));
3379 tcg_gen_ext32s_tl(arg, arg);
3380 rn = "BadVAddr";
3381 break;
3382 default:
3383 goto die;
3385 break;
3386 case 9:
3387 switch (sel) {
3388 case 0:
3389 /* Mark as an IO operation because we read the time. */
3390 if (use_icount)
3391 gen_io_start();
3392 gen_helper_mfc0_count(arg);
3393 if (use_icount) {
3394 gen_io_end();
3395 ctx->bstate = BS_STOP;
3397 rn = "Count";
3398 break;
3399 /* 6,7 are implementation dependent */
3400 default:
3401 goto die;
3403 break;
3404 case 10:
3405 switch (sel) {
3406 case 0:
3407 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_EntryHi));
3408 tcg_gen_ext32s_tl(arg, arg);
3409 rn = "EntryHi";
3410 break;
3411 default:
3412 goto die;
3414 break;
3415 case 11:
3416 switch (sel) {
3417 case 0:
3418 gen_mfc0_load32(arg, offsetof(CPUState, CP0_Compare));
3419 rn = "Compare";
3420 break;
3421 /* 6,7 are implementation dependent */
3422 default:
3423 goto die;
3425 break;
3426 case 12:
3427 switch (sel) {
3428 case 0:
3429 gen_mfc0_load32(arg, offsetof(CPUState, CP0_Status));
3430 rn = "Status";
3431 break;
3432 case 1:
3433 check_insn(env, ctx, ISA_MIPS32R2);
3434 gen_mfc0_load32(arg, offsetof(CPUState, CP0_IntCtl));
3435 rn = "IntCtl";
3436 break;
3437 case 2:
3438 check_insn(env, ctx, ISA_MIPS32R2);
3439 gen_mfc0_load32(arg, offsetof(CPUState, CP0_SRSCtl));
3440 rn = "SRSCtl";
3441 break;
3442 case 3:
3443 check_insn(env, ctx, ISA_MIPS32R2);
3444 gen_mfc0_load32(arg, offsetof(CPUState, CP0_SRSMap));
3445 rn = "SRSMap";
3446 break;
3447 default:
3448 goto die;
3450 break;
3451 case 13:
3452 switch (sel) {
3453 case 0:
3454 gen_mfc0_load32(arg, offsetof(CPUState, CP0_Cause));
3455 rn = "Cause";
3456 break;
3457 default:
3458 goto die;
3460 break;
3461 case 14:
3462 switch (sel) {
3463 case 0:
3464 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_EPC));
3465 tcg_gen_ext32s_tl(arg, arg);
3466 rn = "EPC";
3467 break;
3468 default:
3469 goto die;
3471 break;
3472 case 15:
3473 switch (sel) {
3474 case 0:
3475 gen_mfc0_load32(arg, offsetof(CPUState, CP0_PRid));
3476 rn = "PRid";
3477 break;
3478 case 1:
3479 check_insn(env, ctx, ISA_MIPS32R2);
3480 gen_mfc0_load32(arg, offsetof(CPUState, CP0_EBase));
3481 rn = "EBase";
3482 break;
3483 default:
3484 goto die;
3486 break;
3487 case 16:
3488 switch (sel) {
3489 case 0:
3490 gen_mfc0_load32(arg, offsetof(CPUState, CP0_Config0));
3491 rn = "Config";
3492 break;
3493 case 1:
3494 gen_mfc0_load32(arg, offsetof(CPUState, CP0_Config1));
3495 rn = "Config1";
3496 break;
3497 case 2:
3498 gen_mfc0_load32(arg, offsetof(CPUState, CP0_Config2));
3499 rn = "Config2";
3500 break;
3501 case 3:
3502 gen_mfc0_load32(arg, offsetof(CPUState, CP0_Config3));
3503 rn = "Config3";
3504 break;
3505 /* 4,5 are reserved */
3506 /* 6,7 are implementation dependent */
3507 case 6:
3508 gen_mfc0_load32(arg, offsetof(CPUState, CP0_Config6));
3509 rn = "Config6";
3510 break;
3511 case 7:
3512 gen_mfc0_load32(arg, offsetof(CPUState, CP0_Config7));
3513 rn = "Config7";
3514 break;
3515 default:
3516 goto die;
3518 break;
3519 case 17:
3520 switch (sel) {
3521 case 0:
3522 gen_helper_mfc0_lladdr(arg);
3523 rn = "LLAddr";
3524 break;
3525 default:
3526 goto die;
3528 break;
3529 case 18:
3530 switch (sel) {
3531 case 0 ... 7:
3532 gen_helper_1i(mfc0_watchlo, arg, sel);
3533 rn = "WatchLo";
3534 break;
3535 default:
3536 goto die;
3538 break;
3539 case 19:
3540 switch (sel) {
3541 case 0 ...7:
3542 gen_helper_1i(mfc0_watchhi, arg, sel);
3543 rn = "WatchHi";
3544 break;
3545 default:
3546 goto die;
3548 break;
3549 case 20:
3550 switch (sel) {
3551 case 0:
3552 #if defined(TARGET_MIPS64)
3553 check_insn(env, ctx, ISA_MIPS3);
3554 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_XContext));
3555 tcg_gen_ext32s_tl(arg, arg);
3556 rn = "XContext";
3557 break;
3558 #endif
3559 default:
3560 goto die;
3562 break;
3563 case 21:
3564 /* Officially reserved, but sel 0 is used for R1x000 framemask */
3565 switch (sel) {
3566 case 0:
3567 gen_mfc0_load32(arg, offsetof(CPUState, CP0_Framemask));
3568 rn = "Framemask";
3569 break;
3570 default:
3571 goto die;
3573 break;
3574 case 22:
3575 tcg_gen_movi_tl(arg, 0); /* unimplemented */
3576 rn = "'Diagnostic"; /* implementation dependent */
3577 break;
3578 case 23:
3579 switch (sel) {
3580 case 0:
3581 gen_helper_mfc0_debug(arg); /* EJTAG support */
3582 rn = "Debug";
3583 break;
3584 case 1:
3585 // gen_helper_mfc0_tracecontrol(arg); /* PDtrace support */
3586 rn = "TraceControl";
3587 // break;
3588 case 2:
3589 // gen_helper_mfc0_tracecontrol2(arg); /* PDtrace support */
3590 rn = "TraceControl2";
3591 // break;
3592 case 3:
3593 // gen_helper_mfc0_usertracedata(arg); /* PDtrace support */
3594 rn = "UserTraceData";
3595 // break;
3596 case 4:
3597 // gen_helper_mfc0_tracebpc(arg); /* PDtrace support */
3598 rn = "TraceBPC";
3599 // break;
3600 default:
3601 goto die;
3603 break;
3604 case 24:
3605 switch (sel) {
3606 case 0:
3607 /* EJTAG support */
3608 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_DEPC));
3609 tcg_gen_ext32s_tl(arg, arg);
3610 rn = "DEPC";
3611 break;
3612 default:
3613 goto die;
3615 break;
3616 case 25:
3617 switch (sel) {
3618 case 0:
3619 gen_mfc0_load32(arg, offsetof(CPUState, CP0_Performance0));
3620 rn = "Performance0";
3621 break;
3622 case 1:
3623 // gen_helper_mfc0_performance1(arg);
3624 rn = "Performance1";
3625 // break;
3626 case 2:
3627 // gen_helper_mfc0_performance2(arg);
3628 rn = "Performance2";
3629 // break;
3630 case 3:
3631 // gen_helper_mfc0_performance3(arg);
3632 rn = "Performance3";
3633 // break;
3634 case 4:
3635 // gen_helper_mfc0_performance4(arg);
3636 rn = "Performance4";
3637 // break;
3638 case 5:
3639 // gen_helper_mfc0_performance5(arg);
3640 rn = "Performance5";
3641 // break;
3642 case 6:
3643 // gen_helper_mfc0_performance6(arg);
3644 rn = "Performance6";
3645 // break;
3646 case 7:
3647 // gen_helper_mfc0_performance7(arg);
3648 rn = "Performance7";
3649 // break;
3650 default:
3651 goto die;
3653 break;
3654 case 26:
3655 tcg_gen_movi_tl(arg, 0); /* unimplemented */
3656 rn = "ECC";
3657 break;
3658 case 27:
3659 switch (sel) {
3660 case 0 ... 3:
3661 tcg_gen_movi_tl(arg, 0); /* unimplemented */
3662 rn = "CacheErr";
3663 break;
3664 default:
3665 goto die;
3667 break;
3668 case 28:
3669 switch (sel) {
3670 case 0:
3671 case 2:
3672 case 4:
3673 case 6:
3674 gen_mfc0_load32(arg, offsetof(CPUState, CP0_TagLo));
3675 rn = "TagLo";
3676 break;
3677 case 1:
3678 case 3:
3679 case 5:
3680 case 7:
3681 gen_mfc0_load32(arg, offsetof(CPUState, CP0_DataLo));
3682 rn = "DataLo";
3683 break;
3684 default:
3685 goto die;
3687 break;
3688 case 29:
3689 switch (sel) {
3690 case 0:
3691 case 2:
3692 case 4:
3693 case 6:
3694 gen_mfc0_load32(arg, offsetof(CPUState, CP0_TagHi));
3695 rn = "TagHi";
3696 break;
3697 case 1:
3698 case 3:
3699 case 5:
3700 case 7:
3701 gen_mfc0_load32(arg, offsetof(CPUState, CP0_DataHi));
3702 rn = "DataHi";
3703 break;
3704 default:
3705 goto die;
3707 break;
3708 case 30:
3709 switch (sel) {
3710 case 0:
3711 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_ErrorEPC));
3712 tcg_gen_ext32s_tl(arg, arg);
3713 rn = "ErrorEPC";
3714 break;
3715 default:
3716 goto die;
3718 break;
3719 case 31:
3720 switch (sel) {
3721 case 0:
3722 /* EJTAG support */
3723 gen_mfc0_load32(arg, offsetof(CPUState, CP0_DESAVE));
3724 rn = "DESAVE";
3725 break;
3726 default:
3727 goto die;
3729 break;
3730 default:
3731 goto die;
3733 LOG_DISAS("mfc0 %s (reg %d sel %d)\n", rn, reg, sel);
3734 return;
3736 die:
3737 LOG_DISAS("mfc0 %s (reg %d sel %d)\n", rn, reg, sel);
3738 generate_exception(ctx, EXCP_RI);
3741 static void gen_mtc0 (CPUState *env, DisasContext *ctx, TCGv arg, int reg, int sel)
3743 const char *rn = "invalid";
3745 if (sel != 0)
3746 check_insn(env, ctx, ISA_MIPS32);
3748 if (use_icount)
3749 gen_io_start();
3751 switch (reg) {
3752 case 0:
3753 switch (sel) {
3754 case 0:
3755 gen_helper_mtc0_index(arg);
3756 rn = "Index";
3757 break;
3758 case 1:
3759 check_insn(env, ctx, ASE_MT);
3760 gen_helper_mtc0_mvpcontrol(arg);
3761 rn = "MVPControl";
3762 break;
3763 case 2:
3764 check_insn(env, ctx, ASE_MT);
3765 /* ignored */
3766 rn = "MVPConf0";
3767 break;
3768 case 3:
3769 check_insn(env, ctx, ASE_MT);
3770 /* ignored */
3771 rn = "MVPConf1";
3772 break;
3773 default:
3774 goto die;
3776 break;
3777 case 1:
3778 switch (sel) {
3779 case 0:
3780 /* ignored */
3781 rn = "Random";
3782 break;
3783 case 1:
3784 check_insn(env, ctx, ASE_MT);
3785 gen_helper_mtc0_vpecontrol(arg);
3786 rn = "VPEControl";
3787 break;
3788 case 2:
3789 check_insn(env, ctx, ASE_MT);
3790 gen_helper_mtc0_vpeconf0(arg);
3791 rn = "VPEConf0";
3792 break;
3793 case 3:
3794 check_insn(env, ctx, ASE_MT);
3795 gen_helper_mtc0_vpeconf1(arg);
3796 rn = "VPEConf1";
3797 break;
3798 case 4:
3799 check_insn(env, ctx, ASE_MT);
3800 gen_helper_mtc0_yqmask(arg);
3801 rn = "YQMask";
3802 break;
3803 case 5:
3804 check_insn(env, ctx, ASE_MT);
3805 gen_mtc0_store64(arg, offsetof(CPUState, CP0_VPESchedule));
3806 rn = "VPESchedule";
3807 break;
3808 case 6:
3809 check_insn(env, ctx, ASE_MT);
3810 gen_mtc0_store64(arg, offsetof(CPUState, CP0_VPEScheFBack));
3811 rn = "VPEScheFBack";
3812 break;
3813 case 7:
3814 check_insn(env, ctx, ASE_MT);
3815 gen_helper_mtc0_vpeopt(arg);
3816 rn = "VPEOpt";
3817 break;
3818 default:
3819 goto die;
3821 break;
3822 case 2:
3823 switch (sel) {
3824 case 0:
3825 gen_helper_mtc0_entrylo0(arg);
3826 rn = "EntryLo0";
3827 break;
3828 case 1:
3829 check_insn(env, ctx, ASE_MT);
3830 gen_helper_mtc0_tcstatus(arg);
3831 rn = "TCStatus";
3832 break;
3833 case 2:
3834 check_insn(env, ctx, ASE_MT);
3835 gen_helper_mtc0_tcbind(arg);
3836 rn = "TCBind";
3837 break;
3838 case 3:
3839 check_insn(env, ctx, ASE_MT);
3840 gen_helper_mtc0_tcrestart(arg);
3841 rn = "TCRestart";
3842 break;
3843 case 4:
3844 check_insn(env, ctx, ASE_MT);
3845 gen_helper_mtc0_tchalt(arg);
3846 rn = "TCHalt";
3847 break;
3848 case 5:
3849 check_insn(env, ctx, ASE_MT);
3850 gen_helper_mtc0_tccontext(arg);
3851 rn = "TCContext";
3852 break;
3853 case 6:
3854 check_insn(env, ctx, ASE_MT);
3855 gen_helper_mtc0_tcschedule(arg);
3856 rn = "TCSchedule";
3857 break;
3858 case 7:
3859 check_insn(env, ctx, ASE_MT);
3860 gen_helper_mtc0_tcschefback(arg);
3861 rn = "TCScheFBack";
3862 break;
3863 default:
3864 goto die;
3866 break;
3867 case 3:
3868 switch (sel) {
3869 case 0:
3870 gen_helper_mtc0_entrylo1(arg);
3871 rn = "EntryLo1";
3872 break;
3873 default:
3874 goto die;
3876 break;
3877 case 4:
3878 switch (sel) {
3879 case 0:
3880 gen_helper_mtc0_context(arg);
3881 rn = "Context";
3882 break;
3883 case 1:
3884 // gen_helper_mtc0_contextconfig(arg); /* SmartMIPS ASE */
3885 rn = "ContextConfig";
3886 // break;
3887 default:
3888 goto die;
3890 break;
3891 case 5:
3892 switch (sel) {
3893 case 0:
3894 gen_helper_mtc0_pagemask(arg);
3895 rn = "PageMask";
3896 break;
3897 case 1:
3898 check_insn(env, ctx, ISA_MIPS32R2);
3899 gen_helper_mtc0_pagegrain(arg);
3900 rn = "PageGrain";
3901 break;
3902 default:
3903 goto die;
3905 break;
3906 case 6:
3907 switch (sel) {
3908 case 0:
3909 gen_helper_mtc0_wired(arg);
3910 rn = "Wired";
3911 break;
3912 case 1:
3913 check_insn(env, ctx, ISA_MIPS32R2);
3914 gen_helper_mtc0_srsconf0(arg);
3915 rn = "SRSConf0";
3916 break;
3917 case 2:
3918 check_insn(env, ctx, ISA_MIPS32R2);
3919 gen_helper_mtc0_srsconf1(arg);
3920 rn = "SRSConf1";
3921 break;
3922 case 3:
3923 check_insn(env, ctx, ISA_MIPS32R2);
3924 gen_helper_mtc0_srsconf2(arg);
3925 rn = "SRSConf2";
3926 break;
3927 case 4:
3928 check_insn(env, ctx, ISA_MIPS32R2);
3929 gen_helper_mtc0_srsconf3(arg);
3930 rn = "SRSConf3";
3931 break;
3932 case 5:
3933 check_insn(env, ctx, ISA_MIPS32R2);
3934 gen_helper_mtc0_srsconf4(arg);
3935 rn = "SRSConf4";
3936 break;
3937 default:
3938 goto die;
3940 break;
3941 case 7:
3942 switch (sel) {
3943 case 0:
3944 check_insn(env, ctx, ISA_MIPS32R2);
3945 gen_helper_mtc0_hwrena(arg);
3946 rn = "HWREna";
3947 break;
3948 default:
3949 goto die;
3951 break;
3952 case 8:
3953 /* ignored */
3954 rn = "BadVAddr";
3955 break;
3956 case 9:
3957 switch (sel) {
3958 case 0:
3959 gen_helper_mtc0_count(arg);
3960 rn = "Count";
3961 break;
3962 /* 6,7 are implementation dependent */
3963 default:
3964 goto die;
3966 break;
3967 case 10:
3968 switch (sel) {
3969 case 0:
3970 gen_helper_mtc0_entryhi(arg);
3971 rn = "EntryHi";
3972 break;
3973 default:
3974 goto die;
3976 break;
3977 case 11:
3978 switch (sel) {
3979 case 0:
3980 gen_helper_mtc0_compare(arg);
3981 rn = "Compare";
3982 break;
3983 /* 6,7 are implementation dependent */
3984 default:
3985 goto die;
3987 break;
3988 case 12:
3989 switch (sel) {
3990 case 0:
3991 save_cpu_state(ctx, 1);
3992 gen_helper_mtc0_status(arg);
3993 /* BS_STOP isn't good enough here, hflags may have changed. */
3994 gen_save_pc(ctx->pc + 4);
3995 ctx->bstate = BS_EXCP;
3996 rn = "Status";
3997 break;
3998 case 1:
3999 check_insn(env, ctx, ISA_MIPS32R2);
4000 gen_helper_mtc0_intctl(arg);
4001 /* Stop translation as we may have switched the execution mode */
4002 ctx->bstate = BS_STOP;
4003 rn = "IntCtl";
4004 break;
4005 case 2:
4006 check_insn(env, ctx, ISA_MIPS32R2);
4007 gen_helper_mtc0_srsctl(arg);
4008 /* Stop translation as we may have switched the execution mode */
4009 ctx->bstate = BS_STOP;
4010 rn = "SRSCtl";
4011 break;
4012 case 3:
4013 check_insn(env, ctx, ISA_MIPS32R2);
4014 gen_mtc0_store32(arg, offsetof(CPUState, CP0_SRSMap));
4015 /* Stop translation as we may have switched the execution mode */
4016 ctx->bstate = BS_STOP;
4017 rn = "SRSMap";
4018 break;
4019 default:
4020 goto die;
4022 break;
4023 case 13:
4024 switch (sel) {
4025 case 0:
4026 save_cpu_state(ctx, 1);
4027 gen_helper_mtc0_cause(arg);
4028 rn = "Cause";
4029 break;
4030 default:
4031 goto die;
4033 break;
4034 case 14:
4035 switch (sel) {
4036 case 0:
4037 gen_mtc0_store64(arg, offsetof(CPUState, CP0_EPC));
4038 rn = "EPC";
4039 break;
4040 default:
4041 goto die;
4043 break;
4044 case 15:
4045 switch (sel) {
4046 case 0:
4047 /* ignored */
4048 rn = "PRid";
4049 break;
4050 case 1:
4051 check_insn(env, ctx, ISA_MIPS32R2);
4052 gen_helper_mtc0_ebase(arg);
4053 rn = "EBase";
4054 break;
4055 default:
4056 goto die;
4058 break;
4059 case 16:
4060 switch (sel) {
4061 case 0:
4062 gen_helper_mtc0_config0(arg);
4063 rn = "Config";
4064 /* Stop translation as we may have switched the execution mode */
4065 ctx->bstate = BS_STOP;
4066 break;
4067 case 1:
4068 /* ignored, read only */
4069 rn = "Config1";
4070 break;
4071 case 2:
4072 gen_helper_mtc0_config2(arg);
4073 rn = "Config2";
4074 /* Stop translation as we may have switched the execution mode */
4075 ctx->bstate = BS_STOP;
4076 break;
4077 case 3:
4078 /* ignored, read only */
4079 rn = "Config3";
4080 break;
4081 /* 4,5 are reserved */
4082 /* 6,7 are implementation dependent */
4083 case 6:
4084 /* ignored */
4085 rn = "Config6";
4086 break;
4087 case 7:
4088 /* ignored */
4089 rn = "Config7";
4090 break;
4091 default:
4092 rn = "Invalid config selector";
4093 goto die;
4095 break;
4096 case 17:
4097 switch (sel) {
4098 case 0:
4099 gen_helper_mtc0_lladdr(arg);
4100 rn = "LLAddr";
4101 break;
4102 default:
4103 goto die;
4105 break;
4106 case 18:
4107 switch (sel) {
4108 case 0 ... 7:
4109 gen_helper_1i(mtc0_watchlo, arg, sel);
4110 rn = "WatchLo";
4111 break;
4112 default:
4113 goto die;
4115 break;
4116 case 19:
4117 switch (sel) {
4118 case 0 ... 7:
4119 gen_helper_1i(mtc0_watchhi, arg, sel);
4120 rn = "WatchHi";
4121 break;
4122 default:
4123 goto die;
4125 break;
4126 case 20:
4127 switch (sel) {
4128 case 0:
4129 #if defined(TARGET_MIPS64)
4130 check_insn(env, ctx, ISA_MIPS3);
4131 gen_helper_mtc0_xcontext(arg);
4132 rn = "XContext";
4133 break;
4134 #endif
4135 default:
4136 goto die;
4138 break;
4139 case 21:
4140 /* Officially reserved, but sel 0 is used for R1x000 framemask */
4141 switch (sel) {
4142 case 0:
4143 gen_helper_mtc0_framemask(arg);
4144 rn = "Framemask";
4145 break;
4146 default:
4147 goto die;
4149 break;
4150 case 22:
4151 /* ignored */
4152 rn = "Diagnostic"; /* implementation dependent */
4153 break;
4154 case 23:
4155 switch (sel) {
4156 case 0:
4157 gen_helper_mtc0_debug(arg); /* EJTAG support */
4158 /* BS_STOP isn't good enough here, hflags may have changed. */
4159 gen_save_pc(ctx->pc + 4);
4160 ctx->bstate = BS_EXCP;
4161 rn = "Debug";
4162 break;
4163 case 1:
4164 // gen_helper_mtc0_tracecontrol(arg); /* PDtrace support */
4165 rn = "TraceControl";
4166 /* Stop translation as we may have switched the execution mode */
4167 ctx->bstate = BS_STOP;
4168 // break;
4169 case 2:
4170 // gen_helper_mtc0_tracecontrol2(arg); /* PDtrace support */
4171 rn = "TraceControl2";
4172 /* Stop translation as we may have switched the execution mode */
4173 ctx->bstate = BS_STOP;
4174 // break;
4175 case 3:
4176 /* Stop translation as we may have switched the execution mode */
4177 ctx->bstate = BS_STOP;
4178 // gen_helper_mtc0_usertracedata(arg); /* PDtrace support */
4179 rn = "UserTraceData";
4180 /* Stop translation as we may have switched the execution mode */
4181 ctx->bstate = BS_STOP;
4182 // break;
4183 case 4:
4184 // gen_helper_mtc0_tracebpc(arg); /* PDtrace support */
4185 /* Stop translation as we may have switched the execution mode */
4186 ctx->bstate = BS_STOP;
4187 rn = "TraceBPC";
4188 // break;
4189 default:
4190 goto die;
4192 break;
4193 case 24:
4194 switch (sel) {
4195 case 0:
4196 /* EJTAG support */
4197 gen_mtc0_store64(arg, offsetof(CPUState, CP0_DEPC));
4198 rn = "DEPC";
4199 break;
4200 default:
4201 goto die;
4203 break;
4204 case 25:
4205 switch (sel) {
4206 case 0:
4207 gen_helper_mtc0_performance0(arg);
4208 rn = "Performance0";
4209 break;
4210 case 1:
4211 // gen_helper_mtc0_performance1(arg);
4212 rn = "Performance1";
4213 // break;
4214 case 2:
4215 // gen_helper_mtc0_performance2(arg);
4216 rn = "Performance2";
4217 // break;
4218 case 3:
4219 // gen_helper_mtc0_performance3(arg);
4220 rn = "Performance3";
4221 // break;
4222 case 4:
4223 // gen_helper_mtc0_performance4(arg);
4224 rn = "Performance4";
4225 // break;
4226 case 5:
4227 // gen_helper_mtc0_performance5(arg);
4228 rn = "Performance5";
4229 // break;
4230 case 6:
4231 // gen_helper_mtc0_performance6(arg);
4232 rn = "Performance6";
4233 // break;
4234 case 7:
4235 // gen_helper_mtc0_performance7(arg);
4236 rn = "Performance7";
4237 // break;
4238 default:
4239 goto die;
4241 break;
4242 case 26:
4243 /* ignored */
4244 rn = "ECC";
4245 break;
4246 case 27:
4247 switch (sel) {
4248 case 0 ... 3:
4249 /* ignored */
4250 rn = "CacheErr";
4251 break;
4252 default:
4253 goto die;
4255 break;
4256 case 28:
4257 switch (sel) {
4258 case 0:
4259 case 2:
4260 case 4:
4261 case 6:
4262 gen_helper_mtc0_taglo(arg);
4263 rn = "TagLo";
4264 break;
4265 case 1:
4266 case 3:
4267 case 5:
4268 case 7:
4269 gen_helper_mtc0_datalo(arg);
4270 rn = "DataLo";
4271 break;
4272 default:
4273 goto die;
4275 break;
4276 case 29:
4277 switch (sel) {
4278 case 0:
4279 case 2:
4280 case 4:
4281 case 6:
4282 gen_helper_mtc0_taghi(arg);
4283 rn = "TagHi";
4284 break;
4285 case 1:
4286 case 3:
4287 case 5:
4288 case 7:
4289 gen_helper_mtc0_datahi(arg);
4290 rn = "DataHi";
4291 break;
4292 default:
4293 rn = "invalid sel";
4294 goto die;
4296 break;
4297 case 30:
4298 switch (sel) {
4299 case 0:
4300 gen_mtc0_store64(arg, offsetof(CPUState, CP0_ErrorEPC));
4301 rn = "ErrorEPC";
4302 break;
4303 default:
4304 goto die;
4306 break;
4307 case 31:
4308 switch (sel) {
4309 case 0:
4310 /* EJTAG support */
4311 gen_mtc0_store32(arg, offsetof(CPUState, CP0_DESAVE));
4312 rn = "DESAVE";
4313 break;
4314 default:
4315 goto die;
4317 /* Stop translation as we may have switched the execution mode */
4318 ctx->bstate = BS_STOP;
4319 break;
4320 default:
4321 goto die;
4323 LOG_DISAS("mtc0 %s (reg %d sel %d)\n", rn, reg, sel);
4324 /* For simplicity assume that all writes can cause interrupts. */
4325 if (use_icount) {
4326 gen_io_end();
4327 ctx->bstate = BS_STOP;
4329 return;
4331 die:
4332 LOG_DISAS("mtc0 %s (reg %d sel %d)\n", rn, reg, sel);
4333 generate_exception(ctx, EXCP_RI);
4336 #if defined(TARGET_MIPS64)
4337 static void gen_dmfc0 (CPUState *env, DisasContext *ctx, TCGv arg, int reg, int sel)
4339 const char *rn = "invalid";
4341 if (sel != 0)
4342 check_insn(env, ctx, ISA_MIPS64);
4344 switch (reg) {
4345 case 0:
4346 switch (sel) {
4347 case 0:
4348 gen_mfc0_load32(arg, offsetof(CPUState, CP0_Index));
4349 rn = "Index";
4350 break;
4351 case 1:
4352 check_insn(env, ctx, ASE_MT);
4353 gen_helper_mfc0_mvpcontrol(arg);
4354 rn = "MVPControl";
4355 break;
4356 case 2:
4357 check_insn(env, ctx, ASE_MT);
4358 gen_helper_mfc0_mvpconf0(arg);
4359 rn = "MVPConf0";
4360 break;
4361 case 3:
4362 check_insn(env, ctx, ASE_MT);
4363 gen_helper_mfc0_mvpconf1(arg);
4364 rn = "MVPConf1";
4365 break;
4366 default:
4367 goto die;
4369 break;
4370 case 1:
4371 switch (sel) {
4372 case 0:
4373 gen_helper_mfc0_random(arg);
4374 rn = "Random";
4375 break;
4376 case 1:
4377 check_insn(env, ctx, ASE_MT);
4378 gen_mfc0_load32(arg, offsetof(CPUState, CP0_VPEControl));
4379 rn = "VPEControl";
4380 break;
4381 case 2:
4382 check_insn(env, ctx, ASE_MT);
4383 gen_mfc0_load32(arg, offsetof(CPUState, CP0_VPEConf0));
4384 rn = "VPEConf0";
4385 break;
4386 case 3:
4387 check_insn(env, ctx, ASE_MT);
4388 gen_mfc0_load32(arg, offsetof(CPUState, CP0_VPEConf1));
4389 rn = "VPEConf1";
4390 break;
4391 case 4:
4392 check_insn(env, ctx, ASE_MT);
4393 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_YQMask));
4394 rn = "YQMask";
4395 break;
4396 case 5:
4397 check_insn(env, ctx, ASE_MT);
4398 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_VPESchedule));
4399 rn = "VPESchedule";
4400 break;
4401 case 6:
4402 check_insn(env, ctx, ASE_MT);
4403 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_VPEScheFBack));
4404 rn = "VPEScheFBack";
4405 break;
4406 case 7:
4407 check_insn(env, ctx, ASE_MT);
4408 gen_mfc0_load32(arg, offsetof(CPUState, CP0_VPEOpt));
4409 rn = "VPEOpt";
4410 break;
4411 default:
4412 goto die;
4414 break;
4415 case 2:
4416 switch (sel) {
4417 case 0:
4418 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_EntryLo0));
4419 rn = "EntryLo0";
4420 break;
4421 case 1:
4422 check_insn(env, ctx, ASE_MT);
4423 gen_helper_mfc0_tcstatus(arg);
4424 rn = "TCStatus";
4425 break;
4426 case 2:
4427 check_insn(env, ctx, ASE_MT);
4428 gen_helper_mfc0_tcbind(arg);
4429 rn = "TCBind";
4430 break;
4431 case 3:
4432 check_insn(env, ctx, ASE_MT);
4433 gen_helper_dmfc0_tcrestart(arg);
4434 rn = "TCRestart";
4435 break;
4436 case 4:
4437 check_insn(env, ctx, ASE_MT);
4438 gen_helper_dmfc0_tchalt(arg);
4439 rn = "TCHalt";
4440 break;
4441 case 5:
4442 check_insn(env, ctx, ASE_MT);
4443 gen_helper_dmfc0_tccontext(arg);
4444 rn = "TCContext";
4445 break;
4446 case 6:
4447 check_insn(env, ctx, ASE_MT);
4448 gen_helper_dmfc0_tcschedule(arg);
4449 rn = "TCSchedule";
4450 break;
4451 case 7:
4452 check_insn(env, ctx, ASE_MT);
4453 gen_helper_dmfc0_tcschefback(arg);
4454 rn = "TCScheFBack";
4455 break;
4456 default:
4457 goto die;
4459 break;
4460 case 3:
4461 switch (sel) {
4462 case 0:
4463 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_EntryLo1));
4464 rn = "EntryLo1";
4465 break;
4466 default:
4467 goto die;
4469 break;
4470 case 4:
4471 switch (sel) {
4472 case 0:
4473 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_Context));
4474 rn = "Context";
4475 break;
4476 case 1:
4477 // gen_helper_dmfc0_contextconfig(arg); /* SmartMIPS ASE */
4478 rn = "ContextConfig";
4479 // break;
4480 default:
4481 goto die;
4483 break;
4484 case 5:
4485 switch (sel) {
4486 case 0:
4487 gen_mfc0_load32(arg, offsetof(CPUState, CP0_PageMask));
4488 rn = "PageMask";
4489 break;
4490 case 1:
4491 check_insn(env, ctx, ISA_MIPS32R2);
4492 gen_mfc0_load32(arg, offsetof(CPUState, CP0_PageGrain));
4493 rn = "PageGrain";
4494 break;
4495 default:
4496 goto die;
4498 break;
4499 case 6:
4500 switch (sel) {
4501 case 0:
4502 gen_mfc0_load32(arg, offsetof(CPUState, CP0_Wired));
4503 rn = "Wired";
4504 break;
4505 case 1:
4506 check_insn(env, ctx, ISA_MIPS32R2);
4507 gen_mfc0_load32(arg, offsetof(CPUState, CP0_SRSConf0));
4508 rn = "SRSConf0";
4509 break;
4510 case 2:
4511 check_insn(env, ctx, ISA_MIPS32R2);
4512 gen_mfc0_load32(arg, offsetof(CPUState, CP0_SRSConf1));
4513 rn = "SRSConf1";
4514 break;
4515 case 3:
4516 check_insn(env, ctx, ISA_MIPS32R2);
4517 gen_mfc0_load32(arg, offsetof(CPUState, CP0_SRSConf2));
4518 rn = "SRSConf2";
4519 break;
4520 case 4:
4521 check_insn(env, ctx, ISA_MIPS32R2);
4522 gen_mfc0_load32(arg, offsetof(CPUState, CP0_SRSConf3));
4523 rn = "SRSConf3";
4524 break;
4525 case 5:
4526 check_insn(env, ctx, ISA_MIPS32R2);
4527 gen_mfc0_load32(arg, offsetof(CPUState, CP0_SRSConf4));
4528 rn = "SRSConf4";
4529 break;
4530 default:
4531 goto die;
4533 break;
4534 case 7:
4535 switch (sel) {
4536 case 0:
4537 check_insn(env, ctx, ISA_MIPS32R2);
4538 gen_mfc0_load32(arg, offsetof(CPUState, CP0_HWREna));
4539 rn = "HWREna";
4540 break;
4541 default:
4542 goto die;
4544 break;
4545 case 8:
4546 switch (sel) {
4547 case 0:
4548 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_BadVAddr));
4549 rn = "BadVAddr";
4550 break;
4551 default:
4552 goto die;
4554 break;
4555 case 9:
4556 switch (sel) {
4557 case 0:
4558 /* Mark as an IO operation because we read the time. */
4559 if (use_icount)
4560 gen_io_start();
4561 gen_helper_mfc0_count(arg);
4562 if (use_icount) {
4563 gen_io_end();
4564 ctx->bstate = BS_STOP;
4566 rn = "Count";
4567 break;
4568 /* 6,7 are implementation dependent */
4569 default:
4570 goto die;
4572 break;
4573 case 10:
4574 switch (sel) {
4575 case 0:
4576 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_EntryHi));
4577 rn = "EntryHi";
4578 break;
4579 default:
4580 goto die;
4582 break;
4583 case 11:
4584 switch (sel) {
4585 case 0:
4586 gen_mfc0_load32(arg, offsetof(CPUState, CP0_Compare));
4587 rn = "Compare";
4588 break;
4589 /* 6,7 are implementation dependent */
4590 default:
4591 goto die;
4593 break;
4594 case 12:
4595 switch (sel) {
4596 case 0:
4597 gen_mfc0_load32(arg, offsetof(CPUState, CP0_Status));
4598 rn = "Status";
4599 break;
4600 case 1:
4601 check_insn(env, ctx, ISA_MIPS32R2);
4602 gen_mfc0_load32(arg, offsetof(CPUState, CP0_IntCtl));
4603 rn = "IntCtl";
4604 break;
4605 case 2:
4606 check_insn(env, ctx, ISA_MIPS32R2);
4607 gen_mfc0_load32(arg, offsetof(CPUState, CP0_SRSCtl));
4608 rn = "SRSCtl";
4609 break;
4610 case 3:
4611 check_insn(env, ctx, ISA_MIPS32R2);
4612 gen_mfc0_load32(arg, offsetof(CPUState, CP0_SRSMap));
4613 rn = "SRSMap";
4614 break;
4615 default:
4616 goto die;
4618 break;
4619 case 13:
4620 switch (sel) {
4621 case 0:
4622 gen_mfc0_load32(arg, offsetof(CPUState, CP0_Cause));
4623 rn = "Cause";
4624 break;
4625 default:
4626 goto die;
4628 break;
4629 case 14:
4630 switch (sel) {
4631 case 0:
4632 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_EPC));
4633 rn = "EPC";
4634 break;
4635 default:
4636 goto die;
4638 break;
4639 case 15:
4640 switch (sel) {
4641 case 0:
4642 gen_mfc0_load32(arg, offsetof(CPUState, CP0_PRid));
4643 rn = "PRid";
4644 break;
4645 case 1:
4646 check_insn(env, ctx, ISA_MIPS32R2);
4647 gen_mfc0_load32(arg, offsetof(CPUState, CP0_EBase));
4648 rn = "EBase";
4649 break;
4650 default:
4651 goto die;
4653 break;
4654 case 16:
4655 switch (sel) {
4656 case 0:
4657 gen_mfc0_load32(arg, offsetof(CPUState, CP0_Config0));
4658 rn = "Config";
4659 break;
4660 case 1:
4661 gen_mfc0_load32(arg, offsetof(CPUState, CP0_Config1));
4662 rn = "Config1";
4663 break;
4664 case 2:
4665 gen_mfc0_load32(arg, offsetof(CPUState, CP0_Config2));
4666 rn = "Config2";
4667 break;
4668 case 3:
4669 gen_mfc0_load32(arg, offsetof(CPUState, CP0_Config3));
4670 rn = "Config3";
4671 break;
4672 /* 6,7 are implementation dependent */
4673 case 6:
4674 gen_mfc0_load32(arg, offsetof(CPUState, CP0_Config6));
4675 rn = "Config6";
4676 break;
4677 case 7:
4678 gen_mfc0_load32(arg, offsetof(CPUState, CP0_Config7));
4679 rn = "Config7";
4680 break;
4681 default:
4682 goto die;
4684 break;
4685 case 17:
4686 switch (sel) {
4687 case 0:
4688 gen_helper_dmfc0_lladdr(arg);
4689 rn = "LLAddr";
4690 break;
4691 default:
4692 goto die;
4694 break;
4695 case 18:
4696 switch (sel) {
4697 case 0 ... 7:
4698 gen_helper_1i(dmfc0_watchlo, arg, sel);
4699 rn = "WatchLo";
4700 break;
4701 default:
4702 goto die;
4704 break;
4705 case 19:
4706 switch (sel) {
4707 case 0 ... 7:
4708 gen_helper_1i(mfc0_watchhi, arg, sel);
4709 rn = "WatchHi";
4710 break;
4711 default:
4712 goto die;
4714 break;
4715 case 20:
4716 switch (sel) {
4717 case 0:
4718 check_insn(env, ctx, ISA_MIPS3);
4719 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_XContext));
4720 rn = "XContext";
4721 break;
4722 default:
4723 goto die;
4725 break;
4726 case 21:
4727 /* Officially reserved, but sel 0 is used for R1x000 framemask */
4728 switch (sel) {
4729 case 0:
4730 gen_mfc0_load32(arg, offsetof(CPUState, CP0_Framemask));
4731 rn = "Framemask";
4732 break;
4733 default:
4734 goto die;
4736 break;
4737 case 22:
4738 tcg_gen_movi_tl(arg, 0); /* unimplemented */
4739 rn = "'Diagnostic"; /* implementation dependent */
4740 break;
4741 case 23:
4742 switch (sel) {
4743 case 0:
4744 gen_helper_mfc0_debug(arg); /* EJTAG support */
4745 rn = "Debug";
4746 break;
4747 case 1:
4748 // gen_helper_dmfc0_tracecontrol(arg); /* PDtrace support */
4749 rn = "TraceControl";
4750 // break;
4751 case 2:
4752 // gen_helper_dmfc0_tracecontrol2(arg); /* PDtrace support */
4753 rn = "TraceControl2";
4754 // break;
4755 case 3:
4756 // gen_helper_dmfc0_usertracedata(arg); /* PDtrace support */
4757 rn = "UserTraceData";
4758 // break;
4759 case 4:
4760 // gen_helper_dmfc0_tracebpc(arg); /* PDtrace support */
4761 rn = "TraceBPC";
4762 // break;
4763 default:
4764 goto die;
4766 break;
4767 case 24:
4768 switch (sel) {
4769 case 0:
4770 /* EJTAG support */
4771 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_DEPC));
4772 rn = "DEPC";
4773 break;
4774 default:
4775 goto die;
4777 break;
4778 case 25:
4779 switch (sel) {
4780 case 0:
4781 gen_mfc0_load32(arg, offsetof(CPUState, CP0_Performance0));
4782 rn = "Performance0";
4783 break;
4784 case 1:
4785 // gen_helper_dmfc0_performance1(arg);
4786 rn = "Performance1";
4787 // break;
4788 case 2:
4789 // gen_helper_dmfc0_performance2(arg);
4790 rn = "Performance2";
4791 // break;
4792 case 3:
4793 // gen_helper_dmfc0_performance3(arg);
4794 rn = "Performance3";
4795 // break;
4796 case 4:
4797 // gen_helper_dmfc0_performance4(arg);
4798 rn = "Performance4";
4799 // break;
4800 case 5:
4801 // gen_helper_dmfc0_performance5(arg);
4802 rn = "Performance5";
4803 // break;
4804 case 6:
4805 // gen_helper_dmfc0_performance6(arg);
4806 rn = "Performance6";
4807 // break;
4808 case 7:
4809 // gen_helper_dmfc0_performance7(arg);
4810 rn = "Performance7";
4811 // break;
4812 default:
4813 goto die;
4815 break;
4816 case 26:
4817 tcg_gen_movi_tl(arg, 0); /* unimplemented */
4818 rn = "ECC";
4819 break;
4820 case 27:
4821 switch (sel) {
4822 /* ignored */
4823 case 0 ... 3:
4824 tcg_gen_movi_tl(arg, 0); /* unimplemented */
4825 rn = "CacheErr";
4826 break;
4827 default:
4828 goto die;
4830 break;
4831 case 28:
4832 switch (sel) {
4833 case 0:
4834 case 2:
4835 case 4:
4836 case 6:
4837 gen_mfc0_load32(arg, offsetof(CPUState, CP0_TagLo));
4838 rn = "TagLo";
4839 break;
4840 case 1:
4841 case 3:
4842 case 5:
4843 case 7:
4844 gen_mfc0_load32(arg, offsetof(CPUState, CP0_DataLo));
4845 rn = "DataLo";
4846 break;
4847 default:
4848 goto die;
4850 break;
4851 case 29:
4852 switch (sel) {
4853 case 0:
4854 case 2:
4855 case 4:
4856 case 6:
4857 gen_mfc0_load32(arg, offsetof(CPUState, CP0_TagHi));
4858 rn = "TagHi";
4859 break;
4860 case 1:
4861 case 3:
4862 case 5:
4863 case 7:
4864 gen_mfc0_load32(arg, offsetof(CPUState, CP0_DataHi));
4865 rn = "DataHi";
4866 break;
4867 default:
4868 goto die;
4870 break;
4871 case 30:
4872 switch (sel) {
4873 case 0:
4874 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_ErrorEPC));
4875 rn = "ErrorEPC";
4876 break;
4877 default:
4878 goto die;
4880 break;
4881 case 31:
4882 switch (sel) {
4883 case 0:
4884 /* EJTAG support */
4885 gen_mfc0_load32(arg, offsetof(CPUState, CP0_DESAVE));
4886 rn = "DESAVE";
4887 break;
4888 default:
4889 goto die;
4891 break;
4892 default:
4893 goto die;
4895 LOG_DISAS("dmfc0 %s (reg %d sel %d)\n", rn, reg, sel);
4896 return;
4898 die:
4899 LOG_DISAS("dmfc0 %s (reg %d sel %d)\n", rn, reg, sel);
4900 generate_exception(ctx, EXCP_RI);
4903 static void gen_dmtc0 (CPUState *env, DisasContext *ctx, TCGv arg, int reg, int sel)
4905 const char *rn = "invalid";
4907 if (sel != 0)
4908 check_insn(env, ctx, ISA_MIPS64);
4910 if (use_icount)
4911 gen_io_start();
4913 switch (reg) {
4914 case 0:
4915 switch (sel) {
4916 case 0:
4917 gen_helper_mtc0_index(arg);
4918 rn = "Index";
4919 break;
4920 case 1:
4921 check_insn(env, ctx, ASE_MT);
4922 gen_helper_mtc0_mvpcontrol(arg);
4923 rn = "MVPControl";
4924 break;
4925 case 2:
4926 check_insn(env, ctx, ASE_MT);
4927 /* ignored */
4928 rn = "MVPConf0";
4929 break;
4930 case 3:
4931 check_insn(env, ctx, ASE_MT);
4932 /* ignored */
4933 rn = "MVPConf1";
4934 break;
4935 default:
4936 goto die;
4938 break;
4939 case 1:
4940 switch (sel) {
4941 case 0:
4942 /* ignored */
4943 rn = "Random";
4944 break;
4945 case 1:
4946 check_insn(env, ctx, ASE_MT);
4947 gen_helper_mtc0_vpecontrol(arg);
4948 rn = "VPEControl";
4949 break;
4950 case 2:
4951 check_insn(env, ctx, ASE_MT);
4952 gen_helper_mtc0_vpeconf0(arg);
4953 rn = "VPEConf0";
4954 break;
4955 case 3:
4956 check_insn(env, ctx, ASE_MT);
4957 gen_helper_mtc0_vpeconf1(arg);
4958 rn = "VPEConf1";
4959 break;
4960 case 4:
4961 check_insn(env, ctx, ASE_MT);
4962 gen_helper_mtc0_yqmask(arg);
4963 rn = "YQMask";
4964 break;
4965 case 5:
4966 check_insn(env, ctx, ASE_MT);
4967 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUState, CP0_VPESchedule));
4968 rn = "VPESchedule";
4969 break;
4970 case 6:
4971 check_insn(env, ctx, ASE_MT);
4972 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUState, CP0_VPEScheFBack));
4973 rn = "VPEScheFBack";
4974 break;
4975 case 7:
4976 check_insn(env, ctx, ASE_MT);
4977 gen_helper_mtc0_vpeopt(arg);
4978 rn = "VPEOpt";
4979 break;
4980 default:
4981 goto die;
4983 break;
4984 case 2:
4985 switch (sel) {
4986 case 0:
4987 gen_helper_mtc0_entrylo0(arg);
4988 rn = "EntryLo0";
4989 break;
4990 case 1:
4991 check_insn(env, ctx, ASE_MT);
4992 gen_helper_mtc0_tcstatus(arg);
4993 rn = "TCStatus";
4994 break;
4995 case 2:
4996 check_insn(env, ctx, ASE_MT);
4997 gen_helper_mtc0_tcbind(arg);
4998 rn = "TCBind";
4999 break;
5000 case 3:
5001 check_insn(env, ctx, ASE_MT);
5002 gen_helper_mtc0_tcrestart(arg);
5003 rn = "TCRestart";
5004 break;
5005 case 4:
5006 check_insn(env, ctx, ASE_MT);
5007 gen_helper_mtc0_tchalt(arg);
5008 rn = "TCHalt";
5009 break;
5010 case 5:
5011 check_insn(env, ctx, ASE_MT);
5012 gen_helper_mtc0_tccontext(arg);
5013 rn = "TCContext";
5014 break;
5015 case 6:
5016 check_insn(env, ctx, ASE_MT);
5017 gen_helper_mtc0_tcschedule(arg);
5018 rn = "TCSchedule";
5019 break;
5020 case 7:
5021 check_insn(env, ctx, ASE_MT);
5022 gen_helper_mtc0_tcschefback(arg);
5023 rn = "TCScheFBack";
5024 break;
5025 default:
5026 goto die;
5028 break;
5029 case 3:
5030 switch (sel) {
5031 case 0:
5032 gen_helper_mtc0_entrylo1(arg);
5033 rn = "EntryLo1";
5034 break;
5035 default:
5036 goto die;
5038 break;
5039 case 4:
5040 switch (sel) {
5041 case 0:
5042 gen_helper_mtc0_context(arg);
5043 rn = "Context";
5044 break;
5045 case 1:
5046 // gen_helper_mtc0_contextconfig(arg); /* SmartMIPS ASE */
5047 rn = "ContextConfig";
5048 // break;
5049 default:
5050 goto die;
5052 break;
5053 case 5:
5054 switch (sel) {
5055 case 0:
5056 gen_helper_mtc0_pagemask(arg);
5057 rn = "PageMask";
5058 break;
5059 case 1:
5060 check_insn(env, ctx, ISA_MIPS32R2);
5061 gen_helper_mtc0_pagegrain(arg);
5062 rn = "PageGrain";
5063 break;
5064 default:
5065 goto die;
5067 break;
5068 case 6:
5069 switch (sel) {
5070 case 0:
5071 gen_helper_mtc0_wired(arg);
5072 rn = "Wired";
5073 break;
5074 case 1:
5075 check_insn(env, ctx, ISA_MIPS32R2);
5076 gen_helper_mtc0_srsconf0(arg);
5077 rn = "SRSConf0";
5078 break;
5079 case 2:
5080 check_insn(env, ctx, ISA_MIPS32R2);
5081 gen_helper_mtc0_srsconf1(arg);
5082 rn = "SRSConf1";
5083 break;
5084 case 3:
5085 check_insn(env, ctx, ISA_MIPS32R2);
5086 gen_helper_mtc0_srsconf2(arg);
5087 rn = "SRSConf2";
5088 break;
5089 case 4:
5090 check_insn(env, ctx, ISA_MIPS32R2);
5091 gen_helper_mtc0_srsconf3(arg);
5092 rn = "SRSConf3";
5093 break;
5094 case 5:
5095 check_insn(env, ctx, ISA_MIPS32R2);
5096 gen_helper_mtc0_srsconf4(arg);
5097 rn = "SRSConf4";
5098 break;
5099 default:
5100 goto die;
5102 break;
5103 case 7:
5104 switch (sel) {
5105 case 0:
5106 check_insn(env, ctx, ISA_MIPS32R2);
5107 gen_helper_mtc0_hwrena(arg);
5108 rn = "HWREna";
5109 break;
5110 default:
5111 goto die;
5113 break;
5114 case 8:
5115 /* ignored */
5116 rn = "BadVAddr";
5117 break;
5118 case 9:
5119 switch (sel) {
5120 case 0:
5121 gen_helper_mtc0_count(arg);
5122 rn = "Count";
5123 break;
5124 /* 6,7 are implementation dependent */
5125 default:
5126 goto die;
5128 /* Stop translation as we may have switched the execution mode */
5129 ctx->bstate = BS_STOP;
5130 break;
5131 case 10:
5132 switch (sel) {
5133 case 0:
5134 gen_helper_mtc0_entryhi(arg);
5135 rn = "EntryHi";
5136 break;
5137 default:
5138 goto die;
5140 break;
5141 case 11:
5142 switch (sel) {
5143 case 0:
5144 gen_helper_mtc0_compare(arg);
5145 rn = "Compare";
5146 break;
5147 /* 6,7 are implementation dependent */
5148 default:
5149 goto die;
5151 /* Stop translation as we may have switched the execution mode */
5152 ctx->bstate = BS_STOP;
5153 break;
5154 case 12:
5155 switch (sel) {
5156 case 0:
5157 save_cpu_state(ctx, 1);
5158 gen_helper_mtc0_status(arg);
5159 /* BS_STOP isn't good enough here, hflags may have changed. */
5160 gen_save_pc(ctx->pc + 4);
5161 ctx->bstate = BS_EXCP;
5162 rn = "Status";
5163 break;
5164 case 1:
5165 check_insn(env, ctx, ISA_MIPS32R2);
5166 gen_helper_mtc0_intctl(arg);
5167 /* Stop translation as we may have switched the execution mode */
5168 ctx->bstate = BS_STOP;
5169 rn = "IntCtl";
5170 break;
5171 case 2:
5172 check_insn(env, ctx, ISA_MIPS32R2);
5173 gen_helper_mtc0_srsctl(arg);
5174 /* Stop translation as we may have switched the execution mode */
5175 ctx->bstate = BS_STOP;
5176 rn = "SRSCtl";
5177 break;
5178 case 3:
5179 check_insn(env, ctx, ISA_MIPS32R2);
5180 gen_mtc0_store32(arg, offsetof(CPUState, CP0_SRSMap));
5181 /* Stop translation as we may have switched the execution mode */
5182 ctx->bstate = BS_STOP;
5183 rn = "SRSMap";
5184 break;
5185 default:
5186 goto die;
5188 break;
5189 case 13:
5190 switch (sel) {
5191 case 0:
5192 save_cpu_state(ctx, 1);
5193 gen_helper_mtc0_cause(arg);
5194 rn = "Cause";
5195 break;
5196 default:
5197 goto die;
5199 break;
5200 case 14:
5201 switch (sel) {
5202 case 0:
5203 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUState, CP0_EPC));
5204 rn = "EPC";
5205 break;
5206 default:
5207 goto die;
5209 break;
5210 case 15:
5211 switch (sel) {
5212 case 0:
5213 /* ignored */
5214 rn = "PRid";
5215 break;
5216 case 1:
5217 check_insn(env, ctx, ISA_MIPS32R2);
5218 gen_helper_mtc0_ebase(arg);
5219 rn = "EBase";
5220 break;
5221 default:
5222 goto die;
5224 break;
5225 case 16:
5226 switch (sel) {
5227 case 0:
5228 gen_helper_mtc0_config0(arg);
5229 rn = "Config";
5230 /* Stop translation as we may have switched the execution mode */
5231 ctx->bstate = BS_STOP;
5232 break;
5233 case 1:
5234 /* ignored, read only */
5235 rn = "Config1";
5236 break;
5237 case 2:
5238 gen_helper_mtc0_config2(arg);
5239 rn = "Config2";
5240 /* Stop translation as we may have switched the execution mode */
5241 ctx->bstate = BS_STOP;
5242 break;
5243 case 3:
5244 /* ignored */
5245 rn = "Config3";
5246 break;
5247 /* 6,7 are implementation dependent */
5248 default:
5249 rn = "Invalid config selector";
5250 goto die;
5252 break;
5253 case 17:
5254 switch (sel) {
5255 case 0:
5256 gen_helper_mtc0_lladdr(arg);
5257 rn = "LLAddr";
5258 break;
5259 default:
5260 goto die;
5262 break;
5263 case 18:
5264 switch (sel) {
5265 case 0 ... 7:
5266 gen_helper_1i(mtc0_watchlo, arg, sel);
5267 rn = "WatchLo";
5268 break;
5269 default:
5270 goto die;
5272 break;
5273 case 19:
5274 switch (sel) {
5275 case 0 ... 7:
5276 gen_helper_1i(mtc0_watchhi, arg, sel);
5277 rn = "WatchHi";
5278 break;
5279 default:
5280 goto die;
5282 break;
5283 case 20:
5284 switch (sel) {
5285 case 0:
5286 check_insn(env, ctx, ISA_MIPS3);
5287 gen_helper_mtc0_xcontext(arg);
5288 rn = "XContext";
5289 break;
5290 default:
5291 goto die;
5293 break;
5294 case 21:
5295 /* Officially reserved, but sel 0 is used for R1x000 framemask */
5296 switch (sel) {
5297 case 0:
5298 gen_helper_mtc0_framemask(arg);
5299 rn = "Framemask";
5300 break;
5301 default:
5302 goto die;
5304 break;
5305 case 22:
5306 /* ignored */
5307 rn = "Diagnostic"; /* implementation dependent */
5308 break;
5309 case 23:
5310 switch (sel) {
5311 case 0:
5312 gen_helper_mtc0_debug(arg); /* EJTAG support */
5313 /* BS_STOP isn't good enough here, hflags may have changed. */
5314 gen_save_pc(ctx->pc + 4);
5315 ctx->bstate = BS_EXCP;
5316 rn = "Debug";
5317 break;
5318 case 1:
5319 // gen_helper_mtc0_tracecontrol(arg); /* PDtrace support */
5320 /* Stop translation as we may have switched the execution mode */
5321 ctx->bstate = BS_STOP;
5322 rn = "TraceControl";
5323 // break;
5324 case 2:
5325 // gen_helper_mtc0_tracecontrol2(arg); /* PDtrace support */
5326 /* Stop translation as we may have switched the execution mode */
5327 ctx->bstate = BS_STOP;
5328 rn = "TraceControl2";
5329 // break;
5330 case 3:
5331 // gen_helper_mtc0_usertracedata(arg); /* PDtrace support */
5332 /* Stop translation as we may have switched the execution mode */
5333 ctx->bstate = BS_STOP;
5334 rn = "UserTraceData";
5335 // break;
5336 case 4:
5337 // gen_helper_mtc0_tracebpc(arg); /* PDtrace support */
5338 /* Stop translation as we may have switched the execution mode */
5339 ctx->bstate = BS_STOP;
5340 rn = "TraceBPC";
5341 // break;
5342 default:
5343 goto die;
5345 break;
5346 case 24:
5347 switch (sel) {
5348 case 0:
5349 /* EJTAG support */
5350 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUState, CP0_DEPC));
5351 rn = "DEPC";
5352 break;
5353 default:
5354 goto die;
5356 break;
5357 case 25:
5358 switch (sel) {
5359 case 0:
5360 gen_helper_mtc0_performance0(arg);
5361 rn = "Performance0";
5362 break;
5363 case 1:
5364 // gen_helper_mtc0_performance1(arg);
5365 rn = "Performance1";
5366 // break;
5367 case 2:
5368 // gen_helper_mtc0_performance2(arg);
5369 rn = "Performance2";
5370 // break;
5371 case 3:
5372 // gen_helper_mtc0_performance3(arg);
5373 rn = "Performance3";
5374 // break;
5375 case 4:
5376 // gen_helper_mtc0_performance4(arg);
5377 rn = "Performance4";
5378 // break;
5379 case 5:
5380 // gen_helper_mtc0_performance5(arg);
5381 rn = "Performance5";
5382 // break;
5383 case 6:
5384 // gen_helper_mtc0_performance6(arg);
5385 rn = "Performance6";
5386 // break;
5387 case 7:
5388 // gen_helper_mtc0_performance7(arg);
5389 rn = "Performance7";
5390 // break;
5391 default:
5392 goto die;
5394 break;
5395 case 26:
5396 /* ignored */
5397 rn = "ECC";
5398 break;
5399 case 27:
5400 switch (sel) {
5401 case 0 ... 3:
5402 /* ignored */
5403 rn = "CacheErr";
5404 break;
5405 default:
5406 goto die;
5408 break;
5409 case 28:
5410 switch (sel) {
5411 case 0:
5412 case 2:
5413 case 4:
5414 case 6:
5415 gen_helper_mtc0_taglo(arg);
5416 rn = "TagLo";
5417 break;
5418 case 1:
5419 case 3:
5420 case 5:
5421 case 7:
5422 gen_helper_mtc0_datalo(arg);
5423 rn = "DataLo";
5424 break;
5425 default:
5426 goto die;
5428 break;
5429 case 29:
5430 switch (sel) {
5431 case 0:
5432 case 2:
5433 case 4:
5434 case 6:
5435 gen_helper_mtc0_taghi(arg);
5436 rn = "TagHi";
5437 break;
5438 case 1:
5439 case 3:
5440 case 5:
5441 case 7:
5442 gen_helper_mtc0_datahi(arg);
5443 rn = "DataHi";
5444 break;
5445 default:
5446 rn = "invalid sel";
5447 goto die;
5449 break;
5450 case 30:
5451 switch (sel) {
5452 case 0:
5453 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUState, CP0_ErrorEPC));
5454 rn = "ErrorEPC";
5455 break;
5456 default:
5457 goto die;
5459 break;
5460 case 31:
5461 switch (sel) {
5462 case 0:
5463 /* EJTAG support */
5464 gen_mtc0_store32(arg, offsetof(CPUState, CP0_DESAVE));
5465 rn = "DESAVE";
5466 break;
5467 default:
5468 goto die;
5470 /* Stop translation as we may have switched the execution mode */
5471 ctx->bstate = BS_STOP;
5472 break;
5473 default:
5474 goto die;
5476 LOG_DISAS("dmtc0 %s (reg %d sel %d)\n", rn, reg, sel);
5477 /* For simplicity assume that all writes can cause interrupts. */
5478 if (use_icount) {
5479 gen_io_end();
5480 ctx->bstate = BS_STOP;
5482 return;
5484 die:
5485 LOG_DISAS("dmtc0 %s (reg %d sel %d)\n", rn, reg, sel);
5486 generate_exception(ctx, EXCP_RI);
5488 #endif /* TARGET_MIPS64 */
5490 static void gen_mftr(CPUState *env, DisasContext *ctx, int rt, int rd,
5491 int u, int sel, int h)
5493 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
5494 TCGv t0 = tcg_temp_local_new();
5496 if ((env->CP0_VPEConf0 & (1 << CP0VPEC0_MVP)) == 0 &&
5497 ((env->tcs[other_tc].CP0_TCBind & (0xf << CP0TCBd_CurVPE)) !=
5498 (env->active_tc.CP0_TCBind & (0xf << CP0TCBd_CurVPE))))
5499 tcg_gen_movi_tl(t0, -1);
5500 else if ((env->CP0_VPEControl & (0xff << CP0VPECo_TargTC)) >
5501 (env->mvp->CP0_MVPConf0 & (0xff << CP0MVPC0_PTC)))
5502 tcg_gen_movi_tl(t0, -1);
5503 else if (u == 0) {
5504 switch (rt) {
5505 case 2:
5506 switch (sel) {
5507 case 1:
5508 gen_helper_mftc0_tcstatus(t0);
5509 break;
5510 case 2:
5511 gen_helper_mftc0_tcbind(t0);
5512 break;
5513 case 3:
5514 gen_helper_mftc0_tcrestart(t0);
5515 break;
5516 case 4:
5517 gen_helper_mftc0_tchalt(t0);
5518 break;
5519 case 5:
5520 gen_helper_mftc0_tccontext(t0);
5521 break;
5522 case 6:
5523 gen_helper_mftc0_tcschedule(t0);
5524 break;
5525 case 7:
5526 gen_helper_mftc0_tcschefback(t0);
5527 break;
5528 default:
5529 gen_mfc0(env, ctx, t0, rt, sel);
5530 break;
5532 break;
5533 case 10:
5534 switch (sel) {
5535 case 0:
5536 gen_helper_mftc0_entryhi(t0);
5537 break;
5538 default:
5539 gen_mfc0(env, ctx, t0, rt, sel);
5540 break;
5542 case 12:
5543 switch (sel) {
5544 case 0:
5545 gen_helper_mftc0_status(t0);
5546 break;
5547 default:
5548 gen_mfc0(env, ctx, t0, rt, sel);
5549 break;
5551 case 23:
5552 switch (sel) {
5553 case 0:
5554 gen_helper_mftc0_debug(t0);
5555 break;
5556 default:
5557 gen_mfc0(env, ctx, t0, rt, sel);
5558 break;
5560 break;
5561 default:
5562 gen_mfc0(env, ctx, t0, rt, sel);
5564 } else switch (sel) {
5565 /* GPR registers. */
5566 case 0:
5567 gen_helper_1i(mftgpr, t0, rt);
5568 break;
5569 /* Auxiliary CPU registers */
5570 case 1:
5571 switch (rt) {
5572 case 0:
5573 gen_helper_1i(mftlo, t0, 0);
5574 break;
5575 case 1:
5576 gen_helper_1i(mfthi, t0, 0);
5577 break;
5578 case 2:
5579 gen_helper_1i(mftacx, t0, 0);
5580 break;
5581 case 4:
5582 gen_helper_1i(mftlo, t0, 1);
5583 break;
5584 case 5:
5585 gen_helper_1i(mfthi, t0, 1);
5586 break;
5587 case 6:
5588 gen_helper_1i(mftacx, t0, 1);
5589 break;
5590 case 8:
5591 gen_helper_1i(mftlo, t0, 2);
5592 break;
5593 case 9:
5594 gen_helper_1i(mfthi, t0, 2);
5595 break;
5596 case 10:
5597 gen_helper_1i(mftacx, t0, 2);
5598 break;
5599 case 12:
5600 gen_helper_1i(mftlo, t0, 3);
5601 break;
5602 case 13:
5603 gen_helper_1i(mfthi, t0, 3);
5604 break;
5605 case 14:
5606 gen_helper_1i(mftacx, t0, 3);
5607 break;
5608 case 16:
5609 gen_helper_mftdsp(t0);
5610 break;
5611 default:
5612 goto die;
5614 break;
5615 /* Floating point (COP1). */
5616 case 2:
5617 /* XXX: For now we support only a single FPU context. */
5618 if (h == 0) {
5619 TCGv_i32 fp0 = tcg_temp_new_i32();
5621 gen_load_fpr32(fp0, rt);
5622 tcg_gen_ext_i32_tl(t0, fp0);
5623 tcg_temp_free_i32(fp0);
5624 } else {
5625 TCGv_i32 fp0 = tcg_temp_new_i32();
5627 gen_load_fpr32h(fp0, rt);
5628 tcg_gen_ext_i32_tl(t0, fp0);
5629 tcg_temp_free_i32(fp0);
5631 break;
5632 case 3:
5633 /* XXX: For now we support only a single FPU context. */
5634 gen_helper_1i(cfc1, t0, rt);
5635 break;
5636 /* COP2: Not implemented. */
5637 case 4:
5638 case 5:
5639 /* fall through */
5640 default:
5641 goto die;
5643 LOG_DISAS("mftr (reg %d u %d sel %d h %d)\n", rt, u, sel, h);
5644 gen_store_gpr(t0, rd);
5645 tcg_temp_free(t0);
5646 return;
5648 die:
5649 tcg_temp_free(t0);
5650 LOG_DISAS("mftr (reg %d u %d sel %d h %d)\n", rt, u, sel, h);
5651 generate_exception(ctx, EXCP_RI);
5654 static void gen_mttr(CPUState *env, DisasContext *ctx, int rd, int rt,
5655 int u, int sel, int h)
5657 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
5658 TCGv t0 = tcg_temp_local_new();
5660 gen_load_gpr(t0, rt);
5661 if ((env->CP0_VPEConf0 & (1 << CP0VPEC0_MVP)) == 0 &&
5662 ((env->tcs[other_tc].CP0_TCBind & (0xf << CP0TCBd_CurVPE)) !=
5663 (env->active_tc.CP0_TCBind & (0xf << CP0TCBd_CurVPE))))
5664 /* NOP */ ;
5665 else if ((env->CP0_VPEControl & (0xff << CP0VPECo_TargTC)) >
5666 (env->mvp->CP0_MVPConf0 & (0xff << CP0MVPC0_PTC)))
5667 /* NOP */ ;
5668 else if (u == 0) {
5669 switch (rd) {
5670 case 2:
5671 switch (sel) {
5672 case 1:
5673 gen_helper_mttc0_tcstatus(t0);
5674 break;
5675 case 2:
5676 gen_helper_mttc0_tcbind(t0);
5677 break;
5678 case 3:
5679 gen_helper_mttc0_tcrestart(t0);
5680 break;
5681 case 4:
5682 gen_helper_mttc0_tchalt(t0);
5683 break;
5684 case 5:
5685 gen_helper_mttc0_tccontext(t0);
5686 break;
5687 case 6:
5688 gen_helper_mttc0_tcschedule(t0);
5689 break;
5690 case 7:
5691 gen_helper_mttc0_tcschefback(t0);
5692 break;
5693 default:
5694 gen_mtc0(env, ctx, t0, rd, sel);
5695 break;
5697 break;
5698 case 10:
5699 switch (sel) {
5700 case 0:
5701 gen_helper_mttc0_entryhi(t0);
5702 break;
5703 default:
5704 gen_mtc0(env, ctx, t0, rd, sel);
5705 break;
5707 case 12:
5708 switch (sel) {
5709 case 0:
5710 gen_helper_mttc0_status(t0);
5711 break;
5712 default:
5713 gen_mtc0(env, ctx, t0, rd, sel);
5714 break;
5716 case 23:
5717 switch (sel) {
5718 case 0:
5719 gen_helper_mttc0_debug(t0);
5720 break;
5721 default:
5722 gen_mtc0(env, ctx, t0, rd, sel);
5723 break;
5725 break;
5726 default:
5727 gen_mtc0(env, ctx, t0, rd, sel);
5729 } else switch (sel) {
5730 /* GPR registers. */
5731 case 0:
5732 gen_helper_1i(mttgpr, t0, rd);
5733 break;
5734 /* Auxiliary CPU registers */
5735 case 1:
5736 switch (rd) {
5737 case 0:
5738 gen_helper_1i(mttlo, t0, 0);
5739 break;
5740 case 1:
5741 gen_helper_1i(mtthi, t0, 0);
5742 break;
5743 case 2:
5744 gen_helper_1i(mttacx, t0, 0);
5745 break;
5746 case 4:
5747 gen_helper_1i(mttlo, t0, 1);
5748 break;
5749 case 5:
5750 gen_helper_1i(mtthi, t0, 1);
5751 break;
5752 case 6:
5753 gen_helper_1i(mttacx, t0, 1);
5754 break;
5755 case 8:
5756 gen_helper_1i(mttlo, t0, 2);
5757 break;
5758 case 9:
5759 gen_helper_1i(mtthi, t0, 2);
5760 break;
5761 case 10:
5762 gen_helper_1i(mttacx, t0, 2);
5763 break;
5764 case 12:
5765 gen_helper_1i(mttlo, t0, 3);
5766 break;
5767 case 13:
5768 gen_helper_1i(mtthi, t0, 3);
5769 break;
5770 case 14:
5771 gen_helper_1i(mttacx, t0, 3);
5772 break;
5773 case 16:
5774 gen_helper_mttdsp(t0);
5775 break;
5776 default:
5777 goto die;
5779 break;
5780 /* Floating point (COP1). */
5781 case 2:
5782 /* XXX: For now we support only a single FPU context. */
5783 if (h == 0) {
5784 TCGv_i32 fp0 = tcg_temp_new_i32();
5786 tcg_gen_trunc_tl_i32(fp0, t0);
5787 gen_store_fpr32(fp0, rd);
5788 tcg_temp_free_i32(fp0);
5789 } else {
5790 TCGv_i32 fp0 = tcg_temp_new_i32();
5792 tcg_gen_trunc_tl_i32(fp0, t0);
5793 gen_store_fpr32h(fp0, rd);
5794 tcg_temp_free_i32(fp0);
5796 break;
5797 case 3:
5798 /* XXX: For now we support only a single FPU context. */
5799 gen_helper_1i(ctc1, t0, rd);
5800 break;
5801 /* COP2: Not implemented. */
5802 case 4:
5803 case 5:
5804 /* fall through */
5805 default:
5806 goto die;
5808 LOG_DISAS("mttr (reg %d u %d sel %d h %d)\n", rd, u, sel, h);
5809 tcg_temp_free(t0);
5810 return;
5812 die:
5813 tcg_temp_free(t0);
5814 LOG_DISAS("mttr (reg %d u %d sel %d h %d)\n", rd, u, sel, h);
5815 generate_exception(ctx, EXCP_RI);
5818 static void gen_cp0 (CPUState *env, DisasContext *ctx, uint32_t opc, int rt, int rd)
5820 const char *opn = "ldst";
5822 switch (opc) {
5823 case OPC_MFC0:
5824 if (rt == 0) {
5825 /* Treat as NOP. */
5826 return;
5828 gen_mfc0(env, ctx, cpu_gpr[rt], rd, ctx->opcode & 0x7);
5829 opn = "mfc0";
5830 break;
5831 case OPC_MTC0:
5833 TCGv t0 = tcg_temp_new();
5835 gen_load_gpr(t0, rt);
5836 gen_mtc0(env, ctx, t0, rd, ctx->opcode & 0x7);
5837 tcg_temp_free(t0);
5839 opn = "mtc0";
5840 break;
5841 #if defined(TARGET_MIPS64)
5842 case OPC_DMFC0:
5843 check_insn(env, ctx, ISA_MIPS3);
5844 if (rt == 0) {
5845 /* Treat as NOP. */
5846 return;
5848 gen_dmfc0(env, ctx, cpu_gpr[rt], rd, ctx->opcode & 0x7);
5849 opn = "dmfc0";
5850 break;
5851 case OPC_DMTC0:
5852 check_insn(env, ctx, ISA_MIPS3);
5854 TCGv t0 = tcg_temp_new();
5856 gen_load_gpr(t0, rt);
5857 gen_dmtc0(env, ctx, t0, rd, ctx->opcode & 0x7);
5858 tcg_temp_free(t0);
5860 opn = "dmtc0";
5861 break;
5862 #endif
5863 case OPC_MFTR:
5864 check_insn(env, ctx, ASE_MT);
5865 if (rd == 0) {
5866 /* Treat as NOP. */
5867 return;
5869 gen_mftr(env, ctx, rt, rd, (ctx->opcode >> 5) & 1,
5870 ctx->opcode & 0x7, (ctx->opcode >> 4) & 1);
5871 opn = "mftr";
5872 break;
5873 case OPC_MTTR:
5874 check_insn(env, ctx, ASE_MT);
5875 gen_mttr(env, ctx, rd, rt, (ctx->opcode >> 5) & 1,
5876 ctx->opcode & 0x7, (ctx->opcode >> 4) & 1);
5877 opn = "mttr";
5878 break;
5879 case OPC_TLBWI:
5880 opn = "tlbwi";
5881 if (!env->tlb->helper_tlbwi)
5882 goto die;
5883 gen_helper_tlbwi();
5884 break;
5885 case OPC_TLBWR:
5886 opn = "tlbwr";
5887 if (!env->tlb->helper_tlbwr)
5888 goto die;
5889 gen_helper_tlbwr();
5890 break;
5891 case OPC_TLBP:
5892 opn = "tlbp";
5893 if (!env->tlb->helper_tlbp)
5894 goto die;
5895 gen_helper_tlbp();
5896 break;
5897 case OPC_TLBR:
5898 opn = "tlbr";
5899 if (!env->tlb->helper_tlbr)
5900 goto die;
5901 gen_helper_tlbr();
5902 break;
5903 case OPC_ERET:
5904 opn = "eret";
5905 check_insn(env, ctx, ISA_MIPS2);
5906 gen_helper_eret();
5907 ctx->bstate = BS_EXCP;
5908 break;
5909 case OPC_DERET:
5910 opn = "deret";
5911 check_insn(env, ctx, ISA_MIPS32);
5912 if (!(ctx->hflags & MIPS_HFLAG_DM)) {
5913 MIPS_INVAL(opn);
5914 generate_exception(ctx, EXCP_RI);
5915 } else {
5916 gen_helper_deret();
5917 ctx->bstate = BS_EXCP;
5919 break;
5920 case OPC_WAIT:
5921 opn = "wait";
5922 check_insn(env, ctx, ISA_MIPS3 | ISA_MIPS32);
5923 /* If we get an exception, we want to restart at next instruction */
5924 ctx->pc += 4;
5925 save_cpu_state(ctx, 1);
5926 ctx->pc -= 4;
5927 gen_helper_wait();
5928 ctx->bstate = BS_EXCP;
5929 break;
5930 default:
5931 die:
5932 MIPS_INVAL(opn);
5933 generate_exception(ctx, EXCP_RI);
5934 return;
5936 MIPS_DEBUG("%s %s %d", opn, regnames[rt], rd);
5938 #endif /* !CONFIG_USER_ONLY */
5940 /* CP1 Branches (before delay slot) */
5941 static void gen_compute_branch1 (CPUState *env, DisasContext *ctx, uint32_t op,
5942 int32_t cc, int32_t offset)
5944 target_ulong btarget;
5945 const char *opn = "cp1 cond branch";
5946 TCGv_i32 t0 = tcg_temp_new_i32();
5948 if (cc != 0)
5949 check_insn(env, ctx, ISA_MIPS4 | ISA_MIPS32);
5951 btarget = ctx->pc + 4 + offset;
5953 switch (op) {
5954 case OPC_BC1F:
5955 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
5956 tcg_gen_not_i32(t0, t0);
5957 tcg_gen_andi_i32(t0, t0, 1);
5958 tcg_gen_extu_i32_tl(bcond, t0);
5959 opn = "bc1f";
5960 goto not_likely;
5961 case OPC_BC1FL:
5962 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
5963 tcg_gen_not_i32(t0, t0);
5964 tcg_gen_andi_i32(t0, t0, 1);
5965 tcg_gen_extu_i32_tl(bcond, t0);
5966 opn = "bc1fl";
5967 goto likely;
5968 case OPC_BC1T:
5969 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
5970 tcg_gen_andi_i32(t0, t0, 1);
5971 tcg_gen_extu_i32_tl(bcond, t0);
5972 opn = "bc1t";
5973 goto not_likely;
5974 case OPC_BC1TL:
5975 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
5976 tcg_gen_andi_i32(t0, t0, 1);
5977 tcg_gen_extu_i32_tl(bcond, t0);
5978 opn = "bc1tl";
5979 likely:
5980 ctx->hflags |= MIPS_HFLAG_BL;
5981 break;
5982 case OPC_BC1FANY2:
5984 TCGv_i32 t1 = tcg_temp_new_i32();
5985 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
5986 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+1));
5987 tcg_gen_nor_i32(t0, t0, t1);
5988 tcg_temp_free_i32(t1);
5989 tcg_gen_andi_i32(t0, t0, 1);
5990 tcg_gen_extu_i32_tl(bcond, t0);
5992 opn = "bc1any2f";
5993 goto not_likely;
5994 case OPC_BC1TANY2:
5996 TCGv_i32 t1 = tcg_temp_new_i32();
5997 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
5998 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+1));
5999 tcg_gen_or_i32(t0, t0, t1);
6000 tcg_temp_free_i32(t1);
6001 tcg_gen_andi_i32(t0, t0, 1);
6002 tcg_gen_extu_i32_tl(bcond, t0);
6004 opn = "bc1any2t";
6005 goto not_likely;
6006 case OPC_BC1FANY4:
6008 TCGv_i32 t1 = tcg_temp_new_i32();
6009 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
6010 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+1));
6011 tcg_gen_or_i32(t0, t0, t1);
6012 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+2));
6013 tcg_gen_or_i32(t0, t0, t1);
6014 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+3));
6015 tcg_gen_nor_i32(t0, t0, t1);
6016 tcg_temp_free_i32(t1);
6017 tcg_gen_andi_i32(t0, t0, 1);
6018 tcg_gen_extu_i32_tl(bcond, t0);
6020 opn = "bc1any4f";
6021 goto not_likely;
6022 case OPC_BC1TANY4:
6024 TCGv_i32 t1 = tcg_temp_new_i32();
6025 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
6026 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+1));
6027 tcg_gen_or_i32(t0, t0, t1);
6028 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+2));
6029 tcg_gen_or_i32(t0, t0, t1);
6030 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+3));
6031 tcg_gen_or_i32(t0, t0, t1);
6032 tcg_temp_free_i32(t1);
6033 tcg_gen_andi_i32(t0, t0, 1);
6034 tcg_gen_extu_i32_tl(bcond, t0);
6036 opn = "bc1any4t";
6037 not_likely:
6038 ctx->hflags |= MIPS_HFLAG_BC;
6039 break;
6040 default:
6041 MIPS_INVAL(opn);
6042 generate_exception (ctx, EXCP_RI);
6043 goto out;
6045 MIPS_DEBUG("%s: cond %02x target " TARGET_FMT_lx, opn,
6046 ctx->hflags, btarget);
6047 ctx->btarget = btarget;
6049 out:
6050 tcg_temp_free_i32(t0);
6053 /* Coprocessor 1 (FPU) */
6055 #define FOP(func, fmt) (((fmt) << 21) | (func))
6057 enum fopcode {
6058 OPC_ADD_S = FOP(0, FMT_S),
6059 OPC_SUB_S = FOP(1, FMT_S),
6060 OPC_MUL_S = FOP(2, FMT_S),
6061 OPC_DIV_S = FOP(3, FMT_S),
6062 OPC_SQRT_S = FOP(4, FMT_S),
6063 OPC_ABS_S = FOP(5, FMT_S),
6064 OPC_MOV_S = FOP(6, FMT_S),
6065 OPC_NEG_S = FOP(7, FMT_S),
6066 OPC_ROUND_L_S = FOP(8, FMT_S),
6067 OPC_TRUNC_L_S = FOP(9, FMT_S),
6068 OPC_CEIL_L_S = FOP(10, FMT_S),
6069 OPC_FLOOR_L_S = FOP(11, FMT_S),
6070 OPC_ROUND_W_S = FOP(12, FMT_S),
6071 OPC_TRUNC_W_S = FOP(13, FMT_S),
6072 OPC_CEIL_W_S = FOP(14, FMT_S),
6073 OPC_FLOOR_W_S = FOP(15, FMT_S),
6074 OPC_MOVCF_S = FOP(17, FMT_S),
6075 OPC_MOVZ_S = FOP(18, FMT_S),
6076 OPC_MOVN_S = FOP(19, FMT_S),
6077 OPC_RECIP_S = FOP(21, FMT_S),
6078 OPC_RSQRT_S = FOP(22, FMT_S),
6079 OPC_RECIP2_S = FOP(28, FMT_S),
6080 OPC_RECIP1_S = FOP(29, FMT_S),
6081 OPC_RSQRT1_S = FOP(30, FMT_S),
6082 OPC_RSQRT2_S = FOP(31, FMT_S),
6083 OPC_CVT_D_S = FOP(33, FMT_S),
6084 OPC_CVT_W_S = FOP(36, FMT_S),
6085 OPC_CVT_L_S = FOP(37, FMT_S),
6086 OPC_CVT_PS_S = FOP(38, FMT_S),
6087 OPC_CMP_F_S = FOP (48, FMT_S),
6088 OPC_CMP_UN_S = FOP (49, FMT_S),
6089 OPC_CMP_EQ_S = FOP (50, FMT_S),
6090 OPC_CMP_UEQ_S = FOP (51, FMT_S),
6091 OPC_CMP_OLT_S = FOP (52, FMT_S),
6092 OPC_CMP_ULT_S = FOP (53, FMT_S),
6093 OPC_CMP_OLE_S = FOP (54, FMT_S),
6094 OPC_CMP_ULE_S = FOP (55, FMT_S),
6095 OPC_CMP_SF_S = FOP (56, FMT_S),
6096 OPC_CMP_NGLE_S = FOP (57, FMT_S),
6097 OPC_CMP_SEQ_S = FOP (58, FMT_S),
6098 OPC_CMP_NGL_S = FOP (59, FMT_S),
6099 OPC_CMP_LT_S = FOP (60, FMT_S),
6100 OPC_CMP_NGE_S = FOP (61, FMT_S),
6101 OPC_CMP_LE_S = FOP (62, FMT_S),
6102 OPC_CMP_NGT_S = FOP (63, FMT_S),
6104 OPC_ADD_D = FOP(0, FMT_D),
6105 OPC_SUB_D = FOP(1, FMT_D),
6106 OPC_MUL_D = FOP(2, FMT_D),
6107 OPC_DIV_D = FOP(3, FMT_D),
6108 OPC_SQRT_D = FOP(4, FMT_D),
6109 OPC_ABS_D = FOP(5, FMT_D),
6110 OPC_MOV_D = FOP(6, FMT_D),
6111 OPC_NEG_D = FOP(7, FMT_D),
6112 OPC_ROUND_L_D = FOP(8, FMT_D),
6113 OPC_TRUNC_L_D = FOP(9, FMT_D),
6114 OPC_CEIL_L_D = FOP(10, FMT_D),
6115 OPC_FLOOR_L_D = FOP(11, FMT_D),
6116 OPC_ROUND_W_D = FOP(12, FMT_D),
6117 OPC_TRUNC_W_D = FOP(13, FMT_D),
6118 OPC_CEIL_W_D = FOP(14, FMT_D),
6119 OPC_FLOOR_W_D = FOP(15, FMT_D),
6120 OPC_MOVCF_D = FOP(17, FMT_D),
6121 OPC_MOVZ_D = FOP(18, FMT_D),
6122 OPC_MOVN_D = FOP(19, FMT_D),
6123 OPC_RECIP_D = FOP(21, FMT_D),
6124 OPC_RSQRT_D = FOP(22, FMT_D),
6125 OPC_RECIP2_D = FOP(28, FMT_D),
6126 OPC_RECIP1_D = FOP(29, FMT_D),
6127 OPC_RSQRT1_D = FOP(30, FMT_D),
6128 OPC_RSQRT2_D = FOP(31, FMT_D),
6129 OPC_CVT_S_D = FOP(32, FMT_D),
6130 OPC_CVT_W_D = FOP(36, FMT_D),
6131 OPC_CVT_L_D = FOP(37, FMT_D),
6132 OPC_CMP_F_D = FOP (48, FMT_D),
6133 OPC_CMP_UN_D = FOP (49, FMT_D),
6134 OPC_CMP_EQ_D = FOP (50, FMT_D),
6135 OPC_CMP_UEQ_D = FOP (51, FMT_D),
6136 OPC_CMP_OLT_D = FOP (52, FMT_D),
6137 OPC_CMP_ULT_D = FOP (53, FMT_D),
6138 OPC_CMP_OLE_D = FOP (54, FMT_D),
6139 OPC_CMP_ULE_D = FOP (55, FMT_D),
6140 OPC_CMP_SF_D = FOP (56, FMT_D),
6141 OPC_CMP_NGLE_D = FOP (57, FMT_D),
6142 OPC_CMP_SEQ_D = FOP (58, FMT_D),
6143 OPC_CMP_NGL_D = FOP (59, FMT_D),
6144 OPC_CMP_LT_D = FOP (60, FMT_D),
6145 OPC_CMP_NGE_D = FOP (61, FMT_D),
6146 OPC_CMP_LE_D = FOP (62, FMT_D),
6147 OPC_CMP_NGT_D = FOP (63, FMT_D),
6149 OPC_CVT_S_W = FOP(32, FMT_W),
6150 OPC_CVT_D_W = FOP(33, FMT_W),
6151 OPC_CVT_S_L = FOP(32, FMT_L),
6152 OPC_CVT_D_L = FOP(33, FMT_L),
6153 OPC_CVT_PS_PW = FOP(38, FMT_W),
6155 OPC_ADD_PS = FOP(0, FMT_PS),
6156 OPC_SUB_PS = FOP(1, FMT_PS),
6157 OPC_MUL_PS = FOP(2, FMT_PS),
6158 OPC_DIV_PS = FOP(3, FMT_PS),
6159 OPC_ABS_PS = FOP(5, FMT_PS),
6160 OPC_MOV_PS = FOP(6, FMT_PS),
6161 OPC_NEG_PS = FOP(7, FMT_PS),
6162 OPC_MOVCF_PS = FOP(17, FMT_PS),
6163 OPC_MOVZ_PS = FOP(18, FMT_PS),
6164 OPC_MOVN_PS = FOP(19, FMT_PS),
6165 OPC_ADDR_PS = FOP(24, FMT_PS),
6166 OPC_MULR_PS = FOP(26, FMT_PS),
6167 OPC_RECIP2_PS = FOP(28, FMT_PS),
6168 OPC_RECIP1_PS = FOP(29, FMT_PS),
6169 OPC_RSQRT1_PS = FOP(30, FMT_PS),
6170 OPC_RSQRT2_PS = FOP(31, FMT_PS),
6172 OPC_CVT_S_PU = FOP(32, FMT_PS),
6173 OPC_CVT_PW_PS = FOP(36, FMT_PS),
6174 OPC_CVT_S_PL = FOP(40, FMT_PS),
6175 OPC_PLL_PS = FOP(44, FMT_PS),
6176 OPC_PLU_PS = FOP(45, FMT_PS),
6177 OPC_PUL_PS = FOP(46, FMT_PS),
6178 OPC_PUU_PS = FOP(47, FMT_PS),
6179 OPC_CMP_F_PS = FOP (48, FMT_PS),
6180 OPC_CMP_UN_PS = FOP (49, FMT_PS),
6181 OPC_CMP_EQ_PS = FOP (50, FMT_PS),
6182 OPC_CMP_UEQ_PS = FOP (51, FMT_PS),
6183 OPC_CMP_OLT_PS = FOP (52, FMT_PS),
6184 OPC_CMP_ULT_PS = FOP (53, FMT_PS),
6185 OPC_CMP_OLE_PS = FOP (54, FMT_PS),
6186 OPC_CMP_ULE_PS = FOP (55, FMT_PS),
6187 OPC_CMP_SF_PS = FOP (56, FMT_PS),
6188 OPC_CMP_NGLE_PS = FOP (57, FMT_PS),
6189 OPC_CMP_SEQ_PS = FOP (58, FMT_PS),
6190 OPC_CMP_NGL_PS = FOP (59, FMT_PS),
6191 OPC_CMP_LT_PS = FOP (60, FMT_PS),
6192 OPC_CMP_NGE_PS = FOP (61, FMT_PS),
6193 OPC_CMP_LE_PS = FOP (62, FMT_PS),
6194 OPC_CMP_NGT_PS = FOP (63, FMT_PS),
6197 static void gen_cp1 (DisasContext *ctx, uint32_t opc, int rt, int fs)
6199 const char *opn = "cp1 move";
6200 TCGv t0 = tcg_temp_new();
6202 switch (opc) {
6203 case OPC_MFC1:
6205 TCGv_i32 fp0 = tcg_temp_new_i32();
6207 gen_load_fpr32(fp0, fs);
6208 tcg_gen_ext_i32_tl(t0, fp0);
6209 tcg_temp_free_i32(fp0);
6211 gen_store_gpr(t0, rt);
6212 opn = "mfc1";
6213 break;
6214 case OPC_MTC1:
6215 gen_load_gpr(t0, rt);
6217 TCGv_i32 fp0 = tcg_temp_new_i32();
6219 tcg_gen_trunc_tl_i32(fp0, t0);
6220 gen_store_fpr32(fp0, fs);
6221 tcg_temp_free_i32(fp0);
6223 opn = "mtc1";
6224 break;
6225 case OPC_CFC1:
6226 gen_helper_1i(cfc1, t0, fs);
6227 gen_store_gpr(t0, rt);
6228 opn = "cfc1";
6229 break;
6230 case OPC_CTC1:
6231 gen_load_gpr(t0, rt);
6232 gen_helper_1i(ctc1, t0, fs);
6233 opn = "ctc1";
6234 break;
6235 #if defined(TARGET_MIPS64)
6236 case OPC_DMFC1:
6237 gen_load_fpr64(ctx, t0, fs);
6238 gen_store_gpr(t0, rt);
6239 opn = "dmfc1";
6240 break;
6241 case OPC_DMTC1:
6242 gen_load_gpr(t0, rt);
6243 gen_store_fpr64(ctx, t0, fs);
6244 opn = "dmtc1";
6245 break;
6246 #endif
6247 case OPC_MFHC1:
6249 TCGv_i32 fp0 = tcg_temp_new_i32();
6251 gen_load_fpr32h(fp0, fs);
6252 tcg_gen_ext_i32_tl(t0, fp0);
6253 tcg_temp_free_i32(fp0);
6255 gen_store_gpr(t0, rt);
6256 opn = "mfhc1";
6257 break;
6258 case OPC_MTHC1:
6259 gen_load_gpr(t0, rt);
6261 TCGv_i32 fp0 = tcg_temp_new_i32();
6263 tcg_gen_trunc_tl_i32(fp0, t0);
6264 gen_store_fpr32h(fp0, fs);
6265 tcg_temp_free_i32(fp0);
6267 opn = "mthc1";
6268 break;
6269 default:
6270 MIPS_INVAL(opn);
6271 generate_exception (ctx, EXCP_RI);
6272 goto out;
6274 MIPS_DEBUG("%s %s %s", opn, regnames[rt], fregnames[fs]);
6276 out:
6277 tcg_temp_free(t0);
6280 static void gen_movci (DisasContext *ctx, int rd, int rs, int cc, int tf)
6282 int l1;
6283 TCGCond cond;
6284 TCGv_i32 t0;
6286 if (rd == 0) {
6287 /* Treat as NOP. */
6288 return;
6291 if (tf)
6292 cond = TCG_COND_EQ;
6293 else
6294 cond = TCG_COND_NE;
6296 l1 = gen_new_label();
6297 t0 = tcg_temp_new_i32();
6298 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
6299 tcg_gen_brcondi_i32(cond, t0, 0, l1);
6300 tcg_temp_free_i32(t0);
6301 if (rs == 0) {
6302 tcg_gen_movi_tl(cpu_gpr[rd], 0);
6303 } else {
6304 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
6306 gen_set_label(l1);
6309 static inline void gen_movcf_s (int fs, int fd, int cc, int tf)
6311 int cond;
6312 TCGv_i32 t0 = tcg_temp_new_i32();
6313 int l1 = gen_new_label();
6315 if (tf)
6316 cond = TCG_COND_EQ;
6317 else
6318 cond = TCG_COND_NE;
6320 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
6321 tcg_gen_brcondi_i32(cond, t0, 0, l1);
6322 gen_load_fpr32(t0, fs);
6323 gen_store_fpr32(t0, fd);
6324 gen_set_label(l1);
6325 tcg_temp_free_i32(t0);
6328 static inline void gen_movcf_d (DisasContext *ctx, int fs, int fd, int cc, int tf)
6330 int cond;
6331 TCGv_i32 t0 = tcg_temp_new_i32();
6332 TCGv_i64 fp0;
6333 int l1 = gen_new_label();
6335 if (tf)
6336 cond = TCG_COND_EQ;
6337 else
6338 cond = TCG_COND_NE;
6340 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
6341 tcg_gen_brcondi_i32(cond, t0, 0, l1);
6342 tcg_temp_free_i32(t0);
6343 fp0 = tcg_temp_new_i64();
6344 gen_load_fpr64(ctx, fp0, fs);
6345 gen_store_fpr64(ctx, fp0, fd);
6346 tcg_temp_free_i64(fp0);
6347 gen_set_label(l1);
6350 static inline void gen_movcf_ps (int fs, int fd, int cc, int tf)
6352 int cond;
6353 TCGv_i32 t0 = tcg_temp_new_i32();
6354 int l1 = gen_new_label();
6355 int l2 = gen_new_label();
6357 if (tf)
6358 cond = TCG_COND_EQ;
6359 else
6360 cond = TCG_COND_NE;
6362 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
6363 tcg_gen_brcondi_i32(cond, t0, 0, l1);
6364 gen_load_fpr32(t0, fs);
6365 gen_store_fpr32(t0, fd);
6366 gen_set_label(l1);
6368 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc+1));
6369 tcg_gen_brcondi_i32(cond, t0, 0, l2);
6370 gen_load_fpr32h(t0, fs);
6371 gen_store_fpr32h(t0, fd);
6372 tcg_temp_free_i32(t0);
6373 gen_set_label(l2);
6377 static void gen_farith (DisasContext *ctx, enum fopcode op1,
6378 int ft, int fs, int fd, int cc)
6380 const char *opn = "farith";
6381 const char *condnames[] = {
6382 "c.f",
6383 "c.un",
6384 "c.eq",
6385 "c.ueq",
6386 "c.olt",
6387 "c.ult",
6388 "c.ole",
6389 "c.ule",
6390 "c.sf",
6391 "c.ngle",
6392 "c.seq",
6393 "c.ngl",
6394 "c.lt",
6395 "c.nge",
6396 "c.le",
6397 "c.ngt",
6399 const char *condnames_abs[] = {
6400 "cabs.f",
6401 "cabs.un",
6402 "cabs.eq",
6403 "cabs.ueq",
6404 "cabs.olt",
6405 "cabs.ult",
6406 "cabs.ole",
6407 "cabs.ule",
6408 "cabs.sf",
6409 "cabs.ngle",
6410 "cabs.seq",
6411 "cabs.ngl",
6412 "cabs.lt",
6413 "cabs.nge",
6414 "cabs.le",
6415 "cabs.ngt",
6417 enum { BINOP, CMPOP, OTHEROP } optype = OTHEROP;
6418 uint32_t func = ctx->opcode & 0x3f;
6420 switch (op1) {
6421 case OPC_ADD_S:
6423 TCGv_i32 fp0 = tcg_temp_new_i32();
6424 TCGv_i32 fp1 = tcg_temp_new_i32();
6426 gen_load_fpr32(fp0, fs);
6427 gen_load_fpr32(fp1, ft);
6428 gen_helper_float_add_s(fp0, fp0, fp1);
6429 tcg_temp_free_i32(fp1);
6430 gen_store_fpr32(fp0, fd);
6431 tcg_temp_free_i32(fp0);
6433 opn = "add.s";
6434 optype = BINOP;
6435 break;
6436 case OPC_SUB_S:
6438 TCGv_i32 fp0 = tcg_temp_new_i32();
6439 TCGv_i32 fp1 = tcg_temp_new_i32();
6441 gen_load_fpr32(fp0, fs);
6442 gen_load_fpr32(fp1, ft);
6443 gen_helper_float_sub_s(fp0, fp0, fp1);
6444 tcg_temp_free_i32(fp1);
6445 gen_store_fpr32(fp0, fd);
6446 tcg_temp_free_i32(fp0);
6448 opn = "sub.s";
6449 optype = BINOP;
6450 break;
6451 case OPC_MUL_S:
6453 TCGv_i32 fp0 = tcg_temp_new_i32();
6454 TCGv_i32 fp1 = tcg_temp_new_i32();
6456 gen_load_fpr32(fp0, fs);
6457 gen_load_fpr32(fp1, ft);
6458 gen_helper_float_mul_s(fp0, fp0, fp1);
6459 tcg_temp_free_i32(fp1);
6460 gen_store_fpr32(fp0, fd);
6461 tcg_temp_free_i32(fp0);
6463 opn = "mul.s";
6464 optype = BINOP;
6465 break;
6466 case OPC_DIV_S:
6468 TCGv_i32 fp0 = tcg_temp_new_i32();
6469 TCGv_i32 fp1 = tcg_temp_new_i32();
6471 gen_load_fpr32(fp0, fs);
6472 gen_load_fpr32(fp1, ft);
6473 gen_helper_float_div_s(fp0, fp0, fp1);
6474 tcg_temp_free_i32(fp1);
6475 gen_store_fpr32(fp0, fd);
6476 tcg_temp_free_i32(fp0);
6478 opn = "div.s";
6479 optype = BINOP;
6480 break;
6481 case OPC_SQRT_S:
6483 TCGv_i32 fp0 = tcg_temp_new_i32();
6485 gen_load_fpr32(fp0, fs);
6486 gen_helper_float_sqrt_s(fp0, fp0);
6487 gen_store_fpr32(fp0, fd);
6488 tcg_temp_free_i32(fp0);
6490 opn = "sqrt.s";
6491 break;
6492 case OPC_ABS_S:
6494 TCGv_i32 fp0 = tcg_temp_new_i32();
6496 gen_load_fpr32(fp0, fs);
6497 gen_helper_float_abs_s(fp0, fp0);
6498 gen_store_fpr32(fp0, fd);
6499 tcg_temp_free_i32(fp0);
6501 opn = "abs.s";
6502 break;
6503 case OPC_MOV_S:
6505 TCGv_i32 fp0 = tcg_temp_new_i32();
6507 gen_load_fpr32(fp0, fs);
6508 gen_store_fpr32(fp0, fd);
6509 tcg_temp_free_i32(fp0);
6511 opn = "mov.s";
6512 break;
6513 case OPC_NEG_S:
6515 TCGv_i32 fp0 = tcg_temp_new_i32();
6517 gen_load_fpr32(fp0, fs);
6518 gen_helper_float_chs_s(fp0, fp0);
6519 gen_store_fpr32(fp0, fd);
6520 tcg_temp_free_i32(fp0);
6522 opn = "neg.s";
6523 break;
6524 case OPC_ROUND_L_S:
6525 check_cp1_64bitmode(ctx);
6527 TCGv_i32 fp32 = tcg_temp_new_i32();
6528 TCGv_i64 fp64 = tcg_temp_new_i64();
6530 gen_load_fpr32(fp32, fs);
6531 gen_helper_float_roundl_s(fp64, fp32);
6532 tcg_temp_free_i32(fp32);
6533 gen_store_fpr64(ctx, fp64, fd);
6534 tcg_temp_free_i64(fp64);
6536 opn = "round.l.s";
6537 break;
6538 case OPC_TRUNC_L_S:
6539 check_cp1_64bitmode(ctx);
6541 TCGv_i32 fp32 = tcg_temp_new_i32();
6542 TCGv_i64 fp64 = tcg_temp_new_i64();
6544 gen_load_fpr32(fp32, fs);
6545 gen_helper_float_truncl_s(fp64, fp32);
6546 tcg_temp_free_i32(fp32);
6547 gen_store_fpr64(ctx, fp64, fd);
6548 tcg_temp_free_i64(fp64);
6550 opn = "trunc.l.s";
6551 break;
6552 case OPC_CEIL_L_S:
6553 check_cp1_64bitmode(ctx);
6555 TCGv_i32 fp32 = tcg_temp_new_i32();
6556 TCGv_i64 fp64 = tcg_temp_new_i64();
6558 gen_load_fpr32(fp32, fs);
6559 gen_helper_float_ceill_s(fp64, fp32);
6560 tcg_temp_free_i32(fp32);
6561 gen_store_fpr64(ctx, fp64, fd);
6562 tcg_temp_free_i64(fp64);
6564 opn = "ceil.l.s";
6565 break;
6566 case OPC_FLOOR_L_S:
6567 check_cp1_64bitmode(ctx);
6569 TCGv_i32 fp32 = tcg_temp_new_i32();
6570 TCGv_i64 fp64 = tcg_temp_new_i64();
6572 gen_load_fpr32(fp32, fs);
6573 gen_helper_float_floorl_s(fp64, fp32);
6574 tcg_temp_free_i32(fp32);
6575 gen_store_fpr64(ctx, fp64, fd);
6576 tcg_temp_free_i64(fp64);
6578 opn = "floor.l.s";
6579 break;
6580 case OPC_ROUND_W_S:
6582 TCGv_i32 fp0 = tcg_temp_new_i32();
6584 gen_load_fpr32(fp0, fs);
6585 gen_helper_float_roundw_s(fp0, fp0);
6586 gen_store_fpr32(fp0, fd);
6587 tcg_temp_free_i32(fp0);
6589 opn = "round.w.s";
6590 break;
6591 case OPC_TRUNC_W_S:
6593 TCGv_i32 fp0 = tcg_temp_new_i32();
6595 gen_load_fpr32(fp0, fs);
6596 gen_helper_float_truncw_s(fp0, fp0);
6597 gen_store_fpr32(fp0, fd);
6598 tcg_temp_free_i32(fp0);
6600 opn = "trunc.w.s";
6601 break;
6602 case OPC_CEIL_W_S:
6604 TCGv_i32 fp0 = tcg_temp_new_i32();
6606 gen_load_fpr32(fp0, fs);
6607 gen_helper_float_ceilw_s(fp0, fp0);
6608 gen_store_fpr32(fp0, fd);
6609 tcg_temp_free_i32(fp0);
6611 opn = "ceil.w.s";
6612 break;
6613 case OPC_FLOOR_W_S:
6615 TCGv_i32 fp0 = tcg_temp_new_i32();
6617 gen_load_fpr32(fp0, fs);
6618 gen_helper_float_floorw_s(fp0, fp0);
6619 gen_store_fpr32(fp0, fd);
6620 tcg_temp_free_i32(fp0);
6622 opn = "floor.w.s";
6623 break;
6624 case OPC_MOVCF_S:
6625 gen_movcf_s(fs, fd, (ft >> 2) & 0x7, ft & 0x1);
6626 opn = "movcf.s";
6627 break;
6628 case OPC_MOVZ_S:
6630 int l1 = gen_new_label();
6631 TCGv_i32 fp0;
6633 if (ft != 0) {
6634 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[ft], 0, l1);
6636 fp0 = tcg_temp_new_i32();
6637 gen_load_fpr32(fp0, fs);
6638 gen_store_fpr32(fp0, fd);
6639 tcg_temp_free_i32(fp0);
6640 gen_set_label(l1);
6642 opn = "movz.s";
6643 break;
6644 case OPC_MOVN_S:
6646 int l1 = gen_new_label();
6647 TCGv_i32 fp0;
6649 if (ft != 0) {
6650 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[ft], 0, l1);
6651 fp0 = tcg_temp_new_i32();
6652 gen_load_fpr32(fp0, fs);
6653 gen_store_fpr32(fp0, fd);
6654 tcg_temp_free_i32(fp0);
6655 gen_set_label(l1);
6658 opn = "movn.s";
6659 break;
6660 case OPC_RECIP_S:
6661 check_cop1x(ctx);
6663 TCGv_i32 fp0 = tcg_temp_new_i32();
6665 gen_load_fpr32(fp0, fs);
6666 gen_helper_float_recip_s(fp0, fp0);
6667 gen_store_fpr32(fp0, fd);
6668 tcg_temp_free_i32(fp0);
6670 opn = "recip.s";
6671 break;
6672 case OPC_RSQRT_S:
6673 check_cop1x(ctx);
6675 TCGv_i32 fp0 = tcg_temp_new_i32();
6677 gen_load_fpr32(fp0, fs);
6678 gen_helper_float_rsqrt_s(fp0, fp0);
6679 gen_store_fpr32(fp0, fd);
6680 tcg_temp_free_i32(fp0);
6682 opn = "rsqrt.s";
6683 break;
6684 case OPC_RECIP2_S:
6685 check_cp1_64bitmode(ctx);
6687 TCGv_i32 fp0 = tcg_temp_new_i32();
6688 TCGv_i32 fp1 = tcg_temp_new_i32();
6690 gen_load_fpr32(fp0, fs);
6691 gen_load_fpr32(fp1, fd);
6692 gen_helper_float_recip2_s(fp0, fp0, fp1);
6693 tcg_temp_free_i32(fp1);
6694 gen_store_fpr32(fp0, fd);
6695 tcg_temp_free_i32(fp0);
6697 opn = "recip2.s";
6698 break;
6699 case OPC_RECIP1_S:
6700 check_cp1_64bitmode(ctx);
6702 TCGv_i32 fp0 = tcg_temp_new_i32();
6704 gen_load_fpr32(fp0, fs);
6705 gen_helper_float_recip1_s(fp0, fp0);
6706 gen_store_fpr32(fp0, fd);
6707 tcg_temp_free_i32(fp0);
6709 opn = "recip1.s";
6710 break;
6711 case OPC_RSQRT1_S:
6712 check_cp1_64bitmode(ctx);
6714 TCGv_i32 fp0 = tcg_temp_new_i32();
6716 gen_load_fpr32(fp0, fs);
6717 gen_helper_float_rsqrt1_s(fp0, fp0);
6718 gen_store_fpr32(fp0, fd);
6719 tcg_temp_free_i32(fp0);
6721 opn = "rsqrt1.s";
6722 break;
6723 case OPC_RSQRT2_S:
6724 check_cp1_64bitmode(ctx);
6726 TCGv_i32 fp0 = tcg_temp_new_i32();
6727 TCGv_i32 fp1 = tcg_temp_new_i32();
6729 gen_load_fpr32(fp0, fs);
6730 gen_load_fpr32(fp1, ft);
6731 gen_helper_float_rsqrt2_s(fp0, fp0, fp1);
6732 tcg_temp_free_i32(fp1);
6733 gen_store_fpr32(fp0, fd);
6734 tcg_temp_free_i32(fp0);
6736 opn = "rsqrt2.s";
6737 break;
6738 case OPC_CVT_D_S:
6739 check_cp1_registers(ctx, fd);
6741 TCGv_i32 fp32 = tcg_temp_new_i32();
6742 TCGv_i64 fp64 = tcg_temp_new_i64();
6744 gen_load_fpr32(fp32, fs);
6745 gen_helper_float_cvtd_s(fp64, fp32);
6746 tcg_temp_free_i32(fp32);
6747 gen_store_fpr64(ctx, fp64, fd);
6748 tcg_temp_free_i64(fp64);
6750 opn = "cvt.d.s";
6751 break;
6752 case OPC_CVT_W_S:
6754 TCGv_i32 fp0 = tcg_temp_new_i32();
6756 gen_load_fpr32(fp0, fs);
6757 gen_helper_float_cvtw_s(fp0, fp0);
6758 gen_store_fpr32(fp0, fd);
6759 tcg_temp_free_i32(fp0);
6761 opn = "cvt.w.s";
6762 break;
6763 case OPC_CVT_L_S:
6764 check_cp1_64bitmode(ctx);
6766 TCGv_i32 fp32 = tcg_temp_new_i32();
6767 TCGv_i64 fp64 = tcg_temp_new_i64();
6769 gen_load_fpr32(fp32, fs);
6770 gen_helper_float_cvtl_s(fp64, fp32);
6771 tcg_temp_free_i32(fp32);
6772 gen_store_fpr64(ctx, fp64, fd);
6773 tcg_temp_free_i64(fp64);
6775 opn = "cvt.l.s";
6776 break;
6777 case OPC_CVT_PS_S:
6778 check_cp1_64bitmode(ctx);
6780 TCGv_i64 fp64 = tcg_temp_new_i64();
6781 TCGv_i32 fp32_0 = tcg_temp_new_i32();
6782 TCGv_i32 fp32_1 = tcg_temp_new_i32();
6784 gen_load_fpr32(fp32_0, fs);
6785 gen_load_fpr32(fp32_1, ft);
6786 tcg_gen_concat_i32_i64(fp64, fp32_0, fp32_1);
6787 tcg_temp_free_i32(fp32_1);
6788 tcg_temp_free_i32(fp32_0);
6789 gen_store_fpr64(ctx, fp64, fd);
6790 tcg_temp_free_i64(fp64);
6792 opn = "cvt.ps.s";
6793 break;
6794 case OPC_CMP_F_S:
6795 case OPC_CMP_UN_S:
6796 case OPC_CMP_EQ_S:
6797 case OPC_CMP_UEQ_S:
6798 case OPC_CMP_OLT_S:
6799 case OPC_CMP_ULT_S:
6800 case OPC_CMP_OLE_S:
6801 case OPC_CMP_ULE_S:
6802 case OPC_CMP_SF_S:
6803 case OPC_CMP_NGLE_S:
6804 case OPC_CMP_SEQ_S:
6805 case OPC_CMP_NGL_S:
6806 case OPC_CMP_LT_S:
6807 case OPC_CMP_NGE_S:
6808 case OPC_CMP_LE_S:
6809 case OPC_CMP_NGT_S:
6810 if (ctx->opcode & (1 << 6)) {
6811 gen_cmpabs_s(ctx, func-48, ft, fs, cc);
6812 opn = condnames_abs[func-48];
6813 } else {
6814 gen_cmp_s(ctx, func-48, ft, fs, cc);
6815 opn = condnames[func-48];
6817 break;
6818 case OPC_ADD_D:
6819 check_cp1_registers(ctx, fs | ft | fd);
6821 TCGv_i64 fp0 = tcg_temp_new_i64();
6822 TCGv_i64 fp1 = tcg_temp_new_i64();
6824 gen_load_fpr64(ctx, fp0, fs);
6825 gen_load_fpr64(ctx, fp1, ft);
6826 gen_helper_float_add_d(fp0, fp0, fp1);
6827 tcg_temp_free_i64(fp1);
6828 gen_store_fpr64(ctx, fp0, fd);
6829 tcg_temp_free_i64(fp0);
6831 opn = "add.d";
6832 optype = BINOP;
6833 break;
6834 case OPC_SUB_D:
6835 check_cp1_registers(ctx, fs | ft | fd);
6837 TCGv_i64 fp0 = tcg_temp_new_i64();
6838 TCGv_i64 fp1 = tcg_temp_new_i64();
6840 gen_load_fpr64(ctx, fp0, fs);
6841 gen_load_fpr64(ctx, fp1, ft);
6842 gen_helper_float_sub_d(fp0, fp0, fp1);
6843 tcg_temp_free_i64(fp1);
6844 gen_store_fpr64(ctx, fp0, fd);
6845 tcg_temp_free_i64(fp0);
6847 opn = "sub.d";
6848 optype = BINOP;
6849 break;
6850 case OPC_MUL_D:
6851 check_cp1_registers(ctx, fs | ft | fd);
6853 TCGv_i64 fp0 = tcg_temp_new_i64();
6854 TCGv_i64 fp1 = tcg_temp_new_i64();
6856 gen_load_fpr64(ctx, fp0, fs);
6857 gen_load_fpr64(ctx, fp1, ft);
6858 gen_helper_float_mul_d(fp0, fp0, fp1);
6859 tcg_temp_free_i64(fp1);
6860 gen_store_fpr64(ctx, fp0, fd);
6861 tcg_temp_free_i64(fp0);
6863 opn = "mul.d";
6864 optype = BINOP;
6865 break;
6866 case OPC_DIV_D:
6867 check_cp1_registers(ctx, fs | ft | fd);
6869 TCGv_i64 fp0 = tcg_temp_new_i64();
6870 TCGv_i64 fp1 = tcg_temp_new_i64();
6872 gen_load_fpr64(ctx, fp0, fs);
6873 gen_load_fpr64(ctx, fp1, ft);
6874 gen_helper_float_div_d(fp0, fp0, fp1);
6875 tcg_temp_free_i64(fp1);
6876 gen_store_fpr64(ctx, fp0, fd);
6877 tcg_temp_free_i64(fp0);
6879 opn = "div.d";
6880 optype = BINOP;
6881 break;
6882 case OPC_SQRT_D:
6883 check_cp1_registers(ctx, fs | fd);
6885 TCGv_i64 fp0 = tcg_temp_new_i64();
6887 gen_load_fpr64(ctx, fp0, fs);
6888 gen_helper_float_sqrt_d(fp0, fp0);
6889 gen_store_fpr64(ctx, fp0, fd);
6890 tcg_temp_free_i64(fp0);
6892 opn = "sqrt.d";
6893 break;
6894 case OPC_ABS_D:
6895 check_cp1_registers(ctx, fs | fd);
6897 TCGv_i64 fp0 = tcg_temp_new_i64();
6899 gen_load_fpr64(ctx, fp0, fs);
6900 gen_helper_float_abs_d(fp0, fp0);
6901 gen_store_fpr64(ctx, fp0, fd);
6902 tcg_temp_free_i64(fp0);
6904 opn = "abs.d";
6905 break;
6906 case OPC_MOV_D:
6907 check_cp1_registers(ctx, fs | fd);
6909 TCGv_i64 fp0 = tcg_temp_new_i64();
6911 gen_load_fpr64(ctx, fp0, fs);
6912 gen_store_fpr64(ctx, fp0, fd);
6913 tcg_temp_free_i64(fp0);
6915 opn = "mov.d";
6916 break;
6917 case OPC_NEG_D:
6918 check_cp1_registers(ctx, fs | fd);
6920 TCGv_i64 fp0 = tcg_temp_new_i64();
6922 gen_load_fpr64(ctx, fp0, fs);
6923 gen_helper_float_chs_d(fp0, fp0);
6924 gen_store_fpr64(ctx, fp0, fd);
6925 tcg_temp_free_i64(fp0);
6927 opn = "neg.d";
6928 break;
6929 case OPC_ROUND_L_D:
6930 check_cp1_64bitmode(ctx);
6932 TCGv_i64 fp0 = tcg_temp_new_i64();
6934 gen_load_fpr64(ctx, fp0, fs);
6935 gen_helper_float_roundl_d(fp0, fp0);
6936 gen_store_fpr64(ctx, fp0, fd);
6937 tcg_temp_free_i64(fp0);
6939 opn = "round.l.d";
6940 break;
6941 case OPC_TRUNC_L_D:
6942 check_cp1_64bitmode(ctx);
6944 TCGv_i64 fp0 = tcg_temp_new_i64();
6946 gen_load_fpr64(ctx, fp0, fs);
6947 gen_helper_float_truncl_d(fp0, fp0);
6948 gen_store_fpr64(ctx, fp0, fd);
6949 tcg_temp_free_i64(fp0);
6951 opn = "trunc.l.d";
6952 break;
6953 case OPC_CEIL_L_D:
6954 check_cp1_64bitmode(ctx);
6956 TCGv_i64 fp0 = tcg_temp_new_i64();
6958 gen_load_fpr64(ctx, fp0, fs);
6959 gen_helper_float_ceill_d(fp0, fp0);
6960 gen_store_fpr64(ctx, fp0, fd);
6961 tcg_temp_free_i64(fp0);
6963 opn = "ceil.l.d";
6964 break;
6965 case OPC_FLOOR_L_D:
6966 check_cp1_64bitmode(ctx);
6968 TCGv_i64 fp0 = tcg_temp_new_i64();
6970 gen_load_fpr64(ctx, fp0, fs);
6971 gen_helper_float_floorl_d(fp0, fp0);
6972 gen_store_fpr64(ctx, fp0, fd);
6973 tcg_temp_free_i64(fp0);
6975 opn = "floor.l.d";
6976 break;
6977 case OPC_ROUND_W_D:
6978 check_cp1_registers(ctx, fs);
6980 TCGv_i32 fp32 = tcg_temp_new_i32();
6981 TCGv_i64 fp64 = tcg_temp_new_i64();
6983 gen_load_fpr64(ctx, fp64, fs);
6984 gen_helper_float_roundw_d(fp32, fp64);
6985 tcg_temp_free_i64(fp64);
6986 gen_store_fpr32(fp32, fd);
6987 tcg_temp_free_i32(fp32);
6989 opn = "round.w.d";
6990 break;
6991 case OPC_TRUNC_W_D:
6992 check_cp1_registers(ctx, fs);
6994 TCGv_i32 fp32 = tcg_temp_new_i32();
6995 TCGv_i64 fp64 = tcg_temp_new_i64();
6997 gen_load_fpr64(ctx, fp64, fs);
6998 gen_helper_float_truncw_d(fp32, fp64);
6999 tcg_temp_free_i64(fp64);
7000 gen_store_fpr32(fp32, fd);
7001 tcg_temp_free_i32(fp32);
7003 opn = "trunc.w.d";
7004 break;
7005 case OPC_CEIL_W_D:
7006 check_cp1_registers(ctx, fs);
7008 TCGv_i32 fp32 = tcg_temp_new_i32();
7009 TCGv_i64 fp64 = tcg_temp_new_i64();
7011 gen_load_fpr64(ctx, fp64, fs);
7012 gen_helper_float_ceilw_d(fp32, fp64);
7013 tcg_temp_free_i64(fp64);
7014 gen_store_fpr32(fp32, fd);
7015 tcg_temp_free_i32(fp32);
7017 opn = "ceil.w.d";
7018 break;
7019 case OPC_FLOOR_W_D:
7020 check_cp1_registers(ctx, fs);
7022 TCGv_i32 fp32 = tcg_temp_new_i32();
7023 TCGv_i64 fp64 = tcg_temp_new_i64();
7025 gen_load_fpr64(ctx, fp64, fs);
7026 gen_helper_float_floorw_d(fp32, fp64);
7027 tcg_temp_free_i64(fp64);
7028 gen_store_fpr32(fp32, fd);
7029 tcg_temp_free_i32(fp32);
7031 opn = "floor.w.d";
7032 break;
7033 case OPC_MOVCF_D:
7034 gen_movcf_d(ctx, fs, fd, (ft >> 2) & 0x7, ft & 0x1);
7035 opn = "movcf.d";
7036 break;
7037 case OPC_MOVZ_D:
7039 int l1 = gen_new_label();
7040 TCGv_i64 fp0;
7042 if (ft != 0) {
7043 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[ft], 0, l1);
7045 fp0 = tcg_temp_new_i64();
7046 gen_load_fpr64(ctx, fp0, fs);
7047 gen_store_fpr64(ctx, fp0, fd);
7048 tcg_temp_free_i64(fp0);
7049 gen_set_label(l1);
7051 opn = "movz.d";
7052 break;
7053 case OPC_MOVN_D:
7055 int l1 = gen_new_label();
7056 TCGv_i64 fp0;
7058 if (ft != 0) {
7059 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[ft], 0, l1);
7060 fp0 = tcg_temp_new_i64();
7061 gen_load_fpr64(ctx, fp0, fs);
7062 gen_store_fpr64(ctx, fp0, fd);
7063 tcg_temp_free_i64(fp0);
7064 gen_set_label(l1);
7067 opn = "movn.d";
7068 break;
7069 case OPC_RECIP_D:
7070 check_cp1_64bitmode(ctx);
7072 TCGv_i64 fp0 = tcg_temp_new_i64();
7074 gen_load_fpr64(ctx, fp0, fs);
7075 gen_helper_float_recip_d(fp0, fp0);
7076 gen_store_fpr64(ctx, fp0, fd);
7077 tcg_temp_free_i64(fp0);
7079 opn = "recip.d";
7080 break;
7081 case OPC_RSQRT_D:
7082 check_cp1_64bitmode(ctx);
7084 TCGv_i64 fp0 = tcg_temp_new_i64();
7086 gen_load_fpr64(ctx, fp0, fs);
7087 gen_helper_float_rsqrt_d(fp0, fp0);
7088 gen_store_fpr64(ctx, fp0, fd);
7089 tcg_temp_free_i64(fp0);
7091 opn = "rsqrt.d";
7092 break;
7093 case OPC_RECIP2_D:
7094 check_cp1_64bitmode(ctx);
7096 TCGv_i64 fp0 = tcg_temp_new_i64();
7097 TCGv_i64 fp1 = tcg_temp_new_i64();
7099 gen_load_fpr64(ctx, fp0, fs);
7100 gen_load_fpr64(ctx, fp1, ft);
7101 gen_helper_float_recip2_d(fp0, fp0, fp1);
7102 tcg_temp_free_i64(fp1);
7103 gen_store_fpr64(ctx, fp0, fd);
7104 tcg_temp_free_i64(fp0);
7106 opn = "recip2.d";
7107 break;
7108 case OPC_RECIP1_D:
7109 check_cp1_64bitmode(ctx);
7111 TCGv_i64 fp0 = tcg_temp_new_i64();
7113 gen_load_fpr64(ctx, fp0, fs);
7114 gen_helper_float_recip1_d(fp0, fp0);
7115 gen_store_fpr64(ctx, fp0, fd);
7116 tcg_temp_free_i64(fp0);
7118 opn = "recip1.d";
7119 break;
7120 case OPC_RSQRT1_D:
7121 check_cp1_64bitmode(ctx);
7123 TCGv_i64 fp0 = tcg_temp_new_i64();
7125 gen_load_fpr64(ctx, fp0, fs);
7126 gen_helper_float_rsqrt1_d(fp0, fp0);
7127 gen_store_fpr64(ctx, fp0, fd);
7128 tcg_temp_free_i64(fp0);
7130 opn = "rsqrt1.d";
7131 break;
7132 case OPC_RSQRT2_D:
7133 check_cp1_64bitmode(ctx);
7135 TCGv_i64 fp0 = tcg_temp_new_i64();
7136 TCGv_i64 fp1 = tcg_temp_new_i64();
7138 gen_load_fpr64(ctx, fp0, fs);
7139 gen_load_fpr64(ctx, fp1, ft);
7140 gen_helper_float_rsqrt2_d(fp0, fp0, fp1);
7141 tcg_temp_free_i64(fp1);
7142 gen_store_fpr64(ctx, fp0, fd);
7143 tcg_temp_free_i64(fp0);
7145 opn = "rsqrt2.d";
7146 break;
7147 case OPC_CMP_F_D:
7148 case OPC_CMP_UN_D:
7149 case OPC_CMP_EQ_D:
7150 case OPC_CMP_UEQ_D:
7151 case OPC_CMP_OLT_D:
7152 case OPC_CMP_ULT_D:
7153 case OPC_CMP_OLE_D:
7154 case OPC_CMP_ULE_D:
7155 case OPC_CMP_SF_D:
7156 case OPC_CMP_NGLE_D:
7157 case OPC_CMP_SEQ_D:
7158 case OPC_CMP_NGL_D:
7159 case OPC_CMP_LT_D:
7160 case OPC_CMP_NGE_D:
7161 case OPC_CMP_LE_D:
7162 case OPC_CMP_NGT_D:
7163 if (ctx->opcode & (1 << 6)) {
7164 gen_cmpabs_d(ctx, func-48, ft, fs, cc);
7165 opn = condnames_abs[func-48];
7166 } else {
7167 gen_cmp_d(ctx, func-48, ft, fs, cc);
7168 opn = condnames[func-48];
7170 break;
7171 case OPC_CVT_S_D:
7172 check_cp1_registers(ctx, fs);
7174 TCGv_i32 fp32 = tcg_temp_new_i32();
7175 TCGv_i64 fp64 = tcg_temp_new_i64();
7177 gen_load_fpr64(ctx, fp64, fs);
7178 gen_helper_float_cvts_d(fp32, fp64);
7179 tcg_temp_free_i64(fp64);
7180 gen_store_fpr32(fp32, fd);
7181 tcg_temp_free_i32(fp32);
7183 opn = "cvt.s.d";
7184 break;
7185 case OPC_CVT_W_D:
7186 check_cp1_registers(ctx, fs);
7188 TCGv_i32 fp32 = tcg_temp_new_i32();
7189 TCGv_i64 fp64 = tcg_temp_new_i64();
7191 gen_load_fpr64(ctx, fp64, fs);
7192 gen_helper_float_cvtw_d(fp32, fp64);
7193 tcg_temp_free_i64(fp64);
7194 gen_store_fpr32(fp32, fd);
7195 tcg_temp_free_i32(fp32);
7197 opn = "cvt.w.d";
7198 break;
7199 case OPC_CVT_L_D:
7200 check_cp1_64bitmode(ctx);
7202 TCGv_i64 fp0 = tcg_temp_new_i64();
7204 gen_load_fpr64(ctx, fp0, fs);
7205 gen_helper_float_cvtl_d(fp0, fp0);
7206 gen_store_fpr64(ctx, fp0, fd);
7207 tcg_temp_free_i64(fp0);
7209 opn = "cvt.l.d";
7210 break;
7211 case OPC_CVT_S_W:
7213 TCGv_i32 fp0 = tcg_temp_new_i32();
7215 gen_load_fpr32(fp0, fs);
7216 gen_helper_float_cvts_w(fp0, fp0);
7217 gen_store_fpr32(fp0, fd);
7218 tcg_temp_free_i32(fp0);
7220 opn = "cvt.s.w";
7221 break;
7222 case OPC_CVT_D_W:
7223 check_cp1_registers(ctx, fd);
7225 TCGv_i32 fp32 = tcg_temp_new_i32();
7226 TCGv_i64 fp64 = tcg_temp_new_i64();
7228 gen_load_fpr32(fp32, fs);
7229 gen_helper_float_cvtd_w(fp64, fp32);
7230 tcg_temp_free_i32(fp32);
7231 gen_store_fpr64(ctx, fp64, fd);
7232 tcg_temp_free_i64(fp64);
7234 opn = "cvt.d.w";
7235 break;
7236 case OPC_CVT_S_L:
7237 check_cp1_64bitmode(ctx);
7239 TCGv_i32 fp32 = tcg_temp_new_i32();
7240 TCGv_i64 fp64 = tcg_temp_new_i64();
7242 gen_load_fpr64(ctx, fp64, fs);
7243 gen_helper_float_cvts_l(fp32, fp64);
7244 tcg_temp_free_i64(fp64);
7245 gen_store_fpr32(fp32, fd);
7246 tcg_temp_free_i32(fp32);
7248 opn = "cvt.s.l";
7249 break;
7250 case OPC_CVT_D_L:
7251 check_cp1_64bitmode(ctx);
7253 TCGv_i64 fp0 = tcg_temp_new_i64();
7255 gen_load_fpr64(ctx, fp0, fs);
7256 gen_helper_float_cvtd_l(fp0, fp0);
7257 gen_store_fpr64(ctx, fp0, fd);
7258 tcg_temp_free_i64(fp0);
7260 opn = "cvt.d.l";
7261 break;
7262 case OPC_CVT_PS_PW:
7263 check_cp1_64bitmode(ctx);
7265 TCGv_i64 fp0 = tcg_temp_new_i64();
7267 gen_load_fpr64(ctx, fp0, fs);
7268 gen_helper_float_cvtps_pw(fp0, fp0);
7269 gen_store_fpr64(ctx, fp0, fd);
7270 tcg_temp_free_i64(fp0);
7272 opn = "cvt.ps.pw";
7273 break;
7274 case OPC_ADD_PS:
7275 check_cp1_64bitmode(ctx);
7277 TCGv_i64 fp0 = tcg_temp_new_i64();
7278 TCGv_i64 fp1 = tcg_temp_new_i64();
7280 gen_load_fpr64(ctx, fp0, fs);
7281 gen_load_fpr64(ctx, fp1, ft);
7282 gen_helper_float_add_ps(fp0, fp0, fp1);
7283 tcg_temp_free_i64(fp1);
7284 gen_store_fpr64(ctx, fp0, fd);
7285 tcg_temp_free_i64(fp0);
7287 opn = "add.ps";
7288 break;
7289 case OPC_SUB_PS:
7290 check_cp1_64bitmode(ctx);
7292 TCGv_i64 fp0 = tcg_temp_new_i64();
7293 TCGv_i64 fp1 = tcg_temp_new_i64();
7295 gen_load_fpr64(ctx, fp0, fs);
7296 gen_load_fpr64(ctx, fp1, ft);
7297 gen_helper_float_sub_ps(fp0, fp0, fp1);
7298 tcg_temp_free_i64(fp1);
7299 gen_store_fpr64(ctx, fp0, fd);
7300 tcg_temp_free_i64(fp0);
7302 opn = "sub.ps";
7303 break;
7304 case OPC_MUL_PS:
7305 check_cp1_64bitmode(ctx);
7307 TCGv_i64 fp0 = tcg_temp_new_i64();
7308 TCGv_i64 fp1 = tcg_temp_new_i64();
7310 gen_load_fpr64(ctx, fp0, fs);
7311 gen_load_fpr64(ctx, fp1, ft);
7312 gen_helper_float_mul_ps(fp0, fp0, fp1);
7313 tcg_temp_free_i64(fp1);
7314 gen_store_fpr64(ctx, fp0, fd);
7315 tcg_temp_free_i64(fp0);
7317 opn = "mul.ps";
7318 break;
7319 case OPC_ABS_PS:
7320 check_cp1_64bitmode(ctx);
7322 TCGv_i64 fp0 = tcg_temp_new_i64();
7324 gen_load_fpr64(ctx, fp0, fs);
7325 gen_helper_float_abs_ps(fp0, fp0);
7326 gen_store_fpr64(ctx, fp0, fd);
7327 tcg_temp_free_i64(fp0);
7329 opn = "abs.ps";
7330 break;
7331 case OPC_MOV_PS:
7332 check_cp1_64bitmode(ctx);
7334 TCGv_i64 fp0 = tcg_temp_new_i64();
7336 gen_load_fpr64(ctx, fp0, fs);
7337 gen_store_fpr64(ctx, fp0, fd);
7338 tcg_temp_free_i64(fp0);
7340 opn = "mov.ps";
7341 break;
7342 case OPC_NEG_PS:
7343 check_cp1_64bitmode(ctx);
7345 TCGv_i64 fp0 = tcg_temp_new_i64();
7347 gen_load_fpr64(ctx, fp0, fs);
7348 gen_helper_float_chs_ps(fp0, fp0);
7349 gen_store_fpr64(ctx, fp0, fd);
7350 tcg_temp_free_i64(fp0);
7352 opn = "neg.ps";
7353 break;
7354 case OPC_MOVCF_PS:
7355 check_cp1_64bitmode(ctx);
7356 gen_movcf_ps(fs, fd, (ft >> 2) & 0x7, ft & 0x1);
7357 opn = "movcf.ps";
7358 break;
7359 case OPC_MOVZ_PS:
7360 check_cp1_64bitmode(ctx);
7362 int l1 = gen_new_label();
7363 TCGv_i64 fp0;
7365 if (ft != 0)
7366 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[ft], 0, l1);
7367 fp0 = tcg_temp_new_i64();
7368 gen_load_fpr64(ctx, fp0, fs);
7369 gen_store_fpr64(ctx, fp0, fd);
7370 tcg_temp_free_i64(fp0);
7371 gen_set_label(l1);
7373 opn = "movz.ps";
7374 break;
7375 case OPC_MOVN_PS:
7376 check_cp1_64bitmode(ctx);
7378 int l1 = gen_new_label();
7379 TCGv_i64 fp0;
7381 if (ft != 0) {
7382 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[ft], 0, l1);
7383 fp0 = tcg_temp_new_i64();
7384 gen_load_fpr64(ctx, fp0, fs);
7385 gen_store_fpr64(ctx, fp0, fd);
7386 tcg_temp_free_i64(fp0);
7387 gen_set_label(l1);
7390 opn = "movn.ps";
7391 break;
7392 case OPC_ADDR_PS:
7393 check_cp1_64bitmode(ctx);
7395 TCGv_i64 fp0 = tcg_temp_new_i64();
7396 TCGv_i64 fp1 = tcg_temp_new_i64();
7398 gen_load_fpr64(ctx, fp0, ft);
7399 gen_load_fpr64(ctx, fp1, fs);
7400 gen_helper_float_addr_ps(fp0, fp0, fp1);
7401 tcg_temp_free_i64(fp1);
7402 gen_store_fpr64(ctx, fp0, fd);
7403 tcg_temp_free_i64(fp0);
7405 opn = "addr.ps";
7406 break;
7407 case OPC_MULR_PS:
7408 check_cp1_64bitmode(ctx);
7410 TCGv_i64 fp0 = tcg_temp_new_i64();
7411 TCGv_i64 fp1 = tcg_temp_new_i64();
7413 gen_load_fpr64(ctx, fp0, ft);
7414 gen_load_fpr64(ctx, fp1, fs);
7415 gen_helper_float_mulr_ps(fp0, fp0, fp1);
7416 tcg_temp_free_i64(fp1);
7417 gen_store_fpr64(ctx, fp0, fd);
7418 tcg_temp_free_i64(fp0);
7420 opn = "mulr.ps";
7421 break;
7422 case OPC_RECIP2_PS:
7423 check_cp1_64bitmode(ctx);
7425 TCGv_i64 fp0 = tcg_temp_new_i64();
7426 TCGv_i64 fp1 = tcg_temp_new_i64();
7428 gen_load_fpr64(ctx, fp0, fs);
7429 gen_load_fpr64(ctx, fp1, fd);
7430 gen_helper_float_recip2_ps(fp0, fp0, fp1);
7431 tcg_temp_free_i64(fp1);
7432 gen_store_fpr64(ctx, fp0, fd);
7433 tcg_temp_free_i64(fp0);
7435 opn = "recip2.ps";
7436 break;
7437 case OPC_RECIP1_PS:
7438 check_cp1_64bitmode(ctx);
7440 TCGv_i64 fp0 = tcg_temp_new_i64();
7442 gen_load_fpr64(ctx, fp0, fs);
7443 gen_helper_float_recip1_ps(fp0, fp0);
7444 gen_store_fpr64(ctx, fp0, fd);
7445 tcg_temp_free_i64(fp0);
7447 opn = "recip1.ps";
7448 break;
7449 case OPC_RSQRT1_PS:
7450 check_cp1_64bitmode(ctx);
7452 TCGv_i64 fp0 = tcg_temp_new_i64();
7454 gen_load_fpr64(ctx, fp0, fs);
7455 gen_helper_float_rsqrt1_ps(fp0, fp0);
7456 gen_store_fpr64(ctx, fp0, fd);
7457 tcg_temp_free_i64(fp0);
7459 opn = "rsqrt1.ps";
7460 break;
7461 case OPC_RSQRT2_PS:
7462 check_cp1_64bitmode(ctx);
7464 TCGv_i64 fp0 = tcg_temp_new_i64();
7465 TCGv_i64 fp1 = tcg_temp_new_i64();
7467 gen_load_fpr64(ctx, fp0, fs);
7468 gen_load_fpr64(ctx, fp1, ft);
7469 gen_helper_float_rsqrt2_ps(fp0, fp0, fp1);
7470 tcg_temp_free_i64(fp1);
7471 gen_store_fpr64(ctx, fp0, fd);
7472 tcg_temp_free_i64(fp0);
7474 opn = "rsqrt2.ps";
7475 break;
7476 case OPC_CVT_S_PU:
7477 check_cp1_64bitmode(ctx);
7479 TCGv_i32 fp0 = tcg_temp_new_i32();
7481 gen_load_fpr32h(fp0, fs);
7482 gen_helper_float_cvts_pu(fp0, fp0);
7483 gen_store_fpr32(fp0, fd);
7484 tcg_temp_free_i32(fp0);
7486 opn = "cvt.s.pu";
7487 break;
7488 case OPC_CVT_PW_PS:
7489 check_cp1_64bitmode(ctx);
7491 TCGv_i64 fp0 = tcg_temp_new_i64();
7493 gen_load_fpr64(ctx, fp0, fs);
7494 gen_helper_float_cvtpw_ps(fp0, fp0);
7495 gen_store_fpr64(ctx, fp0, fd);
7496 tcg_temp_free_i64(fp0);
7498 opn = "cvt.pw.ps";
7499 break;
7500 case OPC_CVT_S_PL:
7501 check_cp1_64bitmode(ctx);
7503 TCGv_i32 fp0 = tcg_temp_new_i32();
7505 gen_load_fpr32(fp0, fs);
7506 gen_helper_float_cvts_pl(fp0, fp0);
7507 gen_store_fpr32(fp0, fd);
7508 tcg_temp_free_i32(fp0);
7510 opn = "cvt.s.pl";
7511 break;
7512 case OPC_PLL_PS:
7513 check_cp1_64bitmode(ctx);
7515 TCGv_i32 fp0 = tcg_temp_new_i32();
7516 TCGv_i32 fp1 = tcg_temp_new_i32();
7518 gen_load_fpr32(fp0, fs);
7519 gen_load_fpr32(fp1, ft);
7520 gen_store_fpr32h(fp0, fd);
7521 gen_store_fpr32(fp1, fd);
7522 tcg_temp_free_i32(fp0);
7523 tcg_temp_free_i32(fp1);
7525 opn = "pll.ps";
7526 break;
7527 case OPC_PLU_PS:
7528 check_cp1_64bitmode(ctx);
7530 TCGv_i32 fp0 = tcg_temp_new_i32();
7531 TCGv_i32 fp1 = tcg_temp_new_i32();
7533 gen_load_fpr32(fp0, fs);
7534 gen_load_fpr32h(fp1, ft);
7535 gen_store_fpr32(fp1, fd);
7536 gen_store_fpr32h(fp0, fd);
7537 tcg_temp_free_i32(fp0);
7538 tcg_temp_free_i32(fp1);
7540 opn = "plu.ps";
7541 break;
7542 case OPC_PUL_PS:
7543 check_cp1_64bitmode(ctx);
7545 TCGv_i32 fp0 = tcg_temp_new_i32();
7546 TCGv_i32 fp1 = tcg_temp_new_i32();
7548 gen_load_fpr32h(fp0, fs);
7549 gen_load_fpr32(fp1, ft);
7550 gen_store_fpr32(fp1, fd);
7551 gen_store_fpr32h(fp0, fd);
7552 tcg_temp_free_i32(fp0);
7553 tcg_temp_free_i32(fp1);
7555 opn = "pul.ps";
7556 break;
7557 case OPC_PUU_PS:
7558 check_cp1_64bitmode(ctx);
7560 TCGv_i32 fp0 = tcg_temp_new_i32();
7561 TCGv_i32 fp1 = tcg_temp_new_i32();
7563 gen_load_fpr32h(fp0, fs);
7564 gen_load_fpr32h(fp1, ft);
7565 gen_store_fpr32(fp1, fd);
7566 gen_store_fpr32h(fp0, fd);
7567 tcg_temp_free_i32(fp0);
7568 tcg_temp_free_i32(fp1);
7570 opn = "puu.ps";
7571 break;
7572 case OPC_CMP_F_PS:
7573 case OPC_CMP_UN_PS:
7574 case OPC_CMP_EQ_PS:
7575 case OPC_CMP_UEQ_PS:
7576 case OPC_CMP_OLT_PS:
7577 case OPC_CMP_ULT_PS:
7578 case OPC_CMP_OLE_PS:
7579 case OPC_CMP_ULE_PS:
7580 case OPC_CMP_SF_PS:
7581 case OPC_CMP_NGLE_PS:
7582 case OPC_CMP_SEQ_PS:
7583 case OPC_CMP_NGL_PS:
7584 case OPC_CMP_LT_PS:
7585 case OPC_CMP_NGE_PS:
7586 case OPC_CMP_LE_PS:
7587 case OPC_CMP_NGT_PS:
7588 if (ctx->opcode & (1 << 6)) {
7589 gen_cmpabs_ps(ctx, func-48, ft, fs, cc);
7590 opn = condnames_abs[func-48];
7591 } else {
7592 gen_cmp_ps(ctx, func-48, ft, fs, cc);
7593 opn = condnames[func-48];
7595 break;
7596 default:
7597 MIPS_INVAL(opn);
7598 generate_exception (ctx, EXCP_RI);
7599 return;
7601 switch (optype) {
7602 case BINOP:
7603 MIPS_DEBUG("%s %s, %s, %s", opn, fregnames[fd], fregnames[fs], fregnames[ft]);
7604 break;
7605 case CMPOP:
7606 MIPS_DEBUG("%s %s,%s", opn, fregnames[fs], fregnames[ft]);
7607 break;
7608 default:
7609 MIPS_DEBUG("%s %s,%s", opn, fregnames[fd], fregnames[fs]);
7610 break;
7614 /* Coprocessor 3 (FPU) */
7615 static void gen_flt3_ldst (DisasContext *ctx, uint32_t opc,
7616 int fd, int fs, int base, int index)
7618 const char *opn = "extended float load/store";
7619 int store = 0;
7620 TCGv t0 = tcg_temp_new();
7622 if (base == 0) {
7623 gen_load_gpr(t0, index);
7624 } else if (index == 0) {
7625 gen_load_gpr(t0, base);
7626 } else {
7627 gen_load_gpr(t0, index);
7628 gen_op_addr_add(ctx, t0, cpu_gpr[base], t0);
7630 /* Don't do NOP if destination is zero: we must perform the actual
7631 memory access. */
7632 save_cpu_state(ctx, 0);
7633 switch (opc) {
7634 case OPC_LWXC1:
7635 check_cop1x(ctx);
7637 TCGv_i32 fp0 = tcg_temp_new_i32();
7639 tcg_gen_qemu_ld32s(t0, t0, ctx->mem_idx);
7640 tcg_gen_trunc_tl_i32(fp0, t0);
7641 gen_store_fpr32(fp0, fd);
7642 tcg_temp_free_i32(fp0);
7644 opn = "lwxc1";
7645 break;
7646 case OPC_LDXC1:
7647 check_cop1x(ctx);
7648 check_cp1_registers(ctx, fd);
7650 TCGv_i64 fp0 = tcg_temp_new_i64();
7652 tcg_gen_qemu_ld64(fp0, t0, ctx->mem_idx);
7653 gen_store_fpr64(ctx, fp0, fd);
7654 tcg_temp_free_i64(fp0);
7656 opn = "ldxc1";
7657 break;
7658 case OPC_LUXC1:
7659 check_cp1_64bitmode(ctx);
7660 tcg_gen_andi_tl(t0, t0, ~0x7);
7662 TCGv_i64 fp0 = tcg_temp_new_i64();
7664 tcg_gen_qemu_ld64(fp0, t0, ctx->mem_idx);
7665 gen_store_fpr64(ctx, fp0, fd);
7666 tcg_temp_free_i64(fp0);
7668 opn = "luxc1";
7669 break;
7670 case OPC_SWXC1:
7671 check_cop1x(ctx);
7673 TCGv_i32 fp0 = tcg_temp_new_i32();
7674 TCGv t1 = tcg_temp_new();
7676 gen_load_fpr32(fp0, fs);
7677 tcg_gen_extu_i32_tl(t1, fp0);
7678 tcg_gen_qemu_st32(t1, t0, ctx->mem_idx);
7679 tcg_temp_free_i32(fp0);
7680 tcg_temp_free(t1);
7682 opn = "swxc1";
7683 store = 1;
7684 break;
7685 case OPC_SDXC1:
7686 check_cop1x(ctx);
7687 check_cp1_registers(ctx, fs);
7689 TCGv_i64 fp0 = tcg_temp_new_i64();
7691 gen_load_fpr64(ctx, fp0, fs);
7692 tcg_gen_qemu_st64(fp0, t0, ctx->mem_idx);
7693 tcg_temp_free_i64(fp0);
7695 opn = "sdxc1";
7696 store = 1;
7697 break;
7698 case OPC_SUXC1:
7699 check_cp1_64bitmode(ctx);
7700 tcg_gen_andi_tl(t0, t0, ~0x7);
7702 TCGv_i64 fp0 = tcg_temp_new_i64();
7704 gen_load_fpr64(ctx, fp0, fs);
7705 tcg_gen_qemu_st64(fp0, t0, ctx->mem_idx);
7706 tcg_temp_free_i64(fp0);
7708 opn = "suxc1";
7709 store = 1;
7710 break;
7712 tcg_temp_free(t0);
7713 MIPS_DEBUG("%s %s, %s(%s)", opn, fregnames[store ? fs : fd],
7714 regnames[index], regnames[base]);
7717 static void gen_flt3_arith (DisasContext *ctx, uint32_t opc,
7718 int fd, int fr, int fs, int ft)
7720 const char *opn = "flt3_arith";
7722 switch (opc) {
7723 case OPC_ALNV_PS:
7724 check_cp1_64bitmode(ctx);
7726 TCGv t0 = tcg_temp_local_new();
7727 TCGv_i32 fp = tcg_temp_new_i32();
7728 TCGv_i32 fph = tcg_temp_new_i32();
7729 int l1 = gen_new_label();
7730 int l2 = gen_new_label();
7732 gen_load_gpr(t0, fr);
7733 tcg_gen_andi_tl(t0, t0, 0x7);
7735 tcg_gen_brcondi_tl(TCG_COND_NE, t0, 0, l1);
7736 gen_load_fpr32(fp, fs);
7737 gen_load_fpr32h(fph, fs);
7738 gen_store_fpr32(fp, fd);
7739 gen_store_fpr32h(fph, fd);
7740 tcg_gen_br(l2);
7741 gen_set_label(l1);
7742 tcg_gen_brcondi_tl(TCG_COND_NE, t0, 4, l2);
7743 tcg_temp_free(t0);
7744 #ifdef TARGET_WORDS_BIGENDIAN
7745 gen_load_fpr32(fp, fs);
7746 gen_load_fpr32h(fph, ft);
7747 gen_store_fpr32h(fp, fd);
7748 gen_store_fpr32(fph, fd);
7749 #else
7750 gen_load_fpr32h(fph, fs);
7751 gen_load_fpr32(fp, ft);
7752 gen_store_fpr32(fph, fd);
7753 gen_store_fpr32h(fp, fd);
7754 #endif
7755 gen_set_label(l2);
7756 tcg_temp_free_i32(fp);
7757 tcg_temp_free_i32(fph);
7759 opn = "alnv.ps";
7760 break;
7761 case OPC_MADD_S:
7762 check_cop1x(ctx);
7764 TCGv_i32 fp0 = tcg_temp_new_i32();
7765 TCGv_i32 fp1 = tcg_temp_new_i32();
7766 TCGv_i32 fp2 = tcg_temp_new_i32();
7768 gen_load_fpr32(fp0, fs);
7769 gen_load_fpr32(fp1, ft);
7770 gen_load_fpr32(fp2, fr);
7771 gen_helper_float_muladd_s(fp2, fp0, fp1, fp2);
7772 tcg_temp_free_i32(fp0);
7773 tcg_temp_free_i32(fp1);
7774 gen_store_fpr32(fp2, fd);
7775 tcg_temp_free_i32(fp2);
7777 opn = "madd.s";
7778 break;
7779 case OPC_MADD_D:
7780 check_cop1x(ctx);
7781 check_cp1_registers(ctx, fd | fs | ft | fr);
7783 TCGv_i64 fp0 = tcg_temp_new_i64();
7784 TCGv_i64 fp1 = tcg_temp_new_i64();
7785 TCGv_i64 fp2 = tcg_temp_new_i64();
7787 gen_load_fpr64(ctx, fp0, fs);
7788 gen_load_fpr64(ctx, fp1, ft);
7789 gen_load_fpr64(ctx, fp2, fr);
7790 gen_helper_float_muladd_d(fp2, fp0, fp1, fp2);
7791 tcg_temp_free_i64(fp0);
7792 tcg_temp_free_i64(fp1);
7793 gen_store_fpr64(ctx, fp2, fd);
7794 tcg_temp_free_i64(fp2);
7796 opn = "madd.d";
7797 break;
7798 case OPC_MADD_PS:
7799 check_cp1_64bitmode(ctx);
7801 TCGv_i64 fp0 = tcg_temp_new_i64();
7802 TCGv_i64 fp1 = tcg_temp_new_i64();
7803 TCGv_i64 fp2 = tcg_temp_new_i64();
7805 gen_load_fpr64(ctx, fp0, fs);
7806 gen_load_fpr64(ctx, fp1, ft);
7807 gen_load_fpr64(ctx, fp2, fr);
7808 gen_helper_float_muladd_ps(fp2, fp0, fp1, fp2);
7809 tcg_temp_free_i64(fp0);
7810 tcg_temp_free_i64(fp1);
7811 gen_store_fpr64(ctx, fp2, fd);
7812 tcg_temp_free_i64(fp2);
7814 opn = "madd.ps";
7815 break;
7816 case OPC_MSUB_S:
7817 check_cop1x(ctx);
7819 TCGv_i32 fp0 = tcg_temp_new_i32();
7820 TCGv_i32 fp1 = tcg_temp_new_i32();
7821 TCGv_i32 fp2 = tcg_temp_new_i32();
7823 gen_load_fpr32(fp0, fs);
7824 gen_load_fpr32(fp1, ft);
7825 gen_load_fpr32(fp2, fr);
7826 gen_helper_float_mulsub_s(fp2, fp0, fp1, fp2);
7827 tcg_temp_free_i32(fp0);
7828 tcg_temp_free_i32(fp1);
7829 gen_store_fpr32(fp2, fd);
7830 tcg_temp_free_i32(fp2);
7832 opn = "msub.s";
7833 break;
7834 case OPC_MSUB_D:
7835 check_cop1x(ctx);
7836 check_cp1_registers(ctx, fd | fs | ft | fr);
7838 TCGv_i64 fp0 = tcg_temp_new_i64();
7839 TCGv_i64 fp1 = tcg_temp_new_i64();
7840 TCGv_i64 fp2 = tcg_temp_new_i64();
7842 gen_load_fpr64(ctx, fp0, fs);
7843 gen_load_fpr64(ctx, fp1, ft);
7844 gen_load_fpr64(ctx, fp2, fr);
7845 gen_helper_float_mulsub_d(fp2, fp0, fp1, fp2);
7846 tcg_temp_free_i64(fp0);
7847 tcg_temp_free_i64(fp1);
7848 gen_store_fpr64(ctx, fp2, fd);
7849 tcg_temp_free_i64(fp2);
7851 opn = "msub.d";
7852 break;
7853 case OPC_MSUB_PS:
7854 check_cp1_64bitmode(ctx);
7856 TCGv_i64 fp0 = tcg_temp_new_i64();
7857 TCGv_i64 fp1 = tcg_temp_new_i64();
7858 TCGv_i64 fp2 = tcg_temp_new_i64();
7860 gen_load_fpr64(ctx, fp0, fs);
7861 gen_load_fpr64(ctx, fp1, ft);
7862 gen_load_fpr64(ctx, fp2, fr);
7863 gen_helper_float_mulsub_ps(fp2, fp0, fp1, fp2);
7864 tcg_temp_free_i64(fp0);
7865 tcg_temp_free_i64(fp1);
7866 gen_store_fpr64(ctx, fp2, fd);
7867 tcg_temp_free_i64(fp2);
7869 opn = "msub.ps";
7870 break;
7871 case OPC_NMADD_S:
7872 check_cop1x(ctx);
7874 TCGv_i32 fp0 = tcg_temp_new_i32();
7875 TCGv_i32 fp1 = tcg_temp_new_i32();
7876 TCGv_i32 fp2 = tcg_temp_new_i32();
7878 gen_load_fpr32(fp0, fs);
7879 gen_load_fpr32(fp1, ft);
7880 gen_load_fpr32(fp2, fr);
7881 gen_helper_float_nmuladd_s(fp2, fp0, fp1, fp2);
7882 tcg_temp_free_i32(fp0);
7883 tcg_temp_free_i32(fp1);
7884 gen_store_fpr32(fp2, fd);
7885 tcg_temp_free_i32(fp2);
7887 opn = "nmadd.s";
7888 break;
7889 case OPC_NMADD_D:
7890 check_cop1x(ctx);
7891 check_cp1_registers(ctx, fd | fs | ft | fr);
7893 TCGv_i64 fp0 = tcg_temp_new_i64();
7894 TCGv_i64 fp1 = tcg_temp_new_i64();
7895 TCGv_i64 fp2 = tcg_temp_new_i64();
7897 gen_load_fpr64(ctx, fp0, fs);
7898 gen_load_fpr64(ctx, fp1, ft);
7899 gen_load_fpr64(ctx, fp2, fr);
7900 gen_helper_float_nmuladd_d(fp2, fp0, fp1, fp2);
7901 tcg_temp_free_i64(fp0);
7902 tcg_temp_free_i64(fp1);
7903 gen_store_fpr64(ctx, fp2, fd);
7904 tcg_temp_free_i64(fp2);
7906 opn = "nmadd.d";
7907 break;
7908 case OPC_NMADD_PS:
7909 check_cp1_64bitmode(ctx);
7911 TCGv_i64 fp0 = tcg_temp_new_i64();
7912 TCGv_i64 fp1 = tcg_temp_new_i64();
7913 TCGv_i64 fp2 = tcg_temp_new_i64();
7915 gen_load_fpr64(ctx, fp0, fs);
7916 gen_load_fpr64(ctx, fp1, ft);
7917 gen_load_fpr64(ctx, fp2, fr);
7918 gen_helper_float_nmuladd_ps(fp2, fp0, fp1, fp2);
7919 tcg_temp_free_i64(fp0);
7920 tcg_temp_free_i64(fp1);
7921 gen_store_fpr64(ctx, fp2, fd);
7922 tcg_temp_free_i64(fp2);
7924 opn = "nmadd.ps";
7925 break;
7926 case OPC_NMSUB_S:
7927 check_cop1x(ctx);
7929 TCGv_i32 fp0 = tcg_temp_new_i32();
7930 TCGv_i32 fp1 = tcg_temp_new_i32();
7931 TCGv_i32 fp2 = tcg_temp_new_i32();
7933 gen_load_fpr32(fp0, fs);
7934 gen_load_fpr32(fp1, ft);
7935 gen_load_fpr32(fp2, fr);
7936 gen_helper_float_nmulsub_s(fp2, fp0, fp1, fp2);
7937 tcg_temp_free_i32(fp0);
7938 tcg_temp_free_i32(fp1);
7939 gen_store_fpr32(fp2, fd);
7940 tcg_temp_free_i32(fp2);
7942 opn = "nmsub.s";
7943 break;
7944 case OPC_NMSUB_D:
7945 check_cop1x(ctx);
7946 check_cp1_registers(ctx, fd | fs | ft | fr);
7948 TCGv_i64 fp0 = tcg_temp_new_i64();
7949 TCGv_i64 fp1 = tcg_temp_new_i64();
7950 TCGv_i64 fp2 = tcg_temp_new_i64();
7952 gen_load_fpr64(ctx, fp0, fs);
7953 gen_load_fpr64(ctx, fp1, ft);
7954 gen_load_fpr64(ctx, fp2, fr);
7955 gen_helper_float_nmulsub_d(fp2, fp0, fp1, fp2);
7956 tcg_temp_free_i64(fp0);
7957 tcg_temp_free_i64(fp1);
7958 gen_store_fpr64(ctx, fp2, fd);
7959 tcg_temp_free_i64(fp2);
7961 opn = "nmsub.d";
7962 break;
7963 case OPC_NMSUB_PS:
7964 check_cp1_64bitmode(ctx);
7966 TCGv_i64 fp0 = tcg_temp_new_i64();
7967 TCGv_i64 fp1 = tcg_temp_new_i64();
7968 TCGv_i64 fp2 = tcg_temp_new_i64();
7970 gen_load_fpr64(ctx, fp0, fs);
7971 gen_load_fpr64(ctx, fp1, ft);
7972 gen_load_fpr64(ctx, fp2, fr);
7973 gen_helper_float_nmulsub_ps(fp2, fp0, fp1, fp2);
7974 tcg_temp_free_i64(fp0);
7975 tcg_temp_free_i64(fp1);
7976 gen_store_fpr64(ctx, fp2, fd);
7977 tcg_temp_free_i64(fp2);
7979 opn = "nmsub.ps";
7980 break;
7981 default:
7982 MIPS_INVAL(opn);
7983 generate_exception (ctx, EXCP_RI);
7984 return;
7986 MIPS_DEBUG("%s %s, %s, %s, %s", opn, fregnames[fd], fregnames[fr],
7987 fregnames[fs], fregnames[ft]);
7990 static void
7991 gen_rdhwr (CPUState *env, DisasContext *ctx, int rt, int rd)
7993 TCGv t0;
7995 check_insn(env, ctx, ISA_MIPS32R2);
7996 t0 = tcg_temp_new();
7998 switch (rd) {
7999 case 0:
8000 save_cpu_state(ctx, 1);
8001 gen_helper_rdhwr_cpunum(t0);
8002 gen_store_gpr(t0, rt);
8003 break;
8004 case 1:
8005 save_cpu_state(ctx, 1);
8006 gen_helper_rdhwr_synci_step(t0);
8007 gen_store_gpr(t0, rt);
8008 break;
8009 case 2:
8010 save_cpu_state(ctx, 1);
8011 gen_helper_rdhwr_cc(t0);
8012 gen_store_gpr(t0, rt);
8013 break;
8014 case 3:
8015 save_cpu_state(ctx, 1);
8016 gen_helper_rdhwr_ccres(t0);
8017 gen_store_gpr(t0, rt);
8018 break;
8019 case 29:
8020 #if defined(CONFIG_USER_ONLY)
8021 tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUState, tls_value));
8022 gen_store_gpr(t0, rt);
8023 break;
8024 #else
8025 /* XXX: Some CPUs implement this in hardware.
8026 Not supported yet. */
8027 #endif
8028 default: /* Invalid */
8029 MIPS_INVAL("rdhwr");
8030 generate_exception(ctx, EXCP_RI);
8031 break;
8033 tcg_temp_free(t0);
8036 static void handle_delay_slot (CPUState *env, DisasContext *ctx,
8037 int insn_bytes)
8039 if (ctx->hflags & MIPS_HFLAG_BMASK) {
8040 int proc_hflags = ctx->hflags & MIPS_HFLAG_BMASK;
8041 /* Branches completion */
8042 ctx->hflags &= ~MIPS_HFLAG_BMASK;
8043 ctx->bstate = BS_BRANCH;
8044 save_cpu_state(ctx, 0);
8045 /* FIXME: Need to clear can_do_io. */
8046 switch (proc_hflags & MIPS_HFLAG_BMASK_BASE) {
8047 case MIPS_HFLAG_B:
8048 /* unconditional branch */
8049 MIPS_DEBUG("unconditional branch");
8050 if (proc_hflags & MIPS_HFLAG_BX) {
8051 tcg_gen_xori_i32(hflags, hflags, MIPS_HFLAG_M16);
8053 gen_goto_tb(ctx, 0, ctx->btarget);
8054 break;
8055 case MIPS_HFLAG_BL:
8056 /* blikely taken case */
8057 MIPS_DEBUG("blikely branch taken");
8058 gen_goto_tb(ctx, 0, ctx->btarget);
8059 break;
8060 case MIPS_HFLAG_BC:
8061 /* Conditional branch */
8062 MIPS_DEBUG("conditional branch");
8064 int l1 = gen_new_label();
8066 tcg_gen_brcondi_tl(TCG_COND_NE, bcond, 0, l1);
8067 gen_goto_tb(ctx, 1, ctx->pc + insn_bytes);
8068 gen_set_label(l1);
8069 gen_goto_tb(ctx, 0, ctx->btarget);
8071 break;
8072 case MIPS_HFLAG_BR:
8073 /* unconditional branch to register */
8074 MIPS_DEBUG("branch to register");
8075 if (env->insn_flags & (ASE_MIPS16 | ASE_MICROMIPS)) {
8076 TCGv t0 = tcg_temp_new();
8077 TCGv_i32 t1 = tcg_temp_new_i32();
8079 tcg_gen_andi_tl(t0, btarget, 0x1);
8080 tcg_gen_trunc_tl_i32(t1, t0);
8081 tcg_temp_free(t0);
8082 tcg_gen_andi_i32(hflags, hflags, ~(uint32_t)MIPS_HFLAG_M16);
8083 tcg_gen_shli_i32(t1, t1, MIPS_HFLAG_M16_SHIFT);
8084 tcg_gen_or_i32(hflags, hflags, t1);
8085 tcg_temp_free_i32(t1);
8087 tcg_gen_andi_tl(cpu_PC, btarget, ~(target_ulong)0x1);
8088 } else {
8089 tcg_gen_mov_tl(cpu_PC, btarget);
8091 if (ctx->singlestep_enabled) {
8092 save_cpu_state(ctx, 0);
8093 gen_helper_0i(raise_exception, EXCP_DEBUG);
8095 tcg_gen_exit_tb(0);
8096 break;
8097 default:
8098 MIPS_DEBUG("unknown branch");
8099 break;
8104 /* ISA extensions (ASEs) */
8105 /* MIPS16 extension to MIPS32 */
8107 /* MIPS16 major opcodes */
8108 enum {
8109 M16_OPC_ADDIUSP = 0x00,
8110 M16_OPC_ADDIUPC = 0x01,
8111 M16_OPC_B = 0x02,
8112 M16_OPC_JAL = 0x03,
8113 M16_OPC_BEQZ = 0x04,
8114 M16_OPC_BNEQZ = 0x05,
8115 M16_OPC_SHIFT = 0x06,
8116 M16_OPC_LD = 0x07,
8117 M16_OPC_RRIA = 0x08,
8118 M16_OPC_ADDIU8 = 0x09,
8119 M16_OPC_SLTI = 0x0a,
8120 M16_OPC_SLTIU = 0x0b,
8121 M16_OPC_I8 = 0x0c,
8122 M16_OPC_LI = 0x0d,
8123 M16_OPC_CMPI = 0x0e,
8124 M16_OPC_SD = 0x0f,
8125 M16_OPC_LB = 0x10,
8126 M16_OPC_LH = 0x11,
8127 M16_OPC_LWSP = 0x12,
8128 M16_OPC_LW = 0x13,
8129 M16_OPC_LBU = 0x14,
8130 M16_OPC_LHU = 0x15,
8131 M16_OPC_LWPC = 0x16,
8132 M16_OPC_LWU = 0x17,
8133 M16_OPC_SB = 0x18,
8134 M16_OPC_SH = 0x19,
8135 M16_OPC_SWSP = 0x1a,
8136 M16_OPC_SW = 0x1b,
8137 M16_OPC_RRR = 0x1c,
8138 M16_OPC_RR = 0x1d,
8139 M16_OPC_EXTEND = 0x1e,
8140 M16_OPC_I64 = 0x1f
8143 /* I8 funct field */
8144 enum {
8145 I8_BTEQZ = 0x0,
8146 I8_BTNEZ = 0x1,
8147 I8_SWRASP = 0x2,
8148 I8_ADJSP = 0x3,
8149 I8_SVRS = 0x4,
8150 I8_MOV32R = 0x5,
8151 I8_MOVR32 = 0x7
8154 /* RRR f field */
8155 enum {
8156 RRR_DADDU = 0x0,
8157 RRR_ADDU = 0x1,
8158 RRR_DSUBU = 0x2,
8159 RRR_SUBU = 0x3
8162 /* RR funct field */
8163 enum {
8164 RR_JR = 0x00,
8165 RR_SDBBP = 0x01,
8166 RR_SLT = 0x02,
8167 RR_SLTU = 0x03,
8168 RR_SLLV = 0x04,
8169 RR_BREAK = 0x05,
8170 RR_SRLV = 0x06,
8171 RR_SRAV = 0x07,
8172 RR_DSRL = 0x08,
8173 RR_CMP = 0x0a,
8174 RR_NEG = 0x0b,
8175 RR_AND = 0x0c,
8176 RR_OR = 0x0d,
8177 RR_XOR = 0x0e,
8178 RR_NOT = 0x0f,
8179 RR_MFHI = 0x10,
8180 RR_CNVT = 0x11,
8181 RR_MFLO = 0x12,
8182 RR_DSRA = 0x13,
8183 RR_DSLLV = 0x14,
8184 RR_DSRLV = 0x16,
8185 RR_DSRAV = 0x17,
8186 RR_MULT = 0x18,
8187 RR_MULTU = 0x19,
8188 RR_DIV = 0x1a,
8189 RR_DIVU = 0x1b,
8190 RR_DMULT = 0x1c,
8191 RR_DMULTU = 0x1d,
8192 RR_DDIV = 0x1e,
8193 RR_DDIVU = 0x1f
8196 /* I64 funct field */
8197 enum {
8198 I64_LDSP = 0x0,
8199 I64_SDSP = 0x1,
8200 I64_SDRASP = 0x2,
8201 I64_DADJSP = 0x3,
8202 I64_LDPC = 0x4,
8203 I64_DADDIU5 = 0x5,
8204 I64_DADDIUPC = 0x6,
8205 I64_DADDIUSP = 0x7
8208 /* RR ry field for CNVT */
8209 enum {
8210 RR_RY_CNVT_ZEB = 0x0,
8211 RR_RY_CNVT_ZEH = 0x1,
8212 RR_RY_CNVT_ZEW = 0x2,
8213 RR_RY_CNVT_SEB = 0x4,
8214 RR_RY_CNVT_SEH = 0x5,
8215 RR_RY_CNVT_SEW = 0x6,
8218 static int xlat (int r)
8220 static int map[] = { 16, 17, 2, 3, 4, 5, 6, 7 };
8222 return map[r];
8225 static void gen_mips16_save (DisasContext *ctx,
8226 int xsregs, int aregs,
8227 int do_ra, int do_s0, int do_s1,
8228 int framesize)
8230 TCGv t0 = tcg_temp_new();
8231 TCGv t1 = tcg_temp_new();
8232 int args, astatic;
8234 switch (aregs) {
8235 case 0:
8236 case 1:
8237 case 2:
8238 case 3:
8239 case 11:
8240 args = 0;
8241 break;
8242 case 4:
8243 case 5:
8244 case 6:
8245 case 7:
8246 args = 1;
8247 break;
8248 case 8:
8249 case 9:
8250 case 10:
8251 args = 2;
8252 break;
8253 case 12:
8254 case 13:
8255 args = 3;
8256 break;
8257 case 14:
8258 args = 4;
8259 break;
8260 default:
8261 generate_exception(ctx, EXCP_RI);
8262 return;
8265 switch (args) {
8266 case 4:
8267 gen_base_offset_addr(ctx, t0, 29, 12);
8268 gen_load_gpr(t1, 7);
8269 op_st_sw(t1, t0, ctx);
8270 /* Fall through */
8271 case 3:
8272 gen_base_offset_addr(ctx, t0, 29, 8);
8273 gen_load_gpr(t1, 6);
8274 op_st_sw(t1, t0, ctx);
8275 /* Fall through */
8276 case 2:
8277 gen_base_offset_addr(ctx, t0, 29, 4);
8278 gen_load_gpr(t1, 5);
8279 op_st_sw(t1, t0, ctx);
8280 /* Fall through */
8281 case 1:
8282 gen_base_offset_addr(ctx, t0, 29, 0);
8283 gen_load_gpr(t1, 4);
8284 op_st_sw(t1, t0, ctx);
8287 gen_load_gpr(t0, 29);
8289 #define DECR_AND_STORE(reg) do { \
8290 tcg_gen_subi_tl(t0, t0, 4); \
8291 gen_load_gpr(t1, reg); \
8292 op_st_sw(t1, t0, ctx); \
8293 } while (0)
8295 if (do_ra) {
8296 DECR_AND_STORE(31);
8299 switch (xsregs) {
8300 case 7:
8301 DECR_AND_STORE(30);
8302 /* Fall through */
8303 case 6:
8304 DECR_AND_STORE(23);
8305 /* Fall through */
8306 case 5:
8307 DECR_AND_STORE(22);
8308 /* Fall through */
8309 case 4:
8310 DECR_AND_STORE(21);
8311 /* Fall through */
8312 case 3:
8313 DECR_AND_STORE(20);
8314 /* Fall through */
8315 case 2:
8316 DECR_AND_STORE(19);
8317 /* Fall through */
8318 case 1:
8319 DECR_AND_STORE(18);
8322 if (do_s1) {
8323 DECR_AND_STORE(17);
8325 if (do_s0) {
8326 DECR_AND_STORE(16);
8329 switch (aregs) {
8330 case 0:
8331 case 4:
8332 case 8:
8333 case 12:
8334 case 14:
8335 astatic = 0;
8336 break;
8337 case 1:
8338 case 5:
8339 case 9:
8340 case 13:
8341 astatic = 1;
8342 break;
8343 case 2:
8344 case 6:
8345 case 10:
8346 astatic = 2;
8347 break;
8348 case 3:
8349 case 7:
8350 astatic = 3;
8351 break;
8352 case 11:
8353 astatic = 4;
8354 break;
8355 default:
8356 generate_exception(ctx, EXCP_RI);
8357 return;
8360 if (astatic > 0) {
8361 DECR_AND_STORE(7);
8362 if (astatic > 1) {
8363 DECR_AND_STORE(6);
8364 if (astatic > 2) {
8365 DECR_AND_STORE(5);
8366 if (astatic > 3) {
8367 DECR_AND_STORE(4);
8372 #undef DECR_AND_STORE
8374 tcg_gen_subi_tl(cpu_gpr[29], cpu_gpr[29], framesize);
8375 tcg_temp_free(t0);
8376 tcg_temp_free(t1);
8379 static void gen_mips16_restore (DisasContext *ctx,
8380 int xsregs, int aregs,
8381 int do_ra, int do_s0, int do_s1,
8382 int framesize)
8384 int astatic;
8385 TCGv t0 = tcg_temp_new();
8386 TCGv t1 = tcg_temp_new();
8388 tcg_gen_addi_tl(t0, cpu_gpr[29], framesize);
8390 #define DECR_AND_LOAD(reg) do { \
8391 tcg_gen_subi_tl(t0, t0, 4); \
8392 op_ld_lw(t1, t0, ctx); \
8393 gen_store_gpr(t1, reg); \
8394 } while (0)
8396 if (do_ra) {
8397 DECR_AND_LOAD(31);
8400 switch (xsregs) {
8401 case 7:
8402 DECR_AND_LOAD(30);
8403 /* Fall through */
8404 case 6:
8405 DECR_AND_LOAD(23);
8406 /* Fall through */
8407 case 5:
8408 DECR_AND_LOAD(22);
8409 /* Fall through */
8410 case 4:
8411 DECR_AND_LOAD(21);
8412 /* Fall through */
8413 case 3:
8414 DECR_AND_LOAD(20);
8415 /* Fall through */
8416 case 2:
8417 DECR_AND_LOAD(19);
8418 /* Fall through */
8419 case 1:
8420 DECR_AND_LOAD(18);
8423 if (do_s1) {
8424 DECR_AND_LOAD(17);
8426 if (do_s0) {
8427 DECR_AND_LOAD(16);
8430 switch (aregs) {
8431 case 0:
8432 case 4:
8433 case 8:
8434 case 12:
8435 case 14:
8436 astatic = 0;
8437 break;
8438 case 1:
8439 case 5:
8440 case 9:
8441 case 13:
8442 astatic = 1;
8443 break;
8444 case 2:
8445 case 6:
8446 case 10:
8447 astatic = 2;
8448 break;
8449 case 3:
8450 case 7:
8451 astatic = 3;
8452 break;
8453 case 11:
8454 astatic = 4;
8455 break;
8456 default:
8457 generate_exception(ctx, EXCP_RI);
8458 return;
8461 if (astatic > 0) {
8462 DECR_AND_LOAD(7);
8463 if (astatic > 1) {
8464 DECR_AND_LOAD(6);
8465 if (astatic > 2) {
8466 DECR_AND_LOAD(5);
8467 if (astatic > 3) {
8468 DECR_AND_LOAD(4);
8473 #undef DECR_AND_LOAD
8475 tcg_gen_addi_tl(cpu_gpr[29], cpu_gpr[29], framesize);
8476 tcg_temp_free(t0);
8477 tcg_temp_free(t1);
8480 static void gen_addiupc (DisasContext *ctx, int rx, int imm,
8481 int is_64_bit, int extended)
8483 TCGv t0;
8485 if (extended && (ctx->hflags & MIPS_HFLAG_BMASK)) {
8486 generate_exception(ctx, EXCP_RI);
8487 return;
8490 t0 = tcg_temp_new();
8492 tcg_gen_movi_tl(t0, pc_relative_pc(ctx));
8493 tcg_gen_addi_tl(cpu_gpr[rx], t0, imm);
8494 if (!is_64_bit) {
8495 tcg_gen_ext32s_tl(cpu_gpr[rx], cpu_gpr[rx]);
8498 tcg_temp_free(t0);
8501 #if defined(TARGET_MIPS64)
8502 static void decode_i64_mips16 (CPUState *env, DisasContext *ctx,
8503 int ry, int funct, int16_t offset,
8504 int extended)
8506 switch (funct) {
8507 case I64_LDSP:
8508 check_mips_64(ctx);
8509 offset = extended ? offset : offset << 3;
8510 gen_ld(env, ctx, OPC_LD, ry, 29, offset);
8511 break;
8512 case I64_SDSP:
8513 check_mips_64(ctx);
8514 offset = extended ? offset : offset << 3;
8515 gen_st(ctx, OPC_SD, ry, 29, offset);
8516 break;
8517 case I64_SDRASP:
8518 check_mips_64(ctx);
8519 offset = extended ? offset : (ctx->opcode & 0xff) << 3;
8520 gen_st(ctx, OPC_SD, 31, 29, offset);
8521 break;
8522 case I64_DADJSP:
8523 check_mips_64(ctx);
8524 offset = extended ? offset : ((int8_t)ctx->opcode) << 3;
8525 gen_arith_imm(env, ctx, OPC_DADDIU, 29, 29, offset);
8526 break;
8527 case I64_LDPC:
8528 if (extended && (ctx->hflags & MIPS_HFLAG_BMASK)) {
8529 generate_exception(ctx, EXCP_RI);
8530 } else {
8531 offset = extended ? offset : offset << 3;
8532 gen_ld(env, ctx, OPC_LDPC, ry, 0, offset);
8534 break;
8535 case I64_DADDIU5:
8536 check_mips_64(ctx);
8537 offset = extended ? offset : ((int8_t)(offset << 3)) >> 3;
8538 gen_arith_imm(env, ctx, OPC_DADDIU, ry, ry, offset);
8539 break;
8540 case I64_DADDIUPC:
8541 check_mips_64(ctx);
8542 offset = extended ? offset : offset << 2;
8543 gen_addiupc(ctx, ry, offset, 1, extended);
8544 break;
8545 case I64_DADDIUSP:
8546 check_mips_64(ctx);
8547 offset = extended ? offset : offset << 2;
8548 gen_arith_imm(env, ctx, OPC_DADDIU, ry, 29, offset);
8549 break;
8552 #endif
8554 static int decode_extended_mips16_opc (CPUState *env, DisasContext *ctx,
8555 int *is_branch)
8557 int extend = lduw_code(ctx->pc + 2);
8558 int op, rx, ry, funct, sa;
8559 int16_t imm, offset;
8561 ctx->opcode = (ctx->opcode << 16) | extend;
8562 op = (ctx->opcode >> 11) & 0x1f;
8563 sa = (ctx->opcode >> 22) & 0x1f;
8564 funct = (ctx->opcode >> 8) & 0x7;
8565 rx = xlat((ctx->opcode >> 8) & 0x7);
8566 ry = xlat((ctx->opcode >> 5) & 0x7);
8567 offset = imm = (int16_t) (((ctx->opcode >> 16) & 0x1f) << 11
8568 | ((ctx->opcode >> 21) & 0x3f) << 5
8569 | (ctx->opcode & 0x1f));
8571 /* The extended opcodes cleverly reuse the opcodes from their 16-bit
8572 counterparts. */
8573 switch (op) {
8574 case M16_OPC_ADDIUSP:
8575 gen_arith_imm(env, ctx, OPC_ADDIU, rx, 29, imm);
8576 break;
8577 case M16_OPC_ADDIUPC:
8578 gen_addiupc(ctx, rx, imm, 0, 1);
8579 break;
8580 case M16_OPC_B:
8581 gen_compute_branch(ctx, OPC_BEQ, 4, 0, 0, offset << 1);
8582 /* No delay slot, so just process as a normal instruction */
8583 break;
8584 case M16_OPC_BEQZ:
8585 gen_compute_branch(ctx, OPC_BEQ, 4, rx, 0, offset << 1);
8586 /* No delay slot, so just process as a normal instruction */
8587 break;
8588 case M16_OPC_BNEQZ:
8589 gen_compute_branch(ctx, OPC_BNE, 4, rx, 0, offset << 1);
8590 /* No delay slot, so just process as a normal instruction */
8591 break;
8592 case M16_OPC_SHIFT:
8593 switch (ctx->opcode & 0x3) {
8594 case 0x0:
8595 gen_shift_imm(env, ctx, OPC_SLL, rx, ry, sa);
8596 break;
8597 case 0x1:
8598 #if defined(TARGET_MIPS64)
8599 check_mips_64(ctx);
8600 gen_shift_imm(env, ctx, OPC_DSLL, rx, ry, sa);
8601 #else
8602 generate_exception(ctx, EXCP_RI);
8603 #endif
8604 break;
8605 case 0x2:
8606 gen_shift_imm(env, ctx, OPC_SRL, rx, ry, sa);
8607 break;
8608 case 0x3:
8609 gen_shift_imm(env, ctx, OPC_SRA, rx, ry, sa);
8610 break;
8612 break;
8613 #if defined(TARGET_MIPS64)
8614 case M16_OPC_LD:
8615 check_mips_64(ctx);
8616 gen_ld(env, ctx, OPC_LD, ry, rx, offset);
8617 break;
8618 #endif
8619 case M16_OPC_RRIA:
8620 imm = ctx->opcode & 0xf;
8621 imm = imm | ((ctx->opcode >> 20) & 0x7f) << 4;
8622 imm = imm | ((ctx->opcode >> 16) & 0xf) << 11;
8623 imm = (int16_t) (imm << 1) >> 1;
8624 if ((ctx->opcode >> 4) & 0x1) {
8625 #if defined(TARGET_MIPS64)
8626 check_mips_64(ctx);
8627 gen_arith_imm(env, ctx, OPC_DADDIU, ry, rx, imm);
8628 #else
8629 generate_exception(ctx, EXCP_RI);
8630 #endif
8631 } else {
8632 gen_arith_imm(env, ctx, OPC_ADDIU, ry, rx, imm);
8634 break;
8635 case M16_OPC_ADDIU8:
8636 gen_arith_imm(env, ctx, OPC_ADDIU, rx, rx, imm);
8637 break;
8638 case M16_OPC_SLTI:
8639 gen_slt_imm(env, OPC_SLTI, 24, rx, imm);
8640 break;
8641 case M16_OPC_SLTIU:
8642 gen_slt_imm(env, OPC_SLTIU, 24, rx, imm);
8643 break;
8644 case M16_OPC_I8:
8645 switch (funct) {
8646 case I8_BTEQZ:
8647 gen_compute_branch(ctx, OPC_BEQ, 4, 24, 0, offset << 1);
8648 break;
8649 case I8_BTNEZ:
8650 gen_compute_branch(ctx, OPC_BNE, 4, 24, 0, offset << 1);
8651 break;
8652 case I8_SWRASP:
8653 gen_st(ctx, OPC_SW, 31, 29, imm);
8654 break;
8655 case I8_ADJSP:
8656 gen_arith_imm(env, ctx, OPC_ADDIU, 29, 29, imm);
8657 break;
8658 case I8_SVRS:
8660 int xsregs = (ctx->opcode >> 24) & 0x7;
8661 int aregs = (ctx->opcode >> 16) & 0xf;
8662 int do_ra = (ctx->opcode >> 6) & 0x1;
8663 int do_s0 = (ctx->opcode >> 5) & 0x1;
8664 int do_s1 = (ctx->opcode >> 4) & 0x1;
8665 int framesize = (((ctx->opcode >> 20) & 0xf) << 4
8666 | (ctx->opcode & 0xf)) << 3;
8668 if (ctx->opcode & (1 << 7)) {
8669 gen_mips16_save(ctx, xsregs, aregs,
8670 do_ra, do_s0, do_s1,
8671 framesize);
8672 } else {
8673 gen_mips16_restore(ctx, xsregs, aregs,
8674 do_ra, do_s0, do_s1,
8675 framesize);
8678 break;
8679 default:
8680 generate_exception(ctx, EXCP_RI);
8681 break;
8683 break;
8684 case M16_OPC_LI:
8685 tcg_gen_movi_tl(cpu_gpr[rx], (uint16_t) imm);
8686 break;
8687 case M16_OPC_CMPI:
8688 tcg_gen_xori_tl(cpu_gpr[24], cpu_gpr[rx], (uint16_t) imm);
8689 break;
8690 #if defined(TARGET_MIPS64)
8691 case M16_OPC_SD:
8692 gen_st(ctx, OPC_SD, ry, rx, offset);
8693 break;
8694 #endif
8695 case M16_OPC_LB:
8696 gen_ld(env, ctx, OPC_LB, ry, rx, offset);
8697 break;
8698 case M16_OPC_LH:
8699 gen_ld(env, ctx, OPC_LH, ry, rx, offset);
8700 break;
8701 case M16_OPC_LWSP:
8702 gen_ld(env, ctx, OPC_LW, rx, 29, offset);
8703 break;
8704 case M16_OPC_LW:
8705 gen_ld(env, ctx, OPC_LW, ry, rx, offset);
8706 break;
8707 case M16_OPC_LBU:
8708 gen_ld(env, ctx, OPC_LBU, ry, rx, offset);
8709 break;
8710 case M16_OPC_LHU:
8711 gen_ld(env, ctx, OPC_LHU, ry, rx, offset);
8712 break;
8713 case M16_OPC_LWPC:
8714 gen_ld(env, ctx, OPC_LWPC, rx, 0, offset);
8715 break;
8716 #if defined(TARGET_MIPS64)
8717 case M16_OPC_LWU:
8718 gen_ld(env, ctx, OPC_LWU, ry, rx, offset);
8719 break;
8720 #endif
8721 case M16_OPC_SB:
8722 gen_st(ctx, OPC_SB, ry, rx, offset);
8723 break;
8724 case M16_OPC_SH:
8725 gen_st(ctx, OPC_SH, ry, rx, offset);
8726 break;
8727 case M16_OPC_SWSP:
8728 gen_st(ctx, OPC_SW, rx, 29, offset);
8729 break;
8730 case M16_OPC_SW:
8731 gen_st(ctx, OPC_SW, ry, rx, offset);
8732 break;
8733 #if defined(TARGET_MIPS64)
8734 case M16_OPC_I64:
8735 decode_i64_mips16(env, ctx, ry, funct, offset, 1);
8736 break;
8737 #endif
8738 default:
8739 generate_exception(ctx, EXCP_RI);
8740 break;
8743 return 4;
8746 static int decode_mips16_opc (CPUState *env, DisasContext *ctx,
8747 int *is_branch)
8749 int rx, ry;
8750 int sa;
8751 int op, cnvt_op, op1, offset;
8752 int funct;
8753 int n_bytes;
8755 op = (ctx->opcode >> 11) & 0x1f;
8756 sa = (ctx->opcode >> 2) & 0x7;
8757 sa = sa == 0 ? 8 : sa;
8758 rx = xlat((ctx->opcode >> 8) & 0x7);
8759 cnvt_op = (ctx->opcode >> 5) & 0x7;
8760 ry = xlat((ctx->opcode >> 5) & 0x7);
8761 op1 = offset = ctx->opcode & 0x1f;
8763 n_bytes = 2;
8765 switch (op) {
8766 case M16_OPC_ADDIUSP:
8768 int16_t imm = ((uint8_t) ctx->opcode) << 2;
8770 gen_arith_imm(env, ctx, OPC_ADDIU, rx, 29, imm);
8772 break;
8773 case M16_OPC_ADDIUPC:
8774 gen_addiupc(ctx, rx, ((uint8_t) ctx->opcode) << 2, 0, 0);
8775 break;
8776 case M16_OPC_B:
8777 offset = (ctx->opcode & 0x7ff) << 1;
8778 offset = (int16_t)(offset << 4) >> 4;
8779 gen_compute_branch(ctx, OPC_BEQ, 2, 0, 0, offset);
8780 /* No delay slot, so just process as a normal instruction */
8781 break;
8782 case M16_OPC_JAL:
8783 offset = lduw_code(ctx->pc + 2);
8784 offset = (((ctx->opcode & 0x1f) << 21)
8785 | ((ctx->opcode >> 5) & 0x1f) << 16
8786 | offset) << 2;
8787 op = ((ctx->opcode >> 10) & 0x1) ? OPC_JALXS : OPC_JALS;
8788 gen_compute_branch(ctx, op, 4, rx, ry, offset);
8789 n_bytes = 4;
8790 *is_branch = 1;
8791 break;
8792 case M16_OPC_BEQZ:
8793 gen_compute_branch(ctx, OPC_BEQ, 2, rx, 0, ((int8_t)ctx->opcode) << 1);
8794 /* No delay slot, so just process as a normal instruction */
8795 break;
8796 case M16_OPC_BNEQZ:
8797 gen_compute_branch(ctx, OPC_BNE, 2, rx, 0, ((int8_t)ctx->opcode) << 1);
8798 /* No delay slot, so just process as a normal instruction */
8799 break;
8800 case M16_OPC_SHIFT:
8801 switch (ctx->opcode & 0x3) {
8802 case 0x0:
8803 gen_shift_imm(env, ctx, OPC_SLL, rx, ry, sa);
8804 break;
8805 case 0x1:
8806 #if defined(TARGET_MIPS64)
8807 check_mips_64(ctx);
8808 gen_shift_imm(env, ctx, OPC_DSLL, rx, ry, sa);
8809 #else
8810 generate_exception(ctx, EXCP_RI);
8811 #endif
8812 break;
8813 case 0x2:
8814 gen_shift_imm(env, ctx, OPC_SRL, rx, ry, sa);
8815 break;
8816 case 0x3:
8817 gen_shift_imm(env, ctx, OPC_SRA, rx, ry, sa);
8818 break;
8820 break;
8821 #if defined(TARGET_MIPS64)
8822 case M16_OPC_LD:
8823 check_mips_64(ctx);
8824 gen_ld(env, ctx, OPC_LD, ry, rx, offset << 3);
8825 break;
8826 #endif
8827 case M16_OPC_RRIA:
8829 int16_t imm = (int8_t)((ctx->opcode & 0xf) << 4) >> 4;
8831 if ((ctx->opcode >> 4) & 1) {
8832 #if defined(TARGET_MIPS64)
8833 check_mips_64(ctx);
8834 gen_arith_imm(env, ctx, OPC_DADDIU, ry, rx, imm);
8835 #else
8836 generate_exception(ctx, EXCP_RI);
8837 #endif
8838 } else {
8839 gen_arith_imm(env, ctx, OPC_ADDIU, ry, rx, imm);
8842 break;
8843 case M16_OPC_ADDIU8:
8845 int16_t imm = (int8_t) ctx->opcode;
8847 gen_arith_imm(env, ctx, OPC_ADDIU, rx, rx, imm);
8849 break;
8850 case M16_OPC_SLTI:
8852 int16_t imm = (uint8_t) ctx->opcode;
8854 gen_slt_imm(env, OPC_SLTI, 24, rx, imm);
8856 break;
8857 case M16_OPC_SLTIU:
8859 int16_t imm = (uint8_t) ctx->opcode;
8861 gen_slt_imm(env, OPC_SLTIU, 24, rx, imm);
8863 break;
8864 case M16_OPC_I8:
8866 int reg32;
8868 funct = (ctx->opcode >> 8) & 0x7;
8869 switch (funct) {
8870 case I8_BTEQZ:
8871 gen_compute_branch(ctx, OPC_BEQ, 2, 24, 0,
8872 ((int8_t)ctx->opcode) << 1);
8873 break;
8874 case I8_BTNEZ:
8875 gen_compute_branch(ctx, OPC_BNE, 2, 24, 0,
8876 ((int8_t)ctx->opcode) << 1);
8877 break;
8878 case I8_SWRASP:
8879 gen_st(ctx, OPC_SW, 31, 29, (ctx->opcode & 0xff) << 2);
8880 break;
8881 case I8_ADJSP:
8882 gen_arith_imm(env, ctx, OPC_ADDIU, 29, 29,
8883 ((int8_t)ctx->opcode) << 3);
8884 break;
8885 case I8_SVRS:
8887 int do_ra = ctx->opcode & (1 << 6);
8888 int do_s0 = ctx->opcode & (1 << 5);
8889 int do_s1 = ctx->opcode & (1 << 4);
8890 int framesize = ctx->opcode & 0xf;
8892 if (framesize == 0) {
8893 framesize = 128;
8894 } else {
8895 framesize = framesize << 3;
8898 if (ctx->opcode & (1 << 7)) {
8899 gen_mips16_save(ctx, 0, 0,
8900 do_ra, do_s0, do_s1, framesize);
8901 } else {
8902 gen_mips16_restore(ctx, 0, 0,
8903 do_ra, do_s0, do_s1, framesize);
8906 break;
8907 case I8_MOV32R:
8909 int rz = xlat(ctx->opcode & 0x7);
8911 reg32 = (((ctx->opcode >> 3) & 0x3) << 3) |
8912 ((ctx->opcode >> 5) & 0x7);
8913 gen_arith(env, ctx, OPC_ADDU, reg32, rz, 0);
8915 break;
8916 case I8_MOVR32:
8917 reg32 = ctx->opcode & 0x1f;
8918 gen_arith(env, ctx, OPC_ADDU, ry, reg32, 0);
8919 break;
8920 default:
8921 generate_exception(ctx, EXCP_RI);
8922 break;
8925 break;
8926 case M16_OPC_LI:
8928 int16_t imm = (uint8_t) ctx->opcode;
8930 gen_arith_imm(env, ctx, OPC_ADDIU, rx, 0, imm);
8932 break;
8933 case M16_OPC_CMPI:
8935 int16_t imm = (uint8_t) ctx->opcode;
8937 gen_logic_imm(env, OPC_XORI, 24, rx, imm);
8939 break;
8940 #if defined(TARGET_MIPS64)
8941 case M16_OPC_SD:
8942 check_mips_64(ctx);
8943 gen_st(ctx, OPC_SD, ry, rx, offset << 3);
8944 break;
8945 #endif
8946 case M16_OPC_LB:
8947 gen_ld(env, ctx, OPC_LB, ry, rx, offset);
8948 break;
8949 case M16_OPC_LH:
8950 gen_ld(env, ctx, OPC_LH, ry, rx, offset << 1);
8951 break;
8952 case M16_OPC_LWSP:
8953 gen_ld(env, ctx, OPC_LW, rx, 29, ((uint8_t)ctx->opcode) << 2);
8954 break;
8955 case M16_OPC_LW:
8956 gen_ld(env, ctx, OPC_LW, ry, rx, offset << 2);
8957 break;
8958 case M16_OPC_LBU:
8959 gen_ld(env, ctx, OPC_LBU, ry, rx, offset);
8960 break;
8961 case M16_OPC_LHU:
8962 gen_ld(env, ctx, OPC_LHU, ry, rx, offset << 1);
8963 break;
8964 case M16_OPC_LWPC:
8965 gen_ld(env, ctx, OPC_LWPC, rx, 0, ((uint8_t)ctx->opcode) << 2);
8966 break;
8967 #if defined (TARGET_MIPS64)
8968 case M16_OPC_LWU:
8969 check_mips_64(ctx);
8970 gen_ld(env, ctx, OPC_LWU, ry, rx, offset << 2);
8971 break;
8972 #endif
8973 case M16_OPC_SB:
8974 gen_st(ctx, OPC_SB, ry, rx, offset);
8975 break;
8976 case M16_OPC_SH:
8977 gen_st(ctx, OPC_SH, ry, rx, offset << 1);
8978 break;
8979 case M16_OPC_SWSP:
8980 gen_st(ctx, OPC_SW, rx, 29, ((uint8_t)ctx->opcode) << 2);
8981 break;
8982 case M16_OPC_SW:
8983 gen_st(ctx, OPC_SW, ry, rx, offset << 2);
8984 break;
8985 case M16_OPC_RRR:
8987 int rz = xlat((ctx->opcode >> 2) & 0x7);
8988 int mips32_op;
8990 switch (ctx->opcode & 0x3) {
8991 case RRR_ADDU:
8992 mips32_op = OPC_ADDU;
8993 break;
8994 case RRR_SUBU:
8995 mips32_op = OPC_SUBU;
8996 break;
8997 #if defined(TARGET_MIPS64)
8998 case RRR_DADDU:
8999 mips32_op = OPC_DADDU;
9000 check_mips_64(ctx);
9001 break;
9002 case RRR_DSUBU:
9003 mips32_op = OPC_DSUBU;
9004 check_mips_64(ctx);
9005 break;
9006 #endif
9007 default:
9008 generate_exception(ctx, EXCP_RI);
9009 goto done;
9012 gen_arith(env, ctx, mips32_op, rz, rx, ry);
9013 done:
9016 break;
9017 case M16_OPC_RR:
9018 switch (op1) {
9019 case RR_JR:
9021 int nd = (ctx->opcode >> 7) & 0x1;
9022 int link = (ctx->opcode >> 6) & 0x1;
9023 int ra = (ctx->opcode >> 5) & 0x1;
9025 if (link) {
9026 op = nd ? OPC_JALRC : OPC_JALRS;
9027 } else {
9028 op = OPC_JR;
9031 gen_compute_branch(ctx, op, 2, ra ? 31 : rx, 31, 0);
9032 if (!nd) {
9033 *is_branch = 1;
9036 break;
9037 case RR_SDBBP:
9038 /* XXX: not clear which exception should be raised
9039 * when in debug mode...
9041 check_insn(env, ctx, ISA_MIPS32);
9042 if (!(ctx->hflags & MIPS_HFLAG_DM)) {
9043 generate_exception(ctx, EXCP_DBp);
9044 } else {
9045 generate_exception(ctx, EXCP_DBp);
9047 break;
9048 case RR_SLT:
9049 gen_slt(env, OPC_SLT, 24, rx, ry);
9050 break;
9051 case RR_SLTU:
9052 gen_slt(env, OPC_SLTU, 24, rx, ry);
9053 break;
9054 case RR_BREAK:
9055 generate_exception(ctx, EXCP_BREAK);
9056 break;
9057 case RR_SLLV:
9058 gen_shift(env, ctx, OPC_SLLV, ry, rx, ry);
9059 break;
9060 case RR_SRLV:
9061 gen_shift(env, ctx, OPC_SRLV, ry, rx, ry);
9062 break;
9063 case RR_SRAV:
9064 gen_shift(env, ctx, OPC_SRAV, ry, rx, ry);
9065 break;
9066 #if defined (TARGET_MIPS64)
9067 case RR_DSRL:
9068 check_mips_64(ctx);
9069 gen_shift_imm(env, ctx, OPC_DSRL, ry, ry, sa);
9070 break;
9071 #endif
9072 case RR_CMP:
9073 gen_logic(env, OPC_XOR, 24, rx, ry);
9074 break;
9075 case RR_NEG:
9076 gen_arith(env, ctx, OPC_SUBU, rx, 0, ry);
9077 break;
9078 case RR_AND:
9079 gen_logic(env, OPC_AND, rx, rx, ry);
9080 break;
9081 case RR_OR:
9082 gen_logic(env, OPC_OR, rx, rx, ry);
9083 break;
9084 case RR_XOR:
9085 gen_logic(env, OPC_XOR, rx, rx, ry);
9086 break;
9087 case RR_NOT:
9088 gen_logic(env, OPC_NOR, rx, ry, 0);
9089 break;
9090 case RR_MFHI:
9091 gen_HILO(ctx, OPC_MFHI, rx);
9092 break;
9093 case RR_CNVT:
9094 switch (cnvt_op) {
9095 case RR_RY_CNVT_ZEB:
9096 tcg_gen_ext8u_tl(cpu_gpr[rx], cpu_gpr[rx]);
9097 break;
9098 case RR_RY_CNVT_ZEH:
9099 tcg_gen_ext16u_tl(cpu_gpr[rx], cpu_gpr[rx]);
9100 break;
9101 case RR_RY_CNVT_SEB:
9102 tcg_gen_ext8s_tl(cpu_gpr[rx], cpu_gpr[rx]);
9103 break;
9104 case RR_RY_CNVT_SEH:
9105 tcg_gen_ext16s_tl(cpu_gpr[rx], cpu_gpr[rx]);
9106 break;
9107 #if defined (TARGET_MIPS64)
9108 case RR_RY_CNVT_ZEW:
9109 check_mips_64(ctx);
9110 tcg_gen_ext32u_tl(cpu_gpr[rx], cpu_gpr[rx]);
9111 break;
9112 case RR_RY_CNVT_SEW:
9113 check_mips_64(ctx);
9114 tcg_gen_ext32s_tl(cpu_gpr[rx], cpu_gpr[rx]);
9115 break;
9116 #endif
9117 default:
9118 generate_exception(ctx, EXCP_RI);
9119 break;
9121 break;
9122 case RR_MFLO:
9123 gen_HILO(ctx, OPC_MFLO, rx);
9124 break;
9125 #if defined (TARGET_MIPS64)
9126 case RR_DSRA:
9127 check_mips_64(ctx);
9128 gen_shift_imm(env, ctx, OPC_DSRA, ry, ry, sa);
9129 break;
9130 case RR_DSLLV:
9131 check_mips_64(ctx);
9132 gen_shift(env, ctx, OPC_DSLLV, ry, rx, ry);
9133 break;
9134 case RR_DSRLV:
9135 check_mips_64(ctx);
9136 gen_shift(env, ctx, OPC_DSRLV, ry, rx, ry);
9137 break;
9138 case RR_DSRAV:
9139 check_mips_64(ctx);
9140 gen_shift(env, ctx, OPC_DSRAV, ry, rx, ry);
9141 break;
9142 #endif
9143 case RR_MULT:
9144 gen_muldiv(ctx, OPC_MULT, rx, ry);
9145 break;
9146 case RR_MULTU:
9147 gen_muldiv(ctx, OPC_MULTU, rx, ry);
9148 break;
9149 case RR_DIV:
9150 gen_muldiv(ctx, OPC_DIV, rx, ry);
9151 break;
9152 case RR_DIVU:
9153 gen_muldiv(ctx, OPC_DIVU, rx, ry);
9154 break;
9155 #if defined (TARGET_MIPS64)
9156 case RR_DMULT:
9157 check_mips_64(ctx);
9158 gen_muldiv(ctx, OPC_DMULT, rx, ry);
9159 break;
9160 case RR_DMULTU:
9161 check_mips_64(ctx);
9162 gen_muldiv(ctx, OPC_DMULTU, rx, ry);
9163 break;
9164 case RR_DDIV:
9165 check_mips_64(ctx);
9166 gen_muldiv(ctx, OPC_DDIV, rx, ry);
9167 break;
9168 case RR_DDIVU:
9169 check_mips_64(ctx);
9170 gen_muldiv(ctx, OPC_DDIVU, rx, ry);
9171 break;
9172 #endif
9173 default:
9174 generate_exception(ctx, EXCP_RI);
9175 break;
9177 break;
9178 case M16_OPC_EXTEND:
9179 decode_extended_mips16_opc(env, ctx, is_branch);
9180 n_bytes = 4;
9181 break;
9182 #if defined(TARGET_MIPS64)
9183 case M16_OPC_I64:
9184 funct = (ctx->opcode >> 8) & 0x7;
9185 decode_i64_mips16(env, ctx, ry, funct, offset, 0);
9186 break;
9187 #endif
9188 default:
9189 generate_exception(ctx, EXCP_RI);
9190 break;
9193 return n_bytes;
9196 /* microMIPS extension to MIPS32 */
9198 /* microMIPS32 major opcodes */
9200 enum {
9201 POOL32A = 0x00,
9202 POOL16A = 0x01,
9203 LBU16 = 0x02,
9204 MOVE16 = 0x03,
9205 ADDI32 = 0x04,
9206 LBU32 = 0x05,
9207 SB32 = 0x06,
9208 LB32 = 0x07,
9210 POOL32B = 0x08,
9211 POOL16B = 0x09,
9212 LHU16 = 0x0a,
9213 ANDI16 = 0x0b,
9214 ADDIU32 = 0x0c,
9215 LHU32 = 0x0d,
9216 SH32 = 0x0e,
9217 LH32 = 0x0f,
9219 POOL32I = 0x10,
9220 POOL16C = 0x11,
9221 LWSP16 = 0x12,
9222 POOL16D = 0x13,
9223 ORI32 = 0x14,
9224 POOL32F = 0x15,
9225 POOL32S = 0x16,
9226 DADDIU32 = 0x17,
9228 POOL32C = 0x18,
9229 LWGP16 = 0x19,
9230 LW16 = 0x1a,
9231 POOL16E = 0x1b,
9232 XORI32 = 0x1c,
9233 JALS32 = 0x1d,
9234 ADDIUPC = 0x1e,
9235 POOL48A = 0x1f,
9237 /* 0x20 is reserved */
9238 RES_20 = 0x20,
9239 POOL16F = 0x21,
9240 SB16 = 0x22,
9241 BEQZ16 = 0x23,
9242 SLTI32 = 0x24,
9243 BEQ32 = 0x25,
9244 SWC132 = 0x26,
9245 LWC132 = 0x27,
9247 /* 0x28 and 0x29 are reserved */
9248 RES_28 = 0x28,
9249 RES_29 = 0x29,
9250 SH16 = 0x2a,
9251 BNEZ16 = 0x2b,
9252 SLTIU32 = 0x2c,
9253 BNE32 = 0x2d,
9254 SDC132 = 0x2e,
9255 LDC132 = 0x2f,
9257 /* 0x30 and 0x31 are reserved */
9258 RES_30 = 0x30,
9259 RES_31 = 0x31,
9260 SWSP16 = 0x32,
9261 B16 = 0x33,
9262 ANDI32 = 0x34,
9263 J32 = 0x35,
9264 SD32 = 0x36,
9265 LD32 = 0x37,
9267 /* 0x38 and 0x39 are reserved */
9268 RES_38 = 0x38,
9269 RES_39 = 0x39,
9270 SW16 = 0x3a,
9271 LI16 = 0x3b,
9272 JALX32 = 0x3c,
9273 JAL32 = 0x3d,
9274 SW32 = 0x3e,
9275 LW32 = 0x3f
9278 /* POOL32A encoding of minor opcode field */
9280 enum {
9281 /* These opcodes are distinguished only by bits 9..6; those bits are
9282 * what are recorded below. */
9283 SLL32 = 0x0,
9284 SRL32 = 0x1,
9285 SRA = 0x2,
9286 ROTR = 0x3,
9288 SLLV = 0x0,
9289 SRLV = 0x1,
9290 SRAV = 0x2,
9291 ROTRV = 0x3,
9292 ADD = 0x4,
9293 ADDU32 = 0x5,
9294 SUB = 0x6,
9295 SUBU32 = 0x7,
9296 MUL = 0x8,
9297 AND = 0x9,
9298 OR32 = 0xa,
9299 NOR = 0xb,
9300 XOR32 = 0xc,
9301 SLT = 0xd,
9302 SLTU = 0xe,
9304 MOVN = 0x0,
9305 MOVZ = 0x1,
9306 LWXS = 0x4,
9308 /* The following can be distinguished by their lower 6 bits. */
9309 INS = 0x0c,
9310 EXT = 0x2c,
9311 POOL32AXF = 0x3c
9314 /* POOL32AXF encoding of minor opcode field extension */
9316 enum {
9317 /* bits 11..6 */
9318 TEQ = 0x00,
9319 TGE = 0x08,
9320 TGEU = 0x10,
9321 TLT = 0x20,
9322 TLTU = 0x28,
9323 TNE = 0x30,
9325 MFC0 = 0x03,
9326 MTC0 = 0x0b,
9328 /* bits 13..12 for 0x01 */
9329 MFHI_ACC = 0x0,
9330 MFLO_ACC = 0x1,
9331 MTHI_ACC = 0x2,
9332 MTLO_ACC = 0x3,
9334 /* bits 13..12 for 0x2a */
9335 MADD_ACC = 0x0,
9336 MADDU_ACC = 0x1,
9337 MSUB_ACC = 0x2,
9338 MSUBU_ACC = 0x3,
9340 /* bits 13..12 for 0x32 */
9341 MULT_ACC = 0x0,
9342 MULTU_ACC = 0x0,
9344 /* bits 15..12 for 0x2c */
9345 SEB = 0x2,
9346 SEH = 0x3,
9347 CLO = 0x4,
9348 CLZ = 0x5,
9349 RDHWR = 0x6,
9350 WSBH = 0x7,
9351 MULT = 0x8,
9352 MULTU = 0x9,
9353 DIV = 0xa,
9354 DIVU = 0xb,
9355 MADD = 0xc,
9356 MADDU = 0xd,
9357 MSUB = 0xe,
9358 MSUBU = 0xf,
9360 /* bits 15..12 for 0x34 */
9361 MFC2 = 0x4,
9362 MTC2 = 0x5,
9363 MFHC2 = 0x8,
9364 MTHC2 = 0x9,
9365 CFC2 = 0xc,
9366 CTC2 = 0xd,
9368 /* bits 15..12 for 0x3c */
9369 JALR = 0x0,
9370 JR = 0x0, /* alias */
9371 JALR_HB = 0x1,
9372 JALRS = 0x4,
9373 JALRS_HB = 0x5,
9375 /* bits 15..12 for 0x05 */
9376 RDPGPR = 0xe,
9377 WRPGPR = 0xf,
9379 /* bits 15..12 for 0x0d */
9380 TLBP = 0x0,
9381 TLBR = 0x1,
9382 TLBWI = 0x2,
9383 TLBWR = 0x3,
9384 WAIT = 0x9,
9385 IRET = 0xd,
9386 DERET = 0xe,
9387 ERET = 0xf,
9389 /* bits 15..12 for 0x15 */
9390 DMT = 0x0,
9391 DVPE = 0x1,
9392 EMT = 0x2,
9393 EVPE = 0x3,
9395 /* bits 15..12 for 0x1d */
9396 DI = 0x4,
9397 EI = 0x5,
9399 /* bits 15..12 for 0x2d */
9400 SYNC = 0x6,
9401 SYSCALL = 0x8,
9402 SDBBP = 0xd,
9404 /* bits 15..12 for 0x35 */
9405 MFHI32 = 0x0,
9406 MFLO32 = 0x1,
9407 MTHI32 = 0x2,
9408 MTLO32 = 0x3,
9411 /* POOL32B encoding of minor opcode field (bits 15..12) */
9413 enum {
9414 LWC2 = 0x0,
9415 LWP = 0x1,
9416 LDP = 0x4,
9417 LWM32 = 0x5,
9418 CACHE = 0x6,
9419 LDM = 0x7,
9420 SWC2 = 0x8,
9421 SWP = 0x9,
9422 SDP = 0xc,
9423 SWM32 = 0xd,
9424 SDM = 0xf
9427 /* POOL32C encoding of minor opcode field (bits 15..12) */
9429 enum {
9430 LWL = 0x0,
9431 SWL = 0x8,
9432 LWR = 0x1,
9433 SWR = 0x9,
9434 PREF = 0x2,
9435 /* 0xa is reserved */
9436 LL = 0x3,
9437 SC = 0xb,
9438 LDL = 0x4,
9439 SDL = 0xc,
9440 LDR = 0x5,
9441 SDR = 0xd,
9442 /* 0x6 is reserved */
9443 LWU = 0xe,
9444 LLD = 0x7,
9445 SCD = 0xf
9448 /* POOL32F encoding of minor opcode field (bits 5..0) */
9450 enum {
9451 /* These are the bit 7..6 values */
9452 ADD_FMT = 0x0,
9453 MOVN_FMT = 0x0,
9455 SUB_FMT = 0x1,
9456 MOVZ_FMT = 0x1,
9458 MUL_FMT = 0x2,
9460 DIV_FMT = 0x3,
9462 /* These are the bit 8..6 values */
9463 RSQRT2_FMT = 0x0,
9464 MOVF_FMT = 0x0,
9466 LWXC1 = 0x1,
9467 MOVT_FMT = 0x1,
9469 PLL_PS = 0x2,
9470 SWXC1 = 0x2,
9472 PLU_PS = 0x3,
9473 LDXC1 = 0x3,
9475 PUL_PS = 0x4,
9476 SDXC1 = 0x4,
9477 RECIP2_FMT = 0x4,
9479 PUU_PS = 0x5,
9480 LUXC1 = 0x5,
9482 CVT_PS_S = 0x6,
9483 SUXC1 = 0x6,
9484 ADDR_PS = 0x6,
9485 PREFX = 0x6,
9487 MULR_PS = 0x7,
9489 MADD_S = 0x01,
9490 MADD_D = 0x09,
9491 MADD_PS = 0x11,
9492 ALNV_PS = 0x19,
9493 MSUB_S = 0x21,
9494 MSUB_D = 0x29,
9495 MSUB_PS = 0x31,
9497 NMADD_S = 0x02,
9498 NMADD_D = 0x0a,
9499 NMADD_PS = 0x12,
9500 NMSUB_S = 0x22,
9501 NMSUB_D = 0x2a,
9502 NMSUB_PS = 0x32,
9504 POOL32FXF = 0x3b,
9506 CABS_COND_FMT = 0x1c, /* MIPS3D */
9507 C_COND_FMT = 0x3c
9510 /* POOL32Fxf encoding of minor opcode extension field */
9512 enum {
9513 CVT_L = 0x04,
9514 RSQRT_FMT = 0x08,
9515 FLOOR_L = 0x0c,
9516 CVT_PW_PS = 0x1c,
9517 CVT_W = 0x24,
9518 SQRT_FMT = 0x28,
9519 FLOOR_W = 0x2c,
9520 CVT_PS_PW = 0x3c,
9521 CFC1 = 0x40,
9522 RECIP_FMT = 0x48,
9523 CEIL_L = 0x4c,
9524 CTC1 = 0x60,
9525 CEIL_W = 0x6c,
9526 MFC1 = 0x80,
9527 CVT_S_PL = 0x84,
9528 TRUNC_L = 0x8c,
9529 MTC1 = 0xa0,
9530 CVT_S_PU = 0xa4,
9531 TRUNC_W = 0xac,
9532 MFHC1 = 0xc0,
9533 ROUND_L = 0xcc,
9534 MTHC1 = 0xe0,
9535 ROUND_W = 0xec,
9537 MOV_FMT = 0x01,
9538 MOVF = 0x05,
9539 ABS_FMT = 0x0d,
9540 RSQRT1_FMT = 0x1d,
9541 MOVT = 0x25,
9542 NEG_FMT = 0x2d,
9543 CVT_D = 0x4d,
9544 RECIP1_FMT = 0x5d,
9545 CVT_S = 0x6d
9548 /* POOL32I encoding of minor opcode field (bits 25..21) */
9550 enum {
9551 BLTZ = 0x00,
9552 BLTZAL = 0x01,
9553 BGEZ = 0x02,
9554 BGEZAL = 0x03,
9555 BLEZ = 0x04,
9556 BNEZC = 0x05,
9557 BGTZ = 0x06,
9558 BEQZC = 0x07,
9559 TLTI = 0x08,
9560 TGEI = 0x09,
9561 TLTIU = 0x0a,
9562 TGEIU = 0x0b,
9563 TNEI = 0x0c,
9564 LUI = 0x0d,
9565 TEQI = 0x0e,
9566 SYNCI = 0x10,
9567 BLTZALS = 0x11,
9568 BGEZALS = 0x13,
9569 BC2F = 0x14,
9570 BC2T = 0x15,
9571 BPOSGE64 = 0x1a,
9572 BPOSGE32 = 0x1b,
9573 /* These overlap and are distinguished by bit16 of the instruction */
9574 BC1F = 0x1c,
9575 BC1T = 0x1d,
9576 BC1ANY2F = 0x1c,
9577 BC1ANY2T = 0x1d,
9578 BC1ANY4F = 0x1e,
9579 BC1ANY4T = 0x1f
9582 /* POOL16A encoding of minor opcode field */
9584 enum {
9585 ADDU16 = 0x0,
9586 SUBU16 = 0x1
9589 /* POOL16B encoding of minor opcode field */
9591 enum {
9592 SLL16 = 0x0,
9593 SRL16 = 0x1
9596 /* POOL16C encoding of minor opcode field */
9598 enum {
9599 NOT16 = 0x00,
9600 XOR16 = 0x04,
9601 AND16 = 0x08,
9602 OR16 = 0x0c,
9603 LWM16 = 0x10,
9604 SWM16 = 0x14,
9605 JR16 = 0x18,
9606 JRC16 = 0x1a,
9607 JALR16 = 0x1c,
9608 JALR16S = 0x1e,
9609 MFHI16 = 0x20,
9610 MFLO16 = 0x24,
9611 BREAK16 = 0x28,
9612 SDBBP16 = 0x2c,
9613 JRADDIUSP = 0x30
9616 /* POOL16D encoding of minor opcode field */
9618 enum {
9619 ADDIUS5 = 0x0,
9620 ADDIUSP = 0x1
9623 /* POOL16E encoding of minor opcode field */
9625 enum {
9626 ADDIUR2 = 0x0,
9627 ADDIUR1SP = 0x1
9630 static int mmreg (int r)
9632 static const int map[] = { 16, 17, 2, 3, 4, 5, 6, 7 };
9634 return map[r];
9637 /* Used for 16-bit store instructions. */
9638 static int mmreg2 (int r)
9640 static const int map[] = { 0, 17, 2, 3, 4, 5, 6, 7 };
9642 return map[r];
9645 #define uMIPS_RD(op) ((op >> 7) & 0x7)
9646 #define uMIPS_RS(op) ((op >> 4) & 0x7)
9647 #define uMIPS_RS2(op) uMIPS_RS(op)
9648 #define uMIPS_RS1(op) ((op >> 1) & 0x7)
9649 #define uMIPS_RD5(op) ((op >> 5) & 0x1f)
9650 #define uMIPS_RS5(op) (op & 0x1f)
9652 /* Signed immediate */
9653 #define SIMM(op, start, width) \
9654 ((int32_t)(((op >> start) & ((~0U) >> (32-width))) \
9655 << (32-width)) \
9656 >> (32-width))
9657 /* Zero-extended immediate */
9658 #define ZIMM(op, start, width) ((op >> start) & ((~0U) >> (32-width)))
9660 static void gen_addiur1sp (CPUState *env, DisasContext *ctx)
9662 int rd = mmreg(uMIPS_RD(ctx->opcode));
9664 gen_arith_imm(env, ctx, OPC_ADDIU, rd, 29, ((ctx->opcode >> 1) & 0x3f) << 2);
9667 static void gen_addiur2 (CPUState *env, DisasContext *ctx)
9669 static const int decoded_imm[] = { 1, 4, 8, 12, 16, 20, 24, -1 };
9670 int rd = mmreg(uMIPS_RD(ctx->opcode));
9671 int rs = mmreg(uMIPS_RS(ctx->opcode));
9673 gen_arith_imm(env, ctx, OPC_ADDIU, rd, rs, decoded_imm[ZIMM(ctx->opcode, 1, 3)]);
9676 static void gen_addiusp (CPUState *env, DisasContext *ctx)
9678 int encoded = ZIMM(ctx->opcode, 1, 9);
9679 int decoded;
9681 if (encoded <= 1) {
9682 decoded = 256 + encoded;
9683 } else if (encoded <= 255) {
9684 decoded = encoded;
9685 } else if (encoded <= 509) {
9686 decoded = encoded - 512;
9687 } else {
9688 decoded = encoded - 768;
9691 gen_arith_imm(env, ctx, OPC_ADDIU, 29, 29, decoded << 2);
9694 static void gen_addius5 (CPUState *env, DisasContext *ctx)
9696 int imm = SIMM(ctx->opcode, 1, 4);
9697 int rd = (ctx->opcode >> 5) & 0x1f;
9699 gen_arith_imm(env, ctx, OPC_ADDIU, rd, rd, imm);
9702 static void gen_andi16 (CPUState *env, DisasContext *ctx)
9704 static const int decoded_imm[] = { 128, 1, 2, 3, 4, 7, 8, 15, 16,
9705 31, 32, 63, 64, 255, 32768, 65535 };
9706 int rd = mmreg(uMIPS_RD(ctx->opcode));
9707 int rs = mmreg(uMIPS_RS(ctx->opcode));
9708 int encoded = ZIMM(ctx->opcode, 0, 4);
9710 gen_logic_imm(env, OPC_ANDI, rd, rs, decoded_imm[encoded]);
9713 static void gen_ldst_multiple (DisasContext *ctx, uint32_t opc, int reglist,
9714 int base, int16_t offset)
9716 TCGv t0, t1;
9717 TCGv_i32 t2;
9719 if (ctx->hflags & MIPS_HFLAG_BMASK) {
9720 generate_exception(ctx, EXCP_RI);
9721 return;
9724 t0 = tcg_temp_new();
9726 gen_base_offset_addr(ctx, t0, base, offset);
9728 t1 = tcg_const_tl(reglist);
9729 t2 = tcg_const_i32(ctx->mem_idx);
9731 save_cpu_state(ctx, 1);
9732 switch (opc) {
9733 case LWM32:
9734 gen_helper_lwm(t0, t1, t2);
9735 break;
9736 case SWM32:
9737 gen_helper_swm(t0, t1, t2);
9738 break;
9739 #ifdef TARGET_MIPS64
9740 case LDM:
9741 gen_helper_ldm(t0, t1, t2);
9742 break;
9743 case SDM:
9744 gen_helper_sdm(t0, t1, t2);
9745 break;
9746 #endif
9748 MIPS_DEBUG("%s, %x, %d(%s)", opn, reglist, offset, regnames[base]);
9749 tcg_temp_free(t0);
9750 tcg_temp_free(t1);
9751 tcg_temp_free_i32(t2);
9755 static void gen_pool16c_insn (CPUState *env, DisasContext *ctx, int *is_branch)
9757 int rd = mmreg((ctx->opcode >> 3) & 0x7);
9758 int rs = mmreg(ctx->opcode & 0x7);
9759 int opc;
9761 switch (((ctx->opcode) >> 4) & 0x3f) {
9762 case NOT16 + 0:
9763 case NOT16 + 1:
9764 case NOT16 + 2:
9765 case NOT16 + 3:
9766 gen_logic(env, OPC_NOR, rd, rs, 0);
9767 break;
9768 case XOR16 + 0:
9769 case XOR16 + 1:
9770 case XOR16 + 2:
9771 case XOR16 + 3:
9772 gen_logic(env, OPC_XOR, rd, rd, rs);
9773 break;
9774 case AND16 + 0:
9775 case AND16 + 1:
9776 case AND16 + 2:
9777 case AND16 + 3:
9778 gen_logic(env, OPC_AND, rd, rd, rs);
9779 break;
9780 case OR16 + 0:
9781 case OR16 + 1:
9782 case OR16 + 2:
9783 case OR16 + 3:
9784 gen_logic(env, OPC_OR, rd, rd, rs);
9785 break;
9786 case LWM16 + 0:
9787 case LWM16 + 1:
9788 case LWM16 + 2:
9789 case LWM16 + 3:
9791 static const int lwm_convert[] = { 0x11, 0x12, 0x13, 0x14 };
9792 int offset = ZIMM(ctx->opcode, 0, 4);
9794 gen_ldst_multiple(ctx, LWM32, lwm_convert[(ctx->opcode >> 4) & 0x3],
9795 29, offset << 2);
9797 break;
9798 case SWM16 + 0:
9799 case SWM16 + 1:
9800 case SWM16 + 2:
9801 case SWM16 + 3:
9803 static const int swm_convert[] = { 0x11, 0x12, 0x13, 0x14 };
9804 int offset = ZIMM(ctx->opcode, 0, 4);
9806 gen_ldst_multiple(ctx, SWM32, swm_convert[(ctx->opcode >> 4) & 0x3],
9807 29, offset << 2);
9809 break;
9810 case JR16 + 0:
9811 case JR16 + 1:
9813 int reg = ctx->opcode & 0x1f;
9815 gen_compute_branch(ctx, OPC_JR, 2, reg, 0, 0);
9817 *is_branch = 1;
9818 break;
9819 case JRC16 + 0:
9820 case JRC16 + 1:
9822 int reg = ctx->opcode & 0x1f;
9824 gen_compute_branch(ctx, OPC_JR, 2, reg, 0, 0);
9825 /* Let normal delay slot handling in our caller take us
9826 to the branch target. */
9828 break;
9829 case JALR16 + 0:
9830 case JALR16 + 1:
9831 opc = OPC_JALR;
9832 goto do_jalr;
9833 case JALR16S + 0:
9834 case JALR16S + 1:
9835 opc = OPC_JALRS;
9836 do_jalr:
9838 int reg = ctx->opcode & 0x1f;
9840 gen_compute_branch(ctx, opc, 2, reg, 31, 0);
9842 *is_branch = 1;
9843 break;
9844 case MFHI16 + 0:
9845 case MFHI16 + 1:
9846 gen_HILO(ctx, OPC_MFHI, uMIPS_RS5(ctx->opcode));
9847 break;
9848 case MFLO16 + 0:
9849 case MFLO16 + 1:
9850 gen_HILO(ctx, OPC_MFLO, uMIPS_RS5(ctx->opcode));
9851 break;
9852 case BREAK16:
9853 generate_exception(ctx, EXCP_BREAK);
9854 break;
9855 case SDBBP16:
9856 /* XXX: not clear which exception should be raised
9857 * when in debug mode...
9859 check_insn(env, ctx, ISA_MIPS32);
9860 if (!(ctx->hflags & MIPS_HFLAG_DM)) {
9861 generate_exception(ctx, EXCP_DBp);
9862 } else {
9863 generate_exception(ctx, EXCP_DBp);
9865 break;
9866 case JRADDIUSP + 0:
9867 case JRADDIUSP + 1:
9869 int imm = ZIMM(ctx->opcode, 0, 5);
9871 gen_compute_branch(ctx, OPC_JR, 2, 31, 0, 0);
9872 gen_arith_imm(env, ctx, OPC_ADDIU, 29, 29, imm << 2);
9873 /* Let normal delay slot handling in our caller take us
9874 to the branch target. */
9876 break;
9877 default:
9878 generate_exception(ctx, EXCP_RI);
9879 break;
9883 static void gen_ldxs (DisasContext *ctx, int base, int index, int rd)
9885 TCGv t0 = tcg_temp_new();
9886 TCGv t1 = tcg_temp_new();
9888 gen_load_gpr(t0, base);
9890 if (index != 0) {
9891 gen_load_gpr(t1, index);
9892 tcg_gen_shli_tl(t1, t1, 2);
9893 gen_op_addr_add(ctx, t0, t1, t0);
9896 save_cpu_state(ctx, 0);
9897 op_ld_lw(t1, t0, ctx);
9898 gen_store_gpr(t1, rd);
9900 tcg_temp_free(t0);
9901 tcg_temp_free(t1);
9904 static void gen_ldst_pair (DisasContext *ctx, uint32_t opc, int rd,
9905 int base, int16_t offset)
9907 const char *opn = "ldst_pair";
9908 TCGv t0, t1;
9910 if (ctx->hflags & MIPS_HFLAG_BMASK || rd == 31 || rd == base) {
9911 generate_exception(ctx, EXCP_RI);
9912 return;
9915 t0 = tcg_temp_new();
9916 t1 = tcg_temp_new();
9918 gen_base_offset_addr(ctx, t0, base, offset);
9920 switch (opc) {
9921 case LWP:
9922 save_cpu_state(ctx, 0);
9923 op_ld_lw(t1, t0, ctx);
9924 gen_store_gpr(t1, rd);
9925 tcg_gen_movi_tl(t1, 4);
9926 gen_op_addr_add(ctx, t0, t0, t1);
9927 op_ld_lw(t1, t0, ctx);
9928 gen_store_gpr(t1, rd+1);
9929 opn = "lwp";
9930 break;
9931 case SWP:
9932 save_cpu_state(ctx, 1);
9933 gen_load_gpr(t1, rd);
9934 op_st_sw(t1, t0, ctx);
9935 tcg_gen_movi_tl(t1, 4);
9936 gen_op_addr_add(ctx, t0, t0, t1);
9937 gen_load_gpr(t1, rd+1);
9938 op_st_sw(t1, t0, ctx);
9939 opn = "swp";
9940 break;
9941 #ifdef TARGET_MIPS64
9942 case LDP:
9943 save_cpu_state(ctx, 0);
9944 op_ld_ld(t1, t0, ctx);
9945 gen_store_gpr(t1, rd);
9946 tcg_gen_movi_tl(t1, 8);
9947 gen_op_addr_add(ctx, t0, t0, t1);
9948 op_ld_ld(t1, t0, ctx);
9949 gen_store_gpr(t1, rd+1);
9950 opn = "ldp";
9951 break;
9952 case SDP:
9953 save_cpu_state(ctx, 1);
9954 gen_load_gpr(t1, rd);
9955 op_st_sd(t1, t0, ctx);
9956 tcg_gen_movi_tl(t1, 8);
9957 gen_op_addr_add(ctx, t0, t0, t1);
9958 gen_load_gpr(t1, rd+1);
9959 op_st_sd(t1, t0, ctx);
9960 opn = "sdp";
9961 break;
9962 #endif
9964 MIPS_DEBUG("%s, %s, %d(%s)", opn, regnames[rd], offset, regnames[base]);
9965 tcg_temp_free(t0);
9966 tcg_temp_free(t1);
9969 static void gen_pool32axf (CPUState *env, DisasContext *ctx, int rt, int rs,
9970 int *is_branch)
9972 int extension = (ctx->opcode >> 6) & 0x3f;
9973 int minor = (ctx->opcode >> 12) & 0xf;
9974 uint32_t mips32_op;
9976 switch (extension) {
9977 case TEQ:
9978 mips32_op = OPC_TEQ;
9979 goto do_trap;
9980 case TGE:
9981 mips32_op = OPC_TGE;
9982 goto do_trap;
9983 case TGEU:
9984 mips32_op = OPC_TGEU;
9985 goto do_trap;
9986 case TLT:
9987 mips32_op = OPC_TLT;
9988 goto do_trap;
9989 case TLTU:
9990 mips32_op = OPC_TLTU;
9991 goto do_trap;
9992 case TNE:
9993 mips32_op = OPC_TNE;
9994 do_trap:
9995 gen_trap(ctx, mips32_op, rs, rt, -1);
9996 break;
9997 #ifndef CONFIG_USER_ONLY
9998 case MFC0:
9999 case MFC0 + 32:
10000 if (rt == 0) {
10001 /* Treat as NOP. */
10002 break;
10004 gen_mfc0(env, ctx, cpu_gpr[rt], rs, (ctx->opcode >> 11) & 0x7);
10005 break;
10006 case MTC0:
10007 case MTC0 + 32:
10009 TCGv t0 = tcg_temp_new();
10011 gen_load_gpr(t0, rt);
10012 gen_mtc0(env, ctx, t0, rs, (ctx->opcode >> 11) & 0x7);
10013 tcg_temp_free(t0);
10015 break;
10016 #endif
10017 case 0x2c:
10018 switch (minor) {
10019 case SEB:
10020 gen_bshfl(ctx, OPC_SEB, rs, rt);
10021 break;
10022 case SEH:
10023 gen_bshfl(ctx, OPC_SEH, rs, rt);
10024 break;
10025 case CLO:
10026 mips32_op = OPC_CLO;
10027 goto do_cl;
10028 case CLZ:
10029 mips32_op = OPC_CLZ;
10030 do_cl:
10031 check_insn(env, ctx, ISA_MIPS32);
10032 gen_cl(ctx, mips32_op, rt, rs);
10033 break;
10034 case RDHWR:
10035 gen_rdhwr(env, ctx, rt, rs);
10036 break;
10037 case WSBH:
10038 gen_bshfl(ctx, OPC_WSBH, rs, rt);
10039 break;
10040 case MULT:
10041 mips32_op = OPC_MULT;
10042 goto do_muldiv;
10043 case MULTU:
10044 mips32_op = OPC_MULTU;
10045 goto do_muldiv;
10046 case DIV:
10047 mips32_op = OPC_DIV;
10048 goto do_muldiv;
10049 case DIVU:
10050 mips32_op = OPC_DIVU;
10051 goto do_muldiv;
10052 case MADD:
10053 mips32_op = OPC_MADD;
10054 goto do_muldiv;
10055 case MADDU:
10056 mips32_op = OPC_MADDU;
10057 goto do_muldiv;
10058 case MSUB:
10059 mips32_op = OPC_MSUB;
10060 goto do_muldiv;
10061 case MSUBU:
10062 mips32_op = OPC_MSUBU;
10063 do_muldiv:
10064 check_insn(env, ctx, ISA_MIPS32);
10065 gen_muldiv(ctx, mips32_op, rs, rt);
10066 break;
10067 default:
10068 goto pool32axf_invalid;
10070 break;
10071 case 0x34:
10072 switch (minor) {
10073 case MFC2:
10074 case MTC2:
10075 case MFHC2:
10076 case MTHC2:
10077 case CFC2:
10078 case CTC2:
10079 generate_exception_err(ctx, EXCP_CpU, 2);
10080 break;
10081 default:
10082 goto pool32axf_invalid;
10084 break;
10085 case 0x3c:
10086 switch (minor) {
10087 case JALR:
10088 case JALR_HB:
10089 gen_compute_branch (ctx, OPC_JALR, 4, rs, rt, 0);
10090 *is_branch = 1;
10091 break;
10092 case JALRS:
10093 case JALRS_HB:
10094 gen_compute_branch (ctx, OPC_JALRS, 4, rs, rt, 0);
10095 *is_branch = 1;
10096 break;
10097 default:
10098 goto pool32axf_invalid;
10100 break;
10101 case 0x05:
10102 switch (minor) {
10103 case RDPGPR:
10104 check_insn(env, ctx, ISA_MIPS32R2);
10105 gen_load_srsgpr(rt, rs);
10106 break;
10107 case WRPGPR:
10108 check_insn(env, ctx, ISA_MIPS32R2);
10109 gen_store_srsgpr(rt, rs);
10110 break;
10111 default:
10112 goto pool32axf_invalid;
10114 break;
10115 #ifndef CONFIG_USER_ONLY
10116 case 0x0d:
10117 switch (minor) {
10118 case TLBP:
10119 mips32_op = OPC_TLBP;
10120 goto do_cp0;
10121 case TLBR:
10122 mips32_op = OPC_TLBR;
10123 goto do_cp0;
10124 case TLBWI:
10125 mips32_op = OPC_TLBWI;
10126 goto do_cp0;
10127 case TLBWR:
10128 mips32_op = OPC_TLBWR;
10129 goto do_cp0;
10130 case WAIT:
10131 mips32_op = OPC_WAIT;
10132 goto do_cp0;
10133 case DERET:
10134 mips32_op = OPC_DERET;
10135 goto do_cp0;
10136 case ERET:
10137 mips32_op = OPC_ERET;
10138 do_cp0:
10139 gen_cp0(env, ctx, mips32_op, rt, rs);
10140 break;
10141 default:
10142 goto pool32axf_invalid;
10144 break;
10145 case 0x1d:
10146 switch (minor) {
10147 case DI:
10149 TCGv t0 = tcg_temp_new();
10151 save_cpu_state(ctx, 1);
10152 gen_helper_di(t0);
10153 gen_store_gpr(t0, rs);
10154 /* Stop translation as we may have switched the execution mode */
10155 ctx->bstate = BS_STOP;
10156 tcg_temp_free(t0);
10158 break;
10159 case EI:
10161 TCGv t0 = tcg_temp_new();
10163 save_cpu_state(ctx, 1);
10164 gen_helper_ei(t0);
10165 gen_store_gpr(t0, rs);
10166 /* Stop translation as we may have switched the execution mode */
10167 ctx->bstate = BS_STOP;
10168 tcg_temp_free(t0);
10170 break;
10171 default:
10172 goto pool32axf_invalid;
10174 break;
10175 #endif
10176 case 0x2d:
10177 switch (minor) {
10178 case SYNC:
10179 /* NOP */
10180 break;
10181 case SYSCALL:
10182 generate_exception(ctx, EXCP_SYSCALL);
10183 ctx->bstate = BS_STOP;
10184 break;
10185 case SDBBP:
10186 check_insn(env, ctx, ISA_MIPS32);
10187 if (!(ctx->hflags & MIPS_HFLAG_DM)) {
10188 generate_exception(ctx, EXCP_DBp);
10189 } else {
10190 generate_exception(ctx, EXCP_DBp);
10192 break;
10193 default:
10194 goto pool32axf_invalid;
10196 break;
10197 case 0x35:
10198 switch (minor) {
10199 case MFHI32:
10200 gen_HILO(ctx, OPC_MFHI, rs);
10201 break;
10202 case MFLO32:
10203 gen_HILO(ctx, OPC_MFLO, rs);
10204 break;
10205 case MTHI32:
10206 gen_HILO(ctx, OPC_MTHI, rs);
10207 break;
10208 case MTLO32:
10209 gen_HILO(ctx, OPC_MTLO, rs);
10210 break;
10211 default:
10212 goto pool32axf_invalid;
10214 break;
10215 default:
10216 pool32axf_invalid:
10217 MIPS_INVAL("pool32axf");
10218 generate_exception(ctx, EXCP_RI);
10219 break;
10223 /* Values for microMIPS fmt field. Variable-width, depending on which
10224 formats the instruction supports. */
10226 enum {
10227 FMT_SD_S = 0,
10228 FMT_SD_D = 1,
10230 FMT_SDPS_S = 0,
10231 FMT_SDPS_D = 1,
10232 FMT_SDPS_PS = 2,
10234 FMT_SWL_S = 0,
10235 FMT_SWL_W = 1,
10236 FMT_SWL_L = 2,
10238 FMT_DWL_D = 0,
10239 FMT_DWL_W = 1,
10240 FMT_DWL_L = 2
10243 static void gen_pool32fxf (CPUState *env, DisasContext *ctx, int rt, int rs)
10245 int extension = (ctx->opcode >> 6) & 0x3ff;
10246 uint32_t mips32_op;
10248 #define FLOAT_1BIT_FMT(opc, fmt) (fmt << 8) | opc
10249 #define FLOAT_2BIT_FMT(opc, fmt) (fmt << 7) | opc
10250 #define COND_FLOAT_MOV(opc, cond) (cond << 7) | opc
10252 switch (extension) {
10253 case FLOAT_1BIT_FMT(CFC1, 0):
10254 mips32_op = OPC_CFC1;
10255 goto do_cp1;
10256 case FLOAT_1BIT_FMT(CTC1, 0):
10257 mips32_op = OPC_CTC1;
10258 goto do_cp1;
10259 case FLOAT_1BIT_FMT(MFC1, 0):
10260 mips32_op = OPC_MFC1;
10261 goto do_cp1;
10262 case FLOAT_1BIT_FMT(MTC1, 0):
10263 mips32_op = OPC_MTC1;
10264 goto do_cp1;
10265 case FLOAT_1BIT_FMT(MFHC1, 0):
10266 mips32_op = OPC_MFHC1;
10267 goto do_cp1;
10268 case FLOAT_1BIT_FMT(MTHC1, 0):
10269 mips32_op = OPC_MTHC1;
10270 do_cp1:
10271 gen_cp1(ctx, mips32_op, rt, rs);
10272 break;
10274 /* Reciprocal square root */
10275 case FLOAT_1BIT_FMT(RSQRT_FMT, FMT_SD_S):
10276 mips32_op = OPC_RSQRT_S;
10277 goto do_unaryfp;
10278 case FLOAT_1BIT_FMT(RSQRT_FMT, FMT_SD_D):
10279 mips32_op = OPC_RSQRT_D;
10280 goto do_unaryfp;
10282 /* Square root */
10283 case FLOAT_1BIT_FMT(SQRT_FMT, FMT_SD_S):
10284 mips32_op = OPC_SQRT_S;
10285 goto do_unaryfp;
10286 case FLOAT_1BIT_FMT(SQRT_FMT, FMT_SD_D):
10287 mips32_op = OPC_SQRT_D;
10288 goto do_unaryfp;
10290 /* Reciprocal */
10291 case FLOAT_1BIT_FMT(RECIP_FMT, FMT_SD_S):
10292 mips32_op = OPC_RECIP_S;
10293 goto do_unaryfp;
10294 case FLOAT_1BIT_FMT(RECIP_FMT, FMT_SD_D):
10295 mips32_op = OPC_RECIP_D;
10296 goto do_unaryfp;
10298 /* Floor */
10299 case FLOAT_1BIT_FMT(FLOOR_L, FMT_SD_S):
10300 mips32_op = OPC_FLOOR_L_S;
10301 goto do_unaryfp;
10302 case FLOAT_1BIT_FMT(FLOOR_L, FMT_SD_D):
10303 mips32_op = OPC_FLOOR_L_D;
10304 goto do_unaryfp;
10305 case FLOAT_1BIT_FMT(FLOOR_W, FMT_SD_S):
10306 mips32_op = OPC_FLOOR_W_S;
10307 goto do_unaryfp;
10308 case FLOAT_1BIT_FMT(FLOOR_W, FMT_SD_D):
10309 mips32_op = OPC_FLOOR_W_D;
10310 goto do_unaryfp;
10312 /* Ceiling */
10313 case FLOAT_1BIT_FMT(CEIL_L, FMT_SD_S):
10314 mips32_op = OPC_CEIL_L_S;
10315 goto do_unaryfp;
10316 case FLOAT_1BIT_FMT(CEIL_L, FMT_SD_D):
10317 mips32_op = OPC_CEIL_L_D;
10318 goto do_unaryfp;
10319 case FLOAT_1BIT_FMT(CEIL_W, FMT_SD_S):
10320 mips32_op = OPC_CEIL_W_S;
10321 goto do_unaryfp;
10322 case FLOAT_1BIT_FMT(CEIL_W, FMT_SD_D):
10323 mips32_op = OPC_CEIL_W_D;
10324 goto do_unaryfp;
10326 /* Truncation */
10327 case FLOAT_1BIT_FMT(TRUNC_L, FMT_SD_S):
10328 mips32_op = OPC_TRUNC_L_S;
10329 goto do_unaryfp;
10330 case FLOAT_1BIT_FMT(TRUNC_L, FMT_SD_D):
10331 mips32_op = OPC_TRUNC_L_D;
10332 goto do_unaryfp;
10333 case FLOAT_1BIT_FMT(TRUNC_W, FMT_SD_S):
10334 mips32_op = OPC_TRUNC_W_S;
10335 goto do_unaryfp;
10336 case FLOAT_1BIT_FMT(TRUNC_W, FMT_SD_D):
10337 mips32_op = OPC_TRUNC_W_D;
10338 goto do_unaryfp;
10340 /* Round */
10341 case FLOAT_1BIT_FMT(ROUND_L, FMT_SD_S):
10342 mips32_op = OPC_ROUND_L_S;
10343 goto do_unaryfp;
10344 case FLOAT_1BIT_FMT(ROUND_L, FMT_SD_D):
10345 mips32_op = OPC_ROUND_L_D;
10346 goto do_unaryfp;
10347 case FLOAT_1BIT_FMT(ROUND_W, FMT_SD_S):
10348 mips32_op = OPC_ROUND_W_S;
10349 goto do_unaryfp;
10350 case FLOAT_1BIT_FMT(ROUND_W, FMT_SD_D):
10351 mips32_op = OPC_ROUND_W_D;
10352 goto do_unaryfp;
10354 /* Integer to floating-point conversion */
10355 case FLOAT_1BIT_FMT(CVT_L, FMT_SD_S):
10356 mips32_op = OPC_CVT_L_S;
10357 goto do_unaryfp;
10358 case FLOAT_1BIT_FMT(CVT_L, FMT_SD_D):
10359 mips32_op = OPC_CVT_L_D;
10360 goto do_unaryfp;
10361 case FLOAT_1BIT_FMT(CVT_W, FMT_SD_S):
10362 mips32_op = OPC_CVT_W_S;
10363 goto do_unaryfp;
10364 case FLOAT_1BIT_FMT(CVT_W, FMT_SD_D):
10365 mips32_op = OPC_CVT_W_D;
10366 goto do_unaryfp;
10368 /* Paired-foo conversions */
10369 case FLOAT_1BIT_FMT(CVT_S_PL, 0):
10370 mips32_op = OPC_CVT_S_PL;
10371 goto do_unaryfp;
10372 case FLOAT_1BIT_FMT(CVT_S_PU, 0):
10373 mips32_op = OPC_CVT_S_PU;
10374 goto do_unaryfp;
10375 case FLOAT_1BIT_FMT(CVT_PW_PS, 0):
10376 mips32_op = OPC_CVT_PW_PS;
10377 goto do_unaryfp;
10378 case FLOAT_1BIT_FMT(CVT_PS_PW, 0):
10379 mips32_op = OPC_CVT_PS_PW;
10380 goto do_unaryfp;
10382 /* Floating-point moves */
10383 case FLOAT_2BIT_FMT(MOV_FMT, FMT_SDPS_S):
10384 mips32_op = OPC_MOV_S;
10385 goto do_unaryfp;
10386 case FLOAT_2BIT_FMT(MOV_FMT, FMT_SDPS_D):
10387 mips32_op = OPC_MOV_D;
10388 goto do_unaryfp;
10389 case FLOAT_2BIT_FMT(MOV_FMT, FMT_SDPS_PS):
10390 mips32_op = OPC_MOV_PS;
10391 goto do_unaryfp;
10393 /* Absolute value */
10394 case FLOAT_2BIT_FMT(ABS_FMT, FMT_SDPS_S):
10395 mips32_op = OPC_ABS_S;
10396 goto do_unaryfp;
10397 case FLOAT_2BIT_FMT(ABS_FMT, FMT_SDPS_D):
10398 mips32_op = OPC_ABS_D;
10399 goto do_unaryfp;
10400 case FLOAT_2BIT_FMT(ABS_FMT, FMT_SDPS_PS):
10401 mips32_op = OPC_ABS_PS;
10402 goto do_unaryfp;
10404 /* Negation */
10405 case FLOAT_2BIT_FMT(NEG_FMT, FMT_SDPS_S):
10406 mips32_op = OPC_NEG_S;
10407 goto do_unaryfp;
10408 case FLOAT_2BIT_FMT(NEG_FMT, FMT_SDPS_D):
10409 mips32_op = OPC_NEG_D;
10410 goto do_unaryfp;
10411 case FLOAT_2BIT_FMT(NEG_FMT, FMT_SDPS_PS):
10412 mips32_op = OPC_NEG_PS;
10413 goto do_unaryfp;
10415 /* Reciprocal square root step */
10416 case FLOAT_2BIT_FMT(RSQRT1_FMT, FMT_SDPS_S):
10417 mips32_op = OPC_RSQRT1_S;
10418 goto do_unaryfp;
10419 case FLOAT_2BIT_FMT(RSQRT1_FMT, FMT_SDPS_D):
10420 mips32_op = OPC_RSQRT1_D;
10421 goto do_unaryfp;
10422 case FLOAT_2BIT_FMT(RSQRT1_FMT, FMT_SDPS_PS):
10423 mips32_op = OPC_RSQRT1_PS;
10424 goto do_unaryfp;
10426 /* Reciprocal step */
10427 case FLOAT_2BIT_FMT(RECIP1_FMT, FMT_SDPS_S):
10428 mips32_op = OPC_RECIP1_S;
10429 goto do_unaryfp;
10430 case FLOAT_2BIT_FMT(RECIP1_FMT, FMT_SDPS_D):
10431 mips32_op = OPC_RECIP1_S;
10432 goto do_unaryfp;
10433 case FLOAT_2BIT_FMT(RECIP1_FMT, FMT_SDPS_PS):
10434 mips32_op = OPC_RECIP1_PS;
10435 goto do_unaryfp;
10437 /* Conversions from double */
10438 case FLOAT_2BIT_FMT(CVT_D, FMT_SWL_S):
10439 mips32_op = OPC_CVT_D_S;
10440 goto do_unaryfp;
10441 case FLOAT_2BIT_FMT(CVT_D, FMT_SWL_W):
10442 mips32_op = OPC_CVT_D_W;
10443 goto do_unaryfp;
10444 case FLOAT_2BIT_FMT(CVT_D, FMT_SWL_L):
10445 mips32_op = OPC_CVT_D_L;
10446 goto do_unaryfp;
10448 /* Conversions from single */
10449 case FLOAT_2BIT_FMT(CVT_S, FMT_DWL_D):
10450 mips32_op = OPC_CVT_S_D;
10451 goto do_unaryfp;
10452 case FLOAT_2BIT_FMT(CVT_S, FMT_DWL_W):
10453 mips32_op = OPC_CVT_S_W;
10454 goto do_unaryfp;
10455 case FLOAT_2BIT_FMT(CVT_S, FMT_DWL_L):
10456 mips32_op = OPC_CVT_S_L;
10457 do_unaryfp:
10458 gen_farith(ctx, mips32_op, -1, rs, rt, 0);
10459 break;
10461 /* Conditional moves on floating-point codes */
10462 case COND_FLOAT_MOV(MOVT, 0):
10463 case COND_FLOAT_MOV(MOVT, 1):
10464 case COND_FLOAT_MOV(MOVT, 2):
10465 case COND_FLOAT_MOV(MOVT, 3):
10466 case COND_FLOAT_MOV(MOVT, 4):
10467 case COND_FLOAT_MOV(MOVT, 5):
10468 case COND_FLOAT_MOV(MOVT, 6):
10469 case COND_FLOAT_MOV(MOVT, 7):
10470 gen_movci(ctx, rt, rs, (ctx->opcode >> 13) & 0x7, 1);
10471 break;
10472 case COND_FLOAT_MOV(MOVF, 0):
10473 case COND_FLOAT_MOV(MOVF, 1):
10474 case COND_FLOAT_MOV(MOVF, 2):
10475 case COND_FLOAT_MOV(MOVF, 3):
10476 case COND_FLOAT_MOV(MOVF, 4):
10477 case COND_FLOAT_MOV(MOVF, 5):
10478 case COND_FLOAT_MOV(MOVF, 6):
10479 case COND_FLOAT_MOV(MOVF, 7):
10480 gen_movci(ctx, rt, rs, (ctx->opcode >> 13) & 0x7, 0);
10481 break;
10482 default:
10483 MIPS_INVAL("pool32fxf");
10484 generate_exception(ctx, EXCP_RI);
10485 break;
10489 static void decode_micromips32_opc (CPUState *env, DisasContext *ctx,
10490 uint16_t insn_hw1, int *is_branch)
10492 int32_t offset;
10493 uint16_t insn;
10494 int rt, rs, rd, rr;
10495 int16_t imm;
10496 uint32_t op, minor, mips32_op;
10497 uint32_t cond, fmt, cc;
10499 insn = lduw_code(ctx->pc + 2);
10500 ctx->opcode = (ctx->opcode << 16) | insn;
10502 rt = (ctx->opcode >> 21) & 0x1f;
10503 rs = (ctx->opcode >> 16) & 0x1f;
10504 rd = (ctx->opcode >> 11) & 0x1f;
10505 rr = (ctx->opcode >> 6) & 0x1f;
10506 imm = (int16_t) ctx->opcode;
10508 op = (ctx->opcode >> 26) & 0x3f;
10509 switch (op) {
10510 case POOL32A:
10511 minor = ctx->opcode & 0x3f;
10512 switch (minor) {
10513 case 0x00:
10514 minor = (ctx->opcode >> 6) & 0xf;
10515 switch (minor) {
10516 case SLL32:
10517 mips32_op = OPC_SLL;
10518 goto do_shifti;
10519 case SRA:
10520 mips32_op = OPC_SRA;
10521 goto do_shifti;
10522 case SRL32:
10523 mips32_op = OPC_SRL;
10524 goto do_shifti;
10525 case ROTR:
10526 mips32_op = OPC_ROTR;
10527 do_shifti:
10528 gen_shift_imm(env, ctx, mips32_op, rt, rs, rd);
10529 break;
10530 default:
10531 goto pool32a_invalid;
10533 break;
10534 case 0x10:
10535 minor = (ctx->opcode >> 6) & 0xf;
10536 switch (minor) {
10537 /* Arithmetic */
10538 case ADD:
10539 mips32_op = OPC_ADD;
10540 goto do_arith;
10541 case ADDU32:
10542 mips32_op = OPC_ADDU;
10543 goto do_arith;
10544 case SUB:
10545 mips32_op = OPC_SUB;
10546 goto do_arith;
10547 case SUBU32:
10548 mips32_op = OPC_SUBU;
10549 goto do_arith;
10550 case MUL:
10551 mips32_op = OPC_MUL;
10552 do_arith:
10553 gen_arith(env, ctx, mips32_op, rd, rs, rt);
10554 break;
10555 /* Shifts */
10556 case SLLV:
10557 mips32_op = OPC_SLLV;
10558 goto do_shift;
10559 case SRLV:
10560 mips32_op = OPC_SRLV;
10561 goto do_shift;
10562 case SRAV:
10563 mips32_op = OPC_SRAV;
10564 goto do_shift;
10565 case ROTRV:
10566 mips32_op = OPC_ROTRV;
10567 do_shift:
10568 gen_shift(env, ctx, mips32_op, rd, rs, rt);
10569 break;
10570 /* Logical operations */
10571 case AND:
10572 mips32_op = OPC_AND;
10573 goto do_logic;
10574 case OR32:
10575 mips32_op = OPC_OR;
10576 goto do_logic;
10577 case NOR:
10578 mips32_op = OPC_NOR;
10579 goto do_logic;
10580 case XOR32:
10581 mips32_op = OPC_XOR;
10582 do_logic:
10583 gen_logic(env, mips32_op, rd, rs, rt);
10584 break;
10585 /* Set less than */
10586 case SLT:
10587 mips32_op = OPC_SLT;
10588 goto do_slt;
10589 case SLTU:
10590 mips32_op = OPC_SLTU;
10591 do_slt:
10592 gen_slt(env, mips32_op, rd, rs, rt);
10593 break;
10594 default:
10595 goto pool32a_invalid;
10597 break;
10598 case 0x18:
10599 minor = (ctx->opcode >> 6) & 0xf;
10600 switch (minor) {
10601 /* Conditional moves */
10602 case MOVN:
10603 mips32_op = OPC_MOVN;
10604 goto do_cmov;
10605 case MOVZ:
10606 mips32_op = OPC_MOVZ;
10607 do_cmov:
10608 gen_cond_move(env, mips32_op, rd, rs, rt);
10609 break;
10610 case LWXS:
10611 gen_ldxs(ctx, rs, rt, rd);
10612 break;
10613 default:
10614 goto pool32a_invalid;
10616 break;
10617 case INS:
10618 gen_bitops(ctx, OPC_INS, rt, rs, rr, rd);
10619 return;
10620 case EXT:
10621 gen_bitops(ctx, OPC_EXT, rt, rs, rr, rd);
10622 return;
10623 case POOL32AXF:
10624 gen_pool32axf(env, ctx, rt, rs, is_branch);
10625 break;
10626 case 0x07:
10627 generate_exception(ctx, EXCP_BREAK);
10628 break;
10629 default:
10630 pool32a_invalid:
10631 MIPS_INVAL("pool32a");
10632 generate_exception(ctx, EXCP_RI);
10633 break;
10635 break;
10636 case POOL32B:
10637 minor = (ctx->opcode >> 12) & 0xf;
10638 switch (minor) {
10639 case CACHE:
10640 /* Treat as no-op. */
10641 break;
10642 case LWC2:
10643 case SWC2:
10644 /* COP2: Not implemented. */
10645 generate_exception_err(ctx, EXCP_CpU, 2);
10646 break;
10647 case LWP:
10648 case SWP:
10649 #ifdef TARGET_MIPS64
10650 case LDP:
10651 case SDP:
10652 #endif
10653 gen_ldst_pair(ctx, minor, rt, rs, SIMM(ctx->opcode, 0, 12));
10654 break;
10655 case LWM32:
10656 case SWM32:
10657 #ifdef TARGET_MIPS64
10658 case LDM:
10659 case SDM:
10660 #endif
10661 gen_ldst_multiple(ctx, minor, rt, rs, SIMM(ctx->opcode, 0, 12));
10662 break;
10663 default:
10664 MIPS_INVAL("pool32b");
10665 generate_exception(ctx, EXCP_RI);
10666 break;
10668 break;
10669 case POOL32F:
10670 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
10671 minor = ctx->opcode & 0x3f;
10672 check_cp1_enabled(ctx);
10673 switch (minor) {
10674 case ALNV_PS:
10675 mips32_op = OPC_ALNV_PS;
10676 goto do_madd;
10677 case MADD_S:
10678 mips32_op = OPC_MADD_S;
10679 goto do_madd;
10680 case MADD_D:
10681 mips32_op = OPC_MADD_D;
10682 goto do_madd;
10683 case MADD_PS:
10684 mips32_op = OPC_MADD_PS;
10685 goto do_madd;
10686 case MSUB_S:
10687 mips32_op = OPC_MSUB_S;
10688 goto do_madd;
10689 case MSUB_D:
10690 mips32_op = OPC_MSUB_D;
10691 goto do_madd;
10692 case MSUB_PS:
10693 mips32_op = OPC_MSUB_PS;
10694 goto do_madd;
10695 case NMADD_S:
10696 mips32_op = OPC_NMADD_S;
10697 goto do_madd;
10698 case NMADD_D:
10699 mips32_op = OPC_NMADD_D;
10700 goto do_madd;
10701 case NMADD_PS:
10702 mips32_op = OPC_NMADD_PS;
10703 goto do_madd;
10704 case NMSUB_S:
10705 mips32_op = OPC_NMSUB_S;
10706 goto do_madd;
10707 case NMSUB_D:
10708 mips32_op = OPC_NMSUB_D;
10709 goto do_madd;
10710 case NMSUB_PS:
10711 mips32_op = OPC_NMSUB_PS;
10712 do_madd:
10713 gen_flt3_arith(ctx, mips32_op, rd, rr, rs, rt);
10714 break;
10715 case CABS_COND_FMT:
10716 cond = (ctx->opcode >> 6) & 0xf;
10717 cc = (ctx->opcode >> 13) & 0x7;
10718 fmt = (ctx->opcode >> 10) & 0x3;
10719 switch (fmt) {
10720 case 0x0:
10721 gen_cmpabs_s(ctx, cond, rt, rs, cc);
10722 break;
10723 case 0x1:
10724 gen_cmpabs_d(ctx, cond, rt, rs, cc);
10725 break;
10726 case 0x2:
10727 gen_cmpabs_ps(ctx, cond, rt, rs, cc);
10728 break;
10729 default:
10730 goto pool32f_invalid;
10732 break;
10733 case C_COND_FMT:
10734 cond = (ctx->opcode >> 6) & 0xf;
10735 cc = (ctx->opcode >> 13) & 0x7;
10736 fmt = (ctx->opcode >> 10) & 0x3;
10737 switch (fmt) {
10738 case 0x0:
10739 gen_cmp_s(ctx, cond, rt, rs, cc);
10740 break;
10741 case 0x1:
10742 gen_cmp_d(ctx, cond, rt, rs, cc);
10743 break;
10744 case 0x2:
10745 gen_cmp_ps(ctx, cond, rt, rs, cc);
10746 break;
10747 default:
10748 goto pool32f_invalid;
10750 break;
10751 case POOL32FXF:
10752 gen_pool32fxf(env, ctx, rt, rs);
10753 break;
10754 case 0x00:
10755 /* PLL foo */
10756 switch ((ctx->opcode >> 6) & 0x7) {
10757 case PLL_PS:
10758 mips32_op = OPC_PLL_PS;
10759 goto do_ps;
10760 case PLU_PS:
10761 mips32_op = OPC_PLU_PS;
10762 goto do_ps;
10763 case PUL_PS:
10764 mips32_op = OPC_PUL_PS;
10765 goto do_ps;
10766 case PUU_PS:
10767 mips32_op = OPC_PUU_PS;
10768 goto do_ps;
10769 case CVT_PS_S:
10770 mips32_op = OPC_CVT_PS_S;
10771 do_ps:
10772 gen_farith(ctx, mips32_op, rt, rs, rd, 0);
10773 break;
10774 default:
10775 goto pool32f_invalid;
10777 break;
10778 case 0x08:
10779 /* [LS][WDU]XC1 */
10780 switch ((ctx->opcode >> 6) & 0x7) {
10781 case LWXC1:
10782 mips32_op = OPC_LWXC1;
10783 goto do_ldst_cp1;
10784 case SWXC1:
10785 mips32_op = OPC_SWXC1;
10786 goto do_ldst_cp1;
10787 case LDXC1:
10788 mips32_op = OPC_LDXC1;
10789 goto do_ldst_cp1;
10790 case SDXC1:
10791 mips32_op = OPC_SDXC1;
10792 goto do_ldst_cp1;
10793 case LUXC1:
10794 mips32_op = OPC_LUXC1;
10795 goto do_ldst_cp1;
10796 case SUXC1:
10797 mips32_op = OPC_SUXC1;
10798 do_ldst_cp1:
10799 gen_flt3_ldst(ctx, mips32_op, rd, rd, rt, rs);
10800 break;
10801 default:
10802 goto pool32f_invalid;
10804 break;
10805 case 0x18:
10806 /* 3D insns */
10807 fmt = (ctx->opcode >> 9) & 0x3;
10808 switch ((ctx->opcode >> 6) & 0x7) {
10809 case RSQRT2_FMT:
10810 switch (fmt) {
10811 case FMT_SDPS_S:
10812 mips32_op = OPC_RSQRT2_S;
10813 goto do_3d;
10814 case FMT_SDPS_D:
10815 mips32_op = OPC_RSQRT2_D;
10816 goto do_3d;
10817 case FMT_SDPS_PS:
10818 mips32_op = OPC_RSQRT2_PS;
10819 goto do_3d;
10820 default:
10821 goto pool32f_invalid;
10823 break;
10824 case RECIP2_FMT:
10825 switch (fmt) {
10826 case FMT_SDPS_S:
10827 mips32_op = OPC_RECIP2_S;
10828 goto do_3d;
10829 case FMT_SDPS_D:
10830 mips32_op = OPC_RECIP2_D;
10831 goto do_3d;
10832 case FMT_SDPS_PS:
10833 mips32_op = OPC_RECIP2_PS;
10834 goto do_3d;
10835 default:
10836 goto pool32f_invalid;
10838 break;
10839 case ADDR_PS:
10840 mips32_op = OPC_ADDR_PS;
10841 goto do_3d;
10842 case MULR_PS:
10843 mips32_op = OPC_MULR_PS;
10844 do_3d:
10845 gen_farith(ctx, mips32_op, rt, rs, rd, 0);
10846 break;
10847 default:
10848 goto pool32f_invalid;
10850 break;
10851 case 0x20:
10852 /* MOV[FT].fmt and PREFX */
10853 cc = (ctx->opcode >> 13) & 0x7;
10854 fmt = (ctx->opcode >> 9) & 0x3;
10855 switch ((ctx->opcode >> 6) & 0x7) {
10856 case MOVF_FMT:
10857 switch (fmt) {
10858 case FMT_SDPS_S:
10859 gen_movcf_s(rs, rt, cc, 0);
10860 break;
10861 case FMT_SDPS_D:
10862 gen_movcf_d(ctx, rs, rt, cc, 0);
10863 break;
10864 case FMT_SDPS_PS:
10865 gen_movcf_ps(rs, rt, cc, 0);
10866 break;
10867 default:
10868 goto pool32f_invalid;
10870 break;
10871 case MOVT_FMT:
10872 switch (fmt) {
10873 case FMT_SDPS_S:
10874 gen_movcf_s(rs, rt, cc, 1);
10875 break;
10876 case FMT_SDPS_D:
10877 gen_movcf_d(ctx, rs, rt, cc, 1);
10878 break;
10879 case FMT_SDPS_PS:
10880 gen_movcf_ps(rs, rt, cc, 1);
10881 break;
10882 default:
10883 goto pool32f_invalid;
10885 break;
10886 case PREFX:
10887 break;
10888 default:
10889 goto pool32f_invalid;
10891 break;
10892 #define FINSN_3ARG_SDPS(prfx) \
10893 switch ((ctx->opcode >> 8) & 0x3) { \
10894 case FMT_SDPS_S: \
10895 mips32_op = OPC_##prfx##_S; \
10896 goto do_fpop; \
10897 case FMT_SDPS_D: \
10898 mips32_op = OPC_##prfx##_D; \
10899 goto do_fpop; \
10900 case FMT_SDPS_PS: \
10901 mips32_op = OPC_##prfx##_PS; \
10902 goto do_fpop; \
10903 default: \
10904 goto pool32f_invalid; \
10906 case 0x30:
10907 /* regular FP ops */
10908 switch ((ctx->opcode >> 6) & 0x3) {
10909 case ADD_FMT:
10910 FINSN_3ARG_SDPS(ADD);
10911 break;
10912 case SUB_FMT:
10913 FINSN_3ARG_SDPS(SUB);
10914 break;
10915 case MUL_FMT:
10916 FINSN_3ARG_SDPS(MUL);
10917 break;
10918 case DIV_FMT:
10919 fmt = (ctx->opcode >> 8) & 0x3;
10920 if (fmt == 1) {
10921 mips32_op = OPC_DIV_D;
10922 } else if (fmt == 0) {
10923 mips32_op = OPC_DIV_S;
10924 } else {
10925 goto pool32f_invalid;
10927 goto do_fpop;
10928 default:
10929 goto pool32f_invalid;
10931 break;
10932 case 0x38:
10933 /* cmovs */
10934 switch ((ctx->opcode >> 6) & 0x3) {
10935 case MOVN_FMT:
10936 FINSN_3ARG_SDPS(MOVN);
10937 break;
10938 case MOVZ_FMT:
10939 FINSN_3ARG_SDPS(MOVZ);
10940 break;
10941 default:
10942 goto pool32f_invalid;
10944 break;
10945 do_fpop:
10946 gen_farith(ctx, mips32_op, rt, rs, rd, 0);
10947 break;
10948 default:
10949 pool32f_invalid:
10950 MIPS_INVAL("pool32f");
10951 generate_exception(ctx, EXCP_RI);
10952 break;
10954 } else {
10955 generate_exception_err(ctx, EXCP_CpU, 1);
10957 break;
10958 case POOL32I:
10959 minor = (ctx->opcode >> 21) & 0x1f;
10960 switch (minor) {
10961 case BLTZ:
10962 mips32_op = OPC_BLTZ;
10963 goto do_branch;
10964 case BLTZAL:
10965 mips32_op = OPC_BLTZAL;
10966 goto do_branch;
10967 case BLTZALS:
10968 mips32_op = OPC_BLTZALS;
10969 goto do_branch;
10970 case BGEZ:
10971 mips32_op = OPC_BGEZ;
10972 goto do_branch;
10973 case BGEZAL:
10974 mips32_op = OPC_BGEZAL;
10975 goto do_branch;
10976 case BGEZALS:
10977 mips32_op = OPC_BGEZALS;
10978 goto do_branch;
10979 case BLEZ:
10980 mips32_op = OPC_BLEZ;
10981 goto do_branch;
10982 case BGTZ:
10983 mips32_op = OPC_BGTZ;
10984 do_branch:
10985 gen_compute_branch(ctx, mips32_op, 4, rs, -1, imm << 1);
10986 *is_branch = 1;
10987 break;
10989 /* Traps */
10990 case TLTI:
10991 mips32_op = OPC_TLTI;
10992 goto do_trapi;
10993 case TGEI:
10994 mips32_op = OPC_TGEI;
10995 goto do_trapi;
10996 case TLTIU:
10997 mips32_op = OPC_TLTIU;
10998 goto do_trapi;
10999 case TGEIU:
11000 mips32_op = OPC_TGEIU;
11001 goto do_trapi;
11002 case TNEI:
11003 mips32_op = OPC_TNEI;
11004 goto do_trapi;
11005 case TEQI:
11006 mips32_op = OPC_TEQI;
11007 do_trapi:
11008 gen_trap(ctx, mips32_op, rs, -1, imm);
11009 break;
11011 case BNEZC:
11012 case BEQZC:
11013 gen_compute_branch(ctx, minor == BNEZC ? OPC_BNE : OPC_BEQ,
11014 4, rs, 0, imm << 1);
11015 /* Compact branches don't have a delay slot, so just let
11016 the normal delay slot handling take us to the branch
11017 target. */
11018 break;
11019 case LUI:
11020 gen_logic_imm(env, OPC_LUI, rs, -1, imm);
11021 break;
11022 case SYNCI:
11023 break;
11024 case BC2F:
11025 case BC2T:
11026 /* COP2: Not implemented. */
11027 generate_exception_err(ctx, EXCP_CpU, 2);
11028 break;
11029 case BC1F:
11030 mips32_op = (ctx->opcode & (1 << 16)) ? OPC_BC1FANY2 : OPC_BC1F;
11031 goto do_cp1branch;
11032 case BC1T:
11033 mips32_op = (ctx->opcode & (1 << 16)) ? OPC_BC1TANY2 : OPC_BC1T;
11034 goto do_cp1branch;
11035 case BC1ANY4F:
11036 mips32_op = OPC_BC1FANY4;
11037 goto do_cp1mips3d;
11038 case BC1ANY4T:
11039 mips32_op = OPC_BC1TANY4;
11040 do_cp1mips3d:
11041 check_cop1x(ctx);
11042 check_insn(env, ctx, ASE_MIPS3D);
11043 /* Fall through */
11044 do_cp1branch:
11045 gen_compute_branch1(env, ctx, mips32_op,
11046 (ctx->opcode >> 18) & 0x7, imm << 1);
11047 *is_branch = 1;
11048 break;
11049 case BPOSGE64:
11050 case BPOSGE32:
11051 /* MIPS DSP: not implemented */
11052 /* Fall through */
11053 default:
11054 MIPS_INVAL("pool32i");
11055 generate_exception(ctx, EXCP_RI);
11056 break;
11058 break;
11059 case POOL32C:
11060 minor = (ctx->opcode >> 12) & 0xf;
11061 switch (minor) {
11062 case LWL:
11063 mips32_op = OPC_LWL;
11064 goto do_ld_lr;
11065 case SWL:
11066 mips32_op = OPC_SWL;
11067 goto do_st_lr;
11068 case LWR:
11069 mips32_op = OPC_LWR;
11070 goto do_ld_lr;
11071 case SWR:
11072 mips32_op = OPC_SWR;
11073 goto do_st_lr;
11074 #if defined(TARGET_MIPS64)
11075 case LDL:
11076 mips32_op = OPC_LDL;
11077 goto do_ld_lr;
11078 case SDL:
11079 mips32_op = OPC_SDL;
11080 goto do_st_lr;
11081 case LDR:
11082 mips32_op = OPC_LDR;
11083 goto do_ld_lr;
11084 case SDR:
11085 mips32_op = OPC_SDR;
11086 goto do_st_lr;
11087 case LWU:
11088 mips32_op = OPC_LWU;
11089 goto do_ld_lr;
11090 case LLD:
11091 mips32_op = OPC_LLD;
11092 goto do_ld_lr;
11093 #endif
11094 case LL:
11095 mips32_op = OPC_LL;
11096 goto do_ld_lr;
11097 do_ld_lr:
11098 gen_ld(env, ctx, mips32_op, rt, rs, SIMM(ctx->opcode, 0, 12));
11099 break;
11100 do_st_lr:
11101 gen_st(ctx, mips32_op, rt, rs, SIMM(ctx->opcode, 0, 12));
11102 break;
11103 case SC:
11104 gen_st_cond(ctx, OPC_SC, rt, rs, SIMM(ctx->opcode, 0, 12));
11105 break;
11106 #if defined(TARGET_MIPS64)
11107 case SCD:
11108 gen_st_cond(ctx, OPC_SCD, rt, rs, SIMM(ctx->opcode, 0, 12));
11109 break;
11110 #endif
11111 case PREF:
11112 /* Treat as no-op */
11113 break;
11114 default:
11115 MIPS_INVAL("pool32c");
11116 generate_exception(ctx, EXCP_RI);
11117 break;
11119 break;
11120 case ADDI32:
11121 mips32_op = OPC_ADDI;
11122 goto do_addi;
11123 case ADDIU32:
11124 mips32_op = OPC_ADDIU;
11125 do_addi:
11126 gen_arith_imm(env, ctx, mips32_op, rt, rs, imm);
11127 break;
11129 /* Logical operations */
11130 case ORI32:
11131 mips32_op = OPC_ORI;
11132 goto do_logici;
11133 case XORI32:
11134 mips32_op = OPC_XORI;
11135 goto do_logici;
11136 case ANDI32:
11137 mips32_op = OPC_ANDI;
11138 do_logici:
11139 gen_logic_imm(env, mips32_op, rt, rs, imm);
11140 break;
11142 /* Set less than immediate */
11143 case SLTI32:
11144 mips32_op = OPC_SLTI;
11145 goto do_slti;
11146 case SLTIU32:
11147 mips32_op = OPC_SLTIU;
11148 do_slti:
11149 gen_slt_imm(env, mips32_op, rt, rs, imm);
11150 break;
11151 case JALX32:
11152 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2;
11153 gen_compute_branch(ctx, OPC_JALX, 4, rt, rs, offset);
11154 *is_branch = 1;
11155 break;
11156 case JALS32:
11157 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 1;
11158 gen_compute_branch(ctx, OPC_JALS, 4, rt, rs, offset);
11159 *is_branch = 1;
11160 break;
11161 case BEQ32:
11162 gen_compute_branch(ctx, OPC_BEQ, 4, rt, rs, imm << 1);
11163 *is_branch = 1;
11164 break;
11165 case BNE32:
11166 gen_compute_branch(ctx, OPC_BNE, 4, rt, rs, imm << 1);
11167 *is_branch = 1;
11168 break;
11169 case J32:
11170 gen_compute_branch(ctx, OPC_J, 4, rt, rs,
11171 (int32_t)(ctx->opcode & 0x3FFFFFF) << 1);
11172 *is_branch = 1;
11173 break;
11174 case JAL32:
11175 gen_compute_branch(ctx, OPC_JAL, 4, rt, rs,
11176 (int32_t)(ctx->opcode & 0x3FFFFFF) << 1);
11177 *is_branch = 1;
11178 break;
11179 /* Floating point (COP1) */
11180 case LWC132:
11181 mips32_op = OPC_LWC1;
11182 goto do_cop1;
11183 case LDC132:
11184 mips32_op = OPC_LDC1;
11185 goto do_cop1;
11186 case SWC132:
11187 mips32_op = OPC_SWC1;
11188 goto do_cop1;
11189 case SDC132:
11190 mips32_op = OPC_SDC1;
11191 do_cop1:
11192 gen_cop1_ldst(env, ctx, mips32_op, rt, rs, imm);
11193 break;
11194 case ADDIUPC:
11196 int reg = mmreg(ZIMM(ctx->opcode, 23, 3));
11197 int offset = SIMM(ctx->opcode, 0, 23) << 2;
11199 gen_addiupc(ctx, reg, offset, 0, 0);
11201 break;
11202 /* Loads and stores */
11203 case LB32:
11204 mips32_op = OPC_LB;
11205 goto do_ld;
11206 case LBU32:
11207 mips32_op = OPC_LBU;
11208 goto do_ld;
11209 case LH32:
11210 mips32_op = OPC_LH;
11211 goto do_ld;
11212 case LHU32:
11213 mips32_op = OPC_LHU;
11214 goto do_ld;
11215 case LW32:
11216 mips32_op = OPC_LW;
11217 goto do_ld;
11218 #ifdef TARGET_MIPS64
11219 case LD32:
11220 mips32_op = OPC_LD;
11221 goto do_ld;
11222 case SD32:
11223 mips32_op = OPC_SD;
11224 goto do_st;
11225 #endif
11226 case SB32:
11227 mips32_op = OPC_SB;
11228 goto do_st;
11229 case SH32:
11230 mips32_op = OPC_SH;
11231 goto do_st;
11232 case SW32:
11233 mips32_op = OPC_SW;
11234 goto do_st;
11235 do_ld:
11236 gen_ld(env, ctx, mips32_op, rt, rs, imm);
11237 break;
11238 do_st:
11239 gen_st(ctx, mips32_op, rt, rs, imm);
11240 break;
11241 default:
11242 generate_exception(ctx, EXCP_RI);
11243 break;
11247 static int decode_micromips_opc (CPUState *env, DisasContext *ctx, int *is_branch)
11249 uint32_t op;
11251 /* make sure instructions are on a halfword boundary */
11252 if (ctx->pc & 0x1) {
11253 env->CP0_BadVAddr = ctx->pc;
11254 generate_exception(ctx, EXCP_AdEL);
11255 ctx->bstate = BS_STOP;
11256 return 2;
11259 op = (ctx->opcode >> 10) & 0x3f;
11260 /* Enforce properly-sized instructions in a delay slot */
11261 if (ctx->hflags & MIPS_HFLAG_BMASK) {
11262 int bits = ctx->hflags & MIPS_HFLAG_BMASK_EXT;
11264 switch (op) {
11265 case POOL32A:
11266 case POOL32B:
11267 case POOL32I:
11268 case POOL32C:
11269 case ADDI32:
11270 case ADDIU32:
11271 case ORI32:
11272 case XORI32:
11273 case SLTI32:
11274 case SLTIU32:
11275 case ANDI32:
11276 case JALX32:
11277 case LBU32:
11278 case LHU32:
11279 case POOL32F:
11280 case JALS32:
11281 case BEQ32:
11282 case BNE32:
11283 case J32:
11284 case JAL32:
11285 case SB32:
11286 case SH32:
11287 case POOL32S:
11288 case ADDIUPC:
11289 case SWC132:
11290 case SDC132:
11291 case SD32:
11292 case SW32:
11293 case LB32:
11294 case LH32:
11295 case DADDIU32:
11296 case POOL48A: /* ??? */
11297 case LWC132:
11298 case LDC132:
11299 case LD32:
11300 case LW32:
11301 if (bits & MIPS_HFLAG_BDS16) {
11302 generate_exception(ctx, EXCP_RI);
11303 /* Just stop translation; the user is confused. */
11304 ctx->bstate = BS_STOP;
11305 return 2;
11307 break;
11308 case POOL16A:
11309 case POOL16B:
11310 case POOL16C:
11311 case LWGP16:
11312 case POOL16F:
11313 case LBU16:
11314 case LHU16:
11315 case LWSP16:
11316 case LW16:
11317 case SB16:
11318 case SH16:
11319 case SWSP16:
11320 case SW16:
11321 case MOVE16:
11322 case ANDI16:
11323 case POOL16D:
11324 case POOL16E:
11325 case BEQZ16:
11326 case BNEZ16:
11327 case B16:
11328 case LI16:
11329 if (bits & MIPS_HFLAG_BDS32) {
11330 generate_exception(ctx, EXCP_RI);
11331 /* Just stop translation; the user is confused. */
11332 ctx->bstate = BS_STOP;
11333 return 2;
11335 break;
11336 default:
11337 break;
11340 switch (op) {
11341 case POOL16A:
11343 int rd = mmreg(uMIPS_RD(ctx->opcode));
11344 int rs1 = mmreg(uMIPS_RS1(ctx->opcode));
11345 int rs2 = mmreg(uMIPS_RS2(ctx->opcode));
11346 uint32_t opc = 0;
11348 switch (ctx->opcode & 0x1) {
11349 case ADDU16:
11350 opc = OPC_ADDU;
11351 break;
11352 case SUBU16:
11353 opc = OPC_SUBU;
11354 break;
11357 gen_arith(env, ctx, opc, rd, rs1, rs2);
11359 break;
11360 case POOL16B:
11362 int rd = mmreg(uMIPS_RD(ctx->opcode));
11363 int rs = mmreg(uMIPS_RS(ctx->opcode));
11364 int amount = (ctx->opcode >> 1) & 0x7;
11365 uint32_t opc = 0;
11366 amount = amount == 0 ? 8 : amount;
11368 switch (ctx->opcode & 0x1) {
11369 case SLL16:
11370 opc = OPC_SLL;
11371 break;
11372 case SRL16:
11373 opc = OPC_SRL;
11374 break;
11377 gen_shift_imm(env, ctx, opc, rd, rs, amount);
11379 break;
11380 case POOL16C:
11381 gen_pool16c_insn(env, ctx, is_branch);
11382 break;
11383 case LWGP16:
11385 int rd = mmreg(uMIPS_RD(ctx->opcode));
11386 int rb = 28; /* GP */
11387 int16_t offset = SIMM(ctx->opcode, 0, 7) << 2;
11389 gen_ld(env, ctx, OPC_LW, rd, rb, offset);
11391 break;
11392 case POOL16F:
11393 if (ctx->opcode & 1) {
11394 generate_exception(ctx, EXCP_RI);
11395 } else {
11396 /* MOVEP */
11397 int enc_dest = uMIPS_RD(ctx->opcode);
11398 int enc_rt = uMIPS_RS2(ctx->opcode);
11399 int enc_rs = uMIPS_RS1(ctx->opcode);
11400 int rd, rs, re, rt;
11401 static const int rd_enc[] = { 5, 5, 6, 4, 4, 4, 4, 4 };
11402 static const int re_enc[] = { 6, 7, 7, 21, 22, 5, 6, 7 };
11403 static const int rs_rt_enc[] = { 0, 17, 2, 3, 16, 18, 19, 20 };
11405 rd = rd_enc[enc_dest];
11406 re = re_enc[enc_dest];
11407 rs = rs_rt_enc[enc_rs];
11408 rt = rs_rt_enc[enc_rt];
11410 gen_arith_imm(env, ctx, OPC_ADDIU, rd, rs, 0);
11411 gen_arith_imm(env, ctx, OPC_ADDIU, re, rt, 0);
11413 break;
11414 case LBU16:
11416 int rd = mmreg(uMIPS_RD(ctx->opcode));
11417 int rb = mmreg(uMIPS_RS(ctx->opcode));
11418 int16_t offset = ZIMM(ctx->opcode, 0, 4);
11419 offset = (offset == 0xf ? -1 : offset);
11421 gen_ld(env, ctx, OPC_LBU, rd, rb, offset);
11423 break;
11424 case LHU16:
11426 int rd = mmreg(uMIPS_RD(ctx->opcode));
11427 int rb = mmreg(uMIPS_RS(ctx->opcode));
11428 int16_t offset = ZIMM(ctx->opcode, 0, 4) << 1;
11430 gen_ld(env, ctx, OPC_LHU, rd, rb, offset);
11432 break;
11433 case LWSP16:
11435 int rd = (ctx->opcode >> 5) & 0x1f;
11436 int rb = 29; /* SP */
11437 int16_t offset = ZIMM(ctx->opcode, 0, 5) << 2;
11439 gen_ld(env, ctx, OPC_LW, rd, rb, offset);
11441 break;
11442 case LW16:
11444 int rd = mmreg(uMIPS_RD(ctx->opcode));
11445 int rb = mmreg(uMIPS_RS(ctx->opcode));
11446 int16_t offset = ZIMM(ctx->opcode, 0, 4) << 2;
11448 gen_ld(env, ctx, OPC_LW, rd, rb, offset);
11450 break;
11451 case SB16:
11453 int rd = mmreg2(uMIPS_RD(ctx->opcode));
11454 int rb = mmreg(uMIPS_RS(ctx->opcode));
11455 int16_t offset = ZIMM(ctx->opcode, 0, 4);
11457 gen_st(ctx, OPC_SB, rd, rb, offset);
11459 break;
11460 case SH16:
11462 int rd = mmreg2(uMIPS_RD(ctx->opcode));
11463 int rb = mmreg(uMIPS_RS(ctx->opcode));
11464 int16_t offset = ZIMM(ctx->opcode, 0, 4) << 1;
11466 gen_st(ctx, OPC_SH, rd, rb, offset);
11468 break;
11469 case SWSP16:
11471 int rd = (ctx->opcode >> 5) & 0x1f;
11472 int rb = 29; /* SP */
11473 int16_t offset = ZIMM(ctx->opcode, 0, 5) << 2;
11475 gen_st(ctx, OPC_SW, rd, rb, offset);
11477 break;
11478 case SW16:
11480 int rd = mmreg2(uMIPS_RD(ctx->opcode));
11481 int rb = mmreg(uMIPS_RS(ctx->opcode));
11482 int16_t offset = ZIMM(ctx->opcode, 0, 4) << 2;
11484 gen_st(ctx, OPC_SW, rd, rb, offset);
11486 break;
11487 case MOVE16:
11489 int rd = uMIPS_RD5(ctx->opcode);
11490 int rs = uMIPS_RS5(ctx->opcode);
11492 gen_arith_imm(env, ctx, OPC_ADDIU, rd, rs, 0);
11494 break;
11495 case ANDI16:
11496 gen_andi16(env, ctx);
11497 break;
11498 case POOL16D:
11499 switch (ctx->opcode & 0x1) {
11500 case ADDIUS5:
11501 gen_addius5(env, ctx);
11502 break;
11503 case ADDIUSP:
11504 gen_addiusp(env, ctx);
11505 break;
11507 break;
11508 case POOL16E:
11509 switch (ctx->opcode & 0x1) {
11510 case ADDIUR2:
11511 gen_addiur2(env, ctx);
11512 break;
11513 case ADDIUR1SP:
11514 gen_addiur1sp(env, ctx);
11515 break;
11517 break;
11518 case B16:
11519 gen_compute_branch(ctx, OPC_BEQ, 2, 0, 0,
11520 SIMM(ctx->opcode, 0, 10) << 1);
11521 *is_branch = 1;
11522 break;
11523 case BNEZ16:
11524 case BEQZ16:
11525 gen_compute_branch(ctx, op == BNEZ16 ? OPC_BNE : OPC_BEQ, 2,
11526 mmreg(uMIPS_RD(ctx->opcode)),
11527 0, SIMM(ctx->opcode, 0, 7) << 1);
11528 *is_branch = 1;
11529 break;
11530 case LI16:
11532 int reg = mmreg(uMIPS_RD(ctx->opcode));
11533 int imm = ZIMM(ctx->opcode, 0, 7);
11535 imm = (imm == 0x7f ? -1 : imm);
11536 tcg_gen_movi_tl(cpu_gpr[reg], imm);
11538 break;
11539 case RES_20:
11540 case RES_28:
11541 case RES_29:
11542 case RES_30:
11543 case RES_31:
11544 case RES_38:
11545 case RES_39:
11546 generate_exception(ctx, EXCP_RI);
11547 break;
11548 default:
11549 decode_micromips32_opc (env, ctx, op, is_branch);
11550 return 4;
11553 return 2;
11556 /* SmartMIPS extension to MIPS32 */
11558 #if defined(TARGET_MIPS64)
11560 /* MDMX extension to MIPS64 */
11562 #endif
11564 static void decode_opc (CPUState *env, DisasContext *ctx, int *is_branch)
11566 int32_t offset;
11567 int rs, rt, rd, sa;
11568 uint32_t op, op1, op2;
11569 int16_t imm;
11571 /* make sure instructions are on a word boundary */
11572 if (ctx->pc & 0x3) {
11573 env->CP0_BadVAddr = ctx->pc;
11574 generate_exception(ctx, EXCP_AdEL);
11575 return;
11578 /* Handle blikely not taken case */
11579 if ((ctx->hflags & MIPS_HFLAG_BMASK_BASE) == MIPS_HFLAG_BL) {
11580 int l1 = gen_new_label();
11582 MIPS_DEBUG("blikely condition (" TARGET_FMT_lx ")", ctx->pc + 4);
11583 tcg_gen_brcondi_tl(TCG_COND_NE, bcond, 0, l1);
11584 tcg_gen_movi_i32(hflags, ctx->hflags & ~MIPS_HFLAG_BMASK);
11585 gen_goto_tb(ctx, 1, ctx->pc + 4);
11586 gen_set_label(l1);
11589 if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP)))
11590 tcg_gen_debug_insn_start(ctx->pc);
11592 op = MASK_OP_MAJOR(ctx->opcode);
11593 rs = (ctx->opcode >> 21) & 0x1f;
11594 rt = (ctx->opcode >> 16) & 0x1f;
11595 rd = (ctx->opcode >> 11) & 0x1f;
11596 sa = (ctx->opcode >> 6) & 0x1f;
11597 imm = (int16_t)ctx->opcode;
11598 switch (op) {
11599 case OPC_SPECIAL:
11600 op1 = MASK_SPECIAL(ctx->opcode);
11601 switch (op1) {
11602 case OPC_SLL: /* Shift with immediate */
11603 case OPC_SRA:
11604 gen_shift_imm(env, ctx, op1, rd, rt, sa);
11605 break;
11606 case OPC_SRL:
11607 switch ((ctx->opcode >> 21) & 0x1f) {
11608 case 1:
11609 /* rotr is decoded as srl on non-R2 CPUs */
11610 if (env->insn_flags & ISA_MIPS32R2) {
11611 op1 = OPC_ROTR;
11613 /* Fallthrough */
11614 case 0:
11615 gen_shift_imm(env, ctx, op1, rd, rt, sa);
11616 break;
11617 default:
11618 generate_exception(ctx, EXCP_RI);
11619 break;
11621 break;
11622 case OPC_MOVN: /* Conditional move */
11623 case OPC_MOVZ:
11624 check_insn(env, ctx, ISA_MIPS4 | ISA_MIPS32 |
11625 INSN_LOONGSON2E | INSN_LOONGSON2F);
11626 gen_cond_move(env, op1, rd, rs, rt);
11627 break;
11628 case OPC_ADD ... OPC_SUBU:
11629 gen_arith(env, ctx, op1, rd, rs, rt);
11630 break;
11631 case OPC_SLLV: /* Shifts */
11632 case OPC_SRAV:
11633 gen_shift(env, ctx, op1, rd, rs, rt);
11634 break;
11635 case OPC_SRLV:
11636 switch ((ctx->opcode >> 6) & 0x1f) {
11637 case 1:
11638 /* rotrv is decoded as srlv on non-R2 CPUs */
11639 if (env->insn_flags & ISA_MIPS32R2) {
11640 op1 = OPC_ROTRV;
11642 /* Fallthrough */
11643 case 0:
11644 gen_shift(env, ctx, op1, rd, rs, rt);
11645 break;
11646 default:
11647 generate_exception(ctx, EXCP_RI);
11648 break;
11650 break;
11651 case OPC_SLT: /* Set on less than */
11652 case OPC_SLTU:
11653 gen_slt(env, op1, rd, rs, rt);
11654 break;
11655 case OPC_AND: /* Logic*/
11656 case OPC_OR:
11657 case OPC_NOR:
11658 case OPC_XOR:
11659 gen_logic(env, op1, rd, rs, rt);
11660 break;
11661 case OPC_MULT ... OPC_DIVU:
11662 if (sa) {
11663 check_insn(env, ctx, INSN_VR54XX);
11664 op1 = MASK_MUL_VR54XX(ctx->opcode);
11665 gen_mul_vr54xx(ctx, op1, rd, rs, rt);
11666 } else
11667 gen_muldiv(ctx, op1, rs, rt);
11668 break;
11669 case OPC_JR ... OPC_JALR:
11670 gen_compute_branch(ctx, op1, 4, rs, rd, sa);
11671 *is_branch = 1;
11672 break;
11673 case OPC_TGE ... OPC_TEQ: /* Traps */
11674 case OPC_TNE:
11675 gen_trap(ctx, op1, rs, rt, -1);
11676 break;
11677 case OPC_MFHI: /* Move from HI/LO */
11678 case OPC_MFLO:
11679 gen_HILO(ctx, op1, rd);
11680 break;
11681 case OPC_MTHI:
11682 case OPC_MTLO: /* Move to HI/LO */
11683 gen_HILO(ctx, op1, rs);
11684 break;
11685 case OPC_PMON: /* Pmon entry point, also R4010 selsl */
11686 #ifdef MIPS_STRICT_STANDARD
11687 MIPS_INVAL("PMON / selsl");
11688 generate_exception(ctx, EXCP_RI);
11689 #else
11690 gen_helper_0i(pmon, sa);
11691 #endif
11692 break;
11693 case OPC_SYSCALL:
11694 generate_exception(ctx, EXCP_SYSCALL);
11695 ctx->bstate = BS_STOP;
11696 break;
11697 case OPC_BREAK:
11698 generate_exception(ctx, EXCP_BREAK);
11699 break;
11700 case OPC_SPIM:
11701 #ifdef MIPS_STRICT_STANDARD
11702 MIPS_INVAL("SPIM");
11703 generate_exception(ctx, EXCP_RI);
11704 #else
11705 /* Implemented as RI exception for now. */
11706 MIPS_INVAL("spim (unofficial)");
11707 generate_exception(ctx, EXCP_RI);
11708 #endif
11709 break;
11710 case OPC_SYNC:
11711 /* Treat as NOP. */
11712 break;
11714 case OPC_MOVCI:
11715 check_insn(env, ctx, ISA_MIPS4 | ISA_MIPS32);
11716 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
11717 check_cp1_enabled(ctx);
11718 gen_movci(ctx, rd, rs, (ctx->opcode >> 18) & 0x7,
11719 (ctx->opcode >> 16) & 1);
11720 } else {
11721 generate_exception_err(ctx, EXCP_CpU, 1);
11723 break;
11725 #if defined(TARGET_MIPS64)
11726 /* MIPS64 specific opcodes */
11727 case OPC_DSLL:
11728 case OPC_DSRA:
11729 case OPC_DSLL32:
11730 case OPC_DSRA32:
11731 check_insn(env, ctx, ISA_MIPS3);
11732 check_mips_64(ctx);
11733 gen_shift_imm(env, ctx, op1, rd, rt, sa);
11734 break;
11735 case OPC_DSRL:
11736 switch ((ctx->opcode >> 21) & 0x1f) {
11737 case 1:
11738 /* drotr is decoded as dsrl on non-R2 CPUs */
11739 if (env->insn_flags & ISA_MIPS32R2) {
11740 op1 = OPC_DROTR;
11742 /* Fallthrough */
11743 case 0:
11744 check_insn(env, ctx, ISA_MIPS3);
11745 check_mips_64(ctx);
11746 gen_shift_imm(env, ctx, op1, rd, rt, sa);
11747 break;
11748 default:
11749 generate_exception(ctx, EXCP_RI);
11750 break;
11752 break;
11753 case OPC_DSRL32:
11754 switch ((ctx->opcode >> 21) & 0x1f) {
11755 case 1:
11756 /* drotr32 is decoded as dsrl32 on non-R2 CPUs */
11757 if (env->insn_flags & ISA_MIPS32R2) {
11758 op1 = OPC_DROTR32;
11760 /* Fallthrough */
11761 case 0:
11762 check_insn(env, ctx, ISA_MIPS3);
11763 check_mips_64(ctx);
11764 gen_shift_imm(env, ctx, op1, rd, rt, sa);
11765 break;
11766 default:
11767 generate_exception(ctx, EXCP_RI);
11768 break;
11770 break;
11771 case OPC_DADD ... OPC_DSUBU:
11772 check_insn(env, ctx, ISA_MIPS3);
11773 check_mips_64(ctx);
11774 gen_arith(env, ctx, op1, rd, rs, rt);
11775 break;
11776 case OPC_DSLLV:
11777 case OPC_DSRAV:
11778 check_insn(env, ctx, ISA_MIPS3);
11779 check_mips_64(ctx);
11780 gen_shift(env, ctx, op1, rd, rs, rt);
11781 break;
11782 case OPC_DSRLV:
11783 switch ((ctx->opcode >> 6) & 0x1f) {
11784 case 1:
11785 /* drotrv is decoded as dsrlv on non-R2 CPUs */
11786 if (env->insn_flags & ISA_MIPS32R2) {
11787 op1 = OPC_DROTRV;
11789 /* Fallthrough */
11790 case 0:
11791 check_insn(env, ctx, ISA_MIPS3);
11792 check_mips_64(ctx);
11793 gen_shift(env, ctx, op1, rd, rs, rt);
11794 break;
11795 default:
11796 generate_exception(ctx, EXCP_RI);
11797 break;
11799 break;
11800 case OPC_DMULT ... OPC_DDIVU:
11801 check_insn(env, ctx, ISA_MIPS3);
11802 check_mips_64(ctx);
11803 gen_muldiv(ctx, op1, rs, rt);
11804 break;
11805 #endif
11806 default: /* Invalid */
11807 MIPS_INVAL("special");
11808 generate_exception(ctx, EXCP_RI);
11809 break;
11811 break;
11812 case OPC_SPECIAL2:
11813 op1 = MASK_SPECIAL2(ctx->opcode);
11814 switch (op1) {
11815 case OPC_MADD ... OPC_MADDU: /* Multiply and add/sub */
11816 case OPC_MSUB ... OPC_MSUBU:
11817 check_insn(env, ctx, ISA_MIPS32);
11818 gen_muldiv(ctx, op1, rs, rt);
11819 break;
11820 case OPC_MUL:
11821 gen_arith(env, ctx, op1, rd, rs, rt);
11822 break;
11823 case OPC_CLO:
11824 case OPC_CLZ:
11825 check_insn(env, ctx, ISA_MIPS32);
11826 gen_cl(ctx, op1, rd, rs);
11827 break;
11828 case OPC_SDBBP:
11829 /* XXX: not clear which exception should be raised
11830 * when in debug mode...
11832 check_insn(env, ctx, ISA_MIPS32);
11833 if (!(ctx->hflags & MIPS_HFLAG_DM)) {
11834 generate_exception(ctx, EXCP_DBp);
11835 } else {
11836 generate_exception(ctx, EXCP_DBp);
11838 /* Treat as NOP. */
11839 break;
11840 case OPC_DIV_G_2F:
11841 case OPC_DIVU_G_2F:
11842 case OPC_MULT_G_2F:
11843 case OPC_MULTU_G_2F:
11844 case OPC_MOD_G_2F:
11845 case OPC_MODU_G_2F:
11846 check_insn(env, ctx, INSN_LOONGSON2F);
11847 gen_loongson_integer(ctx, op1, rd, rs, rt);
11848 break;
11849 #if defined(TARGET_MIPS64)
11850 case OPC_DCLO:
11851 case OPC_DCLZ:
11852 check_insn(env, ctx, ISA_MIPS64);
11853 check_mips_64(ctx);
11854 gen_cl(ctx, op1, rd, rs);
11855 break;
11856 case OPC_DMULT_G_2F:
11857 case OPC_DMULTU_G_2F:
11858 case OPC_DDIV_G_2F:
11859 case OPC_DDIVU_G_2F:
11860 case OPC_DMOD_G_2F:
11861 case OPC_DMODU_G_2F:
11862 check_insn(env, ctx, INSN_LOONGSON2F);
11863 gen_loongson_integer(ctx, op1, rd, rs, rt);
11864 break;
11865 #endif
11866 default: /* Invalid */
11867 MIPS_INVAL("special2");
11868 generate_exception(ctx, EXCP_RI);
11869 break;
11871 break;
11872 case OPC_SPECIAL3:
11873 op1 = MASK_SPECIAL3(ctx->opcode);
11874 switch (op1) {
11875 case OPC_EXT:
11876 case OPC_INS:
11877 check_insn(env, ctx, ISA_MIPS32R2);
11878 gen_bitops(ctx, op1, rt, rs, sa, rd);
11879 break;
11880 case OPC_BSHFL:
11881 check_insn(env, ctx, ISA_MIPS32R2);
11882 op2 = MASK_BSHFL(ctx->opcode);
11883 gen_bshfl(ctx, op2, rt, rd);
11884 break;
11885 case OPC_RDHWR:
11886 gen_rdhwr(env, ctx, rt, rd);
11887 break;
11888 case OPC_FORK:
11889 check_insn(env, ctx, ASE_MT);
11891 TCGv t0 = tcg_temp_new();
11892 TCGv t1 = tcg_temp_new();
11894 gen_load_gpr(t0, rt);
11895 gen_load_gpr(t1, rs);
11896 gen_helper_fork(t0, t1);
11897 tcg_temp_free(t0);
11898 tcg_temp_free(t1);
11900 break;
11901 case OPC_YIELD:
11902 check_insn(env, ctx, ASE_MT);
11904 TCGv t0 = tcg_temp_new();
11906 save_cpu_state(ctx, 1);
11907 gen_load_gpr(t0, rs);
11908 gen_helper_yield(t0, t0);
11909 gen_store_gpr(t0, rd);
11910 tcg_temp_free(t0);
11912 break;
11913 case OPC_DIV_G_2E ... OPC_DIVU_G_2E:
11914 case OPC_MULT_G_2E ... OPC_MULTU_G_2E:
11915 case OPC_MOD_G_2E ... OPC_MODU_G_2E:
11916 check_insn(env, ctx, INSN_LOONGSON2E);
11917 gen_loongson_integer(ctx, op1, rd, rs, rt);
11918 break;
11919 #if defined(TARGET_MIPS64)
11920 case OPC_DEXTM ... OPC_DEXT:
11921 case OPC_DINSM ... OPC_DINS:
11922 check_insn(env, ctx, ISA_MIPS64R2);
11923 check_mips_64(ctx);
11924 gen_bitops(ctx, op1, rt, rs, sa, rd);
11925 break;
11926 case OPC_DBSHFL:
11927 check_insn(env, ctx, ISA_MIPS64R2);
11928 check_mips_64(ctx);
11929 op2 = MASK_DBSHFL(ctx->opcode);
11930 gen_bshfl(ctx, op2, rt, rd);
11931 break;
11932 case OPC_DDIV_G_2E ... OPC_DDIVU_G_2E:
11933 case OPC_DMULT_G_2E ... OPC_DMULTU_G_2E:
11934 case OPC_DMOD_G_2E ... OPC_DMODU_G_2E:
11935 check_insn(env, ctx, INSN_LOONGSON2E);
11936 gen_loongson_integer(ctx, op1, rd, rs, rt);
11937 break;
11938 #endif
11939 default: /* Invalid */
11940 MIPS_INVAL("special3");
11941 generate_exception(ctx, EXCP_RI);
11942 break;
11944 break;
11945 case OPC_REGIMM:
11946 op1 = MASK_REGIMM(ctx->opcode);
11947 switch (op1) {
11948 case OPC_BLTZ ... OPC_BGEZL: /* REGIMM branches */
11949 case OPC_BLTZAL ... OPC_BGEZALL:
11950 gen_compute_branch(ctx, op1, 4, rs, -1, imm << 2);
11951 *is_branch = 1;
11952 break;
11953 case OPC_TGEI ... OPC_TEQI: /* REGIMM traps */
11954 case OPC_TNEI:
11955 gen_trap(ctx, op1, rs, -1, imm);
11956 break;
11957 case OPC_SYNCI:
11958 check_insn(env, ctx, ISA_MIPS32R2);
11959 /* Treat as NOP. */
11960 break;
11961 default: /* Invalid */
11962 MIPS_INVAL("regimm");
11963 generate_exception(ctx, EXCP_RI);
11964 break;
11966 break;
11967 case OPC_CP0:
11968 check_cp0_enabled(ctx);
11969 op1 = MASK_CP0(ctx->opcode);
11970 switch (op1) {
11971 case OPC_MFC0:
11972 case OPC_MTC0:
11973 case OPC_MFTR:
11974 case OPC_MTTR:
11975 #if defined(TARGET_MIPS64)
11976 case OPC_DMFC0:
11977 case OPC_DMTC0:
11978 #endif
11979 #ifndef CONFIG_USER_ONLY
11980 gen_cp0(env, ctx, op1, rt, rd);
11981 #endif /* !CONFIG_USER_ONLY */
11982 break;
11983 case OPC_C0_FIRST ... OPC_C0_LAST:
11984 #ifndef CONFIG_USER_ONLY
11985 gen_cp0(env, ctx, MASK_C0(ctx->opcode), rt, rd);
11986 #endif /* !CONFIG_USER_ONLY */
11987 break;
11988 case OPC_MFMC0:
11989 #ifndef CONFIG_USER_ONLY
11991 TCGv t0 = tcg_temp_new();
11993 op2 = MASK_MFMC0(ctx->opcode);
11994 switch (op2) {
11995 case OPC_DMT:
11996 check_insn(env, ctx, ASE_MT);
11997 gen_helper_dmt(t0, t0);
11998 gen_store_gpr(t0, rt);
11999 break;
12000 case OPC_EMT:
12001 check_insn(env, ctx, ASE_MT);
12002 gen_helper_emt(t0, t0);
12003 gen_store_gpr(t0, rt);
12004 break;
12005 case OPC_DVPE:
12006 check_insn(env, ctx, ASE_MT);
12007 gen_helper_dvpe(t0, t0);
12008 gen_store_gpr(t0, rt);
12009 break;
12010 case OPC_EVPE:
12011 check_insn(env, ctx, ASE_MT);
12012 gen_helper_evpe(t0, t0);
12013 gen_store_gpr(t0, rt);
12014 break;
12015 case OPC_DI:
12016 check_insn(env, ctx, ISA_MIPS32R2);
12017 save_cpu_state(ctx, 1);
12018 gen_helper_di(t0);
12019 gen_store_gpr(t0, rt);
12020 /* Stop translation as we may have switched the execution mode */
12021 ctx->bstate = BS_STOP;
12022 break;
12023 case OPC_EI:
12024 check_insn(env, ctx, ISA_MIPS32R2);
12025 save_cpu_state(ctx, 1);
12026 gen_helper_ei(t0);
12027 gen_store_gpr(t0, rt);
12028 /* Stop translation as we may have switched the execution mode */
12029 ctx->bstate = BS_STOP;
12030 break;
12031 default: /* Invalid */
12032 MIPS_INVAL("mfmc0");
12033 generate_exception(ctx, EXCP_RI);
12034 break;
12036 tcg_temp_free(t0);
12038 #endif /* !CONFIG_USER_ONLY */
12039 break;
12040 case OPC_RDPGPR:
12041 check_insn(env, ctx, ISA_MIPS32R2);
12042 gen_load_srsgpr(rt, rd);
12043 break;
12044 case OPC_WRPGPR:
12045 check_insn(env, ctx, ISA_MIPS32R2);
12046 gen_store_srsgpr(rt, rd);
12047 break;
12048 default:
12049 MIPS_INVAL("cp0");
12050 generate_exception(ctx, EXCP_RI);
12051 break;
12053 break;
12054 case OPC_ADDI: /* Arithmetic with immediate opcode */
12055 case OPC_ADDIU:
12056 gen_arith_imm(env, ctx, op, rt, rs, imm);
12057 break;
12058 case OPC_SLTI: /* Set on less than with immediate opcode */
12059 case OPC_SLTIU:
12060 gen_slt_imm(env, op, rt, rs, imm);
12061 break;
12062 case OPC_ANDI: /* Arithmetic with immediate opcode */
12063 case OPC_LUI:
12064 case OPC_ORI:
12065 case OPC_XORI:
12066 gen_logic_imm(env, op, rt, rs, imm);
12067 break;
12068 case OPC_J ... OPC_JAL: /* Jump */
12069 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2;
12070 gen_compute_branch(ctx, op, 4, rs, rt, offset);
12071 *is_branch = 1;
12072 break;
12073 case OPC_BEQ ... OPC_BGTZ: /* Branch */
12074 case OPC_BEQL ... OPC_BGTZL:
12075 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2);
12076 *is_branch = 1;
12077 break;
12078 case OPC_LB ... OPC_LWR: /* Load and stores */
12079 case OPC_LL:
12080 gen_ld(env, ctx, op, rt, rs, imm);
12081 break;
12082 case OPC_SB ... OPC_SW:
12083 case OPC_SWR:
12084 gen_st(ctx, op, rt, rs, imm);
12085 break;
12086 case OPC_SC:
12087 gen_st_cond(ctx, op, rt, rs, imm);
12088 break;
12089 case OPC_CACHE:
12090 check_insn(env, ctx, ISA_MIPS3 | ISA_MIPS32);
12091 /* Treat as NOP. */
12092 break;
12093 case OPC_PREF:
12094 check_insn(env, ctx, ISA_MIPS4 | ISA_MIPS32);
12095 /* Treat as NOP. */
12096 break;
12098 /* Floating point (COP1). */
12099 case OPC_LWC1:
12100 case OPC_LDC1:
12101 case OPC_SWC1:
12102 case OPC_SDC1:
12103 gen_cop1_ldst(env, ctx, op, rt, rs, imm);
12104 break;
12106 case OPC_CP1:
12107 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
12108 check_cp1_enabled(ctx);
12109 op1 = MASK_CP1(ctx->opcode);
12110 switch (op1) {
12111 case OPC_MFHC1:
12112 case OPC_MTHC1:
12113 check_insn(env, ctx, ISA_MIPS32R2);
12114 case OPC_MFC1:
12115 case OPC_CFC1:
12116 case OPC_MTC1:
12117 case OPC_CTC1:
12118 gen_cp1(ctx, op1, rt, rd);
12119 break;
12120 #if defined(TARGET_MIPS64)
12121 case OPC_DMFC1:
12122 case OPC_DMTC1:
12123 check_insn(env, ctx, ISA_MIPS3);
12124 gen_cp1(ctx, op1, rt, rd);
12125 break;
12126 #endif
12127 case OPC_BC1ANY2:
12128 case OPC_BC1ANY4:
12129 check_cop1x(ctx);
12130 check_insn(env, ctx, ASE_MIPS3D);
12131 /* fall through */
12132 case OPC_BC1:
12133 gen_compute_branch1(env, ctx, MASK_BC1(ctx->opcode),
12134 (rt >> 2) & 0x7, imm << 2);
12135 *is_branch = 1;
12136 break;
12137 case OPC_S_FMT:
12138 case OPC_D_FMT:
12139 case OPC_W_FMT:
12140 case OPC_L_FMT:
12141 case OPC_PS_FMT:
12142 gen_farith(ctx, ctx->opcode & FOP(0x3f, 0x1f), rt, rd, sa,
12143 (imm >> 8) & 0x7);
12144 break;
12145 default:
12146 MIPS_INVAL("cp1");
12147 generate_exception (ctx, EXCP_RI);
12148 break;
12150 } else {
12151 generate_exception_err(ctx, EXCP_CpU, 1);
12153 break;
12155 /* COP2. */
12156 case OPC_LWC2:
12157 case OPC_LDC2:
12158 case OPC_SWC2:
12159 case OPC_SDC2:
12160 case OPC_CP2:
12161 /* COP2: Not implemented. */
12162 generate_exception_err(ctx, EXCP_CpU, 2);
12163 break;
12165 case OPC_CP3:
12166 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
12167 check_cp1_enabled(ctx);
12168 op1 = MASK_CP3(ctx->opcode);
12169 switch (op1) {
12170 case OPC_LWXC1:
12171 case OPC_LDXC1:
12172 case OPC_LUXC1:
12173 case OPC_SWXC1:
12174 case OPC_SDXC1:
12175 case OPC_SUXC1:
12176 gen_flt3_ldst(ctx, op1, sa, rd, rs, rt);
12177 break;
12178 case OPC_PREFX:
12179 /* Treat as NOP. */
12180 break;
12181 case OPC_ALNV_PS:
12182 case OPC_MADD_S:
12183 case OPC_MADD_D:
12184 case OPC_MADD_PS:
12185 case OPC_MSUB_S:
12186 case OPC_MSUB_D:
12187 case OPC_MSUB_PS:
12188 case OPC_NMADD_S:
12189 case OPC_NMADD_D:
12190 case OPC_NMADD_PS:
12191 case OPC_NMSUB_S:
12192 case OPC_NMSUB_D:
12193 case OPC_NMSUB_PS:
12194 gen_flt3_arith(ctx, op1, sa, rs, rd, rt);
12195 break;
12196 default:
12197 MIPS_INVAL("cp3");
12198 generate_exception (ctx, EXCP_RI);
12199 break;
12201 } else {
12202 generate_exception_err(ctx, EXCP_CpU, 1);
12204 break;
12206 #if defined(TARGET_MIPS64)
12207 /* MIPS64 opcodes */
12208 case OPC_LWU:
12209 case OPC_LDL ... OPC_LDR:
12210 case OPC_LLD:
12211 case OPC_LD:
12212 check_insn(env, ctx, ISA_MIPS3);
12213 check_mips_64(ctx);
12214 gen_ld(env, ctx, op, rt, rs, imm);
12215 break;
12216 case OPC_SDL ... OPC_SDR:
12217 case OPC_SD:
12218 check_insn(env, ctx, ISA_MIPS3);
12219 check_mips_64(ctx);
12220 gen_st(ctx, op, rt, rs, imm);
12221 break;
12222 case OPC_SCD:
12223 check_insn(env, ctx, ISA_MIPS3);
12224 check_mips_64(ctx);
12225 gen_st_cond(ctx, op, rt, rs, imm);
12226 break;
12227 case OPC_DADDI:
12228 case OPC_DADDIU:
12229 check_insn(env, ctx, ISA_MIPS3);
12230 check_mips_64(ctx);
12231 gen_arith_imm(env, ctx, op, rt, rs, imm);
12232 break;
12233 #endif
12234 case OPC_JALX:
12235 check_insn(env, ctx, ASE_MIPS16 | ASE_MICROMIPS);
12236 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2;
12237 gen_compute_branch(ctx, op, 4, rs, rt, offset);
12238 *is_branch = 1;
12239 break;
12240 case OPC_MDMX:
12241 check_insn(env, ctx, ASE_MDMX);
12242 /* MDMX: Not implemented. */
12243 default: /* Invalid */
12244 MIPS_INVAL("major opcode");
12245 generate_exception(ctx, EXCP_RI);
12246 break;
12250 static inline void
12251 gen_intermediate_code_internal (CPUState *env, TranslationBlock *tb,
12252 int search_pc)
12254 DisasContext ctx;
12255 target_ulong pc_start;
12256 uint16_t *gen_opc_end;
12257 CPUBreakpoint *bp;
12258 int j, lj = -1;
12259 int num_insns;
12260 int max_insns;
12261 int insn_bytes;
12262 int is_branch;
12264 if (search_pc)
12265 qemu_log("search pc %d\n", search_pc);
12267 pc_start = tb->pc;
12268 gen_opc_end = gen_opc_buf + OPC_MAX_SIZE;
12269 ctx.pc = pc_start;
12270 ctx.saved_pc = -1;
12271 ctx.singlestep_enabled = env->singlestep_enabled;
12272 ctx.tb = tb;
12273 ctx.bstate = BS_NONE;
12274 /* Restore delay slot state from the tb context. */
12275 ctx.hflags = (uint32_t)tb->flags; /* FIXME: maybe use 64 bits here? */
12276 restore_cpu_state(env, &ctx);
12277 #ifdef CONFIG_USER_ONLY
12278 ctx.mem_idx = MIPS_HFLAG_UM;
12279 #else
12280 ctx.mem_idx = ctx.hflags & MIPS_HFLAG_KSU;
12281 #endif
12282 num_insns = 0;
12283 max_insns = tb->cflags & CF_COUNT_MASK;
12284 if (max_insns == 0)
12285 max_insns = CF_COUNT_MASK;
12286 LOG_DISAS("\ntb %p idx %d hflags %04x\n", tb, ctx.mem_idx, ctx.hflags);
12287 gen_icount_start();
12288 while (ctx.bstate == BS_NONE) {
12289 if (unlikely(!QTAILQ_EMPTY(&env->breakpoints))) {
12290 QTAILQ_FOREACH(bp, &env->breakpoints, entry) {
12291 if (bp->pc == ctx.pc) {
12292 save_cpu_state(&ctx, 1);
12293 ctx.bstate = BS_BRANCH;
12294 gen_helper_0i(raise_exception, EXCP_DEBUG);
12295 /* Include the breakpoint location or the tb won't
12296 * be flushed when it must be. */
12297 ctx.pc += 4;
12298 goto done_generating;
12303 if (search_pc) {
12304 j = gen_opc_ptr - gen_opc_buf;
12305 if (lj < j) {
12306 lj++;
12307 while (lj < j)
12308 gen_opc_instr_start[lj++] = 0;
12310 gen_opc_pc[lj] = ctx.pc;
12311 gen_opc_hflags[lj] = ctx.hflags & MIPS_HFLAG_BMASK;
12312 gen_opc_instr_start[lj] = 1;
12313 gen_opc_icount[lj] = num_insns;
12315 if (num_insns + 1 == max_insns && (tb->cflags & CF_LAST_IO))
12316 gen_io_start();
12318 is_branch = 0;
12319 if (!(ctx.hflags & MIPS_HFLAG_M16)) {
12320 ctx.opcode = ldl_code(ctx.pc);
12321 insn_bytes = 4;
12322 decode_opc(env, &ctx, &is_branch);
12323 } else if (env->insn_flags & ASE_MICROMIPS) {
12324 ctx.opcode = lduw_code(ctx.pc);
12325 insn_bytes = decode_micromips_opc(env, &ctx, &is_branch);
12326 } else if (env->insn_flags & ASE_MIPS16) {
12327 ctx.opcode = lduw_code(ctx.pc);
12328 insn_bytes = decode_mips16_opc(env, &ctx, &is_branch);
12329 } else {
12330 generate_exception(&ctx, EXCP_RI);
12331 ctx.bstate = BS_STOP;
12332 break;
12334 if (!is_branch) {
12335 handle_delay_slot(env, &ctx, insn_bytes);
12337 ctx.pc += insn_bytes;
12339 num_insns++;
12341 /* Execute a branch and its delay slot as a single instruction.
12342 This is what GDB expects and is consistent with what the
12343 hardware does (e.g. if a delay slot instruction faults, the
12344 reported PC is the PC of the branch). */
12345 if (env->singlestep_enabled && (ctx.hflags & MIPS_HFLAG_BMASK) == 0)
12346 break;
12348 if ((ctx.pc & (TARGET_PAGE_SIZE - 1)) == 0)
12349 break;
12351 if (gen_opc_ptr >= gen_opc_end)
12352 break;
12354 if (num_insns >= max_insns)
12355 break;
12357 if (singlestep)
12358 break;
12360 if (tb->cflags & CF_LAST_IO)
12361 gen_io_end();
12362 if (env->singlestep_enabled && ctx.bstate != BS_BRANCH) {
12363 save_cpu_state(&ctx, ctx.bstate == BS_NONE);
12364 gen_helper_0i(raise_exception, EXCP_DEBUG);
12365 } else {
12366 switch (ctx.bstate) {
12367 case BS_STOP:
12368 gen_helper_interrupt_restart();
12369 gen_goto_tb(&ctx, 0, ctx.pc);
12370 break;
12371 case BS_NONE:
12372 save_cpu_state(&ctx, 0);
12373 gen_goto_tb(&ctx, 0, ctx.pc);
12374 break;
12375 case BS_EXCP:
12376 gen_helper_interrupt_restart();
12377 tcg_gen_exit_tb(0);
12378 break;
12379 case BS_BRANCH:
12380 default:
12381 break;
12384 done_generating:
12385 gen_icount_end(tb, num_insns);
12386 *gen_opc_ptr = INDEX_op_end;
12387 if (search_pc) {
12388 j = gen_opc_ptr - gen_opc_buf;
12389 lj++;
12390 while (lj <= j)
12391 gen_opc_instr_start[lj++] = 0;
12392 } else {
12393 tb->size = ctx.pc - pc_start;
12394 tb->icount = num_insns;
12396 #ifdef DEBUG_DISAS
12397 LOG_DISAS("\n");
12398 if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) {
12399 qemu_log("IN: %s\n", lookup_symbol(pc_start));
12400 log_target_disas(pc_start, ctx.pc - pc_start, 0);
12401 qemu_log("\n");
12403 #endif
12406 void gen_intermediate_code (CPUState *env, struct TranslationBlock *tb)
12408 gen_intermediate_code_internal(env, tb, 0);
12411 void gen_intermediate_code_pc (CPUState *env, struct TranslationBlock *tb)
12413 gen_intermediate_code_internal(env, tb, 1);
12416 static void fpu_dump_state(CPUState *env, FILE *f,
12417 int (*fpu_fprintf)(FILE *f, const char *fmt, ...),
12418 int flags)
12420 int i;
12421 int is_fpu64 = !!(env->hflags & MIPS_HFLAG_F64);
12423 #define printfpr(fp) \
12424 do { \
12425 if (is_fpu64) \
12426 fpu_fprintf(f, "w:%08x d:%016" PRIx64 \
12427 " fd:%13g fs:%13g psu: %13g\n", \
12428 (fp)->w[FP_ENDIAN_IDX], (fp)->d, \
12429 (double)(fp)->fd, \
12430 (double)(fp)->fs[FP_ENDIAN_IDX], \
12431 (double)(fp)->fs[!FP_ENDIAN_IDX]); \
12432 else { \
12433 fpr_t tmp; \
12434 tmp.w[FP_ENDIAN_IDX] = (fp)->w[FP_ENDIAN_IDX]; \
12435 tmp.w[!FP_ENDIAN_IDX] = ((fp) + 1)->w[FP_ENDIAN_IDX]; \
12436 fpu_fprintf(f, "w:%08x d:%016" PRIx64 \
12437 " fd:%13g fs:%13g psu:%13g\n", \
12438 tmp.w[FP_ENDIAN_IDX], tmp.d, \
12439 (double)tmp.fd, \
12440 (double)tmp.fs[FP_ENDIAN_IDX], \
12441 (double)tmp.fs[!FP_ENDIAN_IDX]); \
12443 } while(0)
12446 fpu_fprintf(f, "CP1 FCR0 0x%08x FCR31 0x%08x SR.FR %d fp_status 0x%08x(0x%02x)\n",
12447 env->active_fpu.fcr0, env->active_fpu.fcr31, is_fpu64, env->active_fpu.fp_status,
12448 get_float_exception_flags(&env->active_fpu.fp_status));
12449 for (i = 0; i < 32; (is_fpu64) ? i++ : (i += 2)) {
12450 fpu_fprintf(f, "%3s: ", fregnames[i]);
12451 printfpr(&env->active_fpu.fpr[i]);
12454 #undef printfpr
12457 #if defined(TARGET_MIPS64) && defined(MIPS_DEBUG_SIGN_EXTENSIONS)
12458 /* Debug help: The architecture requires 32bit code to maintain proper
12459 sign-extended values on 64bit machines. */
12461 #define SIGN_EXT_P(val) ((((val) & ~0x7fffffff) == 0) || (((val) & ~0x7fffffff) == ~0x7fffffff))
12463 static void
12464 cpu_mips_check_sign_extensions (CPUState *env, FILE *f,
12465 int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
12466 int flags)
12468 int i;
12470 if (!SIGN_EXT_P(env->active_tc.PC))
12471 cpu_fprintf(f, "BROKEN: pc=0x" TARGET_FMT_lx "\n", env->active_tc.PC);
12472 if (!SIGN_EXT_P(env->active_tc.HI[0]))
12473 cpu_fprintf(f, "BROKEN: HI=0x" TARGET_FMT_lx "\n", env->active_tc.HI[0]);
12474 if (!SIGN_EXT_P(env->active_tc.LO[0]))
12475 cpu_fprintf(f, "BROKEN: LO=0x" TARGET_FMT_lx "\n", env->active_tc.LO[0]);
12476 if (!SIGN_EXT_P(env->btarget))
12477 cpu_fprintf(f, "BROKEN: btarget=0x" TARGET_FMT_lx "\n", env->btarget);
12479 for (i = 0; i < 32; i++) {
12480 if (!SIGN_EXT_P(env->active_tc.gpr[i]))
12481 cpu_fprintf(f, "BROKEN: %s=0x" TARGET_FMT_lx "\n", regnames[i], env->active_tc.gpr[i]);
12484 if (!SIGN_EXT_P(env->CP0_EPC))
12485 cpu_fprintf(f, "BROKEN: EPC=0x" TARGET_FMT_lx "\n", env->CP0_EPC);
12486 if (!SIGN_EXT_P(env->lladdr))
12487 cpu_fprintf(f, "BROKEN: LLAddr=0x" TARGET_FMT_lx "\n", env->lladdr);
12489 #endif
12491 void cpu_dump_state (CPUState *env, FILE *f,
12492 int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
12493 int flags)
12495 int i;
12497 cpu_fprintf(f, "pc=0x" TARGET_FMT_lx " HI=0x" TARGET_FMT_lx
12498 " LO=0x" TARGET_FMT_lx " ds %04x "
12499 TARGET_FMT_lx " " TARGET_FMT_ld "\n",
12500 env->active_tc.PC, env->active_tc.HI[0], env->active_tc.LO[0],
12501 env->hflags, env->btarget, env->bcond);
12502 for (i = 0; i < 32; i++) {
12503 if ((i & 3) == 0)
12504 cpu_fprintf(f, "GPR%02d:", i);
12505 cpu_fprintf(f, " %s " TARGET_FMT_lx, regnames[i], env->active_tc.gpr[i]);
12506 if ((i & 3) == 3)
12507 cpu_fprintf(f, "\n");
12510 cpu_fprintf(f, "CP0 Status 0x%08x Cause 0x%08x EPC 0x" TARGET_FMT_lx "\n",
12511 env->CP0_Status, env->CP0_Cause, env->CP0_EPC);
12512 cpu_fprintf(f, " Config0 0x%08x Config1 0x%08x LLAddr 0x" TARGET_FMT_lx "\n",
12513 env->CP0_Config0, env->CP0_Config1, env->lladdr);
12514 if (env->hflags & MIPS_HFLAG_FPU)
12515 fpu_dump_state(env, f, cpu_fprintf, flags);
12516 #if defined(TARGET_MIPS64) && defined(MIPS_DEBUG_SIGN_EXTENSIONS)
12517 cpu_mips_check_sign_extensions(env, f, cpu_fprintf, flags);
12518 #endif
12521 static void mips_tcg_init(void)
12523 int i;
12524 static int inited;
12526 /* Initialize various static tables. */
12527 if (inited)
12528 return;
12530 cpu_env = tcg_global_reg_new_ptr(TCG_AREG0, "env");
12531 TCGV_UNUSED(cpu_gpr[0]);
12532 for (i = 1; i < 32; i++)
12533 cpu_gpr[i] = tcg_global_mem_new(TCG_AREG0,
12534 offsetof(CPUState, active_tc.gpr[i]),
12535 regnames[i]);
12536 cpu_PC = tcg_global_mem_new(TCG_AREG0,
12537 offsetof(CPUState, active_tc.PC), "PC");
12538 for (i = 0; i < MIPS_DSP_ACC; i++) {
12539 cpu_HI[i] = tcg_global_mem_new(TCG_AREG0,
12540 offsetof(CPUState, active_tc.HI[i]),
12541 regnames_HI[i]);
12542 cpu_LO[i] = tcg_global_mem_new(TCG_AREG0,
12543 offsetof(CPUState, active_tc.LO[i]),
12544 regnames_LO[i]);
12545 cpu_ACX[i] = tcg_global_mem_new(TCG_AREG0,
12546 offsetof(CPUState, active_tc.ACX[i]),
12547 regnames_ACX[i]);
12549 cpu_dspctrl = tcg_global_mem_new(TCG_AREG0,
12550 offsetof(CPUState, active_tc.DSPControl),
12551 "DSPControl");
12552 bcond = tcg_global_mem_new(TCG_AREG0,
12553 offsetof(CPUState, bcond), "bcond");
12554 btarget = tcg_global_mem_new(TCG_AREG0,
12555 offsetof(CPUState, btarget), "btarget");
12556 hflags = tcg_global_mem_new_i32(TCG_AREG0,
12557 offsetof(CPUState, hflags), "hflags");
12559 fpu_fcr0 = tcg_global_mem_new_i32(TCG_AREG0,
12560 offsetof(CPUState, active_fpu.fcr0),
12561 "fcr0");
12562 fpu_fcr31 = tcg_global_mem_new_i32(TCG_AREG0,
12563 offsetof(CPUState, active_fpu.fcr31),
12564 "fcr31");
12566 /* register helpers */
12567 #define GEN_HELPER 2
12568 #include "helper.h"
12570 inited = 1;
12573 #include "translate_init.c"
12575 CPUMIPSState *cpu_mips_init (const char *cpu_model)
12577 CPUMIPSState *env;
12578 const mips_def_t *def;
12580 def = cpu_mips_find_by_name(cpu_model);
12581 if (!def)
12582 return NULL;
12583 env = qemu_mallocz(sizeof(CPUMIPSState));
12584 env->cpu_model = def;
12585 env->cpu_model_str = cpu_model;
12587 cpu_exec_init(env);
12588 #ifndef CONFIG_USER_ONLY
12589 mmu_init(env, def);
12590 #endif
12591 fpu_init(env, def);
12592 mvp_init(env, def);
12593 mips_tcg_init();
12594 cpu_reset(env);
12595 qemu_init_vcpu(env);
12596 return env;
12599 void cpu_reset (CPUMIPSState *env)
12601 if (qemu_loglevel_mask(CPU_LOG_RESET)) {
12602 qemu_log("CPU Reset (CPU %d)\n", env->cpu_index);
12603 log_cpu_state(env, 0);
12606 memset(env, 0, offsetof(CPUMIPSState, breakpoints));
12607 tlb_flush(env, 1);
12609 /* Reset registers to their default values */
12610 env->CP0_PRid = env->cpu_model->CP0_PRid;
12611 env->CP0_Config0 = env->cpu_model->CP0_Config0;
12612 #ifdef TARGET_WORDS_BIGENDIAN
12613 env->CP0_Config0 |= (1 << CP0C0_BE);
12614 #endif
12615 env->CP0_Config1 = env->cpu_model->CP0_Config1;
12616 env->CP0_Config2 = env->cpu_model->CP0_Config2;
12617 env->CP0_Config3 = env->cpu_model->CP0_Config3;
12618 env->CP0_Config6 = env->cpu_model->CP0_Config6;
12619 env->CP0_Config7 = env->cpu_model->CP0_Config7;
12620 env->CP0_LLAddr_rw_bitmask = env->cpu_model->CP0_LLAddr_rw_bitmask
12621 << env->cpu_model->CP0_LLAddr_shift;
12622 env->CP0_LLAddr_shift = env->cpu_model->CP0_LLAddr_shift;
12623 env->SYNCI_Step = env->cpu_model->SYNCI_Step;
12624 env->CCRes = env->cpu_model->CCRes;
12625 env->CP0_Status_rw_bitmask = env->cpu_model->CP0_Status_rw_bitmask;
12626 env->CP0_TCStatus_rw_bitmask = env->cpu_model->CP0_TCStatus_rw_bitmask;
12627 env->CP0_SRSCtl = env->cpu_model->CP0_SRSCtl;
12628 env->current_tc = 0;
12629 env->SEGBITS = env->cpu_model->SEGBITS;
12630 env->SEGMask = (target_ulong)((1ULL << env->cpu_model->SEGBITS) - 1);
12631 #if defined(TARGET_MIPS64)
12632 if (env->cpu_model->insn_flags & ISA_MIPS3) {
12633 env->SEGMask |= 3ULL << 62;
12635 #endif
12636 env->PABITS = env->cpu_model->PABITS;
12637 env->PAMask = (target_ulong)((1ULL << env->cpu_model->PABITS) - 1);
12638 env->CP0_SRSConf0_rw_bitmask = env->cpu_model->CP0_SRSConf0_rw_bitmask;
12639 env->CP0_SRSConf0 = env->cpu_model->CP0_SRSConf0;
12640 env->CP0_SRSConf1_rw_bitmask = env->cpu_model->CP0_SRSConf1_rw_bitmask;
12641 env->CP0_SRSConf1 = env->cpu_model->CP0_SRSConf1;
12642 env->CP0_SRSConf2_rw_bitmask = env->cpu_model->CP0_SRSConf2_rw_bitmask;
12643 env->CP0_SRSConf2 = env->cpu_model->CP0_SRSConf2;
12644 env->CP0_SRSConf3_rw_bitmask = env->cpu_model->CP0_SRSConf3_rw_bitmask;
12645 env->CP0_SRSConf3 = env->cpu_model->CP0_SRSConf3;
12646 env->CP0_SRSConf4_rw_bitmask = env->cpu_model->CP0_SRSConf4_rw_bitmask;
12647 env->CP0_SRSConf4 = env->cpu_model->CP0_SRSConf4;
12648 env->insn_flags = env->cpu_model->insn_flags;
12650 #if defined(CONFIG_USER_ONLY)
12651 env->hflags = MIPS_HFLAG_UM;
12652 /* Enable access to the SYNCI_Step register. */
12653 env->CP0_HWREna |= (1 << 1);
12654 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
12655 env->hflags |= MIPS_HFLAG_FPU;
12657 #ifdef TARGET_MIPS64
12658 if (env->active_fpu.fcr0 & (1 << FCR0_F64)) {
12659 env->hflags |= MIPS_HFLAG_F64;
12661 #endif
12662 #else
12663 if (env->hflags & MIPS_HFLAG_BMASK) {
12664 /* If the exception was raised from a delay slot,
12665 come back to the jump. */
12666 env->CP0_ErrorEPC = env->active_tc.PC - 4;
12667 } else {
12668 env->CP0_ErrorEPC = env->active_tc.PC;
12670 env->active_tc.PC = (int32_t)0xBFC00000;
12671 env->CP0_Random = env->tlb->nb_tlb - 1;
12672 env->tlb->tlb_in_use = env->tlb->nb_tlb;
12673 env->CP0_Wired = 0;
12674 /* SMP not implemented */
12675 env->CP0_EBase = 0x80000000;
12676 env->CP0_Status = (1 << CP0St_BEV) | (1 << CP0St_ERL);
12677 /* vectored interrupts not implemented, timer on int 7,
12678 no performance counters. */
12679 env->CP0_IntCtl = 0xe0000000;
12681 int i;
12683 for (i = 0; i < 7; i++) {
12684 env->CP0_WatchLo[i] = 0;
12685 env->CP0_WatchHi[i] = 0x80000000;
12687 env->CP0_WatchLo[7] = 0;
12688 env->CP0_WatchHi[7] = 0;
12690 /* Count register increments in debug mode, EJTAG version 1 */
12691 env->CP0_Debug = (1 << CP0DB_CNT) | (0x1 << CP0DB_VER);
12692 env->hflags = MIPS_HFLAG_CP0;
12693 #endif
12694 #if defined(TARGET_MIPS64)
12695 if (env->cpu_model->insn_flags & ISA_MIPS3) {
12696 env->hflags |= MIPS_HFLAG_64;
12698 #endif
12699 env->exception_index = EXCP_NONE;
12702 void gen_pc_load(CPUState *env, TranslationBlock *tb,
12703 unsigned long searched_pc, int pc_pos, void *puc)
12705 env->active_tc.PC = gen_opc_pc[pc_pos];
12706 env->hflags &= ~MIPS_HFLAG_BMASK;
12707 env->hflags |= gen_opc_hflags[pc_pos];