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