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