blob: 4ee9615fdab07ed8cb624012b8c7d1e1ad00b07c [file] [log] [blame]
bellard6af0bf92005-07-02 14:58:51 +00001/*
2 * MIPS32 emulation for qemu: main translation routines.
ths5fafdf22007-09-16 21:08:06 +00003 *
bellard6af0bf92005-07-02 14:58:51 +00004 * Copyright (c) 2004-2005 Jocelyn Mayer
bellard6ea83fe2006-06-14 12:56:19 +00005 * Copyright (c) 2006 Marius Groeger (FPU operations)
thsbb8a53a2006-12-06 23:12:49 +00006 * Copyright (c) 2006 Thiemo Seufer (MIPS32R2 support)
Nathan Froyd3c824102010-06-08 13:29:59 -07007 * Copyright (c) 2009 CodeSourcery (MIPS16 and microMIPS support)
Jia Liu41334982012-10-24 22:17:03 +08008 * Copyright (c) 2012 Jia Liu & Dongxue Zhang (MIPS ASE DSP support)
bellard6af0bf92005-07-02 14:58:51 +00009 *
10 * This library is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU Lesser General Public
12 * License as published by the Free Software Foundation; either
13 * version 2 of the License, or (at your option) any later version.
14 *
15 * This library is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 * Lesser General Public License for more details.
19 *
20 * You should have received a copy of the GNU Lesser General Public
Blue Swirl8167ee82009-07-16 20:47:01 +000021 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
bellard6af0bf92005-07-02 14:58:51 +000022 */
23
bellard6af0bf92005-07-02 14:58:51 +000024#include "cpu.h"
Paolo Bonzini76cad712012-10-24 11:12:21 +020025#include "disas/disas.h"
bellard57fec1f2008-02-01 10:50:11 +000026#include "tcg-op.h"
bellard6af0bf92005-07-02 14:58:51 +000027
pbrooka7812ae2008-11-17 14:43:54 +000028#include "helper.h"
29#define GEN_HELPER 1
30#include "helper.h"
31
Richard Hendersonfb7729e2012-09-18 21:55:34 -070032#define MIPS_DEBUG_DISAS 0
thsc570fd12006-12-21 01:19:56 +000033//#define MIPS_DEBUG_SIGN_EXTENSIONS
bellard6af0bf92005-07-02 14:58:51 +000034
ths7a387ff2006-12-06 20:17:30 +000035/* MIPS major opcodes */
36#define MASK_OP_MAJOR(op) (op & (0x3F << 26))
bellarde37e8632005-07-04 22:17:33 +000037
38enum {
39 /* indirect opcode tables */
ths7a387ff2006-12-06 20:17:30 +000040 OPC_SPECIAL = (0x00 << 26),
41 OPC_REGIMM = (0x01 << 26),
42 OPC_CP0 = (0x10 << 26),
43 OPC_CP1 = (0x11 << 26),
44 OPC_CP2 = (0x12 << 26),
45 OPC_CP3 = (0x13 << 26),
46 OPC_SPECIAL2 = (0x1C << 26),
47 OPC_SPECIAL3 = (0x1F << 26),
bellarde37e8632005-07-04 22:17:33 +000048 /* arithmetic with immediate */
ths7a387ff2006-12-06 20:17:30 +000049 OPC_ADDI = (0x08 << 26),
50 OPC_ADDIU = (0x09 << 26),
51 OPC_SLTI = (0x0A << 26),
52 OPC_SLTIU = (0x0B << 26),
aurel32324d9e32009-04-11 18:42:17 +000053 /* logic with immediate */
ths7a387ff2006-12-06 20:17:30 +000054 OPC_ANDI = (0x0C << 26),
55 OPC_ORI = (0x0D << 26),
56 OPC_XORI = (0x0E << 26),
57 OPC_LUI = (0x0F << 26),
aurel32324d9e32009-04-11 18:42:17 +000058 /* arithmetic with immediate */
ths7a387ff2006-12-06 20:17:30 +000059 OPC_DADDI = (0x18 << 26),
60 OPC_DADDIU = (0x19 << 26),
bellarde37e8632005-07-04 22:17:33 +000061 /* Jump and branches */
ths7a387ff2006-12-06 20:17:30 +000062 OPC_J = (0x02 << 26),
63 OPC_JAL = (0x03 << 26),
Nathan Froyd620e48f2010-06-08 13:29:58 -070064 OPC_JALS = OPC_JAL | 0x5,
ths7a387ff2006-12-06 20:17:30 +000065 OPC_BEQ = (0x04 << 26), /* Unconditional if rs = rt = 0 (B) */
66 OPC_BEQL = (0x14 << 26),
67 OPC_BNE = (0x05 << 26),
68 OPC_BNEL = (0x15 << 26),
69 OPC_BLEZ = (0x06 << 26),
70 OPC_BLEZL = (0x16 << 26),
71 OPC_BGTZ = (0x07 << 26),
72 OPC_BGTZL = (0x17 << 26),
73 OPC_JALX = (0x1D << 26), /* MIPS 16 only */
Nathan Froyd620e48f2010-06-08 13:29:58 -070074 OPC_JALXS = OPC_JALX | 0x5,
bellarde37e8632005-07-04 22:17:33 +000075 /* Load and stores */
ths7a387ff2006-12-06 20:17:30 +000076 OPC_LDL = (0x1A << 26),
77 OPC_LDR = (0x1B << 26),
78 OPC_LB = (0x20 << 26),
79 OPC_LH = (0x21 << 26),
80 OPC_LWL = (0x22 << 26),
81 OPC_LW = (0x23 << 26),
Nathan Froyd364d4832009-12-08 08:06:29 -080082 OPC_LWPC = OPC_LW | 0x5,
ths7a387ff2006-12-06 20:17:30 +000083 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),
Nathan Froyd364d4832009-12-08 08:06:29 -080097 OPC_LDPC = OPC_LD | 0x5,
ths7a387ff2006-12-06 20:17:30 +000098 OPC_SC = (0x38 << 26),
99 OPC_SCD = (0x3C << 26),
100 OPC_SD = (0x3F << 26),
bellarde37e8632005-07-04 22:17:33 +0000101 /* Floating point load/store */
ths7a387ff2006-12-06 20:17:30 +0000102 OPC_LWC1 = (0x31 << 26),
103 OPC_LWC2 = (0x32 << 26),
104 OPC_LDC1 = (0x35 << 26),
105 OPC_LDC2 = (0x36 << 26),
106 OPC_SWC1 = (0x39 << 26),
107 OPC_SWC2 = (0x3A << 26),
108 OPC_SDC1 = (0x3D << 26),
109 OPC_SDC2 = (0x3E << 26),
110 /* MDMX ASE specific */
111 OPC_MDMX = (0x1E << 26),
bellarde37e8632005-07-04 22:17:33 +0000112 /* Cache and prefetch */
ths7a387ff2006-12-06 20:17:30 +0000113 OPC_CACHE = (0x2F << 26),
114 OPC_PREF = (0x33 << 26),
115 /* Reserved major opcode */
116 OPC_MAJOR3B_RESERVED = (0x3B << 26),
bellarde37e8632005-07-04 22:17:33 +0000117};
118
119/* MIPS special opcodes */
ths7a387ff2006-12-06 20:17:30 +0000120#define MASK_SPECIAL(op) MASK_OP_MAJOR(op) | (op & 0x3F)
121
bellarde37e8632005-07-04 22:17:33 +0000122enum {
123 /* Shifts */
ths7a387ff2006-12-06 20:17:30 +0000124 OPC_SLL = 0x00 | OPC_SPECIAL,
bellarde37e8632005-07-04 22:17:33 +0000125 /* NOP is SLL r0, r0, 0 */
126 /* SSNOP is SLL r0, r0, 1 */
ths7a387ff2006-12-06 20:17:30 +0000127 /* EHB is SLL r0, r0, 3 */
128 OPC_SRL = 0x02 | OPC_SPECIAL, /* also ROTR */
Nathan Froydea63e2c2009-12-08 08:06:24 -0800129 OPC_ROTR = OPC_SRL | (1 << 21),
ths7a387ff2006-12-06 20:17:30 +0000130 OPC_SRA = 0x03 | OPC_SPECIAL,
131 OPC_SLLV = 0x04 | OPC_SPECIAL,
thse189e742007-09-24 12:48:00 +0000132 OPC_SRLV = 0x06 | OPC_SPECIAL, /* also ROTRV */
Nathan Froydea63e2c2009-12-08 08:06:24 -0800133 OPC_ROTRV = OPC_SRLV | (1 << 6),
ths7a387ff2006-12-06 20:17:30 +0000134 OPC_SRAV = 0x07 | OPC_SPECIAL,
135 OPC_DSLLV = 0x14 | OPC_SPECIAL,
136 OPC_DSRLV = 0x16 | OPC_SPECIAL, /* also DROTRV */
Nathan Froydea63e2c2009-12-08 08:06:24 -0800137 OPC_DROTRV = OPC_DSRLV | (1 << 6),
ths7a387ff2006-12-06 20:17:30 +0000138 OPC_DSRAV = 0x17 | OPC_SPECIAL,
139 OPC_DSLL = 0x38 | OPC_SPECIAL,
140 OPC_DSRL = 0x3A | OPC_SPECIAL, /* also DROTR */
Nathan Froydea63e2c2009-12-08 08:06:24 -0800141 OPC_DROTR = OPC_DSRL | (1 << 21),
ths7a387ff2006-12-06 20:17:30 +0000142 OPC_DSRA = 0x3B | OPC_SPECIAL,
143 OPC_DSLL32 = 0x3C | OPC_SPECIAL,
144 OPC_DSRL32 = 0x3E | OPC_SPECIAL, /* also DROTR32 */
Nathan Froydea63e2c2009-12-08 08:06:24 -0800145 OPC_DROTR32 = OPC_DSRL32 | (1 << 21),
ths7a387ff2006-12-06 20:17:30 +0000146 OPC_DSRA32 = 0x3F | OPC_SPECIAL,
bellarde37e8632005-07-04 22:17:33 +0000147 /* Multiplication / division */
ths7a387ff2006-12-06 20:17:30 +0000148 OPC_MULT = 0x18 | OPC_SPECIAL,
149 OPC_MULTU = 0x19 | OPC_SPECIAL,
150 OPC_DIV = 0x1A | OPC_SPECIAL,
151 OPC_DIVU = 0x1B | OPC_SPECIAL,
152 OPC_DMULT = 0x1C | OPC_SPECIAL,
153 OPC_DMULTU = 0x1D | OPC_SPECIAL,
154 OPC_DDIV = 0x1E | OPC_SPECIAL,
155 OPC_DDIVU = 0x1F | OPC_SPECIAL,
bellarde37e8632005-07-04 22:17:33 +0000156 /* 2 registers arithmetic / logic */
ths7a387ff2006-12-06 20:17:30 +0000157 OPC_ADD = 0x20 | OPC_SPECIAL,
158 OPC_ADDU = 0x21 | OPC_SPECIAL,
159 OPC_SUB = 0x22 | OPC_SPECIAL,
160 OPC_SUBU = 0x23 | OPC_SPECIAL,
161 OPC_AND = 0x24 | OPC_SPECIAL,
162 OPC_OR = 0x25 | OPC_SPECIAL,
163 OPC_XOR = 0x26 | OPC_SPECIAL,
164 OPC_NOR = 0x27 | OPC_SPECIAL,
165 OPC_SLT = 0x2A | OPC_SPECIAL,
166 OPC_SLTU = 0x2B | OPC_SPECIAL,
167 OPC_DADD = 0x2C | OPC_SPECIAL,
168 OPC_DADDU = 0x2D | OPC_SPECIAL,
169 OPC_DSUB = 0x2E | OPC_SPECIAL,
170 OPC_DSUBU = 0x2F | OPC_SPECIAL,
bellarde37e8632005-07-04 22:17:33 +0000171 /* Jumps */
ths7a387ff2006-12-06 20:17:30 +0000172 OPC_JR = 0x08 | OPC_SPECIAL, /* Also JR.HB */
173 OPC_JALR = 0x09 | OPC_SPECIAL, /* Also JALR.HB */
Nathan Froyd364d4832009-12-08 08:06:29 -0800174 OPC_JALRC = OPC_JALR | (0x5 << 6),
Nathan Froyd620e48f2010-06-08 13:29:58 -0700175 OPC_JALRS = 0x10 | OPC_SPECIAL | (0x5 << 6),
bellarde37e8632005-07-04 22:17:33 +0000176 /* Traps */
ths7a387ff2006-12-06 20:17:30 +0000177 OPC_TGE = 0x30 | OPC_SPECIAL,
178 OPC_TGEU = 0x31 | OPC_SPECIAL,
179 OPC_TLT = 0x32 | OPC_SPECIAL,
180 OPC_TLTU = 0x33 | OPC_SPECIAL,
181 OPC_TEQ = 0x34 | OPC_SPECIAL,
182 OPC_TNE = 0x36 | OPC_SPECIAL,
bellarde37e8632005-07-04 22:17:33 +0000183 /* HI / LO registers load & stores */
ths7a387ff2006-12-06 20:17:30 +0000184 OPC_MFHI = 0x10 | OPC_SPECIAL,
185 OPC_MTHI = 0x11 | OPC_SPECIAL,
186 OPC_MFLO = 0x12 | OPC_SPECIAL,
187 OPC_MTLO = 0x13 | OPC_SPECIAL,
bellarde37e8632005-07-04 22:17:33 +0000188 /* Conditional moves */
ths7a387ff2006-12-06 20:17:30 +0000189 OPC_MOVZ = 0x0A | OPC_SPECIAL,
190 OPC_MOVN = 0x0B | OPC_SPECIAL,
bellarde37e8632005-07-04 22:17:33 +0000191
ths7a387ff2006-12-06 20:17:30 +0000192 OPC_MOVCI = 0x01 | OPC_SPECIAL,
bellarde37e8632005-07-04 22:17:33 +0000193
194 /* Special */
Stefan Weila0d700e2009-09-28 23:27:33 +0200195 OPC_PMON = 0x05 | OPC_SPECIAL, /* unofficial */
ths7a387ff2006-12-06 20:17:30 +0000196 OPC_SYSCALL = 0x0C | OPC_SPECIAL,
197 OPC_BREAK = 0x0D | OPC_SPECIAL,
Stefan Weila0d700e2009-09-28 23:27:33 +0200198 OPC_SPIM = 0x0E | OPC_SPECIAL, /* unofficial */
ths7a387ff2006-12-06 20:17:30 +0000199 OPC_SYNC = 0x0F | OPC_SPECIAL,
200
201 OPC_SPECIAL15_RESERVED = 0x15 | OPC_SPECIAL,
202 OPC_SPECIAL28_RESERVED = 0x28 | OPC_SPECIAL,
203 OPC_SPECIAL29_RESERVED = 0x29 | OPC_SPECIAL,
204 OPC_SPECIAL35_RESERVED = 0x35 | OPC_SPECIAL,
205 OPC_SPECIAL37_RESERVED = 0x37 | OPC_SPECIAL,
206 OPC_SPECIAL39_RESERVED = 0x39 | OPC_SPECIAL,
207 OPC_SPECIAL3D_RESERVED = 0x3D | OPC_SPECIAL,
bellarde37e8632005-07-04 22:17:33 +0000208};
209
thse9c71dd2007-12-25 20:46:56 +0000210/* Multiplication variants of the vr54xx. */
211#define MASK_MUL_VR54XX(op) MASK_SPECIAL(op) | (op & (0x1F << 6))
212
213enum {
214 OPC_VR54XX_MULS = (0x03 << 6) | OPC_MULT,
215 OPC_VR54XX_MULSU = (0x03 << 6) | OPC_MULTU,
216 OPC_VR54XX_MACC = (0x05 << 6) | OPC_MULT,
217 OPC_VR54XX_MACCU = (0x05 << 6) | OPC_MULTU,
218 OPC_VR54XX_MSAC = (0x07 << 6) | OPC_MULT,
219 OPC_VR54XX_MSACU = (0x07 << 6) | OPC_MULTU,
220 OPC_VR54XX_MULHI = (0x09 << 6) | OPC_MULT,
221 OPC_VR54XX_MULHIU = (0x09 << 6) | OPC_MULTU,
222 OPC_VR54XX_MULSHI = (0x0B << 6) | OPC_MULT,
223 OPC_VR54XX_MULSHIU = (0x0B << 6) | OPC_MULTU,
224 OPC_VR54XX_MACCHI = (0x0D << 6) | OPC_MULT,
225 OPC_VR54XX_MACCHIU = (0x0D << 6) | OPC_MULTU,
226 OPC_VR54XX_MSACHI = (0x0F << 6) | OPC_MULT,
227 OPC_VR54XX_MSACHIU = (0x0F << 6) | OPC_MULTU,
228};
229
ths7a387ff2006-12-06 20:17:30 +0000230/* REGIMM (rt field) opcodes */
231#define MASK_REGIMM(op) MASK_OP_MAJOR(op) | (op & (0x1F << 16))
232
bellarde37e8632005-07-04 22:17:33 +0000233enum {
ths7a387ff2006-12-06 20:17:30 +0000234 OPC_BLTZ = (0x00 << 16) | OPC_REGIMM,
235 OPC_BLTZL = (0x02 << 16) | OPC_REGIMM,
236 OPC_BGEZ = (0x01 << 16) | OPC_REGIMM,
237 OPC_BGEZL = (0x03 << 16) | OPC_REGIMM,
238 OPC_BLTZAL = (0x10 << 16) | OPC_REGIMM,
Nathan Froyd3c824102010-06-08 13:29:59 -0700239 OPC_BLTZALS = OPC_BLTZAL | 0x5, /* microMIPS */
ths7a387ff2006-12-06 20:17:30 +0000240 OPC_BLTZALL = (0x12 << 16) | OPC_REGIMM,
241 OPC_BGEZAL = (0x11 << 16) | OPC_REGIMM,
Nathan Froyd3c824102010-06-08 13:29:59 -0700242 OPC_BGEZALS = OPC_BGEZAL | 0x5, /* microMIPS */
ths7a387ff2006-12-06 20:17:30 +0000243 OPC_BGEZALL = (0x13 << 16) | OPC_REGIMM,
244 OPC_TGEI = (0x08 << 16) | OPC_REGIMM,
245 OPC_TGEIU = (0x09 << 16) | OPC_REGIMM,
246 OPC_TLTI = (0x0A << 16) | OPC_REGIMM,
247 OPC_TLTIU = (0x0B << 16) | OPC_REGIMM,
248 OPC_TEQI = (0x0C << 16) | OPC_REGIMM,
249 OPC_TNEI = (0x0E << 16) | OPC_REGIMM,
250 OPC_SYNCI = (0x1F << 16) | OPC_REGIMM,
251};
252
253/* Special2 opcodes */
254#define MASK_SPECIAL2(op) MASK_OP_MAJOR(op) | (op & 0x3F)
255
256enum {
257 /* Multiply & xxx operations */
258 OPC_MADD = 0x00 | OPC_SPECIAL2,
259 OPC_MADDU = 0x01 | OPC_SPECIAL2,
260 OPC_MUL = 0x02 | OPC_SPECIAL2,
261 OPC_MSUB = 0x04 | OPC_SPECIAL2,
262 OPC_MSUBU = 0x05 | OPC_SPECIAL2,
Aurelien Jarno161f85e2010-06-18 19:32:43 +0200263 /* Loongson 2F */
264 OPC_MULT_G_2F = 0x10 | OPC_SPECIAL2,
265 OPC_DMULT_G_2F = 0x11 | OPC_SPECIAL2,
266 OPC_MULTU_G_2F = 0x12 | OPC_SPECIAL2,
267 OPC_DMULTU_G_2F = 0x13 | OPC_SPECIAL2,
268 OPC_DIV_G_2F = 0x14 | OPC_SPECIAL2,
269 OPC_DDIV_G_2F = 0x15 | OPC_SPECIAL2,
270 OPC_DIVU_G_2F = 0x16 | OPC_SPECIAL2,
271 OPC_DDIVU_G_2F = 0x17 | OPC_SPECIAL2,
272 OPC_MOD_G_2F = 0x1c | OPC_SPECIAL2,
273 OPC_DMOD_G_2F = 0x1d | OPC_SPECIAL2,
274 OPC_MODU_G_2F = 0x1e | OPC_SPECIAL2,
275 OPC_DMODU_G_2F = 0x1f | OPC_SPECIAL2,
bellarde37e8632005-07-04 22:17:33 +0000276 /* Misc */
ths7a387ff2006-12-06 20:17:30 +0000277 OPC_CLZ = 0x20 | OPC_SPECIAL2,
278 OPC_CLO = 0x21 | OPC_SPECIAL2,
279 OPC_DCLZ = 0x24 | OPC_SPECIAL2,
280 OPC_DCLO = 0x25 | OPC_SPECIAL2,
bellarde37e8632005-07-04 22:17:33 +0000281 /* Special */
ths7a387ff2006-12-06 20:17:30 +0000282 OPC_SDBBP = 0x3F | OPC_SPECIAL2,
bellarde37e8632005-07-04 22:17:33 +0000283};
284
ths7a387ff2006-12-06 20:17:30 +0000285/* Special3 opcodes */
286#define MASK_SPECIAL3(op) MASK_OP_MAJOR(op) | (op & 0x3F)
287
bellarde37e8632005-07-04 22:17:33 +0000288enum {
ths7a387ff2006-12-06 20:17:30 +0000289 OPC_EXT = 0x00 | OPC_SPECIAL3,
290 OPC_DEXTM = 0x01 | OPC_SPECIAL3,
291 OPC_DEXTU = 0x02 | OPC_SPECIAL3,
292 OPC_DEXT = 0x03 | OPC_SPECIAL3,
293 OPC_INS = 0x04 | OPC_SPECIAL3,
294 OPC_DINSM = 0x05 | OPC_SPECIAL3,
295 OPC_DINSU = 0x06 | OPC_SPECIAL3,
296 OPC_DINS = 0x07 | OPC_SPECIAL3,
thsead93602007-09-06 00:18:15 +0000297 OPC_FORK = 0x08 | OPC_SPECIAL3,
298 OPC_YIELD = 0x09 | OPC_SPECIAL3,
ths7a387ff2006-12-06 20:17:30 +0000299 OPC_BSHFL = 0x20 | OPC_SPECIAL3,
300 OPC_DBSHFL = 0x24 | OPC_SPECIAL3,
301 OPC_RDHWR = 0x3B | OPC_SPECIAL3,
Aurelien Jarno161f85e2010-06-18 19:32:43 +0200302
303 /* Loongson 2E */
304 OPC_MULT_G_2E = 0x18 | OPC_SPECIAL3,
305 OPC_MULTU_G_2E = 0x19 | OPC_SPECIAL3,
306 OPC_DIV_G_2E = 0x1A | OPC_SPECIAL3,
307 OPC_DIVU_G_2E = 0x1B | OPC_SPECIAL3,
308 OPC_DMULT_G_2E = 0x1C | OPC_SPECIAL3,
309 OPC_DMULTU_G_2E = 0x1D | OPC_SPECIAL3,
310 OPC_DDIV_G_2E = 0x1E | OPC_SPECIAL3,
311 OPC_DDIVU_G_2E = 0x1F | OPC_SPECIAL3,
312 OPC_MOD_G_2E = 0x22 | OPC_SPECIAL3,
313 OPC_MODU_G_2E = 0x23 | OPC_SPECIAL3,
314 OPC_DMOD_G_2E = 0x26 | OPC_SPECIAL3,
315 OPC_DMODU_G_2E = 0x27 | OPC_SPECIAL3,
Jia Liu9b1a1d62012-10-24 22:17:05 +0800316
317 /* MIPS DSP Load */
318 OPC_LX_DSP = 0x0A | OPC_SPECIAL3,
Jia Liu461c08d2012-10-24 22:17:06 +0800319 /* MIPS DSP Arithmetic */
320 OPC_ADDU_QB_DSP = 0x10 | OPC_SPECIAL3,
Jia Liu461c08d2012-10-24 22:17:06 +0800321 OPC_ADDU_OB_DSP = 0x14 | OPC_SPECIAL3,
Jia Liu461c08d2012-10-24 22:17:06 +0800322 OPC_ABSQ_S_PH_DSP = 0x12 | OPC_SPECIAL3,
Jia Liu461c08d2012-10-24 22:17:06 +0800323 OPC_ABSQ_S_QH_DSP = 0x16 | OPC_SPECIAL3,
Jia Liu461c08d2012-10-24 22:17:06 +0800324 /* OPC_ADDUH_QB_DSP is same as OPC_MULT_G_2E. */
325 /* OPC_ADDUH_QB_DSP = 0x18 | OPC_SPECIAL3, */
326 OPC_CMPU_EQ_QB_DSP = 0x11 | OPC_SPECIAL3,
Jia Liu461c08d2012-10-24 22:17:06 +0800327 OPC_CMPU_EQ_OB_DSP = 0x15 | OPC_SPECIAL3,
Jia Liu77c5fa82012-10-24 22:17:07 +0800328 /* MIPS DSP GPR-Based Shift Sub-class */
329 OPC_SHLL_QB_DSP = 0x13 | OPC_SPECIAL3,
Jia Liu77c5fa82012-10-24 22:17:07 +0800330 OPC_SHLL_OB_DSP = 0x17 | OPC_SPECIAL3,
Jia Liu77c5fa82012-10-24 22:17:07 +0800331 /* MIPS DSP Multiply Sub-class insns */
332 /* OPC_MUL_PH_DSP is same as OPC_ADDUH_QB_DSP. */
333 /* OPC_MUL_PH_DSP = 0x18 | OPC_SPECIAL3, */
334 OPC_DPA_W_PH_DSP = 0x30 | OPC_SPECIAL3,
Jia Liu77c5fa82012-10-24 22:17:07 +0800335 OPC_DPAQ_W_QH_DSP = 0x34 | OPC_SPECIAL3,
Jia Liu1cb66862012-10-24 22:17:09 +0800336 /* DSP Bit/Manipulation Sub-class */
337 OPC_INSV_DSP = 0x0C | OPC_SPECIAL3,
Jia Liu1cb66862012-10-24 22:17:09 +0800338 OPC_DINSV_DSP = 0x0D | OPC_SPECIAL3,
Aurelien Jarnodf6126a2013-01-01 18:02:24 +0100339 /* MIPS DSP Append Sub-class */
Jia Liu26690562012-10-24 22:17:10 +0800340 OPC_APPEND_DSP = 0x31 | OPC_SPECIAL3,
Jia Liu26690562012-10-24 22:17:10 +0800341 OPC_DAPPEND_DSP = 0x35 | OPC_SPECIAL3,
Jia Liub53371e2012-10-24 22:17:11 +0800342 /* MIPS DSP Accumulator and DSPControl Access Sub-class */
343 OPC_EXTR_W_DSP = 0x38 | OPC_SPECIAL3,
Jia Liub53371e2012-10-24 22:17:11 +0800344 OPC_DEXTR_W_DSP = 0x3C | OPC_SPECIAL3,
ths7a387ff2006-12-06 20:17:30 +0000345};
346
347/* BSHFL opcodes */
348#define MASK_BSHFL(op) MASK_SPECIAL3(op) | (op & (0x1F << 6))
349
350enum {
351 OPC_WSBH = (0x02 << 6) | OPC_BSHFL,
352 OPC_SEB = (0x10 << 6) | OPC_BSHFL,
353 OPC_SEH = (0x18 << 6) | OPC_BSHFL,
354};
355
356/* DBSHFL opcodes */
357#define MASK_DBSHFL(op) MASK_SPECIAL3(op) | (op & (0x1F << 6))
358
359enum {
360 OPC_DSBH = (0x02 << 6) | OPC_DBSHFL,
361 OPC_DSHD = (0x05 << 6) | OPC_DBSHFL,
362};
363
Jia Liue45a93e2012-10-24 22:17:04 +0800364/* MIPS DSP REGIMM opcodes */
365enum {
366 OPC_BPOSGE32 = (0x1C << 16) | OPC_REGIMM,
Jia Liue45a93e2012-10-24 22:17:04 +0800367 OPC_BPOSGE64 = (0x1D << 16) | OPC_REGIMM,
Jia Liue45a93e2012-10-24 22:17:04 +0800368};
369
Jia Liu9b1a1d62012-10-24 22:17:05 +0800370#define MASK_LX(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
371/* MIPS DSP Load */
372enum {
373 OPC_LBUX = (0x06 << 6) | OPC_LX_DSP,
374 OPC_LHX = (0x04 << 6) | OPC_LX_DSP,
375 OPC_LWX = (0x00 << 6) | OPC_LX_DSP,
Jia Liu9b1a1d62012-10-24 22:17:05 +0800376 OPC_LDX = (0x08 << 6) | OPC_LX_DSP,
Jia Liu9b1a1d62012-10-24 22:17:05 +0800377};
378
Jia Liu461c08d2012-10-24 22:17:06 +0800379#define MASK_ADDU_QB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
380enum {
381 /* MIPS DSP Arithmetic Sub-class */
382 OPC_ADDQ_PH = (0x0A << 6) | OPC_ADDU_QB_DSP,
383 OPC_ADDQ_S_PH = (0x0E << 6) | OPC_ADDU_QB_DSP,
384 OPC_ADDQ_S_W = (0x16 << 6) | OPC_ADDU_QB_DSP,
385 OPC_ADDU_QB = (0x00 << 6) | OPC_ADDU_QB_DSP,
386 OPC_ADDU_S_QB = (0x04 << 6) | OPC_ADDU_QB_DSP,
387 OPC_ADDU_PH = (0x08 << 6) | OPC_ADDU_QB_DSP,
388 OPC_ADDU_S_PH = (0x0C << 6) | OPC_ADDU_QB_DSP,
389 OPC_SUBQ_PH = (0x0B << 6) | OPC_ADDU_QB_DSP,
390 OPC_SUBQ_S_PH = (0x0F << 6) | OPC_ADDU_QB_DSP,
391 OPC_SUBQ_S_W = (0x17 << 6) | OPC_ADDU_QB_DSP,
392 OPC_SUBU_QB = (0x01 << 6) | OPC_ADDU_QB_DSP,
393 OPC_SUBU_S_QB = (0x05 << 6) | OPC_ADDU_QB_DSP,
394 OPC_SUBU_PH = (0x09 << 6) | OPC_ADDU_QB_DSP,
395 OPC_SUBU_S_PH = (0x0D << 6) | OPC_ADDU_QB_DSP,
396 OPC_ADDSC = (0x10 << 6) | OPC_ADDU_QB_DSP,
397 OPC_ADDWC = (0x11 << 6) | OPC_ADDU_QB_DSP,
398 OPC_MODSUB = (0x12 << 6) | OPC_ADDU_QB_DSP,
399 OPC_RADDU_W_QB = (0x14 << 6) | OPC_ADDU_QB_DSP,
Jia Liua22260a2012-10-24 22:17:08 +0800400 /* MIPS DSP Multiply Sub-class insns */
401 OPC_MULEU_S_PH_QBL = (0x06 << 6) | OPC_ADDU_QB_DSP,
402 OPC_MULEU_S_PH_QBR = (0x07 << 6) | OPC_ADDU_QB_DSP,
403 OPC_MULQ_RS_PH = (0x1F << 6) | OPC_ADDU_QB_DSP,
404 OPC_MULEQ_S_W_PHL = (0x1C << 6) | OPC_ADDU_QB_DSP,
405 OPC_MULEQ_S_W_PHR = (0x1D << 6) | OPC_ADDU_QB_DSP,
406 OPC_MULQ_S_PH = (0x1E << 6) | OPC_ADDU_QB_DSP,
Jia Liu461c08d2012-10-24 22:17:06 +0800407};
408
409#define OPC_ADDUH_QB_DSP OPC_MULT_G_2E
410#define MASK_ADDUH_QB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
411enum {
412 /* MIPS DSP Arithmetic Sub-class */
413 OPC_ADDUH_QB = (0x00 << 6) | OPC_ADDUH_QB_DSP,
414 OPC_ADDUH_R_QB = (0x02 << 6) | OPC_ADDUH_QB_DSP,
415 OPC_ADDQH_PH = (0x08 << 6) | OPC_ADDUH_QB_DSP,
416 OPC_ADDQH_R_PH = (0x0A << 6) | OPC_ADDUH_QB_DSP,
417 OPC_ADDQH_W = (0x10 << 6) | OPC_ADDUH_QB_DSP,
418 OPC_ADDQH_R_W = (0x12 << 6) | OPC_ADDUH_QB_DSP,
419 OPC_SUBUH_QB = (0x01 << 6) | OPC_ADDUH_QB_DSP,
420 OPC_SUBUH_R_QB = (0x03 << 6) | OPC_ADDUH_QB_DSP,
421 OPC_SUBQH_PH = (0x09 << 6) | OPC_ADDUH_QB_DSP,
422 OPC_SUBQH_R_PH = (0x0B << 6) | OPC_ADDUH_QB_DSP,
423 OPC_SUBQH_W = (0x11 << 6) | OPC_ADDUH_QB_DSP,
424 OPC_SUBQH_R_W = (0x13 << 6) | OPC_ADDUH_QB_DSP,
Jia Liua22260a2012-10-24 22:17:08 +0800425 /* MIPS DSP Multiply Sub-class insns */
426 OPC_MUL_PH = (0x0C << 6) | OPC_ADDUH_QB_DSP,
427 OPC_MUL_S_PH = (0x0E << 6) | OPC_ADDUH_QB_DSP,
428 OPC_MULQ_S_W = (0x16 << 6) | OPC_ADDUH_QB_DSP,
429 OPC_MULQ_RS_W = (0x17 << 6) | OPC_ADDUH_QB_DSP,
Jia Liu461c08d2012-10-24 22:17:06 +0800430};
431
432#define MASK_ABSQ_S_PH(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
433enum {
434 /* MIPS DSP Arithmetic Sub-class */
435 OPC_ABSQ_S_QB = (0x01 << 6) | OPC_ABSQ_S_PH_DSP,
436 OPC_ABSQ_S_PH = (0x09 << 6) | OPC_ABSQ_S_PH_DSP,
437 OPC_ABSQ_S_W = (0x11 << 6) | OPC_ABSQ_S_PH_DSP,
438 OPC_PRECEQ_W_PHL = (0x0C << 6) | OPC_ABSQ_S_PH_DSP,
439 OPC_PRECEQ_W_PHR = (0x0D << 6) | OPC_ABSQ_S_PH_DSP,
440 OPC_PRECEQU_PH_QBL = (0x04 << 6) | OPC_ABSQ_S_PH_DSP,
441 OPC_PRECEQU_PH_QBR = (0x05 << 6) | OPC_ABSQ_S_PH_DSP,
442 OPC_PRECEQU_PH_QBLA = (0x06 << 6) | OPC_ABSQ_S_PH_DSP,
443 OPC_PRECEQU_PH_QBRA = (0x07 << 6) | OPC_ABSQ_S_PH_DSP,
444 OPC_PRECEU_PH_QBL = (0x1C << 6) | OPC_ABSQ_S_PH_DSP,
445 OPC_PRECEU_PH_QBR = (0x1D << 6) | OPC_ABSQ_S_PH_DSP,
446 OPC_PRECEU_PH_QBLA = (0x1E << 6) | OPC_ABSQ_S_PH_DSP,
447 OPC_PRECEU_PH_QBRA = (0x1F << 6) | OPC_ABSQ_S_PH_DSP,
Jia Liu1cb66862012-10-24 22:17:09 +0800448 /* DSP Bit/Manipulation Sub-class */
449 OPC_BITREV = (0x1B << 6) | OPC_ABSQ_S_PH_DSP,
450 OPC_REPL_QB = (0x02 << 6) | OPC_ABSQ_S_PH_DSP,
451 OPC_REPLV_QB = (0x03 << 6) | OPC_ABSQ_S_PH_DSP,
452 OPC_REPL_PH = (0x0A << 6) | OPC_ABSQ_S_PH_DSP,
453 OPC_REPLV_PH = (0x0B << 6) | OPC_ABSQ_S_PH_DSP,
Jia Liu461c08d2012-10-24 22:17:06 +0800454};
455
456#define MASK_CMPU_EQ_QB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
457enum {
458 /* MIPS DSP Arithmetic Sub-class */
459 OPC_PRECR_QB_PH = (0x0D << 6) | OPC_CMPU_EQ_QB_DSP,
460 OPC_PRECRQ_QB_PH = (0x0C << 6) | OPC_CMPU_EQ_QB_DSP,
461 OPC_PRECR_SRA_PH_W = (0x1E << 6) | OPC_CMPU_EQ_QB_DSP,
462 OPC_PRECR_SRA_R_PH_W = (0x1F << 6) | OPC_CMPU_EQ_QB_DSP,
463 OPC_PRECRQ_PH_W = (0x14 << 6) | OPC_CMPU_EQ_QB_DSP,
464 OPC_PRECRQ_RS_PH_W = (0x15 << 6) | OPC_CMPU_EQ_QB_DSP,
465 OPC_PRECRQU_S_QB_PH = (0x0F << 6) | OPC_CMPU_EQ_QB_DSP,
Jia Liu26690562012-10-24 22:17:10 +0800466 /* DSP Compare-Pick Sub-class */
467 OPC_CMPU_EQ_QB = (0x00 << 6) | OPC_CMPU_EQ_QB_DSP,
468 OPC_CMPU_LT_QB = (0x01 << 6) | OPC_CMPU_EQ_QB_DSP,
469 OPC_CMPU_LE_QB = (0x02 << 6) | OPC_CMPU_EQ_QB_DSP,
470 OPC_CMPGU_EQ_QB = (0x04 << 6) | OPC_CMPU_EQ_QB_DSP,
471 OPC_CMPGU_LT_QB = (0x05 << 6) | OPC_CMPU_EQ_QB_DSP,
472 OPC_CMPGU_LE_QB = (0x06 << 6) | OPC_CMPU_EQ_QB_DSP,
473 OPC_CMPGDU_EQ_QB = (0x18 << 6) | OPC_CMPU_EQ_QB_DSP,
474 OPC_CMPGDU_LT_QB = (0x19 << 6) | OPC_CMPU_EQ_QB_DSP,
475 OPC_CMPGDU_LE_QB = (0x1A << 6) | OPC_CMPU_EQ_QB_DSP,
476 OPC_CMP_EQ_PH = (0x08 << 6) | OPC_CMPU_EQ_QB_DSP,
477 OPC_CMP_LT_PH = (0x09 << 6) | OPC_CMPU_EQ_QB_DSP,
478 OPC_CMP_LE_PH = (0x0A << 6) | OPC_CMPU_EQ_QB_DSP,
479 OPC_PICK_QB = (0x03 << 6) | OPC_CMPU_EQ_QB_DSP,
480 OPC_PICK_PH = (0x0B << 6) | OPC_CMPU_EQ_QB_DSP,
481 OPC_PACKRL_PH = (0x0E << 6) | OPC_CMPU_EQ_QB_DSP,
Jia Liu461c08d2012-10-24 22:17:06 +0800482};
Jia Liua22260a2012-10-24 22:17:08 +0800483
Jia Liu77c5fa82012-10-24 22:17:07 +0800484#define MASK_SHLL_QB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
485enum {
486 /* MIPS DSP GPR-Based Shift Sub-class */
487 OPC_SHLL_QB = (0x00 << 6) | OPC_SHLL_QB_DSP,
488 OPC_SHLLV_QB = (0x02 << 6) | OPC_SHLL_QB_DSP,
489 OPC_SHLL_PH = (0x08 << 6) | OPC_SHLL_QB_DSP,
490 OPC_SHLLV_PH = (0x0A << 6) | OPC_SHLL_QB_DSP,
491 OPC_SHLL_S_PH = (0x0C << 6) | OPC_SHLL_QB_DSP,
492 OPC_SHLLV_S_PH = (0x0E << 6) | OPC_SHLL_QB_DSP,
493 OPC_SHLL_S_W = (0x14 << 6) | OPC_SHLL_QB_DSP,
494 OPC_SHLLV_S_W = (0x16 << 6) | OPC_SHLL_QB_DSP,
495 OPC_SHRL_QB = (0x01 << 6) | OPC_SHLL_QB_DSP,
496 OPC_SHRLV_QB = (0x03 << 6) | OPC_SHLL_QB_DSP,
497 OPC_SHRL_PH = (0x19 << 6) | OPC_SHLL_QB_DSP,
498 OPC_SHRLV_PH = (0x1B << 6) | OPC_SHLL_QB_DSP,
499 OPC_SHRA_QB = (0x04 << 6) | OPC_SHLL_QB_DSP,
500 OPC_SHRA_R_QB = (0x05 << 6) | OPC_SHLL_QB_DSP,
501 OPC_SHRAV_QB = (0x06 << 6) | OPC_SHLL_QB_DSP,
502 OPC_SHRAV_R_QB = (0x07 << 6) | OPC_SHLL_QB_DSP,
503 OPC_SHRA_PH = (0x09 << 6) | OPC_SHLL_QB_DSP,
504 OPC_SHRAV_PH = (0x0B << 6) | OPC_SHLL_QB_DSP,
505 OPC_SHRA_R_PH = (0x0D << 6) | OPC_SHLL_QB_DSP,
506 OPC_SHRAV_R_PH = (0x0F << 6) | OPC_SHLL_QB_DSP,
507 OPC_SHRA_R_W = (0x15 << 6) | OPC_SHLL_QB_DSP,
508 OPC_SHRAV_R_W = (0x17 << 6) | OPC_SHLL_QB_DSP,
509};
Jia Liu461c08d2012-10-24 22:17:06 +0800510
Jia Liua22260a2012-10-24 22:17:08 +0800511#define MASK_DPA_W_PH(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
512enum {
513 /* MIPS DSP Multiply Sub-class insns */
514 OPC_DPAU_H_QBL = (0x03 << 6) | OPC_DPA_W_PH_DSP,
515 OPC_DPAU_H_QBR = (0x07 << 6) | OPC_DPA_W_PH_DSP,
516 OPC_DPSU_H_QBL = (0x0B << 6) | OPC_DPA_W_PH_DSP,
517 OPC_DPSU_H_QBR = (0x0F << 6) | OPC_DPA_W_PH_DSP,
518 OPC_DPA_W_PH = (0x00 << 6) | OPC_DPA_W_PH_DSP,
519 OPC_DPAX_W_PH = (0x08 << 6) | OPC_DPA_W_PH_DSP,
520 OPC_DPAQ_S_W_PH = (0x04 << 6) | OPC_DPA_W_PH_DSP,
521 OPC_DPAQX_S_W_PH = (0x18 << 6) | OPC_DPA_W_PH_DSP,
522 OPC_DPAQX_SA_W_PH = (0x1A << 6) | OPC_DPA_W_PH_DSP,
523 OPC_DPS_W_PH = (0x01 << 6) | OPC_DPA_W_PH_DSP,
524 OPC_DPSX_W_PH = (0x09 << 6) | OPC_DPA_W_PH_DSP,
525 OPC_DPSQ_S_W_PH = (0x05 << 6) | OPC_DPA_W_PH_DSP,
526 OPC_DPSQX_S_W_PH = (0x19 << 6) | OPC_DPA_W_PH_DSP,
527 OPC_DPSQX_SA_W_PH = (0x1B << 6) | OPC_DPA_W_PH_DSP,
528 OPC_MULSAQ_S_W_PH = (0x06 << 6) | OPC_DPA_W_PH_DSP,
529 OPC_DPAQ_SA_L_W = (0x0C << 6) | OPC_DPA_W_PH_DSP,
530 OPC_DPSQ_SA_L_W = (0x0D << 6) | OPC_DPA_W_PH_DSP,
531 OPC_MAQ_S_W_PHL = (0x14 << 6) | OPC_DPA_W_PH_DSP,
532 OPC_MAQ_S_W_PHR = (0x16 << 6) | OPC_DPA_W_PH_DSP,
533 OPC_MAQ_SA_W_PHL = (0x10 << 6) | OPC_DPA_W_PH_DSP,
534 OPC_MAQ_SA_W_PHR = (0x12 << 6) | OPC_DPA_W_PH_DSP,
535 OPC_MULSA_W_PH = (0x02 << 6) | OPC_DPA_W_PH_DSP,
536};
537
Jia Liu1cb66862012-10-24 22:17:09 +0800538#define MASK_INSV(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
539enum {
540 /* DSP Bit/Manipulation Sub-class */
541 OPC_INSV = (0x00 << 6) | OPC_INSV_DSP,
542};
543
Jia Liu26690562012-10-24 22:17:10 +0800544#define MASK_APPEND(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
545enum {
Aurelien Jarnodf6126a2013-01-01 18:02:24 +0100546 /* MIPS DSP Append Sub-class */
Jia Liu26690562012-10-24 22:17:10 +0800547 OPC_APPEND = (0x00 << 6) | OPC_APPEND_DSP,
548 OPC_PREPEND = (0x01 << 6) | OPC_APPEND_DSP,
549 OPC_BALIGN = (0x10 << 6) | OPC_APPEND_DSP,
550};
551
Jia Liub53371e2012-10-24 22:17:11 +0800552#define MASK_EXTR_W(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
553enum {
554 /* MIPS DSP Accumulator and DSPControl Access Sub-class */
555 OPC_EXTR_W = (0x00 << 6) | OPC_EXTR_W_DSP,
556 OPC_EXTR_R_W = (0x04 << 6) | OPC_EXTR_W_DSP,
557 OPC_EXTR_RS_W = (0x06 << 6) | OPC_EXTR_W_DSP,
558 OPC_EXTR_S_H = (0x0E << 6) | OPC_EXTR_W_DSP,
559 OPC_EXTRV_S_H = (0x0F << 6) | OPC_EXTR_W_DSP,
560 OPC_EXTRV_W = (0x01 << 6) | OPC_EXTR_W_DSP,
561 OPC_EXTRV_R_W = (0x05 << 6) | OPC_EXTR_W_DSP,
562 OPC_EXTRV_RS_W = (0x07 << 6) | OPC_EXTR_W_DSP,
563 OPC_EXTP = (0x02 << 6) | OPC_EXTR_W_DSP,
564 OPC_EXTPV = (0x03 << 6) | OPC_EXTR_W_DSP,
565 OPC_EXTPDP = (0x0A << 6) | OPC_EXTR_W_DSP,
566 OPC_EXTPDPV = (0x0B << 6) | OPC_EXTR_W_DSP,
567 OPC_SHILO = (0x1A << 6) | OPC_EXTR_W_DSP,
568 OPC_SHILOV = (0x1B << 6) | OPC_EXTR_W_DSP,
569 OPC_MTHLIP = (0x1F << 6) | OPC_EXTR_W_DSP,
570 OPC_WRDSP = (0x13 << 6) | OPC_EXTR_W_DSP,
571 OPC_RDDSP = (0x12 << 6) | OPC_EXTR_W_DSP,
572};
573
Jia Liu461c08d2012-10-24 22:17:06 +0800574#define MASK_ABSQ_S_QH(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
575enum {
576 /* MIPS DSP Arithmetic Sub-class */
577 OPC_PRECEQ_L_PWL = (0x14 << 6) | OPC_ABSQ_S_QH_DSP,
578 OPC_PRECEQ_L_PWR = (0x15 << 6) | OPC_ABSQ_S_QH_DSP,
579 OPC_PRECEQ_PW_QHL = (0x0C << 6) | OPC_ABSQ_S_QH_DSP,
580 OPC_PRECEQ_PW_QHR = (0x0D << 6) | OPC_ABSQ_S_QH_DSP,
581 OPC_PRECEQ_PW_QHLA = (0x0E << 6) | OPC_ABSQ_S_QH_DSP,
582 OPC_PRECEQ_PW_QHRA = (0x0F << 6) | OPC_ABSQ_S_QH_DSP,
583 OPC_PRECEQU_QH_OBL = (0x04 << 6) | OPC_ABSQ_S_QH_DSP,
584 OPC_PRECEQU_QH_OBR = (0x05 << 6) | OPC_ABSQ_S_QH_DSP,
585 OPC_PRECEQU_QH_OBLA = (0x06 << 6) | OPC_ABSQ_S_QH_DSP,
586 OPC_PRECEQU_QH_OBRA = (0x07 << 6) | OPC_ABSQ_S_QH_DSP,
587 OPC_PRECEU_QH_OBL = (0x1C << 6) | OPC_ABSQ_S_QH_DSP,
588 OPC_PRECEU_QH_OBR = (0x1D << 6) | OPC_ABSQ_S_QH_DSP,
589 OPC_PRECEU_QH_OBLA = (0x1E << 6) | OPC_ABSQ_S_QH_DSP,
590 OPC_PRECEU_QH_OBRA = (0x1F << 6) | OPC_ABSQ_S_QH_DSP,
591 OPC_ABSQ_S_OB = (0x01 << 6) | OPC_ABSQ_S_QH_DSP,
592 OPC_ABSQ_S_PW = (0x11 << 6) | OPC_ABSQ_S_QH_DSP,
593 OPC_ABSQ_S_QH = (0x09 << 6) | OPC_ABSQ_S_QH_DSP,
Jia Liu1cb66862012-10-24 22:17:09 +0800594 /* DSP Bit/Manipulation Sub-class */
595 OPC_REPL_OB = (0x02 << 6) | OPC_ABSQ_S_QH_DSP,
596 OPC_REPL_PW = (0x12 << 6) | OPC_ABSQ_S_QH_DSP,
597 OPC_REPL_QH = (0x0A << 6) | OPC_ABSQ_S_QH_DSP,
598 OPC_REPLV_OB = (0x03 << 6) | OPC_ABSQ_S_QH_DSP,
599 OPC_REPLV_PW = (0x13 << 6) | OPC_ABSQ_S_QH_DSP,
600 OPC_REPLV_QH = (0x0B << 6) | OPC_ABSQ_S_QH_DSP,
Jia Liu461c08d2012-10-24 22:17:06 +0800601};
Jia Liu461c08d2012-10-24 22:17:06 +0800602
Jia Liu461c08d2012-10-24 22:17:06 +0800603#define MASK_ADDU_OB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
604enum {
Jia Liua22260a2012-10-24 22:17:08 +0800605 /* MIPS DSP Multiply Sub-class insns */
606 OPC_MULEQ_S_PW_QHL = (0x1C << 6) | OPC_ADDU_OB_DSP,
607 OPC_MULEQ_S_PW_QHR = (0x1D << 6) | OPC_ADDU_OB_DSP,
608 OPC_MULEU_S_QH_OBL = (0x06 << 6) | OPC_ADDU_OB_DSP,
609 OPC_MULEU_S_QH_OBR = (0x07 << 6) | OPC_ADDU_OB_DSP,
610 OPC_MULQ_RS_QH = (0x1F << 6) | OPC_ADDU_OB_DSP,
Jia Liu461c08d2012-10-24 22:17:06 +0800611 /* MIPS DSP Arithmetic Sub-class */
612 OPC_RADDU_L_OB = (0x14 << 6) | OPC_ADDU_OB_DSP,
613 OPC_SUBQ_PW = (0x13 << 6) | OPC_ADDU_OB_DSP,
614 OPC_SUBQ_S_PW = (0x17 << 6) | OPC_ADDU_OB_DSP,
615 OPC_SUBQ_QH = (0x0B << 6) | OPC_ADDU_OB_DSP,
616 OPC_SUBQ_S_QH = (0x0F << 6) | OPC_ADDU_OB_DSP,
617 OPC_SUBU_OB = (0x01 << 6) | OPC_ADDU_OB_DSP,
618 OPC_SUBU_S_OB = (0x05 << 6) | OPC_ADDU_OB_DSP,
619 OPC_SUBU_QH = (0x09 << 6) | OPC_ADDU_OB_DSP,
620 OPC_SUBU_S_QH = (0x0D << 6) | OPC_ADDU_OB_DSP,
621 OPC_SUBUH_OB = (0x19 << 6) | OPC_ADDU_OB_DSP,
622 OPC_SUBUH_R_OB = (0x1B << 6) | OPC_ADDU_OB_DSP,
623 OPC_ADDQ_PW = (0x12 << 6) | OPC_ADDU_OB_DSP,
624 OPC_ADDQ_S_PW = (0x16 << 6) | OPC_ADDU_OB_DSP,
625 OPC_ADDQ_QH = (0x0A << 6) | OPC_ADDU_OB_DSP,
626 OPC_ADDQ_S_QH = (0x0E << 6) | OPC_ADDU_OB_DSP,
627 OPC_ADDU_OB = (0x00 << 6) | OPC_ADDU_OB_DSP,
628 OPC_ADDU_S_OB = (0x04 << 6) | OPC_ADDU_OB_DSP,
629 OPC_ADDU_QH = (0x08 << 6) | OPC_ADDU_OB_DSP,
630 OPC_ADDU_S_QH = (0x0C << 6) | OPC_ADDU_OB_DSP,
631 OPC_ADDUH_OB = (0x18 << 6) | OPC_ADDU_OB_DSP,
632 OPC_ADDUH_R_OB = (0x1A << 6) | OPC_ADDU_OB_DSP,
633};
Jia Liu461c08d2012-10-24 22:17:06 +0800634
Jia Liu461c08d2012-10-24 22:17:06 +0800635#define MASK_CMPU_EQ_OB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
636enum {
Jia Liu26690562012-10-24 22:17:10 +0800637 /* DSP Compare-Pick Sub-class */
638 OPC_CMP_EQ_PW = (0x10 << 6) | OPC_CMPU_EQ_OB_DSP,
639 OPC_CMP_LT_PW = (0x11 << 6) | OPC_CMPU_EQ_OB_DSP,
640 OPC_CMP_LE_PW = (0x12 << 6) | OPC_CMPU_EQ_OB_DSP,
641 OPC_CMP_EQ_QH = (0x08 << 6) | OPC_CMPU_EQ_OB_DSP,
642 OPC_CMP_LT_QH = (0x09 << 6) | OPC_CMPU_EQ_OB_DSP,
643 OPC_CMP_LE_QH = (0x0A << 6) | OPC_CMPU_EQ_OB_DSP,
644 OPC_CMPGDU_EQ_OB = (0x18 << 6) | OPC_CMPU_EQ_OB_DSP,
645 OPC_CMPGDU_LT_OB = (0x19 << 6) | OPC_CMPU_EQ_OB_DSP,
646 OPC_CMPGDU_LE_OB = (0x1A << 6) | OPC_CMPU_EQ_OB_DSP,
647 OPC_CMPGU_EQ_OB = (0x04 << 6) | OPC_CMPU_EQ_OB_DSP,
648 OPC_CMPGU_LT_OB = (0x05 << 6) | OPC_CMPU_EQ_OB_DSP,
649 OPC_CMPGU_LE_OB = (0x06 << 6) | OPC_CMPU_EQ_OB_DSP,
650 OPC_CMPU_EQ_OB = (0x00 << 6) | OPC_CMPU_EQ_OB_DSP,
651 OPC_CMPU_LT_OB = (0x01 << 6) | OPC_CMPU_EQ_OB_DSP,
652 OPC_CMPU_LE_OB = (0x02 << 6) | OPC_CMPU_EQ_OB_DSP,
653 OPC_PACKRL_PW = (0x0E << 6) | OPC_CMPU_EQ_OB_DSP,
654 OPC_PICK_OB = (0x03 << 6) | OPC_CMPU_EQ_OB_DSP,
655 OPC_PICK_PW = (0x13 << 6) | OPC_CMPU_EQ_OB_DSP,
656 OPC_PICK_QH = (0x0B << 6) | OPC_CMPU_EQ_OB_DSP,
Jia Liu461c08d2012-10-24 22:17:06 +0800657 /* MIPS DSP Arithmetic Sub-class */
658 OPC_PRECR_OB_QH = (0x0D << 6) | OPC_CMPU_EQ_OB_DSP,
659 OPC_PRECR_SRA_QH_PW = (0x1E << 6) | OPC_CMPU_EQ_OB_DSP,
660 OPC_PRECR_SRA_R_QH_PW = (0x1F << 6) | OPC_CMPU_EQ_OB_DSP,
661 OPC_PRECRQ_OB_QH = (0x0C << 6) | OPC_CMPU_EQ_OB_DSP,
662 OPC_PRECRQ_PW_L = (0x1C << 6) | OPC_CMPU_EQ_OB_DSP,
663 OPC_PRECRQ_QH_PW = (0x14 << 6) | OPC_CMPU_EQ_OB_DSP,
664 OPC_PRECRQ_RS_QH_PW = (0x15 << 6) | OPC_CMPU_EQ_OB_DSP,
665 OPC_PRECRQU_S_OB_QH = (0x0F << 6) | OPC_CMPU_EQ_OB_DSP,
666};
Jia Liu461c08d2012-10-24 22:17:06 +0800667
Jia Liu26690562012-10-24 22:17:10 +0800668#define MASK_DAPPEND(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
669enum {
Aurelien Jarnodf6126a2013-01-01 18:02:24 +0100670 /* DSP Append Sub-class */
Jia Liu26690562012-10-24 22:17:10 +0800671 OPC_DAPPEND = (0x00 << 6) | OPC_DAPPEND_DSP,
672 OPC_PREPENDD = (0x03 << 6) | OPC_DAPPEND_DSP,
673 OPC_PREPENDW = (0x01 << 6) | OPC_DAPPEND_DSP,
674 OPC_DBALIGN = (0x10 << 6) | OPC_DAPPEND_DSP,
675};
Jia Liu26690562012-10-24 22:17:10 +0800676
Jia Liub53371e2012-10-24 22:17:11 +0800677#define MASK_DEXTR_W(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
678enum {
679 /* MIPS DSP Accumulator and DSPControl Access Sub-class */
680 OPC_DMTHLIP = (0x1F << 6) | OPC_DEXTR_W_DSP,
681 OPC_DSHILO = (0x1A << 6) | OPC_DEXTR_W_DSP,
682 OPC_DEXTP = (0x02 << 6) | OPC_DEXTR_W_DSP,
683 OPC_DEXTPDP = (0x0A << 6) | OPC_DEXTR_W_DSP,
684 OPC_DEXTPDPV = (0x0B << 6) | OPC_DEXTR_W_DSP,
685 OPC_DEXTPV = (0x03 << 6) | OPC_DEXTR_W_DSP,
686 OPC_DEXTR_L = (0x10 << 6) | OPC_DEXTR_W_DSP,
687 OPC_DEXTR_R_L = (0x14 << 6) | OPC_DEXTR_W_DSP,
688 OPC_DEXTR_RS_L = (0x16 << 6) | OPC_DEXTR_W_DSP,
689 OPC_DEXTR_W = (0x00 << 6) | OPC_DEXTR_W_DSP,
690 OPC_DEXTR_R_W = (0x04 << 6) | OPC_DEXTR_W_DSP,
691 OPC_DEXTR_RS_W = (0x06 << 6) | OPC_DEXTR_W_DSP,
692 OPC_DEXTR_S_H = (0x0E << 6) | OPC_DEXTR_W_DSP,
693 OPC_DEXTRV_L = (0x11 << 6) | OPC_DEXTR_W_DSP,
694 OPC_DEXTRV_R_L = (0x15 << 6) | OPC_DEXTR_W_DSP,
695 OPC_DEXTRV_RS_L = (0x17 << 6) | OPC_DEXTR_W_DSP,
696 OPC_DEXTRV_S_H = (0x0F << 6) | OPC_DEXTR_W_DSP,
697 OPC_DEXTRV_W = (0x01 << 6) | OPC_DEXTR_W_DSP,
698 OPC_DEXTRV_R_W = (0x05 << 6) | OPC_DEXTR_W_DSP,
699 OPC_DEXTRV_RS_W = (0x07 << 6) | OPC_DEXTR_W_DSP,
700 OPC_DSHILOV = (0x1B << 6) | OPC_DEXTR_W_DSP,
701};
702
Jia Liu1cb66862012-10-24 22:17:09 +0800703#define MASK_DINSV(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
704enum {
705 /* DSP Bit/Manipulation Sub-class */
706 OPC_DINSV = (0x00 << 6) | OPC_DINSV_DSP,
707};
Jia Liu1cb66862012-10-24 22:17:09 +0800708
Jia Liua22260a2012-10-24 22:17:08 +0800709#define MASK_DPAQ_W_QH(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
710enum {
711 /* MIPS DSP Multiply Sub-class insns */
712 OPC_DMADD = (0x19 << 6) | OPC_DPAQ_W_QH_DSP,
713 OPC_DMADDU = (0x1D << 6) | OPC_DPAQ_W_QH_DSP,
714 OPC_DMSUB = (0x1B << 6) | OPC_DPAQ_W_QH_DSP,
715 OPC_DMSUBU = (0x1F << 6) | OPC_DPAQ_W_QH_DSP,
716 OPC_DPA_W_QH = (0x00 << 6) | OPC_DPAQ_W_QH_DSP,
717 OPC_DPAQ_S_W_QH = (0x04 << 6) | OPC_DPAQ_W_QH_DSP,
718 OPC_DPAQ_SA_L_PW = (0x0C << 6) | OPC_DPAQ_W_QH_DSP,
719 OPC_DPAU_H_OBL = (0x03 << 6) | OPC_DPAQ_W_QH_DSP,
720 OPC_DPAU_H_OBR = (0x07 << 6) | OPC_DPAQ_W_QH_DSP,
721 OPC_DPS_W_QH = (0x01 << 6) | OPC_DPAQ_W_QH_DSP,
722 OPC_DPSQ_S_W_QH = (0x05 << 6) | OPC_DPAQ_W_QH_DSP,
723 OPC_DPSQ_SA_L_PW = (0x0D << 6) | OPC_DPAQ_W_QH_DSP,
724 OPC_DPSU_H_OBL = (0x0B << 6) | OPC_DPAQ_W_QH_DSP,
725 OPC_DPSU_H_OBR = (0x0F << 6) | OPC_DPAQ_W_QH_DSP,
726 OPC_MAQ_S_L_PWL = (0x1C << 6) | OPC_DPAQ_W_QH_DSP,
727 OPC_MAQ_S_L_PWR = (0x1E << 6) | OPC_DPAQ_W_QH_DSP,
728 OPC_MAQ_S_W_QHLL = (0x14 << 6) | OPC_DPAQ_W_QH_DSP,
729 OPC_MAQ_SA_W_QHLL = (0x10 << 6) | OPC_DPAQ_W_QH_DSP,
730 OPC_MAQ_S_W_QHLR = (0x15 << 6) | OPC_DPAQ_W_QH_DSP,
731 OPC_MAQ_SA_W_QHLR = (0x11 << 6) | OPC_DPAQ_W_QH_DSP,
732 OPC_MAQ_S_W_QHRL = (0x16 << 6) | OPC_DPAQ_W_QH_DSP,
733 OPC_MAQ_SA_W_QHRL = (0x12 << 6) | OPC_DPAQ_W_QH_DSP,
734 OPC_MAQ_S_W_QHRR = (0x17 << 6) | OPC_DPAQ_W_QH_DSP,
735 OPC_MAQ_SA_W_QHRR = (0x13 << 6) | OPC_DPAQ_W_QH_DSP,
736 OPC_MULSAQ_S_L_PW = (0x0E << 6) | OPC_DPAQ_W_QH_DSP,
737 OPC_MULSAQ_S_W_QH = (0x06 << 6) | OPC_DPAQ_W_QH_DSP,
738};
Jia Liua22260a2012-10-24 22:17:08 +0800739
Jia Liu77c5fa82012-10-24 22:17:07 +0800740#define MASK_SHLL_OB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
741enum {
742 /* MIPS DSP GPR-Based Shift Sub-class */
743 OPC_SHLL_PW = (0x10 << 6) | OPC_SHLL_OB_DSP,
744 OPC_SHLL_S_PW = (0x14 << 6) | OPC_SHLL_OB_DSP,
745 OPC_SHLLV_OB = (0x02 << 6) | OPC_SHLL_OB_DSP,
746 OPC_SHLLV_PW = (0x12 << 6) | OPC_SHLL_OB_DSP,
747 OPC_SHLLV_S_PW = (0x16 << 6) | OPC_SHLL_OB_DSP,
748 OPC_SHLLV_QH = (0x0A << 6) | OPC_SHLL_OB_DSP,
749 OPC_SHLLV_S_QH = (0x0E << 6) | OPC_SHLL_OB_DSP,
750 OPC_SHRA_PW = (0x11 << 6) | OPC_SHLL_OB_DSP,
751 OPC_SHRA_R_PW = (0x15 << 6) | OPC_SHLL_OB_DSP,
752 OPC_SHRAV_OB = (0x06 << 6) | OPC_SHLL_OB_DSP,
753 OPC_SHRAV_R_OB = (0x07 << 6) | OPC_SHLL_OB_DSP,
754 OPC_SHRAV_PW = (0x13 << 6) | OPC_SHLL_OB_DSP,
755 OPC_SHRAV_R_PW = (0x17 << 6) | OPC_SHLL_OB_DSP,
756 OPC_SHRAV_QH = (0x0B << 6) | OPC_SHLL_OB_DSP,
757 OPC_SHRAV_R_QH = (0x0F << 6) | OPC_SHLL_OB_DSP,
758 OPC_SHRLV_OB = (0x03 << 6) | OPC_SHLL_OB_DSP,
759 OPC_SHRLV_QH = (0x1B << 6) | OPC_SHLL_OB_DSP,
760 OPC_SHLL_OB = (0x00 << 6) | OPC_SHLL_OB_DSP,
761 OPC_SHLL_QH = (0x08 << 6) | OPC_SHLL_OB_DSP,
762 OPC_SHLL_S_QH = (0x0C << 6) | OPC_SHLL_OB_DSP,
763 OPC_SHRA_OB = (0x04 << 6) | OPC_SHLL_OB_DSP,
764 OPC_SHRA_R_OB = (0x05 << 6) | OPC_SHLL_OB_DSP,
765 OPC_SHRA_QH = (0x09 << 6) | OPC_SHLL_OB_DSP,
766 OPC_SHRA_R_QH = (0x0D << 6) | OPC_SHLL_OB_DSP,
767 OPC_SHRL_OB = (0x01 << 6) | OPC_SHLL_OB_DSP,
768 OPC_SHRL_QH = (0x19 << 6) | OPC_SHLL_OB_DSP,
769};
Jia Liu77c5fa82012-10-24 22:17:07 +0800770
ths7a387ff2006-12-06 20:17:30 +0000771/* Coprocessor 0 (rs field) */
772#define MASK_CP0(op) MASK_OP_MAJOR(op) | (op & (0x1F << 21))
773
774enum {
775 OPC_MFC0 = (0x00 << 21) | OPC_CP0,
776 OPC_DMFC0 = (0x01 << 21) | OPC_CP0,
777 OPC_MTC0 = (0x04 << 21) | OPC_CP0,
778 OPC_DMTC0 = (0x05 << 21) | OPC_CP0,
thsead93602007-09-06 00:18:15 +0000779 OPC_MFTR = (0x08 << 21) | OPC_CP0,
ths7a387ff2006-12-06 20:17:30 +0000780 OPC_RDPGPR = (0x0A << 21) | OPC_CP0,
781 OPC_MFMC0 = (0x0B << 21) | OPC_CP0,
thsead93602007-09-06 00:18:15 +0000782 OPC_MTTR = (0x0C << 21) | OPC_CP0,
ths7a387ff2006-12-06 20:17:30 +0000783 OPC_WRPGPR = (0x0E << 21) | OPC_CP0,
784 OPC_C0 = (0x10 << 21) | OPC_CP0,
785 OPC_C0_FIRST = (0x10 << 21) | OPC_CP0,
786 OPC_C0_LAST = (0x1F << 21) | OPC_CP0,
787};
788
789/* MFMC0 opcodes */
thsb48cfdf2007-04-11 02:24:14 +0000790#define MASK_MFMC0(op) MASK_CP0(op) | (op & 0xFFFF)
ths7a387ff2006-12-06 20:17:30 +0000791
792enum {
thsead93602007-09-06 00:18:15 +0000793 OPC_DMT = 0x01 | (0 << 5) | (0x0F << 6) | (0x01 << 11) | OPC_MFMC0,
794 OPC_EMT = 0x01 | (1 << 5) | (0x0F << 6) | (0x01 << 11) | OPC_MFMC0,
795 OPC_DVPE = 0x01 | (0 << 5) | OPC_MFMC0,
796 OPC_EVPE = 0x01 | (1 << 5) | OPC_MFMC0,
ths7a387ff2006-12-06 20:17:30 +0000797 OPC_DI = (0 << 5) | (0x0C << 11) | OPC_MFMC0,
798 OPC_EI = (1 << 5) | (0x0C << 11) | OPC_MFMC0,
799};
800
801/* Coprocessor 0 (with rs == C0) */
802#define MASK_C0(op) MASK_CP0(op) | (op & 0x3F)
803
804enum {
805 OPC_TLBR = 0x01 | OPC_C0,
806 OPC_TLBWI = 0x02 | OPC_C0,
807 OPC_TLBWR = 0x06 | OPC_C0,
808 OPC_TLBP = 0x08 | OPC_C0,
809 OPC_RFE = 0x10 | OPC_C0,
810 OPC_ERET = 0x18 | OPC_C0,
811 OPC_DERET = 0x1F | OPC_C0,
812 OPC_WAIT = 0x20 | OPC_C0,
813};
814
815/* Coprocessor 1 (rs field) */
816#define MASK_CP1(op) MASK_OP_MAJOR(op) | (op & (0x1F << 21))
817
Nathan Froydbf4120a2010-06-08 13:29:56 -0700818/* Values for the fmt field in FP instructions */
819enum {
820 /* 0 - 15 are reserved */
Aurelien Jarnoe4594402010-06-09 15:13:17 +0200821 FMT_S = 16, /* single fp */
822 FMT_D = 17, /* double fp */
823 FMT_E = 18, /* extended fp */
824 FMT_Q = 19, /* quad fp */
825 FMT_W = 20, /* 32-bit fixed */
826 FMT_L = 21, /* 64-bit fixed */
827 FMT_PS = 22, /* paired single fp */
Nathan Froydbf4120a2010-06-08 13:29:56 -0700828 /* 23 - 31 are reserved */
829};
830
ths7a387ff2006-12-06 20:17:30 +0000831enum {
832 OPC_MFC1 = (0x00 << 21) | OPC_CP1,
833 OPC_DMFC1 = (0x01 << 21) | OPC_CP1,
834 OPC_CFC1 = (0x02 << 21) | OPC_CP1,
ths5a5012e2007-05-07 13:55:33 +0000835 OPC_MFHC1 = (0x03 << 21) | OPC_CP1,
ths7a387ff2006-12-06 20:17:30 +0000836 OPC_MTC1 = (0x04 << 21) | OPC_CP1,
837 OPC_DMTC1 = (0x05 << 21) | OPC_CP1,
838 OPC_CTC1 = (0x06 << 21) | OPC_CP1,
ths5a5012e2007-05-07 13:55:33 +0000839 OPC_MTHC1 = (0x07 << 21) | OPC_CP1,
ths7a387ff2006-12-06 20:17:30 +0000840 OPC_BC1 = (0x08 << 21) | OPC_CP1, /* bc */
ths5a5012e2007-05-07 13:55:33 +0000841 OPC_BC1ANY2 = (0x09 << 21) | OPC_CP1,
842 OPC_BC1ANY4 = (0x0A << 21) | OPC_CP1,
Aurelien Jarnoe4594402010-06-09 15:13:17 +0200843 OPC_S_FMT = (FMT_S << 21) | OPC_CP1,
844 OPC_D_FMT = (FMT_D << 21) | OPC_CP1,
845 OPC_E_FMT = (FMT_E << 21) | OPC_CP1,
846 OPC_Q_FMT = (FMT_Q << 21) | OPC_CP1,
847 OPC_W_FMT = (FMT_W << 21) | OPC_CP1,
848 OPC_L_FMT = (FMT_L << 21) | OPC_CP1,
849 OPC_PS_FMT = (FMT_PS << 21) | OPC_CP1,
bellarde37e8632005-07-04 22:17:33 +0000850};
851
ths5a5012e2007-05-07 13:55:33 +0000852#define MASK_CP1_FUNC(op) MASK_CP1(op) | (op & 0x3F)
853#define MASK_BC1(op) MASK_CP1(op) | (op & (0x3 << 16))
854
bellarde37e8632005-07-04 22:17:33 +0000855enum {
ths7a387ff2006-12-06 20:17:30 +0000856 OPC_BC1F = (0x00 << 16) | OPC_BC1,
857 OPC_BC1T = (0x01 << 16) | OPC_BC1,
858 OPC_BC1FL = (0x02 << 16) | OPC_BC1,
859 OPC_BC1TL = (0x03 << 16) | OPC_BC1,
bellarde37e8632005-07-04 22:17:33 +0000860};
861
ths5a5012e2007-05-07 13:55:33 +0000862enum {
863 OPC_BC1FANY2 = (0x00 << 16) | OPC_BC1ANY2,
864 OPC_BC1TANY2 = (0x01 << 16) | OPC_BC1ANY2,
865};
866
867enum {
868 OPC_BC1FANY4 = (0x00 << 16) | OPC_BC1ANY4,
869 OPC_BC1TANY4 = (0x01 << 16) | OPC_BC1ANY4,
870};
ths7a387ff2006-12-06 20:17:30 +0000871
872#define MASK_CP2(op) MASK_OP_MAJOR(op) | (op & (0x1F << 21))
thse0c84da2007-04-07 01:11:39 +0000873
874enum {
875 OPC_MFC2 = (0x00 << 21) | OPC_CP2,
876 OPC_DMFC2 = (0x01 << 21) | OPC_CP2,
877 OPC_CFC2 = (0x02 << 21) | OPC_CP2,
878 OPC_MFHC2 = (0x03 << 21) | OPC_CP2,
879 OPC_MTC2 = (0x04 << 21) | OPC_CP2,
880 OPC_DMTC2 = (0x05 << 21) | OPC_CP2,
881 OPC_CTC2 = (0x06 << 21) | OPC_CP2,
882 OPC_MTHC2 = (0x07 << 21) | OPC_CP2,
883 OPC_BC2 = (0x08 << 21) | OPC_CP2,
884};
885
Richard Hendersonbd277fa2012-09-18 21:59:44 -0700886#define MASK_LMI(op) (MASK_OP_MAJOR(op) | (op & (0x1F << 21)) | (op & 0x1F))
887
888enum {
889 OPC_PADDSH = (24 << 21) | (0x00) | OPC_CP2,
890 OPC_PADDUSH = (25 << 21) | (0x00) | OPC_CP2,
891 OPC_PADDH = (26 << 21) | (0x00) | OPC_CP2,
892 OPC_PADDW = (27 << 21) | (0x00) | OPC_CP2,
893 OPC_PADDSB = (28 << 21) | (0x00) | OPC_CP2,
894 OPC_PADDUSB = (29 << 21) | (0x00) | OPC_CP2,
895 OPC_PADDB = (30 << 21) | (0x00) | OPC_CP2,
896 OPC_PADDD = (31 << 21) | (0x00) | OPC_CP2,
897
898 OPC_PSUBSH = (24 << 21) | (0x01) | OPC_CP2,
899 OPC_PSUBUSH = (25 << 21) | (0x01) | OPC_CP2,
900 OPC_PSUBH = (26 << 21) | (0x01) | OPC_CP2,
901 OPC_PSUBW = (27 << 21) | (0x01) | OPC_CP2,
902 OPC_PSUBSB = (28 << 21) | (0x01) | OPC_CP2,
903 OPC_PSUBUSB = (29 << 21) | (0x01) | OPC_CP2,
904 OPC_PSUBB = (30 << 21) | (0x01) | OPC_CP2,
905 OPC_PSUBD = (31 << 21) | (0x01) | OPC_CP2,
906
907 OPC_PSHUFH = (24 << 21) | (0x02) | OPC_CP2,
908 OPC_PACKSSWH = (25 << 21) | (0x02) | OPC_CP2,
909 OPC_PACKSSHB = (26 << 21) | (0x02) | OPC_CP2,
910 OPC_PACKUSHB = (27 << 21) | (0x02) | OPC_CP2,
911 OPC_XOR_CP2 = (28 << 21) | (0x02) | OPC_CP2,
912 OPC_NOR_CP2 = (29 << 21) | (0x02) | OPC_CP2,
913 OPC_AND_CP2 = (30 << 21) | (0x02) | OPC_CP2,
914 OPC_PANDN = (31 << 21) | (0x02) | OPC_CP2,
915
916 OPC_PUNPCKLHW = (24 << 21) | (0x03) | OPC_CP2,
917 OPC_PUNPCKHHW = (25 << 21) | (0x03) | OPC_CP2,
918 OPC_PUNPCKLBH = (26 << 21) | (0x03) | OPC_CP2,
919 OPC_PUNPCKHBH = (27 << 21) | (0x03) | OPC_CP2,
920 OPC_PINSRH_0 = (28 << 21) | (0x03) | OPC_CP2,
921 OPC_PINSRH_1 = (29 << 21) | (0x03) | OPC_CP2,
922 OPC_PINSRH_2 = (30 << 21) | (0x03) | OPC_CP2,
923 OPC_PINSRH_3 = (31 << 21) | (0x03) | OPC_CP2,
924
925 OPC_PAVGH = (24 << 21) | (0x08) | OPC_CP2,
926 OPC_PAVGB = (25 << 21) | (0x08) | OPC_CP2,
927 OPC_PMAXSH = (26 << 21) | (0x08) | OPC_CP2,
928 OPC_PMINSH = (27 << 21) | (0x08) | OPC_CP2,
929 OPC_PMAXUB = (28 << 21) | (0x08) | OPC_CP2,
930 OPC_PMINUB = (29 << 21) | (0x08) | OPC_CP2,
931
932 OPC_PCMPEQW = (24 << 21) | (0x09) | OPC_CP2,
933 OPC_PCMPGTW = (25 << 21) | (0x09) | OPC_CP2,
934 OPC_PCMPEQH = (26 << 21) | (0x09) | OPC_CP2,
935 OPC_PCMPGTH = (27 << 21) | (0x09) | OPC_CP2,
936 OPC_PCMPEQB = (28 << 21) | (0x09) | OPC_CP2,
937 OPC_PCMPGTB = (29 << 21) | (0x09) | OPC_CP2,
938
939 OPC_PSLLW = (24 << 21) | (0x0A) | OPC_CP2,
940 OPC_PSLLH = (25 << 21) | (0x0A) | OPC_CP2,
941 OPC_PMULLH = (26 << 21) | (0x0A) | OPC_CP2,
942 OPC_PMULHH = (27 << 21) | (0x0A) | OPC_CP2,
943 OPC_PMULUW = (28 << 21) | (0x0A) | OPC_CP2,
944 OPC_PMULHUH = (29 << 21) | (0x0A) | OPC_CP2,
945
946 OPC_PSRLW = (24 << 21) | (0x0B) | OPC_CP2,
947 OPC_PSRLH = (25 << 21) | (0x0B) | OPC_CP2,
948 OPC_PSRAW = (26 << 21) | (0x0B) | OPC_CP2,
949 OPC_PSRAH = (27 << 21) | (0x0B) | OPC_CP2,
950 OPC_PUNPCKLWD = (28 << 21) | (0x0B) | OPC_CP2,
951 OPC_PUNPCKHWD = (29 << 21) | (0x0B) | OPC_CP2,
952
953 OPC_ADDU_CP2 = (24 << 21) | (0x0C) | OPC_CP2,
954 OPC_OR_CP2 = (25 << 21) | (0x0C) | OPC_CP2,
955 OPC_ADD_CP2 = (26 << 21) | (0x0C) | OPC_CP2,
956 OPC_DADD_CP2 = (27 << 21) | (0x0C) | OPC_CP2,
957 OPC_SEQU_CP2 = (28 << 21) | (0x0C) | OPC_CP2,
958 OPC_SEQ_CP2 = (29 << 21) | (0x0C) | OPC_CP2,
959
960 OPC_SUBU_CP2 = (24 << 21) | (0x0D) | OPC_CP2,
961 OPC_PASUBUB = (25 << 21) | (0x0D) | OPC_CP2,
962 OPC_SUB_CP2 = (26 << 21) | (0x0D) | OPC_CP2,
963 OPC_DSUB_CP2 = (27 << 21) | (0x0D) | OPC_CP2,
964 OPC_SLTU_CP2 = (28 << 21) | (0x0D) | OPC_CP2,
965 OPC_SLT_CP2 = (29 << 21) | (0x0D) | OPC_CP2,
966
967 OPC_SLL_CP2 = (24 << 21) | (0x0E) | OPC_CP2,
968 OPC_DSLL_CP2 = (25 << 21) | (0x0E) | OPC_CP2,
969 OPC_PEXTRH = (26 << 21) | (0x0E) | OPC_CP2,
970 OPC_PMADDHW = (27 << 21) | (0x0E) | OPC_CP2,
971 OPC_SLEU_CP2 = (28 << 21) | (0x0E) | OPC_CP2,
972 OPC_SLE_CP2 = (29 << 21) | (0x0E) | OPC_CP2,
973
974 OPC_SRL_CP2 = (24 << 21) | (0x0F) | OPC_CP2,
975 OPC_DSRL_CP2 = (25 << 21) | (0x0F) | OPC_CP2,
976 OPC_SRA_CP2 = (26 << 21) | (0x0F) | OPC_CP2,
977 OPC_DSRA_CP2 = (27 << 21) | (0x0F) | OPC_CP2,
978 OPC_BIADD = (28 << 21) | (0x0F) | OPC_CP2,
979 OPC_PMOVMSKB = (29 << 21) | (0x0F) | OPC_CP2,
980};
981
982
thse0c84da2007-04-07 01:11:39 +0000983#define MASK_CP3(op) MASK_OP_MAJOR(op) | (op & 0x3F)
984
985enum {
986 OPC_LWXC1 = 0x00 | OPC_CP3,
987 OPC_LDXC1 = 0x01 | OPC_CP3,
988 OPC_LUXC1 = 0x05 | OPC_CP3,
989 OPC_SWXC1 = 0x08 | OPC_CP3,
990 OPC_SDXC1 = 0x09 | OPC_CP3,
991 OPC_SUXC1 = 0x0D | OPC_CP3,
992 OPC_PREFX = 0x0F | OPC_CP3,
993 OPC_ALNV_PS = 0x1E | OPC_CP3,
994 OPC_MADD_S = 0x20 | OPC_CP3,
995 OPC_MADD_D = 0x21 | OPC_CP3,
996 OPC_MADD_PS = 0x26 | OPC_CP3,
997 OPC_MSUB_S = 0x28 | OPC_CP3,
998 OPC_MSUB_D = 0x29 | OPC_CP3,
999 OPC_MSUB_PS = 0x2E | OPC_CP3,
1000 OPC_NMADD_S = 0x30 | OPC_CP3,
thsfbcc6822007-05-11 09:59:10 +00001001 OPC_NMADD_D = 0x31 | OPC_CP3,
thse0c84da2007-04-07 01:11:39 +00001002 OPC_NMADD_PS= 0x36 | OPC_CP3,
1003 OPC_NMSUB_S = 0x38 | OPC_CP3,
1004 OPC_NMSUB_D = 0x39 | OPC_CP3,
1005 OPC_NMSUB_PS= 0x3E | OPC_CP3,
1006};
1007
ths39454622008-05-04 08:16:10 +00001008/* global register indices */
pbrooka7812ae2008-11-17 14:43:54 +00001009static TCGv_ptr cpu_env;
1010static TCGv cpu_gpr[32], cpu_PC;
ths4b2eb8d2008-09-18 11:59:03 +00001011static TCGv cpu_HI[MIPS_DSP_ACC], cpu_LO[MIPS_DSP_ACC], cpu_ACX[MIPS_DSP_ACC];
aurel3241db4602009-03-29 01:28:29 +00001012static TCGv cpu_dspctrl, btarget, bcond;
1013static TCGv_i32 hflags;
pbrooka7812ae2008-11-17 14:43:54 +00001014static TCGv_i32 fpu_fcr0, fpu_fcr31;
Richard Hendersond73ee8a2012-10-09 21:53:19 +02001015static TCGv_i64 fpu_f64[32];
thsaa0bf002008-06-11 13:02:57 +00001016
Paolo Bonzini1a7ff922010-03-31 16:54:11 +02001017static uint32_t gen_opc_hflags[OPC_BUF_SIZE];
Aurelien Jarno46364012012-10-28 15:42:55 +01001018static target_ulong gen_opc_btarget[OPC_BUF_SIZE];
Paolo Bonzini1a7ff922010-03-31 16:54:11 +02001019
Paolo Bonzini022c62c2012-12-17 18:19:49 +01001020#include "exec/gen-icount.h"
pbrook2e70f6e2008-06-29 01:03:05 +00001021
Blue Swirl895c2d02012-09-02 14:52:59 +00001022#define gen_helper_0e0i(name, arg) do { \
pbrooka7812ae2008-11-17 14:43:54 +00001023 TCGv_i32 helper_tmp = tcg_const_i32(arg); \
Blue Swirl895c2d02012-09-02 14:52:59 +00001024 gen_helper_##name(cpu_env, helper_tmp); \
pbrooka7812ae2008-11-17 14:43:54 +00001025 tcg_temp_free_i32(helper_tmp); \
1026 } while(0)
aurel322fdbad22008-09-05 14:19:17 +00001027
Blue Swirl895c2d02012-09-02 14:52:59 +00001028#define gen_helper_0e1i(name, arg1, arg2) do { \
pbrooka7812ae2008-11-17 14:43:54 +00001029 TCGv_i32 helper_tmp = tcg_const_i32(arg2); \
Blue Swirl895c2d02012-09-02 14:52:59 +00001030 gen_helper_##name(cpu_env, arg1, helper_tmp); \
pbrooka7812ae2008-11-17 14:43:54 +00001031 tcg_temp_free_i32(helper_tmp); \
1032 } while(0)
thsc2395292008-06-05 08:38:44 +00001033
Blue Swirl895c2d02012-09-02 14:52:59 +00001034#define gen_helper_1e0i(name, ret, arg1) do { \
1035 TCGv_i32 helper_tmp = tcg_const_i32(arg1); \
1036 gen_helper_##name(ret, cpu_env, helper_tmp); \
1037 tcg_temp_free_i32(helper_tmp); \
1038 } while(0)
1039
1040#define gen_helper_1e1i(name, ret, arg1, arg2) do { \
1041 TCGv_i32 helper_tmp = tcg_const_i32(arg2); \
1042 gen_helper_##name(ret, cpu_env, arg1, helper_tmp); \
1043 tcg_temp_free_i32(helper_tmp); \
1044 } while(0)
1045
1046#define gen_helper_0e2i(name, arg1, arg2, arg3) do { \
pbrooka7812ae2008-11-17 14:43:54 +00001047 TCGv_i32 helper_tmp = tcg_const_i32(arg3); \
Blue Swirl895c2d02012-09-02 14:52:59 +00001048 gen_helper_##name(cpu_env, arg1, arg2, helper_tmp); \
pbrooka7812ae2008-11-17 14:43:54 +00001049 tcg_temp_free_i32(helper_tmp); \
1050 } while(0)
thsc2395292008-06-05 08:38:44 +00001051
Blue Swirl895c2d02012-09-02 14:52:59 +00001052#define gen_helper_1e2i(name, ret, arg1, arg2, arg3) do { \
1053 TCGv_i32 helper_tmp = tcg_const_i32(arg3); \
1054 gen_helper_##name(ret, cpu_env, arg1, arg2, helper_tmp); \
1055 tcg_temp_free_i32(helper_tmp); \
1056 } while(0)
1057
1058#define gen_helper_0e3i(name, arg1, arg2, arg3, arg4) do { \
pbrooka7812ae2008-11-17 14:43:54 +00001059 TCGv_i32 helper_tmp = tcg_const_i32(arg4); \
Blue Swirl895c2d02012-09-02 14:52:59 +00001060 gen_helper_##name(cpu_env, arg1, arg2, arg3, helper_tmp); \
pbrooka7812ae2008-11-17 14:43:54 +00001061 tcg_temp_free_i32(helper_tmp); \
1062 } while(0)
thsc2395292008-06-05 08:38:44 +00001063
ths8e9ade62008-05-22 17:46:10 +00001064typedef struct DisasContext {
1065 struct TranslationBlock *tb;
1066 target_ulong pc, saved_pc;
1067 uint32_t opcode;
Nathan Froyd7b270ef2009-07-14 08:33:11 -07001068 int singlestep_enabled;
Aurelien Jarnod75c1352013-01-01 18:02:22 +01001069 int insn_flags;
ths8e9ade62008-05-22 17:46:10 +00001070 /* Routine used to access memory */
1071 int mem_idx;
1072 uint32_t hflags, saved_hflags;
1073 int bstate;
1074 target_ulong btarget;
1075} DisasContext;
1076
1077enum {
1078 BS_NONE = 0, /* We go out of the TB without reaching a branch or an
thsd077b6f2008-06-30 11:30:34 +00001079 * exception condition */
ths8e9ade62008-05-22 17:46:10 +00001080 BS_STOP = 1, /* We want to stop translation for any reason */
1081 BS_BRANCH = 2, /* We reached a branch condition */
1082 BS_EXCP = 3, /* We reached an exception condition */
1083};
1084
Richard Hendersond73ee8a2012-10-09 21:53:19 +02001085static const char * const regnames[] = {
1086 "r0", "at", "v0", "v1", "a0", "a1", "a2", "a3",
1087 "t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7",
1088 "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7",
1089 "t8", "t9", "k0", "k1", "gp", "sp", "s8", "ra",
1090};
bellard6af0bf92005-07-02 14:58:51 +00001091
Richard Hendersond73ee8a2012-10-09 21:53:19 +02001092static const char * const regnames_HI[] = {
1093 "HI0", "HI1", "HI2", "HI3",
1094};
ths4b2eb8d2008-09-18 11:59:03 +00001095
Richard Hendersond73ee8a2012-10-09 21:53:19 +02001096static const char * const regnames_LO[] = {
1097 "LO0", "LO1", "LO2", "LO3",
1098};
ths4b2eb8d2008-09-18 11:59:03 +00001099
Richard Hendersond73ee8a2012-10-09 21:53:19 +02001100static const char * const regnames_ACX[] = {
1101 "ACX0", "ACX1", "ACX2", "ACX3",
1102};
ths4b2eb8d2008-09-18 11:59:03 +00001103
Richard Hendersond73ee8a2012-10-09 21:53:19 +02001104static const char * const fregnames[] = {
1105 "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7",
1106 "f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15",
1107 "f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23",
1108 "f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31",
1109};
bellard6ea83fe2006-06-14 12:56:19 +00001110
Richard Hendersonfb7729e2012-09-18 21:55:34 -07001111#define MIPS_DEBUG(fmt, ...) \
1112 do { \
1113 if (MIPS_DEBUG_DISAS) { \
1114 qemu_log_mask(CPU_LOG_TB_IN_ASM, \
1115 TARGET_FMT_lx ": %08x " fmt "\n", \
1116 ctx->pc, ctx->opcode , ## __VA_ARGS__); \
1117 } \
1118 } while (0)
1119
1120#define LOG_DISAS(...) \
1121 do { \
1122 if (MIPS_DEBUG_DISAS) { \
1123 qemu_log_mask(CPU_LOG_TB_IN_ASM, ## __VA_ARGS__); \
1124 } \
1125 } while (0)
ths8e9ade62008-05-22 17:46:10 +00001126
1127#define MIPS_INVAL(op) \
ths8e9ade62008-05-22 17:46:10 +00001128 MIPS_DEBUG("Invalid %s %03x %03x %03x", op, ctx->opcode >> 26, \
Richard Hendersonfb7729e2012-09-18 21:55:34 -07001129 ctx->opcode & 0x3F, ((ctx->opcode >> 16) & 0x1F))
ths8e9ade62008-05-22 17:46:10 +00001130
1131/* General purpose registers moves. */
1132static inline void gen_load_gpr (TCGv t, int reg)
1133{
1134 if (reg == 0)
1135 tcg_gen_movi_tl(t, 0);
1136 else
ths4b2eb8d2008-09-18 11:59:03 +00001137 tcg_gen_mov_tl(t, cpu_gpr[reg]);
ths8e9ade62008-05-22 17:46:10 +00001138}
1139
1140static inline void gen_store_gpr (TCGv t, int reg)
1141{
1142 if (reg != 0)
ths4b2eb8d2008-09-18 11:59:03 +00001143 tcg_gen_mov_tl(cpu_gpr[reg], t);
ths8e9ade62008-05-22 17:46:10 +00001144}
1145
aurel32b10fa3c2008-11-11 11:50:25 +00001146/* Moves to/from ACX register. */
ths4b2eb8d2008-09-18 11:59:03 +00001147static inline void gen_load_ACX (TCGv t, int reg)
1148{
1149 tcg_gen_mov_tl(t, cpu_ACX[reg]);
1150}
1151
1152static inline void gen_store_ACX (TCGv t, int reg)
1153{
1154 tcg_gen_mov_tl(cpu_ACX[reg], t);
ths893f9862008-05-28 13:37:19 +00001155}
1156
ths8e9ade62008-05-22 17:46:10 +00001157/* Moves to/from shadow registers. */
thsbe24bb42008-06-23 12:57:09 +00001158static inline void gen_load_srsgpr (int from, int to)
ths8e9ade62008-05-22 17:46:10 +00001159{
aurel32d9bea112009-04-15 14:41:44 +00001160 TCGv t0 = tcg_temp_new();
thsbe24bb42008-06-23 12:57:09 +00001161
1162 if (from == 0)
aurel32d9bea112009-04-15 14:41:44 +00001163 tcg_gen_movi_tl(t0, 0);
ths8e9ade62008-05-22 17:46:10 +00001164 else {
aurel32d9bea112009-04-15 14:41:44 +00001165 TCGv_i32 t2 = tcg_temp_new_i32();
pbrooka7812ae2008-11-17 14:43:54 +00001166 TCGv_ptr addr = tcg_temp_new_ptr();
ths8e9ade62008-05-22 17:46:10 +00001167
Andreas Färber7db13fa2012-03-14 01:38:22 +01001168 tcg_gen_ld_i32(t2, cpu_env, offsetof(CPUMIPSState, CP0_SRSCtl));
aurel32d9bea112009-04-15 14:41:44 +00001169 tcg_gen_shri_i32(t2, t2, CP0SRSCtl_PSS);
1170 tcg_gen_andi_i32(t2, t2, 0xf);
1171 tcg_gen_muli_i32(t2, t2, sizeof(target_ulong) * 32);
1172 tcg_gen_ext_i32_ptr(addr, t2);
pbrooka7812ae2008-11-17 14:43:54 +00001173 tcg_gen_add_ptr(addr, cpu_env, addr);
ths8e9ade62008-05-22 17:46:10 +00001174
aurel32d9bea112009-04-15 14:41:44 +00001175 tcg_gen_ld_tl(t0, addr, sizeof(target_ulong) * from);
pbrooka7812ae2008-11-17 14:43:54 +00001176 tcg_temp_free_ptr(addr);
aurel32d9bea112009-04-15 14:41:44 +00001177 tcg_temp_free_i32(t2);
ths8e9ade62008-05-22 17:46:10 +00001178 }
aurel32d9bea112009-04-15 14:41:44 +00001179 gen_store_gpr(t0, to);
1180 tcg_temp_free(t0);
ths8e9ade62008-05-22 17:46:10 +00001181}
1182
thsbe24bb42008-06-23 12:57:09 +00001183static inline void gen_store_srsgpr (int from, int to)
ths8e9ade62008-05-22 17:46:10 +00001184{
thsbe24bb42008-06-23 12:57:09 +00001185 if (to != 0) {
aurel32d9bea112009-04-15 14:41:44 +00001186 TCGv t0 = tcg_temp_new();
1187 TCGv_i32 t2 = tcg_temp_new_i32();
pbrooka7812ae2008-11-17 14:43:54 +00001188 TCGv_ptr addr = tcg_temp_new_ptr();
ths8e9ade62008-05-22 17:46:10 +00001189
aurel32d9bea112009-04-15 14:41:44 +00001190 gen_load_gpr(t0, from);
Andreas Färber7db13fa2012-03-14 01:38:22 +01001191 tcg_gen_ld_i32(t2, cpu_env, offsetof(CPUMIPSState, CP0_SRSCtl));
aurel32d9bea112009-04-15 14:41:44 +00001192 tcg_gen_shri_i32(t2, t2, CP0SRSCtl_PSS);
1193 tcg_gen_andi_i32(t2, t2, 0xf);
1194 tcg_gen_muli_i32(t2, t2, sizeof(target_ulong) * 32);
1195 tcg_gen_ext_i32_ptr(addr, t2);
pbrooka7812ae2008-11-17 14:43:54 +00001196 tcg_gen_add_ptr(addr, cpu_env, addr);
ths8e9ade62008-05-22 17:46:10 +00001197
aurel32d9bea112009-04-15 14:41:44 +00001198 tcg_gen_st_tl(t0, addr, sizeof(target_ulong) * to);
pbrooka7812ae2008-11-17 14:43:54 +00001199 tcg_temp_free_ptr(addr);
aurel32d9bea112009-04-15 14:41:44 +00001200 tcg_temp_free_i32(t2);
1201 tcg_temp_free(t0);
ths8e9ade62008-05-22 17:46:10 +00001202 }
1203}
1204
1205/* Floating point register moves. */
Richard Hendersond73ee8a2012-10-09 21:53:19 +02001206static void gen_load_fpr32(TCGv_i32 t, int reg)
thsaa0bf002008-06-11 13:02:57 +00001207{
Richard Hendersond73ee8a2012-10-09 21:53:19 +02001208 tcg_gen_trunc_i64_i32(t, fpu_f64[reg]);
bellard6ea83fe2006-06-14 12:56:19 +00001209}
1210
Richard Hendersond73ee8a2012-10-09 21:53:19 +02001211static void gen_store_fpr32(TCGv_i32 t, int reg)
thsaa0bf002008-06-11 13:02:57 +00001212{
Richard Hendersond73ee8a2012-10-09 21:53:19 +02001213 TCGv_i64 t64 = tcg_temp_new_i64();
1214 tcg_gen_extu_i32_i64(t64, t);
1215 tcg_gen_deposit_i64(fpu_f64[reg], fpu_f64[reg], t64, 0, 32);
1216 tcg_temp_free_i64(t64);
aurel326d066272009-03-29 15:39:08 +00001217}
1218
Richard Hendersond73ee8a2012-10-09 21:53:19 +02001219static void gen_load_fpr32h(TCGv_i32 t, int reg)
aurel326d066272009-03-29 15:39:08 +00001220{
Richard Hendersond73ee8a2012-10-09 21:53:19 +02001221 TCGv_i64 t64 = tcg_temp_new_i64();
1222 tcg_gen_shri_i64(t64, fpu_f64[reg], 32);
1223 tcg_gen_trunc_i64_i32(t, t64);
1224 tcg_temp_free_i64(t64);
aurel326d066272009-03-29 15:39:08 +00001225}
1226
Richard Hendersond73ee8a2012-10-09 21:53:19 +02001227static void gen_store_fpr32h(TCGv_i32 t, int reg)
aurel326d066272009-03-29 15:39:08 +00001228{
Richard Hendersond73ee8a2012-10-09 21:53:19 +02001229 TCGv_i64 t64 = tcg_temp_new_i64();
1230 tcg_gen_extu_i32_i64(t64, t);
1231 tcg_gen_deposit_i64(fpu_f64[reg], fpu_f64[reg], t64, 32, 32);
1232 tcg_temp_free_i64(t64);
thsaa0bf002008-06-11 13:02:57 +00001233}
bellard6ea83fe2006-06-14 12:56:19 +00001234
Richard Hendersond73ee8a2012-10-09 21:53:19 +02001235static void gen_load_fpr64(DisasContext *ctx, TCGv_i64 t, int reg)
thsaa0bf002008-06-11 13:02:57 +00001236{
aurel32f3645152009-03-28 22:22:50 +00001237 if (ctx->hflags & MIPS_HFLAG_F64) {
Richard Hendersond73ee8a2012-10-09 21:53:19 +02001238 tcg_gen_mov_i64(t, fpu_f64[reg]);
aurel32f3645152009-03-28 22:22:50 +00001239 } else {
Richard Hendersond73ee8a2012-10-09 21:53:19 +02001240 tcg_gen_concat32_i64(t, fpu_f64[reg & ~1], fpu_f64[reg | 1]);
thsaa0bf002008-06-11 13:02:57 +00001241 }
1242}
bellard6ea83fe2006-06-14 12:56:19 +00001243
Richard Hendersond73ee8a2012-10-09 21:53:19 +02001244static void gen_store_fpr64(DisasContext *ctx, TCGv_i64 t, int reg)
thsaa0bf002008-06-11 13:02:57 +00001245{
aurel32f3645152009-03-28 22:22:50 +00001246 if (ctx->hflags & MIPS_HFLAG_F64) {
Richard Hendersond73ee8a2012-10-09 21:53:19 +02001247 tcg_gen_mov_i64(fpu_f64[reg], t);
aurel32f3645152009-03-28 22:22:50 +00001248 } else {
Richard Hendersond73ee8a2012-10-09 21:53:19 +02001249 TCGv_i64 t0;
1250 tcg_gen_deposit_i64(fpu_f64[reg & ~1], fpu_f64[reg & ~1], t, 0, 32);
1251 t0 = tcg_temp_new_i64();
aurel326d066272009-03-29 15:39:08 +00001252 tcg_gen_shri_i64(t0, t, 32);
Richard Hendersond73ee8a2012-10-09 21:53:19 +02001253 tcg_gen_deposit_i64(fpu_f64[reg | 1], fpu_f64[reg | 1], t0, 0, 32);
aurel326d066272009-03-29 15:39:08 +00001254 tcg_temp_free_i64(t0);
thsaa0bf002008-06-11 13:02:57 +00001255 }
1256}
bellard6ea83fe2006-06-14 12:56:19 +00001257
aurel32d94536f2009-03-29 15:44:34 +00001258static inline int get_fp_bit (int cc)
thsa16336e2008-06-19 18:35:02 +00001259{
aurel32d94536f2009-03-29 15:44:34 +00001260 if (cc)
1261 return 24 + cc;
1262 else
1263 return 23;
thsa16336e2008-06-19 18:35:02 +00001264}
1265
ths30898802008-05-21 02:04:15 +00001266/* Tests */
ths8e9ade62008-05-22 17:46:10 +00001267static inline void gen_save_pc(target_ulong pc)
ths9b9e4392007-05-28 17:03:28 +00001268{
aurel321eb75d42008-11-11 11:36:04 +00001269 tcg_gen_movi_tl(cpu_PC, pc);
ths9b9e4392007-05-28 17:03:28 +00001270}
1271
ths356265a2008-07-01 16:37:52 +00001272static inline void save_cpu_state (DisasContext *ctx, int do_save_pc)
bellard6af0bf92005-07-02 14:58:51 +00001273{
aliguorid12d51d2009-01-15 21:48:06 +00001274 LOG_DISAS("hflags %08x saved %08x\n", ctx->hflags, ctx->saved_hflags);
bellard6af0bf92005-07-02 14:58:51 +00001275 if (do_save_pc && ctx->pc != ctx->saved_pc) {
ths9b9e4392007-05-28 17:03:28 +00001276 gen_save_pc(ctx->pc);
bellard6af0bf92005-07-02 14:58:51 +00001277 ctx->saved_pc = ctx->pc;
1278 }
1279 if (ctx->hflags != ctx->saved_hflags) {
aurel3241db4602009-03-29 01:28:29 +00001280 tcg_gen_movi_i32(hflags, ctx->hflags);
bellard6af0bf92005-07-02 14:58:51 +00001281 ctx->saved_hflags = ctx->hflags;
Nathan Froyd364d4832009-12-08 08:06:29 -08001282 switch (ctx->hflags & MIPS_HFLAG_BMASK_BASE) {
ths5a5012e2007-05-07 13:55:33 +00001283 case MIPS_HFLAG_BR:
ths5a5012e2007-05-07 13:55:33 +00001284 break;
1285 case MIPS_HFLAG_BC:
ths5a5012e2007-05-07 13:55:33 +00001286 case MIPS_HFLAG_BL:
ths5a5012e2007-05-07 13:55:33 +00001287 case MIPS_HFLAG_B:
thsd077b6f2008-06-30 11:30:34 +00001288 tcg_gen_movi_tl(btarget, ctx->btarget);
ths5a5012e2007-05-07 13:55:33 +00001289 break;
bellard6af0bf92005-07-02 14:58:51 +00001290 }
1291 }
1292}
1293
Andreas Färber7db13fa2012-03-14 01:38:22 +01001294static inline void restore_cpu_state (CPUMIPSState *env, DisasContext *ctx)
ths5a5012e2007-05-07 13:55:33 +00001295{
thsfd4a04e2007-05-18 11:55:54 +00001296 ctx->saved_hflags = ctx->hflags;
Nathan Froyd364d4832009-12-08 08:06:29 -08001297 switch (ctx->hflags & MIPS_HFLAG_BMASK_BASE) {
thsfd4a04e2007-05-18 11:55:54 +00001298 case MIPS_HFLAG_BR:
thsfd4a04e2007-05-18 11:55:54 +00001299 break;
1300 case MIPS_HFLAG_BC:
1301 case MIPS_HFLAG_BL:
ths39454622008-05-04 08:16:10 +00001302 case MIPS_HFLAG_B:
thsfd4a04e2007-05-18 11:55:54 +00001303 ctx->btarget = env->btarget;
thsfd4a04e2007-05-18 11:55:54 +00001304 break;
ths5a5012e2007-05-07 13:55:33 +00001305 }
1306}
1307
ths356265a2008-07-01 16:37:52 +00001308static inline void
ths48d38ca2008-05-18 22:50:49 +00001309generate_exception_err (DisasContext *ctx, int excp, int err)
thsaaa91282008-05-06 21:40:48 +00001310{
pbrooka7812ae2008-11-17 14:43:54 +00001311 TCGv_i32 texcp = tcg_const_i32(excp);
1312 TCGv_i32 terr = tcg_const_i32(err);
thsaaa91282008-05-06 21:40:48 +00001313 save_cpu_state(ctx, 1);
Blue Swirl895c2d02012-09-02 14:52:59 +00001314 gen_helper_raise_exception_err(cpu_env, texcp, terr);
pbrooka7812ae2008-11-17 14:43:54 +00001315 tcg_temp_free_i32(terr);
1316 tcg_temp_free_i32(texcp);
thsaaa91282008-05-06 21:40:48 +00001317}
1318
ths356265a2008-07-01 16:37:52 +00001319static inline void
ths48d38ca2008-05-18 22:50:49 +00001320generate_exception (DisasContext *ctx, int excp)
thsaaa91282008-05-06 21:40:48 +00001321{
bellard6af0bf92005-07-02 14:58:51 +00001322 save_cpu_state(ctx, 1);
Blue Swirl895c2d02012-09-02 14:52:59 +00001323 gen_helper_0e0i(raise_exception, excp);
bellard6af0bf92005-07-02 14:58:51 +00001324}
1325
ths48d38ca2008-05-18 22:50:49 +00001326/* Addresses computation */
Aurelien Jarno941694d2009-09-28 23:40:59 +02001327static inline void gen_op_addr_add (DisasContext *ctx, TCGv ret, TCGv arg0, TCGv arg1)
bellard4ad40f32005-12-05 19:59:36 +00001328{
Aurelien Jarno941694d2009-09-28 23:40:59 +02001329 tcg_gen_add_tl(ret, arg0, arg1);
ths48d38ca2008-05-18 22:50:49 +00001330
1331#if defined(TARGET_MIPS64)
1332 /* For compatibility with 32-bit code, data reference in user mode
1333 with Status_UX = 0 should be casted to 32-bit and sign extended.
1334 See the MIPS64 PRA manual, section 4.10. */
aurel322623c1e2008-11-11 11:39:33 +00001335 if (((ctx->hflags & MIPS_HFLAG_KSU) == MIPS_HFLAG_UM) &&
1336 !(ctx->hflags & MIPS_HFLAG_UX)) {
Aurelien Jarno941694d2009-09-28 23:40:59 +02001337 tcg_gen_ext32s_i64(ret, ret);
ths48d38ca2008-05-18 22:50:49 +00001338 }
1339#endif
bellard4ad40f32005-12-05 19:59:36 +00001340}
1341
ths356265a2008-07-01 16:37:52 +00001342static inline void check_cp0_enabled(DisasContext *ctx)
ths387a8fe2007-09-25 14:49:47 +00001343{
thsfe253232007-09-26 23:50:39 +00001344 if (unlikely(!(ctx->hflags & MIPS_HFLAG_CP0)))
Nathan Froydc2c65da2010-02-20 10:19:09 -08001345 generate_exception_err(ctx, EXCP_CpU, 0);
ths387a8fe2007-09-25 14:49:47 +00001346}
1347
ths356265a2008-07-01 16:37:52 +00001348static inline void check_cp1_enabled(DisasContext *ctx)
ths5e755512007-05-29 16:52:57 +00001349{
thsfe253232007-09-26 23:50:39 +00001350 if (unlikely(!(ctx->hflags & MIPS_HFLAG_FPU)))
ths5e755512007-05-29 16:52:57 +00001351 generate_exception_err(ctx, EXCP_CpU, 1);
1352}
1353
thsb8aa4592007-12-30 15:36:58 +00001354/* Verify that the processor is running with COP1X instructions enabled.
1355 This is associated with the nabla symbol in the MIPS32 and MIPS64
1356 opcode tables. */
1357
ths356265a2008-07-01 16:37:52 +00001358static inline void check_cop1x(DisasContext *ctx)
thsb8aa4592007-12-30 15:36:58 +00001359{
1360 if (unlikely(!(ctx->hflags & MIPS_HFLAG_COP1X)))
1361 generate_exception(ctx, EXCP_RI);
1362}
1363
1364/* Verify that the processor is running with 64-bit floating-point
1365 operations enabled. */
1366
ths356265a2008-07-01 16:37:52 +00001367static inline void check_cp1_64bitmode(DisasContext *ctx)
ths5e755512007-05-29 16:52:57 +00001368{
thsb8aa4592007-12-30 15:36:58 +00001369 if (unlikely(~ctx->hflags & (MIPS_HFLAG_F64 | MIPS_HFLAG_COP1X)))
ths5e755512007-05-29 16:52:57 +00001370 generate_exception(ctx, EXCP_RI);
1371}
1372
1373/*
1374 * Verify if floating point register is valid; an operation is not defined
1375 * if bit 0 of any register specification is set and the FR bit in the
1376 * Status register equals zero, since the register numbers specify an
1377 * even-odd pair of adjacent coprocessor general registers. When the FR bit
1378 * in the Status register equals one, both even and odd register numbers
1379 * are valid. This limitation exists only for 64 bit wide (d,l,ps) registers.
1380 *
1381 * Multiple 64 bit wide registers can be checked by calling
1382 * gen_op_cp1_registers(freg1 | freg2 | ... | fregN);
1383 */
ths356265a2008-07-01 16:37:52 +00001384static inline void check_cp1_registers(DisasContext *ctx, int regs)
ths5e755512007-05-29 16:52:57 +00001385{
thsfe253232007-09-26 23:50:39 +00001386 if (unlikely(!(ctx->hflags & MIPS_HFLAG_F64) && (regs & 1)))
ths5e755512007-05-29 16:52:57 +00001387 generate_exception(ctx, EXCP_RI);
1388}
1389
Jia Liu853c3242012-10-24 22:17:02 +08001390/* Verify that the processor is running with DSP instructions enabled.
1391 This is enabled by CP0 Status register MX(24) bit.
1392 */
1393
1394static inline void check_dsp(DisasContext *ctx)
1395{
1396 if (unlikely(!(ctx->hflags & MIPS_HFLAG_DSP))) {
Aurelien Jarnoad153f12013-01-01 18:02:23 +01001397 if (ctx->insn_flags & ASE_DSP) {
1398 generate_exception(ctx, EXCP_DSPDIS);
1399 } else {
1400 generate_exception(ctx, EXCP_RI);
1401 }
Jia Liu853c3242012-10-24 22:17:02 +08001402 }
1403}
1404
1405static inline void check_dspr2(DisasContext *ctx)
1406{
1407 if (unlikely(!(ctx->hflags & MIPS_HFLAG_DSPR2))) {
Aurelien Jarnoad153f12013-01-01 18:02:23 +01001408 if (ctx->insn_flags & ASE_DSP) {
1409 generate_exception(ctx, EXCP_DSPDIS);
1410 } else {
1411 generate_exception(ctx, EXCP_RI);
1412 }
Jia Liu853c3242012-10-24 22:17:02 +08001413 }
1414}
1415
ths3a95e3a2007-06-02 00:25:12 +00001416/* This code generates a "reserved instruction" exception if the
thse189e742007-09-24 12:48:00 +00001417 CPU does not support the instruction set corresponding to flags. */
Aurelien Jarnod75c1352013-01-01 18:02:22 +01001418static inline void check_insn(DisasContext *ctx, int flags)
ths3a95e3a2007-06-02 00:25:12 +00001419{
Aurelien Jarnod75c1352013-01-01 18:02:22 +01001420 if (unlikely(!(ctx->insn_flags & flags))) {
ths3a95e3a2007-06-02 00:25:12 +00001421 generate_exception(ctx, EXCP_RI);
Aurelien Jarnod75c1352013-01-01 18:02:22 +01001422 }
ths3a95e3a2007-06-02 00:25:12 +00001423}
1424
thse189e742007-09-24 12:48:00 +00001425/* This code generates a "reserved instruction" exception if 64-bit
1426 instructions are not enabled. */
ths356265a2008-07-01 16:37:52 +00001427static inline void check_mips_64(DisasContext *ctx)
thse189e742007-09-24 12:48:00 +00001428{
thsfe253232007-09-26 23:50:39 +00001429 if (unlikely(!(ctx->hflags & MIPS_HFLAG_64)))
thse189e742007-09-24 12:48:00 +00001430 generate_exception(ctx, EXCP_RI);
1431}
1432
Nathan Froyd8153667c2010-06-08 13:29:57 -07001433/* Define small wrappers for gen_load_fpr* so that we have a uniform
1434 calling interface for 32 and 64-bit FPRs. No sense in changing
1435 all callers for gen_load_fpr32 when we need the CTX parameter for
1436 this one use. */
1437#define gen_ldcmp_fpr32(ctx, x, y) gen_load_fpr32(x, y)
1438#define gen_ldcmp_fpr64(ctx, x, y) gen_load_fpr64(ctx, x, y)
1439#define FOP_CONDS(type, abs, fmt, ifmt, bits) \
1440static inline void gen_cmp ## type ## _ ## fmt(DisasContext *ctx, int n, \
1441 int ft, int fs, int cc) \
1442{ \
1443 TCGv_i##bits fp0 = tcg_temp_new_i##bits (); \
1444 TCGv_i##bits fp1 = tcg_temp_new_i##bits (); \
1445 switch (ifmt) { \
1446 case FMT_PS: \
1447 check_cp1_64bitmode(ctx); \
1448 break; \
1449 case FMT_D: \
1450 if (abs) { \
1451 check_cop1x(ctx); \
1452 } \
1453 check_cp1_registers(ctx, fs | ft); \
1454 break; \
1455 case FMT_S: \
1456 if (abs) { \
1457 check_cop1x(ctx); \
1458 } \
1459 break; \
1460 } \
1461 gen_ldcmp_fpr##bits (ctx, fp0, fs); \
1462 gen_ldcmp_fpr##bits (ctx, fp1, ft); \
1463 switch (n) { \
Blue Swirl895c2d02012-09-02 14:52:59 +00001464 case 0: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _f, fp0, fp1, cc); break;\
1465 case 1: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _un, fp0, fp1, cc); break;\
1466 case 2: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _eq, fp0, fp1, cc); break;\
1467 case 3: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ueq, fp0, fp1, cc); break;\
1468 case 4: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _olt, fp0, fp1, cc); break;\
1469 case 5: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ult, fp0, fp1, cc); break;\
1470 case 6: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ole, fp0, fp1, cc); break;\
1471 case 7: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ule, fp0, fp1, cc); break;\
1472 case 8: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _sf, fp0, fp1, cc); break;\
1473 case 9: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ngle, fp0, fp1, cc); break;\
1474 case 10: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _seq, fp0, fp1, cc); break;\
1475 case 11: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ngl, fp0, fp1, cc); break;\
1476 case 12: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _lt, fp0, fp1, cc); break;\
1477 case 13: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _nge, fp0, fp1, cc); break;\
1478 case 14: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _le, fp0, fp1, cc); break;\
1479 case 15: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ngt, fp0, fp1, cc); break;\
Nathan Froyd8153667c2010-06-08 13:29:57 -07001480 default: abort(); \
1481 } \
1482 tcg_temp_free_i##bits (fp0); \
1483 tcg_temp_free_i##bits (fp1); \
1484}
1485
1486FOP_CONDS(, 0, d, FMT_D, 64)
1487FOP_CONDS(abs, 1, d, FMT_D, 64)
1488FOP_CONDS(, 0, s, FMT_S, 32)
1489FOP_CONDS(abs, 1, s, FMT_S, 32)
1490FOP_CONDS(, 0, ps, FMT_PS, 64)
1491FOP_CONDS(abs, 1, ps, FMT_PS, 64)
1492#undef FOP_CONDS
1493#undef gen_ldcmp_fpr32
1494#undef gen_ldcmp_fpr64
1495
ths958fb4a2008-05-06 10:57:59 +00001496/* load/store instructions. */
Aurelien Jarnoe7139c42009-11-30 15:39:54 +01001497#ifdef CONFIG_USER_ONLY
aurel32d9bea112009-04-15 14:41:44 +00001498#define OP_LD_ATOMIC(insn,fname) \
Aurelien Jarno5c13fdf2010-07-01 07:47:00 +02001499static inline void op_ld_##insn(TCGv ret, TCGv arg1, DisasContext *ctx) \
aurel32d9bea112009-04-15 14:41:44 +00001500{ \
1501 TCGv t0 = tcg_temp_new(); \
1502 tcg_gen_mov_tl(t0, arg1); \
1503 tcg_gen_qemu_##fname(ret, arg1, ctx->mem_idx); \
Andreas Färber7db13fa2012-03-14 01:38:22 +01001504 tcg_gen_st_tl(t0, cpu_env, offsetof(CPUMIPSState, lladdr)); \
1505 tcg_gen_st_tl(ret, cpu_env, offsetof(CPUMIPSState, llval)); \
aurel32d9bea112009-04-15 14:41:44 +00001506 tcg_temp_free(t0); \
thsaaa91282008-05-06 21:40:48 +00001507}
Aurelien Jarnoe7139c42009-11-30 15:39:54 +01001508#else
1509#define OP_LD_ATOMIC(insn,fname) \
Aurelien Jarno5c13fdf2010-07-01 07:47:00 +02001510static inline void op_ld_##insn(TCGv ret, TCGv arg1, DisasContext *ctx) \
Aurelien Jarnoe7139c42009-11-30 15:39:54 +01001511{ \
Blue Swirl895c2d02012-09-02 14:52:59 +00001512 gen_helper_1e1i(insn, ret, arg1, ctx->mem_idx); \
Aurelien Jarnoe7139c42009-11-30 15:39:54 +01001513}
1514#endif
thsaaa91282008-05-06 21:40:48 +00001515OP_LD_ATOMIC(ll,ld32s);
1516#if defined(TARGET_MIPS64)
1517OP_LD_ATOMIC(lld,ld64);
1518#endif
1519#undef OP_LD_ATOMIC
1520
Paul Brook590bc602009-07-09 17:45:17 +01001521#ifdef CONFIG_USER_ONLY
1522#define OP_ST_ATOMIC(insn,fname,ldname,almask) \
Aurelien Jarno5c13fdf2010-07-01 07:47:00 +02001523static inline void op_st_##insn(TCGv arg1, TCGv arg2, int rt, DisasContext *ctx) \
Paul Brook590bc602009-07-09 17:45:17 +01001524{ \
1525 TCGv t0 = tcg_temp_new(); \
1526 int l1 = gen_new_label(); \
1527 int l2 = gen_new_label(); \
1528 \
1529 tcg_gen_andi_tl(t0, arg2, almask); \
1530 tcg_gen_brcondi_tl(TCG_COND_EQ, t0, 0, l1); \
Andreas Färber7db13fa2012-03-14 01:38:22 +01001531 tcg_gen_st_tl(arg2, cpu_env, offsetof(CPUMIPSState, CP0_BadVAddr)); \
Paul Brook590bc602009-07-09 17:45:17 +01001532 generate_exception(ctx, EXCP_AdES); \
1533 gen_set_label(l1); \
Andreas Färber7db13fa2012-03-14 01:38:22 +01001534 tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUMIPSState, lladdr)); \
Paul Brook590bc602009-07-09 17:45:17 +01001535 tcg_gen_brcond_tl(TCG_COND_NE, arg2, t0, l2); \
1536 tcg_gen_movi_tl(t0, rt | ((almask << 3) & 0x20)); \
Andreas Färber7db13fa2012-03-14 01:38:22 +01001537 tcg_gen_st_tl(t0, cpu_env, offsetof(CPUMIPSState, llreg)); \
1538 tcg_gen_st_tl(arg1, cpu_env, offsetof(CPUMIPSState, llnewval)); \
Blue Swirl895c2d02012-09-02 14:52:59 +00001539 gen_helper_0e0i(raise_exception, EXCP_SC); \
Paul Brook590bc602009-07-09 17:45:17 +01001540 gen_set_label(l2); \
1541 tcg_gen_movi_tl(t0, 0); \
1542 gen_store_gpr(t0, rt); \
1543 tcg_temp_free(t0); \
thsaaa91282008-05-06 21:40:48 +00001544}
Paul Brook590bc602009-07-09 17:45:17 +01001545#else
1546#define OP_ST_ATOMIC(insn,fname,ldname,almask) \
Aurelien Jarno5c13fdf2010-07-01 07:47:00 +02001547static inline void op_st_##insn(TCGv arg1, TCGv arg2, int rt, DisasContext *ctx) \
Paul Brook590bc602009-07-09 17:45:17 +01001548{ \
1549 TCGv t0 = tcg_temp_new(); \
Blue Swirl895c2d02012-09-02 14:52:59 +00001550 gen_helper_1e2i(insn, t0, arg1, arg2, ctx->mem_idx); \
Paul Brook590bc602009-07-09 17:45:17 +01001551 gen_store_gpr(t0, rt); \
Paul Brook590bc602009-07-09 17:45:17 +01001552 tcg_temp_free(t0); \
1553}
1554#endif
Paul Brook590bc602009-07-09 17:45:17 +01001555OP_ST_ATOMIC(sc,st32,ld32s,0x3);
thsaaa91282008-05-06 21:40:48 +00001556#if defined(TARGET_MIPS64)
Paul Brook590bc602009-07-09 17:45:17 +01001557OP_ST_ATOMIC(scd,st64,ld64,0x7);
thsaaa91282008-05-06 21:40:48 +00001558#endif
1559#undef OP_ST_ATOMIC
1560
Nathan Froyd662d7482009-12-08 10:01:01 -08001561static void gen_base_offset_addr (DisasContext *ctx, TCGv addr,
1562 int base, int16_t offset)
1563{
1564 if (base == 0) {
1565 tcg_gen_movi_tl(addr, offset);
1566 } else if (offset == 0) {
1567 gen_load_gpr(addr, base);
1568 } else {
1569 tcg_gen_movi_tl(addr, offset);
1570 gen_op_addr_add(ctx, addr, cpu_gpr[base], addr);
1571 }
1572}
1573
Nathan Froyd364d4832009-12-08 08:06:29 -08001574static target_ulong pc_relative_pc (DisasContext *ctx)
1575{
1576 target_ulong pc = ctx->pc;
1577
1578 if (ctx->hflags & MIPS_HFLAG_BMASK) {
1579 int branch_bytes = ctx->hflags & MIPS_HFLAG_BDS16 ? 2 : 4;
1580
1581 pc -= branch_bytes;
1582 }
1583
1584 pc &= ~(target_ulong)3;
1585 return pc;
1586}
1587
Aurelien Jarno5c13fdf2010-07-01 07:47:00 +02001588/* Load */
Aurelien Jarnod75c1352013-01-01 18:02:22 +01001589static void gen_ld(DisasContext *ctx, uint32_t opc,
1590 int rt, int base, int16_t offset)
bellard6af0bf92005-07-02 14:58:51 +00001591{
Aurelien Jarno5c13fdf2010-07-01 07:47:00 +02001592 const char *opn = "ld";
Aurelien Jarnofc407872012-10-09 21:53:21 +02001593 TCGv t0, t1, t2;
bellard6af0bf92005-07-02 14:58:51 +00001594
Aurelien Jarnod75c1352013-01-01 18:02:22 +01001595 if (rt == 0 && ctx->insn_flags & (INSN_LOONGSON2E | INSN_LOONGSON2F)) {
Aurelien Jarnoafa88c32010-07-01 23:43:34 +02001596 /* Loongson CPU uses a load to zero register for prefetch.
1597 We emulate it as a NOP. On other CPU we must perform the
1598 actual memory access. */
1599 MIPS_DEBUG("NOP");
1600 return;
1601 }
1602
1603 t0 = tcg_temp_new();
Nathan Froyd662d7482009-12-08 10:01:01 -08001604 gen_base_offset_addr(ctx, t0, base, offset);
Aurelien Jarnoafa88c32010-07-01 23:43:34 +02001605
bellard6af0bf92005-07-02 14:58:51 +00001606 switch (opc) {
thsd26bc212007-11-08 18:05:37 +00001607#if defined(TARGET_MIPS64)
ths6e473122007-05-28 20:36:48 +00001608 case OPC_LWU:
Aurelien Jarno2910c6cb2012-10-09 21:53:20 +02001609 tcg_gen_qemu_ld32u(t0, t0, ctx->mem_idx);
ths78723682008-06-24 20:12:33 +00001610 gen_store_gpr(t0, rt);
ths6e473122007-05-28 20:36:48 +00001611 opn = "lwu";
1612 break;
bellard6af0bf92005-07-02 14:58:51 +00001613 case OPC_LD:
Aurelien Jarno2910c6cb2012-10-09 21:53:20 +02001614 tcg_gen_qemu_ld64(t0, t0, ctx->mem_idx);
ths78723682008-06-24 20:12:33 +00001615 gen_store_gpr(t0, rt);
bellard6af0bf92005-07-02 14:58:51 +00001616 opn = "ld";
1617 break;
ths7a387ff2006-12-06 20:17:30 +00001618 case OPC_LLD:
Aurelien Jarnob835e912011-01-17 19:29:34 +01001619 save_cpu_state(ctx, 1);
Aurelien Jarno5c13fdf2010-07-01 07:47:00 +02001620 op_ld_lld(t0, t0, ctx);
ths78723682008-06-24 20:12:33 +00001621 gen_store_gpr(t0, rt);
ths7a387ff2006-12-06 20:17:30 +00001622 opn = "lld";
1623 break;
bellard6af0bf92005-07-02 14:58:51 +00001624 case OPC_LDL:
Aurelien Jarno3cee3052012-10-09 21:53:20 +02001625 t1 = tcg_temp_new();
Aurelien Jarnofc407872012-10-09 21:53:21 +02001626 tcg_gen_andi_tl(t1, t0, 7);
1627#ifndef TARGET_WORDS_BIGENDIAN
1628 tcg_gen_xori_tl(t1, t1, 7);
1629#endif
1630 tcg_gen_shli_tl(t1, t1, 3);
1631 tcg_gen_andi_tl(t0, t0, ~7);
1632 tcg_gen_qemu_ld64(t0, t0, ctx->mem_idx);
1633 tcg_gen_shl_tl(t0, t0, t1);
1634 tcg_gen_xori_tl(t1, t1, 63);
1635 t2 = tcg_const_tl(0x7fffffffffffffffull);
1636 tcg_gen_shr_tl(t2, t2, t1);
ths78723682008-06-24 20:12:33 +00001637 gen_load_gpr(t1, rt);
Aurelien Jarnofc407872012-10-09 21:53:21 +02001638 tcg_gen_and_tl(t1, t1, t2);
1639 tcg_temp_free(t2);
1640 tcg_gen_or_tl(t0, t0, t1);
Aurelien Jarno3cee3052012-10-09 21:53:20 +02001641 tcg_temp_free(t1);
Aurelien Jarnofc407872012-10-09 21:53:21 +02001642 gen_store_gpr(t0, rt);
bellard6af0bf92005-07-02 14:58:51 +00001643 opn = "ldl";
1644 break;
bellard6af0bf92005-07-02 14:58:51 +00001645 case OPC_LDR:
Aurelien Jarno3cee3052012-10-09 21:53:20 +02001646 t1 = tcg_temp_new();
Aurelien Jarnofc407872012-10-09 21:53:21 +02001647 tcg_gen_andi_tl(t1, t0, 7);
1648#ifdef TARGET_WORDS_BIGENDIAN
1649 tcg_gen_xori_tl(t1, t1, 7);
1650#endif
1651 tcg_gen_shli_tl(t1, t1, 3);
1652 tcg_gen_andi_tl(t0, t0, ~7);
1653 tcg_gen_qemu_ld64(t0, t0, ctx->mem_idx);
1654 tcg_gen_shr_tl(t0, t0, t1);
1655 tcg_gen_xori_tl(t1, t1, 63);
1656 t2 = tcg_const_tl(0xfffffffffffffffeull);
1657 tcg_gen_shl_tl(t2, t2, t1);
ths78723682008-06-24 20:12:33 +00001658 gen_load_gpr(t1, rt);
Aurelien Jarnofc407872012-10-09 21:53:21 +02001659 tcg_gen_and_tl(t1, t1, t2);
1660 tcg_temp_free(t2);
1661 tcg_gen_or_tl(t0, t0, t1);
Aurelien Jarno3cee3052012-10-09 21:53:20 +02001662 tcg_temp_free(t1);
Aurelien Jarnofc407872012-10-09 21:53:21 +02001663 gen_store_gpr(t0, rt);
bellard6af0bf92005-07-02 14:58:51 +00001664 opn = "ldr";
1665 break;
Nathan Froyd364d4832009-12-08 08:06:29 -08001666 case OPC_LDPC:
Aurelien Jarno3cee3052012-10-09 21:53:20 +02001667 t1 = tcg_const_tl(pc_relative_pc(ctx));
Nathan Froyd364d4832009-12-08 08:06:29 -08001668 gen_op_addr_add(ctx, t0, t0, t1);
Aurelien Jarno3cee3052012-10-09 21:53:20 +02001669 tcg_temp_free(t1);
Aurelien Jarno2910c6cb2012-10-09 21:53:20 +02001670 tcg_gen_qemu_ld64(t0, t0, ctx->mem_idx);
Nathan Froyd364d4832009-12-08 08:06:29 -08001671 gen_store_gpr(t0, rt);
Aurelien Jarno5c13fdf2010-07-01 07:47:00 +02001672 opn = "ldpc";
Nathan Froyd364d4832009-12-08 08:06:29 -08001673 break;
bellard6af0bf92005-07-02 14:58:51 +00001674#endif
Nathan Froyd364d4832009-12-08 08:06:29 -08001675 case OPC_LWPC:
Aurelien Jarno3cee3052012-10-09 21:53:20 +02001676 t1 = tcg_const_tl(pc_relative_pc(ctx));
Nathan Froyd364d4832009-12-08 08:06:29 -08001677 gen_op_addr_add(ctx, t0, t0, t1);
Aurelien Jarno3cee3052012-10-09 21:53:20 +02001678 tcg_temp_free(t1);
Aurelien Jarno2910c6cb2012-10-09 21:53:20 +02001679 tcg_gen_qemu_ld32s(t0, t0, ctx->mem_idx);
Nathan Froyd364d4832009-12-08 08:06:29 -08001680 gen_store_gpr(t0, rt);
Aurelien Jarno5c13fdf2010-07-01 07:47:00 +02001681 opn = "lwpc";
Nathan Froyd364d4832009-12-08 08:06:29 -08001682 break;
bellard6af0bf92005-07-02 14:58:51 +00001683 case OPC_LW:
Aurelien Jarno2910c6cb2012-10-09 21:53:20 +02001684 tcg_gen_qemu_ld32s(t0, t0, ctx->mem_idx);
ths78723682008-06-24 20:12:33 +00001685 gen_store_gpr(t0, rt);
bellard6af0bf92005-07-02 14:58:51 +00001686 opn = "lw";
1687 break;
bellard6af0bf92005-07-02 14:58:51 +00001688 case OPC_LH:
Aurelien Jarno2910c6cb2012-10-09 21:53:20 +02001689 tcg_gen_qemu_ld16s(t0, t0, ctx->mem_idx);
ths78723682008-06-24 20:12:33 +00001690 gen_store_gpr(t0, rt);
bellard6af0bf92005-07-02 14:58:51 +00001691 opn = "lh";
1692 break;
bellard6af0bf92005-07-02 14:58:51 +00001693 case OPC_LHU:
Aurelien Jarno2910c6cb2012-10-09 21:53:20 +02001694 tcg_gen_qemu_ld16u(t0, t0, ctx->mem_idx);
ths78723682008-06-24 20:12:33 +00001695 gen_store_gpr(t0, rt);
bellard6af0bf92005-07-02 14:58:51 +00001696 opn = "lhu";
1697 break;
1698 case OPC_LB:
Aurelien Jarno2910c6cb2012-10-09 21:53:20 +02001699 tcg_gen_qemu_ld8s(t0, t0, ctx->mem_idx);
ths78723682008-06-24 20:12:33 +00001700 gen_store_gpr(t0, rt);
bellard6af0bf92005-07-02 14:58:51 +00001701 opn = "lb";
1702 break;
bellard6af0bf92005-07-02 14:58:51 +00001703 case OPC_LBU:
Aurelien Jarno2910c6cb2012-10-09 21:53:20 +02001704 tcg_gen_qemu_ld8u(t0, t0, ctx->mem_idx);
ths78723682008-06-24 20:12:33 +00001705 gen_store_gpr(t0, rt);
bellard6af0bf92005-07-02 14:58:51 +00001706 opn = "lbu";
1707 break;
1708 case OPC_LWL:
Aurelien Jarno3cee3052012-10-09 21:53:20 +02001709 t1 = tcg_temp_new();
Aurelien Jarnofc407872012-10-09 21:53:21 +02001710 tcg_gen_andi_tl(t1, t0, 3);
1711#ifndef TARGET_WORDS_BIGENDIAN
1712 tcg_gen_xori_tl(t1, t1, 3);
1713#endif
1714 tcg_gen_shli_tl(t1, t1, 3);
1715 tcg_gen_andi_tl(t0, t0, ~3);
1716 tcg_gen_qemu_ld32u(t0, t0, ctx->mem_idx);
1717 tcg_gen_shl_tl(t0, t0, t1);
1718 tcg_gen_xori_tl(t1, t1, 31);
1719 t2 = tcg_const_tl(0x7fffffffull);
1720 tcg_gen_shr_tl(t2, t2, t1);
aurel3269585492009-01-14 19:40:36 +00001721 gen_load_gpr(t1, rt);
Aurelien Jarnofc407872012-10-09 21:53:21 +02001722 tcg_gen_and_tl(t1, t1, t2);
1723 tcg_temp_free(t2);
1724 tcg_gen_or_tl(t0, t0, t1);
Aurelien Jarno3cee3052012-10-09 21:53:20 +02001725 tcg_temp_free(t1);
Aurelien Jarnofc407872012-10-09 21:53:21 +02001726 tcg_gen_ext32s_tl(t0, t0);
1727 gen_store_gpr(t0, rt);
bellard6af0bf92005-07-02 14:58:51 +00001728 opn = "lwl";
1729 break;
bellard6af0bf92005-07-02 14:58:51 +00001730 case OPC_LWR:
Aurelien Jarno3cee3052012-10-09 21:53:20 +02001731 t1 = tcg_temp_new();
Aurelien Jarnofc407872012-10-09 21:53:21 +02001732 tcg_gen_andi_tl(t1, t0, 3);
1733#ifdef TARGET_WORDS_BIGENDIAN
1734 tcg_gen_xori_tl(t1, t1, 3);
1735#endif
1736 tcg_gen_shli_tl(t1, t1, 3);
1737 tcg_gen_andi_tl(t0, t0, ~3);
1738 tcg_gen_qemu_ld32u(t0, t0, ctx->mem_idx);
1739 tcg_gen_shr_tl(t0, t0, t1);
1740 tcg_gen_xori_tl(t1, t1, 31);
1741 t2 = tcg_const_tl(0xfffffffeull);
1742 tcg_gen_shl_tl(t2, t2, t1);
aurel3269585492009-01-14 19:40:36 +00001743 gen_load_gpr(t1, rt);
Aurelien Jarnofc407872012-10-09 21:53:21 +02001744 tcg_gen_and_tl(t1, t1, t2);
1745 tcg_temp_free(t2);
1746 tcg_gen_or_tl(t0, t0, t1);
Aurelien Jarno3cee3052012-10-09 21:53:20 +02001747 tcg_temp_free(t1);
Richard Sandifordc7281542013-01-20 19:30:54 +00001748 tcg_gen_ext32s_tl(t0, t0);
Aurelien Jarnofc407872012-10-09 21:53:21 +02001749 gen_store_gpr(t0, rt);
bellard6af0bf92005-07-02 14:58:51 +00001750 opn = "lwr";
1751 break;
bellard6af0bf92005-07-02 14:58:51 +00001752 case OPC_LL:
Aurelien Jarnoe7139c42009-11-30 15:39:54 +01001753 save_cpu_state(ctx, 1);
Aurelien Jarno5c13fdf2010-07-01 07:47:00 +02001754 op_ld_ll(t0, t0, ctx);
ths78723682008-06-24 20:12:33 +00001755 gen_store_gpr(t0, rt);
bellard6af0bf92005-07-02 14:58:51 +00001756 opn = "ll";
1757 break;
bellard6af0bf92005-07-02 14:58:51 +00001758 }
Blue Swirl2abf3142010-10-13 18:38:08 +00001759 (void)opn; /* avoid a compiler warning */
bellard6af0bf92005-07-02 14:58:51 +00001760 MIPS_DEBUG("%s %s, %d(%s)", opn, regnames[rt], offset, regnames[base]);
ths78723682008-06-24 20:12:33 +00001761 tcg_temp_free(t0);
bellard6af0bf92005-07-02 14:58:51 +00001762}
1763
Aurelien Jarno5c13fdf2010-07-01 07:47:00 +02001764/* Store */
1765static void gen_st (DisasContext *ctx, uint32_t opc, int rt,
1766 int base, int16_t offset)
1767{
1768 const char *opn = "st";
1769 TCGv t0 = tcg_temp_new();
1770 TCGv t1 = tcg_temp_new();
1771
1772 gen_base_offset_addr(ctx, t0, base, offset);
1773 gen_load_gpr(t1, rt);
1774 switch (opc) {
1775#if defined(TARGET_MIPS64)
1776 case OPC_SD:
Aurelien Jarno2910c6cb2012-10-09 21:53:20 +02001777 tcg_gen_qemu_st64(t1, t0, ctx->mem_idx);
Aurelien Jarno5c13fdf2010-07-01 07:47:00 +02001778 opn = "sd";
1779 break;
1780 case OPC_SDL:
1781 save_cpu_state(ctx, 1);
Blue Swirl895c2d02012-09-02 14:52:59 +00001782 gen_helper_0e2i(sdl, t1, t0, ctx->mem_idx);
Aurelien Jarno5c13fdf2010-07-01 07:47:00 +02001783 opn = "sdl";
1784 break;
1785 case OPC_SDR:
1786 save_cpu_state(ctx, 1);
Blue Swirl895c2d02012-09-02 14:52:59 +00001787 gen_helper_0e2i(sdr, t1, t0, ctx->mem_idx);
Aurelien Jarno5c13fdf2010-07-01 07:47:00 +02001788 opn = "sdr";
1789 break;
1790#endif
1791 case OPC_SW:
Aurelien Jarno2910c6cb2012-10-09 21:53:20 +02001792 tcg_gen_qemu_st32(t1, t0, ctx->mem_idx);
Aurelien Jarno5c13fdf2010-07-01 07:47:00 +02001793 opn = "sw";
1794 break;
1795 case OPC_SH:
Aurelien Jarno2910c6cb2012-10-09 21:53:20 +02001796 tcg_gen_qemu_st16(t1, t0, ctx->mem_idx);
Aurelien Jarno5c13fdf2010-07-01 07:47:00 +02001797 opn = "sh";
1798 break;
1799 case OPC_SB:
Aurelien Jarno2910c6cb2012-10-09 21:53:20 +02001800 tcg_gen_qemu_st8(t1, t0, ctx->mem_idx);
Aurelien Jarno5c13fdf2010-07-01 07:47:00 +02001801 opn = "sb";
1802 break;
1803 case OPC_SWL:
1804 save_cpu_state(ctx, 1);
Blue Swirl895c2d02012-09-02 14:52:59 +00001805 gen_helper_0e2i(swl, t1, t0, ctx->mem_idx);
Aurelien Jarno5c13fdf2010-07-01 07:47:00 +02001806 opn = "swl";
1807 break;
1808 case OPC_SWR:
1809 save_cpu_state(ctx, 1);
Blue Swirl895c2d02012-09-02 14:52:59 +00001810 gen_helper_0e2i(swr, t1, t0, ctx->mem_idx);
Aurelien Jarno5c13fdf2010-07-01 07:47:00 +02001811 opn = "swr";
1812 break;
1813 }
Blue Swirl2abf3142010-10-13 18:38:08 +00001814 (void)opn; /* avoid a compiler warning */
Aurelien Jarno5c13fdf2010-07-01 07:47:00 +02001815 MIPS_DEBUG("%s %s, %d(%s)", opn, regnames[rt], offset, regnames[base]);
1816 tcg_temp_free(t0);
1817 tcg_temp_free(t1);
1818}
1819
1820
aurel32d66c7132009-04-11 18:42:55 +00001821/* Store conditional */
1822static void gen_st_cond (DisasContext *ctx, uint32_t opc, int rt,
1823 int base, int16_t offset)
1824{
1825 const char *opn = "st_cond";
1826 TCGv t0, t1;
1827
Aurelien Jarno2d2826b2012-10-09 21:53:21 +02001828#ifdef CONFIG_USER_ONLY
aurel32d66c7132009-04-11 18:42:55 +00001829 t0 = tcg_temp_local_new();
aurel32d66c7132009-04-11 18:42:55 +00001830 t1 = tcg_temp_local_new();
Aurelien Jarno2d2826b2012-10-09 21:53:21 +02001831#else
1832 t0 = tcg_temp_new();
1833 t1 = tcg_temp_new();
1834#endif
1835 gen_base_offset_addr(ctx, t0, base, offset);
aurel32d66c7132009-04-11 18:42:55 +00001836 gen_load_gpr(t1, rt);
1837 switch (opc) {
1838#if defined(TARGET_MIPS64)
1839 case OPC_SCD:
Aurelien Jarnob835e912011-01-17 19:29:34 +01001840 save_cpu_state(ctx, 1);
Aurelien Jarno5c13fdf2010-07-01 07:47:00 +02001841 op_st_scd(t1, t0, rt, ctx);
aurel32d66c7132009-04-11 18:42:55 +00001842 opn = "scd";
1843 break;
1844#endif
1845 case OPC_SC:
Aurelien Jarnoe7139c42009-11-30 15:39:54 +01001846 save_cpu_state(ctx, 1);
Aurelien Jarno5c13fdf2010-07-01 07:47:00 +02001847 op_st_sc(t1, t0, rt, ctx);
aurel32d66c7132009-04-11 18:42:55 +00001848 opn = "sc";
1849 break;
1850 }
Blue Swirl2abf3142010-10-13 18:38:08 +00001851 (void)opn; /* avoid a compiler warning */
aurel32d66c7132009-04-11 18:42:55 +00001852 MIPS_DEBUG("%s %s, %d(%s)", opn, regnames[rt], offset, regnames[base]);
1853 tcg_temp_free(t1);
aurel32d66c7132009-04-11 18:42:55 +00001854 tcg_temp_free(t0);
1855}
1856
bellard6ea83fe2006-06-14 12:56:19 +00001857/* Load and store */
ths7a387ff2006-12-06 20:17:30 +00001858static void gen_flt_ldst (DisasContext *ctx, uint32_t opc, int ft,
ths356265a2008-07-01 16:37:52 +00001859 int base, int16_t offset)
bellard6ea83fe2006-06-14 12:56:19 +00001860{
ths923617a2007-05-11 00:16:06 +00001861 const char *opn = "flt_ldst";
aurel324e2474d2009-04-08 21:48:10 +00001862 TCGv t0 = tcg_temp_new();
bellard6ea83fe2006-06-14 12:56:19 +00001863
Nathan Froyd662d7482009-12-08 10:01:01 -08001864 gen_base_offset_addr(ctx, t0, base, offset);
bellard6ea83fe2006-06-14 12:56:19 +00001865 /* Don't do NOP if destination is zero: we must perform the actual
thsead93602007-09-06 00:18:15 +00001866 memory access. */
bellard6ea83fe2006-06-14 12:56:19 +00001867 switch (opc) {
1868 case OPC_LWC1:
thsb6d96be2008-07-09 11:05:10 +00001869 {
pbrooka7812ae2008-11-17 14:43:54 +00001870 TCGv_i32 fp0 = tcg_temp_new_i32();
thsb6d96be2008-07-09 11:05:10 +00001871
aurel32c407df82009-04-16 11:51:03 +00001872 tcg_gen_qemu_ld32s(t0, t0, ctx->mem_idx);
1873 tcg_gen_trunc_tl_i32(fp0, t0);
thsb6d96be2008-07-09 11:05:10 +00001874 gen_store_fpr32(fp0, ft);
pbrooka7812ae2008-11-17 14:43:54 +00001875 tcg_temp_free_i32(fp0);
thsb6d96be2008-07-09 11:05:10 +00001876 }
bellard6ea83fe2006-06-14 12:56:19 +00001877 opn = "lwc1";
1878 break;
1879 case OPC_SWC1:
thsb6d96be2008-07-09 11:05:10 +00001880 {
pbrooka7812ae2008-11-17 14:43:54 +00001881 TCGv_i32 fp0 = tcg_temp_new_i32();
1882 TCGv t1 = tcg_temp_new();
thsb6d96be2008-07-09 11:05:10 +00001883
1884 gen_load_fpr32(fp0, ft);
pbrooka7812ae2008-11-17 14:43:54 +00001885 tcg_gen_extu_i32_tl(t1, fp0);
1886 tcg_gen_qemu_st32(t1, t0, ctx->mem_idx);
1887 tcg_temp_free(t1);
1888 tcg_temp_free_i32(fp0);
thsb6d96be2008-07-09 11:05:10 +00001889 }
bellard6ea83fe2006-06-14 12:56:19 +00001890 opn = "swc1";
1891 break;
1892 case OPC_LDC1:
thsb6d96be2008-07-09 11:05:10 +00001893 {
pbrooka7812ae2008-11-17 14:43:54 +00001894 TCGv_i64 fp0 = tcg_temp_new_i64();
thsb6d96be2008-07-09 11:05:10 +00001895
1896 tcg_gen_qemu_ld64(fp0, t0, ctx->mem_idx);
1897 gen_store_fpr64(ctx, fp0, ft);
pbrooka7812ae2008-11-17 14:43:54 +00001898 tcg_temp_free_i64(fp0);
thsb6d96be2008-07-09 11:05:10 +00001899 }
bellard6ea83fe2006-06-14 12:56:19 +00001900 opn = "ldc1";
1901 break;
1902 case OPC_SDC1:
thsb6d96be2008-07-09 11:05:10 +00001903 {
pbrooka7812ae2008-11-17 14:43:54 +00001904 TCGv_i64 fp0 = tcg_temp_new_i64();
thsb6d96be2008-07-09 11:05:10 +00001905
1906 gen_load_fpr64(ctx, fp0, ft);
1907 tcg_gen_qemu_st64(fp0, t0, ctx->mem_idx);
pbrooka7812ae2008-11-17 14:43:54 +00001908 tcg_temp_free_i64(fp0);
thsb6d96be2008-07-09 11:05:10 +00001909 }
bellard6ea83fe2006-06-14 12:56:19 +00001910 opn = "sdc1";
1911 break;
1912 default:
ths923617a2007-05-11 00:16:06 +00001913 MIPS_INVAL(opn);
thse397ee32007-03-23 00:43:28 +00001914 generate_exception(ctx, EXCP_RI);
ths78723682008-06-24 20:12:33 +00001915 goto out;
bellard6ea83fe2006-06-14 12:56:19 +00001916 }
Blue Swirl2abf3142010-10-13 18:38:08 +00001917 (void)opn; /* avoid a compiler warning */
bellard6ea83fe2006-06-14 12:56:19 +00001918 MIPS_DEBUG("%s %s, %d(%s)", opn, fregnames[ft], offset, regnames[base]);
ths78723682008-06-24 20:12:33 +00001919 out:
1920 tcg_temp_free(t0);
bellard6ea83fe2006-06-14 12:56:19 +00001921}
bellard6ea83fe2006-06-14 12:56:19 +00001922
Andreas Färber7db13fa2012-03-14 01:38:22 +01001923static void gen_cop1_ldst(CPUMIPSState *env, DisasContext *ctx,
Nathan Froyd26ebe462010-05-24 09:19:35 -07001924 uint32_t op, int rt, int rs, int16_t imm)
1925{
1926 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
1927 check_cp1_enabled(ctx);
1928 gen_flt_ldst(ctx, op, rt, rs, imm);
1929 } else {
1930 generate_exception_err(ctx, EXCP_CpU, 1);
1931 }
1932}
1933
bellard6af0bf92005-07-02 14:58:51 +00001934/* Arithmetic with immediate operand */
Aurelien Jarnod75c1352013-01-01 18:02:22 +01001935static void gen_arith_imm(DisasContext *ctx, uint32_t opc,
1936 int rt, int rs, int16_t imm)
bellard6af0bf92005-07-02 14:58:51 +00001937{
aurel32324d9e32009-04-11 18:42:17 +00001938 target_ulong uimm = (target_long)imm; /* Sign extend to 32/64 bits */
ths923617a2007-05-11 00:16:06 +00001939 const char *opn = "imm arith";
bellard6af0bf92005-07-02 14:58:51 +00001940
ths7a387ff2006-12-06 20:17:30 +00001941 if (rt == 0 && opc != OPC_ADDI && opc != OPC_DADDI) {
thsead93602007-09-06 00:18:15 +00001942 /* If no destination, treat it as a NOP.
1943 For addi, we must generate the overflow exception when needed. */
bellard6af0bf92005-07-02 14:58:51 +00001944 MIPS_DEBUG("NOP");
aurel32324d9e32009-04-11 18:42:17 +00001945 return;
bellard6af0bf92005-07-02 14:58:51 +00001946 }
1947 switch (opc) {
1948 case OPC_ADDI:
ths48d38ca2008-05-18 22:50:49 +00001949 {
aurel32324d9e32009-04-11 18:42:17 +00001950 TCGv t0 = tcg_temp_local_new();
1951 TCGv t1 = tcg_temp_new();
1952 TCGv t2 = tcg_temp_new();
ths48d38ca2008-05-18 22:50:49 +00001953 int l1 = gen_new_label();
1954
aurel32324d9e32009-04-11 18:42:17 +00001955 gen_load_gpr(t1, rs);
1956 tcg_gen_addi_tl(t0, t1, uimm);
1957 tcg_gen_ext32s_tl(t0, t0);
ths48d38ca2008-05-18 22:50:49 +00001958
aurel32324d9e32009-04-11 18:42:17 +00001959 tcg_gen_xori_tl(t1, t1, ~uimm);
1960 tcg_gen_xori_tl(t2, t0, uimm);
1961 tcg_gen_and_tl(t1, t1, t2);
1962 tcg_temp_free(t2);
1963 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
1964 tcg_temp_free(t1);
ths48d38ca2008-05-18 22:50:49 +00001965 /* operands of same sign, result different sign */
1966 generate_exception(ctx, EXCP_OVERFLOW);
1967 gen_set_label(l1);
ths78723682008-06-24 20:12:33 +00001968 tcg_gen_ext32s_tl(t0, t0);
aurel32324d9e32009-04-11 18:42:17 +00001969 gen_store_gpr(t0, rt);
1970 tcg_temp_free(t0);
ths48d38ca2008-05-18 22:50:49 +00001971 }
bellard6af0bf92005-07-02 14:58:51 +00001972 opn = "addi";
1973 break;
1974 case OPC_ADDIU:
aurel32324d9e32009-04-11 18:42:17 +00001975 if (rs != 0) {
1976 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
1977 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
1978 } else {
1979 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
1980 }
bellard6af0bf92005-07-02 14:58:51 +00001981 opn = "addiu";
1982 break;
thsd26bc212007-11-08 18:05:37 +00001983#if defined(TARGET_MIPS64)
ths7a387ff2006-12-06 20:17:30 +00001984 case OPC_DADDI:
ths48d38ca2008-05-18 22:50:49 +00001985 {
aurel32324d9e32009-04-11 18:42:17 +00001986 TCGv t0 = tcg_temp_local_new();
1987 TCGv t1 = tcg_temp_new();
1988 TCGv t2 = tcg_temp_new();
ths48d38ca2008-05-18 22:50:49 +00001989 int l1 = gen_new_label();
1990
aurel32324d9e32009-04-11 18:42:17 +00001991 gen_load_gpr(t1, rs);
1992 tcg_gen_addi_tl(t0, t1, uimm);
ths48d38ca2008-05-18 22:50:49 +00001993
aurel32324d9e32009-04-11 18:42:17 +00001994 tcg_gen_xori_tl(t1, t1, ~uimm);
1995 tcg_gen_xori_tl(t2, t0, uimm);
1996 tcg_gen_and_tl(t1, t1, t2);
1997 tcg_temp_free(t2);
1998 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
1999 tcg_temp_free(t1);
ths48d38ca2008-05-18 22:50:49 +00002000 /* operands of same sign, result different sign */
2001 generate_exception(ctx, EXCP_OVERFLOW);
2002 gen_set_label(l1);
aurel32324d9e32009-04-11 18:42:17 +00002003 gen_store_gpr(t0, rt);
2004 tcg_temp_free(t0);
ths48d38ca2008-05-18 22:50:49 +00002005 }
ths7a387ff2006-12-06 20:17:30 +00002006 opn = "daddi";
2007 break;
2008 case OPC_DADDIU:
aurel32324d9e32009-04-11 18:42:17 +00002009 if (rs != 0) {
2010 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
2011 } else {
2012 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
2013 }
ths7a387ff2006-12-06 20:17:30 +00002014 opn = "daddiu";
2015 break;
2016#endif
aurel32324d9e32009-04-11 18:42:17 +00002017 }
Blue Swirl2abf3142010-10-13 18:38:08 +00002018 (void)opn; /* avoid a compiler warning */
aurel32324d9e32009-04-11 18:42:17 +00002019 MIPS_DEBUG("%s %s, %s, " TARGET_FMT_lx, opn, regnames[rt], regnames[rs], uimm);
2020}
2021
2022/* Logic with immediate operand */
Aurelien Jarnod75c1352013-01-01 18:02:22 +01002023static void gen_logic_imm(DisasContext *ctx, uint32_t opc,
Richard Henderson9fa77482012-09-18 21:55:33 -07002024 int rt, int rs, int16_t imm)
aurel32324d9e32009-04-11 18:42:17 +00002025{
2026 target_ulong uimm;
aurel32324d9e32009-04-11 18:42:17 +00002027
2028 if (rt == 0) {
2029 /* If no destination, treat it as a NOP. */
2030 MIPS_DEBUG("NOP");
2031 return;
2032 }
2033 uimm = (uint16_t)imm;
2034 switch (opc) {
bellard6af0bf92005-07-02 14:58:51 +00002035 case OPC_ANDI:
aurel32324d9e32009-04-11 18:42:17 +00002036 if (likely(rs != 0))
2037 tcg_gen_andi_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
2038 else
2039 tcg_gen_movi_tl(cpu_gpr[rt], 0);
Eric Johnson7c2c3ea2012-11-09 19:40:51 -08002040 MIPS_DEBUG("andi %s, %s, " TARGET_FMT_lx, regnames[rt],
2041 regnames[rs], uimm);
bellard6af0bf92005-07-02 14:58:51 +00002042 break;
2043 case OPC_ORI:
aurel32324d9e32009-04-11 18:42:17 +00002044 if (rs != 0)
2045 tcg_gen_ori_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
2046 else
2047 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
Eric Johnson7c2c3ea2012-11-09 19:40:51 -08002048 MIPS_DEBUG("ori %s, %s, " TARGET_FMT_lx, regnames[rt],
2049 regnames[rs], uimm);
bellard6af0bf92005-07-02 14:58:51 +00002050 break;
2051 case OPC_XORI:
aurel32324d9e32009-04-11 18:42:17 +00002052 if (likely(rs != 0))
2053 tcg_gen_xori_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
2054 else
2055 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
Eric Johnson7c2c3ea2012-11-09 19:40:51 -08002056 MIPS_DEBUG("xori %s, %s, " TARGET_FMT_lx, regnames[rt],
2057 regnames[rs], uimm);
bellard6af0bf92005-07-02 14:58:51 +00002058 break;
2059 case OPC_LUI:
aurel32324d9e32009-04-11 18:42:17 +00002060 tcg_gen_movi_tl(cpu_gpr[rt], imm << 16);
Eric Johnson7c2c3ea2012-11-09 19:40:51 -08002061 MIPS_DEBUG("lui %s, " TARGET_FMT_lx, regnames[rt], uimm);
2062 break;
2063
2064 default:
2065 MIPS_DEBUG("Unknown logical immediate opcode %08x", opc);
bellard6af0bf92005-07-02 14:58:51 +00002066 break;
aurel32324d9e32009-04-11 18:42:17 +00002067 }
aurel32324d9e32009-04-11 18:42:17 +00002068}
2069
2070/* Set on less than with immediate operand */
Aurelien Jarnod75c1352013-01-01 18:02:22 +01002071static void gen_slt_imm(DisasContext *ctx, uint32_t opc,
Richard Henderson9fa77482012-09-18 21:55:33 -07002072 int rt, int rs, int16_t imm)
aurel32324d9e32009-04-11 18:42:17 +00002073{
2074 target_ulong uimm = (target_long)imm; /* Sign extend to 32/64 bits */
2075 const char *opn = "imm arith";
2076 TCGv t0;
2077
2078 if (rt == 0) {
2079 /* If no destination, treat it as a NOP. */
2080 MIPS_DEBUG("NOP");
2081 return;
2082 }
2083 t0 = tcg_temp_new();
2084 gen_load_gpr(t0, rs);
2085 switch (opc) {
2086 case OPC_SLTI:
Aurelien Jarnoe68dd282010-02-08 15:50:58 +01002087 tcg_gen_setcondi_tl(TCG_COND_LT, cpu_gpr[rt], t0, uimm);
aurel32324d9e32009-04-11 18:42:17 +00002088 opn = "slti";
2089 break;
2090 case OPC_SLTIU:
Aurelien Jarnoe68dd282010-02-08 15:50:58 +01002091 tcg_gen_setcondi_tl(TCG_COND_LTU, cpu_gpr[rt], t0, uimm);
aurel32324d9e32009-04-11 18:42:17 +00002092 opn = "sltiu";
2093 break;
2094 }
Blue Swirl2abf3142010-10-13 18:38:08 +00002095 (void)opn; /* avoid a compiler warning */
aurel32324d9e32009-04-11 18:42:17 +00002096 MIPS_DEBUG("%s %s, %s, " TARGET_FMT_lx, opn, regnames[rt], regnames[rs], uimm);
2097 tcg_temp_free(t0);
2098}
2099
2100/* Shifts with immediate operand */
Aurelien Jarnod75c1352013-01-01 18:02:22 +01002101static void gen_shift_imm(DisasContext *ctx, uint32_t opc,
aurel32324d9e32009-04-11 18:42:17 +00002102 int rt, int rs, int16_t imm)
2103{
2104 target_ulong uimm = ((uint16_t)imm) & 0x1f;
2105 const char *opn = "imm shift";
2106 TCGv t0;
2107
2108 if (rt == 0) {
2109 /* If no destination, treat it as a NOP. */
2110 MIPS_DEBUG("NOP");
2111 return;
2112 }
2113
2114 t0 = tcg_temp_new();
2115 gen_load_gpr(t0, rs);
2116 switch (opc) {
bellard6af0bf92005-07-02 14:58:51 +00002117 case OPC_SLL:
ths78723682008-06-24 20:12:33 +00002118 tcg_gen_shli_tl(t0, t0, uimm);
aurel32324d9e32009-04-11 18:42:17 +00002119 tcg_gen_ext32s_tl(cpu_gpr[rt], t0);
bellard6af0bf92005-07-02 14:58:51 +00002120 opn = "sll";
2121 break;
2122 case OPC_SRA:
aurel32324d9e32009-04-11 18:42:17 +00002123 tcg_gen_sari_tl(cpu_gpr[rt], t0, uimm);
bellard6af0bf92005-07-02 14:58:51 +00002124 opn = "sra";
2125 break;
2126 case OPC_SRL:
Nathan Froydea63e2c2009-12-08 08:06:24 -08002127 if (uimm != 0) {
2128 tcg_gen_ext32u_tl(t0, t0);
2129 tcg_gen_shri_tl(cpu_gpr[rt], t0, uimm);
2130 } else {
2131 tcg_gen_ext32s_tl(cpu_gpr[rt], t0);
ths5a63bcb2007-04-05 23:20:05 +00002132 }
Nathan Froydea63e2c2009-12-08 08:06:24 -08002133 opn = "srl";
2134 break;
2135 case OPC_ROTR:
2136 if (uimm != 0) {
2137 TCGv_i32 t1 = tcg_temp_new_i32();
2138
2139 tcg_gen_trunc_tl_i32(t1, t0);
2140 tcg_gen_rotri_i32(t1, t1, uimm);
2141 tcg_gen_ext_i32_tl(cpu_gpr[rt], t1);
2142 tcg_temp_free_i32(t1);
Nathan Froyd3399e302010-02-20 10:24:07 -08002143 } else {
2144 tcg_gen_ext32s_tl(cpu_gpr[rt], t0);
Nathan Froydea63e2c2009-12-08 08:06:24 -08002145 }
2146 opn = "rotr";
bellard6af0bf92005-07-02 14:58:51 +00002147 break;
thsd26bc212007-11-08 18:05:37 +00002148#if defined(TARGET_MIPS64)
ths7a387ff2006-12-06 20:17:30 +00002149 case OPC_DSLL:
aurel32324d9e32009-04-11 18:42:17 +00002150 tcg_gen_shli_tl(cpu_gpr[rt], t0, uimm);
ths7a387ff2006-12-06 20:17:30 +00002151 opn = "dsll";
2152 break;
2153 case OPC_DSRA:
aurel32324d9e32009-04-11 18:42:17 +00002154 tcg_gen_sari_tl(cpu_gpr[rt], t0, uimm);
ths7a387ff2006-12-06 20:17:30 +00002155 opn = "dsra";
2156 break;
2157 case OPC_DSRL:
Nathan Froydea63e2c2009-12-08 08:06:24 -08002158 tcg_gen_shri_tl(cpu_gpr[rt], t0, uimm);
2159 opn = "dsrl";
2160 break;
2161 case OPC_DROTR:
2162 if (uimm != 0) {
2163 tcg_gen_rotri_tl(cpu_gpr[rt], t0, uimm);
Nathan Froyd3399e302010-02-20 10:24:07 -08002164 } else {
2165 tcg_gen_mov_tl(cpu_gpr[rt], t0);
ths5a63bcb2007-04-05 23:20:05 +00002166 }
Nathan Froydea63e2c2009-12-08 08:06:24 -08002167 opn = "drotr";
ths7a387ff2006-12-06 20:17:30 +00002168 break;
2169 case OPC_DSLL32:
aurel32324d9e32009-04-11 18:42:17 +00002170 tcg_gen_shli_tl(cpu_gpr[rt], t0, uimm + 32);
ths7a387ff2006-12-06 20:17:30 +00002171 opn = "dsll32";
2172 break;
2173 case OPC_DSRA32:
aurel32324d9e32009-04-11 18:42:17 +00002174 tcg_gen_sari_tl(cpu_gpr[rt], t0, uimm + 32);
ths7a387ff2006-12-06 20:17:30 +00002175 opn = "dsra32";
2176 break;
2177 case OPC_DSRL32:
Nathan Froydea63e2c2009-12-08 08:06:24 -08002178 tcg_gen_shri_tl(cpu_gpr[rt], t0, uimm + 32);
2179 opn = "dsrl32";
2180 break;
2181 case OPC_DROTR32:
2182 tcg_gen_rotri_tl(cpu_gpr[rt], t0, uimm + 32);
2183 opn = "drotr32";
ths7a387ff2006-12-06 20:17:30 +00002184 break;
2185#endif
bellard6af0bf92005-07-02 14:58:51 +00002186 }
Blue Swirl2abf3142010-10-13 18:38:08 +00002187 (void)opn; /* avoid a compiler warning */
ths93b12cc2007-05-20 01:36:29 +00002188 MIPS_DEBUG("%s %s, %s, " TARGET_FMT_lx, opn, regnames[rt], regnames[rs], uimm);
ths78723682008-06-24 20:12:33 +00002189 tcg_temp_free(t0);
bellard6af0bf92005-07-02 14:58:51 +00002190}
2191
2192/* Arithmetic */
Aurelien Jarnod75c1352013-01-01 18:02:22 +01002193static void gen_arith(DisasContext *ctx, uint32_t opc,
2194 int rd, int rs, int rt)
bellard6af0bf92005-07-02 14:58:51 +00002195{
ths923617a2007-05-11 00:16:06 +00002196 const char *opn = "arith";
bellard6af0bf92005-07-02 14:58:51 +00002197
ths7a387ff2006-12-06 20:17:30 +00002198 if (rd == 0 && opc != OPC_ADD && opc != OPC_SUB
2199 && opc != OPC_DADD && opc != OPC_DSUB) {
thsead93602007-09-06 00:18:15 +00002200 /* If no destination, treat it as a NOP.
2201 For add & sub, we must generate the overflow exception when needed. */
bellard6af0bf92005-07-02 14:58:51 +00002202 MIPS_DEBUG("NOP");
aurel32460f00c2009-04-08 21:48:02 +00002203 return;
bellard6af0bf92005-07-02 14:58:51 +00002204 }
aurel32460f00c2009-04-08 21:48:02 +00002205
bellard6af0bf92005-07-02 14:58:51 +00002206 switch (opc) {
2207 case OPC_ADD:
ths48d38ca2008-05-18 22:50:49 +00002208 {
aurel32460f00c2009-04-08 21:48:02 +00002209 TCGv t0 = tcg_temp_local_new();
2210 TCGv t1 = tcg_temp_new();
2211 TCGv t2 = tcg_temp_new();
ths48d38ca2008-05-18 22:50:49 +00002212 int l1 = gen_new_label();
2213
aurel32460f00c2009-04-08 21:48:02 +00002214 gen_load_gpr(t1, rs);
2215 gen_load_gpr(t2, rt);
2216 tcg_gen_add_tl(t0, t1, t2);
2217 tcg_gen_ext32s_tl(t0, t0);
2218 tcg_gen_xor_tl(t1, t1, t2);
aurel32460f00c2009-04-08 21:48:02 +00002219 tcg_gen_xor_tl(t2, t0, t2);
Aurelien Jarnodeb42032010-03-03 12:22:11 +01002220 tcg_gen_andc_tl(t1, t2, t1);
aurel32460f00c2009-04-08 21:48:02 +00002221 tcg_temp_free(t2);
2222 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
2223 tcg_temp_free(t1);
ths48d38ca2008-05-18 22:50:49 +00002224 /* operands of same sign, result different sign */
2225 generate_exception(ctx, EXCP_OVERFLOW);
2226 gen_set_label(l1);
aurel32460f00c2009-04-08 21:48:02 +00002227 gen_store_gpr(t0, rd);
2228 tcg_temp_free(t0);
ths48d38ca2008-05-18 22:50:49 +00002229 }
bellard6af0bf92005-07-02 14:58:51 +00002230 opn = "add";
2231 break;
2232 case OPC_ADDU:
aurel32460f00c2009-04-08 21:48:02 +00002233 if (rs != 0 && rt != 0) {
2234 tcg_gen_add_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
2235 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
2236 } else if (rs == 0 && rt != 0) {
2237 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
2238 } else if (rs != 0 && rt == 0) {
2239 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
2240 } else {
2241 tcg_gen_movi_tl(cpu_gpr[rd], 0);
2242 }
bellard6af0bf92005-07-02 14:58:51 +00002243 opn = "addu";
2244 break;
2245 case OPC_SUB:
ths48d38ca2008-05-18 22:50:49 +00002246 {
aurel32460f00c2009-04-08 21:48:02 +00002247 TCGv t0 = tcg_temp_local_new();
2248 TCGv t1 = tcg_temp_new();
2249 TCGv t2 = tcg_temp_new();
ths48d38ca2008-05-18 22:50:49 +00002250 int l1 = gen_new_label();
2251
aurel32460f00c2009-04-08 21:48:02 +00002252 gen_load_gpr(t1, rs);
2253 gen_load_gpr(t2, rt);
2254 tcg_gen_sub_tl(t0, t1, t2);
2255 tcg_gen_ext32s_tl(t0, t0);
2256 tcg_gen_xor_tl(t2, t1, t2);
2257 tcg_gen_xor_tl(t1, t0, t1);
2258 tcg_gen_and_tl(t1, t1, t2);
2259 tcg_temp_free(t2);
2260 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
2261 tcg_temp_free(t1);
Aurelien Jarno31e31042009-11-14 13:10:00 +01002262 /* operands of different sign, first operand and result different sign */
ths48d38ca2008-05-18 22:50:49 +00002263 generate_exception(ctx, EXCP_OVERFLOW);
2264 gen_set_label(l1);
aurel32460f00c2009-04-08 21:48:02 +00002265 gen_store_gpr(t0, rd);
2266 tcg_temp_free(t0);
ths48d38ca2008-05-18 22:50:49 +00002267 }
bellard6af0bf92005-07-02 14:58:51 +00002268 opn = "sub";
2269 break;
2270 case OPC_SUBU:
aurel32460f00c2009-04-08 21:48:02 +00002271 if (rs != 0 && rt != 0) {
2272 tcg_gen_sub_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
2273 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
2274 } else if (rs == 0 && rt != 0) {
2275 tcg_gen_neg_tl(cpu_gpr[rd], cpu_gpr[rt]);
Aurelien Jarno6bb72b12009-05-04 09:54:57 +02002276 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
aurel32460f00c2009-04-08 21:48:02 +00002277 } else if (rs != 0 && rt == 0) {
2278 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
2279 } else {
2280 tcg_gen_movi_tl(cpu_gpr[rd], 0);
2281 }
bellard6af0bf92005-07-02 14:58:51 +00002282 opn = "subu";
2283 break;
thsd26bc212007-11-08 18:05:37 +00002284#if defined(TARGET_MIPS64)
ths7a387ff2006-12-06 20:17:30 +00002285 case OPC_DADD:
ths48d38ca2008-05-18 22:50:49 +00002286 {
aurel32460f00c2009-04-08 21:48:02 +00002287 TCGv t0 = tcg_temp_local_new();
2288 TCGv t1 = tcg_temp_new();
2289 TCGv t2 = tcg_temp_new();
ths48d38ca2008-05-18 22:50:49 +00002290 int l1 = gen_new_label();
2291
aurel32460f00c2009-04-08 21:48:02 +00002292 gen_load_gpr(t1, rs);
2293 gen_load_gpr(t2, rt);
2294 tcg_gen_add_tl(t0, t1, t2);
2295 tcg_gen_xor_tl(t1, t1, t2);
aurel32460f00c2009-04-08 21:48:02 +00002296 tcg_gen_xor_tl(t2, t0, t2);
Aurelien Jarnodeb42032010-03-03 12:22:11 +01002297 tcg_gen_andc_tl(t1, t2, t1);
aurel32460f00c2009-04-08 21:48:02 +00002298 tcg_temp_free(t2);
2299 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
2300 tcg_temp_free(t1);
ths48d38ca2008-05-18 22:50:49 +00002301 /* operands of same sign, result different sign */
2302 generate_exception(ctx, EXCP_OVERFLOW);
2303 gen_set_label(l1);
aurel32460f00c2009-04-08 21:48:02 +00002304 gen_store_gpr(t0, rd);
2305 tcg_temp_free(t0);
ths48d38ca2008-05-18 22:50:49 +00002306 }
ths7a387ff2006-12-06 20:17:30 +00002307 opn = "dadd";
2308 break;
2309 case OPC_DADDU:
aurel32460f00c2009-04-08 21:48:02 +00002310 if (rs != 0 && rt != 0) {
2311 tcg_gen_add_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
2312 } else if (rs == 0 && rt != 0) {
2313 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
2314 } else if (rs != 0 && rt == 0) {
2315 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
2316 } else {
2317 tcg_gen_movi_tl(cpu_gpr[rd], 0);
2318 }
ths7a387ff2006-12-06 20:17:30 +00002319 opn = "daddu";
2320 break;
2321 case OPC_DSUB:
ths48d38ca2008-05-18 22:50:49 +00002322 {
aurel32460f00c2009-04-08 21:48:02 +00002323 TCGv t0 = tcg_temp_local_new();
2324 TCGv t1 = tcg_temp_new();
2325 TCGv t2 = tcg_temp_new();
ths48d38ca2008-05-18 22:50:49 +00002326 int l1 = gen_new_label();
2327
aurel32460f00c2009-04-08 21:48:02 +00002328 gen_load_gpr(t1, rs);
2329 gen_load_gpr(t2, rt);
2330 tcg_gen_sub_tl(t0, t1, t2);
2331 tcg_gen_xor_tl(t2, t1, t2);
2332 tcg_gen_xor_tl(t1, t0, t1);
2333 tcg_gen_and_tl(t1, t1, t2);
2334 tcg_temp_free(t2);
2335 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
2336 tcg_temp_free(t1);
Aurelien Jarno31e31042009-11-14 13:10:00 +01002337 /* operands of different sign, first operand and result different sign */
ths48d38ca2008-05-18 22:50:49 +00002338 generate_exception(ctx, EXCP_OVERFLOW);
2339 gen_set_label(l1);
aurel32460f00c2009-04-08 21:48:02 +00002340 gen_store_gpr(t0, rd);
2341 tcg_temp_free(t0);
ths48d38ca2008-05-18 22:50:49 +00002342 }
ths7a387ff2006-12-06 20:17:30 +00002343 opn = "dsub";
2344 break;
2345 case OPC_DSUBU:
aurel32460f00c2009-04-08 21:48:02 +00002346 if (rs != 0 && rt != 0) {
2347 tcg_gen_sub_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
2348 } else if (rs == 0 && rt != 0) {
2349 tcg_gen_neg_tl(cpu_gpr[rd], cpu_gpr[rt]);
2350 } else if (rs != 0 && rt == 0) {
2351 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
2352 } else {
2353 tcg_gen_movi_tl(cpu_gpr[rd], 0);
2354 }
ths7a387ff2006-12-06 20:17:30 +00002355 opn = "dsubu";
2356 break;
2357#endif
aurel32460f00c2009-04-08 21:48:02 +00002358 case OPC_MUL:
2359 if (likely(rs != 0 && rt != 0)) {
2360 tcg_gen_mul_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
2361 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
2362 } else {
2363 tcg_gen_movi_tl(cpu_gpr[rd], 0);
2364 }
2365 opn = "mul";
bellard6af0bf92005-07-02 14:58:51 +00002366 break;
aurel32460f00c2009-04-08 21:48:02 +00002367 }
Blue Swirl2abf3142010-10-13 18:38:08 +00002368 (void)opn; /* avoid a compiler warning */
aurel32460f00c2009-04-08 21:48:02 +00002369 MIPS_DEBUG("%s %s, %s, %s", opn, regnames[rd], regnames[rs], regnames[rt]);
2370}
2371
2372/* Conditional move */
Aurelien Jarnod75c1352013-01-01 18:02:22 +01002373static void gen_cond_move(DisasContext *ctx, uint32_t opc,
Richard Henderson9fa77482012-09-18 21:55:33 -07002374 int rd, int rs, int rt)
aurel32460f00c2009-04-08 21:48:02 +00002375{
2376 const char *opn = "cond move";
Aurelien Jarnoacf12462012-10-09 21:53:21 +02002377 TCGv t0, t1, t2;
aurel32460f00c2009-04-08 21:48:02 +00002378
2379 if (rd == 0) {
Aurelien Jarnoacf12462012-10-09 21:53:21 +02002380 /* If no destination, treat it as a NOP. */
aurel32460f00c2009-04-08 21:48:02 +00002381 MIPS_DEBUG("NOP");
2382 return;
2383 }
2384
Aurelien Jarnoacf12462012-10-09 21:53:21 +02002385 t0 = tcg_temp_new();
2386 gen_load_gpr(t0, rt);
2387 t1 = tcg_const_tl(0);
2388 t2 = tcg_temp_new();
2389 gen_load_gpr(t2, rs);
aurel32460f00c2009-04-08 21:48:02 +00002390 switch (opc) {
2391 case OPC_MOVN:
Aurelien Jarnoacf12462012-10-09 21:53:21 +02002392 tcg_gen_movcond_tl(TCG_COND_NE, cpu_gpr[rd], t0, t1, t2, cpu_gpr[rd]);
aurel32460f00c2009-04-08 21:48:02 +00002393 opn = "movn";
bellard6af0bf92005-07-02 14:58:51 +00002394 break;
aurel32460f00c2009-04-08 21:48:02 +00002395 case OPC_MOVZ:
Aurelien Jarnoacf12462012-10-09 21:53:21 +02002396 tcg_gen_movcond_tl(TCG_COND_EQ, cpu_gpr[rd], t0, t1, t2, cpu_gpr[rd]);
aurel32460f00c2009-04-08 21:48:02 +00002397 opn = "movz";
2398 break;
2399 }
Aurelien Jarnoacf12462012-10-09 21:53:21 +02002400 tcg_temp_free(t2);
2401 tcg_temp_free(t1);
2402 tcg_temp_free(t0);
aurel32460f00c2009-04-08 21:48:02 +00002403
Blue Swirl2abf3142010-10-13 18:38:08 +00002404 (void)opn; /* avoid a compiler warning */
aurel32460f00c2009-04-08 21:48:02 +00002405 MIPS_DEBUG("%s %s, %s, %s", opn, regnames[rd], regnames[rs], regnames[rt]);
2406}
2407
2408/* Logic */
Aurelien Jarnod75c1352013-01-01 18:02:22 +01002409static void gen_logic(DisasContext *ctx, uint32_t opc,
Richard Henderson9fa77482012-09-18 21:55:33 -07002410 int rd, int rs, int rt)
aurel32460f00c2009-04-08 21:48:02 +00002411{
2412 const char *opn = "logic";
2413
2414 if (rd == 0) {
2415 /* If no destination, treat it as a NOP. */
2416 MIPS_DEBUG("NOP");
2417 return;
2418 }
2419
2420 switch (opc) {
bellard6af0bf92005-07-02 14:58:51 +00002421 case OPC_AND:
aurel32460f00c2009-04-08 21:48:02 +00002422 if (likely(rs != 0 && rt != 0)) {
2423 tcg_gen_and_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
2424 } else {
2425 tcg_gen_movi_tl(cpu_gpr[rd], 0);
2426 }
bellard6af0bf92005-07-02 14:58:51 +00002427 opn = "and";
2428 break;
2429 case OPC_NOR:
aurel32460f00c2009-04-08 21:48:02 +00002430 if (rs != 0 && rt != 0) {
2431 tcg_gen_nor_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
2432 } else if (rs == 0 && rt != 0) {
2433 tcg_gen_not_tl(cpu_gpr[rd], cpu_gpr[rt]);
2434 } else if (rs != 0 && rt == 0) {
2435 tcg_gen_not_tl(cpu_gpr[rd], cpu_gpr[rs]);
2436 } else {
2437 tcg_gen_movi_tl(cpu_gpr[rd], ~((target_ulong)0));
2438 }
bellard6af0bf92005-07-02 14:58:51 +00002439 opn = "nor";
2440 break;
2441 case OPC_OR:
aurel32460f00c2009-04-08 21:48:02 +00002442 if (likely(rs != 0 && rt != 0)) {
2443 tcg_gen_or_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
2444 } else if (rs == 0 && rt != 0) {
2445 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
2446 } else if (rs != 0 && rt == 0) {
2447 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
2448 } else {
2449 tcg_gen_movi_tl(cpu_gpr[rd], 0);
2450 }
bellard6af0bf92005-07-02 14:58:51 +00002451 opn = "or";
2452 break;
2453 case OPC_XOR:
aurel32460f00c2009-04-08 21:48:02 +00002454 if (likely(rs != 0 && rt != 0)) {
2455 tcg_gen_xor_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
2456 } else if (rs == 0 && rt != 0) {
2457 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
2458 } else if (rs != 0 && rt == 0) {
2459 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
2460 } else {
2461 tcg_gen_movi_tl(cpu_gpr[rd], 0);
2462 }
bellard6af0bf92005-07-02 14:58:51 +00002463 opn = "xor";
2464 break;
aurel32460f00c2009-04-08 21:48:02 +00002465 }
Blue Swirl2abf3142010-10-13 18:38:08 +00002466 (void)opn; /* avoid a compiler warning */
aurel32460f00c2009-04-08 21:48:02 +00002467 MIPS_DEBUG("%s %s, %s, %s", opn, regnames[rd], regnames[rs], regnames[rt]);
2468}
2469
2470/* Set on lower than */
Aurelien Jarnod75c1352013-01-01 18:02:22 +01002471static void gen_slt(DisasContext *ctx, uint32_t opc,
Richard Henderson9fa77482012-09-18 21:55:33 -07002472 int rd, int rs, int rt)
aurel32460f00c2009-04-08 21:48:02 +00002473{
2474 const char *opn = "slt";
2475 TCGv t0, t1;
2476
2477 if (rd == 0) {
2478 /* If no destination, treat it as a NOP. */
2479 MIPS_DEBUG("NOP");
2480 return;
2481 }
2482
2483 t0 = tcg_temp_new();
2484 t1 = tcg_temp_new();
2485 gen_load_gpr(t0, rs);
2486 gen_load_gpr(t1, rt);
2487 switch (opc) {
2488 case OPC_SLT:
Aurelien Jarnoe68dd282010-02-08 15:50:58 +01002489 tcg_gen_setcond_tl(TCG_COND_LT, cpu_gpr[rd], t0, t1);
aurel32460f00c2009-04-08 21:48:02 +00002490 opn = "slt";
bellard6af0bf92005-07-02 14:58:51 +00002491 break;
aurel32460f00c2009-04-08 21:48:02 +00002492 case OPC_SLTU:
Aurelien Jarnoe68dd282010-02-08 15:50:58 +01002493 tcg_gen_setcond_tl(TCG_COND_LTU, cpu_gpr[rd], t0, t1);
aurel32460f00c2009-04-08 21:48:02 +00002494 opn = "sltu";
2495 break;
2496 }
Blue Swirl2abf3142010-10-13 18:38:08 +00002497 (void)opn; /* avoid a compiler warning */
aurel32460f00c2009-04-08 21:48:02 +00002498 MIPS_DEBUG("%s %s, %s, %s", opn, regnames[rd], regnames[rs], regnames[rt]);
2499 tcg_temp_free(t0);
2500 tcg_temp_free(t1);
2501}
ths20c4c972008-05-21 02:02:39 +00002502
aurel32460f00c2009-04-08 21:48:02 +00002503/* Shifts */
Aurelien Jarnod75c1352013-01-01 18:02:22 +01002504static void gen_shift(DisasContext *ctx, uint32_t opc,
2505 int rd, int rs, int rt)
aurel32460f00c2009-04-08 21:48:02 +00002506{
2507 const char *opn = "shifts";
2508 TCGv t0, t1;
ths20c4c972008-05-21 02:02:39 +00002509
aurel32460f00c2009-04-08 21:48:02 +00002510 if (rd == 0) {
2511 /* If no destination, treat it as a NOP.
2512 For add & sub, we must generate the overflow exception when needed. */
2513 MIPS_DEBUG("NOP");
2514 return;
2515 }
2516
2517 t0 = tcg_temp_new();
2518 t1 = tcg_temp_new();
2519 gen_load_gpr(t0, rs);
2520 gen_load_gpr(t1, rt);
2521 switch (opc) {
bellard6af0bf92005-07-02 14:58:51 +00002522 case OPC_SLLV:
ths78723682008-06-24 20:12:33 +00002523 tcg_gen_andi_tl(t0, t0, 0x1f);
2524 tcg_gen_shl_tl(t0, t1, t0);
aurel32460f00c2009-04-08 21:48:02 +00002525 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
bellard6af0bf92005-07-02 14:58:51 +00002526 opn = "sllv";
2527 break;
2528 case OPC_SRAV:
ths78723682008-06-24 20:12:33 +00002529 tcg_gen_andi_tl(t0, t0, 0x1f);
aurel32460f00c2009-04-08 21:48:02 +00002530 tcg_gen_sar_tl(cpu_gpr[rd], t1, t0);
bellard6af0bf92005-07-02 14:58:51 +00002531 opn = "srav";
2532 break;
2533 case OPC_SRLV:
Nathan Froydea63e2c2009-12-08 08:06:24 -08002534 tcg_gen_ext32u_tl(t1, t1);
2535 tcg_gen_andi_tl(t0, t0, 0x1f);
2536 tcg_gen_shr_tl(t0, t1, t0);
2537 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
2538 opn = "srlv";
2539 break;
2540 case OPC_ROTRV:
2541 {
2542 TCGv_i32 t2 = tcg_temp_new_i32();
2543 TCGv_i32 t3 = tcg_temp_new_i32();
ths48d38ca2008-05-18 22:50:49 +00002544
Nathan Froydea63e2c2009-12-08 08:06:24 -08002545 tcg_gen_trunc_tl_i32(t2, t0);
2546 tcg_gen_trunc_tl_i32(t3, t1);
2547 tcg_gen_andi_i32(t2, t2, 0x1f);
2548 tcg_gen_rotr_i32(t2, t3, t2);
2549 tcg_gen_ext_i32_tl(cpu_gpr[rd], t2);
2550 tcg_temp_free_i32(t2);
2551 tcg_temp_free_i32(t3);
2552 opn = "rotrv";
ths5a63bcb2007-04-05 23:20:05 +00002553 }
bellard6af0bf92005-07-02 14:58:51 +00002554 break;
thsd26bc212007-11-08 18:05:37 +00002555#if defined(TARGET_MIPS64)
ths7a387ff2006-12-06 20:17:30 +00002556 case OPC_DSLLV:
ths78723682008-06-24 20:12:33 +00002557 tcg_gen_andi_tl(t0, t0, 0x3f);
aurel32460f00c2009-04-08 21:48:02 +00002558 tcg_gen_shl_tl(cpu_gpr[rd], t1, t0);
ths7a387ff2006-12-06 20:17:30 +00002559 opn = "dsllv";
2560 break;
2561 case OPC_DSRAV:
ths78723682008-06-24 20:12:33 +00002562 tcg_gen_andi_tl(t0, t0, 0x3f);
aurel32460f00c2009-04-08 21:48:02 +00002563 tcg_gen_sar_tl(cpu_gpr[rd], t1, t0);
ths7a387ff2006-12-06 20:17:30 +00002564 opn = "dsrav";
2565 break;
2566 case OPC_DSRLV:
Nathan Froydea63e2c2009-12-08 08:06:24 -08002567 tcg_gen_andi_tl(t0, t0, 0x3f);
2568 tcg_gen_shr_tl(cpu_gpr[rd], t1, t0);
2569 opn = "dsrlv";
2570 break;
2571 case OPC_DROTRV:
2572 tcg_gen_andi_tl(t0, t0, 0x3f);
2573 tcg_gen_rotr_tl(cpu_gpr[rd], t1, t0);
2574 opn = "drotrv";
ths7a387ff2006-12-06 20:17:30 +00002575 break;
2576#endif
bellard6af0bf92005-07-02 14:58:51 +00002577 }
Blue Swirl2abf3142010-10-13 18:38:08 +00002578 (void)opn; /* avoid a compiler warning */
bellard6af0bf92005-07-02 14:58:51 +00002579 MIPS_DEBUG("%s %s, %s, %s", opn, regnames[rd], regnames[rs], regnames[rt]);
ths78723682008-06-24 20:12:33 +00002580 tcg_temp_free(t0);
2581 tcg_temp_free(t1);
bellard6af0bf92005-07-02 14:58:51 +00002582}
2583
2584/* Arithmetic on HI/LO registers */
ths7a387ff2006-12-06 20:17:30 +00002585static void gen_HILO (DisasContext *ctx, uint32_t opc, int reg)
bellard6af0bf92005-07-02 14:58:51 +00002586{
ths923617a2007-05-11 00:16:06 +00002587 const char *opn = "hilo";
Jia Liu41334982012-10-24 22:17:03 +08002588 unsigned int acc;
bellard6af0bf92005-07-02 14:58:51 +00002589
2590 if (reg == 0 && (opc == OPC_MFHI || opc == OPC_MFLO)) {
thsead93602007-09-06 00:18:15 +00002591 /* Treat as NOP. */
bellard6af0bf92005-07-02 14:58:51 +00002592 MIPS_DEBUG("NOP");
aurel32a1f66842009-03-09 18:50:43 +00002593 return;
bellard6af0bf92005-07-02 14:58:51 +00002594 }
Jia Liu41334982012-10-24 22:17:03 +08002595
2596 if (opc == OPC_MFHI || opc == OPC_MFLO) {
2597 acc = ((ctx->opcode) >> 21) & 0x03;
2598 } else {
2599 acc = ((ctx->opcode) >> 11) & 0x03;
2600 }
2601
2602 if (acc != 0) {
2603 check_dsp(ctx);
2604 }
2605
bellard6af0bf92005-07-02 14:58:51 +00002606 switch (opc) {
2607 case OPC_MFHI:
Jia Liu41334982012-10-24 22:17:03 +08002608#if defined(TARGET_MIPS64)
2609 if (acc != 0) {
2610 tcg_gen_ext32s_tl(cpu_gpr[reg], cpu_HI[acc]);
2611 } else
2612#endif
2613 {
2614 tcg_gen_mov_tl(cpu_gpr[reg], cpu_HI[acc]);
2615 }
bellard6af0bf92005-07-02 14:58:51 +00002616 opn = "mfhi";
2617 break;
2618 case OPC_MFLO:
Jia Liu41334982012-10-24 22:17:03 +08002619#if defined(TARGET_MIPS64)
2620 if (acc != 0) {
2621 tcg_gen_ext32s_tl(cpu_gpr[reg], cpu_LO[acc]);
2622 } else
2623#endif
2624 {
2625 tcg_gen_mov_tl(cpu_gpr[reg], cpu_LO[acc]);
2626 }
bellard6af0bf92005-07-02 14:58:51 +00002627 opn = "mflo";
2628 break;
2629 case OPC_MTHI:
Jia Liu41334982012-10-24 22:17:03 +08002630 if (reg != 0) {
2631#if defined(TARGET_MIPS64)
2632 if (acc != 0) {
2633 tcg_gen_ext32s_tl(cpu_HI[acc], cpu_gpr[reg]);
2634 } else
2635#endif
2636 {
2637 tcg_gen_mov_tl(cpu_HI[acc], cpu_gpr[reg]);
2638 }
2639 } else {
2640 tcg_gen_movi_tl(cpu_HI[acc], 0);
2641 }
bellard6af0bf92005-07-02 14:58:51 +00002642 opn = "mthi";
2643 break;
2644 case OPC_MTLO:
Jia Liu41334982012-10-24 22:17:03 +08002645 if (reg != 0) {
2646#if defined(TARGET_MIPS64)
2647 if (acc != 0) {
2648 tcg_gen_ext32s_tl(cpu_LO[acc], cpu_gpr[reg]);
2649 } else
2650#endif
2651 {
2652 tcg_gen_mov_tl(cpu_LO[acc], cpu_gpr[reg]);
2653 }
2654 } else {
2655 tcg_gen_movi_tl(cpu_LO[acc], 0);
2656 }
bellard6af0bf92005-07-02 14:58:51 +00002657 opn = "mtlo";
2658 break;
bellard6af0bf92005-07-02 14:58:51 +00002659 }
Blue Swirl2abf3142010-10-13 18:38:08 +00002660 (void)opn; /* avoid a compiler warning */
bellard6af0bf92005-07-02 14:58:51 +00002661 MIPS_DEBUG("%s %s", opn, regnames[reg]);
2662}
2663
ths7a387ff2006-12-06 20:17:30 +00002664static void gen_muldiv (DisasContext *ctx, uint32_t opc,
bellard6af0bf92005-07-02 14:58:51 +00002665 int rs, int rt)
2666{
ths923617a2007-05-11 00:16:06 +00002667 const char *opn = "mul/div";
aurel32d45f89f2009-03-29 01:19:31 +00002668 TCGv t0, t1;
Jia Liu41334982012-10-24 22:17:03 +08002669 unsigned int acc;
aurel32d45f89f2009-03-29 01:19:31 +00002670
Aurelien Jarno51127182012-10-09 21:53:21 +02002671 t0 = tcg_temp_new();
2672 t1 = tcg_temp_new();
bellard6af0bf92005-07-02 14:58:51 +00002673
ths78723682008-06-24 20:12:33 +00002674 gen_load_gpr(t0, rs);
2675 gen_load_gpr(t1, rt);
Aurelien Jarno51127182012-10-09 21:53:21 +02002676
bellard6af0bf92005-07-02 14:58:51 +00002677 switch (opc) {
2678 case OPC_DIV:
ths48d38ca2008-05-18 22:50:49 +00002679 {
Aurelien Jarno51127182012-10-09 21:53:21 +02002680 TCGv t2 = tcg_temp_new();
2681 TCGv t3 = tcg_temp_new();
aurel32d45f89f2009-03-29 01:19:31 +00002682 tcg_gen_ext32s_tl(t0, t0);
2683 tcg_gen_ext32s_tl(t1, t1);
Aurelien Jarno51127182012-10-09 21:53:21 +02002684 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, INT_MIN);
2685 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1);
2686 tcg_gen_and_tl(t2, t2, t3);
2687 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
2688 tcg_gen_or_tl(t2, t2, t3);
2689 tcg_gen_movi_tl(t3, 0);
2690 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
aurel32d45f89f2009-03-29 01:19:31 +00002691 tcg_gen_div_tl(cpu_LO[0], t0, t1);
2692 tcg_gen_rem_tl(cpu_HI[0], t0, t1);
2693 tcg_gen_ext32s_tl(cpu_LO[0], cpu_LO[0]);
2694 tcg_gen_ext32s_tl(cpu_HI[0], cpu_HI[0]);
Aurelien Jarno51127182012-10-09 21:53:21 +02002695 tcg_temp_free(t3);
2696 tcg_temp_free(t2);
ths48d38ca2008-05-18 22:50:49 +00002697 }
bellard6af0bf92005-07-02 14:58:51 +00002698 opn = "div";
2699 break;
2700 case OPC_DIVU:
ths48d38ca2008-05-18 22:50:49 +00002701 {
Aurelien Jarno51127182012-10-09 21:53:21 +02002702 TCGv t2 = tcg_const_tl(0);
2703 TCGv t3 = tcg_const_tl(1);
aurel320c0ed032009-03-29 15:36:47 +00002704 tcg_gen_ext32u_tl(t0, t0);
2705 tcg_gen_ext32u_tl(t1, t1);
Aurelien Jarno51127182012-10-09 21:53:21 +02002706 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
aurel32d45f89f2009-03-29 01:19:31 +00002707 tcg_gen_divu_tl(cpu_LO[0], t0, t1);
2708 tcg_gen_remu_tl(cpu_HI[0], t0, t1);
2709 tcg_gen_ext32s_tl(cpu_LO[0], cpu_LO[0]);
2710 tcg_gen_ext32s_tl(cpu_HI[0], cpu_HI[0]);
Aurelien Jarno51127182012-10-09 21:53:21 +02002711 tcg_temp_free(t3);
2712 tcg_temp_free(t2);
ths48d38ca2008-05-18 22:50:49 +00002713 }
bellard6af0bf92005-07-02 14:58:51 +00002714 opn = "divu";
2715 break;
2716 case OPC_MULT:
ths214c4652008-06-12 12:43:29 +00002717 {
aurel32d45f89f2009-03-29 01:19:31 +00002718 TCGv_i64 t2 = tcg_temp_new_i64();
2719 TCGv_i64 t3 = tcg_temp_new_i64();
Jia Liu41334982012-10-24 22:17:03 +08002720 acc = ((ctx->opcode) >> 11) & 0x03;
2721 if (acc != 0) {
2722 check_dsp(ctx);
2723 }
ths214c4652008-06-12 12:43:29 +00002724
aurel32d45f89f2009-03-29 01:19:31 +00002725 tcg_gen_ext_tl_i64(t2, t0);
2726 tcg_gen_ext_tl_i64(t3, t1);
2727 tcg_gen_mul_i64(t2, t2, t3);
2728 tcg_temp_free_i64(t3);
2729 tcg_gen_trunc_i64_tl(t0, t2);
2730 tcg_gen_shri_i64(t2, t2, 32);
2731 tcg_gen_trunc_i64_tl(t1, t2);
2732 tcg_temp_free_i64(t2);
Jia Liu41334982012-10-24 22:17:03 +08002733 tcg_gen_ext32s_tl(cpu_LO[acc], t0);
2734 tcg_gen_ext32s_tl(cpu_HI[acc], t1);
ths214c4652008-06-12 12:43:29 +00002735 }
bellard6af0bf92005-07-02 14:58:51 +00002736 opn = "mult";
2737 break;
2738 case OPC_MULTU:
ths214c4652008-06-12 12:43:29 +00002739 {
aurel32d45f89f2009-03-29 01:19:31 +00002740 TCGv_i64 t2 = tcg_temp_new_i64();
2741 TCGv_i64 t3 = tcg_temp_new_i64();
Jia Liu41334982012-10-24 22:17:03 +08002742 acc = ((ctx->opcode) >> 11) & 0x03;
2743 if (acc != 0) {
2744 check_dsp(ctx);
2745 }
ths214c4652008-06-12 12:43:29 +00002746
ths78723682008-06-24 20:12:33 +00002747 tcg_gen_ext32u_tl(t0, t0);
2748 tcg_gen_ext32u_tl(t1, t1);
aurel32d45f89f2009-03-29 01:19:31 +00002749 tcg_gen_extu_tl_i64(t2, t0);
2750 tcg_gen_extu_tl_i64(t3, t1);
2751 tcg_gen_mul_i64(t2, t2, t3);
2752 tcg_temp_free_i64(t3);
2753 tcg_gen_trunc_i64_tl(t0, t2);
2754 tcg_gen_shri_i64(t2, t2, 32);
2755 tcg_gen_trunc_i64_tl(t1, t2);
2756 tcg_temp_free_i64(t2);
Jia Liu41334982012-10-24 22:17:03 +08002757 tcg_gen_ext32s_tl(cpu_LO[acc], t0);
2758 tcg_gen_ext32s_tl(cpu_HI[acc], t1);
ths214c4652008-06-12 12:43:29 +00002759 }
bellard6af0bf92005-07-02 14:58:51 +00002760 opn = "multu";
2761 break;
thsd26bc212007-11-08 18:05:37 +00002762#if defined(TARGET_MIPS64)
ths7a387ff2006-12-06 20:17:30 +00002763 case OPC_DDIV:
ths48d38ca2008-05-18 22:50:49 +00002764 {
Aurelien Jarno51127182012-10-09 21:53:21 +02002765 TCGv t2 = tcg_temp_new();
2766 TCGv t3 = tcg_temp_new();
2767 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, -1LL << 63);
2768 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1LL);
2769 tcg_gen_and_tl(t2, t2, t3);
2770 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
2771 tcg_gen_or_tl(t2, t2, t3);
2772 tcg_gen_movi_tl(t3, 0);
2773 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
2774 tcg_gen_div_tl(cpu_LO[0], t0, t1);
2775 tcg_gen_rem_tl(cpu_HI[0], t0, t1);
2776 tcg_temp_free(t3);
2777 tcg_temp_free(t2);
ths48d38ca2008-05-18 22:50:49 +00002778 }
ths7a387ff2006-12-06 20:17:30 +00002779 opn = "ddiv";
2780 break;
2781 case OPC_DDIVU:
ths48d38ca2008-05-18 22:50:49 +00002782 {
Aurelien Jarno51127182012-10-09 21:53:21 +02002783 TCGv t2 = tcg_const_tl(0);
2784 TCGv t3 = tcg_const_tl(1);
2785 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
aurel32b10fa3c2008-11-11 11:50:25 +00002786 tcg_gen_divu_i64(cpu_LO[0], t0, t1);
2787 tcg_gen_remu_i64(cpu_HI[0], t0, t1);
Aurelien Jarno51127182012-10-09 21:53:21 +02002788 tcg_temp_free(t3);
2789 tcg_temp_free(t2);
ths48d38ca2008-05-18 22:50:49 +00002790 }
ths7a387ff2006-12-06 20:17:30 +00002791 opn = "ddivu";
2792 break;
2793 case OPC_DMULT:
Blue Swirl895c2d02012-09-02 14:52:59 +00002794 gen_helper_dmult(cpu_env, t0, t1);
ths7a387ff2006-12-06 20:17:30 +00002795 opn = "dmult";
2796 break;
2797 case OPC_DMULTU:
Blue Swirl895c2d02012-09-02 14:52:59 +00002798 gen_helper_dmultu(cpu_env, t0, t1);
ths7a387ff2006-12-06 20:17:30 +00002799 opn = "dmultu";
2800 break;
2801#endif
bellard6af0bf92005-07-02 14:58:51 +00002802 case OPC_MADD:
ths214c4652008-06-12 12:43:29 +00002803 {
aurel32d45f89f2009-03-29 01:19:31 +00002804 TCGv_i64 t2 = tcg_temp_new_i64();
2805 TCGv_i64 t3 = tcg_temp_new_i64();
Jia Liu41334982012-10-24 22:17:03 +08002806 acc = ((ctx->opcode) >> 11) & 0x03;
2807 if (acc != 0) {
2808 check_dsp(ctx);
2809 }
ths214c4652008-06-12 12:43:29 +00002810
aurel32d45f89f2009-03-29 01:19:31 +00002811 tcg_gen_ext_tl_i64(t2, t0);
2812 tcg_gen_ext_tl_i64(t3, t1);
2813 tcg_gen_mul_i64(t2, t2, t3);
Jia Liu41334982012-10-24 22:17:03 +08002814 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
aurel32d45f89f2009-03-29 01:19:31 +00002815 tcg_gen_add_i64(t2, t2, t3);
2816 tcg_temp_free_i64(t3);
2817 tcg_gen_trunc_i64_tl(t0, t2);
2818 tcg_gen_shri_i64(t2, t2, 32);
2819 tcg_gen_trunc_i64_tl(t1, t2);
2820 tcg_temp_free_i64(t2);
Jia Liu41334982012-10-24 22:17:03 +08002821 tcg_gen_ext32s_tl(cpu_LO[acc], t0);
2822 tcg_gen_ext32s_tl(cpu_HI[acc], t1);
ths214c4652008-06-12 12:43:29 +00002823 }
bellard6af0bf92005-07-02 14:58:51 +00002824 opn = "madd";
2825 break;
2826 case OPC_MADDU:
Jia Liu41334982012-10-24 22:17:03 +08002827 {
aurel32d45f89f2009-03-29 01:19:31 +00002828 TCGv_i64 t2 = tcg_temp_new_i64();
2829 TCGv_i64 t3 = tcg_temp_new_i64();
Jia Liu41334982012-10-24 22:17:03 +08002830 acc = ((ctx->opcode) >> 11) & 0x03;
2831 if (acc != 0) {
2832 check_dsp(ctx);
2833 }
ths214c4652008-06-12 12:43:29 +00002834
ths78723682008-06-24 20:12:33 +00002835 tcg_gen_ext32u_tl(t0, t0);
2836 tcg_gen_ext32u_tl(t1, t1);
aurel32d45f89f2009-03-29 01:19:31 +00002837 tcg_gen_extu_tl_i64(t2, t0);
2838 tcg_gen_extu_tl_i64(t3, t1);
2839 tcg_gen_mul_i64(t2, t2, t3);
Jia Liu41334982012-10-24 22:17:03 +08002840 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
aurel32d45f89f2009-03-29 01:19:31 +00002841 tcg_gen_add_i64(t2, t2, t3);
2842 tcg_temp_free_i64(t3);
2843 tcg_gen_trunc_i64_tl(t0, t2);
2844 tcg_gen_shri_i64(t2, t2, 32);
2845 tcg_gen_trunc_i64_tl(t1, t2);
2846 tcg_temp_free_i64(t2);
Jia Liu41334982012-10-24 22:17:03 +08002847 tcg_gen_ext32s_tl(cpu_LO[acc], t0);
2848 tcg_gen_ext32s_tl(cpu_HI[acc], t1);
ths214c4652008-06-12 12:43:29 +00002849 }
bellard6af0bf92005-07-02 14:58:51 +00002850 opn = "maddu";
2851 break;
2852 case OPC_MSUB:
ths214c4652008-06-12 12:43:29 +00002853 {
aurel32d45f89f2009-03-29 01:19:31 +00002854 TCGv_i64 t2 = tcg_temp_new_i64();
2855 TCGv_i64 t3 = tcg_temp_new_i64();
Jia Liu41334982012-10-24 22:17:03 +08002856 acc = ((ctx->opcode) >> 11) & 0x03;
2857 if (acc != 0) {
2858 check_dsp(ctx);
2859 }
ths214c4652008-06-12 12:43:29 +00002860
aurel32d45f89f2009-03-29 01:19:31 +00002861 tcg_gen_ext_tl_i64(t2, t0);
2862 tcg_gen_ext_tl_i64(t3, t1);
2863 tcg_gen_mul_i64(t2, t2, t3);
Jia Liu41334982012-10-24 22:17:03 +08002864 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
Nathan Froyd98070ce2009-07-01 10:52:22 -07002865 tcg_gen_sub_i64(t2, t3, t2);
aurel32d45f89f2009-03-29 01:19:31 +00002866 tcg_temp_free_i64(t3);
2867 tcg_gen_trunc_i64_tl(t0, t2);
2868 tcg_gen_shri_i64(t2, t2, 32);
2869 tcg_gen_trunc_i64_tl(t1, t2);
2870 tcg_temp_free_i64(t2);
Jia Liu41334982012-10-24 22:17:03 +08002871 tcg_gen_ext32s_tl(cpu_LO[acc], t0);
2872 tcg_gen_ext32s_tl(cpu_HI[acc], t1);
ths214c4652008-06-12 12:43:29 +00002873 }
bellard6af0bf92005-07-02 14:58:51 +00002874 opn = "msub";
2875 break;
2876 case OPC_MSUBU:
ths214c4652008-06-12 12:43:29 +00002877 {
aurel32d45f89f2009-03-29 01:19:31 +00002878 TCGv_i64 t2 = tcg_temp_new_i64();
2879 TCGv_i64 t3 = tcg_temp_new_i64();
Jia Liu41334982012-10-24 22:17:03 +08002880 acc = ((ctx->opcode) >> 11) & 0x03;
2881 if (acc != 0) {
2882 check_dsp(ctx);
2883 }
ths214c4652008-06-12 12:43:29 +00002884
ths78723682008-06-24 20:12:33 +00002885 tcg_gen_ext32u_tl(t0, t0);
2886 tcg_gen_ext32u_tl(t1, t1);
aurel32d45f89f2009-03-29 01:19:31 +00002887 tcg_gen_extu_tl_i64(t2, t0);
2888 tcg_gen_extu_tl_i64(t3, t1);
2889 tcg_gen_mul_i64(t2, t2, t3);
Jia Liu41334982012-10-24 22:17:03 +08002890 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
Nathan Froyd98070ce2009-07-01 10:52:22 -07002891 tcg_gen_sub_i64(t2, t3, t2);
aurel32d45f89f2009-03-29 01:19:31 +00002892 tcg_temp_free_i64(t3);
2893 tcg_gen_trunc_i64_tl(t0, t2);
2894 tcg_gen_shri_i64(t2, t2, 32);
2895 tcg_gen_trunc_i64_tl(t1, t2);
2896 tcg_temp_free_i64(t2);
Jia Liu41334982012-10-24 22:17:03 +08002897 tcg_gen_ext32s_tl(cpu_LO[acc], t0);
2898 tcg_gen_ext32s_tl(cpu_HI[acc], t1);
ths214c4652008-06-12 12:43:29 +00002899 }
bellard6af0bf92005-07-02 14:58:51 +00002900 opn = "msubu";
2901 break;
2902 default:
ths923617a2007-05-11 00:16:06 +00002903 MIPS_INVAL(opn);
bellard6af0bf92005-07-02 14:58:51 +00002904 generate_exception(ctx, EXCP_RI);
ths78723682008-06-24 20:12:33 +00002905 goto out;
bellard6af0bf92005-07-02 14:58:51 +00002906 }
Blue Swirl2abf3142010-10-13 18:38:08 +00002907 (void)opn; /* avoid a compiler warning */
bellard6af0bf92005-07-02 14:58:51 +00002908 MIPS_DEBUG("%s %s %s", opn, regnames[rs], regnames[rt]);
ths78723682008-06-24 20:12:33 +00002909 out:
2910 tcg_temp_free(t0);
2911 tcg_temp_free(t1);
bellard6af0bf92005-07-02 14:58:51 +00002912}
2913
thse9c71dd2007-12-25 20:46:56 +00002914static void gen_mul_vr54xx (DisasContext *ctx, uint32_t opc,
2915 int rd, int rs, int rt)
2916{
2917 const char *opn = "mul vr54xx";
aurel32f157bfe2009-03-29 01:18:24 +00002918 TCGv t0 = tcg_temp_new();
2919 TCGv t1 = tcg_temp_new();
thse9c71dd2007-12-25 20:46:56 +00002920
ths6c5c1e22008-06-24 15:12:27 +00002921 gen_load_gpr(t0, rs);
2922 gen_load_gpr(t1, rt);
thse9c71dd2007-12-25 20:46:56 +00002923
2924 switch (opc) {
2925 case OPC_VR54XX_MULS:
Blue Swirl895c2d02012-09-02 14:52:59 +00002926 gen_helper_muls(t0, cpu_env, t0, t1);
thse9c71dd2007-12-25 20:46:56 +00002927 opn = "muls";
aurel3269585492009-01-14 19:40:36 +00002928 break;
thse9c71dd2007-12-25 20:46:56 +00002929 case OPC_VR54XX_MULSU:
Blue Swirl895c2d02012-09-02 14:52:59 +00002930 gen_helper_mulsu(t0, cpu_env, t0, t1);
thse9c71dd2007-12-25 20:46:56 +00002931 opn = "mulsu";
aurel3269585492009-01-14 19:40:36 +00002932 break;
thse9c71dd2007-12-25 20:46:56 +00002933 case OPC_VR54XX_MACC:
Blue Swirl895c2d02012-09-02 14:52:59 +00002934 gen_helper_macc(t0, cpu_env, t0, t1);
thse9c71dd2007-12-25 20:46:56 +00002935 opn = "macc";
aurel3269585492009-01-14 19:40:36 +00002936 break;
thse9c71dd2007-12-25 20:46:56 +00002937 case OPC_VR54XX_MACCU:
Blue Swirl895c2d02012-09-02 14:52:59 +00002938 gen_helper_maccu(t0, cpu_env, t0, t1);
thse9c71dd2007-12-25 20:46:56 +00002939 opn = "maccu";
aurel3269585492009-01-14 19:40:36 +00002940 break;
thse9c71dd2007-12-25 20:46:56 +00002941 case OPC_VR54XX_MSAC:
Blue Swirl895c2d02012-09-02 14:52:59 +00002942 gen_helper_msac(t0, cpu_env, t0, t1);
thse9c71dd2007-12-25 20:46:56 +00002943 opn = "msac";
aurel3269585492009-01-14 19:40:36 +00002944 break;
thse9c71dd2007-12-25 20:46:56 +00002945 case OPC_VR54XX_MSACU:
Blue Swirl895c2d02012-09-02 14:52:59 +00002946 gen_helper_msacu(t0, cpu_env, t0, t1);
thse9c71dd2007-12-25 20:46:56 +00002947 opn = "msacu";
aurel3269585492009-01-14 19:40:36 +00002948 break;
thse9c71dd2007-12-25 20:46:56 +00002949 case OPC_VR54XX_MULHI:
Blue Swirl895c2d02012-09-02 14:52:59 +00002950 gen_helper_mulhi(t0, cpu_env, t0, t1);
thse9c71dd2007-12-25 20:46:56 +00002951 opn = "mulhi";
aurel3269585492009-01-14 19:40:36 +00002952 break;
thse9c71dd2007-12-25 20:46:56 +00002953 case OPC_VR54XX_MULHIU:
Blue Swirl895c2d02012-09-02 14:52:59 +00002954 gen_helper_mulhiu(t0, cpu_env, t0, t1);
thse9c71dd2007-12-25 20:46:56 +00002955 opn = "mulhiu";
aurel3269585492009-01-14 19:40:36 +00002956 break;
thse9c71dd2007-12-25 20:46:56 +00002957 case OPC_VR54XX_MULSHI:
Blue Swirl895c2d02012-09-02 14:52:59 +00002958 gen_helper_mulshi(t0, cpu_env, t0, t1);
thse9c71dd2007-12-25 20:46:56 +00002959 opn = "mulshi";
aurel3269585492009-01-14 19:40:36 +00002960 break;
thse9c71dd2007-12-25 20:46:56 +00002961 case OPC_VR54XX_MULSHIU:
Blue Swirl895c2d02012-09-02 14:52:59 +00002962 gen_helper_mulshiu(t0, cpu_env, t0, t1);
thse9c71dd2007-12-25 20:46:56 +00002963 opn = "mulshiu";
aurel3269585492009-01-14 19:40:36 +00002964 break;
thse9c71dd2007-12-25 20:46:56 +00002965 case OPC_VR54XX_MACCHI:
Blue Swirl895c2d02012-09-02 14:52:59 +00002966 gen_helper_macchi(t0, cpu_env, t0, t1);
thse9c71dd2007-12-25 20:46:56 +00002967 opn = "macchi";
aurel3269585492009-01-14 19:40:36 +00002968 break;
thse9c71dd2007-12-25 20:46:56 +00002969 case OPC_VR54XX_MACCHIU:
Blue Swirl895c2d02012-09-02 14:52:59 +00002970 gen_helper_macchiu(t0, cpu_env, t0, t1);
thse9c71dd2007-12-25 20:46:56 +00002971 opn = "macchiu";
aurel3269585492009-01-14 19:40:36 +00002972 break;
thse9c71dd2007-12-25 20:46:56 +00002973 case OPC_VR54XX_MSACHI:
Blue Swirl895c2d02012-09-02 14:52:59 +00002974 gen_helper_msachi(t0, cpu_env, t0, t1);
thse9c71dd2007-12-25 20:46:56 +00002975 opn = "msachi";
aurel3269585492009-01-14 19:40:36 +00002976 break;
thse9c71dd2007-12-25 20:46:56 +00002977 case OPC_VR54XX_MSACHIU:
Blue Swirl895c2d02012-09-02 14:52:59 +00002978 gen_helper_msachiu(t0, cpu_env, t0, t1);
thse9c71dd2007-12-25 20:46:56 +00002979 opn = "msachiu";
aurel3269585492009-01-14 19:40:36 +00002980 break;
thse9c71dd2007-12-25 20:46:56 +00002981 default:
2982 MIPS_INVAL("mul vr54xx");
2983 generate_exception(ctx, EXCP_RI);
ths6c5c1e22008-06-24 15:12:27 +00002984 goto out;
thse9c71dd2007-12-25 20:46:56 +00002985 }
ths6c5c1e22008-06-24 15:12:27 +00002986 gen_store_gpr(t0, rd);
Blue Swirl2abf3142010-10-13 18:38:08 +00002987 (void)opn; /* avoid a compiler warning */
thse9c71dd2007-12-25 20:46:56 +00002988 MIPS_DEBUG("%s %s, %s, %s", opn, regnames[rd], regnames[rs], regnames[rt]);
ths6c5c1e22008-06-24 15:12:27 +00002989
2990 out:
2991 tcg_temp_free(t0);
2992 tcg_temp_free(t1);
thse9c71dd2007-12-25 20:46:56 +00002993}
2994
ths7a387ff2006-12-06 20:17:30 +00002995static void gen_cl (DisasContext *ctx, uint32_t opc,
bellard6af0bf92005-07-02 14:58:51 +00002996 int rd, int rs)
2997{
ths923617a2007-05-11 00:16:06 +00002998 const char *opn = "CLx";
aurel3220e1fb522009-03-29 01:18:16 +00002999 TCGv t0;
ths6c5c1e22008-06-24 15:12:27 +00003000
bellard6af0bf92005-07-02 14:58:51 +00003001 if (rd == 0) {
thsead93602007-09-06 00:18:15 +00003002 /* Treat as NOP. */
bellard6af0bf92005-07-02 14:58:51 +00003003 MIPS_DEBUG("NOP");
aurel3220e1fb522009-03-29 01:18:16 +00003004 return;
bellard6af0bf92005-07-02 14:58:51 +00003005 }
aurel3220e1fb522009-03-29 01:18:16 +00003006 t0 = tcg_temp_new();
ths6c5c1e22008-06-24 15:12:27 +00003007 gen_load_gpr(t0, rs);
bellard6af0bf92005-07-02 14:58:51 +00003008 switch (opc) {
3009 case OPC_CLO:
aurel3220e1fb522009-03-29 01:18:16 +00003010 gen_helper_clo(cpu_gpr[rd], t0);
bellard6af0bf92005-07-02 14:58:51 +00003011 opn = "clo";
3012 break;
3013 case OPC_CLZ:
aurel3220e1fb522009-03-29 01:18:16 +00003014 gen_helper_clz(cpu_gpr[rd], t0);
bellard6af0bf92005-07-02 14:58:51 +00003015 opn = "clz";
3016 break;
thsd26bc212007-11-08 18:05:37 +00003017#if defined(TARGET_MIPS64)
ths7a387ff2006-12-06 20:17:30 +00003018 case OPC_DCLO:
aurel3220e1fb522009-03-29 01:18:16 +00003019 gen_helper_dclo(cpu_gpr[rd], t0);
ths7a387ff2006-12-06 20:17:30 +00003020 opn = "dclo";
3021 break;
3022 case OPC_DCLZ:
aurel3220e1fb522009-03-29 01:18:16 +00003023 gen_helper_dclz(cpu_gpr[rd], t0);
ths7a387ff2006-12-06 20:17:30 +00003024 opn = "dclz";
3025 break;
3026#endif
bellard6af0bf92005-07-02 14:58:51 +00003027 }
Blue Swirl2abf3142010-10-13 18:38:08 +00003028 (void)opn; /* avoid a compiler warning */
bellard6af0bf92005-07-02 14:58:51 +00003029 MIPS_DEBUG("%s %s, %s", opn, regnames[rd], regnames[rs]);
ths6c5c1e22008-06-24 15:12:27 +00003030 tcg_temp_free(t0);
bellard6af0bf92005-07-02 14:58:51 +00003031}
3032
Aurelien Jarno161f85e2010-06-18 19:32:43 +02003033/* Godson integer instructions */
Richard Hendersonbd277fa2012-09-18 21:59:44 -07003034static void gen_loongson_integer(DisasContext *ctx, uint32_t opc,
3035 int rd, int rs, int rt)
Aurelien Jarno161f85e2010-06-18 19:32:43 +02003036{
3037 const char *opn = "loongson";
3038 TCGv t0, t1;
3039
3040 if (rd == 0) {
3041 /* Treat as NOP. */
3042 MIPS_DEBUG("NOP");
3043 return;
3044 }
3045
3046 switch (opc) {
3047 case OPC_MULT_G_2E:
3048 case OPC_MULT_G_2F:
3049 case OPC_MULTU_G_2E:
3050 case OPC_MULTU_G_2F:
3051#if defined(TARGET_MIPS64)
3052 case OPC_DMULT_G_2E:
3053 case OPC_DMULT_G_2F:
3054 case OPC_DMULTU_G_2E:
3055 case OPC_DMULTU_G_2F:
3056#endif
3057 t0 = tcg_temp_new();
3058 t1 = tcg_temp_new();
3059 break;
3060 default:
3061 t0 = tcg_temp_local_new();
3062 t1 = tcg_temp_local_new();
3063 break;
3064 }
3065
3066 gen_load_gpr(t0, rs);
3067 gen_load_gpr(t1, rt);
3068
3069 switch (opc) {
3070 case OPC_MULT_G_2E:
3071 case OPC_MULT_G_2F:
3072 tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
3073 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3074 opn = "mult.g";
3075 break;
3076 case OPC_MULTU_G_2E:
3077 case OPC_MULTU_G_2F:
3078 tcg_gen_ext32u_tl(t0, t0);
3079 tcg_gen_ext32u_tl(t1, t1);
3080 tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
3081 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3082 opn = "multu.g";
3083 break;
3084 case OPC_DIV_G_2E:
3085 case OPC_DIV_G_2F:
3086 {
3087 int l1 = gen_new_label();
3088 int l2 = gen_new_label();
3089 int l3 = gen_new_label();
3090 tcg_gen_ext32s_tl(t0, t0);
3091 tcg_gen_ext32s_tl(t1, t1);
3092 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
3093 tcg_gen_movi_tl(cpu_gpr[rd], 0);
3094 tcg_gen_br(l3);
3095 gen_set_label(l1);
3096 tcg_gen_brcondi_tl(TCG_COND_NE, t0, INT_MIN, l2);
3097 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1, l2);
3098 tcg_gen_mov_tl(cpu_gpr[rd], t0);
3099 tcg_gen_br(l3);
3100 gen_set_label(l2);
3101 tcg_gen_div_tl(cpu_gpr[rd], t0, t1);
3102 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3103 gen_set_label(l3);
3104 }
3105 opn = "div.g";
3106 break;
3107 case OPC_DIVU_G_2E:
3108 case OPC_DIVU_G_2F:
3109 {
3110 int l1 = gen_new_label();
3111 int l2 = gen_new_label();
3112 tcg_gen_ext32u_tl(t0, t0);
3113 tcg_gen_ext32u_tl(t1, t1);
3114 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
3115 tcg_gen_movi_tl(cpu_gpr[rd], 0);
3116 tcg_gen_br(l2);
3117 gen_set_label(l1);
3118 tcg_gen_divu_tl(cpu_gpr[rd], t0, t1);
3119 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3120 gen_set_label(l2);
3121 }
3122 opn = "divu.g";
3123 break;
3124 case OPC_MOD_G_2E:
3125 case OPC_MOD_G_2F:
3126 {
3127 int l1 = gen_new_label();
3128 int l2 = gen_new_label();
3129 int l3 = gen_new_label();
3130 tcg_gen_ext32u_tl(t0, t0);
3131 tcg_gen_ext32u_tl(t1, t1);
3132 tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
3133 tcg_gen_brcondi_tl(TCG_COND_NE, t0, INT_MIN, l2);
3134 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1, l2);
3135 gen_set_label(l1);
3136 tcg_gen_movi_tl(cpu_gpr[rd], 0);
3137 tcg_gen_br(l3);
3138 gen_set_label(l2);
3139 tcg_gen_rem_tl(cpu_gpr[rd], t0, t1);
3140 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3141 gen_set_label(l3);
3142 }
3143 opn = "mod.g";
3144 break;
3145 case OPC_MODU_G_2E:
3146 case OPC_MODU_G_2F:
3147 {
3148 int l1 = gen_new_label();
3149 int l2 = gen_new_label();
3150 tcg_gen_ext32u_tl(t0, t0);
3151 tcg_gen_ext32u_tl(t1, t1);
3152 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
3153 tcg_gen_movi_tl(cpu_gpr[rd], 0);
3154 tcg_gen_br(l2);
3155 gen_set_label(l1);
3156 tcg_gen_remu_tl(cpu_gpr[rd], t0, t1);
3157 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3158 gen_set_label(l2);
3159 }
3160 opn = "modu.g";
3161 break;
3162#if defined(TARGET_MIPS64)
3163 case OPC_DMULT_G_2E:
3164 case OPC_DMULT_G_2F:
3165 tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
3166 opn = "dmult.g";
3167 break;
3168 case OPC_DMULTU_G_2E:
3169 case OPC_DMULTU_G_2F:
3170 tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
3171 opn = "dmultu.g";
3172 break;
3173 case OPC_DDIV_G_2E:
3174 case OPC_DDIV_G_2F:
3175 {
3176 int l1 = gen_new_label();
3177 int l2 = gen_new_label();
3178 int l3 = gen_new_label();
3179 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
3180 tcg_gen_movi_tl(cpu_gpr[rd], 0);
3181 tcg_gen_br(l3);
3182 gen_set_label(l1);
3183 tcg_gen_brcondi_tl(TCG_COND_NE, t0, -1LL << 63, l2);
3184 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1LL, l2);
3185 tcg_gen_mov_tl(cpu_gpr[rd], t0);
3186 tcg_gen_br(l3);
3187 gen_set_label(l2);
3188 tcg_gen_div_tl(cpu_gpr[rd], t0, t1);
3189 gen_set_label(l3);
3190 }
3191 opn = "ddiv.g";
3192 break;
3193 case OPC_DDIVU_G_2E:
3194 case OPC_DDIVU_G_2F:
3195 {
3196 int l1 = gen_new_label();
3197 int l2 = gen_new_label();
3198 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
3199 tcg_gen_movi_tl(cpu_gpr[rd], 0);
3200 tcg_gen_br(l2);
3201 gen_set_label(l1);
3202 tcg_gen_divu_tl(cpu_gpr[rd], t0, t1);
3203 gen_set_label(l2);
3204 }
3205 opn = "ddivu.g";
3206 break;
3207 case OPC_DMOD_G_2E:
3208 case OPC_DMOD_G_2F:
3209 {
3210 int l1 = gen_new_label();
3211 int l2 = gen_new_label();
3212 int l3 = gen_new_label();
3213 tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
3214 tcg_gen_brcondi_tl(TCG_COND_NE, t0, -1LL << 63, l2);
3215 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1LL, l2);
3216 gen_set_label(l1);
3217 tcg_gen_movi_tl(cpu_gpr[rd], 0);
3218 tcg_gen_br(l3);
3219 gen_set_label(l2);
3220 tcg_gen_rem_tl(cpu_gpr[rd], t0, t1);
3221 gen_set_label(l3);
3222 }
3223 opn = "dmod.g";
3224 break;
3225 case OPC_DMODU_G_2E:
3226 case OPC_DMODU_G_2F:
3227 {
3228 int l1 = gen_new_label();
3229 int l2 = gen_new_label();
3230 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
3231 tcg_gen_movi_tl(cpu_gpr[rd], 0);
3232 tcg_gen_br(l2);
3233 gen_set_label(l1);
3234 tcg_gen_remu_tl(cpu_gpr[rd], t0, t1);
3235 gen_set_label(l2);
3236 }
3237 opn = "dmodu.g";
3238 break;
3239#endif
3240 }
3241
Blue Swirl2abf3142010-10-13 18:38:08 +00003242 (void)opn; /* avoid a compiler warning */
Aurelien Jarno161f85e2010-06-18 19:32:43 +02003243 MIPS_DEBUG("%s %s, %s", opn, regnames[rd], regnames[rs]);
3244 tcg_temp_free(t0);
3245 tcg_temp_free(t1);
3246}
3247
Richard Hendersonbd277fa2012-09-18 21:59:44 -07003248/* Loongson multimedia instructions */
3249static void gen_loongson_multimedia(DisasContext *ctx, int rd, int rs, int rt)
3250{
3251 const char *opn = "loongson_cp2";
3252 uint32_t opc, shift_max;
3253 TCGv_i64 t0, t1;
3254
3255 opc = MASK_LMI(ctx->opcode);
3256 switch (opc) {
3257 case OPC_ADD_CP2:
3258 case OPC_SUB_CP2:
3259 case OPC_DADD_CP2:
3260 case OPC_DSUB_CP2:
3261 t0 = tcg_temp_local_new_i64();
3262 t1 = tcg_temp_local_new_i64();
3263 break;
3264 default:
3265 t0 = tcg_temp_new_i64();
3266 t1 = tcg_temp_new_i64();
3267 break;
3268 }
3269
3270 gen_load_fpr64(ctx, t0, rs);
3271 gen_load_fpr64(ctx, t1, rt);
3272
3273#define LMI_HELPER(UP, LO) \
3274 case OPC_##UP: gen_helper_##LO(t0, t0, t1); opn = #LO; break
3275#define LMI_HELPER_1(UP, LO) \
3276 case OPC_##UP: gen_helper_##LO(t0, t0); opn = #LO; break
3277#define LMI_DIRECT(UP, LO, OP) \
3278 case OPC_##UP: tcg_gen_##OP##_i64(t0, t0, t1); opn = #LO; break
3279
3280 switch (opc) {
3281 LMI_HELPER(PADDSH, paddsh);
3282 LMI_HELPER(PADDUSH, paddush);
3283 LMI_HELPER(PADDH, paddh);
3284 LMI_HELPER(PADDW, paddw);
3285 LMI_HELPER(PADDSB, paddsb);
3286 LMI_HELPER(PADDUSB, paddusb);
3287 LMI_HELPER(PADDB, paddb);
3288
3289 LMI_HELPER(PSUBSH, psubsh);
3290 LMI_HELPER(PSUBUSH, psubush);
3291 LMI_HELPER(PSUBH, psubh);
3292 LMI_HELPER(PSUBW, psubw);
3293 LMI_HELPER(PSUBSB, psubsb);
3294 LMI_HELPER(PSUBUSB, psubusb);
3295 LMI_HELPER(PSUBB, psubb);
3296
3297 LMI_HELPER(PSHUFH, pshufh);
3298 LMI_HELPER(PACKSSWH, packsswh);
3299 LMI_HELPER(PACKSSHB, packsshb);
3300 LMI_HELPER(PACKUSHB, packushb);
3301
3302 LMI_HELPER(PUNPCKLHW, punpcklhw);
3303 LMI_HELPER(PUNPCKHHW, punpckhhw);
3304 LMI_HELPER(PUNPCKLBH, punpcklbh);
3305 LMI_HELPER(PUNPCKHBH, punpckhbh);
3306 LMI_HELPER(PUNPCKLWD, punpcklwd);
3307 LMI_HELPER(PUNPCKHWD, punpckhwd);
3308
3309 LMI_HELPER(PAVGH, pavgh);
3310 LMI_HELPER(PAVGB, pavgb);
3311 LMI_HELPER(PMAXSH, pmaxsh);
3312 LMI_HELPER(PMINSH, pminsh);
3313 LMI_HELPER(PMAXUB, pmaxub);
3314 LMI_HELPER(PMINUB, pminub);
3315
3316 LMI_HELPER(PCMPEQW, pcmpeqw);
3317 LMI_HELPER(PCMPGTW, pcmpgtw);
3318 LMI_HELPER(PCMPEQH, pcmpeqh);
3319 LMI_HELPER(PCMPGTH, pcmpgth);
3320 LMI_HELPER(PCMPEQB, pcmpeqb);
3321 LMI_HELPER(PCMPGTB, pcmpgtb);
3322
3323 LMI_HELPER(PSLLW, psllw);
3324 LMI_HELPER(PSLLH, psllh);
3325 LMI_HELPER(PSRLW, psrlw);
3326 LMI_HELPER(PSRLH, psrlh);
3327 LMI_HELPER(PSRAW, psraw);
3328 LMI_HELPER(PSRAH, psrah);
3329
3330 LMI_HELPER(PMULLH, pmullh);
3331 LMI_HELPER(PMULHH, pmulhh);
3332 LMI_HELPER(PMULHUH, pmulhuh);
3333 LMI_HELPER(PMADDHW, pmaddhw);
3334
3335 LMI_HELPER(PASUBUB, pasubub);
3336 LMI_HELPER_1(BIADD, biadd);
3337 LMI_HELPER_1(PMOVMSKB, pmovmskb);
3338
3339 LMI_DIRECT(PADDD, paddd, add);
3340 LMI_DIRECT(PSUBD, psubd, sub);
3341 LMI_DIRECT(XOR_CP2, xor, xor);
3342 LMI_DIRECT(NOR_CP2, nor, nor);
3343 LMI_DIRECT(AND_CP2, and, and);
3344 LMI_DIRECT(PANDN, pandn, andc);
3345 LMI_DIRECT(OR, or, or);
3346
3347 case OPC_PINSRH_0:
3348 tcg_gen_deposit_i64(t0, t0, t1, 0, 16);
3349 opn = "pinsrh_0";
3350 break;
3351 case OPC_PINSRH_1:
3352 tcg_gen_deposit_i64(t0, t0, t1, 16, 16);
3353 opn = "pinsrh_1";
3354 break;
3355 case OPC_PINSRH_2:
3356 tcg_gen_deposit_i64(t0, t0, t1, 32, 16);
3357 opn = "pinsrh_2";
3358 break;
3359 case OPC_PINSRH_3:
3360 tcg_gen_deposit_i64(t0, t0, t1, 48, 16);
3361 opn = "pinsrh_3";
3362 break;
3363
3364 case OPC_PEXTRH:
3365 tcg_gen_andi_i64(t1, t1, 3);
3366 tcg_gen_shli_i64(t1, t1, 4);
3367 tcg_gen_shr_i64(t0, t0, t1);
3368 tcg_gen_ext16u_i64(t0, t0);
3369 opn = "pextrh";
3370 break;
3371
3372 case OPC_ADDU_CP2:
3373 tcg_gen_add_i64(t0, t0, t1);
3374 tcg_gen_ext32s_i64(t0, t0);
3375 opn = "addu";
3376 break;
3377 case OPC_SUBU_CP2:
3378 tcg_gen_sub_i64(t0, t0, t1);
3379 tcg_gen_ext32s_i64(t0, t0);
3380 opn = "addu";
3381 break;
3382
3383 case OPC_SLL_CP2:
3384 opn = "sll";
3385 shift_max = 32;
3386 goto do_shift;
3387 case OPC_SRL_CP2:
3388 opn = "srl";
3389 shift_max = 32;
3390 goto do_shift;
3391 case OPC_SRA_CP2:
3392 opn = "sra";
3393 shift_max = 32;
3394 goto do_shift;
3395 case OPC_DSLL_CP2:
3396 opn = "dsll";
3397 shift_max = 64;
3398 goto do_shift;
3399 case OPC_DSRL_CP2:
3400 opn = "dsrl";
3401 shift_max = 64;
3402 goto do_shift;
3403 case OPC_DSRA_CP2:
3404 opn = "dsra";
3405 shift_max = 64;
3406 goto do_shift;
3407 do_shift:
3408 /* Make sure shift count isn't TCG undefined behaviour. */
3409 tcg_gen_andi_i64(t1, t1, shift_max - 1);
3410
3411 switch (opc) {
3412 case OPC_SLL_CP2:
3413 case OPC_DSLL_CP2:
3414 tcg_gen_shl_i64(t0, t0, t1);
3415 break;
3416 case OPC_SRA_CP2:
3417 case OPC_DSRA_CP2:
3418 /* Since SRA is UndefinedResult without sign-extended inputs,
3419 we can treat SRA and DSRA the same. */
3420 tcg_gen_sar_i64(t0, t0, t1);
3421 break;
3422 case OPC_SRL_CP2:
3423 /* We want to shift in zeros for SRL; zero-extend first. */
3424 tcg_gen_ext32u_i64(t0, t0);
3425 /* FALLTHRU */
3426 case OPC_DSRL_CP2:
3427 tcg_gen_shr_i64(t0, t0, t1);
3428 break;
3429 }
3430
3431 if (shift_max == 32) {
3432 tcg_gen_ext32s_i64(t0, t0);
3433 }
3434
3435 /* Shifts larger than MAX produce zero. */
3436 tcg_gen_setcondi_i64(TCG_COND_LTU, t1, t1, shift_max);
3437 tcg_gen_neg_i64(t1, t1);
3438 tcg_gen_and_i64(t0, t0, t1);
3439 break;
3440
3441 case OPC_ADD_CP2:
3442 case OPC_DADD_CP2:
3443 {
3444 TCGv_i64 t2 = tcg_temp_new_i64();
3445 int lab = gen_new_label();
3446
3447 tcg_gen_mov_i64(t2, t0);
3448 tcg_gen_add_i64(t0, t1, t2);
3449 if (opc == OPC_ADD_CP2) {
3450 tcg_gen_ext32s_i64(t0, t0);
3451 }
3452 tcg_gen_xor_i64(t1, t1, t2);
3453 tcg_gen_xor_i64(t2, t2, t0);
3454 tcg_gen_andc_i64(t1, t2, t1);
3455 tcg_temp_free_i64(t2);
3456 tcg_gen_brcondi_i64(TCG_COND_GE, t1, 0, lab);
3457 generate_exception(ctx, EXCP_OVERFLOW);
3458 gen_set_label(lab);
3459
3460 opn = (opc == OPC_ADD_CP2 ? "add" : "dadd");
3461 break;
3462 }
3463
3464 case OPC_SUB_CP2:
3465 case OPC_DSUB_CP2:
3466 {
3467 TCGv_i64 t2 = tcg_temp_new_i64();
3468 int lab = gen_new_label();
3469
3470 tcg_gen_mov_i64(t2, t0);
3471 tcg_gen_sub_i64(t0, t1, t2);
3472 if (opc == OPC_SUB_CP2) {
3473 tcg_gen_ext32s_i64(t0, t0);
3474 }
3475 tcg_gen_xor_i64(t1, t1, t2);
3476 tcg_gen_xor_i64(t2, t2, t0);
3477 tcg_gen_and_i64(t1, t1, t2);
3478 tcg_temp_free_i64(t2);
3479 tcg_gen_brcondi_i64(TCG_COND_GE, t1, 0, lab);
3480 generate_exception(ctx, EXCP_OVERFLOW);
3481 gen_set_label(lab);
3482
3483 opn = (opc == OPC_SUB_CP2 ? "sub" : "dsub");
3484 break;
3485 }
3486
3487 case OPC_PMULUW:
3488 tcg_gen_ext32u_i64(t0, t0);
3489 tcg_gen_ext32u_i64(t1, t1);
3490 tcg_gen_mul_i64(t0, t0, t1);
3491 opn = "pmuluw";
3492 break;
3493
3494 case OPC_SEQU_CP2:
3495 case OPC_SEQ_CP2:
3496 case OPC_SLTU_CP2:
3497 case OPC_SLT_CP2:
3498 case OPC_SLEU_CP2:
3499 case OPC_SLE_CP2:
3500 /* ??? Document is unclear: Set FCC[CC]. Does that mean the
3501 FD field is the CC field? */
3502 default:
3503 MIPS_INVAL(opn);
3504 generate_exception(ctx, EXCP_RI);
3505 return;
3506 }
3507
3508#undef LMI_HELPER
3509#undef LMI_DIRECT
3510
3511 gen_store_fpr64(ctx, t0, rd);
3512
3513 (void)opn; /* avoid a compiler warning */
3514 MIPS_DEBUG("%s %s, %s, %s", opn,
3515 fregnames[rd], fregnames[rs], fregnames[rt]);
3516 tcg_temp_free_i64(t0);
3517 tcg_temp_free_i64(t1);
3518}
3519
bellard6af0bf92005-07-02 14:58:51 +00003520/* Traps */
ths7a387ff2006-12-06 20:17:30 +00003521static void gen_trap (DisasContext *ctx, uint32_t opc,
bellard6af0bf92005-07-02 14:58:51 +00003522 int rs, int rt, int16_t imm)
3523{
3524 int cond;
aurel32cdc0faa2009-03-29 01:19:02 +00003525 TCGv t0 = tcg_temp_new();
aurel321ba74fb2009-03-29 01:18:52 +00003526 TCGv t1 = tcg_temp_new();
bellard6af0bf92005-07-02 14:58:51 +00003527
3528 cond = 0;
3529 /* Load needed operands */
3530 switch (opc) {
3531 case OPC_TEQ:
3532 case OPC_TGE:
3533 case OPC_TGEU:
3534 case OPC_TLT:
3535 case OPC_TLTU:
3536 case OPC_TNE:
3537 /* Compare two registers */
3538 if (rs != rt) {
thsbe24bb42008-06-23 12:57:09 +00003539 gen_load_gpr(t0, rs);
3540 gen_load_gpr(t1, rt);
bellard6af0bf92005-07-02 14:58:51 +00003541 cond = 1;
3542 }
ths179e32b2006-12-16 16:45:18 +00003543 break;
bellard6af0bf92005-07-02 14:58:51 +00003544 case OPC_TEQI:
3545 case OPC_TGEI:
3546 case OPC_TGEIU:
3547 case OPC_TLTI:
3548 case OPC_TLTIU:
3549 case OPC_TNEI:
3550 /* Compare register to immediate */
3551 if (rs != 0 || imm != 0) {
thsbe24bb42008-06-23 12:57:09 +00003552 gen_load_gpr(t0, rs);
3553 tcg_gen_movi_tl(t1, (int32_t)imm);
bellard6af0bf92005-07-02 14:58:51 +00003554 cond = 1;
3555 }
3556 break;
3557 }
3558 if (cond == 0) {
3559 switch (opc) {
3560 case OPC_TEQ: /* rs == rs */
3561 case OPC_TEQI: /* r0 == 0 */
3562 case OPC_TGE: /* rs >= rs */
3563 case OPC_TGEI: /* r0 >= 0 */
3564 case OPC_TGEU: /* rs >= rs unsigned */
3565 case OPC_TGEIU: /* r0 >= 0 unsigned */
3566 /* Always trap */
aurel32cdc0faa2009-03-29 01:19:02 +00003567 generate_exception(ctx, EXCP_TRAP);
bellard6af0bf92005-07-02 14:58:51 +00003568 break;
3569 case OPC_TLT: /* rs < rs */
3570 case OPC_TLTI: /* r0 < 0 */
3571 case OPC_TLTU: /* rs < rs unsigned */
3572 case OPC_TLTIU: /* r0 < 0 unsigned */
3573 case OPC_TNE: /* rs != rs */
3574 case OPC_TNEI: /* r0 != 0 */
thsead93602007-09-06 00:18:15 +00003575 /* Never trap: treat as NOP. */
aurel32cdc0faa2009-03-29 01:19:02 +00003576 break;
bellard6af0bf92005-07-02 14:58:51 +00003577 }
3578 } else {
aurel32cdc0faa2009-03-29 01:19:02 +00003579 int l1 = gen_new_label();
3580
bellard6af0bf92005-07-02 14:58:51 +00003581 switch (opc) {
3582 case OPC_TEQ:
3583 case OPC_TEQI:
aurel32cdc0faa2009-03-29 01:19:02 +00003584 tcg_gen_brcond_tl(TCG_COND_NE, t0, t1, l1);
bellard6af0bf92005-07-02 14:58:51 +00003585 break;
3586 case OPC_TGE:
3587 case OPC_TGEI:
aurel32cdc0faa2009-03-29 01:19:02 +00003588 tcg_gen_brcond_tl(TCG_COND_LT, t0, t1, l1);
bellard6af0bf92005-07-02 14:58:51 +00003589 break;
3590 case OPC_TGEU:
3591 case OPC_TGEIU:
aurel32cdc0faa2009-03-29 01:19:02 +00003592 tcg_gen_brcond_tl(TCG_COND_LTU, t0, t1, l1);
bellard6af0bf92005-07-02 14:58:51 +00003593 break;
3594 case OPC_TLT:
3595 case OPC_TLTI:
aurel32cdc0faa2009-03-29 01:19:02 +00003596 tcg_gen_brcond_tl(TCG_COND_GE, t0, t1, l1);
bellard6af0bf92005-07-02 14:58:51 +00003597 break;
3598 case OPC_TLTU:
3599 case OPC_TLTIU:
aurel32cdc0faa2009-03-29 01:19:02 +00003600 tcg_gen_brcond_tl(TCG_COND_GEU, t0, t1, l1);
bellard6af0bf92005-07-02 14:58:51 +00003601 break;
3602 case OPC_TNE:
3603 case OPC_TNEI:
aurel32cdc0faa2009-03-29 01:19:02 +00003604 tcg_gen_brcond_tl(TCG_COND_EQ, t0, t1, l1);
bellard6af0bf92005-07-02 14:58:51 +00003605 break;
bellard6af0bf92005-07-02 14:58:51 +00003606 }
aurel32cdc0faa2009-03-29 01:19:02 +00003607 generate_exception(ctx, EXCP_TRAP);
ths08ba7962008-06-12 03:15:13 +00003608 gen_set_label(l1);
3609 }
thsbe24bb42008-06-23 12:57:09 +00003610 tcg_temp_free(t0);
3611 tcg_temp_free(t1);
bellard6af0bf92005-07-02 14:58:51 +00003612}
3613
ths356265a2008-07-01 16:37:52 +00003614static inline void gen_goto_tb(DisasContext *ctx, int n, target_ulong dest)
bellardc53be332005-10-30 21:39:19 +00003615{
bellard6e256c92005-11-20 10:32:05 +00003616 TranslationBlock *tb;
3617 tb = ctx->tb;
Nathan Froyd7b270ef2009-07-14 08:33:11 -07003618 if ((tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK) &&
3619 likely(!ctx->singlestep_enabled)) {
bellard57fec1f2008-02-01 10:50:11 +00003620 tcg_gen_goto_tb(n);
ths9b9e4392007-05-28 17:03:28 +00003621 gen_save_pc(dest);
Stefan Weil4b4a72e2011-04-02 13:36:31 +02003622 tcg_gen_exit_tb((tcg_target_long)tb + n);
bellard6e256c92005-11-20 10:32:05 +00003623 } else {
ths9b9e4392007-05-28 17:03:28 +00003624 gen_save_pc(dest);
Nathan Froyd7b270ef2009-07-14 08:33:11 -07003625 if (ctx->singlestep_enabled) {
3626 save_cpu_state(ctx, 0);
Blue Swirl895c2d02012-09-02 14:52:59 +00003627 gen_helper_0e0i(raise_exception, EXCP_DEBUG);
Nathan Froyd7b270ef2009-07-14 08:33:11 -07003628 }
bellard57fec1f2008-02-01 10:50:11 +00003629 tcg_gen_exit_tb(0);
bellard6e256c92005-11-20 10:32:05 +00003630 }
bellardc53be332005-10-30 21:39:19 +00003631}
3632
bellard6af0bf92005-07-02 14:58:51 +00003633/* Branches (before delay slot) */
ths7a387ff2006-12-06 20:17:30 +00003634static void gen_compute_branch (DisasContext *ctx, uint32_t opc,
Nathan Froyd7dca4ad2009-12-08 08:06:25 -08003635 int insn_bytes,
bellard6af0bf92005-07-02 14:58:51 +00003636 int rs, int rt, int32_t offset)
3637{
thsd077b6f2008-06-30 11:30:34 +00003638 target_ulong btgt = -1;
ths3ad4bb22007-03-19 22:15:30 +00003639 int blink = 0;
aurel322fdbad22008-09-05 14:19:17 +00003640 int bcond_compute = 0;
aurel321ba74fb2009-03-29 01:18:52 +00003641 TCGv t0 = tcg_temp_new();
3642 TCGv t1 = tcg_temp_new();
bellard6af0bf92005-07-02 14:58:51 +00003643
ths3ad4bb22007-03-19 22:15:30 +00003644 if (ctx->hflags & MIPS_HFLAG_BMASK) {
ths923617a2007-05-11 00:16:06 +00003645#ifdef MIPS_DEBUG_DISAS
aliguorid12d51d2009-01-15 21:48:06 +00003646 LOG_DISAS("Branch in delay slot at PC 0x" TARGET_FMT_lx "\n", ctx->pc);
ths923617a2007-05-11 00:16:06 +00003647#endif
ths3ad4bb22007-03-19 22:15:30 +00003648 generate_exception(ctx, EXCP_RI);
ths6c5c1e22008-06-24 15:12:27 +00003649 goto out;
ths3ad4bb22007-03-19 22:15:30 +00003650 }
3651
bellard6af0bf92005-07-02 14:58:51 +00003652 /* Load needed operands */
3653 switch (opc) {
3654 case OPC_BEQ:
3655 case OPC_BEQL:
3656 case OPC_BNE:
3657 case OPC_BNEL:
3658 /* Compare two registers */
3659 if (rs != rt) {
ths6c5c1e22008-06-24 15:12:27 +00003660 gen_load_gpr(t0, rs);
3661 gen_load_gpr(t1, rt);
aurel322fdbad22008-09-05 14:19:17 +00003662 bcond_compute = 1;
bellard6af0bf92005-07-02 14:58:51 +00003663 }
Nathan Froyd7dca4ad2009-12-08 08:06:25 -08003664 btgt = ctx->pc + insn_bytes + offset;
bellard6af0bf92005-07-02 14:58:51 +00003665 break;
3666 case OPC_BGEZ:
3667 case OPC_BGEZAL:
Nathan Froyd3c824102010-06-08 13:29:59 -07003668 case OPC_BGEZALS:
bellard6af0bf92005-07-02 14:58:51 +00003669 case OPC_BGEZALL:
3670 case OPC_BGEZL:
3671 case OPC_BGTZ:
3672 case OPC_BGTZL:
3673 case OPC_BLEZ:
3674 case OPC_BLEZL:
3675 case OPC_BLTZ:
3676 case OPC_BLTZAL:
Nathan Froyd3c824102010-06-08 13:29:59 -07003677 case OPC_BLTZALS:
bellard6af0bf92005-07-02 14:58:51 +00003678 case OPC_BLTZALL:
3679 case OPC_BLTZL:
3680 /* Compare to zero */
3681 if (rs != 0) {
ths6c5c1e22008-06-24 15:12:27 +00003682 gen_load_gpr(t0, rs);
aurel322fdbad22008-09-05 14:19:17 +00003683 bcond_compute = 1;
bellard6af0bf92005-07-02 14:58:51 +00003684 }
Nathan Froyd7dca4ad2009-12-08 08:06:25 -08003685 btgt = ctx->pc + insn_bytes + offset;
bellard6af0bf92005-07-02 14:58:51 +00003686 break;
Jia Liue45a93e2012-10-24 22:17:04 +08003687 case OPC_BPOSGE32:
3688#if defined(TARGET_MIPS64)
3689 case OPC_BPOSGE64:
3690 tcg_gen_andi_tl(t0, cpu_dspctrl, 0x7F);
3691#else
3692 tcg_gen_andi_tl(t0, cpu_dspctrl, 0x3F);
3693#endif
3694 bcond_compute = 1;
3695 btgt = ctx->pc + insn_bytes + offset;
3696 break;
bellard6af0bf92005-07-02 14:58:51 +00003697 case OPC_J:
3698 case OPC_JAL:
Nathan Froyd364d4832009-12-08 08:06:29 -08003699 case OPC_JALX:
Nathan Froyd620e48f2010-06-08 13:29:58 -07003700 case OPC_JALS:
3701 case OPC_JALXS:
bellard6af0bf92005-07-02 14:58:51 +00003702 /* Jump to immediate */
Nathan Froyd7dca4ad2009-12-08 08:06:25 -08003703 btgt = ((ctx->pc + insn_bytes) & (int32_t)0xF0000000) | (uint32_t)offset;
bellard6af0bf92005-07-02 14:58:51 +00003704 break;
3705 case OPC_JR:
3706 case OPC_JALR:
Nathan Froyd364d4832009-12-08 08:06:29 -08003707 case OPC_JALRC:
Nathan Froyd620e48f2010-06-08 13:29:58 -07003708 case OPC_JALRS:
bellard6af0bf92005-07-02 14:58:51 +00003709 /* Jump to register */
ths7a387ff2006-12-06 20:17:30 +00003710 if (offset != 0 && offset != 16) {
3711 /* Hint = 0 is JR/JALR, hint 16 is JR.HB/JALR.HB, the
thscbeb0852007-04-07 01:11:15 +00003712 others are reserved. */
ths923617a2007-05-11 00:16:06 +00003713 MIPS_INVAL("jump hint");
bellard6af0bf92005-07-02 14:58:51 +00003714 generate_exception(ctx, EXCP_RI);
ths6c5c1e22008-06-24 15:12:27 +00003715 goto out;
bellard6af0bf92005-07-02 14:58:51 +00003716 }
thsd077b6f2008-06-30 11:30:34 +00003717 gen_load_gpr(btarget, rs);
bellard6af0bf92005-07-02 14:58:51 +00003718 break;
3719 default:
3720 MIPS_INVAL("branch/jump");
3721 generate_exception(ctx, EXCP_RI);
ths6c5c1e22008-06-24 15:12:27 +00003722 goto out;
bellard6af0bf92005-07-02 14:58:51 +00003723 }
aurel322fdbad22008-09-05 14:19:17 +00003724 if (bcond_compute == 0) {
bellard6af0bf92005-07-02 14:58:51 +00003725 /* No condition to be computed */
3726 switch (opc) {
3727 case OPC_BEQ: /* rx == rx */
3728 case OPC_BEQL: /* rx == rx likely */
3729 case OPC_BGEZ: /* 0 >= 0 */
3730 case OPC_BGEZL: /* 0 >= 0 likely */
3731 case OPC_BLEZ: /* 0 <= 0 */
3732 case OPC_BLEZL: /* 0 <= 0 likely */
3733 /* Always take */
bellard4ad40f32005-12-05 19:59:36 +00003734 ctx->hflags |= MIPS_HFLAG_B;
bellard6af0bf92005-07-02 14:58:51 +00003735 MIPS_DEBUG("balways");
3736 break;
Nathan Froyd3c824102010-06-08 13:29:59 -07003737 case OPC_BGEZALS:
bellard6af0bf92005-07-02 14:58:51 +00003738 case OPC_BGEZAL: /* 0 >= 0 */
3739 case OPC_BGEZALL: /* 0 >= 0 likely */
Nathan Froyd3c824102010-06-08 13:29:59 -07003740 ctx->hflags |= (opc == OPC_BGEZALS
3741 ? MIPS_HFLAG_BDS16
3742 : MIPS_HFLAG_BDS32);
bellard6af0bf92005-07-02 14:58:51 +00003743 /* Always take and link */
3744 blink = 31;
bellard4ad40f32005-12-05 19:59:36 +00003745 ctx->hflags |= MIPS_HFLAG_B;
bellard6af0bf92005-07-02 14:58:51 +00003746 MIPS_DEBUG("balways and link");
3747 break;
3748 case OPC_BNE: /* rx != rx */
3749 case OPC_BGTZ: /* 0 > 0 */
3750 case OPC_BLTZ: /* 0 < 0 */
thsead93602007-09-06 00:18:15 +00003751 /* Treat as NOP. */
bellard6af0bf92005-07-02 14:58:51 +00003752 MIPS_DEBUG("bnever (NOP)");
ths6c5c1e22008-06-24 15:12:27 +00003753 goto out;
Nathan Froyd3c824102010-06-08 13:29:59 -07003754 case OPC_BLTZALS:
bellardeeef26c2005-11-26 18:47:06 +00003755 case OPC_BLTZAL: /* 0 < 0 */
Nathan Froyd3c824102010-06-08 13:29:59 -07003756 ctx->hflags |= (opc == OPC_BLTZALS
3757 ? MIPS_HFLAG_BDS16
3758 : MIPS_HFLAG_BDS32);
3759 /* Handle as an unconditional branch to get correct delay
3760 slot checking. */
3761 blink = 31;
3762 btgt = ctx->pc + (opc == OPC_BLTZALS ? 6 : 8);
3763 ctx->hflags |= MIPS_HFLAG_B;
ths98981282007-04-16 01:35:29 +00003764 MIPS_DEBUG("bnever and link");
Nathan Froyd3c824102010-06-08 13:29:59 -07003765 break;
bellardeeef26c2005-11-26 18:47:06 +00003766 case OPC_BLTZALL: /* 0 < 0 likely */
aurel321ba74fb2009-03-29 01:18:52 +00003767 tcg_gen_movi_tl(cpu_gpr[31], ctx->pc + 8);
ths98981282007-04-16 01:35:29 +00003768 /* Skip the instruction in the delay slot */
3769 MIPS_DEBUG("bnever, link and skip");
3770 ctx->pc += 4;
ths6c5c1e22008-06-24 15:12:27 +00003771 goto out;
bellard6af0bf92005-07-02 14:58:51 +00003772 case OPC_BNEL: /* rx != rx likely */
3773 case OPC_BGTZL: /* 0 > 0 likely */
bellard6af0bf92005-07-02 14:58:51 +00003774 case OPC_BLTZL: /* 0 < 0 likely */
3775 /* Skip the instruction in the delay slot */
3776 MIPS_DEBUG("bnever and skip");
ths98981282007-04-16 01:35:29 +00003777 ctx->pc += 4;
ths6c5c1e22008-06-24 15:12:27 +00003778 goto out;
bellard6af0bf92005-07-02 14:58:51 +00003779 case OPC_J:
bellard4ad40f32005-12-05 19:59:36 +00003780 ctx->hflags |= MIPS_HFLAG_B;
thsd077b6f2008-06-30 11:30:34 +00003781 MIPS_DEBUG("j " TARGET_FMT_lx, btgt);
bellard6af0bf92005-07-02 14:58:51 +00003782 break;
Nathan Froyd620e48f2010-06-08 13:29:58 -07003783 case OPC_JALXS:
Nathan Froyd364d4832009-12-08 08:06:29 -08003784 case OPC_JALX:
3785 ctx->hflags |= MIPS_HFLAG_BX;
3786 /* Fallthrough */
Nathan Froyd620e48f2010-06-08 13:29:58 -07003787 case OPC_JALS:
bellard6af0bf92005-07-02 14:58:51 +00003788 case OPC_JAL:
3789 blink = 31;
bellard4ad40f32005-12-05 19:59:36 +00003790 ctx->hflags |= MIPS_HFLAG_B;
Nathan Froyd620e48f2010-06-08 13:29:58 -07003791 ctx->hflags |= ((opc == OPC_JALS || opc == OPC_JALXS)
Nathan Froyd364d4832009-12-08 08:06:29 -08003792 ? MIPS_HFLAG_BDS16
3793 : MIPS_HFLAG_BDS32);
thsd077b6f2008-06-30 11:30:34 +00003794 MIPS_DEBUG("jal " TARGET_FMT_lx, btgt);
bellard6af0bf92005-07-02 14:58:51 +00003795 break;
3796 case OPC_JR:
bellard4ad40f32005-12-05 19:59:36 +00003797 ctx->hflags |= MIPS_HFLAG_BR;
Nathan Froyd620e48f2010-06-08 13:29:58 -07003798 if (insn_bytes == 4)
3799 ctx->hflags |= MIPS_HFLAG_BDS32;
bellard6af0bf92005-07-02 14:58:51 +00003800 MIPS_DEBUG("jr %s", regnames[rs]);
3801 break;
Nathan Froyd620e48f2010-06-08 13:29:58 -07003802 case OPC_JALRS:
bellard6af0bf92005-07-02 14:58:51 +00003803 case OPC_JALR:
Nathan Froyd364d4832009-12-08 08:06:29 -08003804 case OPC_JALRC:
bellard6af0bf92005-07-02 14:58:51 +00003805 blink = rt;
bellard4ad40f32005-12-05 19:59:36 +00003806 ctx->hflags |= MIPS_HFLAG_BR;
Nathan Froyd620e48f2010-06-08 13:29:58 -07003807 ctx->hflags |= (opc == OPC_JALRS
3808 ? MIPS_HFLAG_BDS16
3809 : MIPS_HFLAG_BDS32);
bellard6af0bf92005-07-02 14:58:51 +00003810 MIPS_DEBUG("jalr %s, %s", regnames[rt], regnames[rs]);
3811 break;
3812 default:
3813 MIPS_INVAL("branch/jump");
3814 generate_exception(ctx, EXCP_RI);
ths6c5c1e22008-06-24 15:12:27 +00003815 goto out;
bellard6af0bf92005-07-02 14:58:51 +00003816 }
3817 } else {
3818 switch (opc) {
3819 case OPC_BEQ:
Aurelien Jarnoe68dd282010-02-08 15:50:58 +01003820 tcg_gen_setcond_tl(TCG_COND_EQ, bcond, t0, t1);
ths923617a2007-05-11 00:16:06 +00003821 MIPS_DEBUG("beq %s, %s, " TARGET_FMT_lx,
thsd077b6f2008-06-30 11:30:34 +00003822 regnames[rs], regnames[rt], btgt);
bellard6af0bf92005-07-02 14:58:51 +00003823 goto not_likely;
3824 case OPC_BEQL:
Aurelien Jarnoe68dd282010-02-08 15:50:58 +01003825 tcg_gen_setcond_tl(TCG_COND_EQ, bcond, t0, t1);
ths923617a2007-05-11 00:16:06 +00003826 MIPS_DEBUG("beql %s, %s, " TARGET_FMT_lx,
thsd077b6f2008-06-30 11:30:34 +00003827 regnames[rs], regnames[rt], btgt);
bellard6af0bf92005-07-02 14:58:51 +00003828 goto likely;
3829 case OPC_BNE:
Aurelien Jarnoe68dd282010-02-08 15:50:58 +01003830 tcg_gen_setcond_tl(TCG_COND_NE, bcond, t0, t1);
ths923617a2007-05-11 00:16:06 +00003831 MIPS_DEBUG("bne %s, %s, " TARGET_FMT_lx,
thsd077b6f2008-06-30 11:30:34 +00003832 regnames[rs], regnames[rt], btgt);
bellard6af0bf92005-07-02 14:58:51 +00003833 goto not_likely;
3834 case OPC_BNEL:
Aurelien Jarnoe68dd282010-02-08 15:50:58 +01003835 tcg_gen_setcond_tl(TCG_COND_NE, bcond, t0, t1);
ths923617a2007-05-11 00:16:06 +00003836 MIPS_DEBUG("bnel %s, %s, " TARGET_FMT_lx,
thsd077b6f2008-06-30 11:30:34 +00003837 regnames[rs], regnames[rt], btgt);
bellard6af0bf92005-07-02 14:58:51 +00003838 goto likely;
3839 case OPC_BGEZ:
Aurelien Jarnoe68dd282010-02-08 15:50:58 +01003840 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
thsd077b6f2008-06-30 11:30:34 +00003841 MIPS_DEBUG("bgez %s, " TARGET_FMT_lx, regnames[rs], btgt);
bellard6af0bf92005-07-02 14:58:51 +00003842 goto not_likely;
3843 case OPC_BGEZL:
Aurelien Jarnoe68dd282010-02-08 15:50:58 +01003844 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
thsd077b6f2008-06-30 11:30:34 +00003845 MIPS_DEBUG("bgezl %s, " TARGET_FMT_lx, regnames[rs], btgt);
bellard6af0bf92005-07-02 14:58:51 +00003846 goto likely;
Nathan Froyd3c824102010-06-08 13:29:59 -07003847 case OPC_BGEZALS:
bellard6af0bf92005-07-02 14:58:51 +00003848 case OPC_BGEZAL:
Nathan Froyd3c824102010-06-08 13:29:59 -07003849 ctx->hflags |= (opc == OPC_BGEZALS
3850 ? MIPS_HFLAG_BDS16
3851 : MIPS_HFLAG_BDS32);
Aurelien Jarnoe68dd282010-02-08 15:50:58 +01003852 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
thsd077b6f2008-06-30 11:30:34 +00003853 MIPS_DEBUG("bgezal %s, " TARGET_FMT_lx, regnames[rs], btgt);
bellard6af0bf92005-07-02 14:58:51 +00003854 blink = 31;
3855 goto not_likely;
3856 case OPC_BGEZALL:
Aurelien Jarnoe68dd282010-02-08 15:50:58 +01003857 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
bellard6af0bf92005-07-02 14:58:51 +00003858 blink = 31;
thsd077b6f2008-06-30 11:30:34 +00003859 MIPS_DEBUG("bgezall %s, " TARGET_FMT_lx, regnames[rs], btgt);
bellard6af0bf92005-07-02 14:58:51 +00003860 goto likely;
3861 case OPC_BGTZ:
Aurelien Jarnoe68dd282010-02-08 15:50:58 +01003862 tcg_gen_setcondi_tl(TCG_COND_GT, bcond, t0, 0);
thsd077b6f2008-06-30 11:30:34 +00003863 MIPS_DEBUG("bgtz %s, " TARGET_FMT_lx, regnames[rs], btgt);
bellard6af0bf92005-07-02 14:58:51 +00003864 goto not_likely;
3865 case OPC_BGTZL:
Aurelien Jarnoe68dd282010-02-08 15:50:58 +01003866 tcg_gen_setcondi_tl(TCG_COND_GT, bcond, t0, 0);
thsd077b6f2008-06-30 11:30:34 +00003867 MIPS_DEBUG("bgtzl %s, " TARGET_FMT_lx, regnames[rs], btgt);
bellard6af0bf92005-07-02 14:58:51 +00003868 goto likely;
3869 case OPC_BLEZ:
Aurelien Jarnoe68dd282010-02-08 15:50:58 +01003870 tcg_gen_setcondi_tl(TCG_COND_LE, bcond, t0, 0);
thsd077b6f2008-06-30 11:30:34 +00003871 MIPS_DEBUG("blez %s, " TARGET_FMT_lx, regnames[rs], btgt);
bellard6af0bf92005-07-02 14:58:51 +00003872 goto not_likely;
3873 case OPC_BLEZL:
Aurelien Jarnoe68dd282010-02-08 15:50:58 +01003874 tcg_gen_setcondi_tl(TCG_COND_LE, bcond, t0, 0);
thsd077b6f2008-06-30 11:30:34 +00003875 MIPS_DEBUG("blezl %s, " TARGET_FMT_lx, regnames[rs], btgt);
bellard6af0bf92005-07-02 14:58:51 +00003876 goto likely;
3877 case OPC_BLTZ:
Aurelien Jarnoe68dd282010-02-08 15:50:58 +01003878 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
thsd077b6f2008-06-30 11:30:34 +00003879 MIPS_DEBUG("bltz %s, " TARGET_FMT_lx, regnames[rs], btgt);
bellard6af0bf92005-07-02 14:58:51 +00003880 goto not_likely;
3881 case OPC_BLTZL:
Aurelien Jarnoe68dd282010-02-08 15:50:58 +01003882 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
thsd077b6f2008-06-30 11:30:34 +00003883 MIPS_DEBUG("bltzl %s, " TARGET_FMT_lx, regnames[rs], btgt);
bellard6af0bf92005-07-02 14:58:51 +00003884 goto likely;
Jia Liue45a93e2012-10-24 22:17:04 +08003885 case OPC_BPOSGE32:
3886 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 32);
3887 MIPS_DEBUG("bposge32 " TARGET_FMT_lx, btgt);
3888 goto not_likely;
3889#if defined(TARGET_MIPS64)
3890 case OPC_BPOSGE64:
3891 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 64);
3892 MIPS_DEBUG("bposge64 " TARGET_FMT_lx, btgt);
3893 goto not_likely;
3894#endif
Nathan Froyd3c824102010-06-08 13:29:59 -07003895 case OPC_BLTZALS:
bellard6af0bf92005-07-02 14:58:51 +00003896 case OPC_BLTZAL:
Nathan Froyd3c824102010-06-08 13:29:59 -07003897 ctx->hflags |= (opc == OPC_BLTZALS
3898 ? MIPS_HFLAG_BDS16
3899 : MIPS_HFLAG_BDS32);
Aurelien Jarnoe68dd282010-02-08 15:50:58 +01003900 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
bellard6af0bf92005-07-02 14:58:51 +00003901 blink = 31;
thsd077b6f2008-06-30 11:30:34 +00003902 MIPS_DEBUG("bltzal %s, " TARGET_FMT_lx, regnames[rs], btgt);
bellard6af0bf92005-07-02 14:58:51 +00003903 not_likely:
bellard4ad40f32005-12-05 19:59:36 +00003904 ctx->hflags |= MIPS_HFLAG_BC;
bellard6af0bf92005-07-02 14:58:51 +00003905 break;
3906 case OPC_BLTZALL:
Aurelien Jarnoe68dd282010-02-08 15:50:58 +01003907 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
bellard6af0bf92005-07-02 14:58:51 +00003908 blink = 31;
thsd077b6f2008-06-30 11:30:34 +00003909 MIPS_DEBUG("bltzall %s, " TARGET_FMT_lx, regnames[rs], btgt);
bellard6af0bf92005-07-02 14:58:51 +00003910 likely:
bellard4ad40f32005-12-05 19:59:36 +00003911 ctx->hflags |= MIPS_HFLAG_BL;
bellard6af0bf92005-07-02 14:58:51 +00003912 break;
thsc53f4a62007-04-05 23:21:37 +00003913 default:
3914 MIPS_INVAL("conditional branch/jump");
3915 generate_exception(ctx, EXCP_RI);
ths6c5c1e22008-06-24 15:12:27 +00003916 goto out;
bellard6af0bf92005-07-02 14:58:51 +00003917 }
bellard6af0bf92005-07-02 14:58:51 +00003918 }
ths923617a2007-05-11 00:16:06 +00003919 MIPS_DEBUG("enter ds: link %d cond %02x target " TARGET_FMT_lx,
thsd077b6f2008-06-30 11:30:34 +00003920 blink, ctx->hflags, btgt);
ths9b9e4392007-05-28 17:03:28 +00003921
thsd077b6f2008-06-30 11:30:34 +00003922 ctx->btarget = btgt;
bellard6af0bf92005-07-02 14:58:51 +00003923 if (blink > 0) {
Nathan Froyd364d4832009-12-08 08:06:29 -08003924 int post_delay = insn_bytes;
3925 int lowbit = !!(ctx->hflags & MIPS_HFLAG_M16);
3926
3927 if (opc != OPC_JALRC)
3928 post_delay += ((ctx->hflags & MIPS_HFLAG_BDS16) ? 2 : 4);
3929
3930 tcg_gen_movi_tl(cpu_gpr[blink], ctx->pc + post_delay + lowbit);
bellard6af0bf92005-07-02 14:58:51 +00003931 }
ths6c5c1e22008-06-24 15:12:27 +00003932
3933 out:
Nathan Froyd364d4832009-12-08 08:06:29 -08003934 if (insn_bytes == 2)
3935 ctx->hflags |= MIPS_HFLAG_B16;
ths6c5c1e22008-06-24 15:12:27 +00003936 tcg_temp_free(t0);
3937 tcg_temp_free(t1);
bellard6af0bf92005-07-02 14:58:51 +00003938}
3939
ths7a387ff2006-12-06 20:17:30 +00003940/* special3 bitfield operations */
3941static void gen_bitops (DisasContext *ctx, uint32_t opc, int rt,
ths356265a2008-07-01 16:37:52 +00003942 int rs, int lsb, int msb)
ths7a387ff2006-12-06 20:17:30 +00003943{
pbrooka7812ae2008-11-17 14:43:54 +00003944 TCGv t0 = tcg_temp_new();
3945 TCGv t1 = tcg_temp_new();
ths6c5c1e22008-06-24 15:12:27 +00003946
3947 gen_load_gpr(t1, rs);
ths7a387ff2006-12-06 20:17:30 +00003948 switch (opc) {
3949 case OPC_EXT:
3950 if (lsb + msb > 31)
3951 goto fail;
aurel32505ad7c2008-11-11 11:46:58 +00003952 tcg_gen_shri_tl(t0, t1, lsb);
3953 if (msb != 31) {
3954 tcg_gen_andi_tl(t0, t0, (1 << (msb + 1)) - 1);
3955 } else {
3956 tcg_gen_ext32s_tl(t0, t0);
3957 }
ths7a387ff2006-12-06 20:17:30 +00003958 break;
thsc6d6dd72007-11-18 03:36:07 +00003959#if defined(TARGET_MIPS64)
ths7a387ff2006-12-06 20:17:30 +00003960 case OPC_DEXTM:
aurel32505ad7c2008-11-11 11:46:58 +00003961 tcg_gen_shri_tl(t0, t1, lsb);
3962 if (msb != 31) {
3963 tcg_gen_andi_tl(t0, t0, (1ULL << (msb + 1 + 32)) - 1);
3964 }
ths7a387ff2006-12-06 20:17:30 +00003965 break;
3966 case OPC_DEXTU:
aurel32505ad7c2008-11-11 11:46:58 +00003967 tcg_gen_shri_tl(t0, t1, lsb + 32);
3968 tcg_gen_andi_tl(t0, t0, (1ULL << (msb + 1)) - 1);
ths7a387ff2006-12-06 20:17:30 +00003969 break;
3970 case OPC_DEXT:
aurel32505ad7c2008-11-11 11:46:58 +00003971 tcg_gen_shri_tl(t0, t1, lsb);
3972 tcg_gen_andi_tl(t0, t0, (1ULL << (msb + 1)) - 1);
ths7a387ff2006-12-06 20:17:30 +00003973 break;
thsc6d6dd72007-11-18 03:36:07 +00003974#endif
ths7a387ff2006-12-06 20:17:30 +00003975 case OPC_INS:
3976 if (lsb > msb)
3977 goto fail;
ths6c5c1e22008-06-24 15:12:27 +00003978 gen_load_gpr(t0, rt);
Aurelien Jarnoe0d002f2012-10-09 21:53:21 +02003979 tcg_gen_deposit_tl(t0, t0, t1, lsb, msb - lsb + 1);
aurel32505ad7c2008-11-11 11:46:58 +00003980 tcg_gen_ext32s_tl(t0, t0);
ths7a387ff2006-12-06 20:17:30 +00003981 break;
thsc6d6dd72007-11-18 03:36:07 +00003982#if defined(TARGET_MIPS64)
ths7a387ff2006-12-06 20:17:30 +00003983 case OPC_DINSM:
ths6c5c1e22008-06-24 15:12:27 +00003984 gen_load_gpr(t0, rt);
Aurelien Jarnoe0d002f2012-10-09 21:53:21 +02003985 tcg_gen_deposit_tl(t0, t0, t1, lsb, msb + 32 - lsb + 1);
ths7a387ff2006-12-06 20:17:30 +00003986 break;
3987 case OPC_DINSU:
ths6c5c1e22008-06-24 15:12:27 +00003988 gen_load_gpr(t0, rt);
Aurelien Jarnoe0d002f2012-10-09 21:53:21 +02003989 tcg_gen_deposit_tl(t0, t0, t1, lsb + 32, msb - lsb + 1);
ths7a387ff2006-12-06 20:17:30 +00003990 break;
3991 case OPC_DINS:
ths6c5c1e22008-06-24 15:12:27 +00003992 gen_load_gpr(t0, rt);
Aurelien Jarnoe0d002f2012-10-09 21:53:21 +02003993 tcg_gen_deposit_tl(t0, t0, t1, lsb, msb - lsb + 1);
ths7a387ff2006-12-06 20:17:30 +00003994 break;
thsc6d6dd72007-11-18 03:36:07 +00003995#endif
ths7a387ff2006-12-06 20:17:30 +00003996 default:
3997fail:
3998 MIPS_INVAL("bitops");
3999 generate_exception(ctx, EXCP_RI);
ths6c5c1e22008-06-24 15:12:27 +00004000 tcg_temp_free(t0);
4001 tcg_temp_free(t1);
ths7a387ff2006-12-06 20:17:30 +00004002 return;
4003 }
ths6c5c1e22008-06-24 15:12:27 +00004004 gen_store_gpr(t0, rt);
4005 tcg_temp_free(t0);
4006 tcg_temp_free(t1);
ths7a387ff2006-12-06 20:17:30 +00004007}
4008
aurel3249bcf332008-11-11 11:47:06 +00004009static void gen_bshfl (DisasContext *ctx, uint32_t op2, int rt, int rd)
4010{
aurel323a55fa42009-03-29 01:18:34 +00004011 TCGv t0;
aurel3249bcf332008-11-11 11:47:06 +00004012
aurel323a55fa42009-03-29 01:18:34 +00004013 if (rd == 0) {
4014 /* If no destination, treat it as a NOP. */
4015 MIPS_DEBUG("NOP");
4016 return;
4017 }
4018
4019 t0 = tcg_temp_new();
4020 gen_load_gpr(t0, rt);
aurel3249bcf332008-11-11 11:47:06 +00004021 switch (op2) {
4022 case OPC_WSBH:
aurel323a55fa42009-03-29 01:18:34 +00004023 {
4024 TCGv t1 = tcg_temp_new();
4025
4026 tcg_gen_shri_tl(t1, t0, 8);
4027 tcg_gen_andi_tl(t1, t1, 0x00FF00FF);
4028 tcg_gen_shli_tl(t0, t0, 8);
4029 tcg_gen_andi_tl(t0, t0, ~0x00FF00FF);
4030 tcg_gen_or_tl(t0, t0, t1);
4031 tcg_temp_free(t1);
4032 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
4033 }
aurel3249bcf332008-11-11 11:47:06 +00004034 break;
4035 case OPC_SEB:
aurel323a55fa42009-03-29 01:18:34 +00004036 tcg_gen_ext8s_tl(cpu_gpr[rd], t0);
aurel3249bcf332008-11-11 11:47:06 +00004037 break;
4038 case OPC_SEH:
aurel323a55fa42009-03-29 01:18:34 +00004039 tcg_gen_ext16s_tl(cpu_gpr[rd], t0);
aurel3249bcf332008-11-11 11:47:06 +00004040 break;
4041#if defined(TARGET_MIPS64)
4042 case OPC_DSBH:
aurel323a55fa42009-03-29 01:18:34 +00004043 {
4044 TCGv t1 = tcg_temp_new();
4045
4046 tcg_gen_shri_tl(t1, t0, 8);
4047 tcg_gen_andi_tl(t1, t1, 0x00FF00FF00FF00FFULL);
4048 tcg_gen_shli_tl(t0, t0, 8);
4049 tcg_gen_andi_tl(t0, t0, ~0x00FF00FF00FF00FFULL);
4050 tcg_gen_or_tl(cpu_gpr[rd], t0, t1);
4051 tcg_temp_free(t1);
4052 }
aurel3249bcf332008-11-11 11:47:06 +00004053 break;
4054 case OPC_DSHD:
aurel323a55fa42009-03-29 01:18:34 +00004055 {
4056 TCGv t1 = tcg_temp_new();
4057
4058 tcg_gen_shri_tl(t1, t0, 16);
4059 tcg_gen_andi_tl(t1, t1, 0x0000FFFF0000FFFFULL);
4060 tcg_gen_shli_tl(t0, t0, 16);
4061 tcg_gen_andi_tl(t0, t0, ~0x0000FFFF0000FFFFULL);
4062 tcg_gen_or_tl(t0, t0, t1);
4063 tcg_gen_shri_tl(t1, t0, 32);
4064 tcg_gen_shli_tl(t0, t0, 32);
4065 tcg_gen_or_tl(cpu_gpr[rd], t0, t1);
4066 tcg_temp_free(t1);
4067 }
aurel3249bcf332008-11-11 11:47:06 +00004068 break;
4069#endif
4070 default:
4071 MIPS_INVAL("bsfhl");
4072 generate_exception(ctx, EXCP_RI);
4073 tcg_temp_free(t0);
aurel3249bcf332008-11-11 11:47:06 +00004074 return;
4075 }
aurel3249bcf332008-11-11 11:47:06 +00004076 tcg_temp_free(t0);
aurel3249bcf332008-11-11 11:47:06 +00004077}
4078
thsf1aa6322008-06-09 07:13:38 +00004079#ifndef CONFIG_USER_ONLY
ths0eaef5a2008-07-23 16:14:22 +00004080/* CP0 (MMU and control) */
aurel32d9bea112009-04-15 14:41:44 +00004081static inline void gen_mfc0_load32 (TCGv arg, target_ulong off)
ths4f576892008-06-04 17:37:03 +00004082{
aurel32d9bea112009-04-15 14:41:44 +00004083 TCGv_i32 t0 = tcg_temp_new_i32();
ths4f576892008-06-04 17:37:03 +00004084
aurel32d9bea112009-04-15 14:41:44 +00004085 tcg_gen_ld_i32(t0, cpu_env, off);
4086 tcg_gen_ext_i32_tl(arg, t0);
4087 tcg_temp_free_i32(t0);
ths4f576892008-06-04 17:37:03 +00004088}
4089
aurel32d9bea112009-04-15 14:41:44 +00004090static inline void gen_mfc0_load64 (TCGv arg, target_ulong off)
ths4f576892008-06-04 17:37:03 +00004091{
aurel32d9bea112009-04-15 14:41:44 +00004092 tcg_gen_ld_tl(arg, cpu_env, off);
4093 tcg_gen_ext32s_tl(arg, arg);
ths4f576892008-06-04 17:37:03 +00004094}
4095
aurel32d9bea112009-04-15 14:41:44 +00004096static inline void gen_mtc0_store32 (TCGv arg, target_ulong off)
thsf1aa6322008-06-09 07:13:38 +00004097{
aurel32d9bea112009-04-15 14:41:44 +00004098 TCGv_i32 t0 = tcg_temp_new_i32();
thsf1aa6322008-06-09 07:13:38 +00004099
aurel32d9bea112009-04-15 14:41:44 +00004100 tcg_gen_trunc_tl_i32(t0, arg);
4101 tcg_gen_st_i32(t0, cpu_env, off);
4102 tcg_temp_free_i32(t0);
thsf1aa6322008-06-09 07:13:38 +00004103}
4104
aurel32d9bea112009-04-15 14:41:44 +00004105static inline void gen_mtc0_store64 (TCGv arg, target_ulong off)
thsf1aa6322008-06-09 07:13:38 +00004106{
aurel32d9bea112009-04-15 14:41:44 +00004107 tcg_gen_ext32s_tl(arg, arg);
4108 tcg_gen_st_tl(arg, cpu_env, off);
thsf1aa6322008-06-09 07:13:38 +00004109}
4110
Aurelien Jarnod75c1352013-01-01 18:02:22 +01004111static void gen_mfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
ths873eb012006-12-06 17:59:07 +00004112{
ths7a387ff2006-12-06 20:17:30 +00004113 const char *rn = "invalid";
ths873eb012006-12-06 17:59:07 +00004114
thse189e742007-09-24 12:48:00 +00004115 if (sel != 0)
Aurelien Jarnod75c1352013-01-01 18:02:22 +01004116 check_insn(ctx, ISA_MIPS32);
thse189e742007-09-24 12:48:00 +00004117
ths873eb012006-12-06 17:59:07 +00004118 switch (reg) {
4119 case 0:
ths7a387ff2006-12-06 20:17:30 +00004120 switch (sel) {
4121 case 0:
Andreas Färber7db13fa2012-03-14 01:38:22 +01004122 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Index));
ths7a387ff2006-12-06 20:17:30 +00004123 rn = "Index";
4124 break;
4125 case 1:
Aurelien Jarnod75c1352013-01-01 18:02:22 +01004126 check_insn(ctx, ASE_MT);
Blue Swirl895c2d02012-09-02 14:52:59 +00004127 gen_helper_mfc0_mvpcontrol(arg, cpu_env);
ths7a387ff2006-12-06 20:17:30 +00004128 rn = "MVPControl";
thsead93602007-09-06 00:18:15 +00004129 break;
ths7a387ff2006-12-06 20:17:30 +00004130 case 2:
Aurelien Jarnod75c1352013-01-01 18:02:22 +01004131 check_insn(ctx, ASE_MT);
Blue Swirl895c2d02012-09-02 14:52:59 +00004132 gen_helper_mfc0_mvpconf0(arg, cpu_env);
ths7a387ff2006-12-06 20:17:30 +00004133 rn = "MVPConf0";
thsead93602007-09-06 00:18:15 +00004134 break;
ths7a387ff2006-12-06 20:17:30 +00004135 case 3:
Aurelien Jarnod75c1352013-01-01 18:02:22 +01004136 check_insn(ctx, ASE_MT);
Blue Swirl895c2d02012-09-02 14:52:59 +00004137 gen_helper_mfc0_mvpconf1(arg, cpu_env);
ths7a387ff2006-12-06 20:17:30 +00004138 rn = "MVPConf1";
thsead93602007-09-06 00:18:15 +00004139 break;
ths7a387ff2006-12-06 20:17:30 +00004140 default:
4141 goto die;
4142 }
ths873eb012006-12-06 17:59:07 +00004143 break;
4144 case 1:
ths7a387ff2006-12-06 20:17:30 +00004145 switch (sel) {
4146 case 0:
Blue Swirl895c2d02012-09-02 14:52:59 +00004147 gen_helper_mfc0_random(arg, cpu_env);
ths7a387ff2006-12-06 20:17:30 +00004148 rn = "Random";
ths2423f662007-04-11 02:15:08 +00004149 break;
ths7a387ff2006-12-06 20:17:30 +00004150 case 1:
Aurelien Jarnod75c1352013-01-01 18:02:22 +01004151 check_insn(ctx, ASE_MT);
Andreas Färber7db13fa2012-03-14 01:38:22 +01004152 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEControl));
ths7a387ff2006-12-06 20:17:30 +00004153 rn = "VPEControl";
thsead93602007-09-06 00:18:15 +00004154 break;
ths7a387ff2006-12-06 20:17:30 +00004155 case 2:
Aurelien Jarnod75c1352013-01-01 18:02:22 +01004156 check_insn(ctx, ASE_MT);
Andreas Färber7db13fa2012-03-14 01:38:22 +01004157 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf0));
ths7a387ff2006-12-06 20:17:30 +00004158 rn = "VPEConf0";
thsead93602007-09-06 00:18:15 +00004159 break;
ths7a387ff2006-12-06 20:17:30 +00004160 case 3:
Aurelien Jarnod75c1352013-01-01 18:02:22 +01004161 check_insn(ctx, ASE_MT);
Andreas Färber7db13fa2012-03-14 01:38:22 +01004162 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf1));
ths7a387ff2006-12-06 20:17:30 +00004163 rn = "VPEConf1";
thsead93602007-09-06 00:18:15 +00004164 break;
ths7a387ff2006-12-06 20:17:30 +00004165 case 4:
Aurelien Jarnod75c1352013-01-01 18:02:22 +01004166 check_insn(ctx, ASE_MT);
Andreas Färber7db13fa2012-03-14 01:38:22 +01004167 gen_mfc0_load64(arg, offsetof(CPUMIPSState, CP0_YQMask));
ths7a387ff2006-12-06 20:17:30 +00004168 rn = "YQMask";
thsead93602007-09-06 00:18:15 +00004169 break;
ths7a387ff2006-12-06 20:17:30 +00004170 case 5:
Aurelien Jarnod75c1352013-01-01 18:02:22 +01004171 check_insn(ctx, ASE_MT);
Andreas Färber7db13fa2012-03-14 01:38:22 +01004172 gen_mfc0_load64(arg, offsetof(CPUMIPSState, CP0_VPESchedule));
ths7a387ff2006-12-06 20:17:30 +00004173 rn = "VPESchedule";
thsead93602007-09-06 00:18:15 +00004174 break;
ths7a387ff2006-12-06 20:17:30 +00004175 case 6:
Aurelien Jarnod75c1352013-01-01 18:02:22 +01004176 check_insn(ctx, ASE_MT);
Andreas Färber7db13fa2012-03-14 01:38:22 +01004177 gen_mfc0_load64(arg, offsetof(CPUMIPSState, CP0_VPEScheFBack));
ths7a387ff2006-12-06 20:17:30 +00004178 rn = "VPEScheFBack";
thsead93602007-09-06 00:18:15 +00004179 break;
ths7a387ff2006-12-06 20:17:30 +00004180 case 7:
Aurelien Jarnod75c1352013-01-01 18:02:22 +01004181 check_insn(ctx, ASE_MT);
Andreas Färber7db13fa2012-03-14 01:38:22 +01004182 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEOpt));
ths7a387ff2006-12-06 20:17:30 +00004183 rn = "VPEOpt";
thsead93602007-09-06 00:18:15 +00004184 break;
ths7a387ff2006-12-06 20:17:30 +00004185 default:
4186 goto die;
4187 }
ths873eb012006-12-06 17:59:07 +00004188 break;
4189 case 2:
ths7a387ff2006-12-06 20:17:30 +00004190 switch (sel) {
4191 case 0:
Andreas Färber7db13fa2012-03-14 01:38:22 +01004192 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryLo0));
aurel32d9bea112009-04-15 14:41:44 +00004193 tcg_gen_ext32s_tl(arg, arg);
ths2423f662007-04-11 02:15:08 +00004194 rn = "EntryLo0";
4195 break;
ths7a387ff2006-12-06 20:17:30 +00004196 case 1:
Aurelien Jarnod75c1352013-01-01 18:02:22 +01004197 check_insn(ctx, ASE_MT);
Blue Swirl895c2d02012-09-02 14:52:59 +00004198 gen_helper_mfc0_tcstatus(arg, cpu_env);
ths2423f662007-04-11 02:15:08 +00004199 rn = "TCStatus";
thsead93602007-09-06 00:18:15 +00004200 break;
ths7a387ff2006-12-06 20:17:30 +00004201 case 2:
Aurelien Jarnod75c1352013-01-01 18:02:22 +01004202 check_insn(ctx, ASE_MT);
Blue Swirl895c2d02012-09-02 14:52:59 +00004203 gen_helper_mfc0_tcbind(arg, cpu_env);
ths2423f662007-04-11 02:15:08 +00004204 rn = "TCBind";
thsead93602007-09-06 00:18:15 +00004205 break;
ths7a387ff2006-12-06 20:17:30 +00004206 case 3:
Aurelien Jarnod75c1352013-01-01 18:02:22 +01004207 check_insn(ctx, ASE_MT);
Blue Swirl895c2d02012-09-02 14:52:59 +00004208 gen_helper_mfc0_tcrestart(arg, cpu_env);
ths2423f662007-04-11 02:15:08 +00004209 rn = "TCRestart";
thsead93602007-09-06 00:18:15 +00004210 break;
ths7a387ff2006-12-06 20:17:30 +00004211 case 4:
Aurelien Jarnod75c1352013-01-01 18:02:22 +01004212 check_insn(ctx, ASE_MT);
Blue Swirl895c2d02012-09-02 14:52:59 +00004213 gen_helper_mfc0_tchalt(arg, cpu_env);
ths2423f662007-04-11 02:15:08 +00004214 rn = "TCHalt";
thsead93602007-09-06 00:18:15 +00004215 break;
ths7a387ff2006-12-06 20:17:30 +00004216 case 5:
Aurelien Jarnod75c1352013-01-01 18:02:22 +01004217 check_insn(ctx, ASE_MT);
Blue Swirl895c2d02012-09-02 14:52:59 +00004218 gen_helper_mfc0_tccontext(arg, cpu_env);
ths2423f662007-04-11 02:15:08 +00004219 rn = "TCContext";
thsead93602007-09-06 00:18:15 +00004220 break;
ths7a387ff2006-12-06 20:17:30 +00004221 case 6:
Aurelien Jarnod75c1352013-01-01 18:02:22 +01004222 check_insn(ctx, ASE_MT);
Blue Swirl895c2d02012-09-02 14:52:59 +00004223 gen_helper_mfc0_tcschedule(arg, cpu_env);
ths2423f662007-04-11 02:15:08 +00004224 rn = "TCSchedule";
thsead93602007-09-06 00:18:15 +00004225 break;
ths7a387ff2006-12-06 20:17:30 +00004226 case 7:
Aurelien Jarnod75c1352013-01-01 18:02:22 +01004227 check_insn(ctx, ASE_MT);
Blue Swirl895c2d02012-09-02 14:52:59 +00004228 gen_helper_mfc0_tcschefback(arg, cpu_env);
ths2423f662007-04-11 02:15:08 +00004229 rn = "TCScheFBack";
thsead93602007-09-06 00:18:15 +00004230 break;
ths7a387ff2006-12-06 20:17:30 +00004231 default:
4232 goto die;
4233 }
ths873eb012006-12-06 17:59:07 +00004234 break;
4235 case 3:
ths7a387ff2006-12-06 20:17:30 +00004236 switch (sel) {
4237 case 0:
Andreas Färber7db13fa2012-03-14 01:38:22 +01004238 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryLo1));
aurel32d9bea112009-04-15 14:41:44 +00004239 tcg_gen_ext32s_tl(arg, arg);
ths2423f662007-04-11 02:15:08 +00004240 rn = "EntryLo1";
4241 break;
ths7a387ff2006-12-06 20:17:30 +00004242 default:
4243 goto die;
ths1579a722007-04-05 23:16:25 +00004244 }
ths873eb012006-12-06 17:59:07 +00004245 break;
4246 case 4:
ths7a387ff2006-12-06 20:17:30 +00004247 switch (sel) {
4248 case 0:
Andreas Färber7db13fa2012-03-14 01:38:22 +01004249 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_Context));
aurel32d9bea112009-04-15 14:41:44 +00004250 tcg_gen_ext32s_tl(arg, arg);
ths2423f662007-04-11 02:15:08 +00004251 rn = "Context";
4252 break;
ths7a387ff2006-12-06 20:17:30 +00004253 case 1:
aurel32d9bea112009-04-15 14:41:44 +00004254// gen_helper_mfc0_contextconfig(arg); /* SmartMIPS ASE */
ths2423f662007-04-11 02:15:08 +00004255 rn = "ContextConfig";
4256// break;
ths7a387ff2006-12-06 20:17:30 +00004257 default:
4258 goto die;
ths1579a722007-04-05 23:16:25 +00004259 }
ths873eb012006-12-06 17:59:07 +00004260 break;
4261 case 5:
ths7a387ff2006-12-06 20:17:30 +00004262 switch (sel) {
4263 case 0:
Andreas Färber7db13fa2012-03-14 01:38:22 +01004264 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageMask));
ths2423f662007-04-11 02:15:08 +00004265 rn = "PageMask";
4266 break;
ths7a387ff2006-12-06 20:17:30 +00004267 case 1:
Aurelien Jarnod75c1352013-01-01 18:02:22 +01004268 check_insn(ctx, ISA_MIPS32R2);
Andreas Färber7db13fa2012-03-14 01:38:22 +01004269 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageGrain));
ths2423f662007-04-11 02:15:08 +00004270 rn = "PageGrain";
4271 break;
ths7a387ff2006-12-06 20:17:30 +00004272 default:
4273 goto die;
ths1579a722007-04-05 23:16:25 +00004274 }
ths873eb012006-12-06 17:59:07 +00004275 break;
4276 case 6:
ths7a387ff2006-12-06 20:17:30 +00004277 switch (sel) {
4278 case 0:
Andreas Färber7db13fa2012-03-14 01:38:22 +01004279 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Wired));
ths2423f662007-04-11 02:15:08 +00004280 rn = "Wired";
4281 break;
ths7a387ff2006-12-06 20:17:30 +00004282 case 1:
Aurelien Jarnod75c1352013-01-01 18:02:22 +01004283 check_insn(ctx, ISA_MIPS32R2);
Andreas Färber7db13fa2012-03-14 01:38:22 +01004284 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf0));
ths2423f662007-04-11 02:15:08 +00004285 rn = "SRSConf0";
thsead93602007-09-06 00:18:15 +00004286 break;
ths7a387ff2006-12-06 20:17:30 +00004287 case 2:
Aurelien Jarnod75c1352013-01-01 18:02:22 +01004288 check_insn(ctx, ISA_MIPS32R2);
Andreas Färber7db13fa2012-03-14 01:38:22 +01004289 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf1));
ths2423f662007-04-11 02:15:08 +00004290 rn = "SRSConf1";
thsead93602007-09-06 00:18:15 +00004291 break;
ths7a387ff2006-12-06 20:17:30 +00004292 case 3:
Aurelien Jarnod75c1352013-01-01 18:02:22 +01004293 check_insn(ctx, ISA_MIPS32R2);
Andreas Färber7db13fa2012-03-14 01:38:22 +01004294 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf2));
ths2423f662007-04-11 02:15:08 +00004295 rn = "SRSConf2";
thsead93602007-09-06 00:18:15 +00004296 break;
ths7a387ff2006-12-06 20:17:30 +00004297 case 4:
Aurelien Jarnod75c1352013-01-01 18:02:22 +01004298 check_insn(ctx, ISA_MIPS32R2);
Andreas Färber7db13fa2012-03-14 01:38:22 +01004299 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf3));
ths2423f662007-04-11 02:15:08 +00004300 rn = "SRSConf3";
thsead93602007-09-06 00:18:15 +00004301 break;
ths7a387ff2006-12-06 20:17:30 +00004302 case 5:
Aurelien Jarnod75c1352013-01-01 18:02:22 +01004303 check_insn(ctx, ISA_MIPS32R2);
Andreas Färber7db13fa2012-03-14 01:38:22 +01004304 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf4));
ths2423f662007-04-11 02:15:08 +00004305 rn = "SRSConf4";
thsead93602007-09-06 00:18:15 +00004306 break;
ths7a387ff2006-12-06 20:17:30 +00004307 default:
4308 goto die;
ths1579a722007-04-05 23:16:25 +00004309 }
ths873eb012006-12-06 17:59:07 +00004310 break;
ths8c0fdd82006-12-06 18:19:33 +00004311 case 7:
ths7a387ff2006-12-06 20:17:30 +00004312 switch (sel) {
4313 case 0:
Aurelien Jarnod75c1352013-01-01 18:02:22 +01004314 check_insn(ctx, ISA_MIPS32R2);
Andreas Färber7db13fa2012-03-14 01:38:22 +01004315 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_HWREna));
ths2423f662007-04-11 02:15:08 +00004316 rn = "HWREna";
4317 break;
ths7a387ff2006-12-06 20:17:30 +00004318 default:
4319 goto die;
ths1579a722007-04-05 23:16:25 +00004320 }
ths8c0fdd82006-12-06 18:19:33 +00004321 break;
ths873eb012006-12-06 17:59:07 +00004322 case 8:
ths7a387ff2006-12-06 20:17:30 +00004323 switch (sel) {
4324 case 0:
Andreas Färber7db13fa2012-03-14 01:38:22 +01004325 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_BadVAddr));
aurel32d9bea112009-04-15 14:41:44 +00004326 tcg_gen_ext32s_tl(arg, arg);
thsf0b3f3a2008-05-23 18:10:51 +00004327 rn = "BadVAddr";
ths2423f662007-04-11 02:15:08 +00004328 break;
ths7a387ff2006-12-06 20:17:30 +00004329 default:
4330 goto die;
4331 }
ths873eb012006-12-06 17:59:07 +00004332 break;
4333 case 9:
ths7a387ff2006-12-06 20:17:30 +00004334 switch (sel) {
4335 case 0:
pbrook2e70f6e2008-06-29 01:03:05 +00004336 /* Mark as an IO operation because we read the time. */
4337 if (use_icount)
4338 gen_io_start();
Blue Swirl895c2d02012-09-02 14:52:59 +00004339 gen_helper_mfc0_count(arg, cpu_env);
pbrook2e70f6e2008-06-29 01:03:05 +00004340 if (use_icount) {
4341 gen_io_end();
pbrook2e70f6e2008-06-29 01:03:05 +00004342 }
Edgar E. Iglesias55807222011-01-17 23:00:08 +01004343 /* Break the TB to be able to take timer interrupts immediately
4344 after reading count. */
4345 ctx->bstate = BS_STOP;
ths2423f662007-04-11 02:15:08 +00004346 rn = "Count";
4347 break;
4348 /* 6,7 are implementation dependent */
ths7a387ff2006-12-06 20:17:30 +00004349 default:
4350 goto die;
ths2423f662007-04-11 02:15:08 +00004351 }
ths873eb012006-12-06 17:59:07 +00004352 break;
4353 case 10:
ths7a387ff2006-12-06 20:17:30 +00004354 switch (sel) {
4355 case 0:
Andreas Färber7db13fa2012-03-14 01:38:22 +01004356 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryHi));
aurel32d9bea112009-04-15 14:41:44 +00004357 tcg_gen_ext32s_tl(arg, arg);
ths2423f662007-04-11 02:15:08 +00004358 rn = "EntryHi";
4359 break;
ths7a387ff2006-12-06 20:17:30 +00004360 default:
4361 goto die;
ths1579a722007-04-05 23:16:25 +00004362 }
ths873eb012006-12-06 17:59:07 +00004363 break;
4364 case 11:
ths7a387ff2006-12-06 20:17:30 +00004365 switch (sel) {
4366 case 0:
Andreas Färber7db13fa2012-03-14 01:38:22 +01004367 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Compare));
ths2423f662007-04-11 02:15:08 +00004368 rn = "Compare";
4369 break;
4370 /* 6,7 are implementation dependent */
ths7a387ff2006-12-06 20:17:30 +00004371 default:
4372 goto die;
ths2423f662007-04-11 02:15:08 +00004373 }
ths873eb012006-12-06 17:59:07 +00004374 break;
4375 case 12:
ths7a387ff2006-12-06 20:17:30 +00004376 switch (sel) {
4377 case 0:
Andreas Färber7db13fa2012-03-14 01:38:22 +01004378 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Status));
ths2423f662007-04-11 02:15:08 +00004379 rn = "Status";
4380 break;
ths7a387ff2006-12-06 20:17:30 +00004381 case 1:
Aurelien Jarnod75c1352013-01-01 18:02:22 +01004382 check_insn(ctx, ISA_MIPS32R2);
Andreas Färber7db13fa2012-03-14 01:38:22 +01004383 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_IntCtl));
ths2423f662007-04-11 02:15:08 +00004384 rn = "IntCtl";
4385 break;
ths7a387ff2006-12-06 20:17:30 +00004386 case 2:
Aurelien Jarnod75c1352013-01-01 18:02:22 +01004387 check_insn(ctx, ISA_MIPS32R2);
Andreas Färber7db13fa2012-03-14 01:38:22 +01004388 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSCtl));
ths2423f662007-04-11 02:15:08 +00004389 rn = "SRSCtl";
4390 break;
ths7a387ff2006-12-06 20:17:30 +00004391 case 3:
Aurelien Jarnod75c1352013-01-01 18:02:22 +01004392 check_insn(ctx, ISA_MIPS32R2);
Andreas Färber7db13fa2012-03-14 01:38:22 +01004393 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
ths2423f662007-04-11 02:15:08 +00004394 rn = "SRSMap";
thsfd88b6a2007-05-23 08:24:25 +00004395 break;
ths7a387ff2006-12-06 20:17:30 +00004396 default:
4397 goto die;
4398 }
ths873eb012006-12-06 17:59:07 +00004399 break;
4400 case 13:
ths7a387ff2006-12-06 20:17:30 +00004401 switch (sel) {
4402 case 0:
Andreas Färber7db13fa2012-03-14 01:38:22 +01004403 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Cause));
ths2423f662007-04-11 02:15:08 +00004404 rn = "Cause";
4405 break;
ths7a387ff2006-12-06 20:17:30 +00004406 default:
4407 goto die;
4408 }
ths873eb012006-12-06 17:59:07 +00004409 break;
4410 case 14:
ths7a387ff2006-12-06 20:17:30 +00004411 switch (sel) {
4412 case 0:
Andreas Färber7db13fa2012-03-14 01:38:22 +01004413 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EPC));
aurel32d9bea112009-04-15 14:41:44 +00004414 tcg_gen_ext32s_tl(arg, arg);
ths2423f662007-04-11 02:15:08 +00004415 rn = "EPC";
4416 break;
ths7a387ff2006-12-06 20:17:30 +00004417 default:
4418 goto die;
ths1579a722007-04-05 23:16:25 +00004419 }
ths873eb012006-12-06 17:59:07 +00004420 break;
4421 case 15:
ths7a387ff2006-12-06 20:17:30 +00004422 switch (sel) {
4423 case 0:
Andreas Färber7db13fa2012-03-14 01:38:22 +01004424 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PRid));
ths2423f662007-04-11 02:15:08 +00004425 rn = "PRid";
4426 break;
ths7a387ff2006-12-06 20:17:30 +00004427 case 1:
Aurelien Jarnod75c1352013-01-01 18:02:22 +01004428 check_insn(ctx, ISA_MIPS32R2);
Andreas Färber7db13fa2012-03-14 01:38:22 +01004429 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_EBase));
ths2423f662007-04-11 02:15:08 +00004430 rn = "EBase";
4431 break;
ths7a387ff2006-12-06 20:17:30 +00004432 default:
4433 goto die;
4434 }
ths873eb012006-12-06 17:59:07 +00004435 break;
4436 case 16:
4437 switch (sel) {
4438 case 0:
Andreas Färber7db13fa2012-03-14 01:38:22 +01004439 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config0));
ths873eb012006-12-06 17:59:07 +00004440 rn = "Config";
4441 break;
4442 case 1:
Andreas Färber7db13fa2012-03-14 01:38:22 +01004443 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config1));
ths873eb012006-12-06 17:59:07 +00004444 rn = "Config1";
4445 break;
ths7a387ff2006-12-06 20:17:30 +00004446 case 2:
Andreas Färber7db13fa2012-03-14 01:38:22 +01004447 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config2));
ths7a387ff2006-12-06 20:17:30 +00004448 rn = "Config2";
4449 break;
4450 case 3:
Andreas Färber7db13fa2012-03-14 01:38:22 +01004451 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config3));
ths7a387ff2006-12-06 20:17:30 +00004452 rn = "Config3";
4453 break;
thse397ee32007-03-23 00:43:28 +00004454 /* 4,5 are reserved */
4455 /* 6,7 are implementation dependent */
4456 case 6:
Andreas Färber7db13fa2012-03-14 01:38:22 +01004457 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config6));
thse397ee32007-03-23 00:43:28 +00004458 rn = "Config6";
4459 break;
4460 case 7:
Andreas Färber7db13fa2012-03-14 01:38:22 +01004461 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config7));
thse397ee32007-03-23 00:43:28 +00004462 rn = "Config7";
4463 break;
ths873eb012006-12-06 17:59:07 +00004464 default:
ths873eb012006-12-06 17:59:07 +00004465 goto die;
4466 }
4467 break;
4468 case 17:
ths7a387ff2006-12-06 20:17:30 +00004469 switch (sel) {
4470 case 0:
Blue Swirl895c2d02012-09-02 14:52:59 +00004471 gen_helper_mfc0_lladdr(arg, cpu_env);
ths2423f662007-04-11 02:15:08 +00004472 rn = "LLAddr";
4473 break;
ths7a387ff2006-12-06 20:17:30 +00004474 default:
4475 goto die;
4476 }
ths873eb012006-12-06 17:59:07 +00004477 break;
4478 case 18:
ths7a387ff2006-12-06 20:17:30 +00004479 switch (sel) {
thsfd88b6a2007-05-23 08:24:25 +00004480 case 0 ... 7:
Blue Swirl895c2d02012-09-02 14:52:59 +00004481 gen_helper_1e0i(mfc0_watchlo, arg, sel);
ths2423f662007-04-11 02:15:08 +00004482 rn = "WatchLo";
4483 break;
ths7a387ff2006-12-06 20:17:30 +00004484 default:
4485 goto die;
4486 }
ths873eb012006-12-06 17:59:07 +00004487 break;
4488 case 19:
ths7a387ff2006-12-06 20:17:30 +00004489 switch (sel) {
thsfd88b6a2007-05-23 08:24:25 +00004490 case 0 ...7:
Blue Swirl895c2d02012-09-02 14:52:59 +00004491 gen_helper_1e0i(mfc0_watchhi, arg, sel);
ths2423f662007-04-11 02:15:08 +00004492 rn = "WatchHi";
4493 break;
ths7a387ff2006-12-06 20:17:30 +00004494 default:
4495 goto die;
4496 }
ths873eb012006-12-06 17:59:07 +00004497 break;
ths8c0fdd82006-12-06 18:19:33 +00004498 case 20:
ths7a387ff2006-12-06 20:17:30 +00004499 switch (sel) {
4500 case 0:
thsd26bc212007-11-08 18:05:37 +00004501#if defined(TARGET_MIPS64)
Aurelien Jarnod75c1352013-01-01 18:02:22 +01004502 check_insn(ctx, ISA_MIPS3);
Andreas Färber7db13fa2012-03-14 01:38:22 +01004503 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_XContext));
aurel32d9bea112009-04-15 14:41:44 +00004504 tcg_gen_ext32s_tl(arg, arg);
ths2423f662007-04-11 02:15:08 +00004505 rn = "XContext";
4506 break;
ths703eaf32007-05-13 14:42:18 +00004507#endif
ths7a387ff2006-12-06 20:17:30 +00004508 default:
4509 goto die;
4510 }
ths8c0fdd82006-12-06 18:19:33 +00004511 break;
4512 case 21:
ths7a387ff2006-12-06 20:17:30 +00004513 /* Officially reserved, but sel 0 is used for R1x000 framemask */
4514 switch (sel) {
4515 case 0:
Andreas Färber7db13fa2012-03-14 01:38:22 +01004516 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Framemask));
ths2423f662007-04-11 02:15:08 +00004517 rn = "Framemask";
4518 break;
ths7a387ff2006-12-06 20:17:30 +00004519 default:
4520 goto die;
4521 }
ths8c0fdd82006-12-06 18:19:33 +00004522 break;
4523 case 22:
aurel32d9bea112009-04-15 14:41:44 +00004524 tcg_gen_movi_tl(arg, 0); /* unimplemented */
ths2423f662007-04-11 02:15:08 +00004525 rn = "'Diagnostic"; /* implementation dependent */
4526 break;
ths873eb012006-12-06 17:59:07 +00004527 case 23:
ths7a387ff2006-12-06 20:17:30 +00004528 switch (sel) {
4529 case 0:
Blue Swirl895c2d02012-09-02 14:52:59 +00004530 gen_helper_mfc0_debug(arg, cpu_env); /* EJTAG support */
ths2423f662007-04-11 02:15:08 +00004531 rn = "Debug";
4532 break;
ths7a387ff2006-12-06 20:17:30 +00004533 case 1:
aurel32d9bea112009-04-15 14:41:44 +00004534// gen_helper_mfc0_tracecontrol(arg); /* PDtrace support */
ths2423f662007-04-11 02:15:08 +00004535 rn = "TraceControl";
4536// break;
ths7a387ff2006-12-06 20:17:30 +00004537 case 2:
aurel32d9bea112009-04-15 14:41:44 +00004538// gen_helper_mfc0_tracecontrol2(arg); /* PDtrace support */
ths2423f662007-04-11 02:15:08 +00004539 rn = "TraceControl2";
4540// break;
ths7a387ff2006-12-06 20:17:30 +00004541 case 3:
aurel32d9bea112009-04-15 14:41:44 +00004542// gen_helper_mfc0_usertracedata(arg); /* PDtrace support */
ths2423f662007-04-11 02:15:08 +00004543 rn = "UserTraceData";
4544// break;
ths7a387ff2006-12-06 20:17:30 +00004545 case 4:
aurel32d9bea112009-04-15 14:41:44 +00004546// gen_helper_mfc0_tracebpc(arg); /* PDtrace support */
ths2423f662007-04-11 02:15:08 +00004547 rn = "TraceBPC";
4548// break;
ths7a387ff2006-12-06 20:17:30 +00004549 default:
4550 goto die;
4551 }
ths873eb012006-12-06 17:59:07 +00004552 break;
4553 case 24:
ths7a387ff2006-12-06 20:17:30 +00004554 switch (sel) {
4555 case 0:
thsf0b3f3a2008-05-23 18:10:51 +00004556 /* EJTAG support */
Andreas Färber7db13fa2012-03-14 01:38:22 +01004557 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_DEPC));
aurel32d9bea112009-04-15 14:41:44 +00004558 tcg_gen_ext32s_tl(arg, arg);
ths2423f662007-04-11 02:15:08 +00004559 rn = "DEPC";
4560 break;
ths7a387ff2006-12-06 20:17:30 +00004561 default:
4562 goto die;
4563 }
ths873eb012006-12-06 17:59:07 +00004564 break;
ths8c0fdd82006-12-06 18:19:33 +00004565 case 25:
ths7a387ff2006-12-06 20:17:30 +00004566 switch (sel) {
4567 case 0:
Andreas Färber7db13fa2012-03-14 01:38:22 +01004568 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Performance0));
ths2423f662007-04-11 02:15:08 +00004569 rn = "Performance0";
ths7a387ff2006-12-06 20:17:30 +00004570 break;
4571 case 1:
aurel32d9bea112009-04-15 14:41:44 +00004572// gen_helper_mfc0_performance1(arg);
ths2423f662007-04-11 02:15:08 +00004573 rn = "Performance1";
4574// break;
ths7a387ff2006-12-06 20:17:30 +00004575 case 2:
aurel32d9bea112009-04-15 14:41:44 +00004576// gen_helper_mfc0_performance2(arg);
ths2423f662007-04-11 02:15:08 +00004577 rn = "Performance2";
4578// break;
ths7a387ff2006-12-06 20:17:30 +00004579 case 3:
aurel32d9bea112009-04-15 14:41:44 +00004580// gen_helper_mfc0_performance3(arg);
ths2423f662007-04-11 02:15:08 +00004581 rn = "Performance3";
4582// break;
ths7a387ff2006-12-06 20:17:30 +00004583 case 4:
aurel32d9bea112009-04-15 14:41:44 +00004584// gen_helper_mfc0_performance4(arg);
ths2423f662007-04-11 02:15:08 +00004585 rn = "Performance4";
4586// break;
ths7a387ff2006-12-06 20:17:30 +00004587 case 5:
aurel32d9bea112009-04-15 14:41:44 +00004588// gen_helper_mfc0_performance5(arg);
ths2423f662007-04-11 02:15:08 +00004589 rn = "Performance5";
4590// break;
ths7a387ff2006-12-06 20:17:30 +00004591 case 6:
aurel32d9bea112009-04-15 14:41:44 +00004592// gen_helper_mfc0_performance6(arg);
ths2423f662007-04-11 02:15:08 +00004593 rn = "Performance6";
4594// break;
ths7a387ff2006-12-06 20:17:30 +00004595 case 7:
aurel32d9bea112009-04-15 14:41:44 +00004596// gen_helper_mfc0_performance7(arg);
ths2423f662007-04-11 02:15:08 +00004597 rn = "Performance7";
4598// break;
ths7a387ff2006-12-06 20:17:30 +00004599 default:
4600 goto die;
4601 }
ths8c0fdd82006-12-06 18:19:33 +00004602 break;
4603 case 26:
aurel32d9bea112009-04-15 14:41:44 +00004604 tcg_gen_movi_tl(arg, 0); /* unimplemented */
aurel32da806822008-11-15 12:12:08 +00004605 rn = "ECC";
4606 break;
ths8c0fdd82006-12-06 18:19:33 +00004607 case 27:
ths7a387ff2006-12-06 20:17:30 +00004608 switch (sel) {
ths7a387ff2006-12-06 20:17:30 +00004609 case 0 ... 3:
aurel32d9bea112009-04-15 14:41:44 +00004610 tcg_gen_movi_tl(arg, 0); /* unimplemented */
ths2423f662007-04-11 02:15:08 +00004611 rn = "CacheErr";
4612 break;
ths7a387ff2006-12-06 20:17:30 +00004613 default:
4614 goto die;
4615 }
ths8c0fdd82006-12-06 18:19:33 +00004616 break;
ths873eb012006-12-06 17:59:07 +00004617 case 28:
4618 switch (sel) {
4619 case 0:
ths7a387ff2006-12-06 20:17:30 +00004620 case 2:
4621 case 4:
4622 case 6:
Andreas Färber7db13fa2012-03-14 01:38:22 +01004623 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_TagLo));
ths873eb012006-12-06 17:59:07 +00004624 rn = "TagLo";
4625 break;
4626 case 1:
ths7a387ff2006-12-06 20:17:30 +00004627 case 3:
4628 case 5:
4629 case 7:
Andreas Färber7db13fa2012-03-14 01:38:22 +01004630 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataLo));
ths873eb012006-12-06 17:59:07 +00004631 rn = "DataLo";
4632 break;
4633 default:
ths873eb012006-12-06 17:59:07 +00004634 goto die;
4635 }
4636 break;
ths8c0fdd82006-12-06 18:19:33 +00004637 case 29:
ths7a387ff2006-12-06 20:17:30 +00004638 switch (sel) {
4639 case 0:
4640 case 2:
4641 case 4:
4642 case 6:
Andreas Färber7db13fa2012-03-14 01:38:22 +01004643 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_TagHi));
ths7a387ff2006-12-06 20:17:30 +00004644 rn = "TagHi";
4645 break;
4646 case 1:
4647 case 3:
4648 case 5:
4649 case 7:
Andreas Färber7db13fa2012-03-14 01:38:22 +01004650 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataHi));
ths7a387ff2006-12-06 20:17:30 +00004651 rn = "DataHi";
4652 break;
4653 default:
4654 goto die;
4655 }
ths8c0fdd82006-12-06 18:19:33 +00004656 break;
ths873eb012006-12-06 17:59:07 +00004657 case 30:
ths7a387ff2006-12-06 20:17:30 +00004658 switch (sel) {
4659 case 0:
Andreas Färber7db13fa2012-03-14 01:38:22 +01004660 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_ErrorEPC));
aurel32d9bea112009-04-15 14:41:44 +00004661 tcg_gen_ext32s_tl(arg, arg);
ths2423f662007-04-11 02:15:08 +00004662 rn = "ErrorEPC";
4663 break;
ths7a387ff2006-12-06 20:17:30 +00004664 default:
4665 goto die;
4666 }
ths873eb012006-12-06 17:59:07 +00004667 break;
4668 case 31:
ths7a387ff2006-12-06 20:17:30 +00004669 switch (sel) {
4670 case 0:
thsf0b3f3a2008-05-23 18:10:51 +00004671 /* EJTAG support */
Andreas Färber7db13fa2012-03-14 01:38:22 +01004672 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
ths2423f662007-04-11 02:15:08 +00004673 rn = "DESAVE";
4674 break;
ths7a387ff2006-12-06 20:17:30 +00004675 default:
4676 goto die;
4677 }
ths873eb012006-12-06 17:59:07 +00004678 break;
4679 default:
ths873eb012006-12-06 17:59:07 +00004680 goto die;
4681 }
Blue Swirl2abf3142010-10-13 18:38:08 +00004682 (void)rn; /* avoid a compiler warning */
aliguorid12d51d2009-01-15 21:48:06 +00004683 LOG_DISAS("mfc0 %s (reg %d sel %d)\n", rn, reg, sel);
ths873eb012006-12-06 17:59:07 +00004684 return;
4685
4686die:
aliguorid12d51d2009-01-15 21:48:06 +00004687 LOG_DISAS("mfc0 %s (reg %d sel %d)\n", rn, reg, sel);
ths873eb012006-12-06 17:59:07 +00004688 generate_exception(ctx, EXCP_RI);
4689}
4690
Aurelien Jarnod75c1352013-01-01 18:02:22 +01004691static void gen_mtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
ths8c0fdd82006-12-06 18:19:33 +00004692{
ths7a387ff2006-12-06 20:17:30 +00004693 const char *rn = "invalid";
ths8c0fdd82006-12-06 18:19:33 +00004694
thse189e742007-09-24 12:48:00 +00004695 if (sel != 0)
Aurelien Jarnod75c1352013-01-01 18:02:22 +01004696 check_insn(ctx, ISA_MIPS32);
thse189e742007-09-24 12:48:00 +00004697
pbrook2e70f6e2008-06-29 01:03:05 +00004698 if (use_icount)
4699 gen_io_start();
4700
ths8c0fdd82006-12-06 18:19:33 +00004701 switch (reg) {
4702 case 0:
ths7a387ff2006-12-06 20:17:30 +00004703 switch (sel) {
4704 case 0:
Blue Swirl895c2d02012-09-02 14:52:59 +00004705 gen_helper_mtc0_index(cpu_env, arg);
ths7a387ff2006-12-06 20:17:30 +00004706 rn = "Index";
4707 break;
4708 case 1:
Aurelien Jarnod75c1352013-01-01 18:02:22 +01004709 check_insn(ctx, ASE_MT);
Blue Swirl895c2d02012-09-02 14:52:59 +00004710 gen_helper_mtc0_mvpcontrol(cpu_env, arg);
ths7a387ff2006-12-06 20:17:30 +00004711 rn = "MVPControl";
thsead93602007-09-06 00:18:15 +00004712 break;
ths7a387ff2006-12-06 20:17:30 +00004713 case 2:
Aurelien Jarnod75c1352013-01-01 18:02:22 +01004714 check_insn(ctx, ASE_MT);
thsead93602007-09-06 00:18:15 +00004715 /* ignored */
ths7a387ff2006-12-06 20:17:30 +00004716 rn = "MVPConf0";
thsead93602007-09-06 00:18:15 +00004717 break;
ths7a387ff2006-12-06 20:17:30 +00004718 case 3:
Aurelien Jarnod75c1352013-01-01 18:02:22 +01004719 check_insn(ctx, ASE_MT);
thsead93602007-09-06 00:18:15 +00004720 /* ignored */
ths7a387ff2006-12-06 20:17:30 +00004721 rn = "MVPConf1";
thsead93602007-09-06 00:18:15 +00004722 break;
ths7a387ff2006-12-06 20:17:30 +00004723 default:
4724 goto die;
4725 }
ths8c0fdd82006-12-06 18:19:33 +00004726 break;
4727 case 1:
ths7a387ff2006-12-06 20:17:30 +00004728 switch (sel) {
4729 case 0:
ths2423f662007-04-11 02:15:08 +00004730 /* ignored */
ths7a387ff2006-12-06 20:17:30 +00004731 rn = "Random";
ths2423f662007-04-11 02:15:08 +00004732 break;
ths7a387ff2006-12-06 20:17:30 +00004733 case 1:
Aurelien Jarnod75c1352013-01-01 18:02:22 +01004734 check_insn(ctx, ASE_MT);
Blue Swirl895c2d02012-09-02 14:52:59 +00004735 gen_helper_mtc0_vpecontrol(cpu_env, arg);
ths7a387ff2006-12-06 20:17:30 +00004736 rn = "VPEControl";
thsead93602007-09-06 00:18:15 +00004737 break;
ths7a387ff2006-12-06 20:17:30 +00004738 case 2:
Aurelien Jarnod75c1352013-01-01 18:02:22 +01004739 check_insn(ctx, ASE_MT);
Blue Swirl895c2d02012-09-02 14:52:59 +00004740 gen_helper_mtc0_vpeconf0(cpu_env, arg);
ths7a387ff2006-12-06 20:17:30 +00004741 rn = "VPEConf0";
thsead93602007-09-06 00:18:15 +00004742 break;
ths7a387ff2006-12-06 20:17:30 +00004743 case 3:
Aurelien Jarnod75c1352013-01-01 18:02:22 +01004744 check_insn(ctx, ASE_MT);
Blue Swirl895c2d02012-09-02 14:52:59 +00004745 gen_helper_mtc0_vpeconf1(cpu_env, arg);
ths7a387ff2006-12-06 20:17:30 +00004746 rn = "VPEConf1";
thsead93602007-09-06 00:18:15 +00004747 break;
ths7a387ff2006-12-06 20:17:30 +00004748 case 4:
Aurelien Jarnod75c1352013-01-01 18:02:22 +01004749 check_insn(ctx, ASE_MT);
Blue Swirl895c2d02012-09-02 14:52:59 +00004750 gen_helper_mtc0_yqmask(cpu_env, arg);
ths7a387ff2006-12-06 20:17:30 +00004751 rn = "YQMask";
thsead93602007-09-06 00:18:15 +00004752 break;
ths7a387ff2006-12-06 20:17:30 +00004753 case 5:
Aurelien Jarnod75c1352013-01-01 18:02:22 +01004754 check_insn(ctx, ASE_MT);
Andreas Färber7db13fa2012-03-14 01:38:22 +01004755 gen_mtc0_store64(arg, offsetof(CPUMIPSState, CP0_VPESchedule));
ths7a387ff2006-12-06 20:17:30 +00004756 rn = "VPESchedule";
thsead93602007-09-06 00:18:15 +00004757 break;
ths7a387ff2006-12-06 20:17:30 +00004758 case 6:
Aurelien Jarnod75c1352013-01-01 18:02:22 +01004759 check_insn(ctx, ASE_MT);
Andreas Färber7db13fa2012-03-14 01:38:22 +01004760 gen_mtc0_store64(arg, offsetof(CPUMIPSState, CP0_VPEScheFBack));
ths7a387ff2006-12-06 20:17:30 +00004761 rn = "VPEScheFBack";
thsead93602007-09-06 00:18:15 +00004762 break;
ths7a387ff2006-12-06 20:17:30 +00004763 case 7:
Aurelien Jarnod75c1352013-01-01 18:02:22 +01004764 check_insn(ctx, ASE_MT);
Blue Swirl895c2d02012-09-02 14:52:59 +00004765 gen_helper_mtc0_vpeopt(cpu_env, arg);
ths7a387ff2006-12-06 20:17:30 +00004766 rn = "VPEOpt";
thsead93602007-09-06 00:18:15 +00004767 break;
ths7a387ff2006-12-06 20:17:30 +00004768 default:
4769 goto die;
4770 }
ths8c0fdd82006-12-06 18:19:33 +00004771 break;
4772 case 2:
ths7a387ff2006-12-06 20:17:30 +00004773 switch (sel) {
4774 case 0:
Blue Swirl895c2d02012-09-02 14:52:59 +00004775 gen_helper_mtc0_entrylo0(cpu_env, arg);
ths2423f662007-04-11 02:15:08 +00004776 rn = "EntryLo0";
4777 break;
ths7a387ff2006-12-06 20:17:30 +00004778 case 1:
Aurelien Jarnod75c1352013-01-01 18:02:22 +01004779 check_insn(ctx, ASE_MT);
Blue Swirl895c2d02012-09-02 14:52:59 +00004780 gen_helper_mtc0_tcstatus(cpu_env, arg);
ths2423f662007-04-11 02:15:08 +00004781 rn = "TCStatus";
thsead93602007-09-06 00:18:15 +00004782 break;
ths7a387ff2006-12-06 20:17:30 +00004783 case 2:
Aurelien Jarnod75c1352013-01-01 18:02:22 +01004784 check_insn(ctx, ASE_MT);
Blue Swirl895c2d02012-09-02 14:52:59 +00004785 gen_helper_mtc0_tcbind(cpu_env, arg);
ths2423f662007-04-11 02:15:08 +00004786 rn = "TCBind";
thsead93602007-09-06 00:18:15 +00004787 break;
ths7a387ff2006-12-06 20:17:30 +00004788 case 3:
Aurelien Jarnod75c1352013-01-01 18:02:22 +01004789 check_insn(ctx, ASE_MT);
Blue Swirl895c2d02012-09-02 14:52:59 +00004790 gen_helper_mtc0_tcrestart(cpu_env, arg);
ths2423f662007-04-11 02:15:08 +00004791 rn = "TCRestart";
thsead93602007-09-06 00:18:15 +00004792 break;
ths7a387ff2006-12-06 20:17:30 +00004793 case 4:
Aurelien Jarnod75c1352013-01-01 18:02:22 +01004794 check_insn(ctx, ASE_MT);
Blue Swirl895c2d02012-09-02 14:52:59 +00004795 gen_helper_mtc0_tchalt(cpu_env, arg);
ths2423f662007-04-11 02:15:08 +00004796 rn = "TCHalt";
thsead93602007-09-06 00:18:15 +00004797 break;
ths7a387ff2006-12-06 20:17:30 +00004798 case 5:
Aurelien Jarnod75c1352013-01-01 18:02:22 +01004799 check_insn(ctx, ASE_MT);
Blue Swirl895c2d02012-09-02 14:52:59 +00004800 gen_helper_mtc0_tccontext(cpu_env, arg);
ths2423f662007-04-11 02:15:08 +00004801 rn = "TCContext";
thsead93602007-09-06 00:18:15 +00004802 break;
ths7a387ff2006-12-06 20:17:30 +00004803 case 6:
Aurelien Jarnod75c1352013-01-01 18:02:22 +01004804 check_insn(ctx, ASE_MT);
Blue Swirl895c2d02012-09-02 14:52:59 +00004805 gen_helper_mtc0_tcschedule(cpu_env, arg);
ths2423f662007-04-11 02:15:08 +00004806 rn = "TCSchedule";
thsead93602007-09-06 00:18:15 +00004807 break;
ths7a387ff2006-12-06 20:17:30 +00004808 case 7:
Aurelien Jarnod75c1352013-01-01 18:02:22 +01004809 check_insn(ctx, ASE_MT);
Blue Swirl895c2d02012-09-02 14:52:59 +00004810 gen_helper_mtc0_tcschefback(cpu_env, arg);
ths2423f662007-04-11 02:15:08 +00004811 rn = "TCScheFBack";
thsead93602007-09-06 00:18:15 +00004812 break;
ths7a387ff2006-12-06 20:17:30 +00004813 default:
4814 goto die;
4815 }
ths8c0fdd82006-12-06 18:19:33 +00004816 break;
4817 case 3:
ths7a387ff2006-12-06 20:17:30 +00004818 switch (sel) {
4819 case 0:
Blue Swirl895c2d02012-09-02 14:52:59 +00004820 gen_helper_mtc0_entrylo1(cpu_env, arg);
ths2423f662007-04-11 02:15:08 +00004821 rn = "EntryLo1";
4822 break;
ths7a387ff2006-12-06 20:17:30 +00004823 default:
4824 goto die;
ths876d4b02007-04-04 21:07:17 +00004825 }
ths8c0fdd82006-12-06 18:19:33 +00004826 break;
4827 case 4:
ths7a387ff2006-12-06 20:17:30 +00004828 switch (sel) {
4829 case 0:
Blue Swirl895c2d02012-09-02 14:52:59 +00004830 gen_helper_mtc0_context(cpu_env, arg);
ths2423f662007-04-11 02:15:08 +00004831 rn = "Context";
4832 break;
ths7a387ff2006-12-06 20:17:30 +00004833 case 1:
Blue Swirl895c2d02012-09-02 14:52:59 +00004834// gen_helper_mtc0_contextconfig(cpu_env, arg); /* SmartMIPS ASE */
ths2423f662007-04-11 02:15:08 +00004835 rn = "ContextConfig";
4836// break;
ths7a387ff2006-12-06 20:17:30 +00004837 default:
4838 goto die;
ths876d4b02007-04-04 21:07:17 +00004839 }
ths8c0fdd82006-12-06 18:19:33 +00004840 break;
4841 case 5:
ths7a387ff2006-12-06 20:17:30 +00004842 switch (sel) {
4843 case 0:
Blue Swirl895c2d02012-09-02 14:52:59 +00004844 gen_helper_mtc0_pagemask(cpu_env, arg);
ths2423f662007-04-11 02:15:08 +00004845 rn = "PageMask";
4846 break;
ths7a387ff2006-12-06 20:17:30 +00004847 case 1:
Aurelien Jarnod75c1352013-01-01 18:02:22 +01004848 check_insn(ctx, ISA_MIPS32R2);
Blue Swirl895c2d02012-09-02 14:52:59 +00004849 gen_helper_mtc0_pagegrain(cpu_env, arg);
ths2423f662007-04-11 02:15:08 +00004850 rn = "PageGrain";
4851 break;
ths7a387ff2006-12-06 20:17:30 +00004852 default:
4853 goto die;
ths876d4b02007-04-04 21:07:17 +00004854 }
ths8c0fdd82006-12-06 18:19:33 +00004855 break;
4856 case 6:
ths7a387ff2006-12-06 20:17:30 +00004857 switch (sel) {
4858 case 0:
Blue Swirl895c2d02012-09-02 14:52:59 +00004859 gen_helper_mtc0_wired(cpu_env, arg);
ths2423f662007-04-11 02:15:08 +00004860 rn = "Wired";
4861 break;
ths7a387ff2006-12-06 20:17:30 +00004862 case 1:
Aurelien Jarnod75c1352013-01-01 18:02:22 +01004863 check_insn(ctx, ISA_MIPS32R2);
Blue Swirl895c2d02012-09-02 14:52:59 +00004864 gen_helper_mtc0_srsconf0(cpu_env, arg);
ths2423f662007-04-11 02:15:08 +00004865 rn = "SRSConf0";
thsead93602007-09-06 00:18:15 +00004866 break;
ths7a387ff2006-12-06 20:17:30 +00004867 case 2:
Aurelien Jarnod75c1352013-01-01 18:02:22 +01004868 check_insn(ctx, ISA_MIPS32R2);
Blue Swirl895c2d02012-09-02 14:52:59 +00004869 gen_helper_mtc0_srsconf1(cpu_env, arg);
ths2423f662007-04-11 02:15:08 +00004870 rn = "SRSConf1";
thsead93602007-09-06 00:18:15 +00004871 break;
ths7a387ff2006-12-06 20:17:30 +00004872 case 3:
Aurelien Jarnod75c1352013-01-01 18:02:22 +01004873 check_insn(ctx, ISA_MIPS32R2);
Blue Swirl895c2d02012-09-02 14:52:59 +00004874 gen_helper_mtc0_srsconf2(cpu_env, arg);
ths2423f662007-04-11 02:15:08 +00004875 rn = "SRSConf2";
thsead93602007-09-06 00:18:15 +00004876 break;
ths7a387ff2006-12-06 20:17:30 +00004877 case 4:
Aurelien Jarnod75c1352013-01-01 18:02:22 +01004878 check_insn(ctx, ISA_MIPS32R2);
Blue Swirl895c2d02012-09-02 14:52:59 +00004879 gen_helper_mtc0_srsconf3(cpu_env, arg);
ths2423f662007-04-11 02:15:08 +00004880 rn = "SRSConf3";
thsead93602007-09-06 00:18:15 +00004881 break;
ths7a387ff2006-12-06 20:17:30 +00004882 case 5:
Aurelien Jarnod75c1352013-01-01 18:02:22 +01004883 check_insn(ctx, ISA_MIPS32R2);
Blue Swirl895c2d02012-09-02 14:52:59 +00004884 gen_helper_mtc0_srsconf4(cpu_env, arg);
ths2423f662007-04-11 02:15:08 +00004885 rn = "SRSConf4";
thsead93602007-09-06 00:18:15 +00004886 break;
ths7a387ff2006-12-06 20:17:30 +00004887 default:
4888 goto die;
ths876d4b02007-04-04 21:07:17 +00004889 }
ths8c0fdd82006-12-06 18:19:33 +00004890 break;
4891 case 7:
ths7a387ff2006-12-06 20:17:30 +00004892 switch (sel) {
4893 case 0:
Aurelien Jarnod75c1352013-01-01 18:02:22 +01004894 check_insn(ctx, ISA_MIPS32R2);
Blue Swirl895c2d02012-09-02 14:52:59 +00004895 gen_helper_mtc0_hwrena(cpu_env, arg);
ths2423f662007-04-11 02:15:08 +00004896 rn = "HWREna";
4897 break;
ths7a387ff2006-12-06 20:17:30 +00004898 default:
4899 goto die;
ths876d4b02007-04-04 21:07:17 +00004900 }
ths8c0fdd82006-12-06 18:19:33 +00004901 break;
4902 case 8:
ths7a387ff2006-12-06 20:17:30 +00004903 /* ignored */
thsf0b3f3a2008-05-23 18:10:51 +00004904 rn = "BadVAddr";
ths8c0fdd82006-12-06 18:19:33 +00004905 break;
4906 case 9:
ths7a387ff2006-12-06 20:17:30 +00004907 switch (sel) {
4908 case 0:
Blue Swirl895c2d02012-09-02 14:52:59 +00004909 gen_helper_mtc0_count(cpu_env, arg);
ths2423f662007-04-11 02:15:08 +00004910 rn = "Count";
4911 break;
ths876d4b02007-04-04 21:07:17 +00004912 /* 6,7 are implementation dependent */
ths7a387ff2006-12-06 20:17:30 +00004913 default:
4914 goto die;
ths876d4b02007-04-04 21:07:17 +00004915 }
ths8c0fdd82006-12-06 18:19:33 +00004916 break;
4917 case 10:
ths7a387ff2006-12-06 20:17:30 +00004918 switch (sel) {
4919 case 0:
Blue Swirl895c2d02012-09-02 14:52:59 +00004920 gen_helper_mtc0_entryhi(cpu_env, arg);
ths2423f662007-04-11 02:15:08 +00004921 rn = "EntryHi";
4922 break;
ths7a387ff2006-12-06 20:17:30 +00004923 default:
4924 goto die;
ths876d4b02007-04-04 21:07:17 +00004925 }
ths8c0fdd82006-12-06 18:19:33 +00004926 break;
4927 case 11:
ths7a387ff2006-12-06 20:17:30 +00004928 switch (sel) {
4929 case 0:
Blue Swirl895c2d02012-09-02 14:52:59 +00004930 gen_helper_mtc0_compare(cpu_env, arg);
ths2423f662007-04-11 02:15:08 +00004931 rn = "Compare";
4932 break;
4933 /* 6,7 are implementation dependent */
ths7a387ff2006-12-06 20:17:30 +00004934 default:
4935 goto die;
ths876d4b02007-04-04 21:07:17 +00004936 }
ths8c0fdd82006-12-06 18:19:33 +00004937 break;
4938 case 12:
ths7a387ff2006-12-06 20:17:30 +00004939 switch (sel) {
4940 case 0:
aurel32867abc72009-04-13 08:53:12 +00004941 save_cpu_state(ctx, 1);
Blue Swirl895c2d02012-09-02 14:52:59 +00004942 gen_helper_mtc0_status(cpu_env, arg);
ths84873272007-06-01 17:47:07 +00004943 /* BS_STOP isn't good enough here, hflags may have changed. */
4944 gen_save_pc(ctx->pc + 4);
4945 ctx->bstate = BS_EXCP;
ths2423f662007-04-11 02:15:08 +00004946 rn = "Status";
4947 break;
ths7a387ff2006-12-06 20:17:30 +00004948 case 1:
Aurelien Jarnod75c1352013-01-01 18:02:22 +01004949 check_insn(ctx, ISA_MIPS32R2);
Blue Swirl895c2d02012-09-02 14:52:59 +00004950 gen_helper_mtc0_intctl(cpu_env, arg);
ths84873272007-06-01 17:47:07 +00004951 /* Stop translation as we may have switched the execution mode */
4952 ctx->bstate = BS_STOP;
ths2423f662007-04-11 02:15:08 +00004953 rn = "IntCtl";
4954 break;
ths7a387ff2006-12-06 20:17:30 +00004955 case 2:
Aurelien Jarnod75c1352013-01-01 18:02:22 +01004956 check_insn(ctx, ISA_MIPS32R2);
Blue Swirl895c2d02012-09-02 14:52:59 +00004957 gen_helper_mtc0_srsctl(cpu_env, arg);
ths84873272007-06-01 17:47:07 +00004958 /* Stop translation as we may have switched the execution mode */
4959 ctx->bstate = BS_STOP;
ths2423f662007-04-11 02:15:08 +00004960 rn = "SRSCtl";
4961 break;
ths7a387ff2006-12-06 20:17:30 +00004962 case 3:
Aurelien Jarnod75c1352013-01-01 18:02:22 +01004963 check_insn(ctx, ISA_MIPS32R2);
Andreas Färber7db13fa2012-03-14 01:38:22 +01004964 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
ths84873272007-06-01 17:47:07 +00004965 /* Stop translation as we may have switched the execution mode */
4966 ctx->bstate = BS_STOP;
ths2423f662007-04-11 02:15:08 +00004967 rn = "SRSMap";
thsfd88b6a2007-05-23 08:24:25 +00004968 break;
ths7a387ff2006-12-06 20:17:30 +00004969 default:
4970 goto die;
ths876d4b02007-04-04 21:07:17 +00004971 }
ths8c0fdd82006-12-06 18:19:33 +00004972 break;
4973 case 13:
ths7a387ff2006-12-06 20:17:30 +00004974 switch (sel) {
4975 case 0:
aurel32867abc72009-04-13 08:53:12 +00004976 save_cpu_state(ctx, 1);
Blue Swirl895c2d02012-09-02 14:52:59 +00004977 gen_helper_mtc0_cause(cpu_env, arg);
ths2423f662007-04-11 02:15:08 +00004978 rn = "Cause";
4979 break;
ths7a387ff2006-12-06 20:17:30 +00004980 default:
4981 goto die;
ths876d4b02007-04-04 21:07:17 +00004982 }
ths8c0fdd82006-12-06 18:19:33 +00004983 break;
4984 case 14:
ths7a387ff2006-12-06 20:17:30 +00004985 switch (sel) {
4986 case 0:
Andreas Färber7db13fa2012-03-14 01:38:22 +01004987 gen_mtc0_store64(arg, offsetof(CPUMIPSState, CP0_EPC));
ths2423f662007-04-11 02:15:08 +00004988 rn = "EPC";
4989 break;
ths7a387ff2006-12-06 20:17:30 +00004990 default:
4991 goto die;
ths876d4b02007-04-04 21:07:17 +00004992 }
ths8c0fdd82006-12-06 18:19:33 +00004993 break;
4994 case 15:
ths7a387ff2006-12-06 20:17:30 +00004995 switch (sel) {
4996 case 0:
ths2423f662007-04-11 02:15:08 +00004997 /* ignored */
4998 rn = "PRid";
4999 break;
ths7a387ff2006-12-06 20:17:30 +00005000 case 1:
Aurelien Jarnod75c1352013-01-01 18:02:22 +01005001 check_insn(ctx, ISA_MIPS32R2);
Blue Swirl895c2d02012-09-02 14:52:59 +00005002 gen_helper_mtc0_ebase(cpu_env, arg);
ths2423f662007-04-11 02:15:08 +00005003 rn = "EBase";
5004 break;
ths7a387ff2006-12-06 20:17:30 +00005005 default:
5006 goto die;
ths1579a722007-04-05 23:16:25 +00005007 }
ths8c0fdd82006-12-06 18:19:33 +00005008 break;
5009 case 16:
5010 switch (sel) {
5011 case 0:
Blue Swirl895c2d02012-09-02 14:52:59 +00005012 gen_helper_mtc0_config0(cpu_env, arg);
ths7a387ff2006-12-06 20:17:30 +00005013 rn = "Config";
ths2423f662007-04-11 02:15:08 +00005014 /* Stop translation as we may have switched the execution mode */
5015 ctx->bstate = BS_STOP;
ths8c0fdd82006-12-06 18:19:33 +00005016 break;
ths7a387ff2006-12-06 20:17:30 +00005017 case 1:
thse397ee32007-03-23 00:43:28 +00005018 /* ignored, read only */
ths7a387ff2006-12-06 20:17:30 +00005019 rn = "Config1";
5020 break;
5021 case 2:
Blue Swirl895c2d02012-09-02 14:52:59 +00005022 gen_helper_mtc0_config2(cpu_env, arg);
ths7a387ff2006-12-06 20:17:30 +00005023 rn = "Config2";
ths2423f662007-04-11 02:15:08 +00005024 /* Stop translation as we may have switched the execution mode */
5025 ctx->bstate = BS_STOP;
ths7a387ff2006-12-06 20:17:30 +00005026 break;
5027 case 3:
thse397ee32007-03-23 00:43:28 +00005028 /* ignored, read only */
ths7a387ff2006-12-06 20:17:30 +00005029 rn = "Config3";
5030 break;
thse397ee32007-03-23 00:43:28 +00005031 /* 4,5 are reserved */
5032 /* 6,7 are implementation dependent */
5033 case 6:
5034 /* ignored */
5035 rn = "Config6";
5036 break;
5037 case 7:
5038 /* ignored */
5039 rn = "Config7";
5040 break;
ths8c0fdd82006-12-06 18:19:33 +00005041 default:
5042 rn = "Invalid config selector";
5043 goto die;
5044 }
5045 break;
5046 case 17:
ths7a387ff2006-12-06 20:17:30 +00005047 switch (sel) {
5048 case 0:
Blue Swirl895c2d02012-09-02 14:52:59 +00005049 gen_helper_mtc0_lladdr(cpu_env, arg);
ths2423f662007-04-11 02:15:08 +00005050 rn = "LLAddr";
5051 break;
ths7a387ff2006-12-06 20:17:30 +00005052 default:
5053 goto die;
5054 }
ths8c0fdd82006-12-06 18:19:33 +00005055 break;
5056 case 18:
ths7a387ff2006-12-06 20:17:30 +00005057 switch (sel) {
thsfd88b6a2007-05-23 08:24:25 +00005058 case 0 ... 7:
Blue Swirl895c2d02012-09-02 14:52:59 +00005059 gen_helper_0e1i(mtc0_watchlo, arg, sel);
ths2423f662007-04-11 02:15:08 +00005060 rn = "WatchLo";
5061 break;
ths7a387ff2006-12-06 20:17:30 +00005062 default:
5063 goto die;
5064 }
ths8c0fdd82006-12-06 18:19:33 +00005065 break;
5066 case 19:
ths7a387ff2006-12-06 20:17:30 +00005067 switch (sel) {
thsfd88b6a2007-05-23 08:24:25 +00005068 case 0 ... 7:
Blue Swirl895c2d02012-09-02 14:52:59 +00005069 gen_helper_0e1i(mtc0_watchhi, arg, sel);
ths2423f662007-04-11 02:15:08 +00005070 rn = "WatchHi";
5071 break;
ths7a387ff2006-12-06 20:17:30 +00005072 default:
5073 goto die;
5074 }
ths8c0fdd82006-12-06 18:19:33 +00005075 break;
5076 case 20:
ths7a387ff2006-12-06 20:17:30 +00005077 switch (sel) {
5078 case 0:
thsd26bc212007-11-08 18:05:37 +00005079#if defined(TARGET_MIPS64)
Aurelien Jarnod75c1352013-01-01 18:02:22 +01005080 check_insn(ctx, ISA_MIPS3);
Blue Swirl895c2d02012-09-02 14:52:59 +00005081 gen_helper_mtc0_xcontext(cpu_env, arg);
ths2423f662007-04-11 02:15:08 +00005082 rn = "XContext";
5083 break;
ths703eaf32007-05-13 14:42:18 +00005084#endif
ths7a387ff2006-12-06 20:17:30 +00005085 default:
5086 goto die;
5087 }
ths8c0fdd82006-12-06 18:19:33 +00005088 break;
5089 case 21:
ths7a387ff2006-12-06 20:17:30 +00005090 /* Officially reserved, but sel 0 is used for R1x000 framemask */
5091 switch (sel) {
5092 case 0:
Blue Swirl895c2d02012-09-02 14:52:59 +00005093 gen_helper_mtc0_framemask(cpu_env, arg);
ths2423f662007-04-11 02:15:08 +00005094 rn = "Framemask";
5095 break;
ths7a387ff2006-12-06 20:17:30 +00005096 default:
5097 goto die;
5098 }
5099 break;
ths8c0fdd82006-12-06 18:19:33 +00005100 case 22:
ths7a387ff2006-12-06 20:17:30 +00005101 /* ignored */
5102 rn = "Diagnostic"; /* implementation dependent */
ths2423f662007-04-11 02:15:08 +00005103 break;
ths8c0fdd82006-12-06 18:19:33 +00005104 case 23:
ths7a387ff2006-12-06 20:17:30 +00005105 switch (sel) {
5106 case 0:
Blue Swirl895c2d02012-09-02 14:52:59 +00005107 gen_helper_mtc0_debug(cpu_env, arg); /* EJTAG support */
ths84873272007-06-01 17:47:07 +00005108 /* BS_STOP isn't good enough here, hflags may have changed. */
5109 gen_save_pc(ctx->pc + 4);
5110 ctx->bstate = BS_EXCP;
ths2423f662007-04-11 02:15:08 +00005111 rn = "Debug";
5112 break;
ths7a387ff2006-12-06 20:17:30 +00005113 case 1:
Blue Swirl895c2d02012-09-02 14:52:59 +00005114// gen_helper_mtc0_tracecontrol(cpu_env, arg); /* PDtrace support */
ths2423f662007-04-11 02:15:08 +00005115 rn = "TraceControl";
ths84873272007-06-01 17:47:07 +00005116 /* Stop translation as we may have switched the execution mode */
5117 ctx->bstate = BS_STOP;
ths2423f662007-04-11 02:15:08 +00005118// break;
ths7a387ff2006-12-06 20:17:30 +00005119 case 2:
Blue Swirl895c2d02012-09-02 14:52:59 +00005120// gen_helper_mtc0_tracecontrol2(cpu_env, arg); /* PDtrace support */
ths2423f662007-04-11 02:15:08 +00005121 rn = "TraceControl2";
ths84873272007-06-01 17:47:07 +00005122 /* Stop translation as we may have switched the execution mode */
5123 ctx->bstate = BS_STOP;
ths2423f662007-04-11 02:15:08 +00005124// break;
ths7a387ff2006-12-06 20:17:30 +00005125 case 3:
ths84873272007-06-01 17:47:07 +00005126 /* Stop translation as we may have switched the execution mode */
5127 ctx->bstate = BS_STOP;
Blue Swirl895c2d02012-09-02 14:52:59 +00005128// gen_helper_mtc0_usertracedata(cpu_env, arg); /* PDtrace support */
ths2423f662007-04-11 02:15:08 +00005129 rn = "UserTraceData";
ths84873272007-06-01 17:47:07 +00005130 /* Stop translation as we may have switched the execution mode */
5131 ctx->bstate = BS_STOP;
ths2423f662007-04-11 02:15:08 +00005132// break;
ths7a387ff2006-12-06 20:17:30 +00005133 case 4:
Blue Swirl895c2d02012-09-02 14:52:59 +00005134// gen_helper_mtc0_tracebpc(cpu_env, arg); /* PDtrace support */
ths84873272007-06-01 17:47:07 +00005135 /* Stop translation as we may have switched the execution mode */
5136 ctx->bstate = BS_STOP;
ths2423f662007-04-11 02:15:08 +00005137 rn = "TraceBPC";
5138// break;
ths7a387ff2006-12-06 20:17:30 +00005139 default:
5140 goto die;
5141 }
ths8c0fdd82006-12-06 18:19:33 +00005142 break;
5143 case 24:
ths7a387ff2006-12-06 20:17:30 +00005144 switch (sel) {
5145 case 0:
thsf1aa6322008-06-09 07:13:38 +00005146 /* EJTAG support */
Andreas Färber7db13fa2012-03-14 01:38:22 +01005147 gen_mtc0_store64(arg, offsetof(CPUMIPSState, CP0_DEPC));
ths2423f662007-04-11 02:15:08 +00005148 rn = "DEPC";
5149 break;
ths7a387ff2006-12-06 20:17:30 +00005150 default:
5151 goto die;
5152 }
ths8c0fdd82006-12-06 18:19:33 +00005153 break;
5154 case 25:
ths7a387ff2006-12-06 20:17:30 +00005155 switch (sel) {
5156 case 0:
Blue Swirl895c2d02012-09-02 14:52:59 +00005157 gen_helper_mtc0_performance0(cpu_env, arg);
ths2423f662007-04-11 02:15:08 +00005158 rn = "Performance0";
5159 break;
ths7a387ff2006-12-06 20:17:30 +00005160 case 1:
aurel32d9bea112009-04-15 14:41:44 +00005161// gen_helper_mtc0_performance1(arg);
ths2423f662007-04-11 02:15:08 +00005162 rn = "Performance1";
5163// break;
ths7a387ff2006-12-06 20:17:30 +00005164 case 2:
aurel32d9bea112009-04-15 14:41:44 +00005165// gen_helper_mtc0_performance2(arg);
ths2423f662007-04-11 02:15:08 +00005166 rn = "Performance2";
5167// break;
ths7a387ff2006-12-06 20:17:30 +00005168 case 3:
aurel32d9bea112009-04-15 14:41:44 +00005169// gen_helper_mtc0_performance3(arg);
ths2423f662007-04-11 02:15:08 +00005170 rn = "Performance3";
5171// break;
ths7a387ff2006-12-06 20:17:30 +00005172 case 4:
aurel32d9bea112009-04-15 14:41:44 +00005173// gen_helper_mtc0_performance4(arg);
ths2423f662007-04-11 02:15:08 +00005174 rn = "Performance4";
5175// break;
ths7a387ff2006-12-06 20:17:30 +00005176 case 5:
aurel32d9bea112009-04-15 14:41:44 +00005177// gen_helper_mtc0_performance5(arg);
ths2423f662007-04-11 02:15:08 +00005178 rn = "Performance5";
5179// break;
ths7a387ff2006-12-06 20:17:30 +00005180 case 6:
aurel32d9bea112009-04-15 14:41:44 +00005181// gen_helper_mtc0_performance6(arg);
ths2423f662007-04-11 02:15:08 +00005182 rn = "Performance6";
5183// break;
ths7a387ff2006-12-06 20:17:30 +00005184 case 7:
aurel32d9bea112009-04-15 14:41:44 +00005185// gen_helper_mtc0_performance7(arg);
ths2423f662007-04-11 02:15:08 +00005186 rn = "Performance7";
5187// break;
ths7a387ff2006-12-06 20:17:30 +00005188 default:
5189 goto die;
5190 }
ths8c0fdd82006-12-06 18:19:33 +00005191 break;
5192 case 26:
ths2423f662007-04-11 02:15:08 +00005193 /* ignored */
ths8c0fdd82006-12-06 18:19:33 +00005194 rn = "ECC";
ths2423f662007-04-11 02:15:08 +00005195 break;
ths8c0fdd82006-12-06 18:19:33 +00005196 case 27:
ths7a387ff2006-12-06 20:17:30 +00005197 switch (sel) {
5198 case 0 ... 3:
ths2423f662007-04-11 02:15:08 +00005199 /* ignored */
5200 rn = "CacheErr";
5201 break;
ths7a387ff2006-12-06 20:17:30 +00005202 default:
5203 goto die;
5204 }
ths8c0fdd82006-12-06 18:19:33 +00005205 break;
5206 case 28:
5207 switch (sel) {
5208 case 0:
ths7a387ff2006-12-06 20:17:30 +00005209 case 2:
5210 case 4:
5211 case 6:
Blue Swirl895c2d02012-09-02 14:52:59 +00005212 gen_helper_mtc0_taglo(cpu_env, arg);
ths8c0fdd82006-12-06 18:19:33 +00005213 rn = "TagLo";
5214 break;
ths7a387ff2006-12-06 20:17:30 +00005215 case 1:
5216 case 3:
5217 case 5:
5218 case 7:
Blue Swirl895c2d02012-09-02 14:52:59 +00005219 gen_helper_mtc0_datalo(cpu_env, arg);
ths7a387ff2006-12-06 20:17:30 +00005220 rn = "DataLo";
5221 break;
5222 default:
5223 goto die;
5224 }
5225 break;
5226 case 29:
5227 switch (sel) {
5228 case 0:
5229 case 2:
5230 case 4:
5231 case 6:
Blue Swirl895c2d02012-09-02 14:52:59 +00005232 gen_helper_mtc0_taghi(cpu_env, arg);
ths7a387ff2006-12-06 20:17:30 +00005233 rn = "TagHi";
5234 break;
5235 case 1:
5236 case 3:
5237 case 5:
5238 case 7:
Blue Swirl895c2d02012-09-02 14:52:59 +00005239 gen_helper_mtc0_datahi(cpu_env, arg);
ths7a387ff2006-12-06 20:17:30 +00005240 rn = "DataHi";
5241 break;
ths8c0fdd82006-12-06 18:19:33 +00005242 default:
5243 rn = "invalid sel";
5244 goto die;
5245 }
ths8c0fdd82006-12-06 18:19:33 +00005246 break;
5247 case 30:
ths7a387ff2006-12-06 20:17:30 +00005248 switch (sel) {
5249 case 0:
Andreas Färber7db13fa2012-03-14 01:38:22 +01005250 gen_mtc0_store64(arg, offsetof(CPUMIPSState, CP0_ErrorEPC));
ths2423f662007-04-11 02:15:08 +00005251 rn = "ErrorEPC";
5252 break;
ths7a387ff2006-12-06 20:17:30 +00005253 default:
5254 goto die;
5255 }
ths8c0fdd82006-12-06 18:19:33 +00005256 break;
5257 case 31:
ths7a387ff2006-12-06 20:17:30 +00005258 switch (sel) {
5259 case 0:
thsf1aa6322008-06-09 07:13:38 +00005260 /* EJTAG support */
Andreas Färber7db13fa2012-03-14 01:38:22 +01005261 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
ths2423f662007-04-11 02:15:08 +00005262 rn = "DESAVE";
5263 break;
ths7a387ff2006-12-06 20:17:30 +00005264 default:
5265 goto die;
5266 }
ths2423f662007-04-11 02:15:08 +00005267 /* Stop translation as we may have switched the execution mode */
5268 ctx->bstate = BS_STOP;
ths8c0fdd82006-12-06 18:19:33 +00005269 break;
5270 default:
ths8c0fdd82006-12-06 18:19:33 +00005271 goto die;
5272 }
Blue Swirl2abf3142010-10-13 18:38:08 +00005273 (void)rn; /* avoid a compiler warning */
aliguorid12d51d2009-01-15 21:48:06 +00005274 LOG_DISAS("mtc0 %s (reg %d sel %d)\n", rn, reg, sel);
thsbf20dc02008-06-30 17:22:19 +00005275 /* For simplicity assume that all writes can cause interrupts. */
pbrook2e70f6e2008-06-29 01:03:05 +00005276 if (use_icount) {
5277 gen_io_end();
5278 ctx->bstate = BS_STOP;
5279 }
ths8c0fdd82006-12-06 18:19:33 +00005280 return;
5281
5282die:
aliguorid12d51d2009-01-15 21:48:06 +00005283 LOG_DISAS("mtc0 %s (reg %d sel %d)\n", rn, reg, sel);
ths8c0fdd82006-12-06 18:19:33 +00005284 generate_exception(ctx, EXCP_RI);
5285}
5286
thsd26bc212007-11-08 18:05:37 +00005287#if defined(TARGET_MIPS64)
Aurelien Jarnod75c1352013-01-01 18:02:22 +01005288static void gen_dmfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
ths9c2149c2007-01-23 22:45:22 +00005289{
5290 const char *rn = "invalid";
5291
thse189e742007-09-24 12:48:00 +00005292 if (sel != 0)
Aurelien Jarnod75c1352013-01-01 18:02:22 +01005293 check_insn(ctx, ISA_MIPS64);
thse189e742007-09-24 12:48:00 +00005294
ths9c2149c2007-01-23 22:45:22 +00005295 switch (reg) {
5296 case 0:
5297 switch (sel) {
5298 case 0:
Andreas Färber7db13fa2012-03-14 01:38:22 +01005299 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Index));
ths9c2149c2007-01-23 22:45:22 +00005300 rn = "Index";
5301 break;
5302 case 1:
Aurelien Jarnod75c1352013-01-01 18:02:22 +01005303 check_insn(ctx, ASE_MT);
Blue Swirl895c2d02012-09-02 14:52:59 +00005304 gen_helper_mfc0_mvpcontrol(arg, cpu_env);
ths9c2149c2007-01-23 22:45:22 +00005305 rn = "MVPControl";
thsead93602007-09-06 00:18:15 +00005306 break;
ths9c2149c2007-01-23 22:45:22 +00005307 case 2:
Aurelien Jarnod75c1352013-01-01 18:02:22 +01005308 check_insn(ctx, ASE_MT);
Blue Swirl895c2d02012-09-02 14:52:59 +00005309 gen_helper_mfc0_mvpconf0(arg, cpu_env);
ths9c2149c2007-01-23 22:45:22 +00005310 rn = "MVPConf0";
thsead93602007-09-06 00:18:15 +00005311 break;
ths9c2149c2007-01-23 22:45:22 +00005312 case 3:
Aurelien Jarnod75c1352013-01-01 18:02:22 +01005313 check_insn(ctx, ASE_MT);
Blue Swirl895c2d02012-09-02 14:52:59 +00005314 gen_helper_mfc0_mvpconf1(arg, cpu_env);
ths9c2149c2007-01-23 22:45:22 +00005315 rn = "MVPConf1";
thsead93602007-09-06 00:18:15 +00005316 break;
ths9c2149c2007-01-23 22:45:22 +00005317 default:
5318 goto die;
5319 }
5320 break;
5321 case 1:
5322 switch (sel) {
5323 case 0:
Blue Swirl895c2d02012-09-02 14:52:59 +00005324 gen_helper_mfc0_random(arg, cpu_env);
ths9c2149c2007-01-23 22:45:22 +00005325 rn = "Random";
ths2423f662007-04-11 02:15:08 +00005326 break;
ths9c2149c2007-01-23 22:45:22 +00005327 case 1:
Aurelien Jarnod75c1352013-01-01 18:02:22 +01005328 check_insn(ctx, ASE_MT);
Andreas Färber7db13fa2012-03-14 01:38:22 +01005329 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEControl));
ths9c2149c2007-01-23 22:45:22 +00005330 rn = "VPEControl";
thsead93602007-09-06 00:18:15 +00005331 break;
ths9c2149c2007-01-23 22:45:22 +00005332 case 2:
Aurelien Jarnod75c1352013-01-01 18:02:22 +01005333 check_insn(ctx, ASE_MT);
Andreas Färber7db13fa2012-03-14 01:38:22 +01005334 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf0));
ths9c2149c2007-01-23 22:45:22 +00005335 rn = "VPEConf0";
thsead93602007-09-06 00:18:15 +00005336 break;
ths9c2149c2007-01-23 22:45:22 +00005337 case 3:
Aurelien Jarnod75c1352013-01-01 18:02:22 +01005338 check_insn(ctx, ASE_MT);
Andreas Färber7db13fa2012-03-14 01:38:22 +01005339 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf1));
ths9c2149c2007-01-23 22:45:22 +00005340 rn = "VPEConf1";
thsead93602007-09-06 00:18:15 +00005341 break;
ths9c2149c2007-01-23 22:45:22 +00005342 case 4:
Aurelien Jarnod75c1352013-01-01 18:02:22 +01005343 check_insn(ctx, ASE_MT);
Andreas Färber7db13fa2012-03-14 01:38:22 +01005344 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_YQMask));
ths9c2149c2007-01-23 22:45:22 +00005345 rn = "YQMask";
thsead93602007-09-06 00:18:15 +00005346 break;
ths9c2149c2007-01-23 22:45:22 +00005347 case 5:
Aurelien Jarnod75c1352013-01-01 18:02:22 +01005348 check_insn(ctx, ASE_MT);
Andreas Färber7db13fa2012-03-14 01:38:22 +01005349 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_VPESchedule));
ths9c2149c2007-01-23 22:45:22 +00005350 rn = "VPESchedule";
thsead93602007-09-06 00:18:15 +00005351 break;
ths9c2149c2007-01-23 22:45:22 +00005352 case 6:
Aurelien Jarnod75c1352013-01-01 18:02:22 +01005353 check_insn(ctx, ASE_MT);
Andreas Färber7db13fa2012-03-14 01:38:22 +01005354 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_VPEScheFBack));
ths9c2149c2007-01-23 22:45:22 +00005355 rn = "VPEScheFBack";
thsead93602007-09-06 00:18:15 +00005356 break;
ths9c2149c2007-01-23 22:45:22 +00005357 case 7:
Aurelien Jarnod75c1352013-01-01 18:02:22 +01005358 check_insn(ctx, ASE_MT);
Andreas Färber7db13fa2012-03-14 01:38:22 +01005359 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEOpt));
ths9c2149c2007-01-23 22:45:22 +00005360 rn = "VPEOpt";
thsead93602007-09-06 00:18:15 +00005361 break;
ths9c2149c2007-01-23 22:45:22 +00005362 default:
5363 goto die;
5364 }
5365 break;
5366 case 2:
5367 switch (sel) {
5368 case 0:
Andreas Färber7db13fa2012-03-14 01:38:22 +01005369 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryLo0));
ths2423f662007-04-11 02:15:08 +00005370 rn = "EntryLo0";
5371 break;
ths9c2149c2007-01-23 22:45:22 +00005372 case 1:
Aurelien Jarnod75c1352013-01-01 18:02:22 +01005373 check_insn(ctx, ASE_MT);
Blue Swirl895c2d02012-09-02 14:52:59 +00005374 gen_helper_mfc0_tcstatus(arg, cpu_env);
ths2423f662007-04-11 02:15:08 +00005375 rn = "TCStatus";
thsead93602007-09-06 00:18:15 +00005376 break;
ths9c2149c2007-01-23 22:45:22 +00005377 case 2:
Aurelien Jarnod75c1352013-01-01 18:02:22 +01005378 check_insn(ctx, ASE_MT);
Blue Swirl895c2d02012-09-02 14:52:59 +00005379 gen_helper_mfc0_tcbind(arg, cpu_env);
ths2423f662007-04-11 02:15:08 +00005380 rn = "TCBind";
thsead93602007-09-06 00:18:15 +00005381 break;
ths9c2149c2007-01-23 22:45:22 +00005382 case 3:
Aurelien Jarnod75c1352013-01-01 18:02:22 +01005383 check_insn(ctx, ASE_MT);
Blue Swirl895c2d02012-09-02 14:52:59 +00005384 gen_helper_dmfc0_tcrestart(arg, cpu_env);
ths2423f662007-04-11 02:15:08 +00005385 rn = "TCRestart";
thsead93602007-09-06 00:18:15 +00005386 break;
ths9c2149c2007-01-23 22:45:22 +00005387 case 4:
Aurelien Jarnod75c1352013-01-01 18:02:22 +01005388 check_insn(ctx, ASE_MT);
Blue Swirl895c2d02012-09-02 14:52:59 +00005389 gen_helper_dmfc0_tchalt(arg, cpu_env);
ths2423f662007-04-11 02:15:08 +00005390 rn = "TCHalt";
thsead93602007-09-06 00:18:15 +00005391 break;
ths9c2149c2007-01-23 22:45:22 +00005392 case 5:
Aurelien Jarnod75c1352013-01-01 18:02:22 +01005393 check_insn(ctx, ASE_MT);
Blue Swirl895c2d02012-09-02 14:52:59 +00005394 gen_helper_dmfc0_tccontext(arg, cpu_env);
ths2423f662007-04-11 02:15:08 +00005395 rn = "TCContext";
thsead93602007-09-06 00:18:15 +00005396 break;
ths9c2149c2007-01-23 22:45:22 +00005397 case 6:
Aurelien Jarnod75c1352013-01-01 18:02:22 +01005398 check_insn(ctx, ASE_MT);
Blue Swirl895c2d02012-09-02 14:52:59 +00005399 gen_helper_dmfc0_tcschedule(arg, cpu_env);
ths2423f662007-04-11 02:15:08 +00005400 rn = "TCSchedule";
thsead93602007-09-06 00:18:15 +00005401 break;
ths9c2149c2007-01-23 22:45:22 +00005402 case 7:
Aurelien Jarnod75c1352013-01-01 18:02:22 +01005403 check_insn(ctx, ASE_MT);
Blue Swirl895c2d02012-09-02 14:52:59 +00005404 gen_helper_dmfc0_tcschefback(arg, cpu_env);
ths2423f662007-04-11 02:15:08 +00005405 rn = "TCScheFBack";
thsead93602007-09-06 00:18:15 +00005406 break;
ths9c2149c2007-01-23 22:45:22 +00005407 default:
5408 goto die;
5409 }
5410 break;
5411 case 3:
5412 switch (sel) {
5413 case 0:
Andreas Färber7db13fa2012-03-14 01:38:22 +01005414 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryLo1));
ths2423f662007-04-11 02:15:08 +00005415 rn = "EntryLo1";
5416 break;
ths9c2149c2007-01-23 22:45:22 +00005417 default:
5418 goto die;
ths1579a722007-04-05 23:16:25 +00005419 }
ths9c2149c2007-01-23 22:45:22 +00005420 break;
5421 case 4:
5422 switch (sel) {
5423 case 0:
Andreas Färber7db13fa2012-03-14 01:38:22 +01005424 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_Context));
ths2423f662007-04-11 02:15:08 +00005425 rn = "Context";
5426 break;
ths9c2149c2007-01-23 22:45:22 +00005427 case 1:
aurel32d9bea112009-04-15 14:41:44 +00005428// gen_helper_dmfc0_contextconfig(arg); /* SmartMIPS ASE */
ths2423f662007-04-11 02:15:08 +00005429 rn = "ContextConfig";
5430// break;
ths9c2149c2007-01-23 22:45:22 +00005431 default:
5432 goto die;
ths876d4b02007-04-04 21:07:17 +00005433 }
ths9c2149c2007-01-23 22:45:22 +00005434 break;
5435 case 5:
5436 switch (sel) {
5437 case 0:
Andreas Färber7db13fa2012-03-14 01:38:22 +01005438 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageMask));
ths2423f662007-04-11 02:15:08 +00005439 rn = "PageMask";
5440 break;
ths9c2149c2007-01-23 22:45:22 +00005441 case 1:
Aurelien Jarnod75c1352013-01-01 18:02:22 +01005442 check_insn(ctx, ISA_MIPS32R2);
Andreas Färber7db13fa2012-03-14 01:38:22 +01005443 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageGrain));
ths2423f662007-04-11 02:15:08 +00005444 rn = "PageGrain";
5445 break;
ths9c2149c2007-01-23 22:45:22 +00005446 default:
5447 goto die;
ths876d4b02007-04-04 21:07:17 +00005448 }
ths9c2149c2007-01-23 22:45:22 +00005449 break;
5450 case 6:
5451 switch (sel) {
5452 case 0:
Andreas Färber7db13fa2012-03-14 01:38:22 +01005453 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Wired));
ths2423f662007-04-11 02:15:08 +00005454 rn = "Wired";
5455 break;
ths9c2149c2007-01-23 22:45:22 +00005456 case 1:
Aurelien Jarnod75c1352013-01-01 18:02:22 +01005457 check_insn(ctx, ISA_MIPS32R2);
Andreas Färber7db13fa2012-03-14 01:38:22 +01005458 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf0));
ths2423f662007-04-11 02:15:08 +00005459 rn = "SRSConf0";
thsead93602007-09-06 00:18:15 +00005460 break;
ths9c2149c2007-01-23 22:45:22 +00005461 case 2:
Aurelien Jarnod75c1352013-01-01 18:02:22 +01005462 check_insn(ctx, ISA_MIPS32R2);
Andreas Färber7db13fa2012-03-14 01:38:22 +01005463 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf1));
ths2423f662007-04-11 02:15:08 +00005464 rn = "SRSConf1";
thsead93602007-09-06 00:18:15 +00005465 break;
ths9c2149c2007-01-23 22:45:22 +00005466 case 3:
Aurelien Jarnod75c1352013-01-01 18:02:22 +01005467 check_insn(ctx, ISA_MIPS32R2);
Andreas Färber7db13fa2012-03-14 01:38:22 +01005468 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf2));
ths2423f662007-04-11 02:15:08 +00005469 rn = "SRSConf2";
thsead93602007-09-06 00:18:15 +00005470 break;
ths9c2149c2007-01-23 22:45:22 +00005471 case 4:
Aurelien Jarnod75c1352013-01-01 18:02:22 +01005472 check_insn(ctx, ISA_MIPS32R2);
Andreas Färber7db13fa2012-03-14 01:38:22 +01005473 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf3));
ths2423f662007-04-11 02:15:08 +00005474 rn = "SRSConf3";
thsead93602007-09-06 00:18:15 +00005475 break;
ths9c2149c2007-01-23 22:45:22 +00005476 case 5:
Aurelien Jarnod75c1352013-01-01 18:02:22 +01005477 check_insn(ctx, ISA_MIPS32R2);
Andreas Färber7db13fa2012-03-14 01:38:22 +01005478 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf4));
ths2423f662007-04-11 02:15:08 +00005479 rn = "SRSConf4";
thsead93602007-09-06 00:18:15 +00005480 break;
ths9c2149c2007-01-23 22:45:22 +00005481 default:
5482 goto die;
ths876d4b02007-04-04 21:07:17 +00005483 }
ths9c2149c2007-01-23 22:45:22 +00005484 break;
5485 case 7:
5486 switch (sel) {
5487 case 0:
Aurelien Jarnod75c1352013-01-01 18:02:22 +01005488 check_insn(ctx, ISA_MIPS32R2);
Andreas Färber7db13fa2012-03-14 01:38:22 +01005489 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_HWREna));
ths2423f662007-04-11 02:15:08 +00005490 rn = "HWREna";
5491 break;
ths9c2149c2007-01-23 22:45:22 +00005492 default:
5493 goto die;
ths876d4b02007-04-04 21:07:17 +00005494 }
ths9c2149c2007-01-23 22:45:22 +00005495 break;
5496 case 8:
5497 switch (sel) {
5498 case 0:
Andreas Färber7db13fa2012-03-14 01:38:22 +01005499 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_BadVAddr));
thsf0b3f3a2008-05-23 18:10:51 +00005500 rn = "BadVAddr";
ths2423f662007-04-11 02:15:08 +00005501 break;
ths9c2149c2007-01-23 22:45:22 +00005502 default:
5503 goto die;
ths876d4b02007-04-04 21:07:17 +00005504 }
ths9c2149c2007-01-23 22:45:22 +00005505 break;
5506 case 9:
5507 switch (sel) {
5508 case 0:
pbrook2e70f6e2008-06-29 01:03:05 +00005509 /* Mark as an IO operation because we read the time. */
5510 if (use_icount)
5511 gen_io_start();
Blue Swirl895c2d02012-09-02 14:52:59 +00005512 gen_helper_mfc0_count(arg, cpu_env);
pbrook2e70f6e2008-06-29 01:03:05 +00005513 if (use_icount) {
5514 gen_io_end();
pbrook2e70f6e2008-06-29 01:03:05 +00005515 }
Edgar E. Iglesias55807222011-01-17 23:00:08 +01005516 /* Break the TB to be able to take timer interrupts immediately
5517 after reading count. */
5518 ctx->bstate = BS_STOP;
ths2423f662007-04-11 02:15:08 +00005519 rn = "Count";
5520 break;
5521 /* 6,7 are implementation dependent */
ths9c2149c2007-01-23 22:45:22 +00005522 default:
5523 goto die;
ths876d4b02007-04-04 21:07:17 +00005524 }
ths9c2149c2007-01-23 22:45:22 +00005525 break;
5526 case 10:
5527 switch (sel) {
5528 case 0:
Andreas Färber7db13fa2012-03-14 01:38:22 +01005529 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryHi));
ths2423f662007-04-11 02:15:08 +00005530 rn = "EntryHi";
5531 break;
ths9c2149c2007-01-23 22:45:22 +00005532 default:
5533 goto die;
ths876d4b02007-04-04 21:07:17 +00005534 }
ths9c2149c2007-01-23 22:45:22 +00005535 break;
5536 case 11:
5537 switch (sel) {
5538 case 0:
Andreas Färber7db13fa2012-03-14 01:38:22 +01005539 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Compare));
ths2423f662007-04-11 02:15:08 +00005540 rn = "Compare";
5541 break;
ths876d4b02007-04-04 21:07:17 +00005542 /* 6,7 are implementation dependent */
ths9c2149c2007-01-23 22:45:22 +00005543 default:
5544 goto die;
ths876d4b02007-04-04 21:07:17 +00005545 }
ths9c2149c2007-01-23 22:45:22 +00005546 break;
5547 case 12:
5548 switch (sel) {
5549 case 0:
Andreas Färber7db13fa2012-03-14 01:38:22 +01005550 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Status));
ths2423f662007-04-11 02:15:08 +00005551 rn = "Status";
5552 break;
ths9c2149c2007-01-23 22:45:22 +00005553 case 1:
Aurelien Jarnod75c1352013-01-01 18:02:22 +01005554 check_insn(ctx, ISA_MIPS32R2);
Andreas Färber7db13fa2012-03-14 01:38:22 +01005555 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_IntCtl));
ths2423f662007-04-11 02:15:08 +00005556 rn = "IntCtl";
5557 break;
ths9c2149c2007-01-23 22:45:22 +00005558 case 2:
Aurelien Jarnod75c1352013-01-01 18:02:22 +01005559 check_insn(ctx, ISA_MIPS32R2);
Andreas Färber7db13fa2012-03-14 01:38:22 +01005560 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSCtl));
ths2423f662007-04-11 02:15:08 +00005561 rn = "SRSCtl";
5562 break;
ths9c2149c2007-01-23 22:45:22 +00005563 case 3:
Aurelien Jarnod75c1352013-01-01 18:02:22 +01005564 check_insn(ctx, ISA_MIPS32R2);
Andreas Färber7db13fa2012-03-14 01:38:22 +01005565 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
ths2423f662007-04-11 02:15:08 +00005566 rn = "SRSMap";
5567 break;
ths9c2149c2007-01-23 22:45:22 +00005568 default:
5569 goto die;
ths876d4b02007-04-04 21:07:17 +00005570 }
ths9c2149c2007-01-23 22:45:22 +00005571 break;
5572 case 13:
5573 switch (sel) {
5574 case 0:
Andreas Färber7db13fa2012-03-14 01:38:22 +01005575 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Cause));
ths2423f662007-04-11 02:15:08 +00005576 rn = "Cause";
5577 break;
ths9c2149c2007-01-23 22:45:22 +00005578 default:
5579 goto die;
ths876d4b02007-04-04 21:07:17 +00005580 }
ths9c2149c2007-01-23 22:45:22 +00005581 break;
5582 case 14:
5583 switch (sel) {
5584 case 0:
Andreas Färber7db13fa2012-03-14 01:38:22 +01005585 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EPC));
ths2423f662007-04-11 02:15:08 +00005586 rn = "EPC";
5587 break;
ths9c2149c2007-01-23 22:45:22 +00005588 default:
5589 goto die;
ths876d4b02007-04-04 21:07:17 +00005590 }
ths9c2149c2007-01-23 22:45:22 +00005591 break;
5592 case 15:
5593 switch (sel) {
5594 case 0:
Andreas Färber7db13fa2012-03-14 01:38:22 +01005595 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PRid));
ths2423f662007-04-11 02:15:08 +00005596 rn = "PRid";
5597 break;
ths9c2149c2007-01-23 22:45:22 +00005598 case 1:
Aurelien Jarnod75c1352013-01-01 18:02:22 +01005599 check_insn(ctx, ISA_MIPS32R2);
Andreas Färber7db13fa2012-03-14 01:38:22 +01005600 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_EBase));
ths2423f662007-04-11 02:15:08 +00005601 rn = "EBase";
5602 break;
ths9c2149c2007-01-23 22:45:22 +00005603 default:
5604 goto die;
ths876d4b02007-04-04 21:07:17 +00005605 }
ths9c2149c2007-01-23 22:45:22 +00005606 break;
5607 case 16:
5608 switch (sel) {
5609 case 0:
Andreas Färber7db13fa2012-03-14 01:38:22 +01005610 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config0));
ths9c2149c2007-01-23 22:45:22 +00005611 rn = "Config";
5612 break;
5613 case 1:
Andreas Färber7db13fa2012-03-14 01:38:22 +01005614 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config1));
ths9c2149c2007-01-23 22:45:22 +00005615 rn = "Config1";
5616 break;
5617 case 2:
Andreas Färber7db13fa2012-03-14 01:38:22 +01005618 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config2));
ths9c2149c2007-01-23 22:45:22 +00005619 rn = "Config2";
5620 break;
5621 case 3:
Andreas Färber7db13fa2012-03-14 01:38:22 +01005622 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config3));
ths9c2149c2007-01-23 22:45:22 +00005623 rn = "Config3";
5624 break;
5625 /* 6,7 are implementation dependent */
thsf0b3f3a2008-05-23 18:10:51 +00005626 case 6:
Andreas Färber7db13fa2012-03-14 01:38:22 +01005627 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config6));
thsf0b3f3a2008-05-23 18:10:51 +00005628 rn = "Config6";
5629 break;
5630 case 7:
Andreas Färber7db13fa2012-03-14 01:38:22 +01005631 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config7));
thsf0b3f3a2008-05-23 18:10:51 +00005632 rn = "Config7";
5633 break;
ths9c2149c2007-01-23 22:45:22 +00005634 default:
5635 goto die;
5636 }
5637 break;
5638 case 17:
5639 switch (sel) {
5640 case 0:
Blue Swirl895c2d02012-09-02 14:52:59 +00005641 gen_helper_dmfc0_lladdr(arg, cpu_env);
ths2423f662007-04-11 02:15:08 +00005642 rn = "LLAddr";
5643 break;
ths9c2149c2007-01-23 22:45:22 +00005644 default:
5645 goto die;
5646 }
5647 break;
5648 case 18:
5649 switch (sel) {
thsfd88b6a2007-05-23 08:24:25 +00005650 case 0 ... 7:
Blue Swirl895c2d02012-09-02 14:52:59 +00005651 gen_helper_1e0i(dmfc0_watchlo, arg, sel);
ths2423f662007-04-11 02:15:08 +00005652 rn = "WatchLo";
5653 break;
ths9c2149c2007-01-23 22:45:22 +00005654 default:
5655 goto die;
5656 }
5657 break;
5658 case 19:
5659 switch (sel) {
thsfd88b6a2007-05-23 08:24:25 +00005660 case 0 ... 7:
Blue Swirl895c2d02012-09-02 14:52:59 +00005661 gen_helper_1e0i(mfc0_watchhi, arg, sel);
ths2423f662007-04-11 02:15:08 +00005662 rn = "WatchHi";
5663 break;
ths9c2149c2007-01-23 22:45:22 +00005664 default:
5665 goto die;
5666 }
5667 break;
5668 case 20:
5669 switch (sel) {
5670 case 0:
Aurelien Jarnod75c1352013-01-01 18:02:22 +01005671 check_insn(ctx, ISA_MIPS3);
Andreas Färber7db13fa2012-03-14 01:38:22 +01005672 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_XContext));
ths2423f662007-04-11 02:15:08 +00005673 rn = "XContext";
5674 break;
ths9c2149c2007-01-23 22:45:22 +00005675 default:
5676 goto die;
5677 }
5678 break;
5679 case 21:
5680 /* Officially reserved, but sel 0 is used for R1x000 framemask */
5681 switch (sel) {
5682 case 0:
Andreas Färber7db13fa2012-03-14 01:38:22 +01005683 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Framemask));
ths2423f662007-04-11 02:15:08 +00005684 rn = "Framemask";
5685 break;
ths9c2149c2007-01-23 22:45:22 +00005686 default:
5687 goto die;
5688 }
5689 break;
5690 case 22:
aurel32d9bea112009-04-15 14:41:44 +00005691 tcg_gen_movi_tl(arg, 0); /* unimplemented */
ths2423f662007-04-11 02:15:08 +00005692 rn = "'Diagnostic"; /* implementation dependent */
5693 break;
ths9c2149c2007-01-23 22:45:22 +00005694 case 23:
5695 switch (sel) {
5696 case 0:
Blue Swirl895c2d02012-09-02 14:52:59 +00005697 gen_helper_mfc0_debug(arg, cpu_env); /* EJTAG support */
ths2423f662007-04-11 02:15:08 +00005698 rn = "Debug";
5699 break;
ths9c2149c2007-01-23 22:45:22 +00005700 case 1:
Blue Swirl895c2d02012-09-02 14:52:59 +00005701// gen_helper_dmfc0_tracecontrol(arg, cpu_env); /* PDtrace support */
ths2423f662007-04-11 02:15:08 +00005702 rn = "TraceControl";
5703// break;
ths9c2149c2007-01-23 22:45:22 +00005704 case 2:
Blue Swirl895c2d02012-09-02 14:52:59 +00005705// gen_helper_dmfc0_tracecontrol2(arg, cpu_env); /* PDtrace support */
ths2423f662007-04-11 02:15:08 +00005706 rn = "TraceControl2";
5707// break;
ths9c2149c2007-01-23 22:45:22 +00005708 case 3:
Blue Swirl895c2d02012-09-02 14:52:59 +00005709// gen_helper_dmfc0_usertracedata(arg, cpu_env); /* PDtrace support */
ths2423f662007-04-11 02:15:08 +00005710 rn = "UserTraceData";
5711// break;
ths9c2149c2007-01-23 22:45:22 +00005712 case 4:
Blue Swirl895c2d02012-09-02 14:52:59 +00005713// gen_helper_dmfc0_tracebpc(arg, cpu_env); /* PDtrace support */
ths2423f662007-04-11 02:15:08 +00005714 rn = "TraceBPC";
5715// break;
ths9c2149c2007-01-23 22:45:22 +00005716 default:
5717 goto die;
5718 }
5719 break;
5720 case 24:
5721 switch (sel) {
5722 case 0:
thsf0b3f3a2008-05-23 18:10:51 +00005723 /* EJTAG support */
Andreas Färber7db13fa2012-03-14 01:38:22 +01005724 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_DEPC));
ths2423f662007-04-11 02:15:08 +00005725 rn = "DEPC";
5726 break;
ths9c2149c2007-01-23 22:45:22 +00005727 default:
5728 goto die;
5729 }
5730 break;
5731 case 25:
5732 switch (sel) {
5733 case 0:
Andreas Färber7db13fa2012-03-14 01:38:22 +01005734 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Performance0));
ths2423f662007-04-11 02:15:08 +00005735 rn = "Performance0";
ths9c2149c2007-01-23 22:45:22 +00005736 break;
5737 case 1:
aurel32d9bea112009-04-15 14:41:44 +00005738// gen_helper_dmfc0_performance1(arg);
ths2423f662007-04-11 02:15:08 +00005739 rn = "Performance1";
5740// break;
ths9c2149c2007-01-23 22:45:22 +00005741 case 2:
aurel32d9bea112009-04-15 14:41:44 +00005742// gen_helper_dmfc0_performance2(arg);
ths2423f662007-04-11 02:15:08 +00005743 rn = "Performance2";
5744// break;
ths9c2149c2007-01-23 22:45:22 +00005745 case 3:
aurel32d9bea112009-04-15 14:41:44 +00005746// gen_helper_dmfc0_performance3(arg);
ths2423f662007-04-11 02:15:08 +00005747 rn = "Performance3";
5748// break;
ths9c2149c2007-01-23 22:45:22 +00005749 case 4:
aurel32d9bea112009-04-15 14:41:44 +00005750// gen_helper_dmfc0_performance4(arg);
ths2423f662007-04-11 02:15:08 +00005751 rn = "Performance4";
5752// break;
ths9c2149c2007-01-23 22:45:22 +00005753 case 5:
aurel32d9bea112009-04-15 14:41:44 +00005754// gen_helper_dmfc0_performance5(arg);
ths2423f662007-04-11 02:15:08 +00005755 rn = "Performance5";
5756// break;
ths9c2149c2007-01-23 22:45:22 +00005757 case 6:
aurel32d9bea112009-04-15 14:41:44 +00005758// gen_helper_dmfc0_performance6(arg);
ths2423f662007-04-11 02:15:08 +00005759 rn = "Performance6";
5760// break;
ths9c2149c2007-01-23 22:45:22 +00005761 case 7:
aurel32d9bea112009-04-15 14:41:44 +00005762// gen_helper_dmfc0_performance7(arg);
ths2423f662007-04-11 02:15:08 +00005763 rn = "Performance7";
5764// break;
ths9c2149c2007-01-23 22:45:22 +00005765 default:
5766 goto die;
5767 }
5768 break;
5769 case 26:
aurel32d9bea112009-04-15 14:41:44 +00005770 tcg_gen_movi_tl(arg, 0); /* unimplemented */
aurel32da806822008-11-15 12:12:08 +00005771 rn = "ECC";
5772 break;
ths9c2149c2007-01-23 22:45:22 +00005773 case 27:
5774 switch (sel) {
5775 /* ignored */
5776 case 0 ... 3:
aurel32d9bea112009-04-15 14:41:44 +00005777 tcg_gen_movi_tl(arg, 0); /* unimplemented */
ths2423f662007-04-11 02:15:08 +00005778 rn = "CacheErr";
5779 break;
ths9c2149c2007-01-23 22:45:22 +00005780 default:
5781 goto die;
5782 }
5783 break;
5784 case 28:
5785 switch (sel) {
5786 case 0:
5787 case 2:
5788 case 4:
5789 case 6:
Andreas Färber7db13fa2012-03-14 01:38:22 +01005790 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_TagLo));
ths9c2149c2007-01-23 22:45:22 +00005791 rn = "TagLo";
5792 break;
5793 case 1:
5794 case 3:
5795 case 5:
5796 case 7:
Andreas Färber7db13fa2012-03-14 01:38:22 +01005797 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataLo));
ths9c2149c2007-01-23 22:45:22 +00005798 rn = "DataLo";
5799 break;
5800 default:
5801 goto die;
5802 }
5803 break;
5804 case 29:
5805 switch (sel) {
5806 case 0:
5807 case 2:
5808 case 4:
5809 case 6:
Andreas Färber7db13fa2012-03-14 01:38:22 +01005810 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_TagHi));
ths9c2149c2007-01-23 22:45:22 +00005811 rn = "TagHi";
5812 break;
5813 case 1:
5814 case 3:
5815 case 5:
5816 case 7:
Andreas Färber7db13fa2012-03-14 01:38:22 +01005817 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataHi));
ths9c2149c2007-01-23 22:45:22 +00005818 rn = "DataHi";
5819 break;
5820 default:
5821 goto die;
5822 }
5823 break;
5824 case 30:
5825 switch (sel) {
5826 case 0:
Andreas Färber7db13fa2012-03-14 01:38:22 +01005827 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_ErrorEPC));
ths2423f662007-04-11 02:15:08 +00005828 rn = "ErrorEPC";
5829 break;
ths9c2149c2007-01-23 22:45:22 +00005830 default:
5831 goto die;
5832 }
5833 break;
5834 case 31:
5835 switch (sel) {
5836 case 0:
thsf0b3f3a2008-05-23 18:10:51 +00005837 /* EJTAG support */
Andreas Färber7db13fa2012-03-14 01:38:22 +01005838 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
ths2423f662007-04-11 02:15:08 +00005839 rn = "DESAVE";
5840 break;
ths9c2149c2007-01-23 22:45:22 +00005841 default:
5842 goto die;
5843 }
5844 break;
5845 default:
ths876d4b02007-04-04 21:07:17 +00005846 goto die;
ths9c2149c2007-01-23 22:45:22 +00005847 }
Blue Swirl2abf3142010-10-13 18:38:08 +00005848 (void)rn; /* avoid a compiler warning */
aliguorid12d51d2009-01-15 21:48:06 +00005849 LOG_DISAS("dmfc0 %s (reg %d sel %d)\n", rn, reg, sel);
ths9c2149c2007-01-23 22:45:22 +00005850 return;
5851
5852die:
aliguorid12d51d2009-01-15 21:48:06 +00005853 LOG_DISAS("dmfc0 %s (reg %d sel %d)\n", rn, reg, sel);
ths9c2149c2007-01-23 22:45:22 +00005854 generate_exception(ctx, EXCP_RI);
5855}
5856
Aurelien Jarnod75c1352013-01-01 18:02:22 +01005857static void gen_dmtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
ths9c2149c2007-01-23 22:45:22 +00005858{
5859 const char *rn = "invalid";
5860
thse189e742007-09-24 12:48:00 +00005861 if (sel != 0)
Aurelien Jarnod75c1352013-01-01 18:02:22 +01005862 check_insn(ctx, ISA_MIPS64);
thse189e742007-09-24 12:48:00 +00005863
pbrook2e70f6e2008-06-29 01:03:05 +00005864 if (use_icount)
5865 gen_io_start();
5866
ths9c2149c2007-01-23 22:45:22 +00005867 switch (reg) {
5868 case 0:
5869 switch (sel) {
5870 case 0:
Blue Swirl895c2d02012-09-02 14:52:59 +00005871 gen_helper_mtc0_index(cpu_env, arg);
ths9c2149c2007-01-23 22:45:22 +00005872 rn = "Index";
5873 break;
5874 case 1:
Aurelien Jarnod75c1352013-01-01 18:02:22 +01005875 check_insn(ctx, ASE_MT);
Blue Swirl895c2d02012-09-02 14:52:59 +00005876 gen_helper_mtc0_mvpcontrol(cpu_env, arg);
ths9c2149c2007-01-23 22:45:22 +00005877 rn = "MVPControl";
thsead93602007-09-06 00:18:15 +00005878 break;
ths9c2149c2007-01-23 22:45:22 +00005879 case 2:
Aurelien Jarnod75c1352013-01-01 18:02:22 +01005880 check_insn(ctx, ASE_MT);
thsead93602007-09-06 00:18:15 +00005881 /* ignored */
ths9c2149c2007-01-23 22:45:22 +00005882 rn = "MVPConf0";
thsead93602007-09-06 00:18:15 +00005883 break;
ths9c2149c2007-01-23 22:45:22 +00005884 case 3:
Aurelien Jarnod75c1352013-01-01 18:02:22 +01005885 check_insn(ctx, ASE_MT);
thsead93602007-09-06 00:18:15 +00005886 /* ignored */
ths9c2149c2007-01-23 22:45:22 +00005887 rn = "MVPConf1";
thsead93602007-09-06 00:18:15 +00005888 break;
ths9c2149c2007-01-23 22:45:22 +00005889 default:
5890 goto die;
5891 }
5892 break;
5893 case 1:
5894 switch (sel) {
5895 case 0:
ths2423f662007-04-11 02:15:08 +00005896 /* ignored */
ths9c2149c2007-01-23 22:45:22 +00005897 rn = "Random";
ths2423f662007-04-11 02:15:08 +00005898 break;
ths9c2149c2007-01-23 22:45:22 +00005899 case 1:
Aurelien Jarnod75c1352013-01-01 18:02:22 +01005900 check_insn(ctx, ASE_MT);
Blue Swirl895c2d02012-09-02 14:52:59 +00005901 gen_helper_mtc0_vpecontrol(cpu_env, arg);
ths9c2149c2007-01-23 22:45:22 +00005902 rn = "VPEControl";
thsead93602007-09-06 00:18:15 +00005903 break;
ths9c2149c2007-01-23 22:45:22 +00005904 case 2:
Aurelien Jarnod75c1352013-01-01 18:02:22 +01005905 check_insn(ctx, ASE_MT);
Blue Swirl895c2d02012-09-02 14:52:59 +00005906 gen_helper_mtc0_vpeconf0(cpu_env, arg);
ths9c2149c2007-01-23 22:45:22 +00005907 rn = "VPEConf0";
thsead93602007-09-06 00:18:15 +00005908 break;
ths9c2149c2007-01-23 22:45:22 +00005909 case 3:
Aurelien Jarnod75c1352013-01-01 18:02:22 +01005910 check_insn(ctx, ASE_MT);
Blue Swirl895c2d02012-09-02 14:52:59 +00005911 gen_helper_mtc0_vpeconf1(cpu_env, arg);
ths9c2149c2007-01-23 22:45:22 +00005912 rn = "VPEConf1";
thsead93602007-09-06 00:18:15 +00005913 break;
ths9c2149c2007-01-23 22:45:22 +00005914 case 4:
Aurelien Jarnod75c1352013-01-01 18:02:22 +01005915 check_insn(ctx, ASE_MT);
Blue Swirl895c2d02012-09-02 14:52:59 +00005916 gen_helper_mtc0_yqmask(cpu_env, arg);
ths9c2149c2007-01-23 22:45:22 +00005917 rn = "YQMask";
thsead93602007-09-06 00:18:15 +00005918 break;
ths9c2149c2007-01-23 22:45:22 +00005919 case 5:
Aurelien Jarnod75c1352013-01-01 18:02:22 +01005920 check_insn(ctx, ASE_MT);
Andreas Färber7db13fa2012-03-14 01:38:22 +01005921 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_VPESchedule));
ths9c2149c2007-01-23 22:45:22 +00005922 rn = "VPESchedule";
thsead93602007-09-06 00:18:15 +00005923 break;
ths9c2149c2007-01-23 22:45:22 +00005924 case 6:
Aurelien Jarnod75c1352013-01-01 18:02:22 +01005925 check_insn(ctx, ASE_MT);
Andreas Färber7db13fa2012-03-14 01:38:22 +01005926 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_VPEScheFBack));
ths9c2149c2007-01-23 22:45:22 +00005927 rn = "VPEScheFBack";
thsead93602007-09-06 00:18:15 +00005928 break;
ths9c2149c2007-01-23 22:45:22 +00005929 case 7:
Aurelien Jarnod75c1352013-01-01 18:02:22 +01005930 check_insn(ctx, ASE_MT);
Blue Swirl895c2d02012-09-02 14:52:59 +00005931 gen_helper_mtc0_vpeopt(cpu_env, arg);
ths9c2149c2007-01-23 22:45:22 +00005932 rn = "VPEOpt";
thsead93602007-09-06 00:18:15 +00005933 break;
ths9c2149c2007-01-23 22:45:22 +00005934 default:
5935 goto die;
5936 }
5937 break;
5938 case 2:
5939 switch (sel) {
5940 case 0:
Blue Swirl895c2d02012-09-02 14:52:59 +00005941 gen_helper_mtc0_entrylo0(cpu_env, arg);
ths2423f662007-04-11 02:15:08 +00005942 rn = "EntryLo0";
5943 break;
ths9c2149c2007-01-23 22:45:22 +00005944 case 1:
Aurelien Jarnod75c1352013-01-01 18:02:22 +01005945 check_insn(ctx, ASE_MT);
Blue Swirl895c2d02012-09-02 14:52:59 +00005946 gen_helper_mtc0_tcstatus(cpu_env, arg);
ths2423f662007-04-11 02:15:08 +00005947 rn = "TCStatus";
thsead93602007-09-06 00:18:15 +00005948 break;
ths9c2149c2007-01-23 22:45:22 +00005949 case 2:
Aurelien Jarnod75c1352013-01-01 18:02:22 +01005950 check_insn(ctx, ASE_MT);
Blue Swirl895c2d02012-09-02 14:52:59 +00005951 gen_helper_mtc0_tcbind(cpu_env, arg);
ths2423f662007-04-11 02:15:08 +00005952 rn = "TCBind";
thsead93602007-09-06 00:18:15 +00005953 break;
ths9c2149c2007-01-23 22:45:22 +00005954 case 3:
Aurelien Jarnod75c1352013-01-01 18:02:22 +01005955 check_insn(ctx, ASE_MT);
Blue Swirl895c2d02012-09-02 14:52:59 +00005956 gen_helper_mtc0_tcrestart(cpu_env, arg);
ths2423f662007-04-11 02:15:08 +00005957 rn = "TCRestart";
thsead93602007-09-06 00:18:15 +00005958 break;
ths9c2149c2007-01-23 22:45:22 +00005959 case 4:
Aurelien Jarnod75c1352013-01-01 18:02:22 +01005960 check_insn(ctx, ASE_MT);
Blue Swirl895c2d02012-09-02 14:52:59 +00005961 gen_helper_mtc0_tchalt(cpu_env, arg);
ths2423f662007-04-11 02:15:08 +00005962 rn = "TCHalt";
thsead93602007-09-06 00:18:15 +00005963 break;
ths9c2149c2007-01-23 22:45:22 +00005964 case 5:
Aurelien Jarnod75c1352013-01-01 18:02:22 +01005965 check_insn(ctx, ASE_MT);
Blue Swirl895c2d02012-09-02 14:52:59 +00005966 gen_helper_mtc0_tccontext(cpu_env, arg);
ths2423f662007-04-11 02:15:08 +00005967 rn = "TCContext";
thsead93602007-09-06 00:18:15 +00005968 break;
ths9c2149c2007-01-23 22:45:22 +00005969 case 6:
Aurelien Jarnod75c1352013-01-01 18:02:22 +01005970 check_insn(ctx, ASE_MT);
Blue Swirl895c2d02012-09-02 14:52:59 +00005971 gen_helper_mtc0_tcschedule(cpu_env, arg);
ths2423f662007-04-11 02:15:08 +00005972 rn = "TCSchedule";
thsead93602007-09-06 00:18:15 +00005973 break;
ths9c2149c2007-01-23 22:45:22 +00005974 case 7:
Aurelien Jarnod75c1352013-01-01 18:02:22 +01005975 check_insn(ctx, ASE_MT);
Blue Swirl895c2d02012-09-02 14:52:59 +00005976 gen_helper_mtc0_tcschefback(cpu_env, arg);
ths2423f662007-04-11 02:15:08 +00005977 rn = "TCScheFBack";
thsead93602007-09-06 00:18:15 +00005978 break;
ths9c2149c2007-01-23 22:45:22 +00005979 default:
5980 goto die;
5981 }
5982 break;
5983 case 3:
5984 switch (sel) {
5985 case 0:
Blue Swirl895c2d02012-09-02 14:52:59 +00005986 gen_helper_mtc0_entrylo1(cpu_env, arg);
ths2423f662007-04-11 02:15:08 +00005987 rn = "EntryLo1";
5988 break;
ths9c2149c2007-01-23 22:45:22 +00005989 default:
5990 goto die;
ths876d4b02007-04-04 21:07:17 +00005991 }
ths9c2149c2007-01-23 22:45:22 +00005992 break;
5993 case 4:
5994 switch (sel) {
5995 case 0:
Blue Swirl895c2d02012-09-02 14:52:59 +00005996 gen_helper_mtc0_context(cpu_env, arg);
ths2423f662007-04-11 02:15:08 +00005997 rn = "Context";
5998 break;
ths9c2149c2007-01-23 22:45:22 +00005999 case 1:
Blue Swirl895c2d02012-09-02 14:52:59 +00006000// gen_helper_mtc0_contextconfig(cpu_env, arg); /* SmartMIPS ASE */
ths2423f662007-04-11 02:15:08 +00006001 rn = "ContextConfig";
6002// break;
ths9c2149c2007-01-23 22:45:22 +00006003 default:
6004 goto die;
ths876d4b02007-04-04 21:07:17 +00006005 }
ths9c2149c2007-01-23 22:45:22 +00006006 break;
6007 case 5:
6008 switch (sel) {
6009 case 0:
Blue Swirl895c2d02012-09-02 14:52:59 +00006010 gen_helper_mtc0_pagemask(cpu_env, arg);
ths2423f662007-04-11 02:15:08 +00006011 rn = "PageMask";
6012 break;
ths9c2149c2007-01-23 22:45:22 +00006013 case 1:
Aurelien Jarnod75c1352013-01-01 18:02:22 +01006014 check_insn(ctx, ISA_MIPS32R2);
Blue Swirl895c2d02012-09-02 14:52:59 +00006015 gen_helper_mtc0_pagegrain(cpu_env, arg);
ths2423f662007-04-11 02:15:08 +00006016 rn = "PageGrain";
6017 break;
ths9c2149c2007-01-23 22:45:22 +00006018 default:
6019 goto die;
ths876d4b02007-04-04 21:07:17 +00006020 }
ths9c2149c2007-01-23 22:45:22 +00006021 break;
6022 case 6:
6023 switch (sel) {
6024 case 0:
Blue Swirl895c2d02012-09-02 14:52:59 +00006025 gen_helper_mtc0_wired(cpu_env, arg);
ths2423f662007-04-11 02:15:08 +00006026 rn = "Wired";
6027 break;
ths9c2149c2007-01-23 22:45:22 +00006028 case 1:
Aurelien Jarnod75c1352013-01-01 18:02:22 +01006029 check_insn(ctx, ISA_MIPS32R2);
Blue Swirl895c2d02012-09-02 14:52:59 +00006030 gen_helper_mtc0_srsconf0(cpu_env, arg);
ths2423f662007-04-11 02:15:08 +00006031 rn = "SRSConf0";
thsead93602007-09-06 00:18:15 +00006032 break;
ths9c2149c2007-01-23 22:45:22 +00006033 case 2:
Aurelien Jarnod75c1352013-01-01 18:02:22 +01006034 check_insn(ctx, ISA_MIPS32R2);
Blue Swirl895c2d02012-09-02 14:52:59 +00006035 gen_helper_mtc0_srsconf1(cpu_env, arg);
ths2423f662007-04-11 02:15:08 +00006036 rn = "SRSConf1";
thsead93602007-09-06 00:18:15 +00006037 break;
ths9c2149c2007-01-23 22:45:22 +00006038 case 3:
Aurelien Jarnod75c1352013-01-01 18:02:22 +01006039 check_insn(ctx, ISA_MIPS32R2);
Blue Swirl895c2d02012-09-02 14:52:59 +00006040 gen_helper_mtc0_srsconf2(cpu_env, arg);
ths2423f662007-04-11 02:15:08 +00006041 rn = "SRSConf2";
thsead93602007-09-06 00:18:15 +00006042 break;
ths9c2149c2007-01-23 22:45:22 +00006043 case 4:
Aurelien Jarnod75c1352013-01-01 18:02:22 +01006044 check_insn(ctx, ISA_MIPS32R2);
Blue Swirl895c2d02012-09-02 14:52:59 +00006045 gen_helper_mtc0_srsconf3(cpu_env, arg);
ths2423f662007-04-11 02:15:08 +00006046 rn = "SRSConf3";
thsead93602007-09-06 00:18:15 +00006047 break;
ths9c2149c2007-01-23 22:45:22 +00006048 case 5:
Aurelien Jarnod75c1352013-01-01 18:02:22 +01006049 check_insn(ctx, ISA_MIPS32R2);
Blue Swirl895c2d02012-09-02 14:52:59 +00006050 gen_helper_mtc0_srsconf4(cpu_env, arg);
ths2423f662007-04-11 02:15:08 +00006051 rn = "SRSConf4";
thsead93602007-09-06 00:18:15 +00006052 break;
ths9c2149c2007-01-23 22:45:22 +00006053 default:
6054 goto die;
ths876d4b02007-04-04 21:07:17 +00006055 }
ths9c2149c2007-01-23 22:45:22 +00006056 break;
6057 case 7:
6058 switch (sel) {
6059 case 0:
Aurelien Jarnod75c1352013-01-01 18:02:22 +01006060 check_insn(ctx, ISA_MIPS32R2);
Blue Swirl895c2d02012-09-02 14:52:59 +00006061 gen_helper_mtc0_hwrena(cpu_env, arg);
ths2423f662007-04-11 02:15:08 +00006062 rn = "HWREna";
6063 break;
ths9c2149c2007-01-23 22:45:22 +00006064 default:
6065 goto die;
ths876d4b02007-04-04 21:07:17 +00006066 }
ths9c2149c2007-01-23 22:45:22 +00006067 break;
6068 case 8:
6069 /* ignored */
thsf0b3f3a2008-05-23 18:10:51 +00006070 rn = "BadVAddr";
ths9c2149c2007-01-23 22:45:22 +00006071 break;
6072 case 9:
6073 switch (sel) {
6074 case 0:
Blue Swirl895c2d02012-09-02 14:52:59 +00006075 gen_helper_mtc0_count(cpu_env, arg);
ths2423f662007-04-11 02:15:08 +00006076 rn = "Count";
6077 break;
ths876d4b02007-04-04 21:07:17 +00006078 /* 6,7 are implementation dependent */
ths9c2149c2007-01-23 22:45:22 +00006079 default:
6080 goto die;
ths876d4b02007-04-04 21:07:17 +00006081 }
6082 /* Stop translation as we may have switched the execution mode */
6083 ctx->bstate = BS_STOP;
ths9c2149c2007-01-23 22:45:22 +00006084 break;
6085 case 10:
6086 switch (sel) {
6087 case 0:
Blue Swirl895c2d02012-09-02 14:52:59 +00006088 gen_helper_mtc0_entryhi(cpu_env, arg);
ths2423f662007-04-11 02:15:08 +00006089 rn = "EntryHi";
6090 break;
ths9c2149c2007-01-23 22:45:22 +00006091 default:
6092 goto die;
ths876d4b02007-04-04 21:07:17 +00006093 }
ths9c2149c2007-01-23 22:45:22 +00006094 break;
6095 case 11:
6096 switch (sel) {
6097 case 0:
Blue Swirl895c2d02012-09-02 14:52:59 +00006098 gen_helper_mtc0_compare(cpu_env, arg);
ths2423f662007-04-11 02:15:08 +00006099 rn = "Compare";
6100 break;
ths876d4b02007-04-04 21:07:17 +00006101 /* 6,7 are implementation dependent */
ths9c2149c2007-01-23 22:45:22 +00006102 default:
6103 goto die;
ths876d4b02007-04-04 21:07:17 +00006104 }
aurel32de9a95f2008-11-11 13:41:01 +00006105 /* Stop translation as we may have switched the execution mode */
6106 ctx->bstate = BS_STOP;
ths9c2149c2007-01-23 22:45:22 +00006107 break;
6108 case 12:
6109 switch (sel) {
6110 case 0:
aurel32867abc72009-04-13 08:53:12 +00006111 save_cpu_state(ctx, 1);
Blue Swirl895c2d02012-09-02 14:52:59 +00006112 gen_helper_mtc0_status(cpu_env, arg);
ths84873272007-06-01 17:47:07 +00006113 /* BS_STOP isn't good enough here, hflags may have changed. */
6114 gen_save_pc(ctx->pc + 4);
6115 ctx->bstate = BS_EXCP;
ths2423f662007-04-11 02:15:08 +00006116 rn = "Status";
6117 break;
ths9c2149c2007-01-23 22:45:22 +00006118 case 1:
Aurelien Jarnod75c1352013-01-01 18:02:22 +01006119 check_insn(ctx, ISA_MIPS32R2);
Blue Swirl895c2d02012-09-02 14:52:59 +00006120 gen_helper_mtc0_intctl(cpu_env, arg);
ths84873272007-06-01 17:47:07 +00006121 /* Stop translation as we may have switched the execution mode */
6122 ctx->bstate = BS_STOP;
ths2423f662007-04-11 02:15:08 +00006123 rn = "IntCtl";
6124 break;
ths9c2149c2007-01-23 22:45:22 +00006125 case 2:
Aurelien Jarnod75c1352013-01-01 18:02:22 +01006126 check_insn(ctx, ISA_MIPS32R2);
Blue Swirl895c2d02012-09-02 14:52:59 +00006127 gen_helper_mtc0_srsctl(cpu_env, arg);
ths84873272007-06-01 17:47:07 +00006128 /* Stop translation as we may have switched the execution mode */
6129 ctx->bstate = BS_STOP;
ths2423f662007-04-11 02:15:08 +00006130 rn = "SRSCtl";
6131 break;
ths9c2149c2007-01-23 22:45:22 +00006132 case 3:
Aurelien Jarnod75c1352013-01-01 18:02:22 +01006133 check_insn(ctx, ISA_MIPS32R2);
Andreas Färber7db13fa2012-03-14 01:38:22 +01006134 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
ths84873272007-06-01 17:47:07 +00006135 /* Stop translation as we may have switched the execution mode */
6136 ctx->bstate = BS_STOP;
ths2423f662007-04-11 02:15:08 +00006137 rn = "SRSMap";
6138 break;
6139 default:
ths9c2149c2007-01-23 22:45:22 +00006140 goto die;
ths876d4b02007-04-04 21:07:17 +00006141 }
ths9c2149c2007-01-23 22:45:22 +00006142 break;
6143 case 13:
6144 switch (sel) {
6145 case 0:
aurel32867abc72009-04-13 08:53:12 +00006146 save_cpu_state(ctx, 1);
Aurelien Jarno5dc5d9f2010-07-25 16:51:29 +02006147 /* Mark as an IO operation because we may trigger a software
6148 interrupt. */
6149 if (use_icount) {
6150 gen_io_start();
6151 }
Blue Swirl895c2d02012-09-02 14:52:59 +00006152 gen_helper_mtc0_cause(cpu_env, arg);
Aurelien Jarno5dc5d9f2010-07-25 16:51:29 +02006153 if (use_icount) {
6154 gen_io_end();
6155 }
6156 /* Stop translation as we may have triggered an intetrupt */
6157 ctx->bstate = BS_STOP;
ths2423f662007-04-11 02:15:08 +00006158 rn = "Cause";
6159 break;
ths9c2149c2007-01-23 22:45:22 +00006160 default:
6161 goto die;
ths876d4b02007-04-04 21:07:17 +00006162 }
ths9c2149c2007-01-23 22:45:22 +00006163 break;
6164 case 14:
6165 switch (sel) {
6166 case 0:
Andreas Färber7db13fa2012-03-14 01:38:22 +01006167 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EPC));
ths2423f662007-04-11 02:15:08 +00006168 rn = "EPC";
6169 break;
ths9c2149c2007-01-23 22:45:22 +00006170 default:
6171 goto die;
ths876d4b02007-04-04 21:07:17 +00006172 }
ths9c2149c2007-01-23 22:45:22 +00006173 break;
6174 case 15:
6175 switch (sel) {
6176 case 0:
ths2423f662007-04-11 02:15:08 +00006177 /* ignored */
6178 rn = "PRid";
6179 break;
ths9c2149c2007-01-23 22:45:22 +00006180 case 1:
Aurelien Jarnod75c1352013-01-01 18:02:22 +01006181 check_insn(ctx, ISA_MIPS32R2);
Blue Swirl895c2d02012-09-02 14:52:59 +00006182 gen_helper_mtc0_ebase(cpu_env, arg);
ths2423f662007-04-11 02:15:08 +00006183 rn = "EBase";
6184 break;
ths9c2149c2007-01-23 22:45:22 +00006185 default:
6186 goto die;
ths876d4b02007-04-04 21:07:17 +00006187 }
ths9c2149c2007-01-23 22:45:22 +00006188 break;
6189 case 16:
6190 switch (sel) {
6191 case 0:
Blue Swirl895c2d02012-09-02 14:52:59 +00006192 gen_helper_mtc0_config0(cpu_env, arg);
ths9c2149c2007-01-23 22:45:22 +00006193 rn = "Config";
ths2423f662007-04-11 02:15:08 +00006194 /* Stop translation as we may have switched the execution mode */
6195 ctx->bstate = BS_STOP;
ths9c2149c2007-01-23 22:45:22 +00006196 break;
6197 case 1:
aurel321fc7bf62009-04-08 21:47:35 +00006198 /* ignored, read only */
ths9c2149c2007-01-23 22:45:22 +00006199 rn = "Config1";
6200 break;
6201 case 2:
Blue Swirl895c2d02012-09-02 14:52:59 +00006202 gen_helper_mtc0_config2(cpu_env, arg);
ths9c2149c2007-01-23 22:45:22 +00006203 rn = "Config2";
ths2423f662007-04-11 02:15:08 +00006204 /* Stop translation as we may have switched the execution mode */
6205 ctx->bstate = BS_STOP;
ths9c2149c2007-01-23 22:45:22 +00006206 break;
6207 case 3:
ths2423f662007-04-11 02:15:08 +00006208 /* ignored */
ths9c2149c2007-01-23 22:45:22 +00006209 rn = "Config3";
6210 break;
6211 /* 6,7 are implementation dependent */
6212 default:
6213 rn = "Invalid config selector";
6214 goto die;
6215 }
ths9c2149c2007-01-23 22:45:22 +00006216 break;
6217 case 17:
6218 switch (sel) {
6219 case 0:
Blue Swirl895c2d02012-09-02 14:52:59 +00006220 gen_helper_mtc0_lladdr(cpu_env, arg);
ths2423f662007-04-11 02:15:08 +00006221 rn = "LLAddr";
6222 break;
ths9c2149c2007-01-23 22:45:22 +00006223 default:
6224 goto die;
6225 }
6226 break;
6227 case 18:
6228 switch (sel) {
thsfd88b6a2007-05-23 08:24:25 +00006229 case 0 ... 7:
Blue Swirl895c2d02012-09-02 14:52:59 +00006230 gen_helper_0e1i(mtc0_watchlo, arg, sel);
ths2423f662007-04-11 02:15:08 +00006231 rn = "WatchLo";
6232 break;
ths9c2149c2007-01-23 22:45:22 +00006233 default:
6234 goto die;
6235 }
6236 break;
6237 case 19:
6238 switch (sel) {
thsfd88b6a2007-05-23 08:24:25 +00006239 case 0 ... 7:
Blue Swirl895c2d02012-09-02 14:52:59 +00006240 gen_helper_0e1i(mtc0_watchhi, arg, sel);
ths2423f662007-04-11 02:15:08 +00006241 rn = "WatchHi";
6242 break;
ths9c2149c2007-01-23 22:45:22 +00006243 default:
6244 goto die;
6245 }
6246 break;
6247 case 20:
6248 switch (sel) {
6249 case 0:
Aurelien Jarnod75c1352013-01-01 18:02:22 +01006250 check_insn(ctx, ISA_MIPS3);
Blue Swirl895c2d02012-09-02 14:52:59 +00006251 gen_helper_mtc0_xcontext(cpu_env, arg);
ths2423f662007-04-11 02:15:08 +00006252 rn = "XContext";
6253 break;
ths9c2149c2007-01-23 22:45:22 +00006254 default:
6255 goto die;
6256 }
6257 break;
6258 case 21:
6259 /* Officially reserved, but sel 0 is used for R1x000 framemask */
6260 switch (sel) {
6261 case 0:
Blue Swirl895c2d02012-09-02 14:52:59 +00006262 gen_helper_mtc0_framemask(cpu_env, arg);
ths2423f662007-04-11 02:15:08 +00006263 rn = "Framemask";
6264 break;
ths9c2149c2007-01-23 22:45:22 +00006265 default:
6266 goto die;
6267 }
6268 break;
6269 case 22:
6270 /* ignored */
6271 rn = "Diagnostic"; /* implementation dependent */
ths876d4b02007-04-04 21:07:17 +00006272 break;
ths9c2149c2007-01-23 22:45:22 +00006273 case 23:
6274 switch (sel) {
6275 case 0:
Blue Swirl895c2d02012-09-02 14:52:59 +00006276 gen_helper_mtc0_debug(cpu_env, arg); /* EJTAG support */
ths84873272007-06-01 17:47:07 +00006277 /* BS_STOP isn't good enough here, hflags may have changed. */
6278 gen_save_pc(ctx->pc + 4);
6279 ctx->bstate = BS_EXCP;
ths2423f662007-04-11 02:15:08 +00006280 rn = "Debug";
6281 break;
ths9c2149c2007-01-23 22:45:22 +00006282 case 1:
Blue Swirl895c2d02012-09-02 14:52:59 +00006283// gen_helper_mtc0_tracecontrol(cpu_env, arg); /* PDtrace support */
ths84873272007-06-01 17:47:07 +00006284 /* Stop translation as we may have switched the execution mode */
6285 ctx->bstate = BS_STOP;
ths2423f662007-04-11 02:15:08 +00006286 rn = "TraceControl";
6287// break;
ths9c2149c2007-01-23 22:45:22 +00006288 case 2:
Blue Swirl895c2d02012-09-02 14:52:59 +00006289// gen_helper_mtc0_tracecontrol2(cpu_env, arg); /* PDtrace support */
ths84873272007-06-01 17:47:07 +00006290 /* Stop translation as we may have switched the execution mode */
6291 ctx->bstate = BS_STOP;
ths2423f662007-04-11 02:15:08 +00006292 rn = "TraceControl2";
6293// break;
ths9c2149c2007-01-23 22:45:22 +00006294 case 3:
Blue Swirl895c2d02012-09-02 14:52:59 +00006295// gen_helper_mtc0_usertracedata(cpu_env, arg); /* PDtrace support */
ths84873272007-06-01 17:47:07 +00006296 /* Stop translation as we may have switched the execution mode */
6297 ctx->bstate = BS_STOP;
ths2423f662007-04-11 02:15:08 +00006298 rn = "UserTraceData";
6299// break;
ths9c2149c2007-01-23 22:45:22 +00006300 case 4:
Blue Swirl895c2d02012-09-02 14:52:59 +00006301// gen_helper_mtc0_tracebpc(cpu_env, arg); /* PDtrace support */
ths84873272007-06-01 17:47:07 +00006302 /* Stop translation as we may have switched the execution mode */
6303 ctx->bstate = BS_STOP;
ths2423f662007-04-11 02:15:08 +00006304 rn = "TraceBPC";
6305// break;
ths9c2149c2007-01-23 22:45:22 +00006306 default:
6307 goto die;
6308 }
ths9c2149c2007-01-23 22:45:22 +00006309 break;
6310 case 24:
6311 switch (sel) {
6312 case 0:
thsf1aa6322008-06-09 07:13:38 +00006313 /* EJTAG support */
Andreas Färber7db13fa2012-03-14 01:38:22 +01006314 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_DEPC));
ths2423f662007-04-11 02:15:08 +00006315 rn = "DEPC";
6316 break;
ths9c2149c2007-01-23 22:45:22 +00006317 default:
6318 goto die;
6319 }
6320 break;
6321 case 25:
6322 switch (sel) {
6323 case 0:
Blue Swirl895c2d02012-09-02 14:52:59 +00006324 gen_helper_mtc0_performance0(cpu_env, arg);
ths2423f662007-04-11 02:15:08 +00006325 rn = "Performance0";
6326 break;
ths9c2149c2007-01-23 22:45:22 +00006327 case 1:
Blue Swirl895c2d02012-09-02 14:52:59 +00006328// gen_helper_mtc0_performance1(cpu_env, arg);
ths2423f662007-04-11 02:15:08 +00006329 rn = "Performance1";
6330// break;
ths9c2149c2007-01-23 22:45:22 +00006331 case 2:
Blue Swirl895c2d02012-09-02 14:52:59 +00006332// gen_helper_mtc0_performance2(cpu_env, arg);
ths2423f662007-04-11 02:15:08 +00006333 rn = "Performance2";
6334// break;
ths9c2149c2007-01-23 22:45:22 +00006335 case 3:
Blue Swirl895c2d02012-09-02 14:52:59 +00006336// gen_helper_mtc0_performance3(cpu_env, arg);
ths2423f662007-04-11 02:15:08 +00006337 rn = "Performance3";
6338// break;
ths9c2149c2007-01-23 22:45:22 +00006339 case 4:
Blue Swirl895c2d02012-09-02 14:52:59 +00006340// gen_helper_mtc0_performance4(cpu_env, arg);
ths2423f662007-04-11 02:15:08 +00006341 rn = "Performance4";
6342// break;
ths9c2149c2007-01-23 22:45:22 +00006343 case 5:
Blue Swirl895c2d02012-09-02 14:52:59 +00006344// gen_helper_mtc0_performance5(cpu_env, arg);
ths2423f662007-04-11 02:15:08 +00006345 rn = "Performance5";
6346// break;
ths9c2149c2007-01-23 22:45:22 +00006347 case 6:
Blue Swirl895c2d02012-09-02 14:52:59 +00006348// gen_helper_mtc0_performance6(cpu_env, arg);
ths2423f662007-04-11 02:15:08 +00006349 rn = "Performance6";
6350// break;
ths9c2149c2007-01-23 22:45:22 +00006351 case 7:
Blue Swirl895c2d02012-09-02 14:52:59 +00006352// gen_helper_mtc0_performance7(cpu_env, arg);
ths2423f662007-04-11 02:15:08 +00006353 rn = "Performance7";
6354// break;
ths9c2149c2007-01-23 22:45:22 +00006355 default:
6356 goto die;
6357 }
ths876d4b02007-04-04 21:07:17 +00006358 break;
ths9c2149c2007-01-23 22:45:22 +00006359 case 26:
ths876d4b02007-04-04 21:07:17 +00006360 /* ignored */
ths9c2149c2007-01-23 22:45:22 +00006361 rn = "ECC";
ths876d4b02007-04-04 21:07:17 +00006362 break;
ths9c2149c2007-01-23 22:45:22 +00006363 case 27:
6364 switch (sel) {
6365 case 0 ... 3:
ths2423f662007-04-11 02:15:08 +00006366 /* ignored */
6367 rn = "CacheErr";
6368 break;
ths9c2149c2007-01-23 22:45:22 +00006369 default:
6370 goto die;
6371 }
ths876d4b02007-04-04 21:07:17 +00006372 break;
ths9c2149c2007-01-23 22:45:22 +00006373 case 28:
6374 switch (sel) {
6375 case 0:
6376 case 2:
6377 case 4:
6378 case 6:
Blue Swirl895c2d02012-09-02 14:52:59 +00006379 gen_helper_mtc0_taglo(cpu_env, arg);
ths9c2149c2007-01-23 22:45:22 +00006380 rn = "TagLo";
6381 break;
6382 case 1:
6383 case 3:
6384 case 5:
6385 case 7:
Blue Swirl895c2d02012-09-02 14:52:59 +00006386 gen_helper_mtc0_datalo(cpu_env, arg);
ths9c2149c2007-01-23 22:45:22 +00006387 rn = "DataLo";
6388 break;
6389 default:
6390 goto die;
6391 }
6392 break;
6393 case 29:
6394 switch (sel) {
6395 case 0:
6396 case 2:
6397 case 4:
6398 case 6:
Blue Swirl895c2d02012-09-02 14:52:59 +00006399 gen_helper_mtc0_taghi(cpu_env, arg);
ths9c2149c2007-01-23 22:45:22 +00006400 rn = "TagHi";
6401 break;
6402 case 1:
6403 case 3:
6404 case 5:
6405 case 7:
Blue Swirl895c2d02012-09-02 14:52:59 +00006406 gen_helper_mtc0_datahi(cpu_env, arg);
ths9c2149c2007-01-23 22:45:22 +00006407 rn = "DataHi";
6408 break;
6409 default:
6410 rn = "invalid sel";
6411 goto die;
6412 }
ths876d4b02007-04-04 21:07:17 +00006413 break;
ths9c2149c2007-01-23 22:45:22 +00006414 case 30:
6415 switch (sel) {
6416 case 0:
Andreas Färber7db13fa2012-03-14 01:38:22 +01006417 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_ErrorEPC));
ths2423f662007-04-11 02:15:08 +00006418 rn = "ErrorEPC";
6419 break;
ths9c2149c2007-01-23 22:45:22 +00006420 default:
6421 goto die;
6422 }
6423 break;
6424 case 31:
6425 switch (sel) {
6426 case 0:
thsf1aa6322008-06-09 07:13:38 +00006427 /* EJTAG support */
Andreas Färber7db13fa2012-03-14 01:38:22 +01006428 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
ths2423f662007-04-11 02:15:08 +00006429 rn = "DESAVE";
6430 break;
ths9c2149c2007-01-23 22:45:22 +00006431 default:
6432 goto die;
6433 }
ths876d4b02007-04-04 21:07:17 +00006434 /* Stop translation as we may have switched the execution mode */
6435 ctx->bstate = BS_STOP;
ths9c2149c2007-01-23 22:45:22 +00006436 break;
6437 default:
ths876d4b02007-04-04 21:07:17 +00006438 goto die;
ths9c2149c2007-01-23 22:45:22 +00006439 }
Blue Swirl2abf3142010-10-13 18:38:08 +00006440 (void)rn; /* avoid a compiler warning */
aliguorid12d51d2009-01-15 21:48:06 +00006441 LOG_DISAS("dmtc0 %s (reg %d sel %d)\n", rn, reg, sel);
thsbf20dc02008-06-30 17:22:19 +00006442 /* For simplicity assume that all writes can cause interrupts. */
pbrook2e70f6e2008-06-29 01:03:05 +00006443 if (use_icount) {
6444 gen_io_end();
6445 ctx->bstate = BS_STOP;
6446 }
ths9c2149c2007-01-23 22:45:22 +00006447 return;
6448
6449die:
aliguorid12d51d2009-01-15 21:48:06 +00006450 LOG_DISAS("dmtc0 %s (reg %d sel %d)\n", rn, reg, sel);
ths9c2149c2007-01-23 22:45:22 +00006451 generate_exception(ctx, EXCP_RI);
6452}
thsd26bc212007-11-08 18:05:37 +00006453#endif /* TARGET_MIPS64 */
ths9c2149c2007-01-23 22:45:22 +00006454
Andreas Färber7db13fa2012-03-14 01:38:22 +01006455static void gen_mftr(CPUMIPSState *env, DisasContext *ctx, int rt, int rd,
thsead93602007-09-06 00:18:15 +00006456 int u, int sel, int h)
6457{
6458 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
pbrooka7812ae2008-11-17 14:43:54 +00006459 TCGv t0 = tcg_temp_local_new();
thsead93602007-09-06 00:18:15 +00006460
6461 if ((env->CP0_VPEConf0 & (1 << CP0VPEC0_MVP)) == 0 &&
thsb5dc7732008-06-27 10:02:35 +00006462 ((env->tcs[other_tc].CP0_TCBind & (0xf << CP0TCBd_CurVPE)) !=
6463 (env->active_tc.CP0_TCBind & (0xf << CP0TCBd_CurVPE))))
ths1a3fd9c2008-06-24 21:58:35 +00006464 tcg_gen_movi_tl(t0, -1);
thsead93602007-09-06 00:18:15 +00006465 else if ((env->CP0_VPEControl & (0xff << CP0VPECo_TargTC)) >
6466 (env->mvp->CP0_MVPConf0 & (0xff << CP0MVPC0_PTC)))
ths1a3fd9c2008-06-24 21:58:35 +00006467 tcg_gen_movi_tl(t0, -1);
thsead93602007-09-06 00:18:15 +00006468 else if (u == 0) {
6469 switch (rt) {
Edgar E. Iglesias5a25ce92011-08-29 23:07:34 +02006470 case 1:
6471 switch (sel) {
6472 case 1:
Blue Swirl895c2d02012-09-02 14:52:59 +00006473 gen_helper_mftc0_vpecontrol(t0, cpu_env);
Edgar E. Iglesias5a25ce92011-08-29 23:07:34 +02006474 break;
6475 case 2:
Blue Swirl895c2d02012-09-02 14:52:59 +00006476 gen_helper_mftc0_vpeconf0(t0, cpu_env);
Edgar E. Iglesias5a25ce92011-08-29 23:07:34 +02006477 break;
6478 default:
6479 goto die;
6480 break;
6481 }
6482 break;
thsead93602007-09-06 00:18:15 +00006483 case 2:
6484 switch (sel) {
6485 case 1:
Blue Swirl895c2d02012-09-02 14:52:59 +00006486 gen_helper_mftc0_tcstatus(t0, cpu_env);
thsead93602007-09-06 00:18:15 +00006487 break;
6488 case 2:
Blue Swirl895c2d02012-09-02 14:52:59 +00006489 gen_helper_mftc0_tcbind(t0, cpu_env);
thsead93602007-09-06 00:18:15 +00006490 break;
6491 case 3:
Blue Swirl895c2d02012-09-02 14:52:59 +00006492 gen_helper_mftc0_tcrestart(t0, cpu_env);
thsead93602007-09-06 00:18:15 +00006493 break;
6494 case 4:
Blue Swirl895c2d02012-09-02 14:52:59 +00006495 gen_helper_mftc0_tchalt(t0, cpu_env);
thsead93602007-09-06 00:18:15 +00006496 break;
6497 case 5:
Blue Swirl895c2d02012-09-02 14:52:59 +00006498 gen_helper_mftc0_tccontext(t0, cpu_env);
thsead93602007-09-06 00:18:15 +00006499 break;
6500 case 6:
Blue Swirl895c2d02012-09-02 14:52:59 +00006501 gen_helper_mftc0_tcschedule(t0, cpu_env);
thsead93602007-09-06 00:18:15 +00006502 break;
6503 case 7:
Blue Swirl895c2d02012-09-02 14:52:59 +00006504 gen_helper_mftc0_tcschefback(t0, cpu_env);
thsead93602007-09-06 00:18:15 +00006505 break;
6506 default:
Aurelien Jarnod75c1352013-01-01 18:02:22 +01006507 gen_mfc0(ctx, t0, rt, sel);
thsead93602007-09-06 00:18:15 +00006508 break;
6509 }
6510 break;
6511 case 10:
6512 switch (sel) {
6513 case 0:
Blue Swirl895c2d02012-09-02 14:52:59 +00006514 gen_helper_mftc0_entryhi(t0, cpu_env);
thsead93602007-09-06 00:18:15 +00006515 break;
6516 default:
Aurelien Jarnod75c1352013-01-01 18:02:22 +01006517 gen_mfc0(ctx, t0, rt, sel);
thsead93602007-09-06 00:18:15 +00006518 break;
6519 }
6520 case 12:
6521 switch (sel) {
6522 case 0:
Blue Swirl895c2d02012-09-02 14:52:59 +00006523 gen_helper_mftc0_status(t0, cpu_env);
thsead93602007-09-06 00:18:15 +00006524 break;
6525 default:
Aurelien Jarnod75c1352013-01-01 18:02:22 +01006526 gen_mfc0(ctx, t0, rt, sel);
thsead93602007-09-06 00:18:15 +00006527 break;
6528 }
Edgar E. Iglesias5a25ce92011-08-29 23:07:34 +02006529 case 13:
6530 switch (sel) {
6531 case 0:
Blue Swirl895c2d02012-09-02 14:52:59 +00006532 gen_helper_mftc0_cause(t0, cpu_env);
Edgar E. Iglesias5a25ce92011-08-29 23:07:34 +02006533 break;
6534 default:
6535 goto die;
6536 break;
6537 }
6538 break;
6539 case 14:
6540 switch (sel) {
6541 case 0:
Blue Swirl895c2d02012-09-02 14:52:59 +00006542 gen_helper_mftc0_epc(t0, cpu_env);
Edgar E. Iglesias5a25ce92011-08-29 23:07:34 +02006543 break;
6544 default:
6545 goto die;
6546 break;
6547 }
6548 break;
6549 case 15:
6550 switch (sel) {
6551 case 1:
Blue Swirl895c2d02012-09-02 14:52:59 +00006552 gen_helper_mftc0_ebase(t0, cpu_env);
Edgar E. Iglesias5a25ce92011-08-29 23:07:34 +02006553 break;
6554 default:
6555 goto die;
6556 break;
6557 }
6558 break;
6559 case 16:
6560 switch (sel) {
6561 case 0 ... 7:
Blue Swirl895c2d02012-09-02 14:52:59 +00006562 gen_helper_mftc0_configx(t0, cpu_env, tcg_const_tl(sel));
Edgar E. Iglesias5a25ce92011-08-29 23:07:34 +02006563 break;
6564 default:
6565 goto die;
6566 break;
6567 }
6568 break;
thsead93602007-09-06 00:18:15 +00006569 case 23:
6570 switch (sel) {
6571 case 0:
Blue Swirl895c2d02012-09-02 14:52:59 +00006572 gen_helper_mftc0_debug(t0, cpu_env);
thsead93602007-09-06 00:18:15 +00006573 break;
6574 default:
Aurelien Jarnod75c1352013-01-01 18:02:22 +01006575 gen_mfc0(ctx, t0, rt, sel);
thsead93602007-09-06 00:18:15 +00006576 break;
6577 }
6578 break;
6579 default:
Aurelien Jarnod75c1352013-01-01 18:02:22 +01006580 gen_mfc0(ctx, t0, rt, sel);
thsead93602007-09-06 00:18:15 +00006581 }
6582 } else switch (sel) {
6583 /* GPR registers. */
6584 case 0:
Blue Swirl895c2d02012-09-02 14:52:59 +00006585 gen_helper_1e0i(mftgpr, t0, rt);
thsead93602007-09-06 00:18:15 +00006586 break;
6587 /* Auxiliary CPU registers */
6588 case 1:
6589 switch (rt) {
6590 case 0:
Blue Swirl895c2d02012-09-02 14:52:59 +00006591 gen_helper_1e0i(mftlo, t0, 0);
thsead93602007-09-06 00:18:15 +00006592 break;
6593 case 1:
Blue Swirl895c2d02012-09-02 14:52:59 +00006594 gen_helper_1e0i(mfthi, t0, 0);
thsead93602007-09-06 00:18:15 +00006595 break;
6596 case 2:
Blue Swirl895c2d02012-09-02 14:52:59 +00006597 gen_helper_1e0i(mftacx, t0, 0);
thsead93602007-09-06 00:18:15 +00006598 break;
6599 case 4:
Blue Swirl895c2d02012-09-02 14:52:59 +00006600 gen_helper_1e0i(mftlo, t0, 1);
thsead93602007-09-06 00:18:15 +00006601 break;
6602 case 5:
Blue Swirl895c2d02012-09-02 14:52:59 +00006603 gen_helper_1e0i(mfthi, t0, 1);
thsead93602007-09-06 00:18:15 +00006604 break;
6605 case 6:
Blue Swirl895c2d02012-09-02 14:52:59 +00006606 gen_helper_1e0i(mftacx, t0, 1);
thsead93602007-09-06 00:18:15 +00006607 break;
6608 case 8:
Blue Swirl895c2d02012-09-02 14:52:59 +00006609 gen_helper_1e0i(mftlo, t0, 2);
thsead93602007-09-06 00:18:15 +00006610 break;
6611 case 9:
Blue Swirl895c2d02012-09-02 14:52:59 +00006612 gen_helper_1e0i(mfthi, t0, 2);
thsead93602007-09-06 00:18:15 +00006613 break;
6614 case 10:
Blue Swirl895c2d02012-09-02 14:52:59 +00006615 gen_helper_1e0i(mftacx, t0, 2);
thsead93602007-09-06 00:18:15 +00006616 break;
6617 case 12:
Blue Swirl895c2d02012-09-02 14:52:59 +00006618 gen_helper_1e0i(mftlo, t0, 3);
thsead93602007-09-06 00:18:15 +00006619 break;
6620 case 13:
Blue Swirl895c2d02012-09-02 14:52:59 +00006621 gen_helper_1e0i(mfthi, t0, 3);
thsead93602007-09-06 00:18:15 +00006622 break;
6623 case 14:
Blue Swirl895c2d02012-09-02 14:52:59 +00006624 gen_helper_1e0i(mftacx, t0, 3);
thsead93602007-09-06 00:18:15 +00006625 break;
6626 case 16:
Blue Swirl895c2d02012-09-02 14:52:59 +00006627 gen_helper_mftdsp(t0, cpu_env);
thsead93602007-09-06 00:18:15 +00006628 break;
6629 default:
6630 goto die;
6631 }
6632 break;
6633 /* Floating point (COP1). */
6634 case 2:
6635 /* XXX: For now we support only a single FPU context. */
6636 if (h == 0) {
pbrooka7812ae2008-11-17 14:43:54 +00006637 TCGv_i32 fp0 = tcg_temp_new_i32();
thsb6d96be2008-07-09 11:05:10 +00006638
6639 gen_load_fpr32(fp0, rt);
6640 tcg_gen_ext_i32_tl(t0, fp0);
pbrooka7812ae2008-11-17 14:43:54 +00006641 tcg_temp_free_i32(fp0);
thsead93602007-09-06 00:18:15 +00006642 } else {
pbrooka7812ae2008-11-17 14:43:54 +00006643 TCGv_i32 fp0 = tcg_temp_new_i32();
thsb6d96be2008-07-09 11:05:10 +00006644
6645 gen_load_fpr32h(fp0, rt);
6646 tcg_gen_ext_i32_tl(t0, fp0);
pbrooka7812ae2008-11-17 14:43:54 +00006647 tcg_temp_free_i32(fp0);
thsead93602007-09-06 00:18:15 +00006648 }
6649 break;
6650 case 3:
6651 /* XXX: For now we support only a single FPU context. */
Blue Swirl895c2d02012-09-02 14:52:59 +00006652 gen_helper_1e0i(cfc1, t0, rt);
thsead93602007-09-06 00:18:15 +00006653 break;
6654 /* COP2: Not implemented. */
6655 case 4:
6656 case 5:
6657 /* fall through */
6658 default:
6659 goto die;
6660 }
aliguorid12d51d2009-01-15 21:48:06 +00006661 LOG_DISAS("mftr (reg %d u %d sel %d h %d)\n", rt, u, sel, h);
ths1a3fd9c2008-06-24 21:58:35 +00006662 gen_store_gpr(t0, rd);
6663 tcg_temp_free(t0);
thsead93602007-09-06 00:18:15 +00006664 return;
6665
6666die:
ths1a3fd9c2008-06-24 21:58:35 +00006667 tcg_temp_free(t0);
aliguorid12d51d2009-01-15 21:48:06 +00006668 LOG_DISAS("mftr (reg %d u %d sel %d h %d)\n", rt, u, sel, h);
thsead93602007-09-06 00:18:15 +00006669 generate_exception(ctx, EXCP_RI);
6670}
6671
Andreas Färber7db13fa2012-03-14 01:38:22 +01006672static void gen_mttr(CPUMIPSState *env, DisasContext *ctx, int rd, int rt,
thsead93602007-09-06 00:18:15 +00006673 int u, int sel, int h)
6674{
6675 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
pbrooka7812ae2008-11-17 14:43:54 +00006676 TCGv t0 = tcg_temp_local_new();
thsead93602007-09-06 00:18:15 +00006677
ths1a3fd9c2008-06-24 21:58:35 +00006678 gen_load_gpr(t0, rt);
thsead93602007-09-06 00:18:15 +00006679 if ((env->CP0_VPEConf0 & (1 << CP0VPEC0_MVP)) == 0 &&
thsb5dc7732008-06-27 10:02:35 +00006680 ((env->tcs[other_tc].CP0_TCBind & (0xf << CP0TCBd_CurVPE)) !=
6681 (env->active_tc.CP0_TCBind & (0xf << CP0TCBd_CurVPE))))
thsead93602007-09-06 00:18:15 +00006682 /* NOP */ ;
6683 else if ((env->CP0_VPEControl & (0xff << CP0VPECo_TargTC)) >
6684 (env->mvp->CP0_MVPConf0 & (0xff << CP0MVPC0_PTC)))
6685 /* NOP */ ;
6686 else if (u == 0) {
6687 switch (rd) {
Edgar E. Iglesias5a25ce92011-08-29 23:07:34 +02006688 case 1:
6689 switch (sel) {
6690 case 1:
Blue Swirl895c2d02012-09-02 14:52:59 +00006691 gen_helper_mttc0_vpecontrol(cpu_env, t0);
Edgar E. Iglesias5a25ce92011-08-29 23:07:34 +02006692 break;
6693 case 2:
Blue Swirl895c2d02012-09-02 14:52:59 +00006694 gen_helper_mttc0_vpeconf0(cpu_env, t0);
Edgar E. Iglesias5a25ce92011-08-29 23:07:34 +02006695 break;
6696 default:
6697 goto die;
6698 break;
6699 }
6700 break;
thsead93602007-09-06 00:18:15 +00006701 case 2:
6702 switch (sel) {
6703 case 1:
Blue Swirl895c2d02012-09-02 14:52:59 +00006704 gen_helper_mttc0_tcstatus(cpu_env, t0);
thsead93602007-09-06 00:18:15 +00006705 break;
6706 case 2:
Blue Swirl895c2d02012-09-02 14:52:59 +00006707 gen_helper_mttc0_tcbind(cpu_env, t0);
thsead93602007-09-06 00:18:15 +00006708 break;
6709 case 3:
Blue Swirl895c2d02012-09-02 14:52:59 +00006710 gen_helper_mttc0_tcrestart(cpu_env, t0);
thsead93602007-09-06 00:18:15 +00006711 break;
6712 case 4:
Blue Swirl895c2d02012-09-02 14:52:59 +00006713 gen_helper_mttc0_tchalt(cpu_env, t0);
thsead93602007-09-06 00:18:15 +00006714 break;
6715 case 5:
Blue Swirl895c2d02012-09-02 14:52:59 +00006716 gen_helper_mttc0_tccontext(cpu_env, t0);
thsead93602007-09-06 00:18:15 +00006717 break;
6718 case 6:
Blue Swirl895c2d02012-09-02 14:52:59 +00006719 gen_helper_mttc0_tcschedule(cpu_env, t0);
thsead93602007-09-06 00:18:15 +00006720 break;
6721 case 7:
Blue Swirl895c2d02012-09-02 14:52:59 +00006722 gen_helper_mttc0_tcschefback(cpu_env, t0);
thsead93602007-09-06 00:18:15 +00006723 break;
6724 default:
Aurelien Jarnod75c1352013-01-01 18:02:22 +01006725 gen_mtc0(ctx, t0, rd, sel);
thsead93602007-09-06 00:18:15 +00006726 break;
6727 }
6728 break;
6729 case 10:
6730 switch (sel) {
6731 case 0:
Blue Swirl895c2d02012-09-02 14:52:59 +00006732 gen_helper_mttc0_entryhi(cpu_env, t0);
thsead93602007-09-06 00:18:15 +00006733 break;
6734 default:
Aurelien Jarnod75c1352013-01-01 18:02:22 +01006735 gen_mtc0(ctx, t0, rd, sel);
thsead93602007-09-06 00:18:15 +00006736 break;
6737 }
6738 case 12:
6739 switch (sel) {
6740 case 0:
Blue Swirl895c2d02012-09-02 14:52:59 +00006741 gen_helper_mttc0_status(cpu_env, t0);
thsead93602007-09-06 00:18:15 +00006742 break;
6743 default:
Aurelien Jarnod75c1352013-01-01 18:02:22 +01006744 gen_mtc0(ctx, t0, rd, sel);
thsead93602007-09-06 00:18:15 +00006745 break;
6746 }
Edgar E. Iglesias5a25ce92011-08-29 23:07:34 +02006747 case 13:
6748 switch (sel) {
6749 case 0:
Blue Swirl895c2d02012-09-02 14:52:59 +00006750 gen_helper_mttc0_cause(cpu_env, t0);
Edgar E. Iglesias5a25ce92011-08-29 23:07:34 +02006751 break;
6752 default:
6753 goto die;
6754 break;
6755 }
6756 break;
6757 case 15:
6758 switch (sel) {
6759 case 1:
Blue Swirl895c2d02012-09-02 14:52:59 +00006760 gen_helper_mttc0_ebase(cpu_env, t0);
Edgar E. Iglesias5a25ce92011-08-29 23:07:34 +02006761 break;
6762 default:
6763 goto die;
6764 break;
6765 }
6766 break;
thsead93602007-09-06 00:18:15 +00006767 case 23:
6768 switch (sel) {
6769 case 0:
Blue Swirl895c2d02012-09-02 14:52:59 +00006770 gen_helper_mttc0_debug(cpu_env, t0);
thsead93602007-09-06 00:18:15 +00006771 break;
6772 default:
Aurelien Jarnod75c1352013-01-01 18:02:22 +01006773 gen_mtc0(ctx, t0, rd, sel);
thsead93602007-09-06 00:18:15 +00006774 break;
6775 }
6776 break;
6777 default:
Aurelien Jarnod75c1352013-01-01 18:02:22 +01006778 gen_mtc0(ctx, t0, rd, sel);
thsead93602007-09-06 00:18:15 +00006779 }
6780 } else switch (sel) {
6781 /* GPR registers. */
6782 case 0:
Blue Swirl895c2d02012-09-02 14:52:59 +00006783 gen_helper_0e1i(mttgpr, t0, rd);
thsead93602007-09-06 00:18:15 +00006784 break;
6785 /* Auxiliary CPU registers */
6786 case 1:
6787 switch (rd) {
6788 case 0:
Blue Swirl895c2d02012-09-02 14:52:59 +00006789 gen_helper_0e1i(mttlo, t0, 0);
thsead93602007-09-06 00:18:15 +00006790 break;
6791 case 1:
Blue Swirl895c2d02012-09-02 14:52:59 +00006792 gen_helper_0e1i(mtthi, t0, 0);
thsead93602007-09-06 00:18:15 +00006793 break;
6794 case 2:
Blue Swirl895c2d02012-09-02 14:52:59 +00006795 gen_helper_0e1i(mttacx, t0, 0);
thsead93602007-09-06 00:18:15 +00006796 break;
6797 case 4:
Blue Swirl895c2d02012-09-02 14:52:59 +00006798 gen_helper_0e1i(mttlo, t0, 1);
thsead93602007-09-06 00:18:15 +00006799 break;
6800 case 5:
Blue Swirl895c2d02012-09-02 14:52:59 +00006801 gen_helper_0e1i(mtthi, t0, 1);
thsead93602007-09-06 00:18:15 +00006802 break;
6803 case 6:
Blue Swirl895c2d02012-09-02 14:52:59 +00006804 gen_helper_0e1i(mttacx, t0, 1);
thsead93602007-09-06 00:18:15 +00006805 break;
6806 case 8:
Blue Swirl895c2d02012-09-02 14:52:59 +00006807 gen_helper_0e1i(mttlo, t0, 2);
thsead93602007-09-06 00:18:15 +00006808 break;
6809 case 9:
Blue Swirl895c2d02012-09-02 14:52:59 +00006810 gen_helper_0e1i(mtthi, t0, 2);
thsead93602007-09-06 00:18:15 +00006811 break;
6812 case 10:
Blue Swirl895c2d02012-09-02 14:52:59 +00006813 gen_helper_0e1i(mttacx, t0, 2);
thsead93602007-09-06 00:18:15 +00006814 break;
6815 case 12:
Blue Swirl895c2d02012-09-02 14:52:59 +00006816 gen_helper_0e1i(mttlo, t0, 3);
thsead93602007-09-06 00:18:15 +00006817 break;
6818 case 13:
Blue Swirl895c2d02012-09-02 14:52:59 +00006819 gen_helper_0e1i(mtthi, t0, 3);
thsead93602007-09-06 00:18:15 +00006820 break;
6821 case 14:
Blue Swirl895c2d02012-09-02 14:52:59 +00006822 gen_helper_0e1i(mttacx, t0, 3);
thsead93602007-09-06 00:18:15 +00006823 break;
6824 case 16:
Blue Swirl895c2d02012-09-02 14:52:59 +00006825 gen_helper_mttdsp(cpu_env, t0);
thsead93602007-09-06 00:18:15 +00006826 break;
6827 default:
6828 goto die;
6829 }
6830 break;
6831 /* Floating point (COP1). */
6832 case 2:
6833 /* XXX: For now we support only a single FPU context. */
6834 if (h == 0) {
pbrooka7812ae2008-11-17 14:43:54 +00006835 TCGv_i32 fp0 = tcg_temp_new_i32();
thsb6d96be2008-07-09 11:05:10 +00006836
6837 tcg_gen_trunc_tl_i32(fp0, t0);
6838 gen_store_fpr32(fp0, rd);
pbrooka7812ae2008-11-17 14:43:54 +00006839 tcg_temp_free_i32(fp0);
thsead93602007-09-06 00:18:15 +00006840 } else {
pbrooka7812ae2008-11-17 14:43:54 +00006841 TCGv_i32 fp0 = tcg_temp_new_i32();
thsb6d96be2008-07-09 11:05:10 +00006842
6843 tcg_gen_trunc_tl_i32(fp0, t0);
6844 gen_store_fpr32h(fp0, rd);
pbrooka7812ae2008-11-17 14:43:54 +00006845 tcg_temp_free_i32(fp0);
thsead93602007-09-06 00:18:15 +00006846 }
6847 break;
6848 case 3:
6849 /* XXX: For now we support only a single FPU context. */
Blue Swirl895c2d02012-09-02 14:52:59 +00006850 gen_helper_0e1i(ctc1, t0, rd);
thsead93602007-09-06 00:18:15 +00006851 break;
6852 /* COP2: Not implemented. */
6853 case 4:
6854 case 5:
6855 /* fall through */
6856 default:
6857 goto die;
6858 }
aliguorid12d51d2009-01-15 21:48:06 +00006859 LOG_DISAS("mttr (reg %d u %d sel %d h %d)\n", rd, u, sel, h);
ths1a3fd9c2008-06-24 21:58:35 +00006860 tcg_temp_free(t0);
thsead93602007-09-06 00:18:15 +00006861 return;
6862
6863die:
ths1a3fd9c2008-06-24 21:58:35 +00006864 tcg_temp_free(t0);
aliguorid12d51d2009-01-15 21:48:06 +00006865 LOG_DISAS("mttr (reg %d u %d sel %d h %d)\n", rd, u, sel, h);
thsead93602007-09-06 00:18:15 +00006866 generate_exception(ctx, EXCP_RI);
6867}
6868
Andreas Färber7db13fa2012-03-14 01:38:22 +01006869static void gen_cp0 (CPUMIPSState *env, DisasContext *ctx, uint32_t opc, int rt, int rd)
bellard6af0bf92005-07-02 14:58:51 +00006870{
ths287c4b82007-05-11 10:43:55 +00006871 const char *opn = "ldst";
bellard6af0bf92005-07-02 14:58:51 +00006872
Eric Johnson2e154972011-09-17 17:05:32 -07006873 check_cp0_enabled(ctx);
bellard6af0bf92005-07-02 14:58:51 +00006874 switch (opc) {
6875 case OPC_MFC0:
6876 if (rt == 0) {
thsead93602007-09-06 00:18:15 +00006877 /* Treat as NOP. */
bellard6af0bf92005-07-02 14:58:51 +00006878 return;
6879 }
Aurelien Jarnod75c1352013-01-01 18:02:22 +01006880 gen_mfc0(ctx, cpu_gpr[rt], rd, ctx->opcode & 0x7);
bellard6af0bf92005-07-02 14:58:51 +00006881 opn = "mfc0";
6882 break;
6883 case OPC_MTC0:
ths1a3fd9c2008-06-24 21:58:35 +00006884 {
aurel321fc7bf62009-04-08 21:47:35 +00006885 TCGv t0 = tcg_temp_new();
ths1a3fd9c2008-06-24 21:58:35 +00006886
6887 gen_load_gpr(t0, rt);
Aurelien Jarnod75c1352013-01-01 18:02:22 +01006888 gen_mtc0(ctx, t0, rd, ctx->opcode & 0x7);
ths1a3fd9c2008-06-24 21:58:35 +00006889 tcg_temp_free(t0);
6890 }
bellard6af0bf92005-07-02 14:58:51 +00006891 opn = "mtc0";
6892 break;
thsd26bc212007-11-08 18:05:37 +00006893#if defined(TARGET_MIPS64)
ths9c2149c2007-01-23 22:45:22 +00006894 case OPC_DMFC0:
Aurelien Jarnod75c1352013-01-01 18:02:22 +01006895 check_insn(ctx, ISA_MIPS3);
ths9c2149c2007-01-23 22:45:22 +00006896 if (rt == 0) {
thsead93602007-09-06 00:18:15 +00006897 /* Treat as NOP. */
ths9c2149c2007-01-23 22:45:22 +00006898 return;
6899 }
Aurelien Jarnod75c1352013-01-01 18:02:22 +01006900 gen_dmfc0(ctx, cpu_gpr[rt], rd, ctx->opcode & 0x7);
ths9c2149c2007-01-23 22:45:22 +00006901 opn = "dmfc0";
6902 break;
6903 case OPC_DMTC0:
Aurelien Jarnod75c1352013-01-01 18:02:22 +01006904 check_insn(ctx, ISA_MIPS3);
ths1a3fd9c2008-06-24 21:58:35 +00006905 {
aurel321fc7bf62009-04-08 21:47:35 +00006906 TCGv t0 = tcg_temp_new();
ths1a3fd9c2008-06-24 21:58:35 +00006907
6908 gen_load_gpr(t0, rt);
Aurelien Jarnod75c1352013-01-01 18:02:22 +01006909 gen_dmtc0(ctx, t0, rd, ctx->opcode & 0x7);
ths1a3fd9c2008-06-24 21:58:35 +00006910 tcg_temp_free(t0);
6911 }
ths9c2149c2007-01-23 22:45:22 +00006912 opn = "dmtc0";
6913 break;
ths534ce692007-04-11 02:13:00 +00006914#endif
thsead93602007-09-06 00:18:15 +00006915 case OPC_MFTR:
Aurelien Jarnod75c1352013-01-01 18:02:22 +01006916 check_insn(ctx, ASE_MT);
thsead93602007-09-06 00:18:15 +00006917 if (rd == 0) {
6918 /* Treat as NOP. */
6919 return;
6920 }
ths6c5c1e22008-06-24 15:12:27 +00006921 gen_mftr(env, ctx, rt, rd, (ctx->opcode >> 5) & 1,
thsead93602007-09-06 00:18:15 +00006922 ctx->opcode & 0x7, (ctx->opcode >> 4) & 1);
thsead93602007-09-06 00:18:15 +00006923 opn = "mftr";
6924 break;
6925 case OPC_MTTR:
Aurelien Jarnod75c1352013-01-01 18:02:22 +01006926 check_insn(ctx, ASE_MT);
ths6c5c1e22008-06-24 15:12:27 +00006927 gen_mttr(env, ctx, rd, rt, (ctx->opcode >> 5) & 1,
thsead93602007-09-06 00:18:15 +00006928 ctx->opcode & 0x7, (ctx->opcode >> 4) & 1);
6929 opn = "mttr";
6930 break;
bellard6af0bf92005-07-02 14:58:51 +00006931 case OPC_TLBWI:
bellard6af0bf92005-07-02 14:58:51 +00006932 opn = "tlbwi";
aurel32c01fccd2009-03-08 00:06:01 +00006933 if (!env->tlb->helper_tlbwi)
ths29929e32007-05-13 13:49:44 +00006934 goto die;
Blue Swirl895c2d02012-09-02 14:52:59 +00006935 gen_helper_tlbwi(cpu_env);
bellard6af0bf92005-07-02 14:58:51 +00006936 break;
6937 case OPC_TLBWR:
bellard6af0bf92005-07-02 14:58:51 +00006938 opn = "tlbwr";
aurel32c01fccd2009-03-08 00:06:01 +00006939 if (!env->tlb->helper_tlbwr)
ths29929e32007-05-13 13:49:44 +00006940 goto die;
Blue Swirl895c2d02012-09-02 14:52:59 +00006941 gen_helper_tlbwr(cpu_env);
bellard6af0bf92005-07-02 14:58:51 +00006942 break;
6943 case OPC_TLBP:
bellard6af0bf92005-07-02 14:58:51 +00006944 opn = "tlbp";
aurel32c01fccd2009-03-08 00:06:01 +00006945 if (!env->tlb->helper_tlbp)
ths29929e32007-05-13 13:49:44 +00006946 goto die;
Blue Swirl895c2d02012-09-02 14:52:59 +00006947 gen_helper_tlbp(cpu_env);
bellard6af0bf92005-07-02 14:58:51 +00006948 break;
6949 case OPC_TLBR:
bellard6af0bf92005-07-02 14:58:51 +00006950 opn = "tlbr";
aurel32c01fccd2009-03-08 00:06:01 +00006951 if (!env->tlb->helper_tlbr)
ths29929e32007-05-13 13:49:44 +00006952 goto die;
Blue Swirl895c2d02012-09-02 14:52:59 +00006953 gen_helper_tlbr(cpu_env);
bellard6af0bf92005-07-02 14:58:51 +00006954 break;
bellard6af0bf92005-07-02 14:58:51 +00006955 case OPC_ERET:
6956 opn = "eret";
Aurelien Jarnod75c1352013-01-01 18:02:22 +01006957 check_insn(ctx, ISA_MIPS2);
Blue Swirl895c2d02012-09-02 14:52:59 +00006958 gen_helper_eret(cpu_env);
bellard6af0bf92005-07-02 14:58:51 +00006959 ctx->bstate = BS_EXCP;
6960 break;
6961 case OPC_DERET:
6962 opn = "deret";
Aurelien Jarnod75c1352013-01-01 18:02:22 +01006963 check_insn(ctx, ISA_MIPS32);
bellard6af0bf92005-07-02 14:58:51 +00006964 if (!(ctx->hflags & MIPS_HFLAG_DM)) {
ths923617a2007-05-11 00:16:06 +00006965 MIPS_INVAL(opn);
bellard6af0bf92005-07-02 14:58:51 +00006966 generate_exception(ctx, EXCP_RI);
6967 } else {
Blue Swirl895c2d02012-09-02 14:52:59 +00006968 gen_helper_deret(cpu_env);
bellard6af0bf92005-07-02 14:58:51 +00006969 ctx->bstate = BS_EXCP;
6970 }
6971 break;
bellard4ad40f32005-12-05 19:59:36 +00006972 case OPC_WAIT:
6973 opn = "wait";
Aurelien Jarnod75c1352013-01-01 18:02:22 +01006974 check_insn(ctx, ISA_MIPS3 | ISA_MIPS32);
bellard4ad40f32005-12-05 19:59:36 +00006975 /* If we get an exception, we want to restart at next instruction */
6976 ctx->pc += 4;
6977 save_cpu_state(ctx, 1);
6978 ctx->pc -= 4;
Blue Swirl895c2d02012-09-02 14:52:59 +00006979 gen_helper_wait(cpu_env);
bellard4ad40f32005-12-05 19:59:36 +00006980 ctx->bstate = BS_EXCP;
6981 break;
bellard6af0bf92005-07-02 14:58:51 +00006982 default:
ths29929e32007-05-13 13:49:44 +00006983 die:
ths923617a2007-05-11 00:16:06 +00006984 MIPS_INVAL(opn);
bellard6af0bf92005-07-02 14:58:51 +00006985 generate_exception(ctx, EXCP_RI);
6986 return;
6987 }
Blue Swirl2abf3142010-10-13 18:38:08 +00006988 (void)opn; /* avoid a compiler warning */
bellard6af0bf92005-07-02 14:58:51 +00006989 MIPS_DEBUG("%s %s %d", opn, regnames[rt], rd);
6990}
thsf1aa6322008-06-09 07:13:38 +00006991#endif /* !CONFIG_USER_ONLY */
bellard6af0bf92005-07-02 14:58:51 +00006992
bellard6ea83fe2006-06-14 12:56:19 +00006993/* CP1 Branches (before delay slot) */
Aurelien Jarnod75c1352013-01-01 18:02:22 +01006994static void gen_compute_branch1(DisasContext *ctx, uint32_t op,
6995 int32_t cc, int32_t offset)
bellard6ea83fe2006-06-14 12:56:19 +00006996{
6997 target_ulong btarget;
ths923617a2007-05-11 00:16:06 +00006998 const char *opn = "cp1 cond branch";
pbrooka7812ae2008-11-17 14:43:54 +00006999 TCGv_i32 t0 = tcg_temp_new_i32();
bellard6ea83fe2006-06-14 12:56:19 +00007000
thse189e742007-09-24 12:48:00 +00007001 if (cc != 0)
Aurelien Jarnod75c1352013-01-01 18:02:22 +01007002 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32);
thse189e742007-09-24 12:48:00 +00007003
bellard6ea83fe2006-06-14 12:56:19 +00007004 btarget = ctx->pc + 4 + offset;
7005
ths7a387ff2006-12-06 20:17:30 +00007006 switch (op) {
7007 case OPC_BC1F:
aurel32d94536f2009-03-29 15:44:34 +00007008 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
7009 tcg_gen_not_i32(t0, t0);
7010 tcg_gen_andi_i32(t0, t0, 1);
7011 tcg_gen_extu_i32_tl(bcond, t0);
ths923617a2007-05-11 00:16:06 +00007012 opn = "bc1f";
bellard6ea83fe2006-06-14 12:56:19 +00007013 goto not_likely;
ths7a387ff2006-12-06 20:17:30 +00007014 case OPC_BC1FL:
aurel32d94536f2009-03-29 15:44:34 +00007015 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
7016 tcg_gen_not_i32(t0, t0);
7017 tcg_gen_andi_i32(t0, t0, 1);
7018 tcg_gen_extu_i32_tl(bcond, t0);
ths923617a2007-05-11 00:16:06 +00007019 opn = "bc1fl";
bellard6ea83fe2006-06-14 12:56:19 +00007020 goto likely;
ths7a387ff2006-12-06 20:17:30 +00007021 case OPC_BC1T:
aurel32d94536f2009-03-29 15:44:34 +00007022 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
7023 tcg_gen_andi_i32(t0, t0, 1);
7024 tcg_gen_extu_i32_tl(bcond, t0);
ths923617a2007-05-11 00:16:06 +00007025 opn = "bc1t";
ths5a5012e2007-05-07 13:55:33 +00007026 goto not_likely;
ths7a387ff2006-12-06 20:17:30 +00007027 case OPC_BC1TL:
aurel32d94536f2009-03-29 15:44:34 +00007028 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
7029 tcg_gen_andi_i32(t0, t0, 1);
7030 tcg_gen_extu_i32_tl(bcond, t0);
ths923617a2007-05-11 00:16:06 +00007031 opn = "bc1tl";
bellard6ea83fe2006-06-14 12:56:19 +00007032 likely:
7033 ctx->hflags |= MIPS_HFLAG_BL;
7034 break;
ths5a5012e2007-05-07 13:55:33 +00007035 case OPC_BC1FANY2:
thsa16336e2008-06-19 18:35:02 +00007036 {
aurel32d94536f2009-03-29 15:44:34 +00007037 TCGv_i32 t1 = tcg_temp_new_i32();
7038 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
7039 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+1));
Richard Sandifordd7f66b52011-11-26 03:37:07 +00007040 tcg_gen_nand_i32(t0, t0, t1);
aurel32d94536f2009-03-29 15:44:34 +00007041 tcg_temp_free_i32(t1);
aurel32d94536f2009-03-29 15:44:34 +00007042 tcg_gen_andi_i32(t0, t0, 1);
7043 tcg_gen_extu_i32_tl(bcond, t0);
thsa16336e2008-06-19 18:35:02 +00007044 }
thsfd4a04e2007-05-18 11:55:54 +00007045 opn = "bc1any2f";
ths5a5012e2007-05-07 13:55:33 +00007046 goto not_likely;
7047 case OPC_BC1TANY2:
thsa16336e2008-06-19 18:35:02 +00007048 {
aurel32d94536f2009-03-29 15:44:34 +00007049 TCGv_i32 t1 = tcg_temp_new_i32();
7050 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
7051 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+1));
7052 tcg_gen_or_i32(t0, t0, t1);
7053 tcg_temp_free_i32(t1);
7054 tcg_gen_andi_i32(t0, t0, 1);
7055 tcg_gen_extu_i32_tl(bcond, t0);
thsa16336e2008-06-19 18:35:02 +00007056 }
thsfd4a04e2007-05-18 11:55:54 +00007057 opn = "bc1any2t";
ths5a5012e2007-05-07 13:55:33 +00007058 goto not_likely;
7059 case OPC_BC1FANY4:
thsa16336e2008-06-19 18:35:02 +00007060 {
aurel32d94536f2009-03-29 15:44:34 +00007061 TCGv_i32 t1 = tcg_temp_new_i32();
7062 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
7063 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+1));
Richard Sandifordd7f66b52011-11-26 03:37:07 +00007064 tcg_gen_and_i32(t0, t0, t1);
aurel32d94536f2009-03-29 15:44:34 +00007065 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+2));
Richard Sandifordd7f66b52011-11-26 03:37:07 +00007066 tcg_gen_and_i32(t0, t0, t1);
aurel32d94536f2009-03-29 15:44:34 +00007067 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+3));
Richard Sandifordd7f66b52011-11-26 03:37:07 +00007068 tcg_gen_nand_i32(t0, t0, t1);
aurel32d94536f2009-03-29 15:44:34 +00007069 tcg_temp_free_i32(t1);
aurel32d94536f2009-03-29 15:44:34 +00007070 tcg_gen_andi_i32(t0, t0, 1);
7071 tcg_gen_extu_i32_tl(bcond, t0);
thsa16336e2008-06-19 18:35:02 +00007072 }
thsfd4a04e2007-05-18 11:55:54 +00007073 opn = "bc1any4f";
ths5a5012e2007-05-07 13:55:33 +00007074 goto not_likely;
7075 case OPC_BC1TANY4:
thsa16336e2008-06-19 18:35:02 +00007076 {
aurel32d94536f2009-03-29 15:44:34 +00007077 TCGv_i32 t1 = tcg_temp_new_i32();
7078 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
7079 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+1));
7080 tcg_gen_or_i32(t0, t0, t1);
7081 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+2));
7082 tcg_gen_or_i32(t0, t0, t1);
7083 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+3));
7084 tcg_gen_or_i32(t0, t0, t1);
7085 tcg_temp_free_i32(t1);
7086 tcg_gen_andi_i32(t0, t0, 1);
7087 tcg_gen_extu_i32_tl(bcond, t0);
thsa16336e2008-06-19 18:35:02 +00007088 }
thsfd4a04e2007-05-18 11:55:54 +00007089 opn = "bc1any4t";
ths5a5012e2007-05-07 13:55:33 +00007090 not_likely:
7091 ctx->hflags |= MIPS_HFLAG_BC;
ths5a5012e2007-05-07 13:55:33 +00007092 break;
7093 default:
ths923617a2007-05-11 00:16:06 +00007094 MIPS_INVAL(opn);
thse397ee32007-03-23 00:43:28 +00007095 generate_exception (ctx, EXCP_RI);
ths6c5c1e22008-06-24 15:12:27 +00007096 goto out;
bellard6ea83fe2006-06-14 12:56:19 +00007097 }
Blue Swirl2abf3142010-10-13 18:38:08 +00007098 (void)opn; /* avoid a compiler warning */
ths923617a2007-05-11 00:16:06 +00007099 MIPS_DEBUG("%s: cond %02x target " TARGET_FMT_lx, opn,
bellard6ea83fe2006-06-14 12:56:19 +00007100 ctx->hflags, btarget);
7101 ctx->btarget = btarget;
ths6c5c1e22008-06-24 15:12:27 +00007102
7103 out:
pbrooka7812ae2008-11-17 14:43:54 +00007104 tcg_temp_free_i32(t0);
bellard6ea83fe2006-06-14 12:56:19 +00007105}
7106
bellard6af0bf92005-07-02 14:58:51 +00007107/* Coprocessor 1 (FPU) */
ths5a5012e2007-05-07 13:55:33 +00007108
ths5a5012e2007-05-07 13:55:33 +00007109#define FOP(func, fmt) (((fmt) << 21) | (func))
7110
Nathan Froydbf4120a2010-06-08 13:29:56 -07007111enum fopcode {
7112 OPC_ADD_S = FOP(0, FMT_S),
7113 OPC_SUB_S = FOP(1, FMT_S),
7114 OPC_MUL_S = FOP(2, FMT_S),
7115 OPC_DIV_S = FOP(3, FMT_S),
7116 OPC_SQRT_S = FOP(4, FMT_S),
7117 OPC_ABS_S = FOP(5, FMT_S),
7118 OPC_MOV_S = FOP(6, FMT_S),
7119 OPC_NEG_S = FOP(7, FMT_S),
7120 OPC_ROUND_L_S = FOP(8, FMT_S),
7121 OPC_TRUNC_L_S = FOP(9, FMT_S),
7122 OPC_CEIL_L_S = FOP(10, FMT_S),
7123 OPC_FLOOR_L_S = FOP(11, FMT_S),
7124 OPC_ROUND_W_S = FOP(12, FMT_S),
7125 OPC_TRUNC_W_S = FOP(13, FMT_S),
7126 OPC_CEIL_W_S = FOP(14, FMT_S),
7127 OPC_FLOOR_W_S = FOP(15, FMT_S),
7128 OPC_MOVCF_S = FOP(17, FMT_S),
7129 OPC_MOVZ_S = FOP(18, FMT_S),
7130 OPC_MOVN_S = FOP(19, FMT_S),
7131 OPC_RECIP_S = FOP(21, FMT_S),
7132 OPC_RSQRT_S = FOP(22, FMT_S),
7133 OPC_RECIP2_S = FOP(28, FMT_S),
7134 OPC_RECIP1_S = FOP(29, FMT_S),
7135 OPC_RSQRT1_S = FOP(30, FMT_S),
7136 OPC_RSQRT2_S = FOP(31, FMT_S),
7137 OPC_CVT_D_S = FOP(33, FMT_S),
7138 OPC_CVT_W_S = FOP(36, FMT_S),
7139 OPC_CVT_L_S = FOP(37, FMT_S),
7140 OPC_CVT_PS_S = FOP(38, FMT_S),
7141 OPC_CMP_F_S = FOP (48, FMT_S),
7142 OPC_CMP_UN_S = FOP (49, FMT_S),
7143 OPC_CMP_EQ_S = FOP (50, FMT_S),
7144 OPC_CMP_UEQ_S = FOP (51, FMT_S),
7145 OPC_CMP_OLT_S = FOP (52, FMT_S),
7146 OPC_CMP_ULT_S = FOP (53, FMT_S),
7147 OPC_CMP_OLE_S = FOP (54, FMT_S),
7148 OPC_CMP_ULE_S = FOP (55, FMT_S),
7149 OPC_CMP_SF_S = FOP (56, FMT_S),
7150 OPC_CMP_NGLE_S = FOP (57, FMT_S),
7151 OPC_CMP_SEQ_S = FOP (58, FMT_S),
7152 OPC_CMP_NGL_S = FOP (59, FMT_S),
7153 OPC_CMP_LT_S = FOP (60, FMT_S),
7154 OPC_CMP_NGE_S = FOP (61, FMT_S),
7155 OPC_CMP_LE_S = FOP (62, FMT_S),
7156 OPC_CMP_NGT_S = FOP (63, FMT_S),
7157
7158 OPC_ADD_D = FOP(0, FMT_D),
7159 OPC_SUB_D = FOP(1, FMT_D),
7160 OPC_MUL_D = FOP(2, FMT_D),
7161 OPC_DIV_D = FOP(3, FMT_D),
7162 OPC_SQRT_D = FOP(4, FMT_D),
7163 OPC_ABS_D = FOP(5, FMT_D),
7164 OPC_MOV_D = FOP(6, FMT_D),
7165 OPC_NEG_D = FOP(7, FMT_D),
7166 OPC_ROUND_L_D = FOP(8, FMT_D),
7167 OPC_TRUNC_L_D = FOP(9, FMT_D),
7168 OPC_CEIL_L_D = FOP(10, FMT_D),
7169 OPC_FLOOR_L_D = FOP(11, FMT_D),
7170 OPC_ROUND_W_D = FOP(12, FMT_D),
7171 OPC_TRUNC_W_D = FOP(13, FMT_D),
7172 OPC_CEIL_W_D = FOP(14, FMT_D),
7173 OPC_FLOOR_W_D = FOP(15, FMT_D),
7174 OPC_MOVCF_D = FOP(17, FMT_D),
7175 OPC_MOVZ_D = FOP(18, FMT_D),
7176 OPC_MOVN_D = FOP(19, FMT_D),
7177 OPC_RECIP_D = FOP(21, FMT_D),
7178 OPC_RSQRT_D = FOP(22, FMT_D),
7179 OPC_RECIP2_D = FOP(28, FMT_D),
7180 OPC_RECIP1_D = FOP(29, FMT_D),
7181 OPC_RSQRT1_D = FOP(30, FMT_D),
7182 OPC_RSQRT2_D = FOP(31, FMT_D),
7183 OPC_CVT_S_D = FOP(32, FMT_D),
7184 OPC_CVT_W_D = FOP(36, FMT_D),
7185 OPC_CVT_L_D = FOP(37, FMT_D),
7186 OPC_CMP_F_D = FOP (48, FMT_D),
7187 OPC_CMP_UN_D = FOP (49, FMT_D),
7188 OPC_CMP_EQ_D = FOP (50, FMT_D),
7189 OPC_CMP_UEQ_D = FOP (51, FMT_D),
7190 OPC_CMP_OLT_D = FOP (52, FMT_D),
7191 OPC_CMP_ULT_D = FOP (53, FMT_D),
7192 OPC_CMP_OLE_D = FOP (54, FMT_D),
7193 OPC_CMP_ULE_D = FOP (55, FMT_D),
7194 OPC_CMP_SF_D = FOP (56, FMT_D),
7195 OPC_CMP_NGLE_D = FOP (57, FMT_D),
7196 OPC_CMP_SEQ_D = FOP (58, FMT_D),
7197 OPC_CMP_NGL_D = FOP (59, FMT_D),
7198 OPC_CMP_LT_D = FOP (60, FMT_D),
7199 OPC_CMP_NGE_D = FOP (61, FMT_D),
7200 OPC_CMP_LE_D = FOP (62, FMT_D),
7201 OPC_CMP_NGT_D = FOP (63, FMT_D),
7202
7203 OPC_CVT_S_W = FOP(32, FMT_W),
7204 OPC_CVT_D_W = FOP(33, FMT_W),
7205 OPC_CVT_S_L = FOP(32, FMT_L),
7206 OPC_CVT_D_L = FOP(33, FMT_L),
7207 OPC_CVT_PS_PW = FOP(38, FMT_W),
7208
7209 OPC_ADD_PS = FOP(0, FMT_PS),
7210 OPC_SUB_PS = FOP(1, FMT_PS),
7211 OPC_MUL_PS = FOP(2, FMT_PS),
7212 OPC_DIV_PS = FOP(3, FMT_PS),
7213 OPC_ABS_PS = FOP(5, FMT_PS),
7214 OPC_MOV_PS = FOP(6, FMT_PS),
7215 OPC_NEG_PS = FOP(7, FMT_PS),
7216 OPC_MOVCF_PS = FOP(17, FMT_PS),
7217 OPC_MOVZ_PS = FOP(18, FMT_PS),
7218 OPC_MOVN_PS = FOP(19, FMT_PS),
7219 OPC_ADDR_PS = FOP(24, FMT_PS),
7220 OPC_MULR_PS = FOP(26, FMT_PS),
7221 OPC_RECIP2_PS = FOP(28, FMT_PS),
7222 OPC_RECIP1_PS = FOP(29, FMT_PS),
7223 OPC_RSQRT1_PS = FOP(30, FMT_PS),
7224 OPC_RSQRT2_PS = FOP(31, FMT_PS),
7225
7226 OPC_CVT_S_PU = FOP(32, FMT_PS),
7227 OPC_CVT_PW_PS = FOP(36, FMT_PS),
7228 OPC_CVT_S_PL = FOP(40, FMT_PS),
7229 OPC_PLL_PS = FOP(44, FMT_PS),
7230 OPC_PLU_PS = FOP(45, FMT_PS),
7231 OPC_PUL_PS = FOP(46, FMT_PS),
7232 OPC_PUU_PS = FOP(47, FMT_PS),
7233 OPC_CMP_F_PS = FOP (48, FMT_PS),
7234 OPC_CMP_UN_PS = FOP (49, FMT_PS),
7235 OPC_CMP_EQ_PS = FOP (50, FMT_PS),
7236 OPC_CMP_UEQ_PS = FOP (51, FMT_PS),
7237 OPC_CMP_OLT_PS = FOP (52, FMT_PS),
7238 OPC_CMP_ULT_PS = FOP (53, FMT_PS),
7239 OPC_CMP_OLE_PS = FOP (54, FMT_PS),
7240 OPC_CMP_ULE_PS = FOP (55, FMT_PS),
7241 OPC_CMP_SF_PS = FOP (56, FMT_PS),
7242 OPC_CMP_NGLE_PS = FOP (57, FMT_PS),
7243 OPC_CMP_SEQ_PS = FOP (58, FMT_PS),
7244 OPC_CMP_NGL_PS = FOP (59, FMT_PS),
7245 OPC_CMP_LT_PS = FOP (60, FMT_PS),
7246 OPC_CMP_NGE_PS = FOP (61, FMT_PS),
7247 OPC_CMP_LE_PS = FOP (62, FMT_PS),
7248 OPC_CMP_NGT_PS = FOP (63, FMT_PS),
7249};
7250
ths7a387ff2006-12-06 20:17:30 +00007251static void gen_cp1 (DisasContext *ctx, uint32_t opc, int rt, int fs)
bellard6ea83fe2006-06-14 12:56:19 +00007252{
ths923617a2007-05-11 00:16:06 +00007253 const char *opn = "cp1 move";
aurel3272c3a3e2009-04-08 21:47:44 +00007254 TCGv t0 = tcg_temp_new();
bellard6ea83fe2006-06-14 12:56:19 +00007255
7256 switch (opc) {
7257 case OPC_MFC1:
thsb6d96be2008-07-09 11:05:10 +00007258 {
pbrooka7812ae2008-11-17 14:43:54 +00007259 TCGv_i32 fp0 = tcg_temp_new_i32();
thsb6d96be2008-07-09 11:05:10 +00007260
7261 gen_load_fpr32(fp0, fs);
7262 tcg_gen_ext_i32_tl(t0, fp0);
pbrooka7812ae2008-11-17 14:43:54 +00007263 tcg_temp_free_i32(fp0);
aurel3269585492009-01-14 19:40:36 +00007264 }
ths6c5c1e22008-06-24 15:12:27 +00007265 gen_store_gpr(t0, rt);
bellard6ea83fe2006-06-14 12:56:19 +00007266 opn = "mfc1";
7267 break;
7268 case OPC_MTC1:
ths6c5c1e22008-06-24 15:12:27 +00007269 gen_load_gpr(t0, rt);
thsb6d96be2008-07-09 11:05:10 +00007270 {
pbrooka7812ae2008-11-17 14:43:54 +00007271 TCGv_i32 fp0 = tcg_temp_new_i32();
thsb6d96be2008-07-09 11:05:10 +00007272
7273 tcg_gen_trunc_tl_i32(fp0, t0);
7274 gen_store_fpr32(fp0, fs);
pbrooka7812ae2008-11-17 14:43:54 +00007275 tcg_temp_free_i32(fp0);
aurel3269585492009-01-14 19:40:36 +00007276 }
bellard6ea83fe2006-06-14 12:56:19 +00007277 opn = "mtc1";
7278 break;
7279 case OPC_CFC1:
Blue Swirl895c2d02012-09-02 14:52:59 +00007280 gen_helper_1e0i(cfc1, t0, fs);
ths6c5c1e22008-06-24 15:12:27 +00007281 gen_store_gpr(t0, rt);
bellard6ea83fe2006-06-14 12:56:19 +00007282 opn = "cfc1";
7283 break;
7284 case OPC_CTC1:
ths6c5c1e22008-06-24 15:12:27 +00007285 gen_load_gpr(t0, rt);
Blue Swirl895c2d02012-09-02 14:52:59 +00007286 gen_helper_0e1i(ctc1, t0, fs);
bellard6ea83fe2006-06-14 12:56:19 +00007287 opn = "ctc1";
7288 break;
aurel3272c3a3e2009-04-08 21:47:44 +00007289#if defined(TARGET_MIPS64)
ths9c2149c2007-01-23 22:45:22 +00007290 case OPC_DMFC1:
aurel3272c3a3e2009-04-08 21:47:44 +00007291 gen_load_fpr64(ctx, t0, fs);
ths6c5c1e22008-06-24 15:12:27 +00007292 gen_store_gpr(t0, rt);
ths5a5012e2007-05-07 13:55:33 +00007293 opn = "dmfc1";
7294 break;
ths9c2149c2007-01-23 22:45:22 +00007295 case OPC_DMTC1:
ths6c5c1e22008-06-24 15:12:27 +00007296 gen_load_gpr(t0, rt);
aurel3272c3a3e2009-04-08 21:47:44 +00007297 gen_store_fpr64(ctx, t0, fs);
ths5a5012e2007-05-07 13:55:33 +00007298 opn = "dmtc1";
7299 break;
aurel3272c3a3e2009-04-08 21:47:44 +00007300#endif
ths5a5012e2007-05-07 13:55:33 +00007301 case OPC_MFHC1:
thsb6d96be2008-07-09 11:05:10 +00007302 {
pbrooka7812ae2008-11-17 14:43:54 +00007303 TCGv_i32 fp0 = tcg_temp_new_i32();
thsb6d96be2008-07-09 11:05:10 +00007304
7305 gen_load_fpr32h(fp0, fs);
7306 tcg_gen_ext_i32_tl(t0, fp0);
pbrooka7812ae2008-11-17 14:43:54 +00007307 tcg_temp_free_i32(fp0);
aurel3269585492009-01-14 19:40:36 +00007308 }
ths6c5c1e22008-06-24 15:12:27 +00007309 gen_store_gpr(t0, rt);
ths5a5012e2007-05-07 13:55:33 +00007310 opn = "mfhc1";
7311 break;
7312 case OPC_MTHC1:
ths6c5c1e22008-06-24 15:12:27 +00007313 gen_load_gpr(t0, rt);
thsb6d96be2008-07-09 11:05:10 +00007314 {
pbrooka7812ae2008-11-17 14:43:54 +00007315 TCGv_i32 fp0 = tcg_temp_new_i32();
thsb6d96be2008-07-09 11:05:10 +00007316
7317 tcg_gen_trunc_tl_i32(fp0, t0);
7318 gen_store_fpr32h(fp0, fs);
pbrooka7812ae2008-11-17 14:43:54 +00007319 tcg_temp_free_i32(fp0);
aurel3269585492009-01-14 19:40:36 +00007320 }
ths5a5012e2007-05-07 13:55:33 +00007321 opn = "mthc1";
7322 break;
bellard6ea83fe2006-06-14 12:56:19 +00007323 default:
ths923617a2007-05-11 00:16:06 +00007324 MIPS_INVAL(opn);
thse397ee32007-03-23 00:43:28 +00007325 generate_exception (ctx, EXCP_RI);
ths6c5c1e22008-06-24 15:12:27 +00007326 goto out;
bellard6ea83fe2006-06-14 12:56:19 +00007327 }
Blue Swirl2abf3142010-10-13 18:38:08 +00007328 (void)opn; /* avoid a compiler warning */
bellard6ea83fe2006-06-14 12:56:19 +00007329 MIPS_DEBUG("%s %s %s", opn, regnames[rt], fregnames[fs]);
ths6c5c1e22008-06-24 15:12:27 +00007330
7331 out:
7332 tcg_temp_free(t0);
bellard6ea83fe2006-06-14 12:56:19 +00007333}
7334
ths5a5012e2007-05-07 13:55:33 +00007335static void gen_movci (DisasContext *ctx, int rd, int rs, int cc, int tf)
7336{
aurel32af58f9c2009-03-29 15:44:50 +00007337 int l1;
thse214b9b2008-05-23 18:06:27 +00007338 TCGCond cond;
aurel32af58f9c2009-03-29 15:44:50 +00007339 TCGv_i32 t0;
bellard6ea83fe2006-06-14 12:56:19 +00007340
aurel32af58f9c2009-03-29 15:44:50 +00007341 if (rd == 0) {
7342 /* Treat as NOP. */
7343 return;
7344 }
7345
thse214b9b2008-05-23 18:06:27 +00007346 if (tf)
thse214b9b2008-05-23 18:06:27 +00007347 cond = TCG_COND_EQ;
ths27848472008-05-24 19:06:07 +00007348 else
7349 cond = TCG_COND_NE;
thse214b9b2008-05-23 18:06:27 +00007350
aurel32af58f9c2009-03-29 15:44:50 +00007351 l1 = gen_new_label();
7352 t0 = tcg_temp_new_i32();
Nathan Froydfa31af02009-08-25 08:20:00 -07007353 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
aurel32af58f9c2009-03-29 15:44:50 +00007354 tcg_gen_brcondi_i32(cond, t0, 0, l1);
aurel32a4e83382009-04-10 21:41:53 +00007355 tcg_temp_free_i32(t0);
aurel32af58f9c2009-03-29 15:44:50 +00007356 if (rs == 0) {
7357 tcg_gen_movi_tl(cpu_gpr[rd], 0);
7358 } else {
7359 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
7360 }
thse214b9b2008-05-23 18:06:27 +00007361 gen_set_label(l1);
ths5a5012e2007-05-07 13:55:33 +00007362}
bellard6ea83fe2006-06-14 12:56:19 +00007363
thsb6d96be2008-07-09 11:05:10 +00007364static inline void gen_movcf_s (int fs, int fd, int cc, int tf)
thsa16336e2008-06-19 18:35:02 +00007365{
thsa16336e2008-06-19 18:35:02 +00007366 int cond;
aurel32cbc37b22009-03-29 15:45:02 +00007367 TCGv_i32 t0 = tcg_temp_new_i32();
thsa16336e2008-06-19 18:35:02 +00007368 int l1 = gen_new_label();
7369
thsa16336e2008-06-19 18:35:02 +00007370 if (tf)
7371 cond = TCG_COND_EQ;
7372 else
7373 cond = TCG_COND_NE;
7374
Nathan Froydfa31af02009-08-25 08:20:00 -07007375 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
aurel32cbc37b22009-03-29 15:45:02 +00007376 tcg_gen_brcondi_i32(cond, t0, 0, l1);
7377 gen_load_fpr32(t0, fs);
7378 gen_store_fpr32(t0, fd);
thsa16336e2008-06-19 18:35:02 +00007379 gen_set_label(l1);
aurel32cbc37b22009-03-29 15:45:02 +00007380 tcg_temp_free_i32(t0);
ths5a5012e2007-05-07 13:55:33 +00007381}
thsa16336e2008-06-19 18:35:02 +00007382
thsb6d96be2008-07-09 11:05:10 +00007383static inline void gen_movcf_d (DisasContext *ctx, int fs, int fd, int cc, int tf)
thsa16336e2008-06-19 18:35:02 +00007384{
thsa16336e2008-06-19 18:35:02 +00007385 int cond;
aurel32cbc37b22009-03-29 15:45:02 +00007386 TCGv_i32 t0 = tcg_temp_new_i32();
7387 TCGv_i64 fp0;
thsa16336e2008-06-19 18:35:02 +00007388 int l1 = gen_new_label();
7389
thsa16336e2008-06-19 18:35:02 +00007390 if (tf)
7391 cond = TCG_COND_EQ;
7392 else
7393 cond = TCG_COND_NE;
7394
Nathan Froydfa31af02009-08-25 08:20:00 -07007395 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
aurel32cbc37b22009-03-29 15:45:02 +00007396 tcg_gen_brcondi_i32(cond, t0, 0, l1);
aurel32a4e83382009-04-10 21:41:53 +00007397 tcg_temp_free_i32(t0);
aurel3211f94252009-04-10 21:42:18 +00007398 fp0 = tcg_temp_new_i64();
aurel329bf3eb22008-11-11 11:50:43 +00007399 gen_load_fpr64(ctx, fp0, fs);
aurel329bf3eb22008-11-11 11:50:43 +00007400 gen_store_fpr64(ctx, fp0, fd);
pbrooka7812ae2008-11-17 14:43:54 +00007401 tcg_temp_free_i64(fp0);
aurel32cbc37b22009-03-29 15:45:02 +00007402 gen_set_label(l1);
thsa16336e2008-06-19 18:35:02 +00007403}
7404
thsb6d96be2008-07-09 11:05:10 +00007405static inline void gen_movcf_ps (int fs, int fd, int cc, int tf)
thsa16336e2008-06-19 18:35:02 +00007406{
7407 int cond;
aurel32cbc37b22009-03-29 15:45:02 +00007408 TCGv_i32 t0 = tcg_temp_new_i32();
thsa16336e2008-06-19 18:35:02 +00007409 int l1 = gen_new_label();
7410 int l2 = gen_new_label();
7411
7412 if (tf)
7413 cond = TCG_COND_EQ;
7414 else
7415 cond = TCG_COND_NE;
7416
Nathan Froydfa31af02009-08-25 08:20:00 -07007417 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
aurel32cbc37b22009-03-29 15:45:02 +00007418 tcg_gen_brcondi_i32(cond, t0, 0, l1);
7419 gen_load_fpr32(t0, fs);
7420 gen_store_fpr32(t0, fd);
thsa16336e2008-06-19 18:35:02 +00007421 gen_set_label(l1);
aurel329bf3eb22008-11-11 11:50:43 +00007422
Nathan Froydfa31af02009-08-25 08:20:00 -07007423 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc+1));
aurel32cbc37b22009-03-29 15:45:02 +00007424 tcg_gen_brcondi_i32(cond, t0, 0, l2);
7425 gen_load_fpr32h(t0, fs);
7426 gen_store_fpr32h(t0, fd);
aurel3252a0e9e2009-04-10 21:56:32 +00007427 tcg_temp_free_i32(t0);
thsa16336e2008-06-19 18:35:02 +00007428 gen_set_label(l2);
thsa16336e2008-06-19 18:35:02 +00007429}
7430
ths5a5012e2007-05-07 13:55:33 +00007431
Nathan Froydbf4120a2010-06-08 13:29:56 -07007432static void gen_farith (DisasContext *ctx, enum fopcode op1,
ths5e755512007-05-29 16:52:57 +00007433 int ft, int fs, int fd, int cc)
bellard6ea83fe2006-06-14 12:56:19 +00007434{
ths923617a2007-05-11 00:16:06 +00007435 const char *opn = "farith";
bellard6ea83fe2006-06-14 12:56:19 +00007436 const char *condnames[] = {
7437 "c.f",
7438 "c.un",
7439 "c.eq",
7440 "c.ueq",
7441 "c.olt",
7442 "c.ult",
7443 "c.ole",
7444 "c.ule",
7445 "c.sf",
7446 "c.ngle",
7447 "c.seq",
7448 "c.ngl",
7449 "c.lt",
7450 "c.nge",
7451 "c.le",
7452 "c.ngt",
7453 };
ths5a1e8ff2007-05-11 17:08:26 +00007454 const char *condnames_abs[] = {
7455 "cabs.f",
7456 "cabs.un",
7457 "cabs.eq",
7458 "cabs.ueq",
7459 "cabs.olt",
7460 "cabs.ult",
7461 "cabs.ole",
7462 "cabs.ule",
7463 "cabs.sf",
7464 "cabs.ngle",
7465 "cabs.seq",
7466 "cabs.ngl",
7467 "cabs.lt",
7468 "cabs.nge",
7469 "cabs.le",
7470 "cabs.ngt",
7471 };
7472 enum { BINOP, CMPOP, OTHEROP } optype = OTHEROP;
ths7a387ff2006-12-06 20:17:30 +00007473 uint32_t func = ctx->opcode & 0x3f;
7474
Nathan Froydbf4120a2010-06-08 13:29:56 -07007475 switch (op1) {
7476 case OPC_ADD_S:
thsb6d96be2008-07-09 11:05:10 +00007477 {
pbrooka7812ae2008-11-17 14:43:54 +00007478 TCGv_i32 fp0 = tcg_temp_new_i32();
7479 TCGv_i32 fp1 = tcg_temp_new_i32();
thsb6d96be2008-07-09 11:05:10 +00007480
7481 gen_load_fpr32(fp0, fs);
7482 gen_load_fpr32(fp1, ft);
Blue Swirl895c2d02012-09-02 14:52:59 +00007483 gen_helper_float_add_s(fp0, cpu_env, fp0, fp1);
pbrooka7812ae2008-11-17 14:43:54 +00007484 tcg_temp_free_i32(fp1);
thsb6d96be2008-07-09 11:05:10 +00007485 gen_store_fpr32(fp0, fd);
pbrooka7812ae2008-11-17 14:43:54 +00007486 tcg_temp_free_i32(fp0);
thsb6d96be2008-07-09 11:05:10 +00007487 }
ths5a5012e2007-05-07 13:55:33 +00007488 opn = "add.s";
ths5a1e8ff2007-05-11 17:08:26 +00007489 optype = BINOP;
ths5a5012e2007-05-07 13:55:33 +00007490 break;
Nathan Froydbf4120a2010-06-08 13:29:56 -07007491 case OPC_SUB_S:
thsb6d96be2008-07-09 11:05:10 +00007492 {
pbrooka7812ae2008-11-17 14:43:54 +00007493 TCGv_i32 fp0 = tcg_temp_new_i32();
7494 TCGv_i32 fp1 = tcg_temp_new_i32();
thsb6d96be2008-07-09 11:05:10 +00007495
7496 gen_load_fpr32(fp0, fs);
7497 gen_load_fpr32(fp1, ft);
Blue Swirl895c2d02012-09-02 14:52:59 +00007498 gen_helper_float_sub_s(fp0, cpu_env, fp0, fp1);
pbrooka7812ae2008-11-17 14:43:54 +00007499 tcg_temp_free_i32(fp1);
thsb6d96be2008-07-09 11:05:10 +00007500 gen_store_fpr32(fp0, fd);
pbrooka7812ae2008-11-17 14:43:54 +00007501 tcg_temp_free_i32(fp0);
thsb6d96be2008-07-09 11:05:10 +00007502 }
ths5a5012e2007-05-07 13:55:33 +00007503 opn = "sub.s";
ths5a1e8ff2007-05-11 17:08:26 +00007504 optype = BINOP;
ths5a5012e2007-05-07 13:55:33 +00007505 break;
Nathan Froydbf4120a2010-06-08 13:29:56 -07007506 case OPC_MUL_S:
thsb6d96be2008-07-09 11:05:10 +00007507 {
pbrooka7812ae2008-11-17 14:43:54 +00007508 TCGv_i32 fp0 = tcg_temp_new_i32();
7509 TCGv_i32 fp1 = tcg_temp_new_i32();
thsb6d96be2008-07-09 11:05:10 +00007510
7511 gen_load_fpr32(fp0, fs);
7512 gen_load_fpr32(fp1, ft);
Blue Swirl895c2d02012-09-02 14:52:59 +00007513 gen_helper_float_mul_s(fp0, cpu_env, fp0, fp1);
pbrooka7812ae2008-11-17 14:43:54 +00007514 tcg_temp_free_i32(fp1);
thsb6d96be2008-07-09 11:05:10 +00007515 gen_store_fpr32(fp0, fd);
pbrooka7812ae2008-11-17 14:43:54 +00007516 tcg_temp_free_i32(fp0);
thsb6d96be2008-07-09 11:05:10 +00007517 }
ths5a5012e2007-05-07 13:55:33 +00007518 opn = "mul.s";
ths5a1e8ff2007-05-11 17:08:26 +00007519 optype = BINOP;
ths5a5012e2007-05-07 13:55:33 +00007520 break;
Nathan Froydbf4120a2010-06-08 13:29:56 -07007521 case OPC_DIV_S:
thsb6d96be2008-07-09 11:05:10 +00007522 {
pbrooka7812ae2008-11-17 14:43:54 +00007523 TCGv_i32 fp0 = tcg_temp_new_i32();
7524 TCGv_i32 fp1 = tcg_temp_new_i32();
thsb6d96be2008-07-09 11:05:10 +00007525
7526 gen_load_fpr32(fp0, fs);
7527 gen_load_fpr32(fp1, ft);
Blue Swirl895c2d02012-09-02 14:52:59 +00007528 gen_helper_float_div_s(fp0, cpu_env, fp0, fp1);
pbrooka7812ae2008-11-17 14:43:54 +00007529 tcg_temp_free_i32(fp1);
thsb6d96be2008-07-09 11:05:10 +00007530 gen_store_fpr32(fp0, fd);
pbrooka7812ae2008-11-17 14:43:54 +00007531 tcg_temp_free_i32(fp0);
thsb6d96be2008-07-09 11:05:10 +00007532 }
ths5a5012e2007-05-07 13:55:33 +00007533 opn = "div.s";
ths5a1e8ff2007-05-11 17:08:26 +00007534 optype = BINOP;
ths5a5012e2007-05-07 13:55:33 +00007535 break;
Nathan Froydbf4120a2010-06-08 13:29:56 -07007536 case OPC_SQRT_S:
thsb6d96be2008-07-09 11:05:10 +00007537 {
pbrooka7812ae2008-11-17 14:43:54 +00007538 TCGv_i32 fp0 = tcg_temp_new_i32();
thsb6d96be2008-07-09 11:05:10 +00007539
7540 gen_load_fpr32(fp0, fs);
Blue Swirl895c2d02012-09-02 14:52:59 +00007541 gen_helper_float_sqrt_s(fp0, cpu_env, fp0);
thsb6d96be2008-07-09 11:05:10 +00007542 gen_store_fpr32(fp0, fd);
pbrooka7812ae2008-11-17 14:43:54 +00007543 tcg_temp_free_i32(fp0);
thsb6d96be2008-07-09 11:05:10 +00007544 }
ths5a5012e2007-05-07 13:55:33 +00007545 opn = "sqrt.s";
7546 break;
Nathan Froydbf4120a2010-06-08 13:29:56 -07007547 case OPC_ABS_S:
thsb6d96be2008-07-09 11:05:10 +00007548 {
pbrooka7812ae2008-11-17 14:43:54 +00007549 TCGv_i32 fp0 = tcg_temp_new_i32();
thsb6d96be2008-07-09 11:05:10 +00007550
7551 gen_load_fpr32(fp0, fs);
pbrooka7812ae2008-11-17 14:43:54 +00007552 gen_helper_float_abs_s(fp0, fp0);
thsb6d96be2008-07-09 11:05:10 +00007553 gen_store_fpr32(fp0, fd);
pbrooka7812ae2008-11-17 14:43:54 +00007554 tcg_temp_free_i32(fp0);
thsb6d96be2008-07-09 11:05:10 +00007555 }
ths5a5012e2007-05-07 13:55:33 +00007556 opn = "abs.s";
7557 break;
Nathan Froydbf4120a2010-06-08 13:29:56 -07007558 case OPC_MOV_S:
thsb6d96be2008-07-09 11:05:10 +00007559 {
pbrooka7812ae2008-11-17 14:43:54 +00007560 TCGv_i32 fp0 = tcg_temp_new_i32();
thsb6d96be2008-07-09 11:05:10 +00007561
7562 gen_load_fpr32(fp0, fs);
7563 gen_store_fpr32(fp0, fd);
pbrooka7812ae2008-11-17 14:43:54 +00007564 tcg_temp_free_i32(fp0);
thsb6d96be2008-07-09 11:05:10 +00007565 }
ths5a5012e2007-05-07 13:55:33 +00007566 opn = "mov.s";
7567 break;
Nathan Froydbf4120a2010-06-08 13:29:56 -07007568 case OPC_NEG_S:
thsb6d96be2008-07-09 11:05:10 +00007569 {
pbrooka7812ae2008-11-17 14:43:54 +00007570 TCGv_i32 fp0 = tcg_temp_new_i32();
thsb6d96be2008-07-09 11:05:10 +00007571
7572 gen_load_fpr32(fp0, fs);
pbrooka7812ae2008-11-17 14:43:54 +00007573 gen_helper_float_chs_s(fp0, fp0);
thsb6d96be2008-07-09 11:05:10 +00007574 gen_store_fpr32(fp0, fd);
pbrooka7812ae2008-11-17 14:43:54 +00007575 tcg_temp_free_i32(fp0);
thsb6d96be2008-07-09 11:05:10 +00007576 }
ths5a5012e2007-05-07 13:55:33 +00007577 opn = "neg.s";
7578 break;
Nathan Froydbf4120a2010-06-08 13:29:56 -07007579 case OPC_ROUND_L_S:
ths5e755512007-05-29 16:52:57 +00007580 check_cp1_64bitmode(ctx);
thsb6d96be2008-07-09 11:05:10 +00007581 {
pbrooka7812ae2008-11-17 14:43:54 +00007582 TCGv_i32 fp32 = tcg_temp_new_i32();
7583 TCGv_i64 fp64 = tcg_temp_new_i64();
thsb6d96be2008-07-09 11:05:10 +00007584
7585 gen_load_fpr32(fp32, fs);
Blue Swirl895c2d02012-09-02 14:52:59 +00007586 gen_helper_float_roundl_s(fp64, cpu_env, fp32);
pbrooka7812ae2008-11-17 14:43:54 +00007587 tcg_temp_free_i32(fp32);
thsb6d96be2008-07-09 11:05:10 +00007588 gen_store_fpr64(ctx, fp64, fd);
pbrooka7812ae2008-11-17 14:43:54 +00007589 tcg_temp_free_i64(fp64);
thsb6d96be2008-07-09 11:05:10 +00007590 }
ths5a5012e2007-05-07 13:55:33 +00007591 opn = "round.l.s";
7592 break;
Nathan Froydbf4120a2010-06-08 13:29:56 -07007593 case OPC_TRUNC_L_S:
ths5e755512007-05-29 16:52:57 +00007594 check_cp1_64bitmode(ctx);
thsb6d96be2008-07-09 11:05:10 +00007595 {
pbrooka7812ae2008-11-17 14:43:54 +00007596 TCGv_i32 fp32 = tcg_temp_new_i32();
7597 TCGv_i64 fp64 = tcg_temp_new_i64();
thsb6d96be2008-07-09 11:05:10 +00007598
7599 gen_load_fpr32(fp32, fs);
Blue Swirl895c2d02012-09-02 14:52:59 +00007600 gen_helper_float_truncl_s(fp64, cpu_env, fp32);
pbrooka7812ae2008-11-17 14:43:54 +00007601 tcg_temp_free_i32(fp32);
thsb6d96be2008-07-09 11:05:10 +00007602 gen_store_fpr64(ctx, fp64, fd);
pbrooka7812ae2008-11-17 14:43:54 +00007603 tcg_temp_free_i64(fp64);
thsb6d96be2008-07-09 11:05:10 +00007604 }
ths5a5012e2007-05-07 13:55:33 +00007605 opn = "trunc.l.s";
7606 break;
Nathan Froydbf4120a2010-06-08 13:29:56 -07007607 case OPC_CEIL_L_S:
ths5e755512007-05-29 16:52:57 +00007608 check_cp1_64bitmode(ctx);
thsb6d96be2008-07-09 11:05:10 +00007609 {
pbrooka7812ae2008-11-17 14:43:54 +00007610 TCGv_i32 fp32 = tcg_temp_new_i32();
7611 TCGv_i64 fp64 = tcg_temp_new_i64();
thsb6d96be2008-07-09 11:05:10 +00007612
7613 gen_load_fpr32(fp32, fs);
Blue Swirl895c2d02012-09-02 14:52:59 +00007614 gen_helper_float_ceill_s(fp64, cpu_env, fp32);
pbrooka7812ae2008-11-17 14:43:54 +00007615 tcg_temp_free_i32(fp32);
thsb6d96be2008-07-09 11:05:10 +00007616 gen_store_fpr64(ctx, fp64, fd);
pbrooka7812ae2008-11-17 14:43:54 +00007617 tcg_temp_free_i64(fp64);
thsb6d96be2008-07-09 11:05:10 +00007618 }
ths5a5012e2007-05-07 13:55:33 +00007619 opn = "ceil.l.s";
7620 break;
Nathan Froydbf4120a2010-06-08 13:29:56 -07007621 case OPC_FLOOR_L_S:
ths5e755512007-05-29 16:52:57 +00007622 check_cp1_64bitmode(ctx);
thsb6d96be2008-07-09 11:05:10 +00007623 {
pbrooka7812ae2008-11-17 14:43:54 +00007624 TCGv_i32 fp32 = tcg_temp_new_i32();
7625 TCGv_i64 fp64 = tcg_temp_new_i64();
thsb6d96be2008-07-09 11:05:10 +00007626
7627 gen_load_fpr32(fp32, fs);
Blue Swirl895c2d02012-09-02 14:52:59 +00007628 gen_helper_float_floorl_s(fp64, cpu_env, fp32);
pbrooka7812ae2008-11-17 14:43:54 +00007629 tcg_temp_free_i32(fp32);
thsb6d96be2008-07-09 11:05:10 +00007630 gen_store_fpr64(ctx, fp64, fd);
pbrooka7812ae2008-11-17 14:43:54 +00007631 tcg_temp_free_i64(fp64);
thsb6d96be2008-07-09 11:05:10 +00007632 }
ths5a5012e2007-05-07 13:55:33 +00007633 opn = "floor.l.s";
7634 break;
Nathan Froydbf4120a2010-06-08 13:29:56 -07007635 case OPC_ROUND_W_S:
thsb6d96be2008-07-09 11:05:10 +00007636 {
pbrooka7812ae2008-11-17 14:43:54 +00007637 TCGv_i32 fp0 = tcg_temp_new_i32();
thsb6d96be2008-07-09 11:05:10 +00007638
7639 gen_load_fpr32(fp0, fs);
Blue Swirl895c2d02012-09-02 14:52:59 +00007640 gen_helper_float_roundw_s(fp0, cpu_env, fp0);
thsb6d96be2008-07-09 11:05:10 +00007641 gen_store_fpr32(fp0, fd);
pbrooka7812ae2008-11-17 14:43:54 +00007642 tcg_temp_free_i32(fp0);
thsb6d96be2008-07-09 11:05:10 +00007643 }
ths5a5012e2007-05-07 13:55:33 +00007644 opn = "round.w.s";
7645 break;
Nathan Froydbf4120a2010-06-08 13:29:56 -07007646 case OPC_TRUNC_W_S:
thsb6d96be2008-07-09 11:05:10 +00007647 {
pbrooka7812ae2008-11-17 14:43:54 +00007648 TCGv_i32 fp0 = tcg_temp_new_i32();
thsb6d96be2008-07-09 11:05:10 +00007649
7650 gen_load_fpr32(fp0, fs);
Blue Swirl895c2d02012-09-02 14:52:59 +00007651 gen_helper_float_truncw_s(fp0, cpu_env, fp0);
thsb6d96be2008-07-09 11:05:10 +00007652 gen_store_fpr32(fp0, fd);
pbrooka7812ae2008-11-17 14:43:54 +00007653 tcg_temp_free_i32(fp0);
thsb6d96be2008-07-09 11:05:10 +00007654 }
ths5a5012e2007-05-07 13:55:33 +00007655 opn = "trunc.w.s";
7656 break;
Nathan Froydbf4120a2010-06-08 13:29:56 -07007657 case OPC_CEIL_W_S:
thsb6d96be2008-07-09 11:05:10 +00007658 {
pbrooka7812ae2008-11-17 14:43:54 +00007659 TCGv_i32 fp0 = tcg_temp_new_i32();
thsb6d96be2008-07-09 11:05:10 +00007660
7661 gen_load_fpr32(fp0, fs);
Blue Swirl895c2d02012-09-02 14:52:59 +00007662 gen_helper_float_ceilw_s(fp0, cpu_env, fp0);
thsb6d96be2008-07-09 11:05:10 +00007663 gen_store_fpr32(fp0, fd);
pbrooka7812ae2008-11-17 14:43:54 +00007664 tcg_temp_free_i32(fp0);
thsb6d96be2008-07-09 11:05:10 +00007665 }
ths5a5012e2007-05-07 13:55:33 +00007666 opn = "ceil.w.s";
7667 break;
Nathan Froydbf4120a2010-06-08 13:29:56 -07007668 case OPC_FLOOR_W_S:
thsb6d96be2008-07-09 11:05:10 +00007669 {
pbrooka7812ae2008-11-17 14:43:54 +00007670 TCGv_i32 fp0 = tcg_temp_new_i32();
thsb6d96be2008-07-09 11:05:10 +00007671
7672 gen_load_fpr32(fp0, fs);
Blue Swirl895c2d02012-09-02 14:52:59 +00007673 gen_helper_float_floorw_s(fp0, cpu_env, fp0);
thsb6d96be2008-07-09 11:05:10 +00007674 gen_store_fpr32(fp0, fd);
pbrooka7812ae2008-11-17 14:43:54 +00007675 tcg_temp_free_i32(fp0);
thsb6d96be2008-07-09 11:05:10 +00007676 }
ths5a5012e2007-05-07 13:55:33 +00007677 opn = "floor.w.s";
7678 break;
Nathan Froydbf4120a2010-06-08 13:29:56 -07007679 case OPC_MOVCF_S:
thsb6d96be2008-07-09 11:05:10 +00007680 gen_movcf_s(fs, fd, (ft >> 2) & 0x7, ft & 0x1);
ths5a5012e2007-05-07 13:55:33 +00007681 opn = "movcf.s";
7682 break;
Nathan Froydbf4120a2010-06-08 13:29:56 -07007683 case OPC_MOVZ_S:
thsa16336e2008-06-19 18:35:02 +00007684 {
7685 int l1 = gen_new_label();
aurel32c9297f42009-04-08 21:48:27 +00007686 TCGv_i32 fp0;
thsa16336e2008-06-19 18:35:02 +00007687
aurel32c9297f42009-04-08 21:48:27 +00007688 if (ft != 0) {
7689 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[ft], 0, l1);
7690 }
7691 fp0 = tcg_temp_new_i32();
thsb6d96be2008-07-09 11:05:10 +00007692 gen_load_fpr32(fp0, fs);
7693 gen_store_fpr32(fp0, fd);
pbrooka7812ae2008-11-17 14:43:54 +00007694 tcg_temp_free_i32(fp0);
thsa16336e2008-06-19 18:35:02 +00007695 gen_set_label(l1);
7696 }
ths5a5012e2007-05-07 13:55:33 +00007697 opn = "movz.s";
7698 break;
Nathan Froydbf4120a2010-06-08 13:29:56 -07007699 case OPC_MOVN_S:
thsa16336e2008-06-19 18:35:02 +00007700 {
7701 int l1 = gen_new_label();
aurel32c9297f42009-04-08 21:48:27 +00007702 TCGv_i32 fp0;
thsa16336e2008-06-19 18:35:02 +00007703
aurel32c9297f42009-04-08 21:48:27 +00007704 if (ft != 0) {
7705 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[ft], 0, l1);
7706 fp0 = tcg_temp_new_i32();
7707 gen_load_fpr32(fp0, fs);
7708 gen_store_fpr32(fp0, fd);
7709 tcg_temp_free_i32(fp0);
7710 gen_set_label(l1);
7711 }
thsa16336e2008-06-19 18:35:02 +00007712 }
ths5a5012e2007-05-07 13:55:33 +00007713 opn = "movn.s";
7714 break;
Nathan Froydbf4120a2010-06-08 13:29:56 -07007715 case OPC_RECIP_S:
thsb8aa4592007-12-30 15:36:58 +00007716 check_cop1x(ctx);
thsb6d96be2008-07-09 11:05:10 +00007717 {
pbrooka7812ae2008-11-17 14:43:54 +00007718 TCGv_i32 fp0 = tcg_temp_new_i32();
thsb6d96be2008-07-09 11:05:10 +00007719
7720 gen_load_fpr32(fp0, fs);
Blue Swirl895c2d02012-09-02 14:52:59 +00007721 gen_helper_float_recip_s(fp0, cpu_env, fp0);
thsb6d96be2008-07-09 11:05:10 +00007722 gen_store_fpr32(fp0, fd);
pbrooka7812ae2008-11-17 14:43:54 +00007723 tcg_temp_free_i32(fp0);
thsb6d96be2008-07-09 11:05:10 +00007724 }
ths57fa1fb2007-05-19 20:29:41 +00007725 opn = "recip.s";
7726 break;
Nathan Froydbf4120a2010-06-08 13:29:56 -07007727 case OPC_RSQRT_S:
thsb8aa4592007-12-30 15:36:58 +00007728 check_cop1x(ctx);
thsb6d96be2008-07-09 11:05:10 +00007729 {
pbrooka7812ae2008-11-17 14:43:54 +00007730 TCGv_i32 fp0 = tcg_temp_new_i32();
thsb6d96be2008-07-09 11:05:10 +00007731
7732 gen_load_fpr32(fp0, fs);
Blue Swirl895c2d02012-09-02 14:52:59 +00007733 gen_helper_float_rsqrt_s(fp0, cpu_env, fp0);
thsb6d96be2008-07-09 11:05:10 +00007734 gen_store_fpr32(fp0, fd);
pbrooka7812ae2008-11-17 14:43:54 +00007735 tcg_temp_free_i32(fp0);
thsb6d96be2008-07-09 11:05:10 +00007736 }
ths57fa1fb2007-05-19 20:29:41 +00007737 opn = "rsqrt.s";
7738 break;
Nathan Froydbf4120a2010-06-08 13:29:56 -07007739 case OPC_RECIP2_S:
ths5e755512007-05-29 16:52:57 +00007740 check_cp1_64bitmode(ctx);
thsb6d96be2008-07-09 11:05:10 +00007741 {
pbrooka7812ae2008-11-17 14:43:54 +00007742 TCGv_i32 fp0 = tcg_temp_new_i32();
7743 TCGv_i32 fp1 = tcg_temp_new_i32();
thsb6d96be2008-07-09 11:05:10 +00007744
7745 gen_load_fpr32(fp0, fs);
Richard Sandifordd22d7282012-08-27 09:50:38 +01007746 gen_load_fpr32(fp1, ft);
Blue Swirl895c2d02012-09-02 14:52:59 +00007747 gen_helper_float_recip2_s(fp0, cpu_env, fp0, fp1);
pbrooka7812ae2008-11-17 14:43:54 +00007748 tcg_temp_free_i32(fp1);
thsb6d96be2008-07-09 11:05:10 +00007749 gen_store_fpr32(fp0, fd);
pbrooka7812ae2008-11-17 14:43:54 +00007750 tcg_temp_free_i32(fp0);
thsb6d96be2008-07-09 11:05:10 +00007751 }
ths57fa1fb2007-05-19 20:29:41 +00007752 opn = "recip2.s";
7753 break;
Nathan Froydbf4120a2010-06-08 13:29:56 -07007754 case OPC_RECIP1_S:
ths5e755512007-05-29 16:52:57 +00007755 check_cp1_64bitmode(ctx);
thsb6d96be2008-07-09 11:05:10 +00007756 {
pbrooka7812ae2008-11-17 14:43:54 +00007757 TCGv_i32 fp0 = tcg_temp_new_i32();
thsb6d96be2008-07-09 11:05:10 +00007758
7759 gen_load_fpr32(fp0, fs);
Blue Swirl895c2d02012-09-02 14:52:59 +00007760 gen_helper_float_recip1_s(fp0, cpu_env, fp0);
thsb6d96be2008-07-09 11:05:10 +00007761 gen_store_fpr32(fp0, fd);
pbrooka7812ae2008-11-17 14:43:54 +00007762 tcg_temp_free_i32(fp0);
thsb6d96be2008-07-09 11:05:10 +00007763 }
ths57fa1fb2007-05-19 20:29:41 +00007764 opn = "recip1.s";
7765 break;
Nathan Froydbf4120a2010-06-08 13:29:56 -07007766 case OPC_RSQRT1_S:
ths5e755512007-05-29 16:52:57 +00007767 check_cp1_64bitmode(ctx);
thsb6d96be2008-07-09 11:05:10 +00007768 {
pbrooka7812ae2008-11-17 14:43:54 +00007769 TCGv_i32 fp0 = tcg_temp_new_i32();
thsb6d96be2008-07-09 11:05:10 +00007770
7771 gen_load_fpr32(fp0, fs);
Blue Swirl895c2d02012-09-02 14:52:59 +00007772 gen_helper_float_rsqrt1_s(fp0, cpu_env, fp0);
thsb6d96be2008-07-09 11:05:10 +00007773 gen_store_fpr32(fp0, fd);
pbrooka7812ae2008-11-17 14:43:54 +00007774 tcg_temp_free_i32(fp0);
thsb6d96be2008-07-09 11:05:10 +00007775 }
ths57fa1fb2007-05-19 20:29:41 +00007776 opn = "rsqrt1.s";
7777 break;
Nathan Froydbf4120a2010-06-08 13:29:56 -07007778 case OPC_RSQRT2_S:
ths5e755512007-05-29 16:52:57 +00007779 check_cp1_64bitmode(ctx);
thsb6d96be2008-07-09 11:05:10 +00007780 {
pbrooka7812ae2008-11-17 14:43:54 +00007781 TCGv_i32 fp0 = tcg_temp_new_i32();
7782 TCGv_i32 fp1 = tcg_temp_new_i32();
thsb6d96be2008-07-09 11:05:10 +00007783
7784 gen_load_fpr32(fp0, fs);
7785 gen_load_fpr32(fp1, ft);
Blue Swirl895c2d02012-09-02 14:52:59 +00007786 gen_helper_float_rsqrt2_s(fp0, cpu_env, fp0, fp1);
pbrooka7812ae2008-11-17 14:43:54 +00007787 tcg_temp_free_i32(fp1);
thsb6d96be2008-07-09 11:05:10 +00007788 gen_store_fpr32(fp0, fd);
pbrooka7812ae2008-11-17 14:43:54 +00007789 tcg_temp_free_i32(fp0);
thsb6d96be2008-07-09 11:05:10 +00007790 }
ths57fa1fb2007-05-19 20:29:41 +00007791 opn = "rsqrt2.s";
7792 break;
Nathan Froydbf4120a2010-06-08 13:29:56 -07007793 case OPC_CVT_D_S:
ths5e755512007-05-29 16:52:57 +00007794 check_cp1_registers(ctx, fd);
thsb6d96be2008-07-09 11:05:10 +00007795 {
pbrooka7812ae2008-11-17 14:43:54 +00007796 TCGv_i32 fp32 = tcg_temp_new_i32();
7797 TCGv_i64 fp64 = tcg_temp_new_i64();
thsb6d96be2008-07-09 11:05:10 +00007798
7799 gen_load_fpr32(fp32, fs);
Blue Swirl895c2d02012-09-02 14:52:59 +00007800 gen_helper_float_cvtd_s(fp64, cpu_env, fp32);
pbrooka7812ae2008-11-17 14:43:54 +00007801 tcg_temp_free_i32(fp32);
thsb6d96be2008-07-09 11:05:10 +00007802 gen_store_fpr64(ctx, fp64, fd);
pbrooka7812ae2008-11-17 14:43:54 +00007803 tcg_temp_free_i64(fp64);
thsb6d96be2008-07-09 11:05:10 +00007804 }
ths5a5012e2007-05-07 13:55:33 +00007805 opn = "cvt.d.s";
7806 break;
Nathan Froydbf4120a2010-06-08 13:29:56 -07007807 case OPC_CVT_W_S:
thsb6d96be2008-07-09 11:05:10 +00007808 {
pbrooka7812ae2008-11-17 14:43:54 +00007809 TCGv_i32 fp0 = tcg_temp_new_i32();
thsb6d96be2008-07-09 11:05:10 +00007810
7811 gen_load_fpr32(fp0, fs);
Blue Swirl895c2d02012-09-02 14:52:59 +00007812 gen_helper_float_cvtw_s(fp0, cpu_env, fp0);
thsb6d96be2008-07-09 11:05:10 +00007813 gen_store_fpr32(fp0, fd);
pbrooka7812ae2008-11-17 14:43:54 +00007814 tcg_temp_free_i32(fp0);
thsb6d96be2008-07-09 11:05:10 +00007815 }
ths5a5012e2007-05-07 13:55:33 +00007816 opn = "cvt.w.s";
7817 break;
Nathan Froydbf4120a2010-06-08 13:29:56 -07007818 case OPC_CVT_L_S:
ths5e755512007-05-29 16:52:57 +00007819 check_cp1_64bitmode(ctx);
thsb6d96be2008-07-09 11:05:10 +00007820 {
pbrooka7812ae2008-11-17 14:43:54 +00007821 TCGv_i32 fp32 = tcg_temp_new_i32();
7822 TCGv_i64 fp64 = tcg_temp_new_i64();
thsb6d96be2008-07-09 11:05:10 +00007823
7824 gen_load_fpr32(fp32, fs);
Blue Swirl895c2d02012-09-02 14:52:59 +00007825 gen_helper_float_cvtl_s(fp64, cpu_env, fp32);
pbrooka7812ae2008-11-17 14:43:54 +00007826 tcg_temp_free_i32(fp32);
thsb6d96be2008-07-09 11:05:10 +00007827 gen_store_fpr64(ctx, fp64, fd);
pbrooka7812ae2008-11-17 14:43:54 +00007828 tcg_temp_free_i64(fp64);
thsb6d96be2008-07-09 11:05:10 +00007829 }
ths5a5012e2007-05-07 13:55:33 +00007830 opn = "cvt.l.s";
7831 break;
Nathan Froydbf4120a2010-06-08 13:29:56 -07007832 case OPC_CVT_PS_S:
ths5e755512007-05-29 16:52:57 +00007833 check_cp1_64bitmode(ctx);
thsb6d96be2008-07-09 11:05:10 +00007834 {
pbrooka7812ae2008-11-17 14:43:54 +00007835 TCGv_i64 fp64 = tcg_temp_new_i64();
7836 TCGv_i32 fp32_0 = tcg_temp_new_i32();
7837 TCGv_i32 fp32_1 = tcg_temp_new_i32();
thsb6d96be2008-07-09 11:05:10 +00007838
7839 gen_load_fpr32(fp32_0, fs);
7840 gen_load_fpr32(fp32_1, ft);
Richard Sandiford13d24f42012-08-27 09:53:29 +01007841 tcg_gen_concat_i32_i64(fp64, fp32_1, fp32_0);
pbrooka7812ae2008-11-17 14:43:54 +00007842 tcg_temp_free_i32(fp32_1);
7843 tcg_temp_free_i32(fp32_0);
pbrook36aa55d2008-09-21 13:48:32 +00007844 gen_store_fpr64(ctx, fp64, fd);
pbrooka7812ae2008-11-17 14:43:54 +00007845 tcg_temp_free_i64(fp64);
thsb6d96be2008-07-09 11:05:10 +00007846 }
ths5a5012e2007-05-07 13:55:33 +00007847 opn = "cvt.ps.s";
7848 break;
Nathan Froydbf4120a2010-06-08 13:29:56 -07007849 case OPC_CMP_F_S:
7850 case OPC_CMP_UN_S:
7851 case OPC_CMP_EQ_S:
7852 case OPC_CMP_UEQ_S:
7853 case OPC_CMP_OLT_S:
7854 case OPC_CMP_ULT_S:
7855 case OPC_CMP_OLE_S:
7856 case OPC_CMP_ULE_S:
7857 case OPC_CMP_SF_S:
7858 case OPC_CMP_NGLE_S:
7859 case OPC_CMP_SEQ_S:
7860 case OPC_CMP_NGL_S:
7861 case OPC_CMP_LT_S:
7862 case OPC_CMP_NGE_S:
7863 case OPC_CMP_LE_S:
7864 case OPC_CMP_NGT_S:
Nathan Froyd8153667c2010-06-08 13:29:57 -07007865 if (ctx->opcode & (1 << 6)) {
7866 gen_cmpabs_s(ctx, func-48, ft, fs, cc);
7867 opn = condnames_abs[func-48];
7868 } else {
7869 gen_cmp_s(ctx, func-48, ft, fs, cc);
7870 opn = condnames[func-48];
ths5a1e8ff2007-05-11 17:08:26 +00007871 }
ths5a5012e2007-05-07 13:55:33 +00007872 break;
Nathan Froydbf4120a2010-06-08 13:29:56 -07007873 case OPC_ADD_D:
ths5e755512007-05-29 16:52:57 +00007874 check_cp1_registers(ctx, fs | ft | fd);
thsb6d96be2008-07-09 11:05:10 +00007875 {
pbrooka7812ae2008-11-17 14:43:54 +00007876 TCGv_i64 fp0 = tcg_temp_new_i64();
7877 TCGv_i64 fp1 = tcg_temp_new_i64();
thsb6d96be2008-07-09 11:05:10 +00007878
7879 gen_load_fpr64(ctx, fp0, fs);
7880 gen_load_fpr64(ctx, fp1, ft);
Blue Swirl895c2d02012-09-02 14:52:59 +00007881 gen_helper_float_add_d(fp0, cpu_env, fp0, fp1);
pbrooka7812ae2008-11-17 14:43:54 +00007882 tcg_temp_free_i64(fp1);
thsb6d96be2008-07-09 11:05:10 +00007883 gen_store_fpr64(ctx, fp0, fd);
pbrooka7812ae2008-11-17 14:43:54 +00007884 tcg_temp_free_i64(fp0);
thsb6d96be2008-07-09 11:05:10 +00007885 }
bellard6ea83fe2006-06-14 12:56:19 +00007886 opn = "add.d";
ths5a1e8ff2007-05-11 17:08:26 +00007887 optype = BINOP;
bellard6ea83fe2006-06-14 12:56:19 +00007888 break;
Nathan Froydbf4120a2010-06-08 13:29:56 -07007889 case OPC_SUB_D:
ths5e755512007-05-29 16:52:57 +00007890 check_cp1_registers(ctx, fs | ft | fd);
thsb6d96be2008-07-09 11:05:10 +00007891 {
pbrooka7812ae2008-11-17 14:43:54 +00007892 TCGv_i64 fp0 = tcg_temp_new_i64();
7893 TCGv_i64 fp1 = tcg_temp_new_i64();
thsb6d96be2008-07-09 11:05:10 +00007894
7895 gen_load_fpr64(ctx, fp0, fs);
7896 gen_load_fpr64(ctx, fp1, ft);
Blue Swirl895c2d02012-09-02 14:52:59 +00007897 gen_helper_float_sub_d(fp0, cpu_env, fp0, fp1);
pbrooka7812ae2008-11-17 14:43:54 +00007898 tcg_temp_free_i64(fp1);
thsb6d96be2008-07-09 11:05:10 +00007899 gen_store_fpr64(ctx, fp0, fd);
pbrooka7812ae2008-11-17 14:43:54 +00007900 tcg_temp_free_i64(fp0);
thsb6d96be2008-07-09 11:05:10 +00007901 }
bellard6ea83fe2006-06-14 12:56:19 +00007902 opn = "sub.d";
ths5a1e8ff2007-05-11 17:08:26 +00007903 optype = BINOP;
bellard6ea83fe2006-06-14 12:56:19 +00007904 break;
Nathan Froydbf4120a2010-06-08 13:29:56 -07007905 case OPC_MUL_D:
ths5e755512007-05-29 16:52:57 +00007906 check_cp1_registers(ctx, fs | ft | fd);
thsb6d96be2008-07-09 11:05:10 +00007907 {
pbrooka7812ae2008-11-17 14:43:54 +00007908 TCGv_i64 fp0 = tcg_temp_new_i64();
7909 TCGv_i64 fp1 = tcg_temp_new_i64();
thsb6d96be2008-07-09 11:05:10 +00007910
7911 gen_load_fpr64(ctx, fp0, fs);
7912 gen_load_fpr64(ctx, fp1, ft);
Blue Swirl895c2d02012-09-02 14:52:59 +00007913 gen_helper_float_mul_d(fp0, cpu_env, fp0, fp1);
pbrooka7812ae2008-11-17 14:43:54 +00007914 tcg_temp_free_i64(fp1);
thsb6d96be2008-07-09 11:05:10 +00007915 gen_store_fpr64(ctx, fp0, fd);
pbrooka7812ae2008-11-17 14:43:54 +00007916 tcg_temp_free_i64(fp0);
thsb6d96be2008-07-09 11:05:10 +00007917 }
bellard6ea83fe2006-06-14 12:56:19 +00007918 opn = "mul.d";
ths5a1e8ff2007-05-11 17:08:26 +00007919 optype = BINOP;
bellard6ea83fe2006-06-14 12:56:19 +00007920 break;
Nathan Froydbf4120a2010-06-08 13:29:56 -07007921 case OPC_DIV_D:
ths5e755512007-05-29 16:52:57 +00007922 check_cp1_registers(ctx, fs | ft | fd);
thsb6d96be2008-07-09 11:05:10 +00007923 {
pbrooka7812ae2008-11-17 14:43:54 +00007924 TCGv_i64 fp0 = tcg_temp_new_i64();
7925 TCGv_i64 fp1 = tcg_temp_new_i64();
thsb6d96be2008-07-09 11:05:10 +00007926
7927 gen_load_fpr64(ctx, fp0, fs);
7928 gen_load_fpr64(ctx, fp1, ft);
Blue Swirl895c2d02012-09-02 14:52:59 +00007929 gen_helper_float_div_d(fp0, cpu_env, fp0, fp1);
pbrooka7812ae2008-11-17 14:43:54 +00007930 tcg_temp_free_i64(fp1);
thsb6d96be2008-07-09 11:05:10 +00007931 gen_store_fpr64(ctx, fp0, fd);
pbrooka7812ae2008-11-17 14:43:54 +00007932 tcg_temp_free_i64(fp0);
thsb6d96be2008-07-09 11:05:10 +00007933 }
bellard6ea83fe2006-06-14 12:56:19 +00007934 opn = "div.d";
ths5a1e8ff2007-05-11 17:08:26 +00007935 optype = BINOP;
bellard6ea83fe2006-06-14 12:56:19 +00007936 break;
Nathan Froydbf4120a2010-06-08 13:29:56 -07007937 case OPC_SQRT_D:
ths5e755512007-05-29 16:52:57 +00007938 check_cp1_registers(ctx, fs | fd);
thsb6d96be2008-07-09 11:05:10 +00007939 {
pbrooka7812ae2008-11-17 14:43:54 +00007940 TCGv_i64 fp0 = tcg_temp_new_i64();
thsb6d96be2008-07-09 11:05:10 +00007941
7942 gen_load_fpr64(ctx, fp0, fs);
Blue Swirl895c2d02012-09-02 14:52:59 +00007943 gen_helper_float_sqrt_d(fp0, cpu_env, fp0);
thsb6d96be2008-07-09 11:05:10 +00007944 gen_store_fpr64(ctx, fp0, fd);
pbrooka7812ae2008-11-17 14:43:54 +00007945 tcg_temp_free_i64(fp0);
thsb6d96be2008-07-09 11:05:10 +00007946 }
bellard6ea83fe2006-06-14 12:56:19 +00007947 opn = "sqrt.d";
7948 break;
Nathan Froydbf4120a2010-06-08 13:29:56 -07007949 case OPC_ABS_D:
ths5e755512007-05-29 16:52:57 +00007950 check_cp1_registers(ctx, fs | fd);
thsb6d96be2008-07-09 11:05:10 +00007951 {
pbrooka7812ae2008-11-17 14:43:54 +00007952 TCGv_i64 fp0 = tcg_temp_new_i64();
thsb6d96be2008-07-09 11:05:10 +00007953
7954 gen_load_fpr64(ctx, fp0, fs);
pbrooka7812ae2008-11-17 14:43:54 +00007955 gen_helper_float_abs_d(fp0, fp0);
thsb6d96be2008-07-09 11:05:10 +00007956 gen_store_fpr64(ctx, fp0, fd);
pbrooka7812ae2008-11-17 14:43:54 +00007957 tcg_temp_free_i64(fp0);
thsb6d96be2008-07-09 11:05:10 +00007958 }
bellard6ea83fe2006-06-14 12:56:19 +00007959 opn = "abs.d";
7960 break;
Nathan Froydbf4120a2010-06-08 13:29:56 -07007961 case OPC_MOV_D:
ths5e755512007-05-29 16:52:57 +00007962 check_cp1_registers(ctx, fs | fd);
thsb6d96be2008-07-09 11:05:10 +00007963 {
pbrooka7812ae2008-11-17 14:43:54 +00007964 TCGv_i64 fp0 = tcg_temp_new_i64();
thsb6d96be2008-07-09 11:05:10 +00007965
7966 gen_load_fpr64(ctx, fp0, fs);
7967 gen_store_fpr64(ctx, fp0, fd);
pbrooka7812ae2008-11-17 14:43:54 +00007968 tcg_temp_free_i64(fp0);
thsb6d96be2008-07-09 11:05:10 +00007969 }
bellard6ea83fe2006-06-14 12:56:19 +00007970 opn = "mov.d";
7971 break;
Nathan Froydbf4120a2010-06-08 13:29:56 -07007972 case OPC_NEG_D:
ths5e755512007-05-29 16:52:57 +00007973 check_cp1_registers(ctx, fs | fd);
thsb6d96be2008-07-09 11:05:10 +00007974 {
pbrooka7812ae2008-11-17 14:43:54 +00007975 TCGv_i64 fp0 = tcg_temp_new_i64();
thsb6d96be2008-07-09 11:05:10 +00007976
7977 gen_load_fpr64(ctx, fp0, fs);
pbrooka7812ae2008-11-17 14:43:54 +00007978 gen_helper_float_chs_d(fp0, fp0);
thsb6d96be2008-07-09 11:05:10 +00007979 gen_store_fpr64(ctx, fp0, fd);
pbrooka7812ae2008-11-17 14:43:54 +00007980 tcg_temp_free_i64(fp0);
thsb6d96be2008-07-09 11:05:10 +00007981 }
bellard6ea83fe2006-06-14 12:56:19 +00007982 opn = "neg.d";
7983 break;
Nathan Froydbf4120a2010-06-08 13:29:56 -07007984 case OPC_ROUND_L_D:
ths5e755512007-05-29 16:52:57 +00007985 check_cp1_64bitmode(ctx);
thsb6d96be2008-07-09 11:05:10 +00007986 {
pbrooka7812ae2008-11-17 14:43:54 +00007987 TCGv_i64 fp0 = tcg_temp_new_i64();
thsb6d96be2008-07-09 11:05:10 +00007988
7989 gen_load_fpr64(ctx, fp0, fs);
Blue Swirl895c2d02012-09-02 14:52:59 +00007990 gen_helper_float_roundl_d(fp0, cpu_env, fp0);
thsb6d96be2008-07-09 11:05:10 +00007991 gen_store_fpr64(ctx, fp0, fd);
pbrooka7812ae2008-11-17 14:43:54 +00007992 tcg_temp_free_i64(fp0);
thsb6d96be2008-07-09 11:05:10 +00007993 }
ths5a5012e2007-05-07 13:55:33 +00007994 opn = "round.l.d";
7995 break;
Nathan Froydbf4120a2010-06-08 13:29:56 -07007996 case OPC_TRUNC_L_D:
ths5e755512007-05-29 16:52:57 +00007997 check_cp1_64bitmode(ctx);
thsb6d96be2008-07-09 11:05:10 +00007998 {
pbrooka7812ae2008-11-17 14:43:54 +00007999 TCGv_i64 fp0 = tcg_temp_new_i64();
thsb6d96be2008-07-09 11:05:10 +00008000
8001 gen_load_fpr64(ctx, fp0, fs);
Blue Swirl895c2d02012-09-02 14:52:59 +00008002 gen_helper_float_truncl_d(fp0, cpu_env, fp0);
thsb6d96be2008-07-09 11:05:10 +00008003 gen_store_fpr64(ctx, fp0, fd);
pbrooka7812ae2008-11-17 14:43:54 +00008004 tcg_temp_free_i64(fp0);
thsb6d96be2008-07-09 11:05:10 +00008005 }
ths5a5012e2007-05-07 13:55:33 +00008006 opn = "trunc.l.d";
8007 break;
Nathan Froydbf4120a2010-06-08 13:29:56 -07008008 case OPC_CEIL_L_D:
ths5e755512007-05-29 16:52:57 +00008009 check_cp1_64bitmode(ctx);
thsb6d96be2008-07-09 11:05:10 +00008010 {
pbrooka7812ae2008-11-17 14:43:54 +00008011 TCGv_i64 fp0 = tcg_temp_new_i64();
thsb6d96be2008-07-09 11:05:10 +00008012
8013 gen_load_fpr64(ctx, fp0, fs);
Blue Swirl895c2d02012-09-02 14:52:59 +00008014 gen_helper_float_ceill_d(fp0, cpu_env, fp0);
thsb6d96be2008-07-09 11:05:10 +00008015 gen_store_fpr64(ctx, fp0, fd);
pbrooka7812ae2008-11-17 14:43:54 +00008016 tcg_temp_free_i64(fp0);
thsb6d96be2008-07-09 11:05:10 +00008017 }
ths5a5012e2007-05-07 13:55:33 +00008018 opn = "ceil.l.d";
8019 break;
Nathan Froydbf4120a2010-06-08 13:29:56 -07008020 case OPC_FLOOR_L_D:
ths5e755512007-05-29 16:52:57 +00008021 check_cp1_64bitmode(ctx);
thsb6d96be2008-07-09 11:05:10 +00008022 {
pbrooka7812ae2008-11-17 14:43:54 +00008023 TCGv_i64 fp0 = tcg_temp_new_i64();
thsb6d96be2008-07-09 11:05:10 +00008024
8025 gen_load_fpr64(ctx, fp0, fs);
Blue Swirl895c2d02012-09-02 14:52:59 +00008026 gen_helper_float_floorl_d(fp0, cpu_env, fp0);
thsb6d96be2008-07-09 11:05:10 +00008027 gen_store_fpr64(ctx, fp0, fd);
pbrooka7812ae2008-11-17 14:43:54 +00008028 tcg_temp_free_i64(fp0);
thsb6d96be2008-07-09 11:05:10 +00008029 }
ths5a5012e2007-05-07 13:55:33 +00008030 opn = "floor.l.d";
8031 break;
Nathan Froydbf4120a2010-06-08 13:29:56 -07008032 case OPC_ROUND_W_D:
ths5e755512007-05-29 16:52:57 +00008033 check_cp1_registers(ctx, fs);
thsb6d96be2008-07-09 11:05:10 +00008034 {
pbrooka7812ae2008-11-17 14:43:54 +00008035 TCGv_i32 fp32 = tcg_temp_new_i32();
8036 TCGv_i64 fp64 = tcg_temp_new_i64();
thsb6d96be2008-07-09 11:05:10 +00008037
8038 gen_load_fpr64(ctx, fp64, fs);
Blue Swirl895c2d02012-09-02 14:52:59 +00008039 gen_helper_float_roundw_d(fp32, cpu_env, fp64);
pbrooka7812ae2008-11-17 14:43:54 +00008040 tcg_temp_free_i64(fp64);
thsb6d96be2008-07-09 11:05:10 +00008041 gen_store_fpr32(fp32, fd);
pbrooka7812ae2008-11-17 14:43:54 +00008042 tcg_temp_free_i32(fp32);
thsb6d96be2008-07-09 11:05:10 +00008043 }
bellard6ea83fe2006-06-14 12:56:19 +00008044 opn = "round.w.d";
8045 break;
Nathan Froydbf4120a2010-06-08 13:29:56 -07008046 case OPC_TRUNC_W_D:
ths5e755512007-05-29 16:52:57 +00008047 check_cp1_registers(ctx, fs);
thsb6d96be2008-07-09 11:05:10 +00008048 {
pbrooka7812ae2008-11-17 14:43:54 +00008049 TCGv_i32 fp32 = tcg_temp_new_i32();
8050 TCGv_i64 fp64 = tcg_temp_new_i64();
thsb6d96be2008-07-09 11:05:10 +00008051
8052 gen_load_fpr64(ctx, fp64, fs);
Blue Swirl895c2d02012-09-02 14:52:59 +00008053 gen_helper_float_truncw_d(fp32, cpu_env, fp64);
pbrooka7812ae2008-11-17 14:43:54 +00008054 tcg_temp_free_i64(fp64);
thsb6d96be2008-07-09 11:05:10 +00008055 gen_store_fpr32(fp32, fd);
pbrooka7812ae2008-11-17 14:43:54 +00008056 tcg_temp_free_i32(fp32);
thsb6d96be2008-07-09 11:05:10 +00008057 }
bellard6ea83fe2006-06-14 12:56:19 +00008058 opn = "trunc.w.d";
8059 break;
Nathan Froydbf4120a2010-06-08 13:29:56 -07008060 case OPC_CEIL_W_D:
ths5e755512007-05-29 16:52:57 +00008061 check_cp1_registers(ctx, fs);
thsb6d96be2008-07-09 11:05:10 +00008062 {
pbrooka7812ae2008-11-17 14:43:54 +00008063 TCGv_i32 fp32 = tcg_temp_new_i32();
8064 TCGv_i64 fp64 = tcg_temp_new_i64();
thsb6d96be2008-07-09 11:05:10 +00008065
8066 gen_load_fpr64(ctx, fp64, fs);
Blue Swirl895c2d02012-09-02 14:52:59 +00008067 gen_helper_float_ceilw_d(fp32, cpu_env, fp64);
pbrooka7812ae2008-11-17 14:43:54 +00008068 tcg_temp_free_i64(fp64);
thsb6d96be2008-07-09 11:05:10 +00008069 gen_store_fpr32(fp32, fd);
pbrooka7812ae2008-11-17 14:43:54 +00008070 tcg_temp_free_i32(fp32);
thsb6d96be2008-07-09 11:05:10 +00008071 }
bellard6ea83fe2006-06-14 12:56:19 +00008072 opn = "ceil.w.d";
8073 break;
Nathan Froydbf4120a2010-06-08 13:29:56 -07008074 case OPC_FLOOR_W_D:
ths5e755512007-05-29 16:52:57 +00008075 check_cp1_registers(ctx, fs);
thsb6d96be2008-07-09 11:05:10 +00008076 {
pbrooka7812ae2008-11-17 14:43:54 +00008077 TCGv_i32 fp32 = tcg_temp_new_i32();
8078 TCGv_i64 fp64 = tcg_temp_new_i64();
thsb6d96be2008-07-09 11:05:10 +00008079
8080 gen_load_fpr64(ctx, fp64, fs);
Blue Swirl895c2d02012-09-02 14:52:59 +00008081 gen_helper_float_floorw_d(fp32, cpu_env, fp64);
pbrooka7812ae2008-11-17 14:43:54 +00008082 tcg_temp_free_i64(fp64);
thsb6d96be2008-07-09 11:05:10 +00008083 gen_store_fpr32(fp32, fd);
pbrooka7812ae2008-11-17 14:43:54 +00008084 tcg_temp_free_i32(fp32);
thsb6d96be2008-07-09 11:05:10 +00008085 }
ths7a387ff2006-12-06 20:17:30 +00008086 opn = "floor.w.d";
bellard6ea83fe2006-06-14 12:56:19 +00008087 break;
Nathan Froydbf4120a2010-06-08 13:29:56 -07008088 case OPC_MOVCF_D:
thsb6d96be2008-07-09 11:05:10 +00008089 gen_movcf_d(ctx, fs, fd, (ft >> 2) & 0x7, ft & 0x1);
ths5a5012e2007-05-07 13:55:33 +00008090 opn = "movcf.d";
bellarddd016882006-10-23 21:25:11 +00008091 break;
Nathan Froydbf4120a2010-06-08 13:29:56 -07008092 case OPC_MOVZ_D:
thsa16336e2008-06-19 18:35:02 +00008093 {
8094 int l1 = gen_new_label();
aurel32c9297f42009-04-08 21:48:27 +00008095 TCGv_i64 fp0;
thsa16336e2008-06-19 18:35:02 +00008096
aurel32c9297f42009-04-08 21:48:27 +00008097 if (ft != 0) {
8098 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[ft], 0, l1);
8099 }
8100 fp0 = tcg_temp_new_i64();
thsb6d96be2008-07-09 11:05:10 +00008101 gen_load_fpr64(ctx, fp0, fs);
8102 gen_store_fpr64(ctx, fp0, fd);
pbrooka7812ae2008-11-17 14:43:54 +00008103 tcg_temp_free_i64(fp0);
thsa16336e2008-06-19 18:35:02 +00008104 gen_set_label(l1);
8105 }
ths5a5012e2007-05-07 13:55:33 +00008106 opn = "movz.d";
8107 break;
Nathan Froydbf4120a2010-06-08 13:29:56 -07008108 case OPC_MOVN_D:
thsa16336e2008-06-19 18:35:02 +00008109 {
8110 int l1 = gen_new_label();
aurel32c9297f42009-04-08 21:48:27 +00008111 TCGv_i64 fp0;
thsa16336e2008-06-19 18:35:02 +00008112
aurel32c9297f42009-04-08 21:48:27 +00008113 if (ft != 0) {
8114 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[ft], 0, l1);
8115 fp0 = tcg_temp_new_i64();
8116 gen_load_fpr64(ctx, fp0, fs);
8117 gen_store_fpr64(ctx, fp0, fd);
8118 tcg_temp_free_i64(fp0);
8119 gen_set_label(l1);
8120 }
thsa16336e2008-06-19 18:35:02 +00008121 }
ths5a5012e2007-05-07 13:55:33 +00008122 opn = "movn.d";
bellard6ea83fe2006-06-14 12:56:19 +00008123 break;
Nathan Froydbf4120a2010-06-08 13:29:56 -07008124 case OPC_RECIP_D:
thsb8aa4592007-12-30 15:36:58 +00008125 check_cp1_64bitmode(ctx);
thsb6d96be2008-07-09 11:05:10 +00008126 {
pbrooka7812ae2008-11-17 14:43:54 +00008127 TCGv_i64 fp0 = tcg_temp_new_i64();
thsb6d96be2008-07-09 11:05:10 +00008128
8129 gen_load_fpr64(ctx, fp0, fs);
Blue Swirl895c2d02012-09-02 14:52:59 +00008130 gen_helper_float_recip_d(fp0, cpu_env, fp0);
thsb6d96be2008-07-09 11:05:10 +00008131 gen_store_fpr64(ctx, fp0, fd);
pbrooka7812ae2008-11-17 14:43:54 +00008132 tcg_temp_free_i64(fp0);
thsb6d96be2008-07-09 11:05:10 +00008133 }
ths57fa1fb2007-05-19 20:29:41 +00008134 opn = "recip.d";
8135 break;
Nathan Froydbf4120a2010-06-08 13:29:56 -07008136 case OPC_RSQRT_D:
thsb8aa4592007-12-30 15:36:58 +00008137 check_cp1_64bitmode(ctx);
thsb6d96be2008-07-09 11:05:10 +00008138 {
pbrooka7812ae2008-11-17 14:43:54 +00008139 TCGv_i64 fp0 = tcg_temp_new_i64();
thsb6d96be2008-07-09 11:05:10 +00008140
8141 gen_load_fpr64(ctx, fp0, fs);
Blue Swirl895c2d02012-09-02 14:52:59 +00008142 gen_helper_float_rsqrt_d(fp0, cpu_env, fp0);
thsb6d96be2008-07-09 11:05:10 +00008143 gen_store_fpr64(ctx, fp0, fd);
pbrooka7812ae2008-11-17 14:43:54 +00008144 tcg_temp_free_i64(fp0);
thsb6d96be2008-07-09 11:05:10 +00008145 }
ths57fa1fb2007-05-19 20:29:41 +00008146 opn = "rsqrt.d";
8147 break;
Nathan Froydbf4120a2010-06-08 13:29:56 -07008148 case OPC_RECIP2_D:
ths5e755512007-05-29 16:52:57 +00008149 check_cp1_64bitmode(ctx);
thsb6d96be2008-07-09 11:05:10 +00008150 {
pbrooka7812ae2008-11-17 14:43:54 +00008151 TCGv_i64 fp0 = tcg_temp_new_i64();
8152 TCGv_i64 fp1 = tcg_temp_new_i64();
thsb6d96be2008-07-09 11:05:10 +00008153
8154 gen_load_fpr64(ctx, fp0, fs);
8155 gen_load_fpr64(ctx, fp1, ft);
Blue Swirl895c2d02012-09-02 14:52:59 +00008156 gen_helper_float_recip2_d(fp0, cpu_env, fp0, fp1);
pbrooka7812ae2008-11-17 14:43:54 +00008157 tcg_temp_free_i64(fp1);
thsb6d96be2008-07-09 11:05:10 +00008158 gen_store_fpr64(ctx, fp0, fd);
pbrooka7812ae2008-11-17 14:43:54 +00008159 tcg_temp_free_i64(fp0);
thsb6d96be2008-07-09 11:05:10 +00008160 }
ths57fa1fb2007-05-19 20:29:41 +00008161 opn = "recip2.d";
8162 break;
Nathan Froydbf4120a2010-06-08 13:29:56 -07008163 case OPC_RECIP1_D:
ths5e755512007-05-29 16:52:57 +00008164 check_cp1_64bitmode(ctx);
thsb6d96be2008-07-09 11:05:10 +00008165 {
pbrooka7812ae2008-11-17 14:43:54 +00008166 TCGv_i64 fp0 = tcg_temp_new_i64();
thsb6d96be2008-07-09 11:05:10 +00008167
8168 gen_load_fpr64(ctx, fp0, fs);
Blue Swirl895c2d02012-09-02 14:52:59 +00008169 gen_helper_float_recip1_d(fp0, cpu_env, fp0);
thsb6d96be2008-07-09 11:05:10 +00008170 gen_store_fpr64(ctx, fp0, fd);
pbrooka7812ae2008-11-17 14:43:54 +00008171 tcg_temp_free_i64(fp0);
thsb6d96be2008-07-09 11:05:10 +00008172 }
ths57fa1fb2007-05-19 20:29:41 +00008173 opn = "recip1.d";
8174 break;
Nathan Froydbf4120a2010-06-08 13:29:56 -07008175 case OPC_RSQRT1_D:
ths5e755512007-05-29 16:52:57 +00008176 check_cp1_64bitmode(ctx);
thsb6d96be2008-07-09 11:05:10 +00008177 {
pbrooka7812ae2008-11-17 14:43:54 +00008178 TCGv_i64 fp0 = tcg_temp_new_i64();
thsb6d96be2008-07-09 11:05:10 +00008179
8180 gen_load_fpr64(ctx, fp0, fs);
Blue Swirl895c2d02012-09-02 14:52:59 +00008181 gen_helper_float_rsqrt1_d(fp0, cpu_env, fp0);
thsb6d96be2008-07-09 11:05:10 +00008182 gen_store_fpr64(ctx, fp0, fd);
pbrooka7812ae2008-11-17 14:43:54 +00008183 tcg_temp_free_i64(fp0);
thsb6d96be2008-07-09 11:05:10 +00008184 }
ths57fa1fb2007-05-19 20:29:41 +00008185 opn = "rsqrt1.d";
8186 break;
Nathan Froydbf4120a2010-06-08 13:29:56 -07008187 case OPC_RSQRT2_D:
ths5e755512007-05-29 16:52:57 +00008188 check_cp1_64bitmode(ctx);
thsb6d96be2008-07-09 11:05:10 +00008189 {
pbrooka7812ae2008-11-17 14:43:54 +00008190 TCGv_i64 fp0 = tcg_temp_new_i64();
8191 TCGv_i64 fp1 = tcg_temp_new_i64();
thsb6d96be2008-07-09 11:05:10 +00008192
8193 gen_load_fpr64(ctx, fp0, fs);
8194 gen_load_fpr64(ctx, fp1, ft);
Blue Swirl895c2d02012-09-02 14:52:59 +00008195 gen_helper_float_rsqrt2_d(fp0, cpu_env, fp0, fp1);
pbrooka7812ae2008-11-17 14:43:54 +00008196 tcg_temp_free_i64(fp1);
thsb6d96be2008-07-09 11:05:10 +00008197 gen_store_fpr64(ctx, fp0, fd);
pbrooka7812ae2008-11-17 14:43:54 +00008198 tcg_temp_free_i64(fp0);
thsb6d96be2008-07-09 11:05:10 +00008199 }
ths57fa1fb2007-05-19 20:29:41 +00008200 opn = "rsqrt2.d";
8201 break;
Nathan Froydbf4120a2010-06-08 13:29:56 -07008202 case OPC_CMP_F_D:
8203 case OPC_CMP_UN_D:
8204 case OPC_CMP_EQ_D:
8205 case OPC_CMP_UEQ_D:
8206 case OPC_CMP_OLT_D:
8207 case OPC_CMP_ULT_D:
8208 case OPC_CMP_OLE_D:
8209 case OPC_CMP_ULE_D:
8210 case OPC_CMP_SF_D:
8211 case OPC_CMP_NGLE_D:
8212 case OPC_CMP_SEQ_D:
8213 case OPC_CMP_NGL_D:
8214 case OPC_CMP_LT_D:
8215 case OPC_CMP_NGE_D:
8216 case OPC_CMP_LE_D:
8217 case OPC_CMP_NGT_D:
Nathan Froyd8153667c2010-06-08 13:29:57 -07008218 if (ctx->opcode & (1 << 6)) {
8219 gen_cmpabs_d(ctx, func-48, ft, fs, cc);
8220 opn = condnames_abs[func-48];
8221 } else {
8222 gen_cmp_d(ctx, func-48, ft, fs, cc);
8223 opn = condnames[func-48];
ths5a1e8ff2007-05-11 17:08:26 +00008224 }
bellard6ea83fe2006-06-14 12:56:19 +00008225 break;
Nathan Froydbf4120a2010-06-08 13:29:56 -07008226 case OPC_CVT_S_D:
ths5e755512007-05-29 16:52:57 +00008227 check_cp1_registers(ctx, fs);
thsb6d96be2008-07-09 11:05:10 +00008228 {
pbrooka7812ae2008-11-17 14:43:54 +00008229 TCGv_i32 fp32 = tcg_temp_new_i32();
8230 TCGv_i64 fp64 = tcg_temp_new_i64();
thsb6d96be2008-07-09 11:05:10 +00008231
8232 gen_load_fpr64(ctx, fp64, fs);
Blue Swirl895c2d02012-09-02 14:52:59 +00008233 gen_helper_float_cvts_d(fp32, cpu_env, fp64);
pbrooka7812ae2008-11-17 14:43:54 +00008234 tcg_temp_free_i64(fp64);
thsb6d96be2008-07-09 11:05:10 +00008235 gen_store_fpr32(fp32, fd);
pbrooka7812ae2008-11-17 14:43:54 +00008236 tcg_temp_free_i32(fp32);
thsb6d96be2008-07-09 11:05:10 +00008237 }
bellarddd016882006-10-23 21:25:11 +00008238 opn = "cvt.s.d";
8239 break;
Nathan Froydbf4120a2010-06-08 13:29:56 -07008240 case OPC_CVT_W_D:
ths5e755512007-05-29 16:52:57 +00008241 check_cp1_registers(ctx, fs);
thsb6d96be2008-07-09 11:05:10 +00008242 {
pbrooka7812ae2008-11-17 14:43:54 +00008243 TCGv_i32 fp32 = tcg_temp_new_i32();
8244 TCGv_i64 fp64 = tcg_temp_new_i64();
thsb6d96be2008-07-09 11:05:10 +00008245
8246 gen_load_fpr64(ctx, fp64, fs);
Blue Swirl895c2d02012-09-02 14:52:59 +00008247 gen_helper_float_cvtw_d(fp32, cpu_env, fp64);
pbrooka7812ae2008-11-17 14:43:54 +00008248 tcg_temp_free_i64(fp64);
thsb6d96be2008-07-09 11:05:10 +00008249 gen_store_fpr32(fp32, fd);
pbrooka7812ae2008-11-17 14:43:54 +00008250 tcg_temp_free_i32(fp32);
thsb6d96be2008-07-09 11:05:10 +00008251 }
bellard6ea83fe2006-06-14 12:56:19 +00008252 opn = "cvt.w.d";
8253 break;
Nathan Froydbf4120a2010-06-08 13:29:56 -07008254 case OPC_CVT_L_D:
ths5e755512007-05-29 16:52:57 +00008255 check_cp1_64bitmode(ctx);
thsb6d96be2008-07-09 11:05:10 +00008256 {
pbrooka7812ae2008-11-17 14:43:54 +00008257 TCGv_i64 fp0 = tcg_temp_new_i64();
thsb6d96be2008-07-09 11:05:10 +00008258
8259 gen_load_fpr64(ctx, fp0, fs);
Blue Swirl895c2d02012-09-02 14:52:59 +00008260 gen_helper_float_cvtl_d(fp0, cpu_env, fp0);
thsb6d96be2008-07-09 11:05:10 +00008261 gen_store_fpr64(ctx, fp0, fd);
pbrooka7812ae2008-11-17 14:43:54 +00008262 tcg_temp_free_i64(fp0);
thsb6d96be2008-07-09 11:05:10 +00008263 }
ths5a5012e2007-05-07 13:55:33 +00008264 opn = "cvt.l.d";
8265 break;
Nathan Froydbf4120a2010-06-08 13:29:56 -07008266 case OPC_CVT_S_W:
thsb6d96be2008-07-09 11:05:10 +00008267 {
pbrooka7812ae2008-11-17 14:43:54 +00008268 TCGv_i32 fp0 = tcg_temp_new_i32();
thsb6d96be2008-07-09 11:05:10 +00008269
8270 gen_load_fpr32(fp0, fs);
Blue Swirl895c2d02012-09-02 14:52:59 +00008271 gen_helper_float_cvts_w(fp0, cpu_env, fp0);
thsb6d96be2008-07-09 11:05:10 +00008272 gen_store_fpr32(fp0, fd);
pbrooka7812ae2008-11-17 14:43:54 +00008273 tcg_temp_free_i32(fp0);
thsb6d96be2008-07-09 11:05:10 +00008274 }
ths5a5012e2007-05-07 13:55:33 +00008275 opn = "cvt.s.w";
8276 break;
Nathan Froydbf4120a2010-06-08 13:29:56 -07008277 case OPC_CVT_D_W:
ths5e755512007-05-29 16:52:57 +00008278 check_cp1_registers(ctx, fd);
thsb6d96be2008-07-09 11:05:10 +00008279 {
pbrooka7812ae2008-11-17 14:43:54 +00008280 TCGv_i32 fp32 = tcg_temp_new_i32();
8281 TCGv_i64 fp64 = tcg_temp_new_i64();
thsb6d96be2008-07-09 11:05:10 +00008282
8283 gen_load_fpr32(fp32, fs);
Blue Swirl895c2d02012-09-02 14:52:59 +00008284 gen_helper_float_cvtd_w(fp64, cpu_env, fp32);
pbrooka7812ae2008-11-17 14:43:54 +00008285 tcg_temp_free_i32(fp32);
thsb6d96be2008-07-09 11:05:10 +00008286 gen_store_fpr64(ctx, fp64, fd);
pbrooka7812ae2008-11-17 14:43:54 +00008287 tcg_temp_free_i64(fp64);
thsb6d96be2008-07-09 11:05:10 +00008288 }
ths5a5012e2007-05-07 13:55:33 +00008289 opn = "cvt.d.w";
8290 break;
Nathan Froydbf4120a2010-06-08 13:29:56 -07008291 case OPC_CVT_S_L:
ths5e755512007-05-29 16:52:57 +00008292 check_cp1_64bitmode(ctx);
thsb6d96be2008-07-09 11:05:10 +00008293 {
pbrooka7812ae2008-11-17 14:43:54 +00008294 TCGv_i32 fp32 = tcg_temp_new_i32();
8295 TCGv_i64 fp64 = tcg_temp_new_i64();
thsb6d96be2008-07-09 11:05:10 +00008296
8297 gen_load_fpr64(ctx, fp64, fs);
Blue Swirl895c2d02012-09-02 14:52:59 +00008298 gen_helper_float_cvts_l(fp32, cpu_env, fp64);
pbrooka7812ae2008-11-17 14:43:54 +00008299 tcg_temp_free_i64(fp64);
thsb6d96be2008-07-09 11:05:10 +00008300 gen_store_fpr32(fp32, fd);
pbrooka7812ae2008-11-17 14:43:54 +00008301 tcg_temp_free_i32(fp32);
thsb6d96be2008-07-09 11:05:10 +00008302 }
ths5a5012e2007-05-07 13:55:33 +00008303 opn = "cvt.s.l";
8304 break;
Nathan Froydbf4120a2010-06-08 13:29:56 -07008305 case OPC_CVT_D_L:
ths5e755512007-05-29 16:52:57 +00008306 check_cp1_64bitmode(ctx);
thsb6d96be2008-07-09 11:05:10 +00008307 {
pbrooka7812ae2008-11-17 14:43:54 +00008308 TCGv_i64 fp0 = tcg_temp_new_i64();
thsb6d96be2008-07-09 11:05:10 +00008309
8310 gen_load_fpr64(ctx, fp0, fs);
Blue Swirl895c2d02012-09-02 14:52:59 +00008311 gen_helper_float_cvtd_l(fp0, cpu_env, fp0);
thsb6d96be2008-07-09 11:05:10 +00008312 gen_store_fpr64(ctx, fp0, fd);
pbrooka7812ae2008-11-17 14:43:54 +00008313 tcg_temp_free_i64(fp0);
thsb6d96be2008-07-09 11:05:10 +00008314 }
ths5a5012e2007-05-07 13:55:33 +00008315 opn = "cvt.d.l";
8316 break;
Nathan Froydbf4120a2010-06-08 13:29:56 -07008317 case OPC_CVT_PS_PW:
ths5e755512007-05-29 16:52:57 +00008318 check_cp1_64bitmode(ctx);
thsb6d96be2008-07-09 11:05:10 +00008319 {
pbrooka7812ae2008-11-17 14:43:54 +00008320 TCGv_i64 fp0 = tcg_temp_new_i64();
thsb6d96be2008-07-09 11:05:10 +00008321
8322 gen_load_fpr64(ctx, fp0, fs);
Blue Swirl895c2d02012-09-02 14:52:59 +00008323 gen_helper_float_cvtps_pw(fp0, cpu_env, fp0);
thsb6d96be2008-07-09 11:05:10 +00008324 gen_store_fpr64(ctx, fp0, fd);
pbrooka7812ae2008-11-17 14:43:54 +00008325 tcg_temp_free_i64(fp0);
thsb6d96be2008-07-09 11:05:10 +00008326 }
ths5a5012e2007-05-07 13:55:33 +00008327 opn = "cvt.ps.pw";
8328 break;
Nathan Froydbf4120a2010-06-08 13:29:56 -07008329 case OPC_ADD_PS:
ths5e755512007-05-29 16:52:57 +00008330 check_cp1_64bitmode(ctx);
thsb6d96be2008-07-09 11:05:10 +00008331 {
pbrooka7812ae2008-11-17 14:43:54 +00008332 TCGv_i64 fp0 = tcg_temp_new_i64();
8333 TCGv_i64 fp1 = tcg_temp_new_i64();
thsb6d96be2008-07-09 11:05:10 +00008334
8335 gen_load_fpr64(ctx, fp0, fs);
8336 gen_load_fpr64(ctx, fp1, ft);
Blue Swirl895c2d02012-09-02 14:52:59 +00008337 gen_helper_float_add_ps(fp0, cpu_env, fp0, fp1);
pbrooka7812ae2008-11-17 14:43:54 +00008338 tcg_temp_free_i64(fp1);
thsb6d96be2008-07-09 11:05:10 +00008339 gen_store_fpr64(ctx, fp0, fd);
pbrooka7812ae2008-11-17 14:43:54 +00008340 tcg_temp_free_i64(fp0);
thsb6d96be2008-07-09 11:05:10 +00008341 }
ths5a5012e2007-05-07 13:55:33 +00008342 opn = "add.ps";
8343 break;
Nathan Froydbf4120a2010-06-08 13:29:56 -07008344 case OPC_SUB_PS:
ths5e755512007-05-29 16:52:57 +00008345 check_cp1_64bitmode(ctx);
thsb6d96be2008-07-09 11:05:10 +00008346 {
pbrooka7812ae2008-11-17 14:43:54 +00008347 TCGv_i64 fp0 = tcg_temp_new_i64();
8348 TCGv_i64 fp1 = tcg_temp_new_i64();
thsb6d96be2008-07-09 11:05:10 +00008349
8350 gen_load_fpr64(ctx, fp0, fs);
8351 gen_load_fpr64(ctx, fp1, ft);
Blue Swirl895c2d02012-09-02 14:52:59 +00008352 gen_helper_float_sub_ps(fp0, cpu_env, fp0, fp1);
pbrooka7812ae2008-11-17 14:43:54 +00008353 tcg_temp_free_i64(fp1);
thsb6d96be2008-07-09 11:05:10 +00008354 gen_store_fpr64(ctx, fp0, fd);
pbrooka7812ae2008-11-17 14:43:54 +00008355 tcg_temp_free_i64(fp0);
thsb6d96be2008-07-09 11:05:10 +00008356 }
ths5a5012e2007-05-07 13:55:33 +00008357 opn = "sub.ps";
8358 break;
Nathan Froydbf4120a2010-06-08 13:29:56 -07008359 case OPC_MUL_PS:
ths5e755512007-05-29 16:52:57 +00008360 check_cp1_64bitmode(ctx);
thsb6d96be2008-07-09 11:05:10 +00008361 {
pbrooka7812ae2008-11-17 14:43:54 +00008362 TCGv_i64 fp0 = tcg_temp_new_i64();
8363 TCGv_i64 fp1 = tcg_temp_new_i64();
thsb6d96be2008-07-09 11:05:10 +00008364
8365 gen_load_fpr64(ctx, fp0, fs);
8366 gen_load_fpr64(ctx, fp1, ft);
Blue Swirl895c2d02012-09-02 14:52:59 +00008367 gen_helper_float_mul_ps(fp0, cpu_env, fp0, fp1);
pbrooka7812ae2008-11-17 14:43:54 +00008368 tcg_temp_free_i64(fp1);
thsb6d96be2008-07-09 11:05:10 +00008369 gen_store_fpr64(ctx, fp0, fd);
pbrooka7812ae2008-11-17 14:43:54 +00008370 tcg_temp_free_i64(fp0);
thsb6d96be2008-07-09 11:05:10 +00008371 }
ths5a5012e2007-05-07 13:55:33 +00008372 opn = "mul.ps";
8373 break;
Nathan Froydbf4120a2010-06-08 13:29:56 -07008374 case OPC_ABS_PS:
ths5e755512007-05-29 16:52:57 +00008375 check_cp1_64bitmode(ctx);
thsb6d96be2008-07-09 11:05:10 +00008376 {
pbrooka7812ae2008-11-17 14:43:54 +00008377 TCGv_i64 fp0 = tcg_temp_new_i64();
thsb6d96be2008-07-09 11:05:10 +00008378
8379 gen_load_fpr64(ctx, fp0, fs);
pbrooka7812ae2008-11-17 14:43:54 +00008380 gen_helper_float_abs_ps(fp0, fp0);
thsb6d96be2008-07-09 11:05:10 +00008381 gen_store_fpr64(ctx, fp0, fd);
pbrooka7812ae2008-11-17 14:43:54 +00008382 tcg_temp_free_i64(fp0);
thsb6d96be2008-07-09 11:05:10 +00008383 }
ths5a5012e2007-05-07 13:55:33 +00008384 opn = "abs.ps";
8385 break;
Nathan Froydbf4120a2010-06-08 13:29:56 -07008386 case OPC_MOV_PS:
ths5e755512007-05-29 16:52:57 +00008387 check_cp1_64bitmode(ctx);
thsb6d96be2008-07-09 11:05:10 +00008388 {
pbrooka7812ae2008-11-17 14:43:54 +00008389 TCGv_i64 fp0 = tcg_temp_new_i64();
thsb6d96be2008-07-09 11:05:10 +00008390
8391 gen_load_fpr64(ctx, fp0, fs);
8392 gen_store_fpr64(ctx, fp0, fd);
pbrooka7812ae2008-11-17 14:43:54 +00008393 tcg_temp_free_i64(fp0);
thsb6d96be2008-07-09 11:05:10 +00008394 }
ths5a5012e2007-05-07 13:55:33 +00008395 opn = "mov.ps";
8396 break;
Nathan Froydbf4120a2010-06-08 13:29:56 -07008397 case OPC_NEG_PS:
ths5e755512007-05-29 16:52:57 +00008398 check_cp1_64bitmode(ctx);
thsb6d96be2008-07-09 11:05:10 +00008399 {
pbrooka7812ae2008-11-17 14:43:54 +00008400 TCGv_i64 fp0 = tcg_temp_new_i64();
thsb6d96be2008-07-09 11:05:10 +00008401
8402 gen_load_fpr64(ctx, fp0, fs);
pbrooka7812ae2008-11-17 14:43:54 +00008403 gen_helper_float_chs_ps(fp0, fp0);
thsb6d96be2008-07-09 11:05:10 +00008404 gen_store_fpr64(ctx, fp0, fd);
pbrooka7812ae2008-11-17 14:43:54 +00008405 tcg_temp_free_i64(fp0);
thsb6d96be2008-07-09 11:05:10 +00008406 }
ths5a5012e2007-05-07 13:55:33 +00008407 opn = "neg.ps";
8408 break;
Nathan Froydbf4120a2010-06-08 13:29:56 -07008409 case OPC_MOVCF_PS:
ths5e755512007-05-29 16:52:57 +00008410 check_cp1_64bitmode(ctx);
thsb6d96be2008-07-09 11:05:10 +00008411 gen_movcf_ps(fs, fd, (ft >> 2) & 0x7, ft & 0x1);
ths5a5012e2007-05-07 13:55:33 +00008412 opn = "movcf.ps";
8413 break;
Nathan Froydbf4120a2010-06-08 13:29:56 -07008414 case OPC_MOVZ_PS:
ths5e755512007-05-29 16:52:57 +00008415 check_cp1_64bitmode(ctx);
thsa16336e2008-06-19 18:35:02 +00008416 {
8417 int l1 = gen_new_label();
aurel3230a38482009-04-12 08:32:45 +00008418 TCGv_i64 fp0;
thsa16336e2008-06-19 18:35:02 +00008419
aurel32c9297f42009-04-08 21:48:27 +00008420 if (ft != 0)
8421 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[ft], 0, l1);
8422 fp0 = tcg_temp_new_i64();
8423 gen_load_fpr64(ctx, fp0, fs);
8424 gen_store_fpr64(ctx, fp0, fd);
8425 tcg_temp_free_i64(fp0);
thsa16336e2008-06-19 18:35:02 +00008426 gen_set_label(l1);
8427 }
ths5a5012e2007-05-07 13:55:33 +00008428 opn = "movz.ps";
8429 break;
Nathan Froydbf4120a2010-06-08 13:29:56 -07008430 case OPC_MOVN_PS:
ths5e755512007-05-29 16:52:57 +00008431 check_cp1_64bitmode(ctx);
thsa16336e2008-06-19 18:35:02 +00008432 {
8433 int l1 = gen_new_label();
aurel3230a38482009-04-12 08:32:45 +00008434 TCGv_i64 fp0;
thsa16336e2008-06-19 18:35:02 +00008435
aurel32c9297f42009-04-08 21:48:27 +00008436 if (ft != 0) {
8437 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[ft], 0, l1);
8438 fp0 = tcg_temp_new_i64();
8439 gen_load_fpr64(ctx, fp0, fs);
8440 gen_store_fpr64(ctx, fp0, fd);
8441 tcg_temp_free_i64(fp0);
8442 gen_set_label(l1);
8443 }
thsa16336e2008-06-19 18:35:02 +00008444 }
ths5a5012e2007-05-07 13:55:33 +00008445 opn = "movn.ps";
8446 break;
Nathan Froydbf4120a2010-06-08 13:29:56 -07008447 case OPC_ADDR_PS:
ths5e755512007-05-29 16:52:57 +00008448 check_cp1_64bitmode(ctx);
thsb6d96be2008-07-09 11:05:10 +00008449 {
pbrooka7812ae2008-11-17 14:43:54 +00008450 TCGv_i64 fp0 = tcg_temp_new_i64();
8451 TCGv_i64 fp1 = tcg_temp_new_i64();
thsb6d96be2008-07-09 11:05:10 +00008452
8453 gen_load_fpr64(ctx, fp0, ft);
8454 gen_load_fpr64(ctx, fp1, fs);
Blue Swirl895c2d02012-09-02 14:52:59 +00008455 gen_helper_float_addr_ps(fp0, cpu_env, fp0, fp1);
pbrooka7812ae2008-11-17 14:43:54 +00008456 tcg_temp_free_i64(fp1);
thsb6d96be2008-07-09 11:05:10 +00008457 gen_store_fpr64(ctx, fp0, fd);
pbrooka7812ae2008-11-17 14:43:54 +00008458 tcg_temp_free_i64(fp0);
thsb6d96be2008-07-09 11:05:10 +00008459 }
thsfbcc6822007-05-11 09:59:10 +00008460 opn = "addr.ps";
8461 break;
Nathan Froydbf4120a2010-06-08 13:29:56 -07008462 case OPC_MULR_PS:
ths5e755512007-05-29 16:52:57 +00008463 check_cp1_64bitmode(ctx);
thsb6d96be2008-07-09 11:05:10 +00008464 {
pbrooka7812ae2008-11-17 14:43:54 +00008465 TCGv_i64 fp0 = tcg_temp_new_i64();
8466 TCGv_i64 fp1 = tcg_temp_new_i64();
thsb6d96be2008-07-09 11:05:10 +00008467
8468 gen_load_fpr64(ctx, fp0, ft);
8469 gen_load_fpr64(ctx, fp1, fs);
Blue Swirl895c2d02012-09-02 14:52:59 +00008470 gen_helper_float_mulr_ps(fp0, cpu_env, fp0, fp1);
pbrooka7812ae2008-11-17 14:43:54 +00008471 tcg_temp_free_i64(fp1);
thsb6d96be2008-07-09 11:05:10 +00008472 gen_store_fpr64(ctx, fp0, fd);
pbrooka7812ae2008-11-17 14:43:54 +00008473 tcg_temp_free_i64(fp0);
thsb6d96be2008-07-09 11:05:10 +00008474 }
ths57fa1fb2007-05-19 20:29:41 +00008475 opn = "mulr.ps";
8476 break;
Nathan Froydbf4120a2010-06-08 13:29:56 -07008477 case OPC_RECIP2_PS:
ths5e755512007-05-29 16:52:57 +00008478 check_cp1_64bitmode(ctx);
thsb6d96be2008-07-09 11:05:10 +00008479 {
pbrooka7812ae2008-11-17 14:43:54 +00008480 TCGv_i64 fp0 = tcg_temp_new_i64();
8481 TCGv_i64 fp1 = tcg_temp_new_i64();
thsb6d96be2008-07-09 11:05:10 +00008482
8483 gen_load_fpr64(ctx, fp0, fs);
Richard Sandifordd22d7282012-08-27 09:50:38 +01008484 gen_load_fpr64(ctx, fp1, ft);
Blue Swirl895c2d02012-09-02 14:52:59 +00008485 gen_helper_float_recip2_ps(fp0, cpu_env, fp0, fp1);
pbrooka7812ae2008-11-17 14:43:54 +00008486 tcg_temp_free_i64(fp1);
thsb6d96be2008-07-09 11:05:10 +00008487 gen_store_fpr64(ctx, fp0, fd);
pbrooka7812ae2008-11-17 14:43:54 +00008488 tcg_temp_free_i64(fp0);
thsb6d96be2008-07-09 11:05:10 +00008489 }
ths57fa1fb2007-05-19 20:29:41 +00008490 opn = "recip2.ps";
8491 break;
Nathan Froydbf4120a2010-06-08 13:29:56 -07008492 case OPC_RECIP1_PS:
ths5e755512007-05-29 16:52:57 +00008493 check_cp1_64bitmode(ctx);
thsb6d96be2008-07-09 11:05:10 +00008494 {
pbrooka7812ae2008-11-17 14:43:54 +00008495 TCGv_i64 fp0 = tcg_temp_new_i64();
thsb6d96be2008-07-09 11:05:10 +00008496
8497 gen_load_fpr64(ctx, fp0, fs);
Blue Swirl895c2d02012-09-02 14:52:59 +00008498 gen_helper_float_recip1_ps(fp0, cpu_env, fp0);
thsb6d96be2008-07-09 11:05:10 +00008499 gen_store_fpr64(ctx, fp0, fd);
pbrooka7812ae2008-11-17 14:43:54 +00008500 tcg_temp_free_i64(fp0);
thsb6d96be2008-07-09 11:05:10 +00008501 }
ths57fa1fb2007-05-19 20:29:41 +00008502 opn = "recip1.ps";
8503 break;
Nathan Froydbf4120a2010-06-08 13:29:56 -07008504 case OPC_RSQRT1_PS:
ths5e755512007-05-29 16:52:57 +00008505 check_cp1_64bitmode(ctx);
thsb6d96be2008-07-09 11:05:10 +00008506 {
pbrooka7812ae2008-11-17 14:43:54 +00008507 TCGv_i64 fp0 = tcg_temp_new_i64();
thsb6d96be2008-07-09 11:05:10 +00008508
8509 gen_load_fpr64(ctx, fp0, fs);
Blue Swirl895c2d02012-09-02 14:52:59 +00008510 gen_helper_float_rsqrt1_ps(fp0, cpu_env, fp0);
thsb6d96be2008-07-09 11:05:10 +00008511 gen_store_fpr64(ctx, fp0, fd);
pbrooka7812ae2008-11-17 14:43:54 +00008512 tcg_temp_free_i64(fp0);
thsb6d96be2008-07-09 11:05:10 +00008513 }
ths57fa1fb2007-05-19 20:29:41 +00008514 opn = "rsqrt1.ps";
8515 break;
Nathan Froydbf4120a2010-06-08 13:29:56 -07008516 case OPC_RSQRT2_PS:
ths5e755512007-05-29 16:52:57 +00008517 check_cp1_64bitmode(ctx);
thsb6d96be2008-07-09 11:05:10 +00008518 {
pbrooka7812ae2008-11-17 14:43:54 +00008519 TCGv_i64 fp0 = tcg_temp_new_i64();
8520 TCGv_i64 fp1 = tcg_temp_new_i64();
thsb6d96be2008-07-09 11:05:10 +00008521
8522 gen_load_fpr64(ctx, fp0, fs);
8523 gen_load_fpr64(ctx, fp1, ft);
Blue Swirl895c2d02012-09-02 14:52:59 +00008524 gen_helper_float_rsqrt2_ps(fp0, cpu_env, fp0, fp1);
pbrooka7812ae2008-11-17 14:43:54 +00008525 tcg_temp_free_i64(fp1);
thsb6d96be2008-07-09 11:05:10 +00008526 gen_store_fpr64(ctx, fp0, fd);
pbrooka7812ae2008-11-17 14:43:54 +00008527 tcg_temp_free_i64(fp0);
thsb6d96be2008-07-09 11:05:10 +00008528 }
ths57fa1fb2007-05-19 20:29:41 +00008529 opn = "rsqrt2.ps";
8530 break;
Nathan Froydbf4120a2010-06-08 13:29:56 -07008531 case OPC_CVT_S_PU:
ths5e755512007-05-29 16:52:57 +00008532 check_cp1_64bitmode(ctx);
thsb6d96be2008-07-09 11:05:10 +00008533 {
pbrooka7812ae2008-11-17 14:43:54 +00008534 TCGv_i32 fp0 = tcg_temp_new_i32();
thsb6d96be2008-07-09 11:05:10 +00008535
8536 gen_load_fpr32h(fp0, fs);
Blue Swirl895c2d02012-09-02 14:52:59 +00008537 gen_helper_float_cvts_pu(fp0, cpu_env, fp0);
thsb6d96be2008-07-09 11:05:10 +00008538 gen_store_fpr32(fp0, fd);
pbrooka7812ae2008-11-17 14:43:54 +00008539 tcg_temp_free_i32(fp0);
thsb6d96be2008-07-09 11:05:10 +00008540 }
ths5a5012e2007-05-07 13:55:33 +00008541 opn = "cvt.s.pu";
8542 break;
Nathan Froydbf4120a2010-06-08 13:29:56 -07008543 case OPC_CVT_PW_PS:
ths5e755512007-05-29 16:52:57 +00008544 check_cp1_64bitmode(ctx);
thsb6d96be2008-07-09 11:05:10 +00008545 {
pbrooka7812ae2008-11-17 14:43:54 +00008546 TCGv_i64 fp0 = tcg_temp_new_i64();
thsb6d96be2008-07-09 11:05:10 +00008547
8548 gen_load_fpr64(ctx, fp0, fs);
Blue Swirl895c2d02012-09-02 14:52:59 +00008549 gen_helper_float_cvtpw_ps(fp0, cpu_env, fp0);
thsb6d96be2008-07-09 11:05:10 +00008550 gen_store_fpr64(ctx, fp0, fd);
pbrooka7812ae2008-11-17 14:43:54 +00008551 tcg_temp_free_i64(fp0);
thsb6d96be2008-07-09 11:05:10 +00008552 }
ths5a5012e2007-05-07 13:55:33 +00008553 opn = "cvt.pw.ps";
8554 break;
Nathan Froydbf4120a2010-06-08 13:29:56 -07008555 case OPC_CVT_S_PL:
ths5e755512007-05-29 16:52:57 +00008556 check_cp1_64bitmode(ctx);
thsb6d96be2008-07-09 11:05:10 +00008557 {
pbrooka7812ae2008-11-17 14:43:54 +00008558 TCGv_i32 fp0 = tcg_temp_new_i32();
thsb6d96be2008-07-09 11:05:10 +00008559
8560 gen_load_fpr32(fp0, fs);
Blue Swirl895c2d02012-09-02 14:52:59 +00008561 gen_helper_float_cvts_pl(fp0, cpu_env, fp0);
thsb6d96be2008-07-09 11:05:10 +00008562 gen_store_fpr32(fp0, fd);
pbrooka7812ae2008-11-17 14:43:54 +00008563 tcg_temp_free_i32(fp0);
thsb6d96be2008-07-09 11:05:10 +00008564 }
ths5a5012e2007-05-07 13:55:33 +00008565 opn = "cvt.s.pl";
8566 break;
Nathan Froydbf4120a2010-06-08 13:29:56 -07008567 case OPC_PLL_PS:
ths5e755512007-05-29 16:52:57 +00008568 check_cp1_64bitmode(ctx);
thsb6d96be2008-07-09 11:05:10 +00008569 {
pbrooka7812ae2008-11-17 14:43:54 +00008570 TCGv_i32 fp0 = tcg_temp_new_i32();
8571 TCGv_i32 fp1 = tcg_temp_new_i32();
thsb6d96be2008-07-09 11:05:10 +00008572
8573 gen_load_fpr32(fp0, fs);
8574 gen_load_fpr32(fp1, ft);
8575 gen_store_fpr32h(fp0, fd);
8576 gen_store_fpr32(fp1, fd);
pbrooka7812ae2008-11-17 14:43:54 +00008577 tcg_temp_free_i32(fp0);
8578 tcg_temp_free_i32(fp1);
thsb6d96be2008-07-09 11:05:10 +00008579 }
ths5a5012e2007-05-07 13:55:33 +00008580 opn = "pll.ps";
8581 break;
Nathan Froydbf4120a2010-06-08 13:29:56 -07008582 case OPC_PLU_PS:
ths5e755512007-05-29 16:52:57 +00008583 check_cp1_64bitmode(ctx);
thsb6d96be2008-07-09 11:05:10 +00008584 {
pbrooka7812ae2008-11-17 14:43:54 +00008585 TCGv_i32 fp0 = tcg_temp_new_i32();
8586 TCGv_i32 fp1 = tcg_temp_new_i32();
thsb6d96be2008-07-09 11:05:10 +00008587
8588 gen_load_fpr32(fp0, fs);
8589 gen_load_fpr32h(fp1, ft);
8590 gen_store_fpr32(fp1, fd);
8591 gen_store_fpr32h(fp0, fd);
pbrooka7812ae2008-11-17 14:43:54 +00008592 tcg_temp_free_i32(fp0);
8593 tcg_temp_free_i32(fp1);
thsb6d96be2008-07-09 11:05:10 +00008594 }
ths5a5012e2007-05-07 13:55:33 +00008595 opn = "plu.ps";
8596 break;
Nathan Froydbf4120a2010-06-08 13:29:56 -07008597 case OPC_PUL_PS:
ths5e755512007-05-29 16:52:57 +00008598 check_cp1_64bitmode(ctx);
thsb6d96be2008-07-09 11:05:10 +00008599 {
pbrooka7812ae2008-11-17 14:43:54 +00008600 TCGv_i32 fp0 = tcg_temp_new_i32();
8601 TCGv_i32 fp1 = tcg_temp_new_i32();
thsb6d96be2008-07-09 11:05:10 +00008602
8603 gen_load_fpr32h(fp0, fs);
8604 gen_load_fpr32(fp1, ft);
8605 gen_store_fpr32(fp1, fd);
8606 gen_store_fpr32h(fp0, fd);
pbrooka7812ae2008-11-17 14:43:54 +00008607 tcg_temp_free_i32(fp0);
8608 tcg_temp_free_i32(fp1);
thsb6d96be2008-07-09 11:05:10 +00008609 }
ths5a5012e2007-05-07 13:55:33 +00008610 opn = "pul.ps";
8611 break;
Nathan Froydbf4120a2010-06-08 13:29:56 -07008612 case OPC_PUU_PS:
ths5e755512007-05-29 16:52:57 +00008613 check_cp1_64bitmode(ctx);
thsb6d96be2008-07-09 11:05:10 +00008614 {
pbrooka7812ae2008-11-17 14:43:54 +00008615 TCGv_i32 fp0 = tcg_temp_new_i32();
8616 TCGv_i32 fp1 = tcg_temp_new_i32();
thsb6d96be2008-07-09 11:05:10 +00008617
8618 gen_load_fpr32h(fp0, fs);
8619 gen_load_fpr32h(fp1, ft);
8620 gen_store_fpr32(fp1, fd);
8621 gen_store_fpr32h(fp0, fd);
pbrooka7812ae2008-11-17 14:43:54 +00008622 tcg_temp_free_i32(fp0);
8623 tcg_temp_free_i32(fp1);
thsb6d96be2008-07-09 11:05:10 +00008624 }
ths5a5012e2007-05-07 13:55:33 +00008625 opn = "puu.ps";
8626 break;
Nathan Froydbf4120a2010-06-08 13:29:56 -07008627 case OPC_CMP_F_PS:
8628 case OPC_CMP_UN_PS:
8629 case OPC_CMP_EQ_PS:
8630 case OPC_CMP_UEQ_PS:
8631 case OPC_CMP_OLT_PS:
8632 case OPC_CMP_ULT_PS:
8633 case OPC_CMP_OLE_PS:
8634 case OPC_CMP_ULE_PS:
8635 case OPC_CMP_SF_PS:
8636 case OPC_CMP_NGLE_PS:
8637 case OPC_CMP_SEQ_PS:
8638 case OPC_CMP_NGL_PS:
8639 case OPC_CMP_LT_PS:
8640 case OPC_CMP_NGE_PS:
8641 case OPC_CMP_LE_PS:
8642 case OPC_CMP_NGT_PS:
Nathan Froyd8153667c2010-06-08 13:29:57 -07008643 if (ctx->opcode & (1 << 6)) {
8644 gen_cmpabs_ps(ctx, func-48, ft, fs, cc);
8645 opn = condnames_abs[func-48];
8646 } else {
8647 gen_cmp_ps(ctx, func-48, ft, fs, cc);
8648 opn = condnames[func-48];
ths5a1e8ff2007-05-11 17:08:26 +00008649 }
bellard6ea83fe2006-06-14 12:56:19 +00008650 break;
ths5a5012e2007-05-07 13:55:33 +00008651 default:
ths923617a2007-05-11 00:16:06 +00008652 MIPS_INVAL(opn);
thse397ee32007-03-23 00:43:28 +00008653 generate_exception (ctx, EXCP_RI);
bellard6ea83fe2006-06-14 12:56:19 +00008654 return;
8655 }
Blue Swirl2abf3142010-10-13 18:38:08 +00008656 (void)opn; /* avoid a compiler warning */
ths5a1e8ff2007-05-11 17:08:26 +00008657 switch (optype) {
8658 case BINOP:
bellard6ea83fe2006-06-14 12:56:19 +00008659 MIPS_DEBUG("%s %s, %s, %s", opn, fregnames[fd], fregnames[fs], fregnames[ft]);
ths5a1e8ff2007-05-11 17:08:26 +00008660 break;
8661 case CMPOP:
8662 MIPS_DEBUG("%s %s,%s", opn, fregnames[fs], fregnames[ft]);
8663 break;
8664 default:
bellard6ea83fe2006-06-14 12:56:19 +00008665 MIPS_DEBUG("%s %s,%s", opn, fregnames[fd], fregnames[fs]);
ths5a1e8ff2007-05-11 17:08:26 +00008666 break;
8667 }
bellard6ea83fe2006-06-14 12:56:19 +00008668}
bellard6af0bf92005-07-02 14:58:51 +00008669
ths5a5012e2007-05-07 13:55:33 +00008670/* Coprocessor 3 (FPU) */
ths5e755512007-05-29 16:52:57 +00008671static void gen_flt3_ldst (DisasContext *ctx, uint32_t opc,
8672 int fd, int fs, int base, int index)
ths7a387ff2006-12-06 20:17:30 +00008673{
ths923617a2007-05-11 00:16:06 +00008674 const char *opn = "extended float load/store";
ths93b12cc2007-05-20 01:36:29 +00008675 int store = 0;
aurel324e2474d2009-04-08 21:48:10 +00008676 TCGv t0 = tcg_temp_new();
ths7a387ff2006-12-06 20:17:30 +00008677
ths93b12cc2007-05-20 01:36:29 +00008678 if (base == 0) {
ths6c5c1e22008-06-24 15:12:27 +00008679 gen_load_gpr(t0, index);
ths93b12cc2007-05-20 01:36:29 +00008680 } else if (index == 0) {
ths6c5c1e22008-06-24 15:12:27 +00008681 gen_load_gpr(t0, base);
ths93b12cc2007-05-20 01:36:29 +00008682 } else {
Richard Henderson05168672012-03-30 13:16:36 -04008683 gen_op_addr_add(ctx, t0, cpu_gpr[base], cpu_gpr[index]);
ths93b12cc2007-05-20 01:36:29 +00008684 }
ths5a5012e2007-05-07 13:55:33 +00008685 /* Don't do NOP if destination is zero: we must perform the actual
thsead93602007-09-06 00:18:15 +00008686 memory access. */
ths5a5012e2007-05-07 13:55:33 +00008687 switch (opc) {
8688 case OPC_LWXC1:
aurel328c0ab412009-04-17 13:17:26 +00008689 check_cop1x(ctx);
thsb6d96be2008-07-09 11:05:10 +00008690 {
pbrooka7812ae2008-11-17 14:43:54 +00008691 TCGv_i32 fp0 = tcg_temp_new_i32();
thsb6d96be2008-07-09 11:05:10 +00008692
aurel32585c88d2009-04-16 11:51:11 +00008693 tcg_gen_qemu_ld32s(t0, t0, ctx->mem_idx);
8694 tcg_gen_trunc_tl_i32(fp0, t0);
thsb6d96be2008-07-09 11:05:10 +00008695 gen_store_fpr32(fp0, fd);
pbrooka7812ae2008-11-17 14:43:54 +00008696 tcg_temp_free_i32(fp0);
thsb6d96be2008-07-09 11:05:10 +00008697 }
ths5a5012e2007-05-07 13:55:33 +00008698 opn = "lwxc1";
8699 break;
8700 case OPC_LDXC1:
aurel328c0ab412009-04-17 13:17:26 +00008701 check_cop1x(ctx);
8702 check_cp1_registers(ctx, fd);
thsb6d96be2008-07-09 11:05:10 +00008703 {
pbrooka7812ae2008-11-17 14:43:54 +00008704 TCGv_i64 fp0 = tcg_temp_new_i64();
thsb6d96be2008-07-09 11:05:10 +00008705
8706 tcg_gen_qemu_ld64(fp0, t0, ctx->mem_idx);
8707 gen_store_fpr64(ctx, fp0, fd);
pbrooka7812ae2008-11-17 14:43:54 +00008708 tcg_temp_free_i64(fp0);
thsb6d96be2008-07-09 11:05:10 +00008709 }
ths5a5012e2007-05-07 13:55:33 +00008710 opn = "ldxc1";
8711 break;
8712 case OPC_LUXC1:
aurel328c0ab412009-04-17 13:17:26 +00008713 check_cp1_64bitmode(ctx);
ths6c5c1e22008-06-24 15:12:27 +00008714 tcg_gen_andi_tl(t0, t0, ~0x7);
thsb6d96be2008-07-09 11:05:10 +00008715 {
pbrooka7812ae2008-11-17 14:43:54 +00008716 TCGv_i64 fp0 = tcg_temp_new_i64();
thsb6d96be2008-07-09 11:05:10 +00008717
8718 tcg_gen_qemu_ld64(fp0, t0, ctx->mem_idx);
8719 gen_store_fpr64(ctx, fp0, fd);
pbrooka7812ae2008-11-17 14:43:54 +00008720 tcg_temp_free_i64(fp0);
thsb6d96be2008-07-09 11:05:10 +00008721 }
ths5a5012e2007-05-07 13:55:33 +00008722 opn = "luxc1";
8723 break;
8724 case OPC_SWXC1:
aurel328c0ab412009-04-17 13:17:26 +00008725 check_cop1x(ctx);
thsb6d96be2008-07-09 11:05:10 +00008726 {
pbrooka7812ae2008-11-17 14:43:54 +00008727 TCGv_i32 fp0 = tcg_temp_new_i32();
aurel32585c88d2009-04-16 11:51:11 +00008728 TCGv t1 = tcg_temp_new();
thsb6d96be2008-07-09 11:05:10 +00008729
8730 gen_load_fpr32(fp0, fs);
pbrooka7812ae2008-11-17 14:43:54 +00008731 tcg_gen_extu_i32_tl(t1, fp0);
8732 tcg_gen_qemu_st32(t1, t0, ctx->mem_idx);
8733 tcg_temp_free_i32(fp0);
aurel32a6035852009-04-16 12:57:50 +00008734 tcg_temp_free(t1);
thsb6d96be2008-07-09 11:05:10 +00008735 }
ths5a5012e2007-05-07 13:55:33 +00008736 opn = "swxc1";
ths93b12cc2007-05-20 01:36:29 +00008737 store = 1;
ths5a5012e2007-05-07 13:55:33 +00008738 break;
8739 case OPC_SDXC1:
aurel328c0ab412009-04-17 13:17:26 +00008740 check_cop1x(ctx);
8741 check_cp1_registers(ctx, fs);
thsb6d96be2008-07-09 11:05:10 +00008742 {
pbrooka7812ae2008-11-17 14:43:54 +00008743 TCGv_i64 fp0 = tcg_temp_new_i64();
thsb6d96be2008-07-09 11:05:10 +00008744
8745 gen_load_fpr64(ctx, fp0, fs);
8746 tcg_gen_qemu_st64(fp0, t0, ctx->mem_idx);
pbrooka7812ae2008-11-17 14:43:54 +00008747 tcg_temp_free_i64(fp0);
thsb6d96be2008-07-09 11:05:10 +00008748 }
ths5a5012e2007-05-07 13:55:33 +00008749 opn = "sdxc1";
ths93b12cc2007-05-20 01:36:29 +00008750 store = 1;
ths5a5012e2007-05-07 13:55:33 +00008751 break;
8752 case OPC_SUXC1:
aurel328c0ab412009-04-17 13:17:26 +00008753 check_cp1_64bitmode(ctx);
ths6c5c1e22008-06-24 15:12:27 +00008754 tcg_gen_andi_tl(t0, t0, ~0x7);
thsb6d96be2008-07-09 11:05:10 +00008755 {
pbrooka7812ae2008-11-17 14:43:54 +00008756 TCGv_i64 fp0 = tcg_temp_new_i64();
thsb6d96be2008-07-09 11:05:10 +00008757
8758 gen_load_fpr64(ctx, fp0, fs);
8759 tcg_gen_qemu_st64(fp0, t0, ctx->mem_idx);
pbrooka7812ae2008-11-17 14:43:54 +00008760 tcg_temp_free_i64(fp0);
thsb6d96be2008-07-09 11:05:10 +00008761 }
ths5a5012e2007-05-07 13:55:33 +00008762 opn = "suxc1";
ths93b12cc2007-05-20 01:36:29 +00008763 store = 1;
ths5a5012e2007-05-07 13:55:33 +00008764 break;
ths5a5012e2007-05-07 13:55:33 +00008765 }
ths6c5c1e22008-06-24 15:12:27 +00008766 tcg_temp_free(t0);
Blue Swirl2abf3142010-10-13 18:38:08 +00008767 (void)opn; (void)store; /* avoid compiler warnings */
ths93b12cc2007-05-20 01:36:29 +00008768 MIPS_DEBUG("%s %s, %s(%s)", opn, fregnames[store ? fs : fd],
8769 regnames[index], regnames[base]);
ths5a5012e2007-05-07 13:55:33 +00008770}
8771
ths5e755512007-05-29 16:52:57 +00008772static void gen_flt3_arith (DisasContext *ctx, uint32_t opc,
8773 int fd, int fr, int fs, int ft)
ths5a5012e2007-05-07 13:55:33 +00008774{
ths923617a2007-05-11 00:16:06 +00008775 const char *opn = "flt3_arith";
ths5a5012e2007-05-07 13:55:33 +00008776
ths5a5012e2007-05-07 13:55:33 +00008777 switch (opc) {
8778 case OPC_ALNV_PS:
thsb8aa4592007-12-30 15:36:58 +00008779 check_cp1_64bitmode(ctx);
thsa16336e2008-06-19 18:35:02 +00008780 {
pbrooka7812ae2008-11-17 14:43:54 +00008781 TCGv t0 = tcg_temp_local_new();
aurel32c905fda2009-04-08 21:48:18 +00008782 TCGv_i32 fp = tcg_temp_new_i32();
8783 TCGv_i32 fph = tcg_temp_new_i32();
thsa16336e2008-06-19 18:35:02 +00008784 int l1 = gen_new_label();
8785 int l2 = gen_new_label();
8786
ths6c5c1e22008-06-24 15:12:27 +00008787 gen_load_gpr(t0, fr);
8788 tcg_gen_andi_tl(t0, t0, 0x7);
ths6c5c1e22008-06-24 15:12:27 +00008789
8790 tcg_gen_brcondi_tl(TCG_COND_NE, t0, 0, l1);
aurel32c905fda2009-04-08 21:48:18 +00008791 gen_load_fpr32(fp, fs);
8792 gen_load_fpr32h(fph, fs);
8793 gen_store_fpr32(fp, fd);
8794 gen_store_fpr32h(fph, fd);
thsa16336e2008-06-19 18:35:02 +00008795 tcg_gen_br(l2);
8796 gen_set_label(l1);
ths6c5c1e22008-06-24 15:12:27 +00008797 tcg_gen_brcondi_tl(TCG_COND_NE, t0, 4, l2);
8798 tcg_temp_free(t0);
thsa16336e2008-06-19 18:35:02 +00008799#ifdef TARGET_WORDS_BIGENDIAN
aurel32c905fda2009-04-08 21:48:18 +00008800 gen_load_fpr32(fp, fs);
8801 gen_load_fpr32h(fph, ft);
8802 gen_store_fpr32h(fp, fd);
8803 gen_store_fpr32(fph, fd);
thsa16336e2008-06-19 18:35:02 +00008804#else
aurel32c905fda2009-04-08 21:48:18 +00008805 gen_load_fpr32h(fph, fs);
8806 gen_load_fpr32(fp, ft);
8807 gen_store_fpr32(fph, fd);
8808 gen_store_fpr32h(fp, fd);
thsa16336e2008-06-19 18:35:02 +00008809#endif
8810 gen_set_label(l2);
aurel32c905fda2009-04-08 21:48:18 +00008811 tcg_temp_free_i32(fp);
8812 tcg_temp_free_i32(fph);
thsa16336e2008-06-19 18:35:02 +00008813 }
ths5a5012e2007-05-07 13:55:33 +00008814 opn = "alnv.ps";
8815 break;
8816 case OPC_MADD_S:
thsb8aa4592007-12-30 15:36:58 +00008817 check_cop1x(ctx);
thsb6d96be2008-07-09 11:05:10 +00008818 {
pbrooka7812ae2008-11-17 14:43:54 +00008819 TCGv_i32 fp0 = tcg_temp_new_i32();
8820 TCGv_i32 fp1 = tcg_temp_new_i32();
8821 TCGv_i32 fp2 = tcg_temp_new_i32();
thsb6d96be2008-07-09 11:05:10 +00008822
8823 gen_load_fpr32(fp0, fs);
8824 gen_load_fpr32(fp1, ft);
8825 gen_load_fpr32(fp2, fr);
Aurelien Jarnob3d6cd42012-10-09 21:53:20 +02008826 gen_helper_float_madd_s(fp2, cpu_env, fp0, fp1, fp2);
pbrooka7812ae2008-11-17 14:43:54 +00008827 tcg_temp_free_i32(fp0);
8828 tcg_temp_free_i32(fp1);
thsb6d96be2008-07-09 11:05:10 +00008829 gen_store_fpr32(fp2, fd);
pbrooka7812ae2008-11-17 14:43:54 +00008830 tcg_temp_free_i32(fp2);
thsb6d96be2008-07-09 11:05:10 +00008831 }
ths5a5012e2007-05-07 13:55:33 +00008832 opn = "madd.s";
8833 break;
8834 case OPC_MADD_D:
thsb8aa4592007-12-30 15:36:58 +00008835 check_cop1x(ctx);
8836 check_cp1_registers(ctx, fd | fs | ft | fr);
thsb6d96be2008-07-09 11:05:10 +00008837 {
pbrooka7812ae2008-11-17 14:43:54 +00008838 TCGv_i64 fp0 = tcg_temp_new_i64();
8839 TCGv_i64 fp1 = tcg_temp_new_i64();
8840 TCGv_i64 fp2 = tcg_temp_new_i64();
thsb6d96be2008-07-09 11:05:10 +00008841
8842 gen_load_fpr64(ctx, fp0, fs);
8843 gen_load_fpr64(ctx, fp1, ft);
8844 gen_load_fpr64(ctx, fp2, fr);
Aurelien Jarnob3d6cd42012-10-09 21:53:20 +02008845 gen_helper_float_madd_d(fp2, cpu_env, fp0, fp1, fp2);
pbrooka7812ae2008-11-17 14:43:54 +00008846 tcg_temp_free_i64(fp0);
8847 tcg_temp_free_i64(fp1);
thsb6d96be2008-07-09 11:05:10 +00008848 gen_store_fpr64(ctx, fp2, fd);
pbrooka7812ae2008-11-17 14:43:54 +00008849 tcg_temp_free_i64(fp2);
thsb6d96be2008-07-09 11:05:10 +00008850 }
ths5a5012e2007-05-07 13:55:33 +00008851 opn = "madd.d";
8852 break;
8853 case OPC_MADD_PS:
thsb8aa4592007-12-30 15:36:58 +00008854 check_cp1_64bitmode(ctx);
thsb6d96be2008-07-09 11:05:10 +00008855 {
pbrooka7812ae2008-11-17 14:43:54 +00008856 TCGv_i64 fp0 = tcg_temp_new_i64();
8857 TCGv_i64 fp1 = tcg_temp_new_i64();
8858 TCGv_i64 fp2 = tcg_temp_new_i64();
thsb6d96be2008-07-09 11:05:10 +00008859
8860 gen_load_fpr64(ctx, fp0, fs);
8861 gen_load_fpr64(ctx, fp1, ft);
8862 gen_load_fpr64(ctx, fp2, fr);
Aurelien Jarnob3d6cd42012-10-09 21:53:20 +02008863 gen_helper_float_madd_ps(fp2, cpu_env, fp0, fp1, fp2);
pbrooka7812ae2008-11-17 14:43:54 +00008864 tcg_temp_free_i64(fp0);
8865 tcg_temp_free_i64(fp1);
thsb6d96be2008-07-09 11:05:10 +00008866 gen_store_fpr64(ctx, fp2, fd);
pbrooka7812ae2008-11-17 14:43:54 +00008867 tcg_temp_free_i64(fp2);
thsb6d96be2008-07-09 11:05:10 +00008868 }
ths5a5012e2007-05-07 13:55:33 +00008869 opn = "madd.ps";
8870 break;
8871 case OPC_MSUB_S:
thsb8aa4592007-12-30 15:36:58 +00008872 check_cop1x(ctx);
thsb6d96be2008-07-09 11:05:10 +00008873 {
pbrooka7812ae2008-11-17 14:43:54 +00008874 TCGv_i32 fp0 = tcg_temp_new_i32();
8875 TCGv_i32 fp1 = tcg_temp_new_i32();
8876 TCGv_i32 fp2 = tcg_temp_new_i32();
thsb6d96be2008-07-09 11:05:10 +00008877
8878 gen_load_fpr32(fp0, fs);
8879 gen_load_fpr32(fp1, ft);
8880 gen_load_fpr32(fp2, fr);
Aurelien Jarnob3d6cd42012-10-09 21:53:20 +02008881 gen_helper_float_msub_s(fp2, cpu_env, fp0, fp1, fp2);
pbrooka7812ae2008-11-17 14:43:54 +00008882 tcg_temp_free_i32(fp0);
8883 tcg_temp_free_i32(fp1);
thsb6d96be2008-07-09 11:05:10 +00008884 gen_store_fpr32(fp2, fd);
pbrooka7812ae2008-11-17 14:43:54 +00008885 tcg_temp_free_i32(fp2);
thsb6d96be2008-07-09 11:05:10 +00008886 }
ths5a5012e2007-05-07 13:55:33 +00008887 opn = "msub.s";
8888 break;
8889 case OPC_MSUB_D:
thsb8aa4592007-12-30 15:36:58 +00008890 check_cop1x(ctx);
8891 check_cp1_registers(ctx, fd | fs | ft | fr);
thsb6d96be2008-07-09 11:05:10 +00008892 {
pbrooka7812ae2008-11-17 14:43:54 +00008893 TCGv_i64 fp0 = tcg_temp_new_i64();
8894 TCGv_i64 fp1 = tcg_temp_new_i64();
8895 TCGv_i64 fp2 = tcg_temp_new_i64();
thsb6d96be2008-07-09 11:05:10 +00008896
8897 gen_load_fpr64(ctx, fp0, fs);
8898 gen_load_fpr64(ctx, fp1, ft);
8899 gen_load_fpr64(ctx, fp2, fr);
Aurelien Jarnob3d6cd42012-10-09 21:53:20 +02008900 gen_helper_float_msub_d(fp2, cpu_env, fp0, fp1, fp2);
pbrooka7812ae2008-11-17 14:43:54 +00008901 tcg_temp_free_i64(fp0);
8902 tcg_temp_free_i64(fp1);
thsb6d96be2008-07-09 11:05:10 +00008903 gen_store_fpr64(ctx, fp2, fd);
pbrooka7812ae2008-11-17 14:43:54 +00008904 tcg_temp_free_i64(fp2);
thsb6d96be2008-07-09 11:05:10 +00008905 }
ths5a5012e2007-05-07 13:55:33 +00008906 opn = "msub.d";
8907 break;
8908 case OPC_MSUB_PS:
thsb8aa4592007-12-30 15:36:58 +00008909 check_cp1_64bitmode(ctx);
thsb6d96be2008-07-09 11:05:10 +00008910 {
pbrooka7812ae2008-11-17 14:43:54 +00008911 TCGv_i64 fp0 = tcg_temp_new_i64();
8912 TCGv_i64 fp1 = tcg_temp_new_i64();
8913 TCGv_i64 fp2 = tcg_temp_new_i64();
thsb6d96be2008-07-09 11:05:10 +00008914
8915 gen_load_fpr64(ctx, fp0, fs);
8916 gen_load_fpr64(ctx, fp1, ft);
8917 gen_load_fpr64(ctx, fp2, fr);
Aurelien Jarnob3d6cd42012-10-09 21:53:20 +02008918 gen_helper_float_msub_ps(fp2, cpu_env, fp0, fp1, fp2);
pbrooka7812ae2008-11-17 14:43:54 +00008919 tcg_temp_free_i64(fp0);
8920 tcg_temp_free_i64(fp1);
thsb6d96be2008-07-09 11:05:10 +00008921 gen_store_fpr64(ctx, fp2, fd);
pbrooka7812ae2008-11-17 14:43:54 +00008922 tcg_temp_free_i64(fp2);
thsb6d96be2008-07-09 11:05:10 +00008923 }
ths5a5012e2007-05-07 13:55:33 +00008924 opn = "msub.ps";
8925 break;
8926 case OPC_NMADD_S:
thsb8aa4592007-12-30 15:36:58 +00008927 check_cop1x(ctx);
thsb6d96be2008-07-09 11:05:10 +00008928 {
pbrooka7812ae2008-11-17 14:43:54 +00008929 TCGv_i32 fp0 = tcg_temp_new_i32();
8930 TCGv_i32 fp1 = tcg_temp_new_i32();
8931 TCGv_i32 fp2 = tcg_temp_new_i32();
thsb6d96be2008-07-09 11:05:10 +00008932
8933 gen_load_fpr32(fp0, fs);
8934 gen_load_fpr32(fp1, ft);
8935 gen_load_fpr32(fp2, fr);
Aurelien Jarnob3d6cd42012-10-09 21:53:20 +02008936 gen_helper_float_nmadd_s(fp2, cpu_env, fp0, fp1, fp2);
pbrooka7812ae2008-11-17 14:43:54 +00008937 tcg_temp_free_i32(fp0);
8938 tcg_temp_free_i32(fp1);
thsb6d96be2008-07-09 11:05:10 +00008939 gen_store_fpr32(fp2, fd);
pbrooka7812ae2008-11-17 14:43:54 +00008940 tcg_temp_free_i32(fp2);
thsb6d96be2008-07-09 11:05:10 +00008941 }
ths5a5012e2007-05-07 13:55:33 +00008942 opn = "nmadd.s";
8943 break;
8944 case OPC_NMADD_D:
thsb8aa4592007-12-30 15:36:58 +00008945 check_cop1x(ctx);
8946 check_cp1_registers(ctx, fd | fs | ft | fr);
thsb6d96be2008-07-09 11:05:10 +00008947 {
pbrooka7812ae2008-11-17 14:43:54 +00008948 TCGv_i64 fp0 = tcg_temp_new_i64();
8949 TCGv_i64 fp1 = tcg_temp_new_i64();
8950 TCGv_i64 fp2 = tcg_temp_new_i64();
thsb6d96be2008-07-09 11:05:10 +00008951
8952 gen_load_fpr64(ctx, fp0, fs);
8953 gen_load_fpr64(ctx, fp1, ft);
8954 gen_load_fpr64(ctx, fp2, fr);
Aurelien Jarnob3d6cd42012-10-09 21:53:20 +02008955 gen_helper_float_nmadd_d(fp2, cpu_env, fp0, fp1, fp2);
pbrooka7812ae2008-11-17 14:43:54 +00008956 tcg_temp_free_i64(fp0);
8957 tcg_temp_free_i64(fp1);
thsb6d96be2008-07-09 11:05:10 +00008958 gen_store_fpr64(ctx, fp2, fd);
pbrooka7812ae2008-11-17 14:43:54 +00008959 tcg_temp_free_i64(fp2);
thsb6d96be2008-07-09 11:05:10 +00008960 }
ths5a5012e2007-05-07 13:55:33 +00008961 opn = "nmadd.d";
8962 break;
8963 case OPC_NMADD_PS:
thsb8aa4592007-12-30 15:36:58 +00008964 check_cp1_64bitmode(ctx);
thsb6d96be2008-07-09 11:05:10 +00008965 {
pbrooka7812ae2008-11-17 14:43:54 +00008966 TCGv_i64 fp0 = tcg_temp_new_i64();
8967 TCGv_i64 fp1 = tcg_temp_new_i64();
8968 TCGv_i64 fp2 = tcg_temp_new_i64();
thsb6d96be2008-07-09 11:05:10 +00008969
8970 gen_load_fpr64(ctx, fp0, fs);
8971 gen_load_fpr64(ctx, fp1, ft);
8972 gen_load_fpr64(ctx, fp2, fr);
Aurelien Jarnob3d6cd42012-10-09 21:53:20 +02008973 gen_helper_float_nmadd_ps(fp2, cpu_env, fp0, fp1, fp2);
pbrooka7812ae2008-11-17 14:43:54 +00008974 tcg_temp_free_i64(fp0);
8975 tcg_temp_free_i64(fp1);
thsb6d96be2008-07-09 11:05:10 +00008976 gen_store_fpr64(ctx, fp2, fd);
pbrooka7812ae2008-11-17 14:43:54 +00008977 tcg_temp_free_i64(fp2);
thsb6d96be2008-07-09 11:05:10 +00008978 }
ths5a5012e2007-05-07 13:55:33 +00008979 opn = "nmadd.ps";
8980 break;
8981 case OPC_NMSUB_S:
thsb8aa4592007-12-30 15:36:58 +00008982 check_cop1x(ctx);
thsb6d96be2008-07-09 11:05:10 +00008983 {
pbrooka7812ae2008-11-17 14:43:54 +00008984 TCGv_i32 fp0 = tcg_temp_new_i32();
8985 TCGv_i32 fp1 = tcg_temp_new_i32();
8986 TCGv_i32 fp2 = tcg_temp_new_i32();
thsb6d96be2008-07-09 11:05:10 +00008987
8988 gen_load_fpr32(fp0, fs);
8989 gen_load_fpr32(fp1, ft);
8990 gen_load_fpr32(fp2, fr);
Aurelien Jarnob3d6cd42012-10-09 21:53:20 +02008991 gen_helper_float_nmsub_s(fp2, cpu_env, fp0, fp1, fp2);
pbrooka7812ae2008-11-17 14:43:54 +00008992 tcg_temp_free_i32(fp0);
8993 tcg_temp_free_i32(fp1);
thsb6d96be2008-07-09 11:05:10 +00008994 gen_store_fpr32(fp2, fd);
pbrooka7812ae2008-11-17 14:43:54 +00008995 tcg_temp_free_i32(fp2);
thsb6d96be2008-07-09 11:05:10 +00008996 }
ths5a5012e2007-05-07 13:55:33 +00008997 opn = "nmsub.s";
8998 break;
8999 case OPC_NMSUB_D:
thsb8aa4592007-12-30 15:36:58 +00009000 check_cop1x(ctx);
9001 check_cp1_registers(ctx, fd | fs | ft | fr);
thsb6d96be2008-07-09 11:05:10 +00009002 {
pbrooka7812ae2008-11-17 14:43:54 +00009003 TCGv_i64 fp0 = tcg_temp_new_i64();
9004 TCGv_i64 fp1 = tcg_temp_new_i64();
9005 TCGv_i64 fp2 = tcg_temp_new_i64();
thsb6d96be2008-07-09 11:05:10 +00009006
9007 gen_load_fpr64(ctx, fp0, fs);
9008 gen_load_fpr64(ctx, fp1, ft);
9009 gen_load_fpr64(ctx, fp2, fr);
Aurelien Jarnob3d6cd42012-10-09 21:53:20 +02009010 gen_helper_float_nmsub_d(fp2, cpu_env, fp0, fp1, fp2);
pbrooka7812ae2008-11-17 14:43:54 +00009011 tcg_temp_free_i64(fp0);
9012 tcg_temp_free_i64(fp1);
thsb6d96be2008-07-09 11:05:10 +00009013 gen_store_fpr64(ctx, fp2, fd);
pbrooka7812ae2008-11-17 14:43:54 +00009014 tcg_temp_free_i64(fp2);
thsb6d96be2008-07-09 11:05:10 +00009015 }
ths5a5012e2007-05-07 13:55:33 +00009016 opn = "nmsub.d";
9017 break;
9018 case OPC_NMSUB_PS:
thsb8aa4592007-12-30 15:36:58 +00009019 check_cp1_64bitmode(ctx);
thsb6d96be2008-07-09 11:05:10 +00009020 {
pbrooka7812ae2008-11-17 14:43:54 +00009021 TCGv_i64 fp0 = tcg_temp_new_i64();
9022 TCGv_i64 fp1 = tcg_temp_new_i64();
9023 TCGv_i64 fp2 = tcg_temp_new_i64();
thsb6d96be2008-07-09 11:05:10 +00009024
9025 gen_load_fpr64(ctx, fp0, fs);
9026 gen_load_fpr64(ctx, fp1, ft);
9027 gen_load_fpr64(ctx, fp2, fr);
Aurelien Jarnob3d6cd42012-10-09 21:53:20 +02009028 gen_helper_float_nmsub_ps(fp2, cpu_env, fp0, fp1, fp2);
pbrooka7812ae2008-11-17 14:43:54 +00009029 tcg_temp_free_i64(fp0);
9030 tcg_temp_free_i64(fp1);
thsb6d96be2008-07-09 11:05:10 +00009031 gen_store_fpr64(ctx, fp2, fd);
pbrooka7812ae2008-11-17 14:43:54 +00009032 tcg_temp_free_i64(fp2);
thsb6d96be2008-07-09 11:05:10 +00009033 }
ths5a5012e2007-05-07 13:55:33 +00009034 opn = "nmsub.ps";
9035 break;
ths923617a2007-05-11 00:16:06 +00009036 default:
9037 MIPS_INVAL(opn);
ths5a5012e2007-05-07 13:55:33 +00009038 generate_exception (ctx, EXCP_RI);
9039 return;
9040 }
Blue Swirl2abf3142010-10-13 18:38:08 +00009041 (void)opn; /* avoid a compiler warning */
ths5a5012e2007-05-07 13:55:33 +00009042 MIPS_DEBUG("%s %s, %s, %s, %s", opn, fregnames[fd], fregnames[fr],
9043 fregnames[fs], fregnames[ft]);
ths7a387ff2006-12-06 20:17:30 +00009044}
9045
Aurelien Jarnod75c1352013-01-01 18:02:22 +01009046static void gen_rdhwr(DisasContext *ctx, int rt, int rd)
Nathan Froyd26ebe462010-05-24 09:19:35 -07009047{
9048 TCGv t0;
9049
Richard Hendersonb3167282012-03-30 13:16:37 -04009050#if !defined(CONFIG_USER_ONLY)
9051 /* The Linux kernel will emulate rdhwr if it's not supported natively.
9052 Therefore only check the ISA in system mode. */
Aurelien Jarnod75c1352013-01-01 18:02:22 +01009053 check_insn(ctx, ISA_MIPS32R2);
Richard Hendersonb3167282012-03-30 13:16:37 -04009054#endif
Nathan Froyd26ebe462010-05-24 09:19:35 -07009055 t0 = tcg_temp_new();
9056
9057 switch (rd) {
9058 case 0:
9059 save_cpu_state(ctx, 1);
Blue Swirl895c2d02012-09-02 14:52:59 +00009060 gen_helper_rdhwr_cpunum(t0, cpu_env);
Nathan Froyd26ebe462010-05-24 09:19:35 -07009061 gen_store_gpr(t0, rt);
9062 break;
9063 case 1:
9064 save_cpu_state(ctx, 1);
Blue Swirl895c2d02012-09-02 14:52:59 +00009065 gen_helper_rdhwr_synci_step(t0, cpu_env);
Nathan Froyd26ebe462010-05-24 09:19:35 -07009066 gen_store_gpr(t0, rt);
9067 break;
9068 case 2:
9069 save_cpu_state(ctx, 1);
Blue Swirl895c2d02012-09-02 14:52:59 +00009070 gen_helper_rdhwr_cc(t0, cpu_env);
Nathan Froyd26ebe462010-05-24 09:19:35 -07009071 gen_store_gpr(t0, rt);
9072 break;
9073 case 3:
9074 save_cpu_state(ctx, 1);
Blue Swirl895c2d02012-09-02 14:52:59 +00009075 gen_helper_rdhwr_ccres(t0, cpu_env);
Nathan Froyd26ebe462010-05-24 09:19:35 -07009076 gen_store_gpr(t0, rt);
9077 break;
9078 case 29:
9079#if defined(CONFIG_USER_ONLY)
Andreas Färber7db13fa2012-03-14 01:38:22 +01009080 tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUMIPSState, tls_value));
Nathan Froyd26ebe462010-05-24 09:19:35 -07009081 gen_store_gpr(t0, rt);
9082 break;
9083#else
9084 /* XXX: Some CPUs implement this in hardware.
9085 Not supported yet. */
9086#endif
9087 default: /* Invalid */
9088 MIPS_INVAL("rdhwr");
9089 generate_exception(ctx, EXCP_RI);
9090 break;
9091 }
9092 tcg_temp_free(t0);
9093}
9094
Aurelien Jarnod75c1352013-01-01 18:02:22 +01009095static void handle_delay_slot(DisasContext *ctx, int insn_bytes)
Nathan Froydc9602062009-12-08 08:06:27 -08009096{
9097 if (ctx->hflags & MIPS_HFLAG_BMASK) {
Nathan Froyd364d4832009-12-08 08:06:29 -08009098 int proc_hflags = ctx->hflags & MIPS_HFLAG_BMASK;
Nathan Froydc9602062009-12-08 08:06:27 -08009099 /* Branches completion */
9100 ctx->hflags &= ~MIPS_HFLAG_BMASK;
9101 ctx->bstate = BS_BRANCH;
9102 save_cpu_state(ctx, 0);
9103 /* FIXME: Need to clear can_do_io. */
Nathan Froyd364d4832009-12-08 08:06:29 -08009104 switch (proc_hflags & MIPS_HFLAG_BMASK_BASE) {
Nathan Froydc9602062009-12-08 08:06:27 -08009105 case MIPS_HFLAG_B:
9106 /* unconditional branch */
9107 MIPS_DEBUG("unconditional branch");
Nathan Froyd364d4832009-12-08 08:06:29 -08009108 if (proc_hflags & MIPS_HFLAG_BX) {
9109 tcg_gen_xori_i32(hflags, hflags, MIPS_HFLAG_M16);
9110 }
Nathan Froydc9602062009-12-08 08:06:27 -08009111 gen_goto_tb(ctx, 0, ctx->btarget);
9112 break;
9113 case MIPS_HFLAG_BL:
9114 /* blikely taken case */
9115 MIPS_DEBUG("blikely branch taken");
9116 gen_goto_tb(ctx, 0, ctx->btarget);
9117 break;
9118 case MIPS_HFLAG_BC:
9119 /* Conditional branch */
9120 MIPS_DEBUG("conditional branch");
9121 {
9122 int l1 = gen_new_label();
9123
9124 tcg_gen_brcondi_tl(TCG_COND_NE, bcond, 0, l1);
9125 gen_goto_tb(ctx, 1, ctx->pc + insn_bytes);
9126 gen_set_label(l1);
9127 gen_goto_tb(ctx, 0, ctx->btarget);
9128 }
9129 break;
9130 case MIPS_HFLAG_BR:
9131 /* unconditional branch to register */
9132 MIPS_DEBUG("branch to register");
Aurelien Jarnod75c1352013-01-01 18:02:22 +01009133 if (ctx->insn_flags & (ASE_MIPS16 | ASE_MICROMIPS)) {
Nathan Froyd364d4832009-12-08 08:06:29 -08009134 TCGv t0 = tcg_temp_new();
9135 TCGv_i32 t1 = tcg_temp_new_i32();
9136
9137 tcg_gen_andi_tl(t0, btarget, 0x1);
9138 tcg_gen_trunc_tl_i32(t1, t0);
9139 tcg_temp_free(t0);
9140 tcg_gen_andi_i32(hflags, hflags, ~(uint32_t)MIPS_HFLAG_M16);
9141 tcg_gen_shli_i32(t1, t1, MIPS_HFLAG_M16_SHIFT);
9142 tcg_gen_or_i32(hflags, hflags, t1);
9143 tcg_temp_free_i32(t1);
9144
9145 tcg_gen_andi_tl(cpu_PC, btarget, ~(target_ulong)0x1);
9146 } else {
9147 tcg_gen_mov_tl(cpu_PC, btarget);
9148 }
Nathan Froydc9602062009-12-08 08:06:27 -08009149 if (ctx->singlestep_enabled) {
9150 save_cpu_state(ctx, 0);
Blue Swirl895c2d02012-09-02 14:52:59 +00009151 gen_helper_0e0i(raise_exception, EXCP_DEBUG);
Nathan Froydc9602062009-12-08 08:06:27 -08009152 }
9153 tcg_gen_exit_tb(0);
9154 break;
9155 default:
9156 MIPS_DEBUG("unknown branch");
9157 break;
9158 }
9159 }
9160}
9161
ths7a387ff2006-12-06 20:17:30 +00009162/* ISA extensions (ASEs) */
bellard6af0bf92005-07-02 14:58:51 +00009163/* MIPS16 extension to MIPS32 */
Nathan Froyd6ea219d2009-12-08 08:06:28 -08009164
9165/* MIPS16 major opcodes */
9166enum {
9167 M16_OPC_ADDIUSP = 0x00,
9168 M16_OPC_ADDIUPC = 0x01,
9169 M16_OPC_B = 0x02,
9170 M16_OPC_JAL = 0x03,
9171 M16_OPC_BEQZ = 0x04,
9172 M16_OPC_BNEQZ = 0x05,
9173 M16_OPC_SHIFT = 0x06,
9174 M16_OPC_LD = 0x07,
9175 M16_OPC_RRIA = 0x08,
9176 M16_OPC_ADDIU8 = 0x09,
9177 M16_OPC_SLTI = 0x0a,
9178 M16_OPC_SLTIU = 0x0b,
9179 M16_OPC_I8 = 0x0c,
9180 M16_OPC_LI = 0x0d,
9181 M16_OPC_CMPI = 0x0e,
9182 M16_OPC_SD = 0x0f,
9183 M16_OPC_LB = 0x10,
9184 M16_OPC_LH = 0x11,
9185 M16_OPC_LWSP = 0x12,
9186 M16_OPC_LW = 0x13,
9187 M16_OPC_LBU = 0x14,
9188 M16_OPC_LHU = 0x15,
9189 M16_OPC_LWPC = 0x16,
9190 M16_OPC_LWU = 0x17,
9191 M16_OPC_SB = 0x18,
9192 M16_OPC_SH = 0x19,
9193 M16_OPC_SWSP = 0x1a,
9194 M16_OPC_SW = 0x1b,
9195 M16_OPC_RRR = 0x1c,
9196 M16_OPC_RR = 0x1d,
9197 M16_OPC_EXTEND = 0x1e,
9198 M16_OPC_I64 = 0x1f
9199};
9200
9201/* I8 funct field */
9202enum {
9203 I8_BTEQZ = 0x0,
9204 I8_BTNEZ = 0x1,
9205 I8_SWRASP = 0x2,
9206 I8_ADJSP = 0x3,
9207 I8_SVRS = 0x4,
9208 I8_MOV32R = 0x5,
9209 I8_MOVR32 = 0x7
9210};
9211
9212/* RRR f field */
9213enum {
9214 RRR_DADDU = 0x0,
9215 RRR_ADDU = 0x1,
9216 RRR_DSUBU = 0x2,
9217 RRR_SUBU = 0x3
9218};
9219
9220/* RR funct field */
9221enum {
9222 RR_JR = 0x00,
9223 RR_SDBBP = 0x01,
9224 RR_SLT = 0x02,
9225 RR_SLTU = 0x03,
9226 RR_SLLV = 0x04,
9227 RR_BREAK = 0x05,
9228 RR_SRLV = 0x06,
9229 RR_SRAV = 0x07,
9230 RR_DSRL = 0x08,
9231 RR_CMP = 0x0a,
9232 RR_NEG = 0x0b,
9233 RR_AND = 0x0c,
9234 RR_OR = 0x0d,
9235 RR_XOR = 0x0e,
9236 RR_NOT = 0x0f,
9237 RR_MFHI = 0x10,
9238 RR_CNVT = 0x11,
9239 RR_MFLO = 0x12,
9240 RR_DSRA = 0x13,
9241 RR_DSLLV = 0x14,
9242 RR_DSRLV = 0x16,
9243 RR_DSRAV = 0x17,
9244 RR_MULT = 0x18,
9245 RR_MULTU = 0x19,
9246 RR_DIV = 0x1a,
9247 RR_DIVU = 0x1b,
9248 RR_DMULT = 0x1c,
9249 RR_DMULTU = 0x1d,
9250 RR_DDIV = 0x1e,
9251 RR_DDIVU = 0x1f
9252};
9253
9254/* I64 funct field */
9255enum {
9256 I64_LDSP = 0x0,
9257 I64_SDSP = 0x1,
9258 I64_SDRASP = 0x2,
9259 I64_DADJSP = 0x3,
9260 I64_LDPC = 0x4,
Nathan Froyd364d4832009-12-08 08:06:29 -08009261 I64_DADDIU5 = 0x5,
Nathan Froyd6ea219d2009-12-08 08:06:28 -08009262 I64_DADDIUPC = 0x6,
9263 I64_DADDIUSP = 0x7
9264};
9265
9266/* RR ry field for CNVT */
9267enum {
9268 RR_RY_CNVT_ZEB = 0x0,
9269 RR_RY_CNVT_ZEH = 0x1,
9270 RR_RY_CNVT_ZEW = 0x2,
9271 RR_RY_CNVT_SEB = 0x4,
9272 RR_RY_CNVT_SEH = 0x5,
9273 RR_RY_CNVT_SEW = 0x6,
9274};
9275
Nathan Froyd364d4832009-12-08 08:06:29 -08009276static int xlat (int r)
9277{
9278 static int map[] = { 16, 17, 2, 3, 4, 5, 6, 7 };
9279
9280 return map[r];
9281}
9282
9283static void gen_mips16_save (DisasContext *ctx,
9284 int xsregs, int aregs,
9285 int do_ra, int do_s0, int do_s1,
9286 int framesize)
9287{
9288 TCGv t0 = tcg_temp_new();
9289 TCGv t1 = tcg_temp_new();
9290 int args, astatic;
9291
9292 switch (aregs) {
9293 case 0:
9294 case 1:
9295 case 2:
9296 case 3:
9297 case 11:
9298 args = 0;
9299 break;
9300 case 4:
9301 case 5:
9302 case 6:
9303 case 7:
9304 args = 1;
9305 break;
9306 case 8:
9307 case 9:
9308 case 10:
9309 args = 2;
9310 break;
9311 case 12:
9312 case 13:
9313 args = 3;
9314 break;
9315 case 14:
9316 args = 4;
9317 break;
9318 default:
9319 generate_exception(ctx, EXCP_RI);
9320 return;
9321 }
9322
9323 switch (args) {
9324 case 4:
9325 gen_base_offset_addr(ctx, t0, 29, 12);
9326 gen_load_gpr(t1, 7);
Aurelien Jarno2910c6cb2012-10-09 21:53:20 +02009327 tcg_gen_qemu_st32(t1, t0, ctx->mem_idx);
Nathan Froyd364d4832009-12-08 08:06:29 -08009328 /* Fall through */
9329 case 3:
9330 gen_base_offset_addr(ctx, t0, 29, 8);
9331 gen_load_gpr(t1, 6);
Aurelien Jarno2910c6cb2012-10-09 21:53:20 +02009332 tcg_gen_qemu_st32(t1, t0, ctx->mem_idx);
Nathan Froyd364d4832009-12-08 08:06:29 -08009333 /* Fall through */
9334 case 2:
9335 gen_base_offset_addr(ctx, t0, 29, 4);
9336 gen_load_gpr(t1, 5);
Aurelien Jarno2910c6cb2012-10-09 21:53:20 +02009337 tcg_gen_qemu_st32(t1, t0, ctx->mem_idx);
Nathan Froyd364d4832009-12-08 08:06:29 -08009338 /* Fall through */
9339 case 1:
9340 gen_base_offset_addr(ctx, t0, 29, 0);
9341 gen_load_gpr(t1, 4);
Aurelien Jarno2910c6cb2012-10-09 21:53:20 +02009342 tcg_gen_qemu_st32(t1, t0, ctx->mem_idx);
Nathan Froyd364d4832009-12-08 08:06:29 -08009343 }
9344
9345 gen_load_gpr(t0, 29);
9346
9347#define DECR_AND_STORE(reg) do { \
9348 tcg_gen_subi_tl(t0, t0, 4); \
9349 gen_load_gpr(t1, reg); \
Aurelien Jarno2910c6cb2012-10-09 21:53:20 +02009350 tcg_gen_qemu_st32(t1, t0, ctx->mem_idx); \
Nathan Froyd364d4832009-12-08 08:06:29 -08009351 } while (0)
9352
9353 if (do_ra) {
9354 DECR_AND_STORE(31);
9355 }
9356
9357 switch (xsregs) {
9358 case 7:
9359 DECR_AND_STORE(30);
9360 /* Fall through */
9361 case 6:
9362 DECR_AND_STORE(23);
9363 /* Fall through */
9364 case 5:
9365 DECR_AND_STORE(22);
9366 /* Fall through */
9367 case 4:
9368 DECR_AND_STORE(21);
9369 /* Fall through */
9370 case 3:
9371 DECR_AND_STORE(20);
9372 /* Fall through */
9373 case 2:
9374 DECR_AND_STORE(19);
9375 /* Fall through */
9376 case 1:
9377 DECR_AND_STORE(18);
9378 }
9379
9380 if (do_s1) {
9381 DECR_AND_STORE(17);
9382 }
9383 if (do_s0) {
9384 DECR_AND_STORE(16);
9385 }
9386
9387 switch (aregs) {
9388 case 0:
9389 case 4:
9390 case 8:
9391 case 12:
9392 case 14:
9393 astatic = 0;
9394 break;
9395 case 1:
9396 case 5:
9397 case 9:
9398 case 13:
9399 astatic = 1;
9400 break;
9401 case 2:
9402 case 6:
9403 case 10:
9404 astatic = 2;
9405 break;
9406 case 3:
9407 case 7:
9408 astatic = 3;
9409 break;
9410 case 11:
9411 astatic = 4;
9412 break;
9413 default:
9414 generate_exception(ctx, EXCP_RI);
9415 return;
9416 }
9417
9418 if (astatic > 0) {
9419 DECR_AND_STORE(7);
9420 if (astatic > 1) {
9421 DECR_AND_STORE(6);
9422 if (astatic > 2) {
9423 DECR_AND_STORE(5);
9424 if (astatic > 3) {
9425 DECR_AND_STORE(4);
9426 }
9427 }
9428 }
9429 }
9430#undef DECR_AND_STORE
9431
9432 tcg_gen_subi_tl(cpu_gpr[29], cpu_gpr[29], framesize);
9433 tcg_temp_free(t0);
9434 tcg_temp_free(t1);
9435}
9436
9437static void gen_mips16_restore (DisasContext *ctx,
9438 int xsregs, int aregs,
9439 int do_ra, int do_s0, int do_s1,
9440 int framesize)
9441{
9442 int astatic;
9443 TCGv t0 = tcg_temp_new();
9444 TCGv t1 = tcg_temp_new();
9445
9446 tcg_gen_addi_tl(t0, cpu_gpr[29], framesize);
9447
Aurelien Jarno2910c6cb2012-10-09 21:53:20 +02009448#define DECR_AND_LOAD(reg) do { \
9449 tcg_gen_subi_tl(t0, t0, 4); \
Richard Sandiford17e8fef2013-01-20 19:28:48 +00009450 tcg_gen_qemu_ld32s(t1, t0, ctx->mem_idx); \
Aurelien Jarno2910c6cb2012-10-09 21:53:20 +02009451 gen_store_gpr(t1, reg); \
Nathan Froyd364d4832009-12-08 08:06:29 -08009452 } while (0)
9453
9454 if (do_ra) {
9455 DECR_AND_LOAD(31);
9456 }
9457
9458 switch (xsregs) {
9459 case 7:
9460 DECR_AND_LOAD(30);
9461 /* Fall through */
9462 case 6:
9463 DECR_AND_LOAD(23);
9464 /* Fall through */
9465 case 5:
9466 DECR_AND_LOAD(22);
9467 /* Fall through */
9468 case 4:
9469 DECR_AND_LOAD(21);
9470 /* Fall through */
9471 case 3:
9472 DECR_AND_LOAD(20);
9473 /* Fall through */
9474 case 2:
9475 DECR_AND_LOAD(19);
9476 /* Fall through */
9477 case 1:
9478 DECR_AND_LOAD(18);
9479 }
9480
9481 if (do_s1) {
9482 DECR_AND_LOAD(17);
9483 }
9484 if (do_s0) {
9485 DECR_AND_LOAD(16);
9486 }
9487
9488 switch (aregs) {
9489 case 0:
9490 case 4:
9491 case 8:
9492 case 12:
9493 case 14:
9494 astatic = 0;
9495 break;
9496 case 1:
9497 case 5:
9498 case 9:
9499 case 13:
9500 astatic = 1;
9501 break;
9502 case 2:
9503 case 6:
9504 case 10:
9505 astatic = 2;
9506 break;
9507 case 3:
9508 case 7:
9509 astatic = 3;
9510 break;
9511 case 11:
9512 astatic = 4;
9513 break;
9514 default:
9515 generate_exception(ctx, EXCP_RI);
9516 return;
9517 }
9518
9519 if (astatic > 0) {
9520 DECR_AND_LOAD(7);
9521 if (astatic > 1) {
9522 DECR_AND_LOAD(6);
9523 if (astatic > 2) {
9524 DECR_AND_LOAD(5);
9525 if (astatic > 3) {
9526 DECR_AND_LOAD(4);
9527 }
9528 }
9529 }
9530 }
9531#undef DECR_AND_LOAD
9532
9533 tcg_gen_addi_tl(cpu_gpr[29], cpu_gpr[29], framesize);
9534 tcg_temp_free(t0);
9535 tcg_temp_free(t1);
9536}
9537
9538static void gen_addiupc (DisasContext *ctx, int rx, int imm,
9539 int is_64_bit, int extended)
9540{
9541 TCGv t0;
9542
9543 if (extended && (ctx->hflags & MIPS_HFLAG_BMASK)) {
9544 generate_exception(ctx, EXCP_RI);
9545 return;
9546 }
9547
9548 t0 = tcg_temp_new();
9549
9550 tcg_gen_movi_tl(t0, pc_relative_pc(ctx));
9551 tcg_gen_addi_tl(cpu_gpr[rx], t0, imm);
9552 if (!is_64_bit) {
9553 tcg_gen_ext32s_tl(cpu_gpr[rx], cpu_gpr[rx]);
9554 }
9555
9556 tcg_temp_free(t0);
9557}
9558
9559#if defined(TARGET_MIPS64)
Aurelien Jarnod75c1352013-01-01 18:02:22 +01009560static void decode_i64_mips16 (DisasContext *ctx,
Nathan Froyd364d4832009-12-08 08:06:29 -08009561 int ry, int funct, int16_t offset,
9562 int extended)
9563{
9564 switch (funct) {
9565 case I64_LDSP:
9566 check_mips_64(ctx);
9567 offset = extended ? offset : offset << 3;
Aurelien Jarnod75c1352013-01-01 18:02:22 +01009568 gen_ld(ctx, OPC_LD, ry, 29, offset);
Nathan Froyd364d4832009-12-08 08:06:29 -08009569 break;
9570 case I64_SDSP:
9571 check_mips_64(ctx);
9572 offset = extended ? offset : offset << 3;
Aurelien Jarno5c13fdf2010-07-01 07:47:00 +02009573 gen_st(ctx, OPC_SD, ry, 29, offset);
Nathan Froyd364d4832009-12-08 08:06:29 -08009574 break;
9575 case I64_SDRASP:
9576 check_mips_64(ctx);
9577 offset = extended ? offset : (ctx->opcode & 0xff) << 3;
Aurelien Jarno5c13fdf2010-07-01 07:47:00 +02009578 gen_st(ctx, OPC_SD, 31, 29, offset);
Nathan Froyd364d4832009-12-08 08:06:29 -08009579 break;
9580 case I64_DADJSP:
9581 check_mips_64(ctx);
9582 offset = extended ? offset : ((int8_t)ctx->opcode) << 3;
Aurelien Jarnod75c1352013-01-01 18:02:22 +01009583 gen_arith_imm(ctx, OPC_DADDIU, 29, 29, offset);
Nathan Froyd364d4832009-12-08 08:06:29 -08009584 break;
9585 case I64_LDPC:
9586 if (extended && (ctx->hflags & MIPS_HFLAG_BMASK)) {
9587 generate_exception(ctx, EXCP_RI);
9588 } else {
9589 offset = extended ? offset : offset << 3;
Aurelien Jarnod75c1352013-01-01 18:02:22 +01009590 gen_ld(ctx, OPC_LDPC, ry, 0, offset);
Nathan Froyd364d4832009-12-08 08:06:29 -08009591 }
9592 break;
9593 case I64_DADDIU5:
9594 check_mips_64(ctx);
9595 offset = extended ? offset : ((int8_t)(offset << 3)) >> 3;
Aurelien Jarnod75c1352013-01-01 18:02:22 +01009596 gen_arith_imm(ctx, OPC_DADDIU, ry, ry, offset);
Nathan Froyd364d4832009-12-08 08:06:29 -08009597 break;
9598 case I64_DADDIUPC:
9599 check_mips_64(ctx);
9600 offset = extended ? offset : offset << 2;
9601 gen_addiupc(ctx, ry, offset, 1, extended);
9602 break;
9603 case I64_DADDIUSP:
9604 check_mips_64(ctx);
9605 offset = extended ? offset : offset << 2;
Aurelien Jarnod75c1352013-01-01 18:02:22 +01009606 gen_arith_imm(ctx, OPC_DADDIU, ry, 29, offset);
Nathan Froyd364d4832009-12-08 08:06:29 -08009607 break;
9608 }
9609}
9610#endif
9611
Andreas Färber7db13fa2012-03-14 01:38:22 +01009612static int decode_extended_mips16_opc (CPUMIPSState *env, DisasContext *ctx,
Nathan Froyd364d4832009-12-08 08:06:29 -08009613 int *is_branch)
9614{
Blue Swirl895c2d02012-09-02 14:52:59 +00009615 int extend = cpu_lduw_code(env, ctx->pc + 2);
Nathan Froyd364d4832009-12-08 08:06:29 -08009616 int op, rx, ry, funct, sa;
9617 int16_t imm, offset;
9618
9619 ctx->opcode = (ctx->opcode << 16) | extend;
9620 op = (ctx->opcode >> 11) & 0x1f;
9621 sa = (ctx->opcode >> 22) & 0x1f;
9622 funct = (ctx->opcode >> 8) & 0x7;
9623 rx = xlat((ctx->opcode >> 8) & 0x7);
9624 ry = xlat((ctx->opcode >> 5) & 0x7);
9625 offset = imm = (int16_t) (((ctx->opcode >> 16) & 0x1f) << 11
9626 | ((ctx->opcode >> 21) & 0x3f) << 5
9627 | (ctx->opcode & 0x1f));
9628
9629 /* The extended opcodes cleverly reuse the opcodes from their 16-bit
9630 counterparts. */
9631 switch (op) {
9632 case M16_OPC_ADDIUSP:
Aurelien Jarnod75c1352013-01-01 18:02:22 +01009633 gen_arith_imm(ctx, OPC_ADDIU, rx, 29, imm);
Nathan Froyd364d4832009-12-08 08:06:29 -08009634 break;
9635 case M16_OPC_ADDIUPC:
9636 gen_addiupc(ctx, rx, imm, 0, 1);
9637 break;
9638 case M16_OPC_B:
9639 gen_compute_branch(ctx, OPC_BEQ, 4, 0, 0, offset << 1);
9640 /* No delay slot, so just process as a normal instruction */
9641 break;
9642 case M16_OPC_BEQZ:
9643 gen_compute_branch(ctx, OPC_BEQ, 4, rx, 0, offset << 1);
9644 /* No delay slot, so just process as a normal instruction */
9645 break;
9646 case M16_OPC_BNEQZ:
9647 gen_compute_branch(ctx, OPC_BNE, 4, rx, 0, offset << 1);
9648 /* No delay slot, so just process as a normal instruction */
9649 break;
9650 case M16_OPC_SHIFT:
9651 switch (ctx->opcode & 0x3) {
9652 case 0x0:
Aurelien Jarnod75c1352013-01-01 18:02:22 +01009653 gen_shift_imm(ctx, OPC_SLL, rx, ry, sa);
Nathan Froyd364d4832009-12-08 08:06:29 -08009654 break;
9655 case 0x1:
9656#if defined(TARGET_MIPS64)
9657 check_mips_64(ctx);
Aurelien Jarnod75c1352013-01-01 18:02:22 +01009658 gen_shift_imm(ctx, OPC_DSLL, rx, ry, sa);
Nathan Froyd364d4832009-12-08 08:06:29 -08009659#else
9660 generate_exception(ctx, EXCP_RI);
9661#endif
9662 break;
9663 case 0x2:
Aurelien Jarnod75c1352013-01-01 18:02:22 +01009664 gen_shift_imm(ctx, OPC_SRL, rx, ry, sa);
Nathan Froyd364d4832009-12-08 08:06:29 -08009665 break;
9666 case 0x3:
Aurelien Jarnod75c1352013-01-01 18:02:22 +01009667 gen_shift_imm(ctx, OPC_SRA, rx, ry, sa);
Nathan Froyd364d4832009-12-08 08:06:29 -08009668 break;
9669 }
9670 break;
9671#if defined(TARGET_MIPS64)
9672 case M16_OPC_LD:
9673 check_mips_64(ctx);
Aurelien Jarnod75c1352013-01-01 18:02:22 +01009674 gen_ld(ctx, OPC_LD, ry, rx, offset);
Nathan Froyd364d4832009-12-08 08:06:29 -08009675 break;
9676#endif
9677 case M16_OPC_RRIA:
9678 imm = ctx->opcode & 0xf;
9679 imm = imm | ((ctx->opcode >> 20) & 0x7f) << 4;
9680 imm = imm | ((ctx->opcode >> 16) & 0xf) << 11;
9681 imm = (int16_t) (imm << 1) >> 1;
9682 if ((ctx->opcode >> 4) & 0x1) {
9683#if defined(TARGET_MIPS64)
9684 check_mips_64(ctx);
Aurelien Jarnod75c1352013-01-01 18:02:22 +01009685 gen_arith_imm(ctx, OPC_DADDIU, ry, rx, imm);
Nathan Froyd364d4832009-12-08 08:06:29 -08009686#else
9687 generate_exception(ctx, EXCP_RI);
9688#endif
9689 } else {
Aurelien Jarnod75c1352013-01-01 18:02:22 +01009690 gen_arith_imm(ctx, OPC_ADDIU, ry, rx, imm);
Nathan Froyd364d4832009-12-08 08:06:29 -08009691 }
9692 break;
9693 case M16_OPC_ADDIU8:
Aurelien Jarnod75c1352013-01-01 18:02:22 +01009694 gen_arith_imm(ctx, OPC_ADDIU, rx, rx, imm);
Nathan Froyd364d4832009-12-08 08:06:29 -08009695 break;
9696 case M16_OPC_SLTI:
Aurelien Jarnod75c1352013-01-01 18:02:22 +01009697 gen_slt_imm(ctx, OPC_SLTI, 24, rx, imm);
Nathan Froyd364d4832009-12-08 08:06:29 -08009698 break;
9699 case M16_OPC_SLTIU:
Aurelien Jarnod75c1352013-01-01 18:02:22 +01009700 gen_slt_imm(ctx, OPC_SLTIU, 24, rx, imm);
Nathan Froyd364d4832009-12-08 08:06:29 -08009701 break;
9702 case M16_OPC_I8:
9703 switch (funct) {
9704 case I8_BTEQZ:
9705 gen_compute_branch(ctx, OPC_BEQ, 4, 24, 0, offset << 1);
9706 break;
9707 case I8_BTNEZ:
9708 gen_compute_branch(ctx, OPC_BNE, 4, 24, 0, offset << 1);
9709 break;
9710 case I8_SWRASP:
Aurelien Jarno5c13fdf2010-07-01 07:47:00 +02009711 gen_st(ctx, OPC_SW, 31, 29, imm);
Nathan Froyd364d4832009-12-08 08:06:29 -08009712 break;
9713 case I8_ADJSP:
Aurelien Jarnod75c1352013-01-01 18:02:22 +01009714 gen_arith_imm(ctx, OPC_ADDIU, 29, 29, imm);
Nathan Froyd364d4832009-12-08 08:06:29 -08009715 break;
9716 case I8_SVRS:
9717 {
9718 int xsregs = (ctx->opcode >> 24) & 0x7;
9719 int aregs = (ctx->opcode >> 16) & 0xf;
9720 int do_ra = (ctx->opcode >> 6) & 0x1;
9721 int do_s0 = (ctx->opcode >> 5) & 0x1;
9722 int do_s1 = (ctx->opcode >> 4) & 0x1;
9723 int framesize = (((ctx->opcode >> 20) & 0xf) << 4
9724 | (ctx->opcode & 0xf)) << 3;
9725
9726 if (ctx->opcode & (1 << 7)) {
9727 gen_mips16_save(ctx, xsregs, aregs,
9728 do_ra, do_s0, do_s1,
9729 framesize);
9730 } else {
9731 gen_mips16_restore(ctx, xsregs, aregs,
9732 do_ra, do_s0, do_s1,
9733 framesize);
9734 }
9735 }
9736 break;
9737 default:
9738 generate_exception(ctx, EXCP_RI);
9739 break;
9740 }
9741 break;
9742 case M16_OPC_LI:
9743 tcg_gen_movi_tl(cpu_gpr[rx], (uint16_t) imm);
9744 break;
9745 case M16_OPC_CMPI:
9746 tcg_gen_xori_tl(cpu_gpr[24], cpu_gpr[rx], (uint16_t) imm);
9747 break;
9748#if defined(TARGET_MIPS64)
9749 case M16_OPC_SD:
Aurelien Jarno5c13fdf2010-07-01 07:47:00 +02009750 gen_st(ctx, OPC_SD, ry, rx, offset);
Nathan Froyd364d4832009-12-08 08:06:29 -08009751 break;
9752#endif
9753 case M16_OPC_LB:
Aurelien Jarnod75c1352013-01-01 18:02:22 +01009754 gen_ld(ctx, OPC_LB, ry, rx, offset);
Nathan Froyd364d4832009-12-08 08:06:29 -08009755 break;
9756 case M16_OPC_LH:
Aurelien Jarnod75c1352013-01-01 18:02:22 +01009757 gen_ld(ctx, OPC_LH, ry, rx, offset);
Nathan Froyd364d4832009-12-08 08:06:29 -08009758 break;
9759 case M16_OPC_LWSP:
Aurelien Jarnod75c1352013-01-01 18:02:22 +01009760 gen_ld(ctx, OPC_LW, rx, 29, offset);
Nathan Froyd364d4832009-12-08 08:06:29 -08009761 break;
9762 case M16_OPC_LW:
Aurelien Jarnod75c1352013-01-01 18:02:22 +01009763 gen_ld(ctx, OPC_LW, ry, rx, offset);
Nathan Froyd364d4832009-12-08 08:06:29 -08009764 break;
9765 case M16_OPC_LBU:
Aurelien Jarnod75c1352013-01-01 18:02:22 +01009766 gen_ld(ctx, OPC_LBU, ry, rx, offset);
Nathan Froyd364d4832009-12-08 08:06:29 -08009767 break;
9768 case M16_OPC_LHU:
Aurelien Jarnod75c1352013-01-01 18:02:22 +01009769 gen_ld(ctx, OPC_LHU, ry, rx, offset);
Nathan Froyd364d4832009-12-08 08:06:29 -08009770 break;
9771 case M16_OPC_LWPC:
Aurelien Jarnod75c1352013-01-01 18:02:22 +01009772 gen_ld(ctx, OPC_LWPC, rx, 0, offset);
Nathan Froyd364d4832009-12-08 08:06:29 -08009773 break;
9774#if defined(TARGET_MIPS64)
9775 case M16_OPC_LWU:
Aurelien Jarnod75c1352013-01-01 18:02:22 +01009776 gen_ld(ctx, OPC_LWU, ry, rx, offset);
Nathan Froyd364d4832009-12-08 08:06:29 -08009777 break;
9778#endif
9779 case M16_OPC_SB:
Aurelien Jarno5c13fdf2010-07-01 07:47:00 +02009780 gen_st(ctx, OPC_SB, ry, rx, offset);
Nathan Froyd364d4832009-12-08 08:06:29 -08009781 break;
9782 case M16_OPC_SH:
Aurelien Jarno5c13fdf2010-07-01 07:47:00 +02009783 gen_st(ctx, OPC_SH, ry, rx, offset);
Nathan Froyd364d4832009-12-08 08:06:29 -08009784 break;
9785 case M16_OPC_SWSP:
Aurelien Jarno5c13fdf2010-07-01 07:47:00 +02009786 gen_st(ctx, OPC_SW, rx, 29, offset);
Nathan Froyd364d4832009-12-08 08:06:29 -08009787 break;
9788 case M16_OPC_SW:
Aurelien Jarno5c13fdf2010-07-01 07:47:00 +02009789 gen_st(ctx, OPC_SW, ry, rx, offset);
Nathan Froyd364d4832009-12-08 08:06:29 -08009790 break;
9791#if defined(TARGET_MIPS64)
9792 case M16_OPC_I64:
Aurelien Jarnod75c1352013-01-01 18:02:22 +01009793 decode_i64_mips16(ctx, ry, funct, offset, 1);
Nathan Froyd364d4832009-12-08 08:06:29 -08009794 break;
9795#endif
9796 default:
9797 generate_exception(ctx, EXCP_RI);
9798 break;
9799 }
9800
9801 return 4;
9802}
9803
Andreas Färber7db13fa2012-03-14 01:38:22 +01009804static int decode_mips16_opc (CPUMIPSState *env, DisasContext *ctx,
Nathan Froyd364d4832009-12-08 08:06:29 -08009805 int *is_branch)
9806{
9807 int rx, ry;
9808 int sa;
9809 int op, cnvt_op, op1, offset;
9810 int funct;
9811 int n_bytes;
9812
9813 op = (ctx->opcode >> 11) & 0x1f;
9814 sa = (ctx->opcode >> 2) & 0x7;
9815 sa = sa == 0 ? 8 : sa;
9816 rx = xlat((ctx->opcode >> 8) & 0x7);
9817 cnvt_op = (ctx->opcode >> 5) & 0x7;
9818 ry = xlat((ctx->opcode >> 5) & 0x7);
9819 op1 = offset = ctx->opcode & 0x1f;
9820
9821 n_bytes = 2;
9822
9823 switch (op) {
9824 case M16_OPC_ADDIUSP:
9825 {
9826 int16_t imm = ((uint8_t) ctx->opcode) << 2;
9827
Aurelien Jarnod75c1352013-01-01 18:02:22 +01009828 gen_arith_imm(ctx, OPC_ADDIU, rx, 29, imm);
Nathan Froyd364d4832009-12-08 08:06:29 -08009829 }
9830 break;
9831 case M16_OPC_ADDIUPC:
9832 gen_addiupc(ctx, rx, ((uint8_t) ctx->opcode) << 2, 0, 0);
9833 break;
9834 case M16_OPC_B:
9835 offset = (ctx->opcode & 0x7ff) << 1;
9836 offset = (int16_t)(offset << 4) >> 4;
9837 gen_compute_branch(ctx, OPC_BEQ, 2, 0, 0, offset);
9838 /* No delay slot, so just process as a normal instruction */
9839 break;
9840 case M16_OPC_JAL:
Blue Swirl895c2d02012-09-02 14:52:59 +00009841 offset = cpu_lduw_code(env, ctx->pc + 2);
Nathan Froyd364d4832009-12-08 08:06:29 -08009842 offset = (((ctx->opcode & 0x1f) << 21)
9843 | ((ctx->opcode >> 5) & 0x1f) << 16
9844 | offset) << 2;
Nathan Froyd620e48f2010-06-08 13:29:58 -07009845 op = ((ctx->opcode >> 10) & 0x1) ? OPC_JALXS : OPC_JALS;
Nathan Froyd364d4832009-12-08 08:06:29 -08009846 gen_compute_branch(ctx, op, 4, rx, ry, offset);
9847 n_bytes = 4;
9848 *is_branch = 1;
9849 break;
9850 case M16_OPC_BEQZ:
9851 gen_compute_branch(ctx, OPC_BEQ, 2, rx, 0, ((int8_t)ctx->opcode) << 1);
9852 /* No delay slot, so just process as a normal instruction */
9853 break;
9854 case M16_OPC_BNEQZ:
9855 gen_compute_branch(ctx, OPC_BNE, 2, rx, 0, ((int8_t)ctx->opcode) << 1);
9856 /* No delay slot, so just process as a normal instruction */
9857 break;
9858 case M16_OPC_SHIFT:
9859 switch (ctx->opcode & 0x3) {
9860 case 0x0:
Aurelien Jarnod75c1352013-01-01 18:02:22 +01009861 gen_shift_imm(ctx, OPC_SLL, rx, ry, sa);
Nathan Froyd364d4832009-12-08 08:06:29 -08009862 break;
9863 case 0x1:
9864#if defined(TARGET_MIPS64)
9865 check_mips_64(ctx);
Aurelien Jarnod75c1352013-01-01 18:02:22 +01009866 gen_shift_imm(ctx, OPC_DSLL, rx, ry, sa);
Nathan Froyd364d4832009-12-08 08:06:29 -08009867#else
9868 generate_exception(ctx, EXCP_RI);
9869#endif
9870 break;
9871 case 0x2:
Aurelien Jarnod75c1352013-01-01 18:02:22 +01009872 gen_shift_imm(ctx, OPC_SRL, rx, ry, sa);
Nathan Froyd364d4832009-12-08 08:06:29 -08009873 break;
9874 case 0x3:
Aurelien Jarnod75c1352013-01-01 18:02:22 +01009875 gen_shift_imm(ctx, OPC_SRA, rx, ry, sa);
Nathan Froyd364d4832009-12-08 08:06:29 -08009876 break;
9877 }
9878 break;
9879#if defined(TARGET_MIPS64)
9880 case M16_OPC_LD:
9881 check_mips_64(ctx);
Aurelien Jarnod75c1352013-01-01 18:02:22 +01009882 gen_ld(ctx, OPC_LD, ry, rx, offset << 3);
Nathan Froyd364d4832009-12-08 08:06:29 -08009883 break;
9884#endif
9885 case M16_OPC_RRIA:
9886 {
9887 int16_t imm = (int8_t)((ctx->opcode & 0xf) << 4) >> 4;
9888
9889 if ((ctx->opcode >> 4) & 1) {
9890#if defined(TARGET_MIPS64)
9891 check_mips_64(ctx);
Aurelien Jarnod75c1352013-01-01 18:02:22 +01009892 gen_arith_imm(ctx, OPC_DADDIU, ry, rx, imm);
Nathan Froyd364d4832009-12-08 08:06:29 -08009893#else
9894 generate_exception(ctx, EXCP_RI);
9895#endif
9896 } else {
Aurelien Jarnod75c1352013-01-01 18:02:22 +01009897 gen_arith_imm(ctx, OPC_ADDIU, ry, rx, imm);
Nathan Froyd364d4832009-12-08 08:06:29 -08009898 }
9899 }
9900 break;
9901 case M16_OPC_ADDIU8:
9902 {
9903 int16_t imm = (int8_t) ctx->opcode;
9904
Aurelien Jarnod75c1352013-01-01 18:02:22 +01009905 gen_arith_imm(ctx, OPC_ADDIU, rx, rx, imm);
Nathan Froyd364d4832009-12-08 08:06:29 -08009906 }
9907 break;
9908 case M16_OPC_SLTI:
9909 {
9910 int16_t imm = (uint8_t) ctx->opcode;
Aurelien Jarnod75c1352013-01-01 18:02:22 +01009911 gen_slt_imm(ctx, OPC_SLTI, 24, rx, imm);
Nathan Froyd364d4832009-12-08 08:06:29 -08009912 }
9913 break;
9914 case M16_OPC_SLTIU:
9915 {
9916 int16_t imm = (uint8_t) ctx->opcode;
Aurelien Jarnod75c1352013-01-01 18:02:22 +01009917 gen_slt_imm(ctx, OPC_SLTIU, 24, rx, imm);
Nathan Froyd364d4832009-12-08 08:06:29 -08009918 }
9919 break;
9920 case M16_OPC_I8:
9921 {
9922 int reg32;
9923
9924 funct = (ctx->opcode >> 8) & 0x7;
9925 switch (funct) {
9926 case I8_BTEQZ:
9927 gen_compute_branch(ctx, OPC_BEQ, 2, 24, 0,
9928 ((int8_t)ctx->opcode) << 1);
9929 break;
9930 case I8_BTNEZ:
9931 gen_compute_branch(ctx, OPC_BNE, 2, 24, 0,
9932 ((int8_t)ctx->opcode) << 1);
9933 break;
9934 case I8_SWRASP:
Aurelien Jarno5c13fdf2010-07-01 07:47:00 +02009935 gen_st(ctx, OPC_SW, 31, 29, (ctx->opcode & 0xff) << 2);
Nathan Froyd364d4832009-12-08 08:06:29 -08009936 break;
9937 case I8_ADJSP:
Aurelien Jarnod75c1352013-01-01 18:02:22 +01009938 gen_arith_imm(ctx, OPC_ADDIU, 29, 29,
Nathan Froyd364d4832009-12-08 08:06:29 -08009939 ((int8_t)ctx->opcode) << 3);
9940 break;
9941 case I8_SVRS:
9942 {
9943 int do_ra = ctx->opcode & (1 << 6);
9944 int do_s0 = ctx->opcode & (1 << 5);
9945 int do_s1 = ctx->opcode & (1 << 4);
9946 int framesize = ctx->opcode & 0xf;
9947
9948 if (framesize == 0) {
9949 framesize = 128;
9950 } else {
9951 framesize = framesize << 3;
9952 }
9953
9954 if (ctx->opcode & (1 << 7)) {
9955 gen_mips16_save(ctx, 0, 0,
9956 do_ra, do_s0, do_s1, framesize);
9957 } else {
9958 gen_mips16_restore(ctx, 0, 0,
9959 do_ra, do_s0, do_s1, framesize);
9960 }
9961 }
9962 break;
9963 case I8_MOV32R:
9964 {
9965 int rz = xlat(ctx->opcode & 0x7);
9966
9967 reg32 = (((ctx->opcode >> 3) & 0x3) << 3) |
9968 ((ctx->opcode >> 5) & 0x7);
Aurelien Jarnod75c1352013-01-01 18:02:22 +01009969 gen_arith(ctx, OPC_ADDU, reg32, rz, 0);
Nathan Froyd364d4832009-12-08 08:06:29 -08009970 }
9971 break;
9972 case I8_MOVR32:
9973 reg32 = ctx->opcode & 0x1f;
Aurelien Jarnod75c1352013-01-01 18:02:22 +01009974 gen_arith(ctx, OPC_ADDU, ry, reg32, 0);
Nathan Froyd364d4832009-12-08 08:06:29 -08009975 break;
9976 default:
9977 generate_exception(ctx, EXCP_RI);
9978 break;
9979 }
9980 }
9981 break;
9982 case M16_OPC_LI:
9983 {
9984 int16_t imm = (uint8_t) ctx->opcode;
9985
Aurelien Jarnod75c1352013-01-01 18:02:22 +01009986 gen_arith_imm(ctx, OPC_ADDIU, rx, 0, imm);
Nathan Froyd364d4832009-12-08 08:06:29 -08009987 }
9988 break;
9989 case M16_OPC_CMPI:
9990 {
9991 int16_t imm = (uint8_t) ctx->opcode;
Aurelien Jarnod75c1352013-01-01 18:02:22 +01009992 gen_logic_imm(ctx, OPC_XORI, 24, rx, imm);
Nathan Froyd364d4832009-12-08 08:06:29 -08009993 }
9994 break;
9995#if defined(TARGET_MIPS64)
9996 case M16_OPC_SD:
9997 check_mips_64(ctx);
Aurelien Jarno5c13fdf2010-07-01 07:47:00 +02009998 gen_st(ctx, OPC_SD, ry, rx, offset << 3);
Nathan Froyd364d4832009-12-08 08:06:29 -08009999 break;
10000#endif
10001 case M16_OPC_LB:
Aurelien Jarnod75c1352013-01-01 18:02:22 +010010002 gen_ld(ctx, OPC_LB, ry, rx, offset);
Nathan Froyd364d4832009-12-08 08:06:29 -080010003 break;
10004 case M16_OPC_LH:
Aurelien Jarnod75c1352013-01-01 18:02:22 +010010005 gen_ld(ctx, OPC_LH, ry, rx, offset << 1);
Nathan Froyd364d4832009-12-08 08:06:29 -080010006 break;
10007 case M16_OPC_LWSP:
Aurelien Jarnod75c1352013-01-01 18:02:22 +010010008 gen_ld(ctx, OPC_LW, rx, 29, ((uint8_t)ctx->opcode) << 2);
Nathan Froyd364d4832009-12-08 08:06:29 -080010009 break;
10010 case M16_OPC_LW:
Aurelien Jarnod75c1352013-01-01 18:02:22 +010010011 gen_ld(ctx, OPC_LW, ry, rx, offset << 2);
Nathan Froyd364d4832009-12-08 08:06:29 -080010012 break;
10013 case M16_OPC_LBU:
Aurelien Jarnod75c1352013-01-01 18:02:22 +010010014 gen_ld(ctx, OPC_LBU, ry, rx, offset);
Nathan Froyd364d4832009-12-08 08:06:29 -080010015 break;
10016 case M16_OPC_LHU:
Aurelien Jarnod75c1352013-01-01 18:02:22 +010010017 gen_ld(ctx, OPC_LHU, ry, rx, offset << 1);
Nathan Froyd364d4832009-12-08 08:06:29 -080010018 break;
10019 case M16_OPC_LWPC:
Aurelien Jarnod75c1352013-01-01 18:02:22 +010010020 gen_ld(ctx, OPC_LWPC, rx, 0, ((uint8_t)ctx->opcode) << 2);
Nathan Froyd364d4832009-12-08 08:06:29 -080010021 break;
10022#if defined (TARGET_MIPS64)
10023 case M16_OPC_LWU:
10024 check_mips_64(ctx);
Aurelien Jarnod75c1352013-01-01 18:02:22 +010010025 gen_ld(ctx, OPC_LWU, ry, rx, offset << 2);
Nathan Froyd364d4832009-12-08 08:06:29 -080010026 break;
10027#endif
10028 case M16_OPC_SB:
Aurelien Jarno5c13fdf2010-07-01 07:47:00 +020010029 gen_st(ctx, OPC_SB, ry, rx, offset);
Nathan Froyd364d4832009-12-08 08:06:29 -080010030 break;
10031 case M16_OPC_SH:
Aurelien Jarno5c13fdf2010-07-01 07:47:00 +020010032 gen_st(ctx, OPC_SH, ry, rx, offset << 1);
Nathan Froyd364d4832009-12-08 08:06:29 -080010033 break;
10034 case M16_OPC_SWSP:
Aurelien Jarno5c13fdf2010-07-01 07:47:00 +020010035 gen_st(ctx, OPC_SW, rx, 29, ((uint8_t)ctx->opcode) << 2);
Nathan Froyd364d4832009-12-08 08:06:29 -080010036 break;
10037 case M16_OPC_SW:
Aurelien Jarno5c13fdf2010-07-01 07:47:00 +020010038 gen_st(ctx, OPC_SW, ry, rx, offset << 2);
Nathan Froyd364d4832009-12-08 08:06:29 -080010039 break;
10040 case M16_OPC_RRR:
10041 {
10042 int rz = xlat((ctx->opcode >> 2) & 0x7);
10043 int mips32_op;
10044
10045 switch (ctx->opcode & 0x3) {
10046 case RRR_ADDU:
10047 mips32_op = OPC_ADDU;
10048 break;
10049 case RRR_SUBU:
10050 mips32_op = OPC_SUBU;
10051 break;
10052#if defined(TARGET_MIPS64)
10053 case RRR_DADDU:
10054 mips32_op = OPC_DADDU;
10055 check_mips_64(ctx);
10056 break;
10057 case RRR_DSUBU:
10058 mips32_op = OPC_DSUBU;
10059 check_mips_64(ctx);
10060 break;
10061#endif
10062 default:
10063 generate_exception(ctx, EXCP_RI);
10064 goto done;
10065 }
10066
Aurelien Jarnod75c1352013-01-01 18:02:22 +010010067 gen_arith(ctx, mips32_op, rz, rx, ry);
Nathan Froyd364d4832009-12-08 08:06:29 -080010068 done:
10069 ;
10070 }
10071 break;
10072 case M16_OPC_RR:
10073 switch (op1) {
10074 case RR_JR:
10075 {
10076 int nd = (ctx->opcode >> 7) & 0x1;
10077 int link = (ctx->opcode >> 6) & 0x1;
10078 int ra = (ctx->opcode >> 5) & 0x1;
10079
10080 if (link) {
Nathan Froyd620e48f2010-06-08 13:29:58 -070010081 op = nd ? OPC_JALRC : OPC_JALRS;
Nathan Froyd364d4832009-12-08 08:06:29 -080010082 } else {
10083 op = OPC_JR;
10084 }
10085
10086 gen_compute_branch(ctx, op, 2, ra ? 31 : rx, 31, 0);
10087 if (!nd) {
10088 *is_branch = 1;
10089 }
10090 }
10091 break;
10092 case RR_SDBBP:
10093 /* XXX: not clear which exception should be raised
10094 * when in debug mode...
10095 */
Aurelien Jarnod75c1352013-01-01 18:02:22 +010010096 check_insn(ctx, ISA_MIPS32);
Nathan Froyd364d4832009-12-08 08:06:29 -080010097 if (!(ctx->hflags & MIPS_HFLAG_DM)) {
10098 generate_exception(ctx, EXCP_DBp);
10099 } else {
10100 generate_exception(ctx, EXCP_DBp);
10101 }
10102 break;
10103 case RR_SLT:
Aurelien Jarnod75c1352013-01-01 18:02:22 +010010104 gen_slt(ctx, OPC_SLT, 24, rx, ry);
Nathan Froyd364d4832009-12-08 08:06:29 -080010105 break;
10106 case RR_SLTU:
Aurelien Jarnod75c1352013-01-01 18:02:22 +010010107 gen_slt(ctx, OPC_SLTU, 24, rx, ry);
Nathan Froyd364d4832009-12-08 08:06:29 -080010108 break;
10109 case RR_BREAK:
10110 generate_exception(ctx, EXCP_BREAK);
10111 break;
10112 case RR_SLLV:
Aurelien Jarnod75c1352013-01-01 18:02:22 +010010113 gen_shift(ctx, OPC_SLLV, ry, rx, ry);
Nathan Froyd364d4832009-12-08 08:06:29 -080010114 break;
10115 case RR_SRLV:
Aurelien Jarnod75c1352013-01-01 18:02:22 +010010116 gen_shift(ctx, OPC_SRLV, ry, rx, ry);
Nathan Froyd364d4832009-12-08 08:06:29 -080010117 break;
10118 case RR_SRAV:
Aurelien Jarnod75c1352013-01-01 18:02:22 +010010119 gen_shift(ctx, OPC_SRAV, ry, rx, ry);
Nathan Froyd364d4832009-12-08 08:06:29 -080010120 break;
10121#if defined (TARGET_MIPS64)
10122 case RR_DSRL:
10123 check_mips_64(ctx);
Aurelien Jarnod75c1352013-01-01 18:02:22 +010010124 gen_shift_imm(ctx, OPC_DSRL, ry, ry, sa);
Nathan Froyd364d4832009-12-08 08:06:29 -080010125 break;
10126#endif
10127 case RR_CMP:
Aurelien Jarnod75c1352013-01-01 18:02:22 +010010128 gen_logic(ctx, OPC_XOR, 24, rx, ry);
Nathan Froyd364d4832009-12-08 08:06:29 -080010129 break;
10130 case RR_NEG:
Aurelien Jarnod75c1352013-01-01 18:02:22 +010010131 gen_arith(ctx, OPC_SUBU, rx, 0, ry);
Nathan Froyd364d4832009-12-08 08:06:29 -080010132 break;
10133 case RR_AND:
Aurelien Jarnod75c1352013-01-01 18:02:22 +010010134 gen_logic(ctx, OPC_AND, rx, rx, ry);
Nathan Froyd364d4832009-12-08 08:06:29 -080010135 break;
10136 case RR_OR:
Aurelien Jarnod75c1352013-01-01 18:02:22 +010010137 gen_logic(ctx, OPC_OR, rx, rx, ry);
Nathan Froyd364d4832009-12-08 08:06:29 -080010138 break;
10139 case RR_XOR:
Aurelien Jarnod75c1352013-01-01 18:02:22 +010010140 gen_logic(ctx, OPC_XOR, rx, rx, ry);
Nathan Froyd364d4832009-12-08 08:06:29 -080010141 break;
10142 case RR_NOT:
Aurelien Jarnod75c1352013-01-01 18:02:22 +010010143 gen_logic(ctx, OPC_NOR, rx, ry, 0);
Nathan Froyd364d4832009-12-08 08:06:29 -080010144 break;
10145 case RR_MFHI:
10146 gen_HILO(ctx, OPC_MFHI, rx);
10147 break;
10148 case RR_CNVT:
10149 switch (cnvt_op) {
10150 case RR_RY_CNVT_ZEB:
10151 tcg_gen_ext8u_tl(cpu_gpr[rx], cpu_gpr[rx]);
10152 break;
10153 case RR_RY_CNVT_ZEH:
10154 tcg_gen_ext16u_tl(cpu_gpr[rx], cpu_gpr[rx]);
10155 break;
10156 case RR_RY_CNVT_SEB:
10157 tcg_gen_ext8s_tl(cpu_gpr[rx], cpu_gpr[rx]);
10158 break;
10159 case RR_RY_CNVT_SEH:
10160 tcg_gen_ext16s_tl(cpu_gpr[rx], cpu_gpr[rx]);
10161 break;
10162#if defined (TARGET_MIPS64)
10163 case RR_RY_CNVT_ZEW:
10164 check_mips_64(ctx);
10165 tcg_gen_ext32u_tl(cpu_gpr[rx], cpu_gpr[rx]);
10166 break;
10167 case RR_RY_CNVT_SEW:
10168 check_mips_64(ctx);
10169 tcg_gen_ext32s_tl(cpu_gpr[rx], cpu_gpr[rx]);
10170 break;
10171#endif
10172 default:
10173 generate_exception(ctx, EXCP_RI);
10174 break;
10175 }
10176 break;
10177 case RR_MFLO:
10178 gen_HILO(ctx, OPC_MFLO, rx);
10179 break;
10180#if defined (TARGET_MIPS64)
10181 case RR_DSRA:
10182 check_mips_64(ctx);
Aurelien Jarnod75c1352013-01-01 18:02:22 +010010183 gen_shift_imm(ctx, OPC_DSRA, ry, ry, sa);
Nathan Froyd364d4832009-12-08 08:06:29 -080010184 break;
10185 case RR_DSLLV:
10186 check_mips_64(ctx);
Aurelien Jarnod75c1352013-01-01 18:02:22 +010010187 gen_shift(ctx, OPC_DSLLV, ry, rx, ry);
Nathan Froyd364d4832009-12-08 08:06:29 -080010188 break;
10189 case RR_DSRLV:
10190 check_mips_64(ctx);
Aurelien Jarnod75c1352013-01-01 18:02:22 +010010191 gen_shift(ctx, OPC_DSRLV, ry, rx, ry);
Nathan Froyd364d4832009-12-08 08:06:29 -080010192 break;
10193 case RR_DSRAV:
10194 check_mips_64(ctx);
Aurelien Jarnod75c1352013-01-01 18:02:22 +010010195 gen_shift(ctx, OPC_DSRAV, ry, rx, ry);
Nathan Froyd364d4832009-12-08 08:06:29 -080010196 break;
10197#endif
10198 case RR_MULT:
10199 gen_muldiv(ctx, OPC_MULT, rx, ry);
10200 break;
10201 case RR_MULTU:
10202 gen_muldiv(ctx, OPC_MULTU, rx, ry);
10203 break;
10204 case RR_DIV:
10205 gen_muldiv(ctx, OPC_DIV, rx, ry);
10206 break;
10207 case RR_DIVU:
10208 gen_muldiv(ctx, OPC_DIVU, rx, ry);
10209 break;
10210#if defined (TARGET_MIPS64)
10211 case RR_DMULT:
10212 check_mips_64(ctx);
10213 gen_muldiv(ctx, OPC_DMULT, rx, ry);
10214 break;
10215 case RR_DMULTU:
10216 check_mips_64(ctx);
10217 gen_muldiv(ctx, OPC_DMULTU, rx, ry);
10218 break;
10219 case RR_DDIV:
10220 check_mips_64(ctx);
10221 gen_muldiv(ctx, OPC_DDIV, rx, ry);
10222 break;
10223 case RR_DDIVU:
10224 check_mips_64(ctx);
10225 gen_muldiv(ctx, OPC_DDIVU, rx, ry);
10226 break;
10227#endif
10228 default:
10229 generate_exception(ctx, EXCP_RI);
10230 break;
10231 }
10232 break;
10233 case M16_OPC_EXTEND:
10234 decode_extended_mips16_opc(env, ctx, is_branch);
10235 n_bytes = 4;
10236 break;
10237#if defined(TARGET_MIPS64)
10238 case M16_OPC_I64:
10239 funct = (ctx->opcode >> 8) & 0x7;
Aurelien Jarnod75c1352013-01-01 18:02:22 +010010240 decode_i64_mips16(ctx, ry, funct, offset, 0);
Nathan Froyd364d4832009-12-08 08:06:29 -080010241 break;
10242#endif
10243 default:
10244 generate_exception(ctx, EXCP_RI);
10245 break;
10246 }
10247
10248 return n_bytes;
10249}
10250
陳韋任 (Wei-Ren Chen)211da992012-11-21 14:04:41 +080010251/* microMIPS extension to MIPS32/MIPS64 */
Nathan Froyd3c824102010-06-08 13:29:59 -070010252
陳韋任 (Wei-Ren Chen)211da992012-11-21 14:04:41 +080010253/*
10254 * microMIPS32/microMIPS64 major opcodes
10255 *
10256 * 1. MIPS Architecture for Programmers Volume II-B:
10257 * The microMIPS32 Instruction Set (Revision 3.05)
10258 *
10259 * Table 6.2 microMIPS32 Encoding of Major Opcode Field
10260 *
10261 * 2. MIPS Architecture For Programmers Volume II-A:
10262 * The MIPS64 Instruction Set (Revision 3.51)
10263 */
Nathan Froyd3c824102010-06-08 13:29:59 -070010264
10265enum {
10266 POOL32A = 0x00,
10267 POOL16A = 0x01,
10268 LBU16 = 0x02,
10269 MOVE16 = 0x03,
10270 ADDI32 = 0x04,
10271 LBU32 = 0x05,
10272 SB32 = 0x06,
10273 LB32 = 0x07,
10274
10275 POOL32B = 0x08,
10276 POOL16B = 0x09,
10277 LHU16 = 0x0a,
10278 ANDI16 = 0x0b,
10279 ADDIU32 = 0x0c,
10280 LHU32 = 0x0d,
10281 SH32 = 0x0e,
10282 LH32 = 0x0f,
10283
10284 POOL32I = 0x10,
10285 POOL16C = 0x11,
10286 LWSP16 = 0x12,
10287 POOL16D = 0x13,
10288 ORI32 = 0x14,
10289 POOL32F = 0x15,
陳韋任 (Wei-Ren Chen)211da992012-11-21 14:04:41 +080010290 POOL32S = 0x16, /* MIPS64 */
10291 DADDIU32 = 0x17, /* MIPS64 */
Nathan Froyd3c824102010-06-08 13:29:59 -070010292
陳韋任 (Wei-Ren Chen)211da992012-11-21 14:04:41 +080010293 /* 0x1f is reserved */
Nathan Froyd3c824102010-06-08 13:29:59 -070010294 POOL32C = 0x18,
10295 LWGP16 = 0x19,
10296 LW16 = 0x1a,
10297 POOL16E = 0x1b,
10298 XORI32 = 0x1c,
10299 JALS32 = 0x1d,
10300 ADDIUPC = 0x1e,
Nathan Froyd3c824102010-06-08 13:29:59 -070010301
10302 /* 0x20 is reserved */
10303 RES_20 = 0x20,
10304 POOL16F = 0x21,
10305 SB16 = 0x22,
10306 BEQZ16 = 0x23,
10307 SLTI32 = 0x24,
10308 BEQ32 = 0x25,
10309 SWC132 = 0x26,
10310 LWC132 = 0x27,
10311
10312 /* 0x28 and 0x29 are reserved */
10313 RES_28 = 0x28,
10314 RES_29 = 0x29,
10315 SH16 = 0x2a,
10316 BNEZ16 = 0x2b,
10317 SLTIU32 = 0x2c,
10318 BNE32 = 0x2d,
10319 SDC132 = 0x2e,
10320 LDC132 = 0x2f,
10321
10322 /* 0x30 and 0x31 are reserved */
10323 RES_30 = 0x30,
10324 RES_31 = 0x31,
10325 SWSP16 = 0x32,
10326 B16 = 0x33,
10327 ANDI32 = 0x34,
10328 J32 = 0x35,
陳韋任 (Wei-Ren Chen)211da992012-11-21 14:04:41 +080010329 SD32 = 0x36, /* MIPS64 */
10330 LD32 = 0x37, /* MIPS64 */
Nathan Froyd3c824102010-06-08 13:29:59 -070010331
10332 /* 0x38 and 0x39 are reserved */
10333 RES_38 = 0x38,
10334 RES_39 = 0x39,
10335 SW16 = 0x3a,
10336 LI16 = 0x3b,
10337 JALX32 = 0x3c,
10338 JAL32 = 0x3d,
10339 SW32 = 0x3e,
10340 LW32 = 0x3f
10341};
10342
10343/* POOL32A encoding of minor opcode field */
10344
10345enum {
10346 /* These opcodes are distinguished only by bits 9..6; those bits are
10347 * what are recorded below. */
10348 SLL32 = 0x0,
10349 SRL32 = 0x1,
10350 SRA = 0x2,
10351 ROTR = 0x3,
10352
10353 SLLV = 0x0,
10354 SRLV = 0x1,
10355 SRAV = 0x2,
10356 ROTRV = 0x3,
10357 ADD = 0x4,
10358 ADDU32 = 0x5,
10359 SUB = 0x6,
10360 SUBU32 = 0x7,
10361 MUL = 0x8,
10362 AND = 0x9,
10363 OR32 = 0xa,
10364 NOR = 0xb,
10365 XOR32 = 0xc,
10366 SLT = 0xd,
10367 SLTU = 0xe,
10368
10369 MOVN = 0x0,
10370 MOVZ = 0x1,
10371 LWXS = 0x4,
10372
10373 /* The following can be distinguished by their lower 6 bits. */
10374 INS = 0x0c,
10375 EXT = 0x2c,
10376 POOL32AXF = 0x3c
10377};
10378
10379/* POOL32AXF encoding of minor opcode field extension */
10380
陳韋任 (Wei-Ren Chen)d132c792012-11-21 13:50:45 +080010381/*
10382 * 1. MIPS Architecture for Programmers Volume II-B:
10383 * The microMIPS32 Instruction Set (Revision 3.05)
10384 *
10385 * Table 6.5 POOL32Axf Encoding of Minor Opcode Extension Field
10386 *
10387 * 2. MIPS Architecture for Programmers VolumeIV-e:
10388 * The MIPS DSP Application-Specific Extension
10389 * to the microMIPS32 Architecture (Revision 2.34)
10390 *
10391 * Table 5.5 POOL32Axf Encoding of Minor Opcode Extension Field
10392 */
10393
Nathan Froyd3c824102010-06-08 13:29:59 -070010394enum {
10395 /* bits 11..6 */
10396 TEQ = 0x00,
10397 TGE = 0x08,
10398 TGEU = 0x10,
10399 TLT = 0x20,
10400 TLTU = 0x28,
10401 TNE = 0x30,
10402
10403 MFC0 = 0x03,
10404 MTC0 = 0x0b,
10405
陳韋任 (Wei-Ren Chen)d132c792012-11-21 13:50:45 +080010406 /* begin of microMIPS32 DSP */
10407
Nathan Froyd3c824102010-06-08 13:29:59 -070010408 /* bits 13..12 for 0x01 */
10409 MFHI_ACC = 0x0,
10410 MFLO_ACC = 0x1,
10411 MTHI_ACC = 0x2,
10412 MTLO_ACC = 0x3,
10413
10414 /* bits 13..12 for 0x2a */
10415 MADD_ACC = 0x0,
10416 MADDU_ACC = 0x1,
10417 MSUB_ACC = 0x2,
10418 MSUBU_ACC = 0x3,
10419
10420 /* bits 13..12 for 0x32 */
10421 MULT_ACC = 0x0,
陳韋任 (Wei-Ren Chen)68010382012-11-14 10:49:55 +080010422 MULTU_ACC = 0x1,
Nathan Froyd3c824102010-06-08 13:29:59 -070010423
陳韋任 (Wei-Ren Chen)d132c792012-11-21 13:50:45 +080010424 /* end of microMIPS32 DSP */
10425
Nathan Froyd3c824102010-06-08 13:29:59 -070010426 /* bits 15..12 for 0x2c */
10427 SEB = 0x2,
10428 SEH = 0x3,
10429 CLO = 0x4,
10430 CLZ = 0x5,
10431 RDHWR = 0x6,
10432 WSBH = 0x7,
10433 MULT = 0x8,
10434 MULTU = 0x9,
10435 DIV = 0xa,
10436 DIVU = 0xb,
10437 MADD = 0xc,
10438 MADDU = 0xd,
10439 MSUB = 0xe,
10440 MSUBU = 0xf,
10441
10442 /* bits 15..12 for 0x34 */
10443 MFC2 = 0x4,
10444 MTC2 = 0x5,
10445 MFHC2 = 0x8,
10446 MTHC2 = 0x9,
10447 CFC2 = 0xc,
10448 CTC2 = 0xd,
10449
10450 /* bits 15..12 for 0x3c */
10451 JALR = 0x0,
10452 JR = 0x0, /* alias */
10453 JALR_HB = 0x1,
10454 JALRS = 0x4,
10455 JALRS_HB = 0x5,
10456
10457 /* bits 15..12 for 0x05 */
10458 RDPGPR = 0xe,
10459 WRPGPR = 0xf,
10460
10461 /* bits 15..12 for 0x0d */
10462 TLBP = 0x0,
10463 TLBR = 0x1,
10464 TLBWI = 0x2,
10465 TLBWR = 0x3,
10466 WAIT = 0x9,
10467 IRET = 0xd,
10468 DERET = 0xe,
10469 ERET = 0xf,
10470
10471 /* bits 15..12 for 0x15 */
10472 DMT = 0x0,
10473 DVPE = 0x1,
10474 EMT = 0x2,
10475 EVPE = 0x3,
10476
10477 /* bits 15..12 for 0x1d */
10478 DI = 0x4,
10479 EI = 0x5,
10480
10481 /* bits 15..12 for 0x2d */
10482 SYNC = 0x6,
10483 SYSCALL = 0x8,
10484 SDBBP = 0xd,
10485
10486 /* bits 15..12 for 0x35 */
10487 MFHI32 = 0x0,
10488 MFLO32 = 0x1,
10489 MTHI32 = 0x2,
10490 MTLO32 = 0x3,
10491};
10492
10493/* POOL32B encoding of minor opcode field (bits 15..12) */
10494
10495enum {
10496 LWC2 = 0x0,
10497 LWP = 0x1,
10498 LDP = 0x4,
10499 LWM32 = 0x5,
10500 CACHE = 0x6,
10501 LDM = 0x7,
10502 SWC2 = 0x8,
10503 SWP = 0x9,
10504 SDP = 0xc,
10505 SWM32 = 0xd,
10506 SDM = 0xf
10507};
10508
10509/* POOL32C encoding of minor opcode field (bits 15..12) */
10510
10511enum {
10512 LWL = 0x0,
10513 SWL = 0x8,
10514 LWR = 0x1,
10515 SWR = 0x9,
10516 PREF = 0x2,
10517 /* 0xa is reserved */
10518 LL = 0x3,
10519 SC = 0xb,
10520 LDL = 0x4,
10521 SDL = 0xc,
10522 LDR = 0x5,
10523 SDR = 0xd,
10524 /* 0x6 is reserved */
10525 LWU = 0xe,
10526 LLD = 0x7,
10527 SCD = 0xf
10528};
10529
10530/* POOL32F encoding of minor opcode field (bits 5..0) */
10531
10532enum {
10533 /* These are the bit 7..6 values */
10534 ADD_FMT = 0x0,
10535 MOVN_FMT = 0x0,
10536
10537 SUB_FMT = 0x1,
10538 MOVZ_FMT = 0x1,
10539
10540 MUL_FMT = 0x2,
10541
10542 DIV_FMT = 0x3,
10543
10544 /* These are the bit 8..6 values */
10545 RSQRT2_FMT = 0x0,
10546 MOVF_FMT = 0x0,
10547
10548 LWXC1 = 0x1,
10549 MOVT_FMT = 0x1,
10550
10551 PLL_PS = 0x2,
10552 SWXC1 = 0x2,
10553
10554 PLU_PS = 0x3,
10555 LDXC1 = 0x3,
10556
10557 PUL_PS = 0x4,
10558 SDXC1 = 0x4,
10559 RECIP2_FMT = 0x4,
10560
10561 PUU_PS = 0x5,
10562 LUXC1 = 0x5,
10563
10564 CVT_PS_S = 0x6,
10565 SUXC1 = 0x6,
10566 ADDR_PS = 0x6,
10567 PREFX = 0x6,
10568
10569 MULR_PS = 0x7,
10570
10571 MADD_S = 0x01,
10572 MADD_D = 0x09,
10573 MADD_PS = 0x11,
10574 ALNV_PS = 0x19,
10575 MSUB_S = 0x21,
10576 MSUB_D = 0x29,
10577 MSUB_PS = 0x31,
10578
10579 NMADD_S = 0x02,
10580 NMADD_D = 0x0a,
10581 NMADD_PS = 0x12,
10582 NMSUB_S = 0x22,
10583 NMSUB_D = 0x2a,
10584 NMSUB_PS = 0x32,
10585
10586 POOL32FXF = 0x3b,
10587
10588 CABS_COND_FMT = 0x1c, /* MIPS3D */
10589 C_COND_FMT = 0x3c
10590};
10591
10592/* POOL32Fxf encoding of minor opcode extension field */
10593
10594enum {
10595 CVT_L = 0x04,
10596 RSQRT_FMT = 0x08,
10597 FLOOR_L = 0x0c,
10598 CVT_PW_PS = 0x1c,
10599 CVT_W = 0x24,
10600 SQRT_FMT = 0x28,
10601 FLOOR_W = 0x2c,
10602 CVT_PS_PW = 0x3c,
10603 CFC1 = 0x40,
10604 RECIP_FMT = 0x48,
10605 CEIL_L = 0x4c,
10606 CTC1 = 0x60,
10607 CEIL_W = 0x6c,
10608 MFC1 = 0x80,
10609 CVT_S_PL = 0x84,
10610 TRUNC_L = 0x8c,
10611 MTC1 = 0xa0,
10612 CVT_S_PU = 0xa4,
10613 TRUNC_W = 0xac,
10614 MFHC1 = 0xc0,
10615 ROUND_L = 0xcc,
10616 MTHC1 = 0xe0,
10617 ROUND_W = 0xec,
10618
10619 MOV_FMT = 0x01,
10620 MOVF = 0x05,
10621 ABS_FMT = 0x0d,
10622 RSQRT1_FMT = 0x1d,
10623 MOVT = 0x25,
10624 NEG_FMT = 0x2d,
10625 CVT_D = 0x4d,
10626 RECIP1_FMT = 0x5d,
10627 CVT_S = 0x6d
10628};
10629
10630/* POOL32I encoding of minor opcode field (bits 25..21) */
10631
10632enum {
10633 BLTZ = 0x00,
10634 BLTZAL = 0x01,
10635 BGEZ = 0x02,
10636 BGEZAL = 0x03,
10637 BLEZ = 0x04,
10638 BNEZC = 0x05,
10639 BGTZ = 0x06,
10640 BEQZC = 0x07,
10641 TLTI = 0x08,
10642 TGEI = 0x09,
10643 TLTIU = 0x0a,
10644 TGEIU = 0x0b,
10645 TNEI = 0x0c,
10646 LUI = 0x0d,
10647 TEQI = 0x0e,
10648 SYNCI = 0x10,
10649 BLTZALS = 0x11,
10650 BGEZALS = 0x13,
10651 BC2F = 0x14,
10652 BC2T = 0x15,
10653 BPOSGE64 = 0x1a,
10654 BPOSGE32 = 0x1b,
10655 /* These overlap and are distinguished by bit16 of the instruction */
10656 BC1F = 0x1c,
10657 BC1T = 0x1d,
10658 BC1ANY2F = 0x1c,
10659 BC1ANY2T = 0x1d,
10660 BC1ANY4F = 0x1e,
10661 BC1ANY4T = 0x1f
10662};
10663
10664/* POOL16A encoding of minor opcode field */
10665
10666enum {
10667 ADDU16 = 0x0,
10668 SUBU16 = 0x1
10669};
10670
10671/* POOL16B encoding of minor opcode field */
10672
10673enum {
10674 SLL16 = 0x0,
10675 SRL16 = 0x1
10676};
10677
10678/* POOL16C encoding of minor opcode field */
10679
10680enum {
10681 NOT16 = 0x00,
10682 XOR16 = 0x04,
10683 AND16 = 0x08,
10684 OR16 = 0x0c,
10685 LWM16 = 0x10,
10686 SWM16 = 0x14,
10687 JR16 = 0x18,
10688 JRC16 = 0x1a,
10689 JALR16 = 0x1c,
10690 JALR16S = 0x1e,
10691 MFHI16 = 0x20,
10692 MFLO16 = 0x24,
10693 BREAK16 = 0x28,
10694 SDBBP16 = 0x2c,
10695 JRADDIUSP = 0x30
10696};
10697
10698/* POOL16D encoding of minor opcode field */
10699
10700enum {
10701 ADDIUS5 = 0x0,
10702 ADDIUSP = 0x1
10703};
10704
10705/* POOL16E encoding of minor opcode field */
10706
10707enum {
10708 ADDIUR2 = 0x0,
10709 ADDIUR1SP = 0x1
10710};
10711
10712static int mmreg (int r)
10713{
10714 static const int map[] = { 16, 17, 2, 3, 4, 5, 6, 7 };
10715
10716 return map[r];
10717}
10718
10719/* Used for 16-bit store instructions. */
10720static int mmreg2 (int r)
10721{
10722 static const int map[] = { 0, 17, 2, 3, 4, 5, 6, 7 };
10723
10724 return map[r];
10725}
10726
10727#define uMIPS_RD(op) ((op >> 7) & 0x7)
10728#define uMIPS_RS(op) ((op >> 4) & 0x7)
10729#define uMIPS_RS2(op) uMIPS_RS(op)
10730#define uMIPS_RS1(op) ((op >> 1) & 0x7)
10731#define uMIPS_RD5(op) ((op >> 5) & 0x1f)
10732#define uMIPS_RS5(op) (op & 0x1f)
10733
10734/* Signed immediate */
10735#define SIMM(op, start, width) \
10736 ((int32_t)(((op >> start) & ((~0U) >> (32-width))) \
10737 << (32-width)) \
10738 >> (32-width))
10739/* Zero-extended immediate */
10740#define ZIMM(op, start, width) ((op >> start) & ((~0U) >> (32-width)))
10741
Aurelien Jarnod75c1352013-01-01 18:02:22 +010010742static void gen_addiur1sp(DisasContext *ctx)
Nathan Froyd3c824102010-06-08 13:29:59 -070010743{
10744 int rd = mmreg(uMIPS_RD(ctx->opcode));
10745
Aurelien Jarnod75c1352013-01-01 18:02:22 +010010746 gen_arith_imm(ctx, OPC_ADDIU, rd, 29, ((ctx->opcode >> 1) & 0x3f) << 2);
Nathan Froyd3c824102010-06-08 13:29:59 -070010747}
10748
Aurelien Jarnod75c1352013-01-01 18:02:22 +010010749static void gen_addiur2(DisasContext *ctx)
Nathan Froyd3c824102010-06-08 13:29:59 -070010750{
10751 static const int decoded_imm[] = { 1, 4, 8, 12, 16, 20, 24, -1 };
10752 int rd = mmreg(uMIPS_RD(ctx->opcode));
10753 int rs = mmreg(uMIPS_RS(ctx->opcode));
10754
Aurelien Jarnod75c1352013-01-01 18:02:22 +010010755 gen_arith_imm(ctx, OPC_ADDIU, rd, rs, decoded_imm[ZIMM(ctx->opcode, 1, 3)]);
Nathan Froyd3c824102010-06-08 13:29:59 -070010756}
10757
Aurelien Jarnod75c1352013-01-01 18:02:22 +010010758static void gen_addiusp(DisasContext *ctx)
Nathan Froyd3c824102010-06-08 13:29:59 -070010759{
10760 int encoded = ZIMM(ctx->opcode, 1, 9);
10761 int decoded;
10762
10763 if (encoded <= 1) {
10764 decoded = 256 + encoded;
10765 } else if (encoded <= 255) {
10766 decoded = encoded;
10767 } else if (encoded <= 509) {
10768 decoded = encoded - 512;
10769 } else {
10770 decoded = encoded - 768;
10771 }
10772
Aurelien Jarnod75c1352013-01-01 18:02:22 +010010773 gen_arith_imm(ctx, OPC_ADDIU, 29, 29, decoded << 2);
Nathan Froyd3c824102010-06-08 13:29:59 -070010774}
10775
Aurelien Jarnod75c1352013-01-01 18:02:22 +010010776static void gen_addius5(DisasContext *ctx)
Nathan Froyd3c824102010-06-08 13:29:59 -070010777{
10778 int imm = SIMM(ctx->opcode, 1, 4);
10779 int rd = (ctx->opcode >> 5) & 0x1f;
10780
Aurelien Jarnod75c1352013-01-01 18:02:22 +010010781 gen_arith_imm(ctx, OPC_ADDIU, rd, rd, imm);
Nathan Froyd3c824102010-06-08 13:29:59 -070010782}
10783
Aurelien Jarnod75c1352013-01-01 18:02:22 +010010784static void gen_andi16(DisasContext *ctx)
Nathan Froyd3c824102010-06-08 13:29:59 -070010785{
10786 static const int decoded_imm[] = { 128, 1, 2, 3, 4, 7, 8, 15, 16,
10787 31, 32, 63, 64, 255, 32768, 65535 };
10788 int rd = mmreg(uMIPS_RD(ctx->opcode));
10789 int rs = mmreg(uMIPS_RS(ctx->opcode));
10790 int encoded = ZIMM(ctx->opcode, 0, 4);
10791
Aurelien Jarnod75c1352013-01-01 18:02:22 +010010792 gen_logic_imm(ctx, OPC_ANDI, rd, rs, decoded_imm[encoded]);
Nathan Froyd3c824102010-06-08 13:29:59 -070010793}
10794
10795static void gen_ldst_multiple (DisasContext *ctx, uint32_t opc, int reglist,
10796 int base, int16_t offset)
10797{
Richard Hendersone1050a72012-09-18 21:55:32 -070010798 const char *opn = "ldst_multiple";
Nathan Froyd3c824102010-06-08 13:29:59 -070010799 TCGv t0, t1;
10800 TCGv_i32 t2;
10801
10802 if (ctx->hflags & MIPS_HFLAG_BMASK) {
10803 generate_exception(ctx, EXCP_RI);
10804 return;
10805 }
10806
10807 t0 = tcg_temp_new();
10808
10809 gen_base_offset_addr(ctx, t0, base, offset);
10810
10811 t1 = tcg_const_tl(reglist);
10812 t2 = tcg_const_i32(ctx->mem_idx);
10813
10814 save_cpu_state(ctx, 1);
10815 switch (opc) {
10816 case LWM32:
Blue Swirl895c2d02012-09-02 14:52:59 +000010817 gen_helper_lwm(cpu_env, t0, t1, t2);
Richard Hendersone1050a72012-09-18 21:55:32 -070010818 opn = "lwm";
Nathan Froyd3c824102010-06-08 13:29:59 -070010819 break;
10820 case SWM32:
Blue Swirl895c2d02012-09-02 14:52:59 +000010821 gen_helper_swm(cpu_env, t0, t1, t2);
Richard Hendersone1050a72012-09-18 21:55:32 -070010822 opn = "swm";
Nathan Froyd3c824102010-06-08 13:29:59 -070010823 break;
10824#ifdef TARGET_MIPS64
10825 case LDM:
Blue Swirl895c2d02012-09-02 14:52:59 +000010826 gen_helper_ldm(cpu_env, t0, t1, t2);
Richard Hendersone1050a72012-09-18 21:55:32 -070010827 opn = "ldm";
Nathan Froyd3c824102010-06-08 13:29:59 -070010828 break;
10829 case SDM:
Blue Swirl895c2d02012-09-02 14:52:59 +000010830 gen_helper_sdm(cpu_env, t0, t1, t2);
Richard Hendersone1050a72012-09-18 21:55:32 -070010831 opn = "sdm";
Nathan Froyd3c824102010-06-08 13:29:59 -070010832 break;
10833#endif
10834 }
Richard Hendersone1050a72012-09-18 21:55:32 -070010835 (void)opn;
Nathan Froyd3c824102010-06-08 13:29:59 -070010836 MIPS_DEBUG("%s, %x, %d(%s)", opn, reglist, offset, regnames[base]);
10837 tcg_temp_free(t0);
Stefan Weil33087592010-06-09 22:09:40 +020010838 tcg_temp_free(t1);
Nathan Froyd3c824102010-06-08 13:29:59 -070010839 tcg_temp_free_i32(t2);
10840}
10841
10842
Aurelien Jarnod75c1352013-01-01 18:02:22 +010010843static void gen_pool16c_insn(DisasContext *ctx, int *is_branch)
Nathan Froyd3c824102010-06-08 13:29:59 -070010844{
10845 int rd = mmreg((ctx->opcode >> 3) & 0x7);
10846 int rs = mmreg(ctx->opcode & 0x7);
10847 int opc;
10848
10849 switch (((ctx->opcode) >> 4) & 0x3f) {
10850 case NOT16 + 0:
10851 case NOT16 + 1:
10852 case NOT16 + 2:
10853 case NOT16 + 3:
Aurelien Jarnod75c1352013-01-01 18:02:22 +010010854 gen_logic(ctx, OPC_NOR, rd, rs, 0);
Nathan Froyd3c824102010-06-08 13:29:59 -070010855 break;
10856 case XOR16 + 0:
10857 case XOR16 + 1:
10858 case XOR16 + 2:
10859 case XOR16 + 3:
Aurelien Jarnod75c1352013-01-01 18:02:22 +010010860 gen_logic(ctx, OPC_XOR, rd, rd, rs);
Nathan Froyd3c824102010-06-08 13:29:59 -070010861 break;
10862 case AND16 + 0:
10863 case AND16 + 1:
10864 case AND16 + 2:
10865 case AND16 + 3:
Aurelien Jarnod75c1352013-01-01 18:02:22 +010010866 gen_logic(ctx, OPC_AND, rd, rd, rs);
Nathan Froyd3c824102010-06-08 13:29:59 -070010867 break;
10868 case OR16 + 0:
10869 case OR16 + 1:
10870 case OR16 + 2:
10871 case OR16 + 3:
Aurelien Jarnod75c1352013-01-01 18:02:22 +010010872 gen_logic(ctx, OPC_OR, rd, rd, rs);
Nathan Froyd3c824102010-06-08 13:29:59 -070010873 break;
10874 case LWM16 + 0:
10875 case LWM16 + 1:
10876 case LWM16 + 2:
10877 case LWM16 + 3:
10878 {
10879 static const int lwm_convert[] = { 0x11, 0x12, 0x13, 0x14 };
10880 int offset = ZIMM(ctx->opcode, 0, 4);
10881
10882 gen_ldst_multiple(ctx, LWM32, lwm_convert[(ctx->opcode >> 4) & 0x3],
10883 29, offset << 2);
10884 }
10885 break;
10886 case SWM16 + 0:
10887 case SWM16 + 1:
10888 case SWM16 + 2:
10889 case SWM16 + 3:
10890 {
10891 static const int swm_convert[] = { 0x11, 0x12, 0x13, 0x14 };
10892 int offset = ZIMM(ctx->opcode, 0, 4);
10893
10894 gen_ldst_multiple(ctx, SWM32, swm_convert[(ctx->opcode >> 4) & 0x3],
10895 29, offset << 2);
10896 }
10897 break;
10898 case JR16 + 0:
10899 case JR16 + 1:
10900 {
10901 int reg = ctx->opcode & 0x1f;
10902
10903 gen_compute_branch(ctx, OPC_JR, 2, reg, 0, 0);
10904 }
10905 *is_branch = 1;
10906 break;
10907 case JRC16 + 0:
10908 case JRC16 + 1:
10909 {
10910 int reg = ctx->opcode & 0x1f;
10911
10912 gen_compute_branch(ctx, OPC_JR, 2, reg, 0, 0);
10913 /* Let normal delay slot handling in our caller take us
10914 to the branch target. */
10915 }
10916 break;
10917 case JALR16 + 0:
10918 case JALR16 + 1:
10919 opc = OPC_JALR;
10920 goto do_jalr;
10921 case JALR16S + 0:
10922 case JALR16S + 1:
10923 opc = OPC_JALRS;
10924 do_jalr:
10925 {
10926 int reg = ctx->opcode & 0x1f;
10927
10928 gen_compute_branch(ctx, opc, 2, reg, 31, 0);
10929 }
10930 *is_branch = 1;
10931 break;
10932 case MFHI16 + 0:
10933 case MFHI16 + 1:
10934 gen_HILO(ctx, OPC_MFHI, uMIPS_RS5(ctx->opcode));
10935 break;
10936 case MFLO16 + 0:
10937 case MFLO16 + 1:
10938 gen_HILO(ctx, OPC_MFLO, uMIPS_RS5(ctx->opcode));
10939 break;
10940 case BREAK16:
10941 generate_exception(ctx, EXCP_BREAK);
10942 break;
10943 case SDBBP16:
10944 /* XXX: not clear which exception should be raised
10945 * when in debug mode...
10946 */
Aurelien Jarnod75c1352013-01-01 18:02:22 +010010947 check_insn(ctx, ISA_MIPS32);
Nathan Froyd3c824102010-06-08 13:29:59 -070010948 if (!(ctx->hflags & MIPS_HFLAG_DM)) {
10949 generate_exception(ctx, EXCP_DBp);
10950 } else {
10951 generate_exception(ctx, EXCP_DBp);
10952 }
10953 break;
10954 case JRADDIUSP + 0:
10955 case JRADDIUSP + 1:
10956 {
10957 int imm = ZIMM(ctx->opcode, 0, 5);
10958
10959 gen_compute_branch(ctx, OPC_JR, 2, 31, 0, 0);
Aurelien Jarnod75c1352013-01-01 18:02:22 +010010960 gen_arith_imm(ctx, OPC_ADDIU, 29, 29, imm << 2);
Nathan Froyd3c824102010-06-08 13:29:59 -070010961 /* Let normal delay slot handling in our caller take us
10962 to the branch target. */
10963 }
10964 break;
10965 default:
10966 generate_exception(ctx, EXCP_RI);
10967 break;
10968 }
10969}
10970
10971static void gen_ldxs (DisasContext *ctx, int base, int index, int rd)
10972{
10973 TCGv t0 = tcg_temp_new();
10974 TCGv t1 = tcg_temp_new();
10975
10976 gen_load_gpr(t0, base);
10977
10978 if (index != 0) {
10979 gen_load_gpr(t1, index);
10980 tcg_gen_shli_tl(t1, t1, 2);
10981 gen_op_addr_add(ctx, t0, t1, t0);
10982 }
10983
Aurelien Jarno2910c6cb2012-10-09 21:53:20 +020010984 tcg_gen_qemu_ld32s(t1, t0, ctx->mem_idx);
Nathan Froyd3c824102010-06-08 13:29:59 -070010985 gen_store_gpr(t1, rd);
10986
10987 tcg_temp_free(t0);
10988 tcg_temp_free(t1);
10989}
10990
10991static void gen_ldst_pair (DisasContext *ctx, uint32_t opc, int rd,
10992 int base, int16_t offset)
10993{
10994 const char *opn = "ldst_pair";
10995 TCGv t0, t1;
10996
Eric Johnson36c67112011-09-17 17:28:16 -070010997 if (ctx->hflags & MIPS_HFLAG_BMASK || rd == 31) {
Nathan Froyd3c824102010-06-08 13:29:59 -070010998 generate_exception(ctx, EXCP_RI);
10999 return;
11000 }
11001
11002 t0 = tcg_temp_new();
11003 t1 = tcg_temp_new();
11004
11005 gen_base_offset_addr(ctx, t0, base, offset);
11006
11007 switch (opc) {
11008 case LWP:
Eric Johnson36c67112011-09-17 17:28:16 -070011009 if (rd == base) {
11010 generate_exception(ctx, EXCP_RI);
11011 return;
11012 }
Aurelien Jarno2910c6cb2012-10-09 21:53:20 +020011013 tcg_gen_qemu_ld32s(t1, t0, ctx->mem_idx);
Nathan Froyd3c824102010-06-08 13:29:59 -070011014 gen_store_gpr(t1, rd);
11015 tcg_gen_movi_tl(t1, 4);
11016 gen_op_addr_add(ctx, t0, t0, t1);
Aurelien Jarno2910c6cb2012-10-09 21:53:20 +020011017 tcg_gen_qemu_ld32s(t1, t0, ctx->mem_idx);
Nathan Froyd3c824102010-06-08 13:29:59 -070011018 gen_store_gpr(t1, rd+1);
11019 opn = "lwp";
11020 break;
11021 case SWP:
Nathan Froyd3c824102010-06-08 13:29:59 -070011022 gen_load_gpr(t1, rd);
Aurelien Jarno2910c6cb2012-10-09 21:53:20 +020011023 tcg_gen_qemu_st32(t1, t0, ctx->mem_idx);
Nathan Froyd3c824102010-06-08 13:29:59 -070011024 tcg_gen_movi_tl(t1, 4);
11025 gen_op_addr_add(ctx, t0, t0, t1);
11026 gen_load_gpr(t1, rd+1);
Aurelien Jarno2910c6cb2012-10-09 21:53:20 +020011027 tcg_gen_qemu_st32(t1, t0, ctx->mem_idx);
Nathan Froyd3c824102010-06-08 13:29:59 -070011028 opn = "swp";
11029 break;
11030#ifdef TARGET_MIPS64
11031 case LDP:
Eric Johnson36c67112011-09-17 17:28:16 -070011032 if (rd == base) {
11033 generate_exception(ctx, EXCP_RI);
11034 return;
11035 }
Aurelien Jarno2910c6cb2012-10-09 21:53:20 +020011036 tcg_gen_qemu_ld64(t1, t0, ctx->mem_idx);
Nathan Froyd3c824102010-06-08 13:29:59 -070011037 gen_store_gpr(t1, rd);
11038 tcg_gen_movi_tl(t1, 8);
11039 gen_op_addr_add(ctx, t0, t0, t1);
Aurelien Jarno2910c6cb2012-10-09 21:53:20 +020011040 tcg_gen_qemu_ld64(t1, t0, ctx->mem_idx);
Nathan Froyd3c824102010-06-08 13:29:59 -070011041 gen_store_gpr(t1, rd+1);
11042 opn = "ldp";
11043 break;
11044 case SDP:
Nathan Froyd3c824102010-06-08 13:29:59 -070011045 gen_load_gpr(t1, rd);
Aurelien Jarno2910c6cb2012-10-09 21:53:20 +020011046 tcg_gen_qemu_st64(t1, t0, ctx->mem_idx);
Nathan Froyd3c824102010-06-08 13:29:59 -070011047 tcg_gen_movi_tl(t1, 8);
11048 gen_op_addr_add(ctx, t0, t0, t1);
11049 gen_load_gpr(t1, rd+1);
Aurelien Jarno2910c6cb2012-10-09 21:53:20 +020011050 tcg_gen_qemu_st64(t1, t0, ctx->mem_idx);
Nathan Froyd3c824102010-06-08 13:29:59 -070011051 opn = "sdp";
11052 break;
11053#endif
11054 }
Blue Swirl2abf3142010-10-13 18:38:08 +000011055 (void)opn; /* avoid a compiler warning */
Nathan Froyd3c824102010-06-08 13:29:59 -070011056 MIPS_DEBUG("%s, %s, %d(%s)", opn, regnames[rd], offset, regnames[base]);
11057 tcg_temp_free(t0);
11058 tcg_temp_free(t1);
11059}
11060
Andreas Färber7db13fa2012-03-14 01:38:22 +010011061static void gen_pool32axf (CPUMIPSState *env, DisasContext *ctx, int rt, int rs,
Nathan Froyd3c824102010-06-08 13:29:59 -070011062 int *is_branch)
11063{
11064 int extension = (ctx->opcode >> 6) & 0x3f;
11065 int minor = (ctx->opcode >> 12) & 0xf;
11066 uint32_t mips32_op;
11067
11068 switch (extension) {
11069 case TEQ:
11070 mips32_op = OPC_TEQ;
11071 goto do_trap;
11072 case TGE:
11073 mips32_op = OPC_TGE;
11074 goto do_trap;
11075 case TGEU:
11076 mips32_op = OPC_TGEU;
11077 goto do_trap;
11078 case TLT:
11079 mips32_op = OPC_TLT;
11080 goto do_trap;
11081 case TLTU:
11082 mips32_op = OPC_TLTU;
11083 goto do_trap;
11084 case TNE:
11085 mips32_op = OPC_TNE;
11086 do_trap:
11087 gen_trap(ctx, mips32_op, rs, rt, -1);
11088 break;
11089#ifndef CONFIG_USER_ONLY
11090 case MFC0:
11091 case MFC0 + 32:
Eric Johnson2e154972011-09-17 17:05:32 -070011092 check_cp0_enabled(ctx);
Nathan Froyd3c824102010-06-08 13:29:59 -070011093 if (rt == 0) {
11094 /* Treat as NOP. */
11095 break;
11096 }
Aurelien Jarnod75c1352013-01-01 18:02:22 +010011097 gen_mfc0(ctx, cpu_gpr[rt], rs, (ctx->opcode >> 11) & 0x7);
Nathan Froyd3c824102010-06-08 13:29:59 -070011098 break;
11099 case MTC0:
11100 case MTC0 + 32:
Eric Johnson2e154972011-09-17 17:05:32 -070011101 check_cp0_enabled(ctx);
Nathan Froyd3c824102010-06-08 13:29:59 -070011102 {
11103 TCGv t0 = tcg_temp_new();
11104
11105 gen_load_gpr(t0, rt);
Aurelien Jarnod75c1352013-01-01 18:02:22 +010011106 gen_mtc0(ctx, t0, rs, (ctx->opcode >> 11) & 0x7);
Nathan Froyd3c824102010-06-08 13:29:59 -070011107 tcg_temp_free(t0);
11108 }
11109 break;
11110#endif
11111 case 0x2c:
11112 switch (minor) {
11113 case SEB:
11114 gen_bshfl(ctx, OPC_SEB, rs, rt);
11115 break;
11116 case SEH:
11117 gen_bshfl(ctx, OPC_SEH, rs, rt);
11118 break;
11119 case CLO:
11120 mips32_op = OPC_CLO;
11121 goto do_cl;
11122 case CLZ:
11123 mips32_op = OPC_CLZ;
11124 do_cl:
Aurelien Jarnod75c1352013-01-01 18:02:22 +010011125 check_insn(ctx, ISA_MIPS32);
Nathan Froyd3c824102010-06-08 13:29:59 -070011126 gen_cl(ctx, mips32_op, rt, rs);
11127 break;
11128 case RDHWR:
Aurelien Jarnod75c1352013-01-01 18:02:22 +010011129 gen_rdhwr(ctx, rt, rs);
Nathan Froyd3c824102010-06-08 13:29:59 -070011130 break;
11131 case WSBH:
11132 gen_bshfl(ctx, OPC_WSBH, rs, rt);
11133 break;
11134 case MULT:
11135 mips32_op = OPC_MULT;
11136 goto do_muldiv;
11137 case MULTU:
11138 mips32_op = OPC_MULTU;
11139 goto do_muldiv;
11140 case DIV:
11141 mips32_op = OPC_DIV;
11142 goto do_muldiv;
11143 case DIVU:
11144 mips32_op = OPC_DIVU;
11145 goto do_muldiv;
11146 case MADD:
11147 mips32_op = OPC_MADD;
11148 goto do_muldiv;
11149 case MADDU:
11150 mips32_op = OPC_MADDU;
11151 goto do_muldiv;
11152 case MSUB:
11153 mips32_op = OPC_MSUB;
11154 goto do_muldiv;
11155 case MSUBU:
11156 mips32_op = OPC_MSUBU;
11157 do_muldiv:
Aurelien Jarnod75c1352013-01-01 18:02:22 +010011158 check_insn(ctx, ISA_MIPS32);
Nathan Froyd3c824102010-06-08 13:29:59 -070011159 gen_muldiv(ctx, mips32_op, rs, rt);
11160 break;
11161 default:
11162 goto pool32axf_invalid;
11163 }
11164 break;
11165 case 0x34:
11166 switch (minor) {
11167 case MFC2:
11168 case MTC2:
11169 case MFHC2:
11170 case MTHC2:
11171 case CFC2:
11172 case CTC2:
11173 generate_exception_err(ctx, EXCP_CpU, 2);
11174 break;
11175 default:
11176 goto pool32axf_invalid;
11177 }
11178 break;
11179 case 0x3c:
11180 switch (minor) {
11181 case JALR:
11182 case JALR_HB:
11183 gen_compute_branch (ctx, OPC_JALR, 4, rs, rt, 0);
11184 *is_branch = 1;
11185 break;
11186 case JALRS:
11187 case JALRS_HB:
11188 gen_compute_branch (ctx, OPC_JALRS, 4, rs, rt, 0);
11189 *is_branch = 1;
11190 break;
11191 default:
11192 goto pool32axf_invalid;
11193 }
11194 break;
11195 case 0x05:
11196 switch (minor) {
11197 case RDPGPR:
Eric Johnson2e154972011-09-17 17:05:32 -070011198 check_cp0_enabled(ctx);
Aurelien Jarnod75c1352013-01-01 18:02:22 +010011199 check_insn(ctx, ISA_MIPS32R2);
Nathan Froyd3c824102010-06-08 13:29:59 -070011200 gen_load_srsgpr(rt, rs);
11201 break;
11202 case WRPGPR:
Eric Johnson2e154972011-09-17 17:05:32 -070011203 check_cp0_enabled(ctx);
Aurelien Jarnod75c1352013-01-01 18:02:22 +010011204 check_insn(ctx, ISA_MIPS32R2);
Nathan Froyd3c824102010-06-08 13:29:59 -070011205 gen_store_srsgpr(rt, rs);
11206 break;
11207 default:
11208 goto pool32axf_invalid;
11209 }
11210 break;
11211#ifndef CONFIG_USER_ONLY
11212 case 0x0d:
11213 switch (minor) {
11214 case TLBP:
11215 mips32_op = OPC_TLBP;
11216 goto do_cp0;
11217 case TLBR:
11218 mips32_op = OPC_TLBR;
11219 goto do_cp0;
11220 case TLBWI:
11221 mips32_op = OPC_TLBWI;
11222 goto do_cp0;
11223 case TLBWR:
11224 mips32_op = OPC_TLBWR;
11225 goto do_cp0;
11226 case WAIT:
11227 mips32_op = OPC_WAIT;
11228 goto do_cp0;
11229 case DERET:
11230 mips32_op = OPC_DERET;
11231 goto do_cp0;
11232 case ERET:
11233 mips32_op = OPC_ERET;
11234 do_cp0:
11235 gen_cp0(env, ctx, mips32_op, rt, rs);
11236 break;
11237 default:
11238 goto pool32axf_invalid;
11239 }
11240 break;
11241 case 0x1d:
11242 switch (minor) {
11243 case DI:
Eric Johnson2e154972011-09-17 17:05:32 -070011244 check_cp0_enabled(ctx);
Nathan Froyd3c824102010-06-08 13:29:59 -070011245 {
11246 TCGv t0 = tcg_temp_new();
11247
11248 save_cpu_state(ctx, 1);
Blue Swirl895c2d02012-09-02 14:52:59 +000011249 gen_helper_di(t0, cpu_env);
Nathan Froyd3c824102010-06-08 13:29:59 -070011250 gen_store_gpr(t0, rs);
11251 /* Stop translation as we may have switched the execution mode */
11252 ctx->bstate = BS_STOP;
11253 tcg_temp_free(t0);
11254 }
11255 break;
11256 case EI:
Eric Johnson2e154972011-09-17 17:05:32 -070011257 check_cp0_enabled(ctx);
Nathan Froyd3c824102010-06-08 13:29:59 -070011258 {
11259 TCGv t0 = tcg_temp_new();
11260
11261 save_cpu_state(ctx, 1);
Blue Swirl895c2d02012-09-02 14:52:59 +000011262 gen_helper_ei(t0, cpu_env);
Nathan Froyd3c824102010-06-08 13:29:59 -070011263 gen_store_gpr(t0, rs);
11264 /* Stop translation as we may have switched the execution mode */
11265 ctx->bstate = BS_STOP;
11266 tcg_temp_free(t0);
11267 }
11268 break;
11269 default:
11270 goto pool32axf_invalid;
11271 }
11272 break;
11273#endif
11274 case 0x2d:
11275 switch (minor) {
11276 case SYNC:
11277 /* NOP */
11278 break;
11279 case SYSCALL:
11280 generate_exception(ctx, EXCP_SYSCALL);
11281 ctx->bstate = BS_STOP;
11282 break;
11283 case SDBBP:
Aurelien Jarnod75c1352013-01-01 18:02:22 +010011284 check_insn(ctx, ISA_MIPS32);
Nathan Froyd3c824102010-06-08 13:29:59 -070011285 if (!(ctx->hflags & MIPS_HFLAG_DM)) {
11286 generate_exception(ctx, EXCP_DBp);
11287 } else {
11288 generate_exception(ctx, EXCP_DBp);
11289 }
11290 break;
11291 default:
11292 goto pool32axf_invalid;
11293 }
11294 break;
11295 case 0x35:
11296 switch (minor) {
11297 case MFHI32:
11298 gen_HILO(ctx, OPC_MFHI, rs);
11299 break;
11300 case MFLO32:
11301 gen_HILO(ctx, OPC_MFLO, rs);
11302 break;
11303 case MTHI32:
11304 gen_HILO(ctx, OPC_MTHI, rs);
11305 break;
11306 case MTLO32:
11307 gen_HILO(ctx, OPC_MTLO, rs);
11308 break;
11309 default:
11310 goto pool32axf_invalid;
11311 }
11312 break;
11313 default:
11314 pool32axf_invalid:
11315 MIPS_INVAL("pool32axf");
11316 generate_exception(ctx, EXCP_RI);
11317 break;
11318 }
11319}
11320
11321/* Values for microMIPS fmt field. Variable-width, depending on which
11322 formats the instruction supports. */
11323
11324enum {
11325 FMT_SD_S = 0,
11326 FMT_SD_D = 1,
11327
11328 FMT_SDPS_S = 0,
11329 FMT_SDPS_D = 1,
11330 FMT_SDPS_PS = 2,
11331
11332 FMT_SWL_S = 0,
11333 FMT_SWL_W = 1,
11334 FMT_SWL_L = 2,
11335
11336 FMT_DWL_D = 0,
11337 FMT_DWL_W = 1,
11338 FMT_DWL_L = 2
11339};
11340
Aurelien Jarnod75c1352013-01-01 18:02:22 +010011341static void gen_pool32fxf(DisasContext *ctx, int rt, int rs)
Nathan Froyd3c824102010-06-08 13:29:59 -070011342{
11343 int extension = (ctx->opcode >> 6) & 0x3ff;
11344 uint32_t mips32_op;
11345
11346#define FLOAT_1BIT_FMT(opc, fmt) (fmt << 8) | opc
11347#define FLOAT_2BIT_FMT(opc, fmt) (fmt << 7) | opc
11348#define COND_FLOAT_MOV(opc, cond) (cond << 7) | opc
11349
11350 switch (extension) {
11351 case FLOAT_1BIT_FMT(CFC1, 0):
11352 mips32_op = OPC_CFC1;
11353 goto do_cp1;
11354 case FLOAT_1BIT_FMT(CTC1, 0):
11355 mips32_op = OPC_CTC1;
11356 goto do_cp1;
11357 case FLOAT_1BIT_FMT(MFC1, 0):
11358 mips32_op = OPC_MFC1;
11359 goto do_cp1;
11360 case FLOAT_1BIT_FMT(MTC1, 0):
11361 mips32_op = OPC_MTC1;
11362 goto do_cp1;
11363 case FLOAT_1BIT_FMT(MFHC1, 0):
11364 mips32_op = OPC_MFHC1;
11365 goto do_cp1;
11366 case FLOAT_1BIT_FMT(MTHC1, 0):
11367 mips32_op = OPC_MTHC1;
11368 do_cp1:
11369 gen_cp1(ctx, mips32_op, rt, rs);
11370 break;
11371
11372 /* Reciprocal square root */
11373 case FLOAT_1BIT_FMT(RSQRT_FMT, FMT_SD_S):
11374 mips32_op = OPC_RSQRT_S;
11375 goto do_unaryfp;
11376 case FLOAT_1BIT_FMT(RSQRT_FMT, FMT_SD_D):
11377 mips32_op = OPC_RSQRT_D;
11378 goto do_unaryfp;
11379
11380 /* Square root */
11381 case FLOAT_1BIT_FMT(SQRT_FMT, FMT_SD_S):
11382 mips32_op = OPC_SQRT_S;
11383 goto do_unaryfp;
11384 case FLOAT_1BIT_FMT(SQRT_FMT, FMT_SD_D):
11385 mips32_op = OPC_SQRT_D;
11386 goto do_unaryfp;
11387
11388 /* Reciprocal */
11389 case FLOAT_1BIT_FMT(RECIP_FMT, FMT_SD_S):
11390 mips32_op = OPC_RECIP_S;
11391 goto do_unaryfp;
11392 case FLOAT_1BIT_FMT(RECIP_FMT, FMT_SD_D):
11393 mips32_op = OPC_RECIP_D;
11394 goto do_unaryfp;
11395
11396 /* Floor */
11397 case FLOAT_1BIT_FMT(FLOOR_L, FMT_SD_S):
11398 mips32_op = OPC_FLOOR_L_S;
11399 goto do_unaryfp;
11400 case FLOAT_1BIT_FMT(FLOOR_L, FMT_SD_D):
11401 mips32_op = OPC_FLOOR_L_D;
11402 goto do_unaryfp;
11403 case FLOAT_1BIT_FMT(FLOOR_W, FMT_SD_S):
11404 mips32_op = OPC_FLOOR_W_S;
11405 goto do_unaryfp;
11406 case FLOAT_1BIT_FMT(FLOOR_W, FMT_SD_D):
11407 mips32_op = OPC_FLOOR_W_D;
11408 goto do_unaryfp;
11409
11410 /* Ceiling */
11411 case FLOAT_1BIT_FMT(CEIL_L, FMT_SD_S):
11412 mips32_op = OPC_CEIL_L_S;
11413 goto do_unaryfp;
11414 case FLOAT_1BIT_FMT(CEIL_L, FMT_SD_D):
11415 mips32_op = OPC_CEIL_L_D;
11416 goto do_unaryfp;
11417 case FLOAT_1BIT_FMT(CEIL_W, FMT_SD_S):
11418 mips32_op = OPC_CEIL_W_S;
11419 goto do_unaryfp;
11420 case FLOAT_1BIT_FMT(CEIL_W, FMT_SD_D):
11421 mips32_op = OPC_CEIL_W_D;
11422 goto do_unaryfp;
11423
11424 /* Truncation */
11425 case FLOAT_1BIT_FMT(TRUNC_L, FMT_SD_S):
11426 mips32_op = OPC_TRUNC_L_S;
11427 goto do_unaryfp;
11428 case FLOAT_1BIT_FMT(TRUNC_L, FMT_SD_D):
11429 mips32_op = OPC_TRUNC_L_D;
11430 goto do_unaryfp;
11431 case FLOAT_1BIT_FMT(TRUNC_W, FMT_SD_S):
11432 mips32_op = OPC_TRUNC_W_S;
11433 goto do_unaryfp;
11434 case FLOAT_1BIT_FMT(TRUNC_W, FMT_SD_D):
11435 mips32_op = OPC_TRUNC_W_D;
11436 goto do_unaryfp;
11437
11438 /* Round */
11439 case FLOAT_1BIT_FMT(ROUND_L, FMT_SD_S):
11440 mips32_op = OPC_ROUND_L_S;
11441 goto do_unaryfp;
11442 case FLOAT_1BIT_FMT(ROUND_L, FMT_SD_D):
11443 mips32_op = OPC_ROUND_L_D;
11444 goto do_unaryfp;
11445 case FLOAT_1BIT_FMT(ROUND_W, FMT_SD_S):
11446 mips32_op = OPC_ROUND_W_S;
11447 goto do_unaryfp;
11448 case FLOAT_1BIT_FMT(ROUND_W, FMT_SD_D):
11449 mips32_op = OPC_ROUND_W_D;
11450 goto do_unaryfp;
11451
11452 /* Integer to floating-point conversion */
11453 case FLOAT_1BIT_FMT(CVT_L, FMT_SD_S):
11454 mips32_op = OPC_CVT_L_S;
11455 goto do_unaryfp;
11456 case FLOAT_1BIT_FMT(CVT_L, FMT_SD_D):
11457 mips32_op = OPC_CVT_L_D;
11458 goto do_unaryfp;
11459 case FLOAT_1BIT_FMT(CVT_W, FMT_SD_S):
11460 mips32_op = OPC_CVT_W_S;
11461 goto do_unaryfp;
11462 case FLOAT_1BIT_FMT(CVT_W, FMT_SD_D):
11463 mips32_op = OPC_CVT_W_D;
11464 goto do_unaryfp;
11465
11466 /* Paired-foo conversions */
11467 case FLOAT_1BIT_FMT(CVT_S_PL, 0):
11468 mips32_op = OPC_CVT_S_PL;
11469 goto do_unaryfp;
11470 case FLOAT_1BIT_FMT(CVT_S_PU, 0):
11471 mips32_op = OPC_CVT_S_PU;
11472 goto do_unaryfp;
11473 case FLOAT_1BIT_FMT(CVT_PW_PS, 0):
11474 mips32_op = OPC_CVT_PW_PS;
11475 goto do_unaryfp;
11476 case FLOAT_1BIT_FMT(CVT_PS_PW, 0):
11477 mips32_op = OPC_CVT_PS_PW;
11478 goto do_unaryfp;
11479
11480 /* Floating-point moves */
11481 case FLOAT_2BIT_FMT(MOV_FMT, FMT_SDPS_S):
11482 mips32_op = OPC_MOV_S;
11483 goto do_unaryfp;
11484 case FLOAT_2BIT_FMT(MOV_FMT, FMT_SDPS_D):
11485 mips32_op = OPC_MOV_D;
11486 goto do_unaryfp;
11487 case FLOAT_2BIT_FMT(MOV_FMT, FMT_SDPS_PS):
11488 mips32_op = OPC_MOV_PS;
11489 goto do_unaryfp;
11490
11491 /* Absolute value */
11492 case FLOAT_2BIT_FMT(ABS_FMT, FMT_SDPS_S):
11493 mips32_op = OPC_ABS_S;
11494 goto do_unaryfp;
11495 case FLOAT_2BIT_FMT(ABS_FMT, FMT_SDPS_D):
11496 mips32_op = OPC_ABS_D;
11497 goto do_unaryfp;
11498 case FLOAT_2BIT_FMT(ABS_FMT, FMT_SDPS_PS):
11499 mips32_op = OPC_ABS_PS;
11500 goto do_unaryfp;
11501
11502 /* Negation */
11503 case FLOAT_2BIT_FMT(NEG_FMT, FMT_SDPS_S):
11504 mips32_op = OPC_NEG_S;
11505 goto do_unaryfp;
11506 case FLOAT_2BIT_FMT(NEG_FMT, FMT_SDPS_D):
11507 mips32_op = OPC_NEG_D;
11508 goto do_unaryfp;
11509 case FLOAT_2BIT_FMT(NEG_FMT, FMT_SDPS_PS):
11510 mips32_op = OPC_NEG_PS;
11511 goto do_unaryfp;
11512
11513 /* Reciprocal square root step */
11514 case FLOAT_2BIT_FMT(RSQRT1_FMT, FMT_SDPS_S):
11515 mips32_op = OPC_RSQRT1_S;
11516 goto do_unaryfp;
11517 case FLOAT_2BIT_FMT(RSQRT1_FMT, FMT_SDPS_D):
11518 mips32_op = OPC_RSQRT1_D;
11519 goto do_unaryfp;
11520 case FLOAT_2BIT_FMT(RSQRT1_FMT, FMT_SDPS_PS):
11521 mips32_op = OPC_RSQRT1_PS;
11522 goto do_unaryfp;
11523
11524 /* Reciprocal step */
11525 case FLOAT_2BIT_FMT(RECIP1_FMT, FMT_SDPS_S):
11526 mips32_op = OPC_RECIP1_S;
11527 goto do_unaryfp;
11528 case FLOAT_2BIT_FMT(RECIP1_FMT, FMT_SDPS_D):
11529 mips32_op = OPC_RECIP1_S;
11530 goto do_unaryfp;
11531 case FLOAT_2BIT_FMT(RECIP1_FMT, FMT_SDPS_PS):
11532 mips32_op = OPC_RECIP1_PS;
11533 goto do_unaryfp;
11534
11535 /* Conversions from double */
11536 case FLOAT_2BIT_FMT(CVT_D, FMT_SWL_S):
11537 mips32_op = OPC_CVT_D_S;
11538 goto do_unaryfp;
11539 case FLOAT_2BIT_FMT(CVT_D, FMT_SWL_W):
11540 mips32_op = OPC_CVT_D_W;
11541 goto do_unaryfp;
11542 case FLOAT_2BIT_FMT(CVT_D, FMT_SWL_L):
11543 mips32_op = OPC_CVT_D_L;
11544 goto do_unaryfp;
11545
11546 /* Conversions from single */
11547 case FLOAT_2BIT_FMT(CVT_S, FMT_DWL_D):
11548 mips32_op = OPC_CVT_S_D;
11549 goto do_unaryfp;
11550 case FLOAT_2BIT_FMT(CVT_S, FMT_DWL_W):
11551 mips32_op = OPC_CVT_S_W;
11552 goto do_unaryfp;
11553 case FLOAT_2BIT_FMT(CVT_S, FMT_DWL_L):
11554 mips32_op = OPC_CVT_S_L;
11555 do_unaryfp:
11556 gen_farith(ctx, mips32_op, -1, rs, rt, 0);
11557 break;
11558
11559 /* Conditional moves on floating-point codes */
11560 case COND_FLOAT_MOV(MOVT, 0):
11561 case COND_FLOAT_MOV(MOVT, 1):
11562 case COND_FLOAT_MOV(MOVT, 2):
11563 case COND_FLOAT_MOV(MOVT, 3):
11564 case COND_FLOAT_MOV(MOVT, 4):
11565 case COND_FLOAT_MOV(MOVT, 5):
11566 case COND_FLOAT_MOV(MOVT, 6):
11567 case COND_FLOAT_MOV(MOVT, 7):
11568 gen_movci(ctx, rt, rs, (ctx->opcode >> 13) & 0x7, 1);
11569 break;
11570 case COND_FLOAT_MOV(MOVF, 0):
11571 case COND_FLOAT_MOV(MOVF, 1):
11572 case COND_FLOAT_MOV(MOVF, 2):
11573 case COND_FLOAT_MOV(MOVF, 3):
11574 case COND_FLOAT_MOV(MOVF, 4):
11575 case COND_FLOAT_MOV(MOVF, 5):
11576 case COND_FLOAT_MOV(MOVF, 6):
11577 case COND_FLOAT_MOV(MOVF, 7):
11578 gen_movci(ctx, rt, rs, (ctx->opcode >> 13) & 0x7, 0);
11579 break;
11580 default:
11581 MIPS_INVAL("pool32fxf");
11582 generate_exception(ctx, EXCP_RI);
11583 break;
11584 }
11585}
11586
Andreas Färber7db13fa2012-03-14 01:38:22 +010011587static void decode_micromips32_opc (CPUMIPSState *env, DisasContext *ctx,
Nathan Froyd3c824102010-06-08 13:29:59 -070011588 uint16_t insn_hw1, int *is_branch)
11589{
11590 int32_t offset;
11591 uint16_t insn;
11592 int rt, rs, rd, rr;
11593 int16_t imm;
11594 uint32_t op, minor, mips32_op;
11595 uint32_t cond, fmt, cc;
11596
Blue Swirl895c2d02012-09-02 14:52:59 +000011597 insn = cpu_lduw_code(env, ctx->pc + 2);
Nathan Froyd3c824102010-06-08 13:29:59 -070011598 ctx->opcode = (ctx->opcode << 16) | insn;
11599
11600 rt = (ctx->opcode >> 21) & 0x1f;
11601 rs = (ctx->opcode >> 16) & 0x1f;
11602 rd = (ctx->opcode >> 11) & 0x1f;
11603 rr = (ctx->opcode >> 6) & 0x1f;
11604 imm = (int16_t) ctx->opcode;
11605
11606 op = (ctx->opcode >> 26) & 0x3f;
11607 switch (op) {
11608 case POOL32A:
11609 minor = ctx->opcode & 0x3f;
11610 switch (minor) {
11611 case 0x00:
11612 minor = (ctx->opcode >> 6) & 0xf;
11613 switch (minor) {
11614 case SLL32:
11615 mips32_op = OPC_SLL;
11616 goto do_shifti;
11617 case SRA:
11618 mips32_op = OPC_SRA;
11619 goto do_shifti;
11620 case SRL32:
11621 mips32_op = OPC_SRL;
11622 goto do_shifti;
11623 case ROTR:
11624 mips32_op = OPC_ROTR;
11625 do_shifti:
Aurelien Jarnod75c1352013-01-01 18:02:22 +010011626 gen_shift_imm(ctx, mips32_op, rt, rs, rd);
Nathan Froyd3c824102010-06-08 13:29:59 -070011627 break;
11628 default:
11629 goto pool32a_invalid;
11630 }
11631 break;
11632 case 0x10:
11633 minor = (ctx->opcode >> 6) & 0xf;
11634 switch (minor) {
11635 /* Arithmetic */
11636 case ADD:
11637 mips32_op = OPC_ADD;
11638 goto do_arith;
11639 case ADDU32:
11640 mips32_op = OPC_ADDU;
11641 goto do_arith;
11642 case SUB:
11643 mips32_op = OPC_SUB;
11644 goto do_arith;
11645 case SUBU32:
11646 mips32_op = OPC_SUBU;
11647 goto do_arith;
11648 case MUL:
11649 mips32_op = OPC_MUL;
11650 do_arith:
Aurelien Jarnod75c1352013-01-01 18:02:22 +010011651 gen_arith(ctx, mips32_op, rd, rs, rt);
Nathan Froyd3c824102010-06-08 13:29:59 -070011652 break;
11653 /* Shifts */
11654 case SLLV:
11655 mips32_op = OPC_SLLV;
11656 goto do_shift;
11657 case SRLV:
11658 mips32_op = OPC_SRLV;
11659 goto do_shift;
11660 case SRAV:
11661 mips32_op = OPC_SRAV;
11662 goto do_shift;
11663 case ROTRV:
11664 mips32_op = OPC_ROTRV;
11665 do_shift:
Aurelien Jarnod75c1352013-01-01 18:02:22 +010011666 gen_shift(ctx, mips32_op, rd, rs, rt);
Nathan Froyd3c824102010-06-08 13:29:59 -070011667 break;
11668 /* Logical operations */
11669 case AND:
11670 mips32_op = OPC_AND;
11671 goto do_logic;
11672 case OR32:
11673 mips32_op = OPC_OR;
11674 goto do_logic;
11675 case NOR:
11676 mips32_op = OPC_NOR;
11677 goto do_logic;
11678 case XOR32:
11679 mips32_op = OPC_XOR;
11680 do_logic:
Aurelien Jarnod75c1352013-01-01 18:02:22 +010011681 gen_logic(ctx, mips32_op, rd, rs, rt);
Nathan Froyd3c824102010-06-08 13:29:59 -070011682 break;
11683 /* Set less than */
11684 case SLT:
11685 mips32_op = OPC_SLT;
11686 goto do_slt;
11687 case SLTU:
11688 mips32_op = OPC_SLTU;
11689 do_slt:
Aurelien Jarnod75c1352013-01-01 18:02:22 +010011690 gen_slt(ctx, mips32_op, rd, rs, rt);
Nathan Froyd3c824102010-06-08 13:29:59 -070011691 break;
11692 default:
11693 goto pool32a_invalid;
11694 }
11695 break;
11696 case 0x18:
11697 minor = (ctx->opcode >> 6) & 0xf;
11698 switch (minor) {
11699 /* Conditional moves */
11700 case MOVN:
11701 mips32_op = OPC_MOVN;
11702 goto do_cmov;
11703 case MOVZ:
11704 mips32_op = OPC_MOVZ;
11705 do_cmov:
Aurelien Jarnod75c1352013-01-01 18:02:22 +010011706 gen_cond_move(ctx, mips32_op, rd, rs, rt);
Nathan Froyd3c824102010-06-08 13:29:59 -070011707 break;
11708 case LWXS:
11709 gen_ldxs(ctx, rs, rt, rd);
11710 break;
11711 default:
11712 goto pool32a_invalid;
11713 }
11714 break;
11715 case INS:
11716 gen_bitops(ctx, OPC_INS, rt, rs, rr, rd);
11717 return;
11718 case EXT:
11719 gen_bitops(ctx, OPC_EXT, rt, rs, rr, rd);
11720 return;
11721 case POOL32AXF:
11722 gen_pool32axf(env, ctx, rt, rs, is_branch);
11723 break;
11724 case 0x07:
11725 generate_exception(ctx, EXCP_BREAK);
11726 break;
11727 default:
11728 pool32a_invalid:
11729 MIPS_INVAL("pool32a");
11730 generate_exception(ctx, EXCP_RI);
11731 break;
11732 }
11733 break;
11734 case POOL32B:
11735 minor = (ctx->opcode >> 12) & 0xf;
11736 switch (minor) {
11737 case CACHE:
Eric Johnson2e154972011-09-17 17:05:32 -070011738 check_cp0_enabled(ctx);
Nathan Froyd3c824102010-06-08 13:29:59 -070011739 /* Treat as no-op. */
11740 break;
11741 case LWC2:
11742 case SWC2:
11743 /* COP2: Not implemented. */
11744 generate_exception_err(ctx, EXCP_CpU, 2);
11745 break;
11746 case LWP:
11747 case SWP:
11748#ifdef TARGET_MIPS64
11749 case LDP:
11750 case SDP:
11751#endif
11752 gen_ldst_pair(ctx, minor, rt, rs, SIMM(ctx->opcode, 0, 12));
11753 break;
11754 case LWM32:
11755 case SWM32:
11756#ifdef TARGET_MIPS64
11757 case LDM:
11758 case SDM:
11759#endif
11760 gen_ldst_multiple(ctx, minor, rt, rs, SIMM(ctx->opcode, 0, 12));
11761 break;
11762 default:
11763 MIPS_INVAL("pool32b");
11764 generate_exception(ctx, EXCP_RI);
11765 break;
11766 }
11767 break;
11768 case POOL32F:
11769 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
11770 minor = ctx->opcode & 0x3f;
11771 check_cp1_enabled(ctx);
11772 switch (minor) {
11773 case ALNV_PS:
11774 mips32_op = OPC_ALNV_PS;
11775 goto do_madd;
11776 case MADD_S:
11777 mips32_op = OPC_MADD_S;
11778 goto do_madd;
11779 case MADD_D:
11780 mips32_op = OPC_MADD_D;
11781 goto do_madd;
11782 case MADD_PS:
11783 mips32_op = OPC_MADD_PS;
11784 goto do_madd;
11785 case MSUB_S:
11786 mips32_op = OPC_MSUB_S;
11787 goto do_madd;
11788 case MSUB_D:
11789 mips32_op = OPC_MSUB_D;
11790 goto do_madd;
11791 case MSUB_PS:
11792 mips32_op = OPC_MSUB_PS;
11793 goto do_madd;
11794 case NMADD_S:
11795 mips32_op = OPC_NMADD_S;
11796 goto do_madd;
11797 case NMADD_D:
11798 mips32_op = OPC_NMADD_D;
11799 goto do_madd;
11800 case NMADD_PS:
11801 mips32_op = OPC_NMADD_PS;
11802 goto do_madd;
11803 case NMSUB_S:
11804 mips32_op = OPC_NMSUB_S;
11805 goto do_madd;
11806 case NMSUB_D:
11807 mips32_op = OPC_NMSUB_D;
11808 goto do_madd;
11809 case NMSUB_PS:
11810 mips32_op = OPC_NMSUB_PS;
11811 do_madd:
11812 gen_flt3_arith(ctx, mips32_op, rd, rr, rs, rt);
11813 break;
11814 case CABS_COND_FMT:
11815 cond = (ctx->opcode >> 6) & 0xf;
11816 cc = (ctx->opcode >> 13) & 0x7;
11817 fmt = (ctx->opcode >> 10) & 0x3;
11818 switch (fmt) {
11819 case 0x0:
11820 gen_cmpabs_s(ctx, cond, rt, rs, cc);
11821 break;
11822 case 0x1:
11823 gen_cmpabs_d(ctx, cond, rt, rs, cc);
11824 break;
11825 case 0x2:
11826 gen_cmpabs_ps(ctx, cond, rt, rs, cc);
11827 break;
11828 default:
11829 goto pool32f_invalid;
11830 }
11831 break;
11832 case C_COND_FMT:
11833 cond = (ctx->opcode >> 6) & 0xf;
11834 cc = (ctx->opcode >> 13) & 0x7;
11835 fmt = (ctx->opcode >> 10) & 0x3;
11836 switch (fmt) {
11837 case 0x0:
11838 gen_cmp_s(ctx, cond, rt, rs, cc);
11839 break;
11840 case 0x1:
11841 gen_cmp_d(ctx, cond, rt, rs, cc);
11842 break;
11843 case 0x2:
11844 gen_cmp_ps(ctx, cond, rt, rs, cc);
11845 break;
11846 default:
11847 goto pool32f_invalid;
11848 }
11849 break;
11850 case POOL32FXF:
Aurelien Jarnod75c1352013-01-01 18:02:22 +010011851 gen_pool32fxf(ctx, rt, rs);
Nathan Froyd3c824102010-06-08 13:29:59 -070011852 break;
11853 case 0x00:
11854 /* PLL foo */
11855 switch ((ctx->opcode >> 6) & 0x7) {
11856 case PLL_PS:
11857 mips32_op = OPC_PLL_PS;
11858 goto do_ps;
11859 case PLU_PS:
11860 mips32_op = OPC_PLU_PS;
11861 goto do_ps;
11862 case PUL_PS:
11863 mips32_op = OPC_PUL_PS;
11864 goto do_ps;
11865 case PUU_PS:
11866 mips32_op = OPC_PUU_PS;
11867 goto do_ps;
11868 case CVT_PS_S:
11869 mips32_op = OPC_CVT_PS_S;
11870 do_ps:
11871 gen_farith(ctx, mips32_op, rt, rs, rd, 0);
11872 break;
11873 default:
11874 goto pool32f_invalid;
11875 }
11876 break;
11877 case 0x08:
11878 /* [LS][WDU]XC1 */
11879 switch ((ctx->opcode >> 6) & 0x7) {
11880 case LWXC1:
11881 mips32_op = OPC_LWXC1;
11882 goto do_ldst_cp1;
11883 case SWXC1:
11884 mips32_op = OPC_SWXC1;
11885 goto do_ldst_cp1;
11886 case LDXC1:
11887 mips32_op = OPC_LDXC1;
11888 goto do_ldst_cp1;
11889 case SDXC1:
11890 mips32_op = OPC_SDXC1;
11891 goto do_ldst_cp1;
11892 case LUXC1:
11893 mips32_op = OPC_LUXC1;
11894 goto do_ldst_cp1;
11895 case SUXC1:
11896 mips32_op = OPC_SUXC1;
11897 do_ldst_cp1:
11898 gen_flt3_ldst(ctx, mips32_op, rd, rd, rt, rs);
11899 break;
11900 default:
11901 goto pool32f_invalid;
11902 }
11903 break;
11904 case 0x18:
11905 /* 3D insns */
11906 fmt = (ctx->opcode >> 9) & 0x3;
11907 switch ((ctx->opcode >> 6) & 0x7) {
11908 case RSQRT2_FMT:
11909 switch (fmt) {
11910 case FMT_SDPS_S:
11911 mips32_op = OPC_RSQRT2_S;
11912 goto do_3d;
11913 case FMT_SDPS_D:
11914 mips32_op = OPC_RSQRT2_D;
11915 goto do_3d;
11916 case FMT_SDPS_PS:
11917 mips32_op = OPC_RSQRT2_PS;
11918 goto do_3d;
11919 default:
11920 goto pool32f_invalid;
11921 }
11922 break;
11923 case RECIP2_FMT:
11924 switch (fmt) {
11925 case FMT_SDPS_S:
11926 mips32_op = OPC_RECIP2_S;
11927 goto do_3d;
11928 case FMT_SDPS_D:
11929 mips32_op = OPC_RECIP2_D;
11930 goto do_3d;
11931 case FMT_SDPS_PS:
11932 mips32_op = OPC_RECIP2_PS;
11933 goto do_3d;
11934 default:
11935 goto pool32f_invalid;
11936 }
11937 break;
11938 case ADDR_PS:
11939 mips32_op = OPC_ADDR_PS;
11940 goto do_3d;
11941 case MULR_PS:
11942 mips32_op = OPC_MULR_PS;
11943 do_3d:
11944 gen_farith(ctx, mips32_op, rt, rs, rd, 0);
11945 break;
11946 default:
11947 goto pool32f_invalid;
11948 }
11949 break;
11950 case 0x20:
11951 /* MOV[FT].fmt and PREFX */
11952 cc = (ctx->opcode >> 13) & 0x7;
11953 fmt = (ctx->opcode >> 9) & 0x3;
11954 switch ((ctx->opcode >> 6) & 0x7) {
11955 case MOVF_FMT:
11956 switch (fmt) {
11957 case FMT_SDPS_S:
11958 gen_movcf_s(rs, rt, cc, 0);
11959 break;
11960 case FMT_SDPS_D:
11961 gen_movcf_d(ctx, rs, rt, cc, 0);
11962 break;
11963 case FMT_SDPS_PS:
11964 gen_movcf_ps(rs, rt, cc, 0);
11965 break;
11966 default:
11967 goto pool32f_invalid;
11968 }
11969 break;
11970 case MOVT_FMT:
11971 switch (fmt) {
11972 case FMT_SDPS_S:
11973 gen_movcf_s(rs, rt, cc, 1);
11974 break;
11975 case FMT_SDPS_D:
11976 gen_movcf_d(ctx, rs, rt, cc, 1);
11977 break;
11978 case FMT_SDPS_PS:
11979 gen_movcf_ps(rs, rt, cc, 1);
11980 break;
11981 default:
11982 goto pool32f_invalid;
11983 }
11984 break;
11985 case PREFX:
11986 break;
11987 default:
11988 goto pool32f_invalid;
11989 }
11990 break;
11991#define FINSN_3ARG_SDPS(prfx) \
11992 switch ((ctx->opcode >> 8) & 0x3) { \
11993 case FMT_SDPS_S: \
11994 mips32_op = OPC_##prfx##_S; \
11995 goto do_fpop; \
11996 case FMT_SDPS_D: \
11997 mips32_op = OPC_##prfx##_D; \
11998 goto do_fpop; \
11999 case FMT_SDPS_PS: \
12000 mips32_op = OPC_##prfx##_PS; \
12001 goto do_fpop; \
12002 default: \
12003 goto pool32f_invalid; \
12004 }
12005 case 0x30:
12006 /* regular FP ops */
12007 switch ((ctx->opcode >> 6) & 0x3) {
12008 case ADD_FMT:
12009 FINSN_3ARG_SDPS(ADD);
12010 break;
12011 case SUB_FMT:
12012 FINSN_3ARG_SDPS(SUB);
12013 break;
12014 case MUL_FMT:
12015 FINSN_3ARG_SDPS(MUL);
12016 break;
12017 case DIV_FMT:
12018 fmt = (ctx->opcode >> 8) & 0x3;
12019 if (fmt == 1) {
12020 mips32_op = OPC_DIV_D;
12021 } else if (fmt == 0) {
12022 mips32_op = OPC_DIV_S;
12023 } else {
12024 goto pool32f_invalid;
12025 }
12026 goto do_fpop;
12027 default:
12028 goto pool32f_invalid;
12029 }
12030 break;
12031 case 0x38:
12032 /* cmovs */
12033 switch ((ctx->opcode >> 6) & 0x3) {
12034 case MOVN_FMT:
12035 FINSN_3ARG_SDPS(MOVN);
12036 break;
12037 case MOVZ_FMT:
12038 FINSN_3ARG_SDPS(MOVZ);
12039 break;
12040 default:
12041 goto pool32f_invalid;
12042 }
12043 break;
12044 do_fpop:
12045 gen_farith(ctx, mips32_op, rt, rs, rd, 0);
12046 break;
12047 default:
12048 pool32f_invalid:
12049 MIPS_INVAL("pool32f");
12050 generate_exception(ctx, EXCP_RI);
12051 break;
12052 }
12053 } else {
12054 generate_exception_err(ctx, EXCP_CpU, 1);
12055 }
12056 break;
12057 case POOL32I:
12058 minor = (ctx->opcode >> 21) & 0x1f;
12059 switch (minor) {
12060 case BLTZ:
12061 mips32_op = OPC_BLTZ;
12062 goto do_branch;
12063 case BLTZAL:
12064 mips32_op = OPC_BLTZAL;
12065 goto do_branch;
12066 case BLTZALS:
12067 mips32_op = OPC_BLTZALS;
12068 goto do_branch;
12069 case BGEZ:
12070 mips32_op = OPC_BGEZ;
12071 goto do_branch;
12072 case BGEZAL:
12073 mips32_op = OPC_BGEZAL;
12074 goto do_branch;
12075 case BGEZALS:
12076 mips32_op = OPC_BGEZALS;
12077 goto do_branch;
12078 case BLEZ:
12079 mips32_op = OPC_BLEZ;
12080 goto do_branch;
12081 case BGTZ:
12082 mips32_op = OPC_BGTZ;
12083 do_branch:
12084 gen_compute_branch(ctx, mips32_op, 4, rs, -1, imm << 1);
12085 *is_branch = 1;
12086 break;
12087
12088 /* Traps */
12089 case TLTI:
12090 mips32_op = OPC_TLTI;
12091 goto do_trapi;
12092 case TGEI:
12093 mips32_op = OPC_TGEI;
12094 goto do_trapi;
12095 case TLTIU:
12096 mips32_op = OPC_TLTIU;
12097 goto do_trapi;
12098 case TGEIU:
12099 mips32_op = OPC_TGEIU;
12100 goto do_trapi;
12101 case TNEI:
12102 mips32_op = OPC_TNEI;
12103 goto do_trapi;
12104 case TEQI:
12105 mips32_op = OPC_TEQI;
12106 do_trapi:
12107 gen_trap(ctx, mips32_op, rs, -1, imm);
12108 break;
12109
12110 case BNEZC:
12111 case BEQZC:
12112 gen_compute_branch(ctx, minor == BNEZC ? OPC_BNE : OPC_BEQ,
12113 4, rs, 0, imm << 1);
12114 /* Compact branches don't have a delay slot, so just let
12115 the normal delay slot handling take us to the branch
12116 target. */
12117 break;
12118 case LUI:
Aurelien Jarnod75c1352013-01-01 18:02:22 +010012119 gen_logic_imm(ctx, OPC_LUI, rs, -1, imm);
Nathan Froyd3c824102010-06-08 13:29:59 -070012120 break;
12121 case SYNCI:
12122 break;
12123 case BC2F:
12124 case BC2T:
12125 /* COP2: Not implemented. */
12126 generate_exception_err(ctx, EXCP_CpU, 2);
12127 break;
12128 case BC1F:
12129 mips32_op = (ctx->opcode & (1 << 16)) ? OPC_BC1FANY2 : OPC_BC1F;
12130 goto do_cp1branch;
12131 case BC1T:
12132 mips32_op = (ctx->opcode & (1 << 16)) ? OPC_BC1TANY2 : OPC_BC1T;
12133 goto do_cp1branch;
12134 case BC1ANY4F:
12135 mips32_op = OPC_BC1FANY4;
12136 goto do_cp1mips3d;
12137 case BC1ANY4T:
12138 mips32_op = OPC_BC1TANY4;
12139 do_cp1mips3d:
12140 check_cop1x(ctx);
Aurelien Jarnod75c1352013-01-01 18:02:22 +010012141 check_insn(ctx, ASE_MIPS3D);
Nathan Froyd3c824102010-06-08 13:29:59 -070012142 /* Fall through */
12143 do_cp1branch:
Aurelien Jarnod75c1352013-01-01 18:02:22 +010012144 gen_compute_branch1(ctx, mips32_op,
Nathan Froyd3c824102010-06-08 13:29:59 -070012145 (ctx->opcode >> 18) & 0x7, imm << 1);
12146 *is_branch = 1;
12147 break;
12148 case BPOSGE64:
12149 case BPOSGE32:
12150 /* MIPS DSP: not implemented */
12151 /* Fall through */
12152 default:
12153 MIPS_INVAL("pool32i");
12154 generate_exception(ctx, EXCP_RI);
12155 break;
12156 }
12157 break;
12158 case POOL32C:
12159 minor = (ctx->opcode >> 12) & 0xf;
12160 switch (minor) {
12161 case LWL:
12162 mips32_op = OPC_LWL;
Aurelien Jarno5c13fdf2010-07-01 07:47:00 +020012163 goto do_ld_lr;
Nathan Froyd3c824102010-06-08 13:29:59 -070012164 case SWL:
12165 mips32_op = OPC_SWL;
Aurelien Jarno5c13fdf2010-07-01 07:47:00 +020012166 goto do_st_lr;
Nathan Froyd3c824102010-06-08 13:29:59 -070012167 case LWR:
12168 mips32_op = OPC_LWR;
Aurelien Jarno5c13fdf2010-07-01 07:47:00 +020012169 goto do_ld_lr;
Nathan Froyd3c824102010-06-08 13:29:59 -070012170 case SWR:
12171 mips32_op = OPC_SWR;
Aurelien Jarno5c13fdf2010-07-01 07:47:00 +020012172 goto do_st_lr;
Nathan Froyd3c824102010-06-08 13:29:59 -070012173#if defined(TARGET_MIPS64)
12174 case LDL:
12175 mips32_op = OPC_LDL;
Aurelien Jarno5c13fdf2010-07-01 07:47:00 +020012176 goto do_ld_lr;
Nathan Froyd3c824102010-06-08 13:29:59 -070012177 case SDL:
12178 mips32_op = OPC_SDL;
Aurelien Jarno5c13fdf2010-07-01 07:47:00 +020012179 goto do_st_lr;
Nathan Froyd3c824102010-06-08 13:29:59 -070012180 case LDR:
12181 mips32_op = OPC_LDR;
Aurelien Jarno5c13fdf2010-07-01 07:47:00 +020012182 goto do_ld_lr;
Nathan Froyd3c824102010-06-08 13:29:59 -070012183 case SDR:
12184 mips32_op = OPC_SDR;
Aurelien Jarno5c13fdf2010-07-01 07:47:00 +020012185 goto do_st_lr;
Nathan Froyd3c824102010-06-08 13:29:59 -070012186 case LWU:
12187 mips32_op = OPC_LWU;
Aurelien Jarno5c13fdf2010-07-01 07:47:00 +020012188 goto do_ld_lr;
Nathan Froyd3c824102010-06-08 13:29:59 -070012189 case LLD:
12190 mips32_op = OPC_LLD;
Aurelien Jarno5c13fdf2010-07-01 07:47:00 +020012191 goto do_ld_lr;
Nathan Froyd3c824102010-06-08 13:29:59 -070012192#endif
12193 case LL:
12194 mips32_op = OPC_LL;
Aurelien Jarno5c13fdf2010-07-01 07:47:00 +020012195 goto do_ld_lr;
12196 do_ld_lr:
Aurelien Jarnod75c1352013-01-01 18:02:22 +010012197 gen_ld(ctx, mips32_op, rt, rs, SIMM(ctx->opcode, 0, 12));
Aurelien Jarno5c13fdf2010-07-01 07:47:00 +020012198 break;
12199 do_st_lr:
12200 gen_st(ctx, mips32_op, rt, rs, SIMM(ctx->opcode, 0, 12));
Nathan Froyd3c824102010-06-08 13:29:59 -070012201 break;
12202 case SC:
12203 gen_st_cond(ctx, OPC_SC, rt, rs, SIMM(ctx->opcode, 0, 12));
12204 break;
12205#if defined(TARGET_MIPS64)
12206 case SCD:
12207 gen_st_cond(ctx, OPC_SCD, rt, rs, SIMM(ctx->opcode, 0, 12));
12208 break;
12209#endif
12210 case PREF:
12211 /* Treat as no-op */
12212 break;
12213 default:
12214 MIPS_INVAL("pool32c");
12215 generate_exception(ctx, EXCP_RI);
12216 break;
12217 }
12218 break;
12219 case ADDI32:
12220 mips32_op = OPC_ADDI;
12221 goto do_addi;
12222 case ADDIU32:
12223 mips32_op = OPC_ADDIU;
12224 do_addi:
Aurelien Jarnod75c1352013-01-01 18:02:22 +010012225 gen_arith_imm(ctx, mips32_op, rt, rs, imm);
Nathan Froyd3c824102010-06-08 13:29:59 -070012226 break;
12227
12228 /* Logical operations */
12229 case ORI32:
12230 mips32_op = OPC_ORI;
12231 goto do_logici;
12232 case XORI32:
12233 mips32_op = OPC_XORI;
12234 goto do_logici;
12235 case ANDI32:
12236 mips32_op = OPC_ANDI;
12237 do_logici:
Aurelien Jarnod75c1352013-01-01 18:02:22 +010012238 gen_logic_imm(ctx, mips32_op, rt, rs, imm);
Nathan Froyd3c824102010-06-08 13:29:59 -070012239 break;
12240
12241 /* Set less than immediate */
12242 case SLTI32:
12243 mips32_op = OPC_SLTI;
12244 goto do_slti;
12245 case SLTIU32:
12246 mips32_op = OPC_SLTIU;
12247 do_slti:
Aurelien Jarnod75c1352013-01-01 18:02:22 +010012248 gen_slt_imm(ctx, mips32_op, rt, rs, imm);
Nathan Froyd3c824102010-06-08 13:29:59 -070012249 break;
12250 case JALX32:
12251 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2;
12252 gen_compute_branch(ctx, OPC_JALX, 4, rt, rs, offset);
12253 *is_branch = 1;
12254 break;
12255 case JALS32:
12256 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 1;
12257 gen_compute_branch(ctx, OPC_JALS, 4, rt, rs, offset);
12258 *is_branch = 1;
12259 break;
12260 case BEQ32:
12261 gen_compute_branch(ctx, OPC_BEQ, 4, rt, rs, imm << 1);
12262 *is_branch = 1;
12263 break;
12264 case BNE32:
12265 gen_compute_branch(ctx, OPC_BNE, 4, rt, rs, imm << 1);
12266 *is_branch = 1;
12267 break;
12268 case J32:
12269 gen_compute_branch(ctx, OPC_J, 4, rt, rs,
12270 (int32_t)(ctx->opcode & 0x3FFFFFF) << 1);
12271 *is_branch = 1;
12272 break;
12273 case JAL32:
12274 gen_compute_branch(ctx, OPC_JAL, 4, rt, rs,
12275 (int32_t)(ctx->opcode & 0x3FFFFFF) << 1);
12276 *is_branch = 1;
12277 break;
12278 /* Floating point (COP1) */
12279 case LWC132:
12280 mips32_op = OPC_LWC1;
12281 goto do_cop1;
12282 case LDC132:
12283 mips32_op = OPC_LDC1;
12284 goto do_cop1;
12285 case SWC132:
12286 mips32_op = OPC_SWC1;
12287 goto do_cop1;
12288 case SDC132:
12289 mips32_op = OPC_SDC1;
12290 do_cop1:
12291 gen_cop1_ldst(env, ctx, mips32_op, rt, rs, imm);
12292 break;
12293 case ADDIUPC:
12294 {
12295 int reg = mmreg(ZIMM(ctx->opcode, 23, 3));
12296 int offset = SIMM(ctx->opcode, 0, 23) << 2;
12297
12298 gen_addiupc(ctx, reg, offset, 0, 0);
12299 }
12300 break;
12301 /* Loads and stores */
12302 case LB32:
12303 mips32_op = OPC_LB;
Aurelien Jarno5c13fdf2010-07-01 07:47:00 +020012304 goto do_ld;
Nathan Froyd3c824102010-06-08 13:29:59 -070012305 case LBU32:
12306 mips32_op = OPC_LBU;
Aurelien Jarno5c13fdf2010-07-01 07:47:00 +020012307 goto do_ld;
Nathan Froyd3c824102010-06-08 13:29:59 -070012308 case LH32:
12309 mips32_op = OPC_LH;
Aurelien Jarno5c13fdf2010-07-01 07:47:00 +020012310 goto do_ld;
Nathan Froyd3c824102010-06-08 13:29:59 -070012311 case LHU32:
12312 mips32_op = OPC_LHU;
Aurelien Jarno5c13fdf2010-07-01 07:47:00 +020012313 goto do_ld;
Nathan Froyd3c824102010-06-08 13:29:59 -070012314 case LW32:
12315 mips32_op = OPC_LW;
Aurelien Jarno5c13fdf2010-07-01 07:47:00 +020012316 goto do_ld;
Nathan Froyd3c824102010-06-08 13:29:59 -070012317#ifdef TARGET_MIPS64
12318 case LD32:
12319 mips32_op = OPC_LD;
Aurelien Jarno5c13fdf2010-07-01 07:47:00 +020012320 goto do_ld;
Nathan Froyd3c824102010-06-08 13:29:59 -070012321 case SD32:
12322 mips32_op = OPC_SD;
Aurelien Jarno5c13fdf2010-07-01 07:47:00 +020012323 goto do_st;
Nathan Froyd3c824102010-06-08 13:29:59 -070012324#endif
12325 case SB32:
12326 mips32_op = OPC_SB;
Aurelien Jarno5c13fdf2010-07-01 07:47:00 +020012327 goto do_st;
Nathan Froyd3c824102010-06-08 13:29:59 -070012328 case SH32:
12329 mips32_op = OPC_SH;
Aurelien Jarno5c13fdf2010-07-01 07:47:00 +020012330 goto do_st;
Nathan Froyd3c824102010-06-08 13:29:59 -070012331 case SW32:
12332 mips32_op = OPC_SW;
Aurelien Jarno5c13fdf2010-07-01 07:47:00 +020012333 goto do_st;
12334 do_ld:
Aurelien Jarnod75c1352013-01-01 18:02:22 +010012335 gen_ld(ctx, mips32_op, rt, rs, imm);
Aurelien Jarno5c13fdf2010-07-01 07:47:00 +020012336 break;
12337 do_st:
12338 gen_st(ctx, mips32_op, rt, rs, imm);
Nathan Froyd3c824102010-06-08 13:29:59 -070012339 break;
12340 default:
12341 generate_exception(ctx, EXCP_RI);
12342 break;
12343 }
12344}
12345
Andreas Färber7db13fa2012-03-14 01:38:22 +010012346static int decode_micromips_opc (CPUMIPSState *env, DisasContext *ctx, int *is_branch)
Nathan Froyd3c824102010-06-08 13:29:59 -070012347{
12348 uint32_t op;
12349
12350 /* make sure instructions are on a halfword boundary */
12351 if (ctx->pc & 0x1) {
12352 env->CP0_BadVAddr = ctx->pc;
12353 generate_exception(ctx, EXCP_AdEL);
12354 ctx->bstate = BS_STOP;
12355 return 2;
12356 }
12357
12358 op = (ctx->opcode >> 10) & 0x3f;
12359 /* Enforce properly-sized instructions in a delay slot */
12360 if (ctx->hflags & MIPS_HFLAG_BMASK) {
12361 int bits = ctx->hflags & MIPS_HFLAG_BMASK_EXT;
12362
12363 switch (op) {
12364 case POOL32A:
12365 case POOL32B:
12366 case POOL32I:
12367 case POOL32C:
12368 case ADDI32:
12369 case ADDIU32:
12370 case ORI32:
12371 case XORI32:
12372 case SLTI32:
12373 case SLTIU32:
12374 case ANDI32:
12375 case JALX32:
12376 case LBU32:
12377 case LHU32:
12378 case POOL32F:
12379 case JALS32:
12380 case BEQ32:
12381 case BNE32:
12382 case J32:
12383 case JAL32:
12384 case SB32:
12385 case SH32:
12386 case POOL32S:
12387 case ADDIUPC:
12388 case SWC132:
12389 case SDC132:
12390 case SD32:
12391 case SW32:
12392 case LB32:
12393 case LH32:
12394 case DADDIU32:
Nathan Froyd3c824102010-06-08 13:29:59 -070012395 case LWC132:
12396 case LDC132:
12397 case LD32:
12398 case LW32:
12399 if (bits & MIPS_HFLAG_BDS16) {
12400 generate_exception(ctx, EXCP_RI);
12401 /* Just stop translation; the user is confused. */
12402 ctx->bstate = BS_STOP;
12403 return 2;
12404 }
12405 break;
12406 case POOL16A:
12407 case POOL16B:
12408 case POOL16C:
12409 case LWGP16:
12410 case POOL16F:
12411 case LBU16:
12412 case LHU16:
12413 case LWSP16:
12414 case LW16:
12415 case SB16:
12416 case SH16:
12417 case SWSP16:
12418 case SW16:
12419 case MOVE16:
12420 case ANDI16:
12421 case POOL16D:
12422 case POOL16E:
12423 case BEQZ16:
12424 case BNEZ16:
12425 case B16:
12426 case LI16:
12427 if (bits & MIPS_HFLAG_BDS32) {
12428 generate_exception(ctx, EXCP_RI);
12429 /* Just stop translation; the user is confused. */
12430 ctx->bstate = BS_STOP;
12431 return 2;
12432 }
12433 break;
12434 default:
12435 break;
12436 }
12437 }
12438 switch (op) {
12439 case POOL16A:
12440 {
12441 int rd = mmreg(uMIPS_RD(ctx->opcode));
12442 int rs1 = mmreg(uMIPS_RS1(ctx->opcode));
12443 int rs2 = mmreg(uMIPS_RS2(ctx->opcode));
12444 uint32_t opc = 0;
12445
12446 switch (ctx->opcode & 0x1) {
12447 case ADDU16:
12448 opc = OPC_ADDU;
12449 break;
12450 case SUBU16:
12451 opc = OPC_SUBU;
12452 break;
12453 }
12454
Aurelien Jarnod75c1352013-01-01 18:02:22 +010012455 gen_arith(ctx, opc, rd, rs1, rs2);
Nathan Froyd3c824102010-06-08 13:29:59 -070012456 }
12457 break;
12458 case POOL16B:
12459 {
12460 int rd = mmreg(uMIPS_RD(ctx->opcode));
12461 int rs = mmreg(uMIPS_RS(ctx->opcode));
12462 int amount = (ctx->opcode >> 1) & 0x7;
12463 uint32_t opc = 0;
12464 amount = amount == 0 ? 8 : amount;
12465
12466 switch (ctx->opcode & 0x1) {
12467 case SLL16:
12468 opc = OPC_SLL;
12469 break;
12470 case SRL16:
12471 opc = OPC_SRL;
12472 break;
12473 }
12474
Aurelien Jarnod75c1352013-01-01 18:02:22 +010012475 gen_shift_imm(ctx, opc, rd, rs, amount);
Nathan Froyd3c824102010-06-08 13:29:59 -070012476 }
12477 break;
12478 case POOL16C:
Aurelien Jarnod75c1352013-01-01 18:02:22 +010012479 gen_pool16c_insn(ctx, is_branch);
Nathan Froyd3c824102010-06-08 13:29:59 -070012480 break;
12481 case LWGP16:
12482 {
12483 int rd = mmreg(uMIPS_RD(ctx->opcode));
12484 int rb = 28; /* GP */
12485 int16_t offset = SIMM(ctx->opcode, 0, 7) << 2;
12486
Aurelien Jarnod75c1352013-01-01 18:02:22 +010012487 gen_ld(ctx, OPC_LW, rd, rb, offset);
Nathan Froyd3c824102010-06-08 13:29:59 -070012488 }
12489 break;
12490 case POOL16F:
12491 if (ctx->opcode & 1) {
12492 generate_exception(ctx, EXCP_RI);
12493 } else {
12494 /* MOVEP */
12495 int enc_dest = uMIPS_RD(ctx->opcode);
12496 int enc_rt = uMIPS_RS2(ctx->opcode);
12497 int enc_rs = uMIPS_RS1(ctx->opcode);
12498 int rd, rs, re, rt;
12499 static const int rd_enc[] = { 5, 5, 6, 4, 4, 4, 4, 4 };
12500 static const int re_enc[] = { 6, 7, 7, 21, 22, 5, 6, 7 };
12501 static const int rs_rt_enc[] = { 0, 17, 2, 3, 16, 18, 19, 20 };
12502
12503 rd = rd_enc[enc_dest];
12504 re = re_enc[enc_dest];
12505 rs = rs_rt_enc[enc_rs];
12506 rt = rs_rt_enc[enc_rt];
12507
Aurelien Jarnod75c1352013-01-01 18:02:22 +010012508 gen_arith_imm(ctx, OPC_ADDIU, rd, rs, 0);
12509 gen_arith_imm(ctx, OPC_ADDIU, re, rt, 0);
Nathan Froyd3c824102010-06-08 13:29:59 -070012510 }
12511 break;
12512 case LBU16:
12513 {
12514 int rd = mmreg(uMIPS_RD(ctx->opcode));
12515 int rb = mmreg(uMIPS_RS(ctx->opcode));
12516 int16_t offset = ZIMM(ctx->opcode, 0, 4);
12517 offset = (offset == 0xf ? -1 : offset);
12518
Aurelien Jarnod75c1352013-01-01 18:02:22 +010012519 gen_ld(ctx, OPC_LBU, rd, rb, offset);
Nathan Froyd3c824102010-06-08 13:29:59 -070012520 }
12521 break;
12522 case LHU16:
12523 {
12524 int rd = mmreg(uMIPS_RD(ctx->opcode));
12525 int rb = mmreg(uMIPS_RS(ctx->opcode));
12526 int16_t offset = ZIMM(ctx->opcode, 0, 4) << 1;
12527
Aurelien Jarnod75c1352013-01-01 18:02:22 +010012528 gen_ld(ctx, OPC_LHU, rd, rb, offset);
Nathan Froyd3c824102010-06-08 13:29:59 -070012529 }
12530 break;
12531 case LWSP16:
12532 {
12533 int rd = (ctx->opcode >> 5) & 0x1f;
12534 int rb = 29; /* SP */
12535 int16_t offset = ZIMM(ctx->opcode, 0, 5) << 2;
12536
Aurelien Jarnod75c1352013-01-01 18:02:22 +010012537 gen_ld(ctx, OPC_LW, rd, rb, offset);
Nathan Froyd3c824102010-06-08 13:29:59 -070012538 }
12539 break;
12540 case LW16:
12541 {
12542 int rd = mmreg(uMIPS_RD(ctx->opcode));
12543 int rb = mmreg(uMIPS_RS(ctx->opcode));
12544 int16_t offset = ZIMM(ctx->opcode, 0, 4) << 2;
12545
Aurelien Jarnod75c1352013-01-01 18:02:22 +010012546 gen_ld(ctx, OPC_LW, rd, rb, offset);
Nathan Froyd3c824102010-06-08 13:29:59 -070012547 }
12548 break;
12549 case SB16:
12550 {
12551 int rd = mmreg2(uMIPS_RD(ctx->opcode));
12552 int rb = mmreg(uMIPS_RS(ctx->opcode));
12553 int16_t offset = ZIMM(ctx->opcode, 0, 4);
12554
Aurelien Jarno5c13fdf2010-07-01 07:47:00 +020012555 gen_st(ctx, OPC_SB, rd, rb, offset);
Nathan Froyd3c824102010-06-08 13:29:59 -070012556 }
12557 break;
12558 case SH16:
12559 {
12560 int rd = mmreg2(uMIPS_RD(ctx->opcode));
12561 int rb = mmreg(uMIPS_RS(ctx->opcode));
12562 int16_t offset = ZIMM(ctx->opcode, 0, 4) << 1;
12563
Aurelien Jarno5c13fdf2010-07-01 07:47:00 +020012564 gen_st(ctx, OPC_SH, rd, rb, offset);
Nathan Froyd3c824102010-06-08 13:29:59 -070012565 }
12566 break;
12567 case SWSP16:
12568 {
12569 int rd = (ctx->opcode >> 5) & 0x1f;
12570 int rb = 29; /* SP */
12571 int16_t offset = ZIMM(ctx->opcode, 0, 5) << 2;
12572
Aurelien Jarno5c13fdf2010-07-01 07:47:00 +020012573 gen_st(ctx, OPC_SW, rd, rb, offset);
Nathan Froyd3c824102010-06-08 13:29:59 -070012574 }
12575 break;
12576 case SW16:
12577 {
12578 int rd = mmreg2(uMIPS_RD(ctx->opcode));
12579 int rb = mmreg(uMIPS_RS(ctx->opcode));
12580 int16_t offset = ZIMM(ctx->opcode, 0, 4) << 2;
12581
Aurelien Jarno5c13fdf2010-07-01 07:47:00 +020012582 gen_st(ctx, OPC_SW, rd, rb, offset);
Nathan Froyd3c824102010-06-08 13:29:59 -070012583 }
12584 break;
12585 case MOVE16:
12586 {
12587 int rd = uMIPS_RD5(ctx->opcode);
12588 int rs = uMIPS_RS5(ctx->opcode);
12589
Aurelien Jarnod75c1352013-01-01 18:02:22 +010012590 gen_arith_imm(ctx, OPC_ADDIU, rd, rs, 0);
Nathan Froyd3c824102010-06-08 13:29:59 -070012591 }
12592 break;
12593 case ANDI16:
Aurelien Jarnod75c1352013-01-01 18:02:22 +010012594 gen_andi16(ctx);
Nathan Froyd3c824102010-06-08 13:29:59 -070012595 break;
12596 case POOL16D:
12597 switch (ctx->opcode & 0x1) {
12598 case ADDIUS5:
Aurelien Jarnod75c1352013-01-01 18:02:22 +010012599 gen_addius5(ctx);
Nathan Froyd3c824102010-06-08 13:29:59 -070012600 break;
12601 case ADDIUSP:
Aurelien Jarnod75c1352013-01-01 18:02:22 +010012602 gen_addiusp(ctx);
Nathan Froyd3c824102010-06-08 13:29:59 -070012603 break;
12604 }
12605 break;
12606 case POOL16E:
12607 switch (ctx->opcode & 0x1) {
12608 case ADDIUR2:
Aurelien Jarnod75c1352013-01-01 18:02:22 +010012609 gen_addiur2(ctx);
Nathan Froyd3c824102010-06-08 13:29:59 -070012610 break;
12611 case ADDIUR1SP:
Aurelien Jarnod75c1352013-01-01 18:02:22 +010012612 gen_addiur1sp(ctx);
Nathan Froyd3c824102010-06-08 13:29:59 -070012613 break;
12614 }
12615 break;
12616 case B16:
12617 gen_compute_branch(ctx, OPC_BEQ, 2, 0, 0,
12618 SIMM(ctx->opcode, 0, 10) << 1);
12619 *is_branch = 1;
12620 break;
12621 case BNEZ16:
12622 case BEQZ16:
12623 gen_compute_branch(ctx, op == BNEZ16 ? OPC_BNE : OPC_BEQ, 2,
12624 mmreg(uMIPS_RD(ctx->opcode)),
12625 0, SIMM(ctx->opcode, 0, 7) << 1);
12626 *is_branch = 1;
12627 break;
12628 case LI16:
12629 {
12630 int reg = mmreg(uMIPS_RD(ctx->opcode));
12631 int imm = ZIMM(ctx->opcode, 0, 7);
12632
12633 imm = (imm == 0x7f ? -1 : imm);
12634 tcg_gen_movi_tl(cpu_gpr[reg], imm);
12635 }
12636 break;
12637 case RES_20:
12638 case RES_28:
12639 case RES_29:
12640 case RES_30:
12641 case RES_31:
12642 case RES_38:
12643 case RES_39:
12644 generate_exception(ctx, EXCP_RI);
12645 break;
12646 default:
12647 decode_micromips32_opc (env, ctx, op, is_branch);
12648 return 4;
12649 }
12650
12651 return 2;
12652}
12653
bellard6af0bf92005-07-02 14:58:51 +000012654/* SmartMIPS extension to MIPS32 */
12655
thsd26bc212007-11-08 18:05:37 +000012656#if defined(TARGET_MIPS64)
bellard6af0bf92005-07-02 14:58:51 +000012657
12658/* MDMX extension to MIPS64 */
bellard6af0bf92005-07-02 14:58:51 +000012659
12660#endif
12661
Jia Liu9b1a1d62012-10-24 22:17:05 +080012662/* MIPSDSP functions. */
Aurelien Jarnod75c1352013-01-01 18:02:22 +010012663static void gen_mipsdsp_ld(DisasContext *ctx, uint32_t opc,
Jia Liu9b1a1d62012-10-24 22:17:05 +080012664 int rd, int base, int offset)
12665{
12666 const char *opn = "ldx";
12667 TCGv t0;
12668
Jia Liu9b1a1d62012-10-24 22:17:05 +080012669 check_dsp(ctx);
12670 t0 = tcg_temp_new();
12671
12672 if (base == 0) {
12673 gen_load_gpr(t0, offset);
12674 } else if (offset == 0) {
12675 gen_load_gpr(t0, base);
12676 } else {
12677 gen_op_addr_add(ctx, t0, cpu_gpr[base], cpu_gpr[offset]);
12678 }
12679
Jia Liu9b1a1d62012-10-24 22:17:05 +080012680 switch (opc) {
12681 case OPC_LBUX:
Aurelien Jarno2910c6cb2012-10-09 21:53:20 +020012682 tcg_gen_qemu_ld8u(t0, t0, ctx->mem_idx);
Jia Liu9b1a1d62012-10-24 22:17:05 +080012683 gen_store_gpr(t0, rd);
12684 opn = "lbux";
12685 break;
12686 case OPC_LHX:
Aurelien Jarno2910c6cb2012-10-09 21:53:20 +020012687 tcg_gen_qemu_ld16s(t0, t0, ctx->mem_idx);
Jia Liu9b1a1d62012-10-24 22:17:05 +080012688 gen_store_gpr(t0, rd);
12689 opn = "lhx";
12690 break;
12691 case OPC_LWX:
Aurelien Jarno2910c6cb2012-10-09 21:53:20 +020012692 tcg_gen_qemu_ld32s(t0, t0, ctx->mem_idx);
Jia Liu9b1a1d62012-10-24 22:17:05 +080012693 gen_store_gpr(t0, rd);
12694 opn = "lwx";
12695 break;
12696#if defined(TARGET_MIPS64)
12697 case OPC_LDX:
Aurelien Jarno2910c6cb2012-10-09 21:53:20 +020012698 tcg_gen_qemu_ld64(t0, t0, ctx->mem_idx);
Jia Liu9b1a1d62012-10-24 22:17:05 +080012699 gen_store_gpr(t0, rd);
12700 opn = "ldx";
12701 break;
12702#endif
12703 }
12704 (void)opn; /* avoid a compiler warning */
12705 MIPS_DEBUG("%s %s, %s(%s)", opn,
12706 regnames[rd], regnames[offset], regnames[base]);
12707 tcg_temp_free(t0);
12708}
12709
Jia Liu461c08d2012-10-24 22:17:06 +080012710static void gen_mipsdsp_arith(DisasContext *ctx, uint32_t op1, uint32_t op2,
12711 int ret, int v1, int v2)
12712{
12713 const char *opn = "mipsdsp arith";
12714 TCGv v1_t;
12715 TCGv v2_t;
12716
12717 if (ret == 0) {
12718 /* Treat as NOP. */
12719 MIPS_DEBUG("NOP");
12720 return;
12721 }
12722
12723 v1_t = tcg_temp_new();
12724 v2_t = tcg_temp_new();
12725
12726 gen_load_gpr(v1_t, v1);
12727 gen_load_gpr(v2_t, v2);
12728
12729 switch (op1) {
12730 /* OPC_MULT_G_2E is equal OPC_ADDUH_QB_DSP */
12731 case OPC_MULT_G_2E:
12732 check_dspr2(ctx);
12733 switch (op2) {
12734 case OPC_ADDUH_QB:
12735 gen_helper_adduh_qb(cpu_gpr[ret], v1_t, v2_t);
12736 break;
12737 case OPC_ADDUH_R_QB:
12738 gen_helper_adduh_r_qb(cpu_gpr[ret], v1_t, v2_t);
12739 break;
12740 case OPC_ADDQH_PH:
12741 gen_helper_addqh_ph(cpu_gpr[ret], v1_t, v2_t);
12742 break;
12743 case OPC_ADDQH_R_PH:
12744 gen_helper_addqh_r_ph(cpu_gpr[ret], v1_t, v2_t);
12745 break;
12746 case OPC_ADDQH_W:
12747 gen_helper_addqh_w(cpu_gpr[ret], v1_t, v2_t);
12748 break;
12749 case OPC_ADDQH_R_W:
12750 gen_helper_addqh_r_w(cpu_gpr[ret], v1_t, v2_t);
12751 break;
12752 case OPC_SUBUH_QB:
12753 gen_helper_subuh_qb(cpu_gpr[ret], v1_t, v2_t);
12754 break;
12755 case OPC_SUBUH_R_QB:
12756 gen_helper_subuh_r_qb(cpu_gpr[ret], v1_t, v2_t);
12757 break;
12758 case OPC_SUBQH_PH:
12759 gen_helper_subqh_ph(cpu_gpr[ret], v1_t, v2_t);
12760 break;
12761 case OPC_SUBQH_R_PH:
12762 gen_helper_subqh_r_ph(cpu_gpr[ret], v1_t, v2_t);
12763 break;
12764 case OPC_SUBQH_W:
12765 gen_helper_subqh_w(cpu_gpr[ret], v1_t, v2_t);
12766 break;
12767 case OPC_SUBQH_R_W:
12768 gen_helper_subqh_r_w(cpu_gpr[ret], v1_t, v2_t);
12769 break;
12770 }
12771 break;
12772 case OPC_ABSQ_S_PH_DSP:
12773 switch (op2) {
12774 case OPC_ABSQ_S_QB:
12775 check_dspr2(ctx);
12776 gen_helper_absq_s_qb(cpu_gpr[ret], v2_t, cpu_env);
12777 break;
12778 case OPC_ABSQ_S_PH:
12779 check_dsp(ctx);
12780 gen_helper_absq_s_ph(cpu_gpr[ret], v2_t, cpu_env);
12781 break;
12782 case OPC_ABSQ_S_W:
12783 check_dsp(ctx);
12784 gen_helper_absq_s_w(cpu_gpr[ret], v2_t, cpu_env);
12785 break;
12786 case OPC_PRECEQ_W_PHL:
12787 check_dsp(ctx);
12788 tcg_gen_andi_tl(cpu_gpr[ret], v2_t, 0xFFFF0000);
12789 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
12790 break;
12791 case OPC_PRECEQ_W_PHR:
12792 check_dsp(ctx);
12793 tcg_gen_andi_tl(cpu_gpr[ret], v2_t, 0x0000FFFF);
12794 tcg_gen_shli_tl(cpu_gpr[ret], cpu_gpr[ret], 16);
12795 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
12796 break;
12797 case OPC_PRECEQU_PH_QBL:
12798 check_dsp(ctx);
12799 gen_helper_precequ_ph_qbl(cpu_gpr[ret], v2_t);
12800 break;
12801 case OPC_PRECEQU_PH_QBR:
12802 check_dsp(ctx);
12803 gen_helper_precequ_ph_qbr(cpu_gpr[ret], v2_t);
12804 break;
12805 case OPC_PRECEQU_PH_QBLA:
12806 check_dsp(ctx);
12807 gen_helper_precequ_ph_qbla(cpu_gpr[ret], v2_t);
12808 break;
12809 case OPC_PRECEQU_PH_QBRA:
12810 check_dsp(ctx);
12811 gen_helper_precequ_ph_qbra(cpu_gpr[ret], v2_t);
12812 break;
12813 case OPC_PRECEU_PH_QBL:
12814 check_dsp(ctx);
12815 gen_helper_preceu_ph_qbl(cpu_gpr[ret], v2_t);
12816 break;
12817 case OPC_PRECEU_PH_QBR:
12818 check_dsp(ctx);
12819 gen_helper_preceu_ph_qbr(cpu_gpr[ret], v2_t);
12820 break;
12821 case OPC_PRECEU_PH_QBLA:
12822 check_dsp(ctx);
12823 gen_helper_preceu_ph_qbla(cpu_gpr[ret], v2_t);
12824 break;
12825 case OPC_PRECEU_PH_QBRA:
12826 check_dsp(ctx);
12827 gen_helper_preceu_ph_qbra(cpu_gpr[ret], v2_t);
12828 break;
12829 }
12830 break;
12831 case OPC_ADDU_QB_DSP:
12832 switch (op2) {
12833 case OPC_ADDQ_PH:
12834 check_dsp(ctx);
12835 gen_helper_addq_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
12836 break;
12837 case OPC_ADDQ_S_PH:
12838 check_dsp(ctx);
12839 gen_helper_addq_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
12840 break;
12841 case OPC_ADDQ_S_W:
12842 check_dsp(ctx);
12843 gen_helper_addq_s_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
12844 break;
12845 case OPC_ADDU_QB:
12846 check_dsp(ctx);
12847 gen_helper_addu_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
12848 break;
12849 case OPC_ADDU_S_QB:
12850 check_dsp(ctx);
12851 gen_helper_addu_s_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
12852 break;
12853 case OPC_ADDU_PH:
12854 check_dspr2(ctx);
12855 gen_helper_addu_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
12856 break;
12857 case OPC_ADDU_S_PH:
12858 check_dspr2(ctx);
12859 gen_helper_addu_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
12860 break;
12861 case OPC_SUBQ_PH:
12862 check_dsp(ctx);
12863 gen_helper_subq_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
12864 break;
12865 case OPC_SUBQ_S_PH:
12866 check_dsp(ctx);
12867 gen_helper_subq_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
12868 break;
12869 case OPC_SUBQ_S_W:
12870 check_dsp(ctx);
12871 gen_helper_subq_s_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
12872 break;
12873 case OPC_SUBU_QB:
12874 check_dsp(ctx);
12875 gen_helper_subu_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
12876 break;
12877 case OPC_SUBU_S_QB:
12878 check_dsp(ctx);
12879 gen_helper_subu_s_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
12880 break;
12881 case OPC_SUBU_PH:
12882 check_dspr2(ctx);
12883 gen_helper_subu_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
12884 break;
12885 case OPC_SUBU_S_PH:
12886 check_dspr2(ctx);
12887 gen_helper_subu_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
12888 break;
12889 case OPC_ADDSC:
12890 check_dsp(ctx);
12891 gen_helper_addsc(cpu_gpr[ret], v1_t, v2_t, cpu_env);
12892 break;
12893 case OPC_ADDWC:
12894 check_dsp(ctx);
12895 gen_helper_addwc(cpu_gpr[ret], v1_t, v2_t, cpu_env);
12896 break;
12897 case OPC_MODSUB:
12898 check_dsp(ctx);
12899 gen_helper_modsub(cpu_gpr[ret], v1_t, v2_t);
12900 break;
12901 case OPC_RADDU_W_QB:
12902 check_dsp(ctx);
12903 gen_helper_raddu_w_qb(cpu_gpr[ret], v1_t);
12904 break;
12905 }
12906 break;
12907 case OPC_CMPU_EQ_QB_DSP:
12908 switch (op2) {
12909 case OPC_PRECR_QB_PH:
12910 check_dspr2(ctx);
12911 gen_helper_precr_qb_ph(cpu_gpr[ret], v1_t, v2_t);
12912 break;
12913 case OPC_PRECRQ_QB_PH:
12914 check_dsp(ctx);
12915 gen_helper_precrq_qb_ph(cpu_gpr[ret], v1_t, v2_t);
12916 break;
12917 case OPC_PRECR_SRA_PH_W:
12918 check_dspr2(ctx);
12919 {
12920 TCGv_i32 sa_t = tcg_const_i32(v2);
12921 gen_helper_precr_sra_ph_w(cpu_gpr[ret], sa_t, v1_t,
12922 cpu_gpr[ret]);
12923 tcg_temp_free_i32(sa_t);
12924 break;
12925 }
12926 case OPC_PRECR_SRA_R_PH_W:
12927 check_dspr2(ctx);
12928 {
12929 TCGv_i32 sa_t = tcg_const_i32(v2);
12930 gen_helper_precr_sra_r_ph_w(cpu_gpr[ret], sa_t, v1_t,
12931 cpu_gpr[ret]);
12932 tcg_temp_free_i32(sa_t);
12933 break;
12934 }
12935 case OPC_PRECRQ_PH_W:
12936 check_dsp(ctx);
12937 gen_helper_precrq_ph_w(cpu_gpr[ret], v1_t, v2_t);
12938 break;
12939 case OPC_PRECRQ_RS_PH_W:
12940 check_dsp(ctx);
12941 gen_helper_precrq_rs_ph_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
12942 break;
12943 case OPC_PRECRQU_S_QB_PH:
12944 check_dsp(ctx);
12945 gen_helper_precrqu_s_qb_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
12946 break;
12947 }
12948 break;
12949#ifdef TARGET_MIPS64
12950 case OPC_ABSQ_S_QH_DSP:
12951 switch (op2) {
12952 case OPC_PRECEQ_L_PWL:
12953 check_dsp(ctx);
12954 tcg_gen_andi_tl(cpu_gpr[ret], v2_t, 0xFFFFFFFF00000000ull);
12955 break;
12956 case OPC_PRECEQ_L_PWR:
12957 check_dsp(ctx);
12958 tcg_gen_shli_tl(cpu_gpr[ret], v2_t, 32);
12959 break;
12960 case OPC_PRECEQ_PW_QHL:
12961 check_dsp(ctx);
12962 gen_helper_preceq_pw_qhl(cpu_gpr[ret], v2_t);
12963 break;
12964 case OPC_PRECEQ_PW_QHR:
12965 check_dsp(ctx);
12966 gen_helper_preceq_pw_qhr(cpu_gpr[ret], v2_t);
12967 break;
12968 case OPC_PRECEQ_PW_QHLA:
12969 check_dsp(ctx);
12970 gen_helper_preceq_pw_qhla(cpu_gpr[ret], v2_t);
12971 break;
12972 case OPC_PRECEQ_PW_QHRA:
12973 check_dsp(ctx);
12974 gen_helper_preceq_pw_qhra(cpu_gpr[ret], v2_t);
12975 break;
12976 case OPC_PRECEQU_QH_OBL:
12977 check_dsp(ctx);
12978 gen_helper_precequ_qh_obl(cpu_gpr[ret], v2_t);
12979 break;
12980 case OPC_PRECEQU_QH_OBR:
12981 check_dsp(ctx);
12982 gen_helper_precequ_qh_obr(cpu_gpr[ret], v2_t);
12983 break;
12984 case OPC_PRECEQU_QH_OBLA:
12985 check_dsp(ctx);
12986 gen_helper_precequ_qh_obla(cpu_gpr[ret], v2_t);
12987 break;
12988 case OPC_PRECEQU_QH_OBRA:
12989 check_dsp(ctx);
12990 gen_helper_precequ_qh_obra(cpu_gpr[ret], v2_t);
12991 break;
12992 case OPC_PRECEU_QH_OBL:
12993 check_dsp(ctx);
12994 gen_helper_preceu_qh_obl(cpu_gpr[ret], v2_t);
12995 break;
12996 case OPC_PRECEU_QH_OBR:
12997 check_dsp(ctx);
12998 gen_helper_preceu_qh_obr(cpu_gpr[ret], v2_t);
12999 break;
13000 case OPC_PRECEU_QH_OBLA:
13001 check_dsp(ctx);
13002 gen_helper_preceu_qh_obla(cpu_gpr[ret], v2_t);
13003 break;
13004 case OPC_PRECEU_QH_OBRA:
13005 check_dsp(ctx);
13006 gen_helper_preceu_qh_obra(cpu_gpr[ret], v2_t);
13007 break;
13008 case OPC_ABSQ_S_OB:
13009 check_dspr2(ctx);
13010 gen_helper_absq_s_ob(cpu_gpr[ret], v2_t, cpu_env);
13011 break;
13012 case OPC_ABSQ_S_PW:
13013 check_dsp(ctx);
13014 gen_helper_absq_s_pw(cpu_gpr[ret], v2_t, cpu_env);
13015 break;
13016 case OPC_ABSQ_S_QH:
13017 check_dsp(ctx);
13018 gen_helper_absq_s_qh(cpu_gpr[ret], v2_t, cpu_env);
13019 break;
13020 }
13021 break;
13022 case OPC_ADDU_OB_DSP:
13023 switch (op2) {
13024 case OPC_RADDU_L_OB:
13025 check_dsp(ctx);
13026 gen_helper_raddu_l_ob(cpu_gpr[ret], v1_t);
13027 break;
13028 case OPC_SUBQ_PW:
13029 check_dsp(ctx);
13030 gen_helper_subq_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
13031 break;
13032 case OPC_SUBQ_S_PW:
13033 check_dsp(ctx);
13034 gen_helper_subq_s_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
13035 break;
13036 case OPC_SUBQ_QH:
13037 check_dsp(ctx);
13038 gen_helper_subq_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
13039 break;
13040 case OPC_SUBQ_S_QH:
13041 check_dsp(ctx);
13042 gen_helper_subq_s_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
13043 break;
13044 case OPC_SUBU_OB:
13045 check_dsp(ctx);
13046 gen_helper_subu_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
13047 break;
13048 case OPC_SUBU_S_OB:
13049 check_dsp(ctx);
13050 gen_helper_subu_s_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
13051 break;
13052 case OPC_SUBU_QH:
13053 check_dspr2(ctx);
13054 gen_helper_subu_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
13055 break;
13056 case OPC_SUBU_S_QH:
13057 check_dspr2(ctx);
13058 gen_helper_subu_s_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
13059 break;
13060 case OPC_SUBUH_OB:
13061 check_dspr2(ctx);
13062 gen_helper_subuh_ob(cpu_gpr[ret], v1_t, v2_t);
13063 break;
13064 case OPC_SUBUH_R_OB:
13065 check_dspr2(ctx);
13066 gen_helper_subuh_r_ob(cpu_gpr[ret], v1_t, v2_t);
13067 break;
13068 case OPC_ADDQ_PW:
13069 check_dsp(ctx);
13070 gen_helper_addq_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
13071 break;
13072 case OPC_ADDQ_S_PW:
13073 check_dsp(ctx);
13074 gen_helper_addq_s_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
13075 break;
13076 case OPC_ADDQ_QH:
13077 check_dsp(ctx);
13078 gen_helper_addq_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
13079 break;
13080 case OPC_ADDQ_S_QH:
13081 check_dsp(ctx);
13082 gen_helper_addq_s_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
13083 break;
13084 case OPC_ADDU_OB:
13085 check_dsp(ctx);
13086 gen_helper_addu_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
13087 break;
13088 case OPC_ADDU_S_OB:
13089 check_dsp(ctx);
13090 gen_helper_addu_s_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
13091 break;
13092 case OPC_ADDU_QH:
13093 check_dspr2(ctx);
13094 gen_helper_addu_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
13095 break;
13096 case OPC_ADDU_S_QH:
13097 check_dspr2(ctx);
13098 gen_helper_addu_s_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
13099 break;
13100 case OPC_ADDUH_OB:
13101 check_dspr2(ctx);
13102 gen_helper_adduh_ob(cpu_gpr[ret], v1_t, v2_t);
13103 break;
13104 case OPC_ADDUH_R_OB:
13105 check_dspr2(ctx);
13106 gen_helper_adduh_r_ob(cpu_gpr[ret], v1_t, v2_t);
13107 break;
13108 }
13109 break;
13110 case OPC_CMPU_EQ_OB_DSP:
13111 switch (op2) {
13112 case OPC_PRECR_OB_QH:
13113 check_dspr2(ctx);
13114 gen_helper_precr_ob_qh(cpu_gpr[ret], v1_t, v2_t);
13115 break;
13116 case OPC_PRECR_SRA_QH_PW:
13117 check_dspr2(ctx);
13118 {
13119 TCGv_i32 ret_t = tcg_const_i32(ret);
13120 gen_helper_precr_sra_qh_pw(v2_t, v1_t, v2_t, ret_t);
13121 tcg_temp_free_i32(ret_t);
13122 break;
13123 }
13124 case OPC_PRECR_SRA_R_QH_PW:
13125 check_dspr2(ctx);
13126 {
13127 TCGv_i32 sa_v = tcg_const_i32(ret);
13128 gen_helper_precr_sra_r_qh_pw(v2_t, v1_t, v2_t, sa_v);
13129 tcg_temp_free_i32(sa_v);
13130 break;
13131 }
13132 case OPC_PRECRQ_OB_QH:
13133 check_dsp(ctx);
13134 gen_helper_precrq_ob_qh(cpu_gpr[ret], v1_t, v2_t);
13135 break;
13136 case OPC_PRECRQ_PW_L:
13137 check_dsp(ctx);
13138 gen_helper_precrq_pw_l(cpu_gpr[ret], v1_t, v2_t);
13139 break;
13140 case OPC_PRECRQ_QH_PW:
13141 check_dsp(ctx);
13142 gen_helper_precrq_qh_pw(cpu_gpr[ret], v1_t, v2_t);
13143 break;
13144 case OPC_PRECRQ_RS_QH_PW:
13145 check_dsp(ctx);
13146 gen_helper_precrq_rs_qh_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
13147 break;
13148 case OPC_PRECRQU_S_OB_QH:
13149 check_dsp(ctx);
13150 gen_helper_precrqu_s_ob_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
13151 break;
13152 }
13153 break;
13154#endif
13155 }
13156
13157 tcg_temp_free(v1_t);
13158 tcg_temp_free(v2_t);
13159
13160 (void)opn; /* avoid a compiler warning */
13161 MIPS_DEBUG("%s", opn);
13162}
Jia Liu9b1a1d62012-10-24 22:17:05 +080013163
Jia Liu77c5fa82012-10-24 22:17:07 +080013164static void gen_mipsdsp_shift(DisasContext *ctx, uint32_t opc,
13165 int ret, int v1, int v2)
13166{
13167 uint32_t op2;
13168 const char *opn = "mipsdsp shift";
13169 TCGv t0;
13170 TCGv v1_t;
13171 TCGv v2_t;
13172
13173 if (ret == 0) {
13174 /* Treat as NOP. */
13175 MIPS_DEBUG("NOP");
13176 return;
13177 }
13178
13179 t0 = tcg_temp_new();
13180 v1_t = tcg_temp_new();
13181 v2_t = tcg_temp_new();
13182
13183 tcg_gen_movi_tl(t0, v1);
13184 gen_load_gpr(v1_t, v1);
13185 gen_load_gpr(v2_t, v2);
13186
13187 switch (opc) {
13188 case OPC_SHLL_QB_DSP:
13189 {
13190 op2 = MASK_SHLL_QB(ctx->opcode);
13191 switch (op2) {
13192 case OPC_SHLL_QB:
13193 check_dsp(ctx);
13194 gen_helper_shll_qb(cpu_gpr[ret], t0, v2_t, cpu_env);
13195 break;
13196 case OPC_SHLLV_QB:
13197 check_dsp(ctx);
13198 gen_helper_shll_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
13199 break;
13200 case OPC_SHLL_PH:
13201 check_dsp(ctx);
13202 gen_helper_shll_ph(cpu_gpr[ret], t0, v2_t, cpu_env);
13203 break;
13204 case OPC_SHLLV_PH:
13205 check_dsp(ctx);
13206 gen_helper_shll_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
13207 break;
13208 case OPC_SHLL_S_PH:
13209 check_dsp(ctx);
13210 gen_helper_shll_s_ph(cpu_gpr[ret], t0, v2_t, cpu_env);
13211 break;
13212 case OPC_SHLLV_S_PH:
13213 check_dsp(ctx);
13214 gen_helper_shll_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
13215 break;
13216 case OPC_SHLL_S_W:
13217 check_dsp(ctx);
13218 gen_helper_shll_s_w(cpu_gpr[ret], t0, v2_t, cpu_env);
13219 break;
13220 case OPC_SHLLV_S_W:
13221 check_dsp(ctx);
13222 gen_helper_shll_s_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
13223 break;
13224 case OPC_SHRL_QB:
13225 check_dsp(ctx);
13226 gen_helper_shrl_qb(cpu_gpr[ret], t0, v2_t);
13227 break;
13228 case OPC_SHRLV_QB:
13229 check_dsp(ctx);
13230 gen_helper_shrl_qb(cpu_gpr[ret], v1_t, v2_t);
13231 break;
13232 case OPC_SHRL_PH:
13233 check_dspr2(ctx);
13234 gen_helper_shrl_ph(cpu_gpr[ret], t0, v2_t);
13235 break;
13236 case OPC_SHRLV_PH:
13237 check_dspr2(ctx);
13238 gen_helper_shrl_ph(cpu_gpr[ret], v1_t, v2_t);
13239 break;
13240 case OPC_SHRA_QB:
13241 check_dspr2(ctx);
13242 gen_helper_shra_qb(cpu_gpr[ret], t0, v2_t);
13243 break;
13244 case OPC_SHRA_R_QB:
13245 check_dspr2(ctx);
13246 gen_helper_shra_r_qb(cpu_gpr[ret], t0, v2_t);
13247 break;
13248 case OPC_SHRAV_QB:
13249 check_dspr2(ctx);
13250 gen_helper_shra_qb(cpu_gpr[ret], v1_t, v2_t);
13251 break;
13252 case OPC_SHRAV_R_QB:
13253 check_dspr2(ctx);
13254 gen_helper_shra_r_qb(cpu_gpr[ret], v1_t, v2_t);
13255 break;
13256 case OPC_SHRA_PH:
13257 check_dsp(ctx);
13258 gen_helper_shra_ph(cpu_gpr[ret], t0, v2_t);
13259 break;
13260 case OPC_SHRA_R_PH:
13261 check_dsp(ctx);
13262 gen_helper_shra_r_ph(cpu_gpr[ret], t0, v2_t);
13263 break;
13264 case OPC_SHRAV_PH:
13265 check_dsp(ctx);
13266 gen_helper_shra_ph(cpu_gpr[ret], v1_t, v2_t);
13267 break;
13268 case OPC_SHRAV_R_PH:
13269 check_dsp(ctx);
13270 gen_helper_shra_r_ph(cpu_gpr[ret], v1_t, v2_t);
13271 break;
13272 case OPC_SHRA_R_W:
13273 check_dsp(ctx);
13274 gen_helper_shra_r_w(cpu_gpr[ret], t0, v2_t);
13275 break;
13276 case OPC_SHRAV_R_W:
13277 check_dsp(ctx);
13278 gen_helper_shra_r_w(cpu_gpr[ret], v1_t, v2_t);
13279 break;
13280 default: /* Invalid */
13281 MIPS_INVAL("MASK SHLL.QB");
13282 generate_exception(ctx, EXCP_RI);
13283 break;
13284 }
13285 break;
13286 }
13287#ifdef TARGET_MIPS64
13288 case OPC_SHLL_OB_DSP:
13289 op2 = MASK_SHLL_OB(ctx->opcode);
13290 switch (op2) {
13291 case OPC_SHLL_PW:
13292 check_dsp(ctx);
13293 gen_helper_shll_pw(cpu_gpr[ret], v2_t, t0, cpu_env);
13294 break;
13295 case OPC_SHLLV_PW:
13296 check_dsp(ctx);
13297 gen_helper_shll_pw(cpu_gpr[ret], v2_t, v1_t, cpu_env);
13298 break;
13299 case OPC_SHLL_S_PW:
13300 check_dsp(ctx);
13301 gen_helper_shll_s_pw(cpu_gpr[ret], v2_t, t0, cpu_env);
13302 break;
13303 case OPC_SHLLV_S_PW:
13304 check_dsp(ctx);
13305 gen_helper_shll_s_pw(cpu_gpr[ret], v2_t, v1_t, cpu_env);
13306 break;
13307 case OPC_SHLL_OB:
13308 check_dsp(ctx);
13309 gen_helper_shll_ob(cpu_gpr[ret], v2_t, t0, cpu_env);
13310 break;
13311 case OPC_SHLLV_OB:
13312 check_dsp(ctx);
13313 gen_helper_shll_ob(cpu_gpr[ret], v2_t, v1_t, cpu_env);
13314 break;
13315 case OPC_SHLL_QH:
13316 check_dsp(ctx);
13317 gen_helper_shll_qh(cpu_gpr[ret], v2_t, t0, cpu_env);
13318 break;
13319 case OPC_SHLLV_QH:
13320 check_dsp(ctx);
13321 gen_helper_shll_qh(cpu_gpr[ret], v2_t, v1_t, cpu_env);
13322 break;
13323 case OPC_SHLL_S_QH:
13324 check_dsp(ctx);
13325 gen_helper_shll_s_qh(cpu_gpr[ret], v2_t, t0, cpu_env);
13326 break;
13327 case OPC_SHLLV_S_QH:
13328 check_dsp(ctx);
13329 gen_helper_shll_s_qh(cpu_gpr[ret], v2_t, v1_t, cpu_env);
13330 break;
13331 case OPC_SHRA_OB:
13332 check_dspr2(ctx);
13333 gen_helper_shra_ob(cpu_gpr[ret], v2_t, t0);
13334 break;
13335 case OPC_SHRAV_OB:
13336 check_dspr2(ctx);
13337 gen_helper_shra_ob(cpu_gpr[ret], v2_t, v1_t);
13338 break;
13339 case OPC_SHRA_R_OB:
13340 check_dspr2(ctx);
13341 gen_helper_shra_r_ob(cpu_gpr[ret], v2_t, t0);
13342 break;
13343 case OPC_SHRAV_R_OB:
13344 check_dspr2(ctx);
13345 gen_helper_shra_r_ob(cpu_gpr[ret], v2_t, v1_t);
13346 break;
13347 case OPC_SHRA_PW:
13348 check_dsp(ctx);
13349 gen_helper_shra_pw(cpu_gpr[ret], v2_t, t0);
13350 break;
13351 case OPC_SHRAV_PW:
13352 check_dsp(ctx);
13353 gen_helper_shra_pw(cpu_gpr[ret], v2_t, v1_t);
13354 break;
13355 case OPC_SHRA_R_PW:
13356 check_dsp(ctx);
13357 gen_helper_shra_r_pw(cpu_gpr[ret], v2_t, t0);
13358 break;
13359 case OPC_SHRAV_R_PW:
13360 check_dsp(ctx);
13361 gen_helper_shra_r_pw(cpu_gpr[ret], v2_t, v1_t);
13362 break;
13363 case OPC_SHRA_QH:
13364 check_dsp(ctx);
13365 gen_helper_shra_qh(cpu_gpr[ret], v2_t, t0);
13366 break;
13367 case OPC_SHRAV_QH:
13368 check_dsp(ctx);
13369 gen_helper_shra_qh(cpu_gpr[ret], v2_t, v1_t);
13370 break;
13371 case OPC_SHRA_R_QH:
13372 check_dsp(ctx);
13373 gen_helper_shra_r_qh(cpu_gpr[ret], v2_t, t0);
13374 break;
13375 case OPC_SHRAV_R_QH:
13376 check_dsp(ctx);
13377 gen_helper_shra_r_qh(cpu_gpr[ret], v2_t, v1_t);
13378 break;
13379 case OPC_SHRL_OB:
13380 check_dsp(ctx);
13381 gen_helper_shrl_ob(cpu_gpr[ret], v2_t, t0);
13382 break;
13383 case OPC_SHRLV_OB:
13384 check_dsp(ctx);
13385 gen_helper_shrl_ob(cpu_gpr[ret], v2_t, v1_t);
13386 break;
13387 case OPC_SHRL_QH:
13388 check_dspr2(ctx);
13389 gen_helper_shrl_qh(cpu_gpr[ret], v2_t, t0);
13390 break;
13391 case OPC_SHRLV_QH:
13392 check_dspr2(ctx);
13393 gen_helper_shrl_qh(cpu_gpr[ret], v2_t, v1_t);
13394 break;
13395 default: /* Invalid */
13396 MIPS_INVAL("MASK SHLL.OB");
13397 generate_exception(ctx, EXCP_RI);
13398 break;
13399 }
13400 break;
13401#endif
13402 }
13403
13404 tcg_temp_free(t0);
13405 tcg_temp_free(v1_t);
13406 tcg_temp_free(v2_t);
13407 (void)opn; /* avoid a compiler warning */
13408 MIPS_DEBUG("%s", opn);
13409}
13410
Jia Liua22260a2012-10-24 22:17:08 +080013411static void gen_mipsdsp_multiply(DisasContext *ctx, uint32_t op1, uint32_t op2,
13412 int ret, int v1, int v2, int check_ret)
13413{
13414 const char *opn = "mipsdsp multiply";
13415 TCGv_i32 t0;
13416 TCGv v1_t;
13417 TCGv v2_t;
13418
13419 if ((ret == 0) && (check_ret == 1)) {
13420 /* Treat as NOP. */
13421 MIPS_DEBUG("NOP");
13422 return;
13423 }
13424
13425 t0 = tcg_temp_new_i32();
13426 v1_t = tcg_temp_new();
13427 v2_t = tcg_temp_new();
13428
13429 tcg_gen_movi_i32(t0, ret);
13430 gen_load_gpr(v1_t, v1);
13431 gen_load_gpr(v2_t, v2);
13432
13433 switch (op1) {
13434 /* OPC_MULT_G_2E, OPC_ADDUH_QB_DSP, OPC_MUL_PH_DSP have
13435 * the same mask and op1. */
13436 case OPC_MULT_G_2E:
13437 switch (op2) {
13438 case OPC_MUL_PH:
13439 gen_helper_mul_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
13440 break;
13441 case OPC_MUL_S_PH:
13442 gen_helper_mul_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
13443 break;
13444 case OPC_MULQ_S_W:
13445 gen_helper_mulq_s_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
13446 break;
13447 case OPC_MULQ_RS_W:
13448 gen_helper_mulq_rs_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
13449 break;
13450 }
13451 break;
13452 case OPC_DPA_W_PH_DSP:
13453 switch (op2) {
13454 case OPC_DPAU_H_QBL:
13455 check_dsp(ctx);
13456 gen_helper_dpau_h_qbl(t0, v1_t, v2_t, cpu_env);
13457 break;
13458 case OPC_DPAU_H_QBR:
13459 check_dsp(ctx);
13460 gen_helper_dpau_h_qbr(t0, v1_t, v2_t, cpu_env);
13461 break;
13462 case OPC_DPSU_H_QBL:
13463 check_dsp(ctx);
13464 gen_helper_dpsu_h_qbl(t0, v1_t, v2_t, cpu_env);
13465 break;
13466 case OPC_DPSU_H_QBR:
13467 check_dsp(ctx);
13468 gen_helper_dpsu_h_qbr(t0, v1_t, v2_t, cpu_env);
13469 break;
13470 case OPC_DPA_W_PH:
13471 check_dspr2(ctx);
13472 gen_helper_dpa_w_ph(t0, v1_t, v2_t, cpu_env);
13473 break;
13474 case OPC_DPAX_W_PH:
13475 check_dspr2(ctx);
13476 gen_helper_dpax_w_ph(t0, v1_t, v2_t, cpu_env);
13477 break;
13478 case OPC_DPAQ_S_W_PH:
13479 check_dsp(ctx);
13480 gen_helper_dpaq_s_w_ph(t0, v1_t, v2_t, cpu_env);
13481 break;
13482 case OPC_DPAQX_S_W_PH:
13483 check_dspr2(ctx);
13484 gen_helper_dpaqx_s_w_ph(t0, v1_t, v2_t, cpu_env);
13485 break;
13486 case OPC_DPAQX_SA_W_PH:
13487 check_dspr2(ctx);
13488 gen_helper_dpaqx_sa_w_ph(t0, v1_t, v2_t, cpu_env);
13489 break;
13490 case OPC_DPS_W_PH:
13491 check_dspr2(ctx);
13492 gen_helper_dps_w_ph(t0, v1_t, v2_t, cpu_env);
13493 break;
13494 case OPC_DPSX_W_PH:
13495 check_dspr2(ctx);
13496 gen_helper_dpsx_w_ph(t0, v1_t, v2_t, cpu_env);
13497 break;
13498 case OPC_DPSQ_S_W_PH:
13499 check_dsp(ctx);
13500 gen_helper_dpsq_s_w_ph(t0, v1_t, v2_t, cpu_env);
13501 break;
13502 case OPC_DPSQX_S_W_PH:
13503 check_dspr2(ctx);
13504 gen_helper_dpsqx_s_w_ph(t0, v1_t, v2_t, cpu_env);
13505 break;
13506 case OPC_DPSQX_SA_W_PH:
13507 check_dspr2(ctx);
13508 gen_helper_dpsqx_sa_w_ph(t0, v1_t, v2_t, cpu_env);
13509 break;
13510 case OPC_MULSAQ_S_W_PH:
13511 check_dsp(ctx);
13512 gen_helper_mulsaq_s_w_ph(t0, v1_t, v2_t, cpu_env);
13513 break;
13514 case OPC_DPAQ_SA_L_W:
13515 check_dsp(ctx);
13516 gen_helper_dpaq_sa_l_w(t0, v1_t, v2_t, cpu_env);
13517 break;
13518 case OPC_DPSQ_SA_L_W:
13519 check_dsp(ctx);
13520 gen_helper_dpsq_sa_l_w(t0, v1_t, v2_t, cpu_env);
13521 break;
13522 case OPC_MAQ_S_W_PHL:
13523 check_dsp(ctx);
13524 gen_helper_maq_s_w_phl(t0, v1_t, v2_t, cpu_env);
13525 break;
13526 case OPC_MAQ_S_W_PHR:
13527 check_dsp(ctx);
13528 gen_helper_maq_s_w_phr(t0, v1_t, v2_t, cpu_env);
13529 break;
13530 case OPC_MAQ_SA_W_PHL:
13531 check_dsp(ctx);
13532 gen_helper_maq_sa_w_phl(t0, v1_t, v2_t, cpu_env);
13533 break;
13534 case OPC_MAQ_SA_W_PHR:
13535 check_dsp(ctx);
13536 gen_helper_maq_sa_w_phr(t0, v1_t, v2_t, cpu_env);
13537 break;
13538 case OPC_MULSA_W_PH:
13539 check_dspr2(ctx);
13540 gen_helper_mulsa_w_ph(t0, v1_t, v2_t, cpu_env);
13541 break;
13542 }
13543 break;
13544#ifdef TARGET_MIPS64
13545 case OPC_DPAQ_W_QH_DSP:
13546 {
13547 int ac = ret & 0x03;
13548 tcg_gen_movi_i32(t0, ac);
13549
13550 switch (op2) {
13551 case OPC_DMADD:
13552 check_dsp(ctx);
13553 gen_helper_dmadd(v1_t, v2_t, t0, cpu_env);
13554 break;
13555 case OPC_DMADDU:
13556 check_dsp(ctx);
13557 gen_helper_dmaddu(v1_t, v2_t, t0, cpu_env);
13558 break;
13559 case OPC_DMSUB:
13560 check_dsp(ctx);
13561 gen_helper_dmsub(v1_t, v2_t, t0, cpu_env);
13562 break;
13563 case OPC_DMSUBU:
13564 check_dsp(ctx);
13565 gen_helper_dmsubu(v1_t, v2_t, t0, cpu_env);
13566 break;
13567 case OPC_DPA_W_QH:
13568 check_dspr2(ctx);
13569 gen_helper_dpa_w_qh(v1_t, v2_t, t0, cpu_env);
13570 break;
13571 case OPC_DPAQ_S_W_QH:
13572 check_dsp(ctx);
13573 gen_helper_dpaq_s_w_qh(v1_t, v2_t, t0, cpu_env);
13574 break;
13575 case OPC_DPAQ_SA_L_PW:
13576 check_dsp(ctx);
13577 gen_helper_dpaq_sa_l_pw(v1_t, v2_t, t0, cpu_env);
13578 break;
13579 case OPC_DPAU_H_OBL:
13580 check_dsp(ctx);
13581 gen_helper_dpau_h_obl(v1_t, v2_t, t0, cpu_env);
13582 break;
13583 case OPC_DPAU_H_OBR:
13584 check_dsp(ctx);
13585 gen_helper_dpau_h_obr(v1_t, v2_t, t0, cpu_env);
13586 break;
13587 case OPC_DPS_W_QH:
13588 check_dspr2(ctx);
13589 gen_helper_dps_w_qh(v1_t, v2_t, t0, cpu_env);
13590 break;
13591 case OPC_DPSQ_S_W_QH:
13592 check_dsp(ctx);
13593 gen_helper_dpsq_s_w_qh(v1_t, v2_t, t0, cpu_env);
13594 break;
13595 case OPC_DPSQ_SA_L_PW:
13596 check_dsp(ctx);
13597 gen_helper_dpsq_sa_l_pw(v1_t, v2_t, t0, cpu_env);
13598 break;
13599 case OPC_DPSU_H_OBL:
13600 check_dsp(ctx);
13601 gen_helper_dpsu_h_obl(v1_t, v2_t, t0, cpu_env);
13602 break;
13603 case OPC_DPSU_H_OBR:
13604 check_dsp(ctx);
13605 gen_helper_dpsu_h_obr(v1_t, v2_t, t0, cpu_env);
13606 break;
13607 case OPC_MAQ_S_L_PWL:
13608 check_dsp(ctx);
13609 gen_helper_maq_s_l_pwl(v1_t, v2_t, t0, cpu_env);
13610 break;
13611 case OPC_MAQ_S_L_PWR:
13612 check_dsp(ctx);
13613 gen_helper_maq_s_l_pwr(v1_t, v2_t, t0, cpu_env);
13614 break;
13615 case OPC_MAQ_S_W_QHLL:
13616 check_dsp(ctx);
13617 gen_helper_maq_s_w_qhll(v1_t, v2_t, t0, cpu_env);
13618 break;
13619 case OPC_MAQ_SA_W_QHLL:
13620 check_dsp(ctx);
13621 gen_helper_maq_sa_w_qhll(v1_t, v2_t, t0, cpu_env);
13622 break;
13623 case OPC_MAQ_S_W_QHLR:
13624 check_dsp(ctx);
13625 gen_helper_maq_s_w_qhlr(v1_t, v2_t, t0, cpu_env);
13626 break;
13627 case OPC_MAQ_SA_W_QHLR:
13628 check_dsp(ctx);
13629 gen_helper_maq_sa_w_qhlr(v1_t, v2_t, t0, cpu_env);
13630 break;
13631 case OPC_MAQ_S_W_QHRL:
13632 check_dsp(ctx);
13633 gen_helper_maq_s_w_qhrl(v1_t, v2_t, t0, cpu_env);
13634 break;
13635 case OPC_MAQ_SA_W_QHRL:
13636 check_dsp(ctx);
13637 gen_helper_maq_sa_w_qhrl(v1_t, v2_t, t0, cpu_env);
13638 break;
13639 case OPC_MAQ_S_W_QHRR:
13640 check_dsp(ctx);
13641 gen_helper_maq_s_w_qhrr(v1_t, v2_t, t0, cpu_env);
13642 break;
13643 case OPC_MAQ_SA_W_QHRR:
13644 check_dsp(ctx);
13645 gen_helper_maq_sa_w_qhrr(v1_t, v2_t, t0, cpu_env);
13646 break;
13647 case OPC_MULSAQ_S_L_PW:
13648 check_dsp(ctx);
13649 gen_helper_mulsaq_s_l_pw(v1_t, v2_t, t0, cpu_env);
13650 break;
13651 case OPC_MULSAQ_S_W_QH:
13652 check_dsp(ctx);
13653 gen_helper_mulsaq_s_w_qh(v1_t, v2_t, t0, cpu_env);
13654 break;
13655 }
13656 }
13657 break;
13658#endif
13659 case OPC_ADDU_QB_DSP:
13660 switch (op2) {
13661 case OPC_MULEU_S_PH_QBL:
13662 check_dsp(ctx);
13663 gen_helper_muleu_s_ph_qbl(cpu_gpr[ret], v1_t, v2_t, cpu_env);
13664 break;
13665 case OPC_MULEU_S_PH_QBR:
13666 check_dsp(ctx);
13667 gen_helper_muleu_s_ph_qbr(cpu_gpr[ret], v1_t, v2_t, cpu_env);
13668 break;
13669 case OPC_MULQ_RS_PH:
13670 check_dsp(ctx);
13671 gen_helper_mulq_rs_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
13672 break;
13673 case OPC_MULEQ_S_W_PHL:
13674 check_dsp(ctx);
13675 gen_helper_muleq_s_w_phl(cpu_gpr[ret], v1_t, v2_t, cpu_env);
13676 break;
13677 case OPC_MULEQ_S_W_PHR:
13678 check_dsp(ctx);
13679 gen_helper_muleq_s_w_phr(cpu_gpr[ret], v1_t, v2_t, cpu_env);
13680 break;
13681 case OPC_MULQ_S_PH:
13682 check_dspr2(ctx);
13683 gen_helper_mulq_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
13684 break;
13685 }
13686 break;
13687#ifdef TARGET_MIPS64
13688 case OPC_ADDU_OB_DSP:
13689 switch (op2) {
13690 case OPC_MULEQ_S_PW_QHL:
13691 check_dsp(ctx);
13692 gen_helper_muleq_s_pw_qhl(cpu_gpr[ret], v1_t, v2_t, cpu_env);
13693 break;
13694 case OPC_MULEQ_S_PW_QHR:
13695 check_dsp(ctx);
13696 gen_helper_muleq_s_pw_qhr(cpu_gpr[ret], v1_t, v2_t, cpu_env);
13697 break;
13698 case OPC_MULEU_S_QH_OBL:
13699 check_dsp(ctx);
13700 gen_helper_muleu_s_qh_obl(cpu_gpr[ret], v1_t, v2_t, cpu_env);
13701 break;
13702 case OPC_MULEU_S_QH_OBR:
13703 check_dsp(ctx);
13704 gen_helper_muleu_s_qh_obr(cpu_gpr[ret], v1_t, v2_t, cpu_env);
13705 break;
13706 case OPC_MULQ_RS_QH:
13707 check_dsp(ctx);
13708 gen_helper_mulq_rs_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
13709 break;
13710 }
13711 break;
13712#endif
13713 }
13714
13715 tcg_temp_free_i32(t0);
13716 tcg_temp_free(v1_t);
13717 tcg_temp_free(v2_t);
13718
13719 (void)opn; /* avoid a compiler warning */
13720 MIPS_DEBUG("%s", opn);
13721
13722}
13723
Aurelien Jarnod75c1352013-01-01 18:02:22 +010013724static void gen_mipsdsp_bitinsn(DisasContext *ctx, uint32_t op1, uint32_t op2,
Jia Liu1cb66862012-10-24 22:17:09 +080013725 int ret, int val)
13726{
13727 const char *opn = "mipsdsp Bit/ Manipulation";
13728 int16_t imm;
13729 TCGv t0;
13730 TCGv val_t;
13731
13732 if (ret == 0) {
13733 /* Treat as NOP. */
13734 MIPS_DEBUG("NOP");
13735 return;
13736 }
13737
13738 t0 = tcg_temp_new();
13739 val_t = tcg_temp_new();
13740 gen_load_gpr(val_t, val);
13741
13742 switch (op1) {
13743 case OPC_ABSQ_S_PH_DSP:
13744 switch (op2) {
13745 case OPC_BITREV:
13746 check_dsp(ctx);
13747 gen_helper_bitrev(cpu_gpr[ret], val_t);
13748 break;
13749 case OPC_REPL_QB:
13750 check_dsp(ctx);
13751 {
13752 target_long result;
13753 imm = (ctx->opcode >> 16) & 0xFF;
13754 result = (uint32_t)imm << 24 |
13755 (uint32_t)imm << 16 |
13756 (uint32_t)imm << 8 |
13757 (uint32_t)imm;
13758 result = (int32_t)result;
13759 tcg_gen_movi_tl(cpu_gpr[ret], result);
13760 }
13761 break;
13762 case OPC_REPLV_QB:
13763 check_dsp(ctx);
13764 tcg_gen_ext8u_tl(cpu_gpr[ret], val_t);
13765 tcg_gen_shli_tl(t0, cpu_gpr[ret], 8);
13766 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
13767 tcg_gen_shli_tl(t0, cpu_gpr[ret], 16);
13768 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
13769 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
13770 break;
13771 case OPC_REPL_PH:
13772 check_dsp(ctx);
13773 {
13774 imm = (ctx->opcode >> 16) & 0x03FF;
Jovanovic, Petarc4aaba92012-12-11 15:06:35 +000013775 imm = (int16_t)(imm << 6) >> 6;
Jia Liu1cb66862012-10-24 22:17:09 +080013776 tcg_gen_movi_tl(cpu_gpr[ret], \
13777 (target_long)((int32_t)imm << 16 | \
Jovanovic, Petarc4aaba92012-12-11 15:06:35 +000013778 (uint16_t)imm));
Jia Liu1cb66862012-10-24 22:17:09 +080013779 }
13780 break;
13781 case OPC_REPLV_PH:
13782 check_dsp(ctx);
13783 tcg_gen_ext16u_tl(cpu_gpr[ret], val_t);
13784 tcg_gen_shli_tl(t0, cpu_gpr[ret], 16);
13785 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
13786 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
13787 break;
13788 }
13789 break;
13790#ifdef TARGET_MIPS64
13791 case OPC_ABSQ_S_QH_DSP:
13792 switch (op2) {
13793 case OPC_REPL_OB:
13794 check_dsp(ctx);
13795 {
13796 target_long temp;
13797
13798 imm = (ctx->opcode >> 16) & 0xFF;
13799 temp = ((uint64_t)imm << 8) | (uint64_t)imm;
13800 temp = (temp << 16) | temp;
13801 temp = (temp << 32) | temp;
13802 tcg_gen_movi_tl(cpu_gpr[ret], temp);
13803 break;
13804 }
13805 case OPC_REPL_PW:
13806 check_dsp(ctx);
13807 {
13808 target_long temp;
13809
13810 imm = (ctx->opcode >> 16) & 0x03FF;
13811 imm = (int16_t)(imm << 6) >> 6;
13812 temp = ((target_long)imm << 32) \
13813 | ((target_long)imm & 0xFFFFFFFF);
13814 tcg_gen_movi_tl(cpu_gpr[ret], temp);
13815 break;
13816 }
13817 case OPC_REPL_QH:
13818 check_dsp(ctx);
13819 {
13820 target_long temp;
13821
13822 imm = (ctx->opcode >> 16) & 0x03FF;
13823 imm = (int16_t)(imm << 6) >> 6;
13824
13825 temp = ((uint64_t)(uint16_t)imm << 48) |
13826 ((uint64_t)(uint16_t)imm << 32) |
13827 ((uint64_t)(uint16_t)imm << 16) |
13828 (uint64_t)(uint16_t)imm;
13829 tcg_gen_movi_tl(cpu_gpr[ret], temp);
13830 break;
13831 }
13832 case OPC_REPLV_OB:
13833 check_dsp(ctx);
13834 tcg_gen_ext8u_tl(cpu_gpr[ret], val_t);
13835 tcg_gen_shli_tl(t0, cpu_gpr[ret], 8);
13836 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
13837 tcg_gen_shli_tl(t0, cpu_gpr[ret], 16);
13838 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
13839 tcg_gen_shli_tl(t0, cpu_gpr[ret], 32);
13840 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
13841 break;
13842 case OPC_REPLV_PW:
13843 check_dsp(ctx);
13844 tcg_gen_ext32u_i64(cpu_gpr[ret], val_t);
13845 tcg_gen_shli_tl(t0, cpu_gpr[ret], 32);
13846 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
13847 break;
13848 case OPC_REPLV_QH:
13849 check_dsp(ctx);
13850 tcg_gen_ext16u_tl(cpu_gpr[ret], val_t);
13851 tcg_gen_shli_tl(t0, cpu_gpr[ret], 16);
13852 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
13853 tcg_gen_shli_tl(t0, cpu_gpr[ret], 32);
13854 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
13855 break;
13856 }
13857 break;
13858#endif
13859 }
13860 tcg_temp_free(t0);
13861 tcg_temp_free(val_t);
13862
13863 (void)opn; /* avoid a compiler warning */
13864 MIPS_DEBUG("%s", opn);
13865}
13866
Jia Liu26690562012-10-24 22:17:10 +080013867static void gen_mipsdsp_add_cmp_pick(DisasContext *ctx,
13868 uint32_t op1, uint32_t op2,
13869 int ret, int v1, int v2, int check_ret)
13870{
13871 const char *opn = "mipsdsp add compare pick";
Jia Liu26690562012-10-24 22:17:10 +080013872 TCGv t1;
13873 TCGv v1_t;
13874 TCGv v2_t;
13875
13876 if ((ret == 0) && (check_ret == 1)) {
13877 /* Treat as NOP. */
13878 MIPS_DEBUG("NOP");
13879 return;
13880 }
13881
Jia Liu26690562012-10-24 22:17:10 +080013882 t1 = tcg_temp_new();
13883 v1_t = tcg_temp_new();
13884 v2_t = tcg_temp_new();
13885
13886 gen_load_gpr(v1_t, v1);
13887 gen_load_gpr(v2_t, v2);
13888
13889 switch (op1) {
Jia Liu26690562012-10-24 22:17:10 +080013890 case OPC_CMPU_EQ_QB_DSP:
13891 switch (op2) {
13892 case OPC_CMPU_EQ_QB:
13893 check_dsp(ctx);
13894 gen_helper_cmpu_eq_qb(v1_t, v2_t, cpu_env);
13895 break;
13896 case OPC_CMPU_LT_QB:
13897 check_dsp(ctx);
13898 gen_helper_cmpu_lt_qb(v1_t, v2_t, cpu_env);
13899 break;
13900 case OPC_CMPU_LE_QB:
13901 check_dsp(ctx);
13902 gen_helper_cmpu_le_qb(v1_t, v2_t, cpu_env);
13903 break;
13904 case OPC_CMPGU_EQ_QB:
13905 check_dsp(ctx);
13906 gen_helper_cmpgu_eq_qb(cpu_gpr[ret], v1_t, v2_t);
13907 break;
13908 case OPC_CMPGU_LT_QB:
13909 check_dsp(ctx);
13910 gen_helper_cmpgu_lt_qb(cpu_gpr[ret], v1_t, v2_t);
13911 break;
13912 case OPC_CMPGU_LE_QB:
13913 check_dsp(ctx);
13914 gen_helper_cmpgu_le_qb(cpu_gpr[ret], v1_t, v2_t);
13915 break;
13916 case OPC_CMPGDU_EQ_QB:
13917 check_dspr2(ctx);
13918 gen_helper_cmpgu_eq_qb(t1, v1_t, v2_t);
13919 tcg_gen_mov_tl(cpu_gpr[ret], t1);
13920 tcg_gen_andi_tl(cpu_dspctrl, cpu_dspctrl, 0xF0FFFFFF);
13921 tcg_gen_shli_tl(t1, t1, 24);
13922 tcg_gen_or_tl(cpu_dspctrl, cpu_dspctrl, t1);
13923 break;
13924 case OPC_CMPGDU_LT_QB:
13925 check_dspr2(ctx);
13926 gen_helper_cmpgu_lt_qb(t1, v1_t, v2_t);
13927 tcg_gen_mov_tl(cpu_gpr[ret], t1);
13928 tcg_gen_andi_tl(cpu_dspctrl, cpu_dspctrl, 0xF0FFFFFF);
13929 tcg_gen_shli_tl(t1, t1, 24);
13930 tcg_gen_or_tl(cpu_dspctrl, cpu_dspctrl, t1);
13931 break;
13932 case OPC_CMPGDU_LE_QB:
13933 check_dspr2(ctx);
13934 gen_helper_cmpgu_le_qb(t1, v1_t, v2_t);
13935 tcg_gen_mov_tl(cpu_gpr[ret], t1);
13936 tcg_gen_andi_tl(cpu_dspctrl, cpu_dspctrl, 0xF0FFFFFF);
13937 tcg_gen_shli_tl(t1, t1, 24);
13938 tcg_gen_or_tl(cpu_dspctrl, cpu_dspctrl, t1);
13939 break;
13940 case OPC_CMP_EQ_PH:
13941 check_dsp(ctx);
13942 gen_helper_cmp_eq_ph(v1_t, v2_t, cpu_env);
13943 break;
13944 case OPC_CMP_LT_PH:
13945 check_dsp(ctx);
13946 gen_helper_cmp_lt_ph(v1_t, v2_t, cpu_env);
13947 break;
13948 case OPC_CMP_LE_PH:
13949 check_dsp(ctx);
13950 gen_helper_cmp_le_ph(v1_t, v2_t, cpu_env);
13951 break;
13952 case OPC_PICK_QB:
13953 check_dsp(ctx);
13954 gen_helper_pick_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
13955 break;
13956 case OPC_PICK_PH:
13957 check_dsp(ctx);
13958 gen_helper_pick_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
13959 break;
13960 case OPC_PACKRL_PH:
13961 check_dsp(ctx);
13962 gen_helper_packrl_ph(cpu_gpr[ret], v1_t, v2_t);
13963 break;
13964 }
13965 break;
13966#ifdef TARGET_MIPS64
13967 case OPC_CMPU_EQ_OB_DSP:
13968 switch (op2) {
13969 case OPC_CMP_EQ_PW:
13970 check_dsp(ctx);
13971 gen_helper_cmp_eq_pw(v1_t, v2_t, cpu_env);
13972 break;
13973 case OPC_CMP_LT_PW:
13974 check_dsp(ctx);
13975 gen_helper_cmp_lt_pw(v1_t, v2_t, cpu_env);
13976 break;
13977 case OPC_CMP_LE_PW:
13978 check_dsp(ctx);
13979 gen_helper_cmp_le_pw(v1_t, v2_t, cpu_env);
13980 break;
13981 case OPC_CMP_EQ_QH:
13982 check_dsp(ctx);
13983 gen_helper_cmp_eq_qh(v1_t, v2_t, cpu_env);
13984 break;
13985 case OPC_CMP_LT_QH:
13986 check_dsp(ctx);
13987 gen_helper_cmp_lt_qh(v1_t, v2_t, cpu_env);
13988 break;
13989 case OPC_CMP_LE_QH:
13990 check_dsp(ctx);
13991 gen_helper_cmp_le_qh(v1_t, v2_t, cpu_env);
13992 break;
13993 case OPC_CMPGDU_EQ_OB:
13994 check_dspr2(ctx);
13995 gen_helper_cmpgdu_eq_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
13996 break;
13997 case OPC_CMPGDU_LT_OB:
13998 check_dspr2(ctx);
13999 gen_helper_cmpgdu_lt_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
14000 break;
14001 case OPC_CMPGDU_LE_OB:
14002 check_dspr2(ctx);
14003 gen_helper_cmpgdu_le_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
14004 break;
14005 case OPC_CMPGU_EQ_OB:
14006 check_dsp(ctx);
14007 gen_helper_cmpgu_eq_ob(cpu_gpr[ret], v1_t, v2_t);
14008 break;
14009 case OPC_CMPGU_LT_OB:
14010 check_dsp(ctx);
14011 gen_helper_cmpgu_lt_ob(cpu_gpr[ret], v1_t, v2_t);
14012 break;
14013 case OPC_CMPGU_LE_OB:
14014 check_dsp(ctx);
14015 gen_helper_cmpgu_le_ob(cpu_gpr[ret], v1_t, v2_t);
14016 break;
14017 case OPC_CMPU_EQ_OB:
14018 check_dsp(ctx);
14019 gen_helper_cmpu_eq_ob(v1_t, v2_t, cpu_env);
14020 break;
14021 case OPC_CMPU_LT_OB:
14022 check_dsp(ctx);
14023 gen_helper_cmpu_lt_ob(v1_t, v2_t, cpu_env);
14024 break;
14025 case OPC_CMPU_LE_OB:
14026 check_dsp(ctx);
14027 gen_helper_cmpu_le_ob(v1_t, v2_t, cpu_env);
14028 break;
14029 case OPC_PACKRL_PW:
14030 check_dsp(ctx);
14031 gen_helper_packrl_pw(cpu_gpr[ret], v1_t, v2_t);
14032 break;
14033 case OPC_PICK_OB:
14034 check_dsp(ctx);
14035 gen_helper_pick_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
14036 break;
14037 case OPC_PICK_PW:
14038 check_dsp(ctx);
14039 gen_helper_pick_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
14040 break;
14041 case OPC_PICK_QH:
14042 check_dsp(ctx);
14043 gen_helper_pick_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
14044 break;
14045 }
14046 break;
Aurelien Jarnodf6126a2013-01-01 18:02:24 +010014047#endif
14048 }
14049
14050 tcg_temp_free(t1);
14051 tcg_temp_free(v1_t);
14052 tcg_temp_free(v2_t);
14053
14054 (void)opn; /* avoid a compiler warning */
14055 MIPS_DEBUG("%s", opn);
14056}
14057
14058static void gen_mipsdsp_append(CPUMIPSState *env, DisasContext *ctx,
14059 uint32_t op1, int rt, int rs, int sa)
14060{
14061 const char *opn = "mipsdsp append/dappend";
14062 TCGv t0;
14063
14064 check_dspr2(ctx);
14065
14066 if (rt == 0) {
14067 /* Treat as NOP. */
14068 MIPS_DEBUG("NOP");
14069 return;
14070 }
14071
14072 t0 = tcg_temp_new();
14073 gen_load_gpr(t0, rs);
14074
14075 switch (op1) {
14076 case OPC_APPEND_DSP:
14077 switch (MASK_APPEND(ctx->opcode)) {
14078 case OPC_APPEND:
14079 if (sa != 0) {
14080 tcg_gen_deposit_tl(cpu_gpr[rt], t0, cpu_gpr[rt], sa, 32 - sa);
14081 }
14082 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
14083 break;
14084 case OPC_PREPEND:
14085 if (sa != 0) {
14086 tcg_gen_ext32u_tl(cpu_gpr[rt], cpu_gpr[rt]);
14087 tcg_gen_shri_tl(cpu_gpr[rt], cpu_gpr[rt], sa);
14088 tcg_gen_shli_tl(t0, t0, 32 - sa);
14089 tcg_gen_or_tl(cpu_gpr[rt], cpu_gpr[rt], t0);
14090 }
14091 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
14092 break;
14093 case OPC_BALIGN:
14094 sa &= 3;
14095 if (sa != 0 && sa != 2) {
14096 tcg_gen_shli_tl(cpu_gpr[rt], cpu_gpr[rt], 8 * sa);
14097 tcg_gen_ext32u_tl(t0, t0);
14098 tcg_gen_shri_tl(t0, t0, 8 * (4 - sa));
14099 tcg_gen_or_tl(cpu_gpr[rt], cpu_gpr[rt], t0);
14100 }
14101 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
14102 break;
14103 default: /* Invalid */
14104 MIPS_INVAL("MASK APPEND");
14105 generate_exception(ctx, EXCP_RI);
14106 break;
14107 }
14108 break;
14109#ifdef TARGET_MIPS64
Jia Liu26690562012-10-24 22:17:10 +080014110 case OPC_DAPPEND_DSP:
Aurelien Jarnodf6126a2013-01-01 18:02:24 +010014111 switch (MASK_DAPPEND(ctx->opcode)) {
Jia Liu26690562012-10-24 22:17:10 +080014112 case OPC_DAPPEND:
Aurelien Jarnodf6126a2013-01-01 18:02:24 +010014113 if (sa != 0) {
14114 tcg_gen_deposit_tl(cpu_gpr[rt], t0, cpu_gpr[rt], sa, 64 - sa);
14115 }
Jia Liu26690562012-10-24 22:17:10 +080014116 break;
14117 case OPC_PREPENDD:
Aurelien Jarnodf6126a2013-01-01 18:02:24 +010014118 tcg_gen_shri_tl(cpu_gpr[rt], cpu_gpr[rt], 0x20 | sa);
14119 tcg_gen_shli_tl(t0, t0, 64 - (0x20 | sa));
14120 tcg_gen_or_tl(cpu_gpr[rt], t0, t0);
Jia Liu26690562012-10-24 22:17:10 +080014121 break;
14122 case OPC_PREPENDW:
Aurelien Jarnodf6126a2013-01-01 18:02:24 +010014123 if (sa != 0) {
14124 tcg_gen_shri_tl(cpu_gpr[rt], cpu_gpr[rt], sa);
14125 tcg_gen_shli_tl(t0, t0, 64 - sa);
14126 tcg_gen_or_tl(cpu_gpr[rt], cpu_gpr[rt], t0);
14127 }
Jia Liu26690562012-10-24 22:17:10 +080014128 break;
14129 case OPC_DBALIGN:
Aurelien Jarnodf6126a2013-01-01 18:02:24 +010014130 sa &= 7;
14131 if (sa != 0 && sa != 2 && sa != 4) {
14132 tcg_gen_shli_tl(cpu_gpr[rt], cpu_gpr[rt], 8 * sa);
14133 tcg_gen_shri_tl(t0, t0, 8 * (8 - sa));
14134 tcg_gen_or_tl(cpu_gpr[rt], cpu_gpr[rt], t0);
14135 }
Jia Liu26690562012-10-24 22:17:10 +080014136 break;
14137 default: /* Invalid */
14138 MIPS_INVAL("MASK DAPPEND");
14139 generate_exception(ctx, EXCP_RI);
14140 break;
14141 }
14142 break;
14143#endif
14144 }
Aurelien Jarnodf6126a2013-01-01 18:02:24 +010014145 tcg_temp_free(t0);
Jia Liu26690562012-10-24 22:17:10 +080014146 (void)opn; /* avoid a compiler warning */
14147 MIPS_DEBUG("%s", opn);
14148}
14149
Jia Liub53371e2012-10-24 22:17:11 +080014150static void gen_mipsdsp_accinsn(DisasContext *ctx, uint32_t op1, uint32_t op2,
14151 int ret, int v1, int v2, int check_ret)
14152
14153{
14154 const char *opn = "mipsdsp accumulator";
14155 TCGv t0;
14156 TCGv t1;
14157 TCGv v1_t;
14158 TCGv v2_t;
14159 int16_t imm;
14160
14161 if ((ret == 0) && (check_ret == 1)) {
14162 /* Treat as NOP. */
14163 MIPS_DEBUG("NOP");
14164 return;
14165 }
14166
14167 t0 = tcg_temp_new();
14168 t1 = tcg_temp_new();
14169 v1_t = tcg_temp_new();
14170 v2_t = tcg_temp_new();
14171
14172 gen_load_gpr(v1_t, v1);
14173 gen_load_gpr(v2_t, v2);
14174
14175 switch (op1) {
14176 case OPC_EXTR_W_DSP:
14177 check_dsp(ctx);
14178 switch (op2) {
14179 case OPC_EXTR_W:
14180 tcg_gen_movi_tl(t0, v2);
14181 tcg_gen_movi_tl(t1, v1);
14182 gen_helper_extr_w(cpu_gpr[ret], t0, t1, cpu_env);
14183 break;
14184 case OPC_EXTR_R_W:
14185 tcg_gen_movi_tl(t0, v2);
14186 tcg_gen_movi_tl(t1, v1);
14187 gen_helper_extr_r_w(cpu_gpr[ret], t0, t1, cpu_env);
14188 break;
14189 case OPC_EXTR_RS_W:
14190 tcg_gen_movi_tl(t0, v2);
14191 tcg_gen_movi_tl(t1, v1);
14192 gen_helper_extr_rs_w(cpu_gpr[ret], t0, t1, cpu_env);
14193 break;
14194 case OPC_EXTR_S_H:
14195 tcg_gen_movi_tl(t0, v2);
14196 tcg_gen_movi_tl(t1, v1);
14197 gen_helper_extr_s_h(cpu_gpr[ret], t0, t1, cpu_env);
14198 break;
14199 case OPC_EXTRV_S_H:
14200 tcg_gen_movi_tl(t0, v2);
14201 gen_helper_extr_s_h(cpu_gpr[ret], t0, v1_t, cpu_env);
14202 break;
14203 case OPC_EXTRV_W:
14204 tcg_gen_movi_tl(t0, v2);
14205 gen_helper_extr_w(cpu_gpr[ret], t0, v1_t, cpu_env);
14206 break;
14207 case OPC_EXTRV_R_W:
14208 tcg_gen_movi_tl(t0, v2);
14209 gen_helper_extr_r_w(cpu_gpr[ret], t0, v1_t, cpu_env);
14210 break;
14211 case OPC_EXTRV_RS_W:
14212 tcg_gen_movi_tl(t0, v2);
14213 gen_helper_extr_rs_w(cpu_gpr[ret], t0, v1_t, cpu_env);
14214 break;
14215 case OPC_EXTP:
14216 tcg_gen_movi_tl(t0, v2);
14217 tcg_gen_movi_tl(t1, v1);
14218 gen_helper_extp(cpu_gpr[ret], t0, t1, cpu_env);
14219 break;
14220 case OPC_EXTPV:
14221 tcg_gen_movi_tl(t0, v2);
14222 gen_helper_extp(cpu_gpr[ret], t0, v1_t, cpu_env);
14223 break;
14224 case OPC_EXTPDP:
14225 tcg_gen_movi_tl(t0, v2);
14226 tcg_gen_movi_tl(t1, v1);
14227 gen_helper_extpdp(cpu_gpr[ret], t0, t1, cpu_env);
14228 break;
14229 case OPC_EXTPDPV:
14230 tcg_gen_movi_tl(t0, v2);
14231 gen_helper_extpdp(cpu_gpr[ret], t0, v1_t, cpu_env);
14232 break;
14233 case OPC_SHILO:
14234 imm = (ctx->opcode >> 20) & 0x3F;
14235 tcg_gen_movi_tl(t0, ret);
14236 tcg_gen_movi_tl(t1, imm);
14237 gen_helper_shilo(t0, t1, cpu_env);
14238 break;
14239 case OPC_SHILOV:
14240 tcg_gen_movi_tl(t0, ret);
14241 gen_helper_shilo(t0, v1_t, cpu_env);
14242 break;
14243 case OPC_MTHLIP:
14244 tcg_gen_movi_tl(t0, ret);
14245 gen_helper_mthlip(t0, v1_t, cpu_env);
14246 break;
14247 case OPC_WRDSP:
14248 imm = (ctx->opcode >> 11) & 0x3FF;
14249 tcg_gen_movi_tl(t0, imm);
14250 gen_helper_wrdsp(v1_t, t0, cpu_env);
14251 break;
14252 case OPC_RDDSP:
14253 imm = (ctx->opcode >> 16) & 0x03FF;
14254 tcg_gen_movi_tl(t0, imm);
14255 gen_helper_rddsp(cpu_gpr[ret], t0, cpu_env);
14256 break;
14257 }
14258 break;
14259#ifdef TARGET_MIPS64
14260 case OPC_DEXTR_W_DSP:
14261 check_dsp(ctx);
14262 switch (op2) {
14263 case OPC_DMTHLIP:
14264 tcg_gen_movi_tl(t0, ret);
14265 gen_helper_dmthlip(v1_t, t0, cpu_env);
14266 break;
14267 case OPC_DSHILO:
14268 {
14269 int shift = (ctx->opcode >> 19) & 0x7F;
14270 int ac = (ctx->opcode >> 11) & 0x03;
14271 tcg_gen_movi_tl(t0, shift);
14272 tcg_gen_movi_tl(t1, ac);
14273 gen_helper_dshilo(t0, t1, cpu_env);
14274 break;
14275 }
14276 case OPC_DSHILOV:
14277 {
14278 int ac = (ctx->opcode >> 11) & 0x03;
14279 tcg_gen_movi_tl(t0, ac);
14280 gen_helper_dshilo(v1_t, t0, cpu_env);
14281 break;
14282 }
14283 case OPC_DEXTP:
14284 tcg_gen_movi_tl(t0, v2);
14285 tcg_gen_movi_tl(t1, v1);
14286
14287 gen_helper_dextp(cpu_gpr[ret], t0, t1, cpu_env);
14288 break;
14289 case OPC_DEXTPV:
14290 tcg_gen_movi_tl(t0, v2);
14291 gen_helper_dextp(cpu_gpr[ret], t0, v1_t, cpu_env);
14292 break;
14293 case OPC_DEXTPDP:
14294 tcg_gen_movi_tl(t0, v2);
14295 tcg_gen_movi_tl(t1, v1);
14296 gen_helper_dextpdp(cpu_gpr[ret], t0, t1, cpu_env);
14297 break;
14298 case OPC_DEXTPDPV:
14299 tcg_gen_movi_tl(t0, v2);
14300 gen_helper_dextpdp(cpu_gpr[ret], t0, v1_t, cpu_env);
14301 break;
14302 case OPC_DEXTR_L:
14303 tcg_gen_movi_tl(t0, v2);
14304 tcg_gen_movi_tl(t1, v1);
14305 gen_helper_dextr_l(cpu_gpr[ret], t0, t1, cpu_env);
14306 break;
14307 case OPC_DEXTR_R_L:
14308 tcg_gen_movi_tl(t0, v2);
14309 tcg_gen_movi_tl(t1, v1);
14310 gen_helper_dextr_r_l(cpu_gpr[ret], t0, t1, cpu_env);
14311 break;
14312 case OPC_DEXTR_RS_L:
14313 tcg_gen_movi_tl(t0, v2);
14314 tcg_gen_movi_tl(t1, v1);
14315 gen_helper_dextr_rs_l(cpu_gpr[ret], t0, t1, cpu_env);
14316 break;
14317 case OPC_DEXTR_W:
14318 tcg_gen_movi_tl(t0, v2);
14319 tcg_gen_movi_tl(t1, v1);
14320 gen_helper_dextr_w(cpu_gpr[ret], t0, t1, cpu_env);
14321 break;
14322 case OPC_DEXTR_R_W:
14323 tcg_gen_movi_tl(t0, v2);
14324 tcg_gen_movi_tl(t1, v1);
14325 gen_helper_dextr_r_w(cpu_gpr[ret], t0, t1, cpu_env);
14326 break;
14327 case OPC_DEXTR_RS_W:
14328 tcg_gen_movi_tl(t0, v2);
14329 tcg_gen_movi_tl(t1, v1);
14330 gen_helper_dextr_rs_w(cpu_gpr[ret], t0, t1, cpu_env);
14331 break;
14332 case OPC_DEXTR_S_H:
14333 tcg_gen_movi_tl(t0, v2);
14334 tcg_gen_movi_tl(t1, v1);
14335 gen_helper_dextr_s_h(cpu_gpr[ret], t0, t1, cpu_env);
14336 break;
14337 case OPC_DEXTRV_S_H:
14338 tcg_gen_movi_tl(t0, v2);
14339 tcg_gen_movi_tl(t1, v1);
14340 gen_helper_dextr_s_h(cpu_gpr[ret], t0, t1, cpu_env);
14341 break;
14342 case OPC_DEXTRV_L:
14343 tcg_gen_movi_tl(t0, v2);
14344 gen_helper_dextr_l(cpu_gpr[ret], t0, v1_t, cpu_env);
14345 break;
14346 case OPC_DEXTRV_R_L:
14347 tcg_gen_movi_tl(t0, v2);
14348 gen_helper_dextr_r_l(cpu_gpr[ret], t0, v1_t, cpu_env);
14349 break;
14350 case OPC_DEXTRV_RS_L:
14351 tcg_gen_movi_tl(t0, v2);
14352 gen_helper_dextr_rs_l(cpu_gpr[ret], t0, v1_t, cpu_env);
14353 break;
14354 case OPC_DEXTRV_W:
14355 tcg_gen_movi_tl(t0, v2);
14356 gen_helper_dextr_w(cpu_gpr[ret], t0, v1_t, cpu_env);
14357 break;
14358 case OPC_DEXTRV_R_W:
14359 tcg_gen_movi_tl(t0, v2);
14360 gen_helper_dextr_r_w(cpu_gpr[ret], t0, v1_t, cpu_env);
14361 break;
14362 case OPC_DEXTRV_RS_W:
14363 tcg_gen_movi_tl(t0, v2);
14364 gen_helper_dextr_rs_w(cpu_gpr[ret], t0, v1_t, cpu_env);
14365 break;
14366 }
14367 break;
14368#endif
14369 }
14370
14371 tcg_temp_free(t0);
14372 tcg_temp_free(t1);
14373 tcg_temp_free(v1_t);
14374 tcg_temp_free(v2_t);
14375
14376 (void)opn; /* avoid a compiler warning */
14377 MIPS_DEBUG("%s", opn);
14378}
14379
Jia Liu9b1a1d62012-10-24 22:17:05 +080014380/* End MIPSDSP functions. */
14381
Andreas Färber7db13fa2012-03-14 01:38:22 +010014382static void decode_opc (CPUMIPSState *env, DisasContext *ctx, int *is_branch)
bellard6af0bf92005-07-02 14:58:51 +000014383{
14384 int32_t offset;
14385 int rs, rt, rd, sa;
ths7a387ff2006-12-06 20:17:30 +000014386 uint32_t op, op1, op2;
bellard6af0bf92005-07-02 14:58:51 +000014387 int16_t imm;
14388
bellardd7963212006-06-26 20:02:45 +000014389 /* make sure instructions are on a word boundary */
14390 if (ctx->pc & 0x3) {
thscbeb0852007-04-07 01:11:15 +000014391 env->CP0_BadVAddr = ctx->pc;
bellardd7963212006-06-26 20:02:45 +000014392 generate_exception(ctx, EXCP_AdEL);
14393 return;
14394 }
14395
ths8e9ade62008-05-22 17:46:10 +000014396 /* Handle blikely not taken case */
Nathan Froydc9602062009-12-08 08:06:27 -080014397 if ((ctx->hflags & MIPS_HFLAG_BMASK_BASE) == MIPS_HFLAG_BL) {
ths8e9ade62008-05-22 17:46:10 +000014398 int l1 = gen_new_label();
14399
ths3594c772007-02-20 23:37:21 +000014400 MIPS_DEBUG("blikely condition (" TARGET_FMT_lx ")", ctx->pc + 4);
aurel321ba74fb2009-03-29 01:18:52 +000014401 tcg_gen_brcondi_tl(TCG_COND_NE, bcond, 0, l1);
aurel3241db4602009-03-29 01:28:29 +000014402 tcg_gen_movi_i32(hflags, ctx->hflags & ~MIPS_HFLAG_BMASK);
ths5a5012e2007-05-07 13:55:33 +000014403 gen_goto_tb(ctx, 1, ctx->pc + 4);
14404 gen_set_label(l1);
bellard6af0bf92005-07-02 14:58:51 +000014405 }
Aurelien Jarno618b0fe2009-09-28 13:03:30 +020014406
Richard Hendersonfdefe512012-09-24 14:55:47 -070014407 if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP | CPU_LOG_TB_OP_OPT))) {
Aurelien Jarno618b0fe2009-09-28 13:03:30 +020014408 tcg_gen_debug_insn_start(ctx->pc);
Richard Hendersonfdefe512012-09-24 14:55:47 -070014409 }
Aurelien Jarno618b0fe2009-09-28 13:03:30 +020014410
ths7a387ff2006-12-06 20:17:30 +000014411 op = MASK_OP_MAJOR(ctx->opcode);
14412 rs = (ctx->opcode >> 21) & 0x1f;
14413 rt = (ctx->opcode >> 16) & 0x1f;
14414 rd = (ctx->opcode >> 11) & 0x1f;
14415 sa = (ctx->opcode >> 6) & 0x1f;
bellard6af0bf92005-07-02 14:58:51 +000014416 imm = (int16_t)ctx->opcode;
14417 switch (op) {
ths7a387ff2006-12-06 20:17:30 +000014418 case OPC_SPECIAL:
14419 op1 = MASK_SPECIAL(ctx->opcode);
bellard6af0bf92005-07-02 14:58:51 +000014420 switch (op1) {
aurel32324d9e32009-04-11 18:42:17 +000014421 case OPC_SLL: /* Shift with immediate */
14422 case OPC_SRA:
Aurelien Jarnod75c1352013-01-01 18:02:22 +010014423 gen_shift_imm(ctx, op1, rd, rt, sa);
bellard6af0bf92005-07-02 14:58:51 +000014424 break;
Nathan Froydea63e2c2009-12-08 08:06:24 -080014425 case OPC_SRL:
14426 switch ((ctx->opcode >> 21) & 0x1f) {
14427 case 1:
14428 /* rotr is decoded as srl on non-R2 CPUs */
Aurelien Jarnod75c1352013-01-01 18:02:22 +010014429 if (ctx->insn_flags & ISA_MIPS32R2) {
Nathan Froydea63e2c2009-12-08 08:06:24 -080014430 op1 = OPC_ROTR;
14431 }
14432 /* Fallthrough */
14433 case 0:
Aurelien Jarnod75c1352013-01-01 18:02:22 +010014434 gen_shift_imm(ctx, op1, rd, rt, sa);
Nathan Froydea63e2c2009-12-08 08:06:24 -080014435 break;
14436 default:
14437 generate_exception(ctx, EXCP_RI);
14438 break;
14439 }
14440 break;
aurel32460f00c2009-04-08 21:48:02 +000014441 case OPC_MOVN: /* Conditional move */
14442 case OPC_MOVZ:
Aurelien Jarnod75c1352013-01-01 18:02:22 +010014443 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32 |
Aurelien Jarnoaa8f4002010-06-19 11:11:10 +020014444 INSN_LOONGSON2E | INSN_LOONGSON2F);
Aurelien Jarnod75c1352013-01-01 18:02:22 +010014445 gen_cond_move(ctx, op1, rd, rs, rt);
aurel32460f00c2009-04-08 21:48:02 +000014446 break;
14447 case OPC_ADD ... OPC_SUBU:
Aurelien Jarnod75c1352013-01-01 18:02:22 +010014448 gen_arith(ctx, op1, rd, rs, rt);
bellard6af0bf92005-07-02 14:58:51 +000014449 break;
aurel32460f00c2009-04-08 21:48:02 +000014450 case OPC_SLLV: /* Shifts */
aurel32460f00c2009-04-08 21:48:02 +000014451 case OPC_SRAV:
Aurelien Jarnod75c1352013-01-01 18:02:22 +010014452 gen_shift(ctx, op1, rd, rs, rt);
aurel32460f00c2009-04-08 21:48:02 +000014453 break;
Nathan Froydea63e2c2009-12-08 08:06:24 -080014454 case OPC_SRLV:
14455 switch ((ctx->opcode >> 6) & 0x1f) {
14456 case 1:
14457 /* rotrv is decoded as srlv on non-R2 CPUs */
Aurelien Jarnod75c1352013-01-01 18:02:22 +010014458 if (ctx->insn_flags & ISA_MIPS32R2) {
Nathan Froydea63e2c2009-12-08 08:06:24 -080014459 op1 = OPC_ROTRV;
14460 }
14461 /* Fallthrough */
14462 case 0:
Aurelien Jarnod75c1352013-01-01 18:02:22 +010014463 gen_shift(ctx, op1, rd, rs, rt);
Nathan Froydea63e2c2009-12-08 08:06:24 -080014464 break;
14465 default:
14466 generate_exception(ctx, EXCP_RI);
14467 break;
14468 }
14469 break;
aurel32460f00c2009-04-08 21:48:02 +000014470 case OPC_SLT: /* Set on less than */
14471 case OPC_SLTU:
Aurelien Jarnod75c1352013-01-01 18:02:22 +010014472 gen_slt(ctx, op1, rd, rs, rt);
aurel32460f00c2009-04-08 21:48:02 +000014473 break;
14474 case OPC_AND: /* Logic*/
14475 case OPC_OR:
14476 case OPC_NOR:
14477 case OPC_XOR:
Aurelien Jarnod75c1352013-01-01 18:02:22 +010014478 gen_logic(ctx, op1, rd, rs, rt);
aurel32460f00c2009-04-08 21:48:02 +000014479 break;
ths7a387ff2006-12-06 20:17:30 +000014480 case OPC_MULT ... OPC_DIVU:
thse9c71dd2007-12-25 20:46:56 +000014481 if (sa) {
Aurelien Jarnod75c1352013-01-01 18:02:22 +010014482 check_insn(ctx, INSN_VR54XX);
thse9c71dd2007-12-25 20:46:56 +000014483 op1 = MASK_MUL_VR54XX(ctx->opcode);
14484 gen_mul_vr54xx(ctx, op1, rd, rs, rt);
14485 } else
14486 gen_muldiv(ctx, op1, rs, rt);
bellard6af0bf92005-07-02 14:58:51 +000014487 break;
ths7a387ff2006-12-06 20:17:30 +000014488 case OPC_JR ... OPC_JALR:
Nathan Froyd7dca4ad2009-12-08 08:06:25 -080014489 gen_compute_branch(ctx, op1, 4, rs, rd, sa);
Nathan Froydc9602062009-12-08 08:06:27 -080014490 *is_branch = 1;
14491 break;
ths7a387ff2006-12-06 20:17:30 +000014492 case OPC_TGE ... OPC_TEQ: /* Traps */
14493 case OPC_TNE:
14494 gen_trap(ctx, op1, rs, rt, -1);
bellard6af0bf92005-07-02 14:58:51 +000014495 break;
ths7a387ff2006-12-06 20:17:30 +000014496 case OPC_MFHI: /* Move from HI/LO */
14497 case OPC_MFLO:
14498 gen_HILO(ctx, op1, rd);
bellard6af0bf92005-07-02 14:58:51 +000014499 break;
ths7a387ff2006-12-06 20:17:30 +000014500 case OPC_MTHI:
14501 case OPC_MTLO: /* Move to HI/LO */
14502 gen_HILO(ctx, op1, rs);
bellard6af0bf92005-07-02 14:58:51 +000014503 break;
thsb48cfdf2007-04-11 02:24:14 +000014504 case OPC_PMON: /* Pmon entry point, also R4010 selsl */
14505#ifdef MIPS_STRICT_STANDARD
14506 MIPS_INVAL("PMON / selsl");
14507 generate_exception(ctx, EXCP_RI);
14508#else
Blue Swirl895c2d02012-09-02 14:52:59 +000014509 gen_helper_0e0i(pmon, sa);
thsb48cfdf2007-04-11 02:24:14 +000014510#endif
ths7a387ff2006-12-06 20:17:30 +000014511 break;
14512 case OPC_SYSCALL:
bellard6af0bf92005-07-02 14:58:51 +000014513 generate_exception(ctx, EXCP_SYSCALL);
pbrook8e0f9502009-04-16 10:56:43 +000014514 ctx->bstate = BS_STOP;
bellard6af0bf92005-07-02 14:58:51 +000014515 break;
ths7a387ff2006-12-06 20:17:30 +000014516 case OPC_BREAK:
bellard6af0bf92005-07-02 14:58:51 +000014517 generate_exception(ctx, EXCP_BREAK);
14518 break;
thsb48cfdf2007-04-11 02:24:14 +000014519 case OPC_SPIM:
14520#ifdef MIPS_STRICT_STANDARD
14521 MIPS_INVAL("SPIM");
14522 generate_exception(ctx, EXCP_RI);
14523#else
ths7a387ff2006-12-06 20:17:30 +000014524 /* Implemented as RI exception for now. */
14525 MIPS_INVAL("spim (unofficial)");
14526 generate_exception(ctx, EXCP_RI);
thsb48cfdf2007-04-11 02:24:14 +000014527#endif
bellard6af0bf92005-07-02 14:58:51 +000014528 break;
ths7a387ff2006-12-06 20:17:30 +000014529 case OPC_SYNC:
thsead93602007-09-06 00:18:15 +000014530 /* Treat as NOP. */
bellard6af0bf92005-07-02 14:58:51 +000014531 break;
bellard4ad40f32005-12-05 19:59:36 +000014532
ths7a387ff2006-12-06 20:17:30 +000014533 case OPC_MOVCI:
Aurelien Jarnod75c1352013-01-01 18:02:22 +010014534 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32);
ths36d23952007-02-28 22:37:42 +000014535 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
ths5e755512007-05-29 16:52:57 +000014536 check_cp1_enabled(ctx);
ths36d23952007-02-28 22:37:42 +000014537 gen_movci(ctx, rd, rs, (ctx->opcode >> 18) & 0x7,
14538 (ctx->opcode >> 16) & 1);
14539 } else {
thse397ee32007-03-23 00:43:28 +000014540 generate_exception_err(ctx, EXCP_CpU, 1);
ths36d23952007-02-28 22:37:42 +000014541 }
bellard4ad40f32005-12-05 19:59:36 +000014542 break;
14543
thsd26bc212007-11-08 18:05:37 +000014544#if defined(TARGET_MIPS64)
ths7a387ff2006-12-06 20:17:30 +000014545 /* MIPS64 specific opcodes */
14546 case OPC_DSLL:
aurel32324d9e32009-04-11 18:42:17 +000014547 case OPC_DSRA:
ths7a387ff2006-12-06 20:17:30 +000014548 case OPC_DSLL32:
aurel32324d9e32009-04-11 18:42:17 +000014549 case OPC_DSRA32:
Aurelien Jarnod75c1352013-01-01 18:02:22 +010014550 check_insn(ctx, ISA_MIPS3);
thse189e742007-09-24 12:48:00 +000014551 check_mips_64(ctx);
Aurelien Jarnod75c1352013-01-01 18:02:22 +010014552 gen_shift_imm(ctx, op1, rd, rt, sa);
ths7a387ff2006-12-06 20:17:30 +000014553 break;
Nathan Froydea63e2c2009-12-08 08:06:24 -080014554 case OPC_DSRL:
14555 switch ((ctx->opcode >> 21) & 0x1f) {
14556 case 1:
14557 /* drotr is decoded as dsrl on non-R2 CPUs */
Aurelien Jarnod75c1352013-01-01 18:02:22 +010014558 if (ctx->insn_flags & ISA_MIPS32R2) {
Nathan Froydea63e2c2009-12-08 08:06:24 -080014559 op1 = OPC_DROTR;
14560 }
14561 /* Fallthrough */
14562 case 0:
Aurelien Jarnod75c1352013-01-01 18:02:22 +010014563 check_insn(ctx, ISA_MIPS3);
Nathan Froydea63e2c2009-12-08 08:06:24 -080014564 check_mips_64(ctx);
Aurelien Jarnod75c1352013-01-01 18:02:22 +010014565 gen_shift_imm(ctx, op1, rd, rt, sa);
Nathan Froydea63e2c2009-12-08 08:06:24 -080014566 break;
14567 default:
14568 generate_exception(ctx, EXCP_RI);
14569 break;
14570 }
14571 break;
14572 case OPC_DSRL32:
14573 switch ((ctx->opcode >> 21) & 0x1f) {
14574 case 1:
14575 /* drotr32 is decoded as dsrl32 on non-R2 CPUs */
Aurelien Jarnod75c1352013-01-01 18:02:22 +010014576 if (ctx->insn_flags & ISA_MIPS32R2) {
Nathan Froydea63e2c2009-12-08 08:06:24 -080014577 op1 = OPC_DROTR32;
14578 }
14579 /* Fallthrough */
14580 case 0:
Aurelien Jarnod75c1352013-01-01 18:02:22 +010014581 check_insn(ctx, ISA_MIPS3);
Nathan Froydea63e2c2009-12-08 08:06:24 -080014582 check_mips_64(ctx);
Aurelien Jarnod75c1352013-01-01 18:02:22 +010014583 gen_shift_imm(ctx, op1, rd, rt, sa);
Nathan Froydea63e2c2009-12-08 08:06:24 -080014584 break;
14585 default:
14586 generate_exception(ctx, EXCP_RI);
14587 break;
14588 }
14589 break;
ths7a387ff2006-12-06 20:17:30 +000014590 case OPC_DADD ... OPC_DSUBU:
Aurelien Jarnod75c1352013-01-01 18:02:22 +010014591 check_insn(ctx, ISA_MIPS3);
thse189e742007-09-24 12:48:00 +000014592 check_mips_64(ctx);
Aurelien Jarnod75c1352013-01-01 18:02:22 +010014593 gen_arith(ctx, op1, rd, rs, rt);
ths7a387ff2006-12-06 20:17:30 +000014594 break;
aurel32460f00c2009-04-08 21:48:02 +000014595 case OPC_DSLLV:
14596 case OPC_DSRAV:
Aurelien Jarnod75c1352013-01-01 18:02:22 +010014597 check_insn(ctx, ISA_MIPS3);
aurel32460f00c2009-04-08 21:48:02 +000014598 check_mips_64(ctx);
Aurelien Jarnod75c1352013-01-01 18:02:22 +010014599 gen_shift(ctx, op1, rd, rs, rt);
aurel32460f00c2009-04-08 21:48:02 +000014600 break;
Nathan Froydea63e2c2009-12-08 08:06:24 -080014601 case OPC_DSRLV:
14602 switch ((ctx->opcode >> 6) & 0x1f) {
14603 case 1:
14604 /* drotrv is decoded as dsrlv on non-R2 CPUs */
Aurelien Jarnod75c1352013-01-01 18:02:22 +010014605 if (ctx->insn_flags & ISA_MIPS32R2) {
Nathan Froydea63e2c2009-12-08 08:06:24 -080014606 op1 = OPC_DROTRV;
14607 }
14608 /* Fallthrough */
14609 case 0:
Aurelien Jarnod75c1352013-01-01 18:02:22 +010014610 check_insn(ctx, ISA_MIPS3);
Nathan Froydea63e2c2009-12-08 08:06:24 -080014611 check_mips_64(ctx);
Aurelien Jarnod75c1352013-01-01 18:02:22 +010014612 gen_shift(ctx, op1, rd, rs, rt);
Nathan Froydea63e2c2009-12-08 08:06:24 -080014613 break;
14614 default:
14615 generate_exception(ctx, EXCP_RI);
14616 break;
14617 }
14618 break;
ths7a387ff2006-12-06 20:17:30 +000014619 case OPC_DMULT ... OPC_DDIVU:
Aurelien Jarnod75c1352013-01-01 18:02:22 +010014620 check_insn(ctx, ISA_MIPS3);
thse189e742007-09-24 12:48:00 +000014621 check_mips_64(ctx);
ths7a387ff2006-12-06 20:17:30 +000014622 gen_muldiv(ctx, op1, rs, rt);
14623 break;
bellard6af0bf92005-07-02 14:58:51 +000014624#endif
14625 default: /* Invalid */
14626 MIPS_INVAL("special");
14627 generate_exception(ctx, EXCP_RI);
14628 break;
14629 }
14630 break;
ths7a387ff2006-12-06 20:17:30 +000014631 case OPC_SPECIAL2:
14632 op1 = MASK_SPECIAL2(ctx->opcode);
bellard6af0bf92005-07-02 14:58:51 +000014633 switch (op1) {
ths7a387ff2006-12-06 20:17:30 +000014634 case OPC_MADD ... OPC_MADDU: /* Multiply and add/sub */
14635 case OPC_MSUB ... OPC_MSUBU:
Aurelien Jarnod75c1352013-01-01 18:02:22 +010014636 check_insn(ctx, ISA_MIPS32);
ths7a387ff2006-12-06 20:17:30 +000014637 gen_muldiv(ctx, op1, rs, rt);
bellard6af0bf92005-07-02 14:58:51 +000014638 break;
ths7a387ff2006-12-06 20:17:30 +000014639 case OPC_MUL:
Aurelien Jarnod75c1352013-01-01 18:02:22 +010014640 gen_arith(ctx, op1, rd, rs, rt);
bellard6af0bf92005-07-02 14:58:51 +000014641 break;
aurel3220e1fb522009-03-29 01:18:16 +000014642 case OPC_CLO:
14643 case OPC_CLZ:
Aurelien Jarnod75c1352013-01-01 18:02:22 +010014644 check_insn(ctx, ISA_MIPS32);
ths7a387ff2006-12-06 20:17:30 +000014645 gen_cl(ctx, op1, rd, rs);
bellard6af0bf92005-07-02 14:58:51 +000014646 break;
ths7a387ff2006-12-06 20:17:30 +000014647 case OPC_SDBBP:
bellard6af0bf92005-07-02 14:58:51 +000014648 /* XXX: not clear which exception should be raised
14649 * when in debug mode...
14650 */
Aurelien Jarnod75c1352013-01-01 18:02:22 +010014651 check_insn(ctx, ISA_MIPS32);
bellard6af0bf92005-07-02 14:58:51 +000014652 if (!(ctx->hflags & MIPS_HFLAG_DM)) {
14653 generate_exception(ctx, EXCP_DBp);
14654 } else {
14655 generate_exception(ctx, EXCP_DBp);
14656 }
thsead93602007-09-06 00:18:15 +000014657 /* Treat as NOP. */
bellard6af0bf92005-07-02 14:58:51 +000014658 break;
Aurelien Jarno161f85e2010-06-18 19:32:43 +020014659 case OPC_DIV_G_2F:
14660 case OPC_DIVU_G_2F:
14661 case OPC_MULT_G_2F:
14662 case OPC_MULTU_G_2F:
14663 case OPC_MOD_G_2F:
14664 case OPC_MODU_G_2F:
Aurelien Jarnod75c1352013-01-01 18:02:22 +010014665 check_insn(ctx, INSN_LOONGSON2F);
Aurelien Jarno161f85e2010-06-18 19:32:43 +020014666 gen_loongson_integer(ctx, op1, rd, rs, rt);
14667 break;
thsd26bc212007-11-08 18:05:37 +000014668#if defined(TARGET_MIPS64)
aurel3220e1fb522009-03-29 01:18:16 +000014669 case OPC_DCLO:
14670 case OPC_DCLZ:
Aurelien Jarnod75c1352013-01-01 18:02:22 +010014671 check_insn(ctx, ISA_MIPS64);
thse189e742007-09-24 12:48:00 +000014672 check_mips_64(ctx);
ths7a387ff2006-12-06 20:17:30 +000014673 gen_cl(ctx, op1, rd, rs);
14674 break;
Aurelien Jarno161f85e2010-06-18 19:32:43 +020014675 case OPC_DMULT_G_2F:
14676 case OPC_DMULTU_G_2F:
14677 case OPC_DDIV_G_2F:
14678 case OPC_DDIVU_G_2F:
14679 case OPC_DMOD_G_2F:
14680 case OPC_DMODU_G_2F:
Aurelien Jarnod75c1352013-01-01 18:02:22 +010014681 check_insn(ctx, INSN_LOONGSON2F);
Aurelien Jarno161f85e2010-06-18 19:32:43 +020014682 gen_loongson_integer(ctx, op1, rd, rs, rt);
14683 break;
ths7a387ff2006-12-06 20:17:30 +000014684#endif
bellard6af0bf92005-07-02 14:58:51 +000014685 default: /* Invalid */
14686 MIPS_INVAL("special2");
14687 generate_exception(ctx, EXCP_RI);
14688 break;
14689 }
14690 break;
ths7a387ff2006-12-06 20:17:30 +000014691 case OPC_SPECIAL3:
ths2b0233a2008-06-12 12:42:35 +000014692 op1 = MASK_SPECIAL3(ctx->opcode);
14693 switch (op1) {
14694 case OPC_EXT:
14695 case OPC_INS:
Aurelien Jarnod75c1352013-01-01 18:02:22 +010014696 check_insn(ctx, ISA_MIPS32R2);
ths2b0233a2008-06-12 12:42:35 +000014697 gen_bitops(ctx, op1, rt, rs, sa, rd);
14698 break;
14699 case OPC_BSHFL:
Aurelien Jarnod75c1352013-01-01 18:02:22 +010014700 check_insn(ctx, ISA_MIPS32R2);
ths2b0233a2008-06-12 12:42:35 +000014701 op2 = MASK_BSHFL(ctx->opcode);
aurel3249bcf332008-11-11 11:47:06 +000014702 gen_bshfl(ctx, op2, rt, rd);
ths1579a722007-04-05 23:16:25 +000014703 break;
14704 case OPC_RDHWR:
Aurelien Jarnod75c1352013-01-01 18:02:22 +010014705 gen_rdhwr(ctx, rt, rd);
ths7a387ff2006-12-06 20:17:30 +000014706 break;
thsead93602007-09-06 00:18:15 +000014707 case OPC_FORK:
Aurelien Jarnod75c1352013-01-01 18:02:22 +010014708 check_insn(ctx, ASE_MT);
ths6c5c1e22008-06-24 15:12:27 +000014709 {
aurel3235fbce22009-04-08 21:47:55 +000014710 TCGv t0 = tcg_temp_new();
14711 TCGv t1 = tcg_temp_new();
ths6c5c1e22008-06-24 15:12:27 +000014712
14713 gen_load_gpr(t0, rt);
14714 gen_load_gpr(t1, rs);
pbrooka7812ae2008-11-17 14:43:54 +000014715 gen_helper_fork(t0, t1);
ths6c5c1e22008-06-24 15:12:27 +000014716 tcg_temp_free(t0);
14717 tcg_temp_free(t1);
14718 }
thsead93602007-09-06 00:18:15 +000014719 break;
14720 case OPC_YIELD:
Aurelien Jarnod75c1352013-01-01 18:02:22 +010014721 check_insn(ctx, ASE_MT);
ths6c5c1e22008-06-24 15:12:27 +000014722 {
aurel3235fbce22009-04-08 21:47:55 +000014723 TCGv t0 = tcg_temp_new();
ths6c5c1e22008-06-24 15:12:27 +000014724
aurel3235fbce22009-04-08 21:47:55 +000014725 save_cpu_state(ctx, 1);
ths6c5c1e22008-06-24 15:12:27 +000014726 gen_load_gpr(t0, rs);
Blue Swirl895c2d02012-09-02 14:52:59 +000014727 gen_helper_yield(t0, cpu_env, t0);
ths6c5c1e22008-06-24 15:12:27 +000014728 gen_store_gpr(t0, rd);
14729 tcg_temp_free(t0);
14730 }
thsead93602007-09-06 00:18:15 +000014731 break;
Aurelien Jarno161f85e2010-06-18 19:32:43 +020014732 case OPC_DIV_G_2E ... OPC_DIVU_G_2E:
Aurelien Jarno161f85e2010-06-18 19:32:43 +020014733 case OPC_MOD_G_2E ... OPC_MODU_G_2E:
Jia Liu461c08d2012-10-24 22:17:06 +080014734 case OPC_MULT_G_2E ... OPC_MULTU_G_2E:
14735 /* OPC_MULT_G_2E, OPC_ADDUH_QB_DSP, OPC_MUL_PH_DSP have
14736 * the same mask and op1. */
Aurelien Jarnod75c1352013-01-01 18:02:22 +010014737 if ((ctx->insn_flags & ASE_DSPR2) && (op1 == OPC_MULT_G_2E)) {
Jia Liu461c08d2012-10-24 22:17:06 +080014738 op2 = MASK_ADDUH_QB(ctx->opcode);
14739 switch (op2) {
14740 case OPC_ADDUH_QB:
14741 case OPC_ADDUH_R_QB:
14742 case OPC_ADDQH_PH:
14743 case OPC_ADDQH_R_PH:
14744 case OPC_ADDQH_W:
14745 case OPC_ADDQH_R_W:
14746 case OPC_SUBUH_QB:
14747 case OPC_SUBUH_R_QB:
14748 case OPC_SUBQH_PH:
14749 case OPC_SUBQH_R_PH:
14750 case OPC_SUBQH_W:
14751 case OPC_SUBQH_R_W:
14752 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
14753 break;
Jia Liua22260a2012-10-24 22:17:08 +080014754 case OPC_MUL_PH:
14755 case OPC_MUL_S_PH:
14756 case OPC_MULQ_S_W:
14757 case OPC_MULQ_RS_W:
14758 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 1);
14759 break;
Jia Liu461c08d2012-10-24 22:17:06 +080014760 default:
14761 MIPS_INVAL("MASK ADDUH.QB");
14762 generate_exception(ctx, EXCP_RI);
14763 break;
14764 }
Aurelien Jarnod75c1352013-01-01 18:02:22 +010014765 } else if (ctx->insn_flags & INSN_LOONGSON2E) {
Jia Liu461c08d2012-10-24 22:17:06 +080014766 gen_loongson_integer(ctx, op1, rd, rs, rt);
14767 } else {
14768 generate_exception(ctx, EXCP_RI);
14769 }
Aurelien Jarno161f85e2010-06-18 19:32:43 +020014770 break;
Jia Liu9b1a1d62012-10-24 22:17:05 +080014771 case OPC_LX_DSP:
14772 op2 = MASK_LX(ctx->opcode);
14773 switch (op2) {
14774#if defined(TARGET_MIPS64)
14775 case OPC_LDX:
14776#endif
14777 case OPC_LBUX:
14778 case OPC_LHX:
14779 case OPC_LWX:
Aurelien Jarnod75c1352013-01-01 18:02:22 +010014780 gen_mipsdsp_ld(ctx, op2, rd, rs, rt);
Jia Liu9b1a1d62012-10-24 22:17:05 +080014781 break;
14782 default: /* Invalid */
14783 MIPS_INVAL("MASK LX");
14784 generate_exception(ctx, EXCP_RI);
14785 break;
14786 }
14787 break;
Jia Liu461c08d2012-10-24 22:17:06 +080014788 case OPC_ABSQ_S_PH_DSP:
14789 op2 = MASK_ABSQ_S_PH(ctx->opcode);
14790 switch (op2) {
14791 case OPC_ABSQ_S_QB:
14792 case OPC_ABSQ_S_PH:
14793 case OPC_ABSQ_S_W:
14794 case OPC_PRECEQ_W_PHL:
14795 case OPC_PRECEQ_W_PHR:
14796 case OPC_PRECEQU_PH_QBL:
14797 case OPC_PRECEQU_PH_QBR:
14798 case OPC_PRECEQU_PH_QBLA:
14799 case OPC_PRECEQU_PH_QBRA:
14800 case OPC_PRECEU_PH_QBL:
14801 case OPC_PRECEU_PH_QBR:
14802 case OPC_PRECEU_PH_QBLA:
14803 case OPC_PRECEU_PH_QBRA:
14804 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
14805 break;
Jia Liu1cb66862012-10-24 22:17:09 +080014806 case OPC_BITREV:
14807 case OPC_REPL_QB:
14808 case OPC_REPLV_QB:
14809 case OPC_REPL_PH:
14810 case OPC_REPLV_PH:
Aurelien Jarnod75c1352013-01-01 18:02:22 +010014811 gen_mipsdsp_bitinsn(ctx, op1, op2, rd, rt);
Jia Liu1cb66862012-10-24 22:17:09 +080014812 break;
Jia Liu461c08d2012-10-24 22:17:06 +080014813 default:
14814 MIPS_INVAL("MASK ABSQ_S.PH");
14815 generate_exception(ctx, EXCP_RI);
14816 break;
14817 }
14818 break;
14819 case OPC_ADDU_QB_DSP:
14820 op2 = MASK_ADDU_QB(ctx->opcode);
14821 switch (op2) {
14822 case OPC_ADDQ_PH:
14823 case OPC_ADDQ_S_PH:
14824 case OPC_ADDQ_S_W:
14825 case OPC_ADDU_QB:
14826 case OPC_ADDU_S_QB:
14827 case OPC_ADDU_PH:
14828 case OPC_ADDU_S_PH:
14829 case OPC_SUBQ_PH:
14830 case OPC_SUBQ_S_PH:
14831 case OPC_SUBQ_S_W:
14832 case OPC_SUBU_QB:
14833 case OPC_SUBU_S_QB:
14834 case OPC_SUBU_PH:
14835 case OPC_SUBU_S_PH:
14836 case OPC_ADDSC:
14837 case OPC_ADDWC:
14838 case OPC_MODSUB:
14839 case OPC_RADDU_W_QB:
14840 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
14841 break;
Jia Liua22260a2012-10-24 22:17:08 +080014842 case OPC_MULEU_S_PH_QBL:
14843 case OPC_MULEU_S_PH_QBR:
14844 case OPC_MULQ_RS_PH:
14845 case OPC_MULEQ_S_W_PHL:
14846 case OPC_MULEQ_S_W_PHR:
14847 case OPC_MULQ_S_PH:
14848 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 1);
14849 break;
Jia Liu461c08d2012-10-24 22:17:06 +080014850 default: /* Invalid */
14851 MIPS_INVAL("MASK ADDU.QB");
14852 generate_exception(ctx, EXCP_RI);
14853 break;
14854
14855 }
14856 break;
14857 case OPC_CMPU_EQ_QB_DSP:
14858 op2 = MASK_CMPU_EQ_QB(ctx->opcode);
14859 switch (op2) {
14860 case OPC_PRECR_SRA_PH_W:
14861 case OPC_PRECR_SRA_R_PH_W:
14862 gen_mipsdsp_arith(ctx, op1, op2, rt, rs, rd);
14863 break;
14864 case OPC_PRECR_QB_PH:
14865 case OPC_PRECRQ_QB_PH:
14866 case OPC_PRECRQ_PH_W:
14867 case OPC_PRECRQ_RS_PH_W:
14868 case OPC_PRECRQU_S_QB_PH:
14869 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
14870 break;
Jia Liu26690562012-10-24 22:17:10 +080014871 case OPC_CMPU_EQ_QB:
14872 case OPC_CMPU_LT_QB:
14873 case OPC_CMPU_LE_QB:
14874 case OPC_CMP_EQ_PH:
14875 case OPC_CMP_LT_PH:
14876 case OPC_CMP_LE_PH:
14877 gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rd, rs, rt, 0);
14878 break;
14879 case OPC_CMPGU_EQ_QB:
14880 case OPC_CMPGU_LT_QB:
14881 case OPC_CMPGU_LE_QB:
14882 case OPC_CMPGDU_EQ_QB:
14883 case OPC_CMPGDU_LT_QB:
14884 case OPC_CMPGDU_LE_QB:
14885 case OPC_PICK_QB:
14886 case OPC_PICK_PH:
14887 case OPC_PACKRL_PH:
14888 gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rd, rs, rt, 1);
14889 break;
Jia Liu461c08d2012-10-24 22:17:06 +080014890 default: /* Invalid */
14891 MIPS_INVAL("MASK CMPU.EQ.QB");
14892 generate_exception(ctx, EXCP_RI);
14893 break;
14894 }
14895 break;
Jia Liu77c5fa82012-10-24 22:17:07 +080014896 case OPC_SHLL_QB_DSP:
14897 gen_mipsdsp_shift(ctx, op1, rd, rs, rt);
14898 break;
Jia Liua22260a2012-10-24 22:17:08 +080014899 case OPC_DPA_W_PH_DSP:
14900 op2 = MASK_DPA_W_PH(ctx->opcode);
14901 switch (op2) {
14902 case OPC_DPAU_H_QBL:
14903 case OPC_DPAU_H_QBR:
14904 case OPC_DPSU_H_QBL:
14905 case OPC_DPSU_H_QBR:
14906 case OPC_DPA_W_PH:
14907 case OPC_DPAX_W_PH:
14908 case OPC_DPAQ_S_W_PH:
14909 case OPC_DPAQX_S_W_PH:
14910 case OPC_DPAQX_SA_W_PH:
14911 case OPC_DPS_W_PH:
14912 case OPC_DPSX_W_PH:
14913 case OPC_DPSQ_S_W_PH:
14914 case OPC_DPSQX_S_W_PH:
14915 case OPC_DPSQX_SA_W_PH:
14916 case OPC_MULSAQ_S_W_PH:
14917 case OPC_DPAQ_SA_L_W:
14918 case OPC_DPSQ_SA_L_W:
14919 case OPC_MAQ_S_W_PHL:
14920 case OPC_MAQ_S_W_PHR:
14921 case OPC_MAQ_SA_W_PHL:
14922 case OPC_MAQ_SA_W_PHR:
14923 case OPC_MULSA_W_PH:
14924 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 0);
14925 break;
14926 default: /* Invalid */
14927 MIPS_INVAL("MASK DPAW.PH");
14928 generate_exception(ctx, EXCP_RI);
14929 break;
14930 }
14931 break;
Jia Liu1cb66862012-10-24 22:17:09 +080014932 case OPC_INSV_DSP:
14933 op2 = MASK_INSV(ctx->opcode);
14934 switch (op2) {
14935 case OPC_INSV:
14936 check_dsp(ctx);
14937 {
14938 TCGv t0, t1;
14939
14940 if (rt == 0) {
14941 MIPS_DEBUG("NOP");
14942 break;
14943 }
14944
14945 t0 = tcg_temp_new();
14946 t1 = tcg_temp_new();
14947
14948 gen_load_gpr(t0, rt);
14949 gen_load_gpr(t1, rs);
14950
14951 gen_helper_insv(cpu_gpr[rt], cpu_env, t1, t0);
14952
14953 tcg_temp_free(t0);
14954 tcg_temp_free(t1);
14955 break;
14956 }
14957 default: /* Invalid */
14958 MIPS_INVAL("MASK INSV");
14959 generate_exception(ctx, EXCP_RI);
14960 break;
14961 }
14962 break;
Jia Liu26690562012-10-24 22:17:10 +080014963 case OPC_APPEND_DSP:
Aurelien Jarnodf6126a2013-01-01 18:02:24 +010014964 gen_mipsdsp_append(env, ctx, op1, rt, rs, rd);
Jia Liu26690562012-10-24 22:17:10 +080014965 break;
Jia Liub53371e2012-10-24 22:17:11 +080014966 case OPC_EXTR_W_DSP:
14967 op2 = MASK_EXTR_W(ctx->opcode);
14968 switch (op2) {
14969 case OPC_EXTR_W:
14970 case OPC_EXTR_R_W:
14971 case OPC_EXTR_RS_W:
14972 case OPC_EXTR_S_H:
14973 case OPC_EXTRV_S_H:
14974 case OPC_EXTRV_W:
14975 case OPC_EXTRV_R_W:
14976 case OPC_EXTRV_RS_W:
14977 case OPC_EXTP:
14978 case OPC_EXTPV:
14979 case OPC_EXTPDP:
14980 case OPC_EXTPDPV:
14981 gen_mipsdsp_accinsn(ctx, op1, op2, rt, rs, rd, 1);
14982 break;
14983 case OPC_RDDSP:
14984 gen_mipsdsp_accinsn(ctx, op1, op2, rd, rs, rt, 1);
14985 break;
14986 case OPC_SHILO:
14987 case OPC_SHILOV:
14988 case OPC_MTHLIP:
14989 case OPC_WRDSP:
14990 gen_mipsdsp_accinsn(ctx, op1, op2, rd, rs, rt, 0);
14991 break;
14992 default: /* Invalid */
14993 MIPS_INVAL("MASK EXTR.W");
14994 generate_exception(ctx, EXCP_RI);
14995 break;
14996 }
14997 break;
thsd26bc212007-11-08 18:05:37 +000014998#if defined(TARGET_MIPS64)
ths1579a722007-04-05 23:16:25 +000014999 case OPC_DEXTM ... OPC_DEXT:
15000 case OPC_DINSM ... OPC_DINS:
Aurelien Jarnod75c1352013-01-01 18:02:22 +010015001 check_insn(ctx, ISA_MIPS64R2);
thse189e742007-09-24 12:48:00 +000015002 check_mips_64(ctx);
ths1579a722007-04-05 23:16:25 +000015003 gen_bitops(ctx, op1, rt, rs, sa, rd);
15004 break;
15005 case OPC_DBSHFL:
Aurelien Jarnod75c1352013-01-01 18:02:22 +010015006 check_insn(ctx, ISA_MIPS64R2);
thse189e742007-09-24 12:48:00 +000015007 check_mips_64(ctx);
ths1579a722007-04-05 23:16:25 +000015008 op2 = MASK_DBSHFL(ctx->opcode);
aurel3249bcf332008-11-11 11:47:06 +000015009 gen_bshfl(ctx, op2, rt, rd);
thsc6d6dd72007-11-18 03:36:07 +000015010 break;
Aurelien Jarno161f85e2010-06-18 19:32:43 +020015011 case OPC_DDIV_G_2E ... OPC_DDIVU_G_2E:
15012 case OPC_DMULT_G_2E ... OPC_DMULTU_G_2E:
15013 case OPC_DMOD_G_2E ... OPC_DMODU_G_2E:
Aurelien Jarnod75c1352013-01-01 18:02:22 +010015014 check_insn(ctx, INSN_LOONGSON2E);
Aurelien Jarno161f85e2010-06-18 19:32:43 +020015015 gen_loongson_integer(ctx, op1, rd, rs, rt);
15016 break;
Jia Liu461c08d2012-10-24 22:17:06 +080015017 case OPC_ABSQ_S_QH_DSP:
15018 op2 = MASK_ABSQ_S_QH(ctx->opcode);
15019 switch (op2) {
15020 case OPC_PRECEQ_L_PWL:
15021 case OPC_PRECEQ_L_PWR:
15022 case OPC_PRECEQ_PW_QHL:
15023 case OPC_PRECEQ_PW_QHR:
15024 case OPC_PRECEQ_PW_QHLA:
15025 case OPC_PRECEQ_PW_QHRA:
15026 case OPC_PRECEQU_QH_OBL:
15027 case OPC_PRECEQU_QH_OBR:
15028 case OPC_PRECEQU_QH_OBLA:
15029 case OPC_PRECEQU_QH_OBRA:
15030 case OPC_PRECEU_QH_OBL:
15031 case OPC_PRECEU_QH_OBR:
15032 case OPC_PRECEU_QH_OBLA:
15033 case OPC_PRECEU_QH_OBRA:
15034 case OPC_ABSQ_S_OB:
15035 case OPC_ABSQ_S_PW:
15036 case OPC_ABSQ_S_QH:
15037 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
15038 break;
Jia Liu1cb66862012-10-24 22:17:09 +080015039 case OPC_REPL_OB:
15040 case OPC_REPL_PW:
15041 case OPC_REPL_QH:
15042 case OPC_REPLV_OB:
15043 case OPC_REPLV_PW:
15044 case OPC_REPLV_QH:
Aurelien Jarnod75c1352013-01-01 18:02:22 +010015045 gen_mipsdsp_bitinsn(ctx, op1, op2, rd, rt);
Jia Liu1cb66862012-10-24 22:17:09 +080015046 break;
Jia Liu461c08d2012-10-24 22:17:06 +080015047 default: /* Invalid */
15048 MIPS_INVAL("MASK ABSQ_S.QH");
15049 generate_exception(ctx, EXCP_RI);
15050 break;
15051 }
15052 break;
15053 case OPC_ADDU_OB_DSP:
15054 op2 = MASK_ADDU_OB(ctx->opcode);
15055 switch (op2) {
15056 case OPC_RADDU_L_OB:
15057 case OPC_SUBQ_PW:
15058 case OPC_SUBQ_S_PW:
15059 case OPC_SUBQ_QH:
15060 case OPC_SUBQ_S_QH:
15061 case OPC_SUBU_OB:
15062 case OPC_SUBU_S_OB:
15063 case OPC_SUBU_QH:
15064 case OPC_SUBU_S_QH:
15065 case OPC_SUBUH_OB:
15066 case OPC_SUBUH_R_OB:
15067 case OPC_ADDQ_PW:
15068 case OPC_ADDQ_S_PW:
15069 case OPC_ADDQ_QH:
15070 case OPC_ADDQ_S_QH:
15071 case OPC_ADDU_OB:
15072 case OPC_ADDU_S_OB:
15073 case OPC_ADDU_QH:
15074 case OPC_ADDU_S_QH:
15075 case OPC_ADDUH_OB:
15076 case OPC_ADDUH_R_OB:
15077 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
15078 break;
Jia Liua22260a2012-10-24 22:17:08 +080015079 case OPC_MULEQ_S_PW_QHL:
15080 case OPC_MULEQ_S_PW_QHR:
15081 case OPC_MULEU_S_QH_OBL:
15082 case OPC_MULEU_S_QH_OBR:
15083 case OPC_MULQ_RS_QH:
15084 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 1);
15085 break;
Jia Liu461c08d2012-10-24 22:17:06 +080015086 default: /* Invalid */
15087 MIPS_INVAL("MASK ADDU.OB");
15088 generate_exception(ctx, EXCP_RI);
15089 break;
15090 }
15091 break;
15092 case OPC_CMPU_EQ_OB_DSP:
15093 op2 = MASK_CMPU_EQ_OB(ctx->opcode);
15094 switch (op2) {
15095 case OPC_PRECR_SRA_QH_PW:
15096 case OPC_PRECR_SRA_R_QH_PW:
15097 /* Return value is rt. */
15098 gen_mipsdsp_arith(ctx, op1, op2, rt, rs, rd);
15099 break;
15100 case OPC_PRECR_OB_QH:
15101 case OPC_PRECRQ_OB_QH:
15102 case OPC_PRECRQ_PW_L:
15103 case OPC_PRECRQ_QH_PW:
15104 case OPC_PRECRQ_RS_QH_PW:
15105 case OPC_PRECRQU_S_OB_QH:
15106 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
15107 break;
Jia Liu26690562012-10-24 22:17:10 +080015108 case OPC_CMPU_EQ_OB:
15109 case OPC_CMPU_LT_OB:
15110 case OPC_CMPU_LE_OB:
15111 case OPC_CMP_EQ_QH:
15112 case OPC_CMP_LT_QH:
15113 case OPC_CMP_LE_QH:
15114 case OPC_CMP_EQ_PW:
15115 case OPC_CMP_LT_PW:
15116 case OPC_CMP_LE_PW:
15117 gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rd, rs, rt, 0);
15118 break;
15119 case OPC_CMPGDU_EQ_OB:
15120 case OPC_CMPGDU_LT_OB:
15121 case OPC_CMPGDU_LE_OB:
15122 case OPC_CMPGU_EQ_OB:
15123 case OPC_CMPGU_LT_OB:
15124 case OPC_CMPGU_LE_OB:
15125 case OPC_PACKRL_PW:
15126 case OPC_PICK_OB:
15127 case OPC_PICK_PW:
15128 case OPC_PICK_QH:
15129 gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rd, rs, rt, 1);
15130 break;
Jia Liu461c08d2012-10-24 22:17:06 +080015131 default: /* Invalid */
15132 MIPS_INVAL("MASK CMPU_EQ.OB");
15133 generate_exception(ctx, EXCP_RI);
15134 break;
15135 }
15136 break;
Jia Liu26690562012-10-24 22:17:10 +080015137 case OPC_DAPPEND_DSP:
Aurelien Jarnodf6126a2013-01-01 18:02:24 +010015138 gen_mipsdsp_append(env, ctx, op1, rt, rs, rd);
Jia Liu26690562012-10-24 22:17:10 +080015139 break;
Jia Liub53371e2012-10-24 22:17:11 +080015140 case OPC_DEXTR_W_DSP:
15141 op2 = MASK_DEXTR_W(ctx->opcode);
15142 switch (op2) {
15143 case OPC_DEXTP:
15144 case OPC_DEXTPDP:
15145 case OPC_DEXTPDPV:
15146 case OPC_DEXTPV:
15147 case OPC_DEXTR_L:
15148 case OPC_DEXTR_R_L:
15149 case OPC_DEXTR_RS_L:
15150 case OPC_DEXTR_W:
15151 case OPC_DEXTR_R_W:
15152 case OPC_DEXTR_RS_W:
15153 case OPC_DEXTR_S_H:
15154 case OPC_DEXTRV_L:
15155 case OPC_DEXTRV_R_L:
15156 case OPC_DEXTRV_RS_L:
15157 case OPC_DEXTRV_S_H:
15158 case OPC_DEXTRV_W:
15159 case OPC_DEXTRV_R_W:
15160 case OPC_DEXTRV_RS_W:
15161 gen_mipsdsp_accinsn(ctx, op1, op2, rt, rs, rd, 1);
15162 break;
15163 case OPC_DMTHLIP:
15164 case OPC_DSHILO:
15165 case OPC_DSHILOV:
15166 gen_mipsdsp_accinsn(ctx, op1, op2, rd, rs, rt, 0);
15167 break;
15168 default: /* Invalid */
15169 MIPS_INVAL("MASK EXTR.W");
15170 generate_exception(ctx, EXCP_RI);
15171 break;
15172 }
15173 break;
Jia Liua22260a2012-10-24 22:17:08 +080015174 case OPC_DPAQ_W_QH_DSP:
15175 op2 = MASK_DPAQ_W_QH(ctx->opcode);
15176 switch (op2) {
15177 case OPC_DPAU_H_OBL:
15178 case OPC_DPAU_H_OBR:
15179 case OPC_DPSU_H_OBL:
15180 case OPC_DPSU_H_OBR:
15181 case OPC_DPA_W_QH:
15182 case OPC_DPAQ_S_W_QH:
15183 case OPC_DPS_W_QH:
15184 case OPC_DPSQ_S_W_QH:
15185 case OPC_MULSAQ_S_W_QH:
15186 case OPC_DPAQ_SA_L_PW:
15187 case OPC_DPSQ_SA_L_PW:
15188 case OPC_MULSAQ_S_L_PW:
15189 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 0);
15190 break;
15191 case OPC_MAQ_S_W_QHLL:
15192 case OPC_MAQ_S_W_QHLR:
15193 case OPC_MAQ_S_W_QHRL:
15194 case OPC_MAQ_S_W_QHRR:
15195 case OPC_MAQ_SA_W_QHLL:
15196 case OPC_MAQ_SA_W_QHLR:
15197 case OPC_MAQ_SA_W_QHRL:
15198 case OPC_MAQ_SA_W_QHRR:
15199 case OPC_MAQ_S_L_PWL:
15200 case OPC_MAQ_S_L_PWR:
15201 case OPC_DMADD:
15202 case OPC_DMADDU:
15203 case OPC_DMSUB:
15204 case OPC_DMSUBU:
15205 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 0);
15206 break;
15207 default: /* Invalid */
15208 MIPS_INVAL("MASK DPAQ.W.QH");
15209 generate_exception(ctx, EXCP_RI);
15210 break;
15211 }
15212 break;
Jia Liu1cb66862012-10-24 22:17:09 +080015213 case OPC_DINSV_DSP:
15214 op2 = MASK_INSV(ctx->opcode);
15215 switch (op2) {
15216 case OPC_DINSV:
15217 {
15218 TCGv t0, t1;
15219
15220 if (rt == 0) {
15221 MIPS_DEBUG("NOP");
15222 break;
15223 }
15224 check_dsp(ctx);
15225
15226 t0 = tcg_temp_new();
15227 t1 = tcg_temp_new();
15228
15229 gen_load_gpr(t0, rt);
15230 gen_load_gpr(t1, rs);
15231
15232 gen_helper_dinsv(cpu_gpr[rt], cpu_env, t1, t0);
15233 break;
15234 }
15235 default: /* Invalid */
15236 MIPS_INVAL("MASK DINSV");
15237 generate_exception(ctx, EXCP_RI);
15238 break;
15239 }
15240 break;
Jia Liu77c5fa82012-10-24 22:17:07 +080015241 case OPC_SHLL_OB_DSP:
15242 gen_mipsdsp_shift(ctx, op1, rd, rs, rt);
15243 break;
ths7a387ff2006-12-06 20:17:30 +000015244#endif
15245 default: /* Invalid */
15246 MIPS_INVAL("special3");
15247 generate_exception(ctx, EXCP_RI);
15248 break;
15249 }
15250 break;
15251 case OPC_REGIMM:
15252 op1 = MASK_REGIMM(ctx->opcode);
15253 switch (op1) {
15254 case OPC_BLTZ ... OPC_BGEZL: /* REGIMM branches */
15255 case OPC_BLTZAL ... OPC_BGEZALL:
Nathan Froyd7dca4ad2009-12-08 08:06:25 -080015256 gen_compute_branch(ctx, op1, 4, rs, -1, imm << 2);
Nathan Froydc9602062009-12-08 08:06:27 -080015257 *is_branch = 1;
15258 break;
ths7a387ff2006-12-06 20:17:30 +000015259 case OPC_TGEI ... OPC_TEQI: /* REGIMM traps */
15260 case OPC_TNEI:
15261 gen_trap(ctx, op1, rs, -1, imm);
15262 break;
15263 case OPC_SYNCI:
Aurelien Jarnod75c1352013-01-01 18:02:22 +010015264 check_insn(ctx, ISA_MIPS32R2);
thsead93602007-09-06 00:18:15 +000015265 /* Treat as NOP. */
bellard6af0bf92005-07-02 14:58:51 +000015266 break;
Jia Liue45a93e2012-10-24 22:17:04 +080015267 case OPC_BPOSGE32: /* MIPS DSP branch */
15268#if defined(TARGET_MIPS64)
15269 case OPC_BPOSGE64:
15270#endif
15271 check_dsp(ctx);
15272 gen_compute_branch(ctx, op1, 4, -1, -2, (int32_t)imm << 2);
15273 *is_branch = 1;
15274 break;
bellard6af0bf92005-07-02 14:58:51 +000015275 default: /* Invalid */
ths923617a2007-05-11 00:16:06 +000015276 MIPS_INVAL("regimm");
bellard6af0bf92005-07-02 14:58:51 +000015277 generate_exception(ctx, EXCP_RI);
15278 break;
15279 }
15280 break;
ths7a387ff2006-12-06 20:17:30 +000015281 case OPC_CP0:
ths387a8fe2007-09-25 14:49:47 +000015282 check_cp0_enabled(ctx);
ths7a387ff2006-12-06 20:17:30 +000015283 op1 = MASK_CP0(ctx->opcode);
bellard6af0bf92005-07-02 14:58:51 +000015284 switch (op1) {
ths7a387ff2006-12-06 20:17:30 +000015285 case OPC_MFC0:
15286 case OPC_MTC0:
thsead93602007-09-06 00:18:15 +000015287 case OPC_MFTR:
15288 case OPC_MTTR:
thsd26bc212007-11-08 18:05:37 +000015289#if defined(TARGET_MIPS64)
ths7a387ff2006-12-06 20:17:30 +000015290 case OPC_DMFC0:
15291 case OPC_DMTC0:
15292#endif
thsf1aa6322008-06-09 07:13:38 +000015293#ifndef CONFIG_USER_ONLY
aurel32932e71c2009-01-12 21:33:13 +000015294 gen_cp0(env, ctx, op1, rt, rd);
ths0eaef5a2008-07-23 16:14:22 +000015295#endif /* !CONFIG_USER_ONLY */
bellard6af0bf92005-07-02 14:58:51 +000015296 break;
ths7a387ff2006-12-06 20:17:30 +000015297 case OPC_C0_FIRST ... OPC_C0_LAST:
thsf1aa6322008-06-09 07:13:38 +000015298#ifndef CONFIG_USER_ONLY
aurel32932e71c2009-01-12 21:33:13 +000015299 gen_cp0(env, ctx, MASK_C0(ctx->opcode), rt, rd);
ths0eaef5a2008-07-23 16:14:22 +000015300#endif /* !CONFIG_USER_ONLY */
ths7a387ff2006-12-06 20:17:30 +000015301 break;
15302 case OPC_MFMC0:
ths8706c382008-07-21 21:38:04 +000015303#ifndef CONFIG_USER_ONLY
aurel32932e71c2009-01-12 21:33:13 +000015304 {
aurel3235fbce22009-04-08 21:47:55 +000015305 TCGv t0 = tcg_temp_new();
ths6c5c1e22008-06-24 15:12:27 +000015306
ths0eaef5a2008-07-23 16:14:22 +000015307 op2 = MASK_MFMC0(ctx->opcode);
ths6c5c1e22008-06-24 15:12:27 +000015308 switch (op2) {
15309 case OPC_DMT:
Aurelien Jarnod75c1352013-01-01 18:02:22 +010015310 check_insn(ctx, ASE_MT);
Nathan Froyd9ed57262010-10-29 07:48:46 -070015311 gen_helper_dmt(t0);
aurel3235fbce22009-04-08 21:47:55 +000015312 gen_store_gpr(t0, rt);
ths6c5c1e22008-06-24 15:12:27 +000015313 break;
15314 case OPC_EMT:
Aurelien Jarnod75c1352013-01-01 18:02:22 +010015315 check_insn(ctx, ASE_MT);
Nathan Froyd9ed57262010-10-29 07:48:46 -070015316 gen_helper_emt(t0);
aurel3235fbce22009-04-08 21:47:55 +000015317 gen_store_gpr(t0, rt);
aurel32da806822008-11-15 12:12:08 +000015318 break;
ths6c5c1e22008-06-24 15:12:27 +000015319 case OPC_DVPE:
Aurelien Jarnod75c1352013-01-01 18:02:22 +010015320 check_insn(ctx, ASE_MT);
Blue Swirl895c2d02012-09-02 14:52:59 +000015321 gen_helper_dvpe(t0, cpu_env);
aurel3235fbce22009-04-08 21:47:55 +000015322 gen_store_gpr(t0, rt);
ths6c5c1e22008-06-24 15:12:27 +000015323 break;
15324 case OPC_EVPE:
Aurelien Jarnod75c1352013-01-01 18:02:22 +010015325 check_insn(ctx, ASE_MT);
Blue Swirl895c2d02012-09-02 14:52:59 +000015326 gen_helper_evpe(t0, cpu_env);
aurel3235fbce22009-04-08 21:47:55 +000015327 gen_store_gpr(t0, rt);
ths6c5c1e22008-06-24 15:12:27 +000015328 break;
15329 case OPC_DI:
Aurelien Jarnod75c1352013-01-01 18:02:22 +010015330 check_insn(ctx, ISA_MIPS32R2);
aurel32867abc72009-04-13 08:53:12 +000015331 save_cpu_state(ctx, 1);
Blue Swirl895c2d02012-09-02 14:52:59 +000015332 gen_helper_di(t0, cpu_env);
aurel3235fbce22009-04-08 21:47:55 +000015333 gen_store_gpr(t0, rt);
ths6c5c1e22008-06-24 15:12:27 +000015334 /* Stop translation as we may have switched the execution mode */
15335 ctx->bstate = BS_STOP;
15336 break;
15337 case OPC_EI:
Aurelien Jarnod75c1352013-01-01 18:02:22 +010015338 check_insn(ctx, ISA_MIPS32R2);
aurel32867abc72009-04-13 08:53:12 +000015339 save_cpu_state(ctx, 1);
Blue Swirl895c2d02012-09-02 14:52:59 +000015340 gen_helper_ei(t0, cpu_env);
aurel3235fbce22009-04-08 21:47:55 +000015341 gen_store_gpr(t0, rt);
ths6c5c1e22008-06-24 15:12:27 +000015342 /* Stop translation as we may have switched the execution mode */
15343 ctx->bstate = BS_STOP;
15344 break;
15345 default: /* Invalid */
15346 MIPS_INVAL("mfmc0");
15347 generate_exception(ctx, EXCP_RI);
15348 break;
15349 }
ths6c5c1e22008-06-24 15:12:27 +000015350 tcg_temp_free(t0);
ths7a387ff2006-12-06 20:17:30 +000015351 }
ths0eaef5a2008-07-23 16:14:22 +000015352#endif /* !CONFIG_USER_ONLY */
ths7a387ff2006-12-06 20:17:30 +000015353 break;
ths7a387ff2006-12-06 20:17:30 +000015354 case OPC_RDPGPR:
Aurelien Jarnod75c1352013-01-01 18:02:22 +010015355 check_insn(ctx, ISA_MIPS32R2);
thsbe24bb42008-06-23 12:57:09 +000015356 gen_load_srsgpr(rt, rd);
thsead93602007-09-06 00:18:15 +000015357 break;
ths7a387ff2006-12-06 20:17:30 +000015358 case OPC_WRPGPR:
Aurelien Jarnod75c1352013-01-01 18:02:22 +010015359 check_insn(ctx, ISA_MIPS32R2);
thsbe24bb42008-06-23 12:57:09 +000015360 gen_store_srsgpr(rt, rd);
ths38121542007-04-02 17:28:07 +000015361 break;
bellard6af0bf92005-07-02 14:58:51 +000015362 default:
ths923617a2007-05-11 00:16:06 +000015363 MIPS_INVAL("cp0");
ths7a387ff2006-12-06 20:17:30 +000015364 generate_exception(ctx, EXCP_RI);
bellard6af0bf92005-07-02 14:58:51 +000015365 break;
15366 }
15367 break;
aurel32324d9e32009-04-11 18:42:17 +000015368 case OPC_ADDI: /* Arithmetic with immediate opcode */
15369 case OPC_ADDIU:
Aurelien Jarnod75c1352013-01-01 18:02:22 +010015370 gen_arith_imm(ctx, op, rt, rs, imm);
ths7a387ff2006-12-06 20:17:30 +000015371 break;
aurel32324d9e32009-04-11 18:42:17 +000015372 case OPC_SLTI: /* Set on less than with immediate opcode */
15373 case OPC_SLTIU:
Aurelien Jarnod75c1352013-01-01 18:02:22 +010015374 gen_slt_imm(ctx, op, rt, rs, imm);
aurel32324d9e32009-04-11 18:42:17 +000015375 break;
15376 case OPC_ANDI: /* Arithmetic with immediate opcode */
15377 case OPC_LUI:
15378 case OPC_ORI:
15379 case OPC_XORI:
Aurelien Jarnod75c1352013-01-01 18:02:22 +010015380 gen_logic_imm(ctx, op, rt, rs, imm);
aurel32324d9e32009-04-11 18:42:17 +000015381 break;
ths7a387ff2006-12-06 20:17:30 +000015382 case OPC_J ... OPC_JAL: /* Jump */
15383 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2;
Nathan Froyd7dca4ad2009-12-08 08:06:25 -080015384 gen_compute_branch(ctx, op, 4, rs, rt, offset);
Nathan Froydc9602062009-12-08 08:06:27 -080015385 *is_branch = 1;
15386 break;
ths7a387ff2006-12-06 20:17:30 +000015387 case OPC_BEQ ... OPC_BGTZ: /* Branch */
15388 case OPC_BEQL ... OPC_BGTZL:
Nathan Froyd7dca4ad2009-12-08 08:06:25 -080015389 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2);
Nathan Froydc9602062009-12-08 08:06:27 -080015390 *is_branch = 1;
15391 break;
ths7a387ff2006-12-06 20:17:30 +000015392 case OPC_LB ... OPC_LWR: /* Load and stores */
Aurelien Jarno5c13fdf2010-07-01 07:47:00 +020015393 case OPC_LL:
Aurelien Jarnod75c1352013-01-01 18:02:22 +010015394 gen_ld(ctx, op, rt, rs, imm);
Aurelien Jarno5c13fdf2010-07-01 07:47:00 +020015395 break;
ths7a387ff2006-12-06 20:17:30 +000015396 case OPC_SB ... OPC_SW:
15397 case OPC_SWR:
Aurelien Jarno5c13fdf2010-07-01 07:47:00 +020015398 gen_st(ctx, op, rt, rs, imm);
ths7a387ff2006-12-06 20:17:30 +000015399 break;
aurel32d66c7132009-04-11 18:42:55 +000015400 case OPC_SC:
15401 gen_st_cond(ctx, op, rt, rs, imm);
15402 break;
ths7a387ff2006-12-06 20:17:30 +000015403 case OPC_CACHE:
Eric Johnson2e154972011-09-17 17:05:32 -070015404 check_cp0_enabled(ctx);
Aurelien Jarnod75c1352013-01-01 18:02:22 +010015405 check_insn(ctx, ISA_MIPS3 | ISA_MIPS32);
thsead93602007-09-06 00:18:15 +000015406 /* Treat as NOP. */
ths34ae7b52007-05-18 01:13:09 +000015407 break;
ths7a387ff2006-12-06 20:17:30 +000015408 case OPC_PREF:
Aurelien Jarnod75c1352013-01-01 18:02:22 +010015409 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32);
thsead93602007-09-06 00:18:15 +000015410 /* Treat as NOP. */
bellard6af0bf92005-07-02 14:58:51 +000015411 break;
bellard4ad40f32005-12-05 19:59:36 +000015412
ths923617a2007-05-11 00:16:06 +000015413 /* Floating point (COP1). */
ths7a387ff2006-12-06 20:17:30 +000015414 case OPC_LWC1:
15415 case OPC_LDC1:
15416 case OPC_SWC1:
15417 case OPC_SDC1:
Nathan Froyd26ebe462010-05-24 09:19:35 -070015418 gen_cop1_ldst(env, ctx, op, rt, rs, imm);
bellard6ea83fe2006-06-14 12:56:19 +000015419 break;
15420
ths7a387ff2006-12-06 20:17:30 +000015421 case OPC_CP1:
ths36d23952007-02-28 22:37:42 +000015422 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
ths5e755512007-05-29 16:52:57 +000015423 check_cp1_enabled(ctx);
ths36d23952007-02-28 22:37:42 +000015424 op1 = MASK_CP1(ctx->opcode);
15425 switch (op1) {
ths3a95e3a2007-06-02 00:25:12 +000015426 case OPC_MFHC1:
15427 case OPC_MTHC1:
Aurelien Jarnod75c1352013-01-01 18:02:22 +010015428 check_insn(ctx, ISA_MIPS32R2);
ths36d23952007-02-28 22:37:42 +000015429 case OPC_MFC1:
15430 case OPC_CFC1:
15431 case OPC_MTC1:
15432 case OPC_CTC1:
thse189e742007-09-24 12:48:00 +000015433 gen_cp1(ctx, op1, rt, rd);
15434 break;
thsd26bc212007-11-08 18:05:37 +000015435#if defined(TARGET_MIPS64)
ths36d23952007-02-28 22:37:42 +000015436 case OPC_DMFC1:
15437 case OPC_DMTC1:
Aurelien Jarnod75c1352013-01-01 18:02:22 +010015438 check_insn(ctx, ISA_MIPS3);
ths36d23952007-02-28 22:37:42 +000015439 gen_cp1(ctx, op1, rt, rd);
15440 break;
thse189e742007-09-24 12:48:00 +000015441#endif
thsfbcc6822007-05-11 09:59:10 +000015442 case OPC_BC1ANY2:
15443 case OPC_BC1ANY4:
thsb8aa4592007-12-30 15:36:58 +000015444 check_cop1x(ctx);
Aurelien Jarnod75c1352013-01-01 18:02:22 +010015445 check_insn(ctx, ASE_MIPS3D);
thsd8a59502007-10-23 13:15:33 +000015446 /* fall through */
15447 case OPC_BC1:
Aurelien Jarnod75c1352013-01-01 18:02:22 +010015448 gen_compute_branch1(ctx, MASK_BC1(ctx->opcode),
ths5a5012e2007-05-07 13:55:33 +000015449 (rt >> 2) & 0x7, imm << 2);
Nathan Froydc9602062009-12-08 08:06:27 -080015450 *is_branch = 1;
15451 break;
ths36d23952007-02-28 22:37:42 +000015452 case OPC_S_FMT:
15453 case OPC_D_FMT:
15454 case OPC_W_FMT:
15455 case OPC_L_FMT:
ths5a5012e2007-05-07 13:55:33 +000015456 case OPC_PS_FMT:
Nathan Froydbf4120a2010-06-08 13:29:56 -070015457 gen_farith(ctx, ctx->opcode & FOP(0x3f, 0x1f), rt, rd, sa,
ths5a5012e2007-05-07 13:55:33 +000015458 (imm >> 8) & 0x7);
ths36d23952007-02-28 22:37:42 +000015459 break;
15460 default:
ths923617a2007-05-11 00:16:06 +000015461 MIPS_INVAL("cp1");
thse397ee32007-03-23 00:43:28 +000015462 generate_exception (ctx, EXCP_RI);
ths36d23952007-02-28 22:37:42 +000015463 break;
15464 }
15465 } else {
15466 generate_exception_err(ctx, EXCP_CpU, 1);
bellard6ea83fe2006-06-14 12:56:19 +000015467 }
bellard4ad40f32005-12-05 19:59:36 +000015468 break;
15469
15470 /* COP2. */
ths7a387ff2006-12-06 20:17:30 +000015471 case OPC_LWC2:
15472 case OPC_LDC2:
15473 case OPC_SWC2:
15474 case OPC_SDC2:
ths7a387ff2006-12-06 20:17:30 +000015475 /* COP2: Not implemented. */
bellard4ad40f32005-12-05 19:59:36 +000015476 generate_exception_err(ctx, EXCP_CpU, 2);
15477 break;
Richard Hendersonbd277fa2012-09-18 21:59:44 -070015478 case OPC_CP2:
Aurelien Jarnod75c1352013-01-01 18:02:22 +010015479 check_insn(ctx, INSN_LOONGSON2F);
Richard Hendersonbd277fa2012-09-18 21:59:44 -070015480 /* Note that these instructions use different fields. */
15481 gen_loongson_multimedia(ctx, sa, rd, rt);
15482 break;
bellard4ad40f32005-12-05 19:59:36 +000015483
ths7a387ff2006-12-06 20:17:30 +000015484 case OPC_CP3:
ths36d23952007-02-28 22:37:42 +000015485 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
ths5e755512007-05-29 16:52:57 +000015486 check_cp1_enabled(ctx);
ths36d23952007-02-28 22:37:42 +000015487 op1 = MASK_CP3(ctx->opcode);
15488 switch (op1) {
ths5a5012e2007-05-07 13:55:33 +000015489 case OPC_LWXC1:
15490 case OPC_LDXC1:
15491 case OPC_LUXC1:
15492 case OPC_SWXC1:
15493 case OPC_SDXC1:
15494 case OPC_SUXC1:
ths93b12cc2007-05-20 01:36:29 +000015495 gen_flt3_ldst(ctx, op1, sa, rd, rs, rt);
ths5a5012e2007-05-07 13:55:33 +000015496 break;
thse0c84da2007-04-07 01:11:39 +000015497 case OPC_PREFX:
thsead93602007-09-06 00:18:15 +000015498 /* Treat as NOP. */
thse0c84da2007-04-07 01:11:39 +000015499 break;
ths5a5012e2007-05-07 13:55:33 +000015500 case OPC_ALNV_PS:
15501 case OPC_MADD_S:
15502 case OPC_MADD_D:
15503 case OPC_MADD_PS:
15504 case OPC_MSUB_S:
15505 case OPC_MSUB_D:
15506 case OPC_MSUB_PS:
15507 case OPC_NMADD_S:
15508 case OPC_NMADD_D:
15509 case OPC_NMADD_PS:
15510 case OPC_NMSUB_S:
15511 case OPC_NMSUB_D:
15512 case OPC_NMSUB_PS:
15513 gen_flt3_arith(ctx, op1, sa, rs, rd, rt);
15514 break;
ths36d23952007-02-28 22:37:42 +000015515 default:
ths923617a2007-05-11 00:16:06 +000015516 MIPS_INVAL("cp3");
thse397ee32007-03-23 00:43:28 +000015517 generate_exception (ctx, EXCP_RI);
ths36d23952007-02-28 22:37:42 +000015518 break;
15519 }
15520 } else {
thse397ee32007-03-23 00:43:28 +000015521 generate_exception_err(ctx, EXCP_CpU, 1);
ths7a387ff2006-12-06 20:17:30 +000015522 }
bellard4ad40f32005-12-05 19:59:36 +000015523 break;
15524
thsd26bc212007-11-08 18:05:37 +000015525#if defined(TARGET_MIPS64)
ths7a387ff2006-12-06 20:17:30 +000015526 /* MIPS64 opcodes */
15527 case OPC_LWU:
15528 case OPC_LDL ... OPC_LDR:
ths7a387ff2006-12-06 20:17:30 +000015529 case OPC_LLD:
15530 case OPC_LD:
Aurelien Jarnod75c1352013-01-01 18:02:22 +010015531 check_insn(ctx, ISA_MIPS3);
Aurelien Jarno5c13fdf2010-07-01 07:47:00 +020015532 check_mips_64(ctx);
Aurelien Jarnod75c1352013-01-01 18:02:22 +010015533 gen_ld(ctx, op, rt, rs, imm);
Aurelien Jarno5c13fdf2010-07-01 07:47:00 +020015534 break;
15535 case OPC_SDL ... OPC_SDR:
ths7a387ff2006-12-06 20:17:30 +000015536 case OPC_SD:
Aurelien Jarnod75c1352013-01-01 18:02:22 +010015537 check_insn(ctx, ISA_MIPS3);
thse189e742007-09-24 12:48:00 +000015538 check_mips_64(ctx);
Aurelien Jarno5c13fdf2010-07-01 07:47:00 +020015539 gen_st(ctx, op, rt, rs, imm);
ths7a387ff2006-12-06 20:17:30 +000015540 break;
aurel32d66c7132009-04-11 18:42:55 +000015541 case OPC_SCD:
Aurelien Jarnod75c1352013-01-01 18:02:22 +010015542 check_insn(ctx, ISA_MIPS3);
aurel32d66c7132009-04-11 18:42:55 +000015543 check_mips_64(ctx);
15544 gen_st_cond(ctx, op, rt, rs, imm);
15545 break;
aurel32324d9e32009-04-11 18:42:17 +000015546 case OPC_DADDI:
15547 case OPC_DADDIU:
Aurelien Jarnod75c1352013-01-01 18:02:22 +010015548 check_insn(ctx, ISA_MIPS3);
thse189e742007-09-24 12:48:00 +000015549 check_mips_64(ctx);
Aurelien Jarnod75c1352013-01-01 18:02:22 +010015550 gen_arith_imm(ctx, op, rt, rs, imm);
ths7a387ff2006-12-06 20:17:30 +000015551 break;
bellard6af0bf92005-07-02 14:58:51 +000015552#endif
ths7a387ff2006-12-06 20:17:30 +000015553 case OPC_JALX:
Aurelien Jarnod75c1352013-01-01 18:02:22 +010015554 check_insn(ctx, ASE_MIPS16 | ASE_MICROMIPS);
Nathan Froyd364d4832009-12-08 08:06:29 -080015555 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2;
15556 gen_compute_branch(ctx, op, 4, rs, rt, offset);
15557 *is_branch = 1;
15558 break;
ths7a387ff2006-12-06 20:17:30 +000015559 case OPC_MDMX:
Aurelien Jarnod75c1352013-01-01 18:02:22 +010015560 check_insn(ctx, ASE_MDMX);
ths7a387ff2006-12-06 20:17:30 +000015561 /* MDMX: Not implemented. */
bellard6af0bf92005-07-02 14:58:51 +000015562 default: /* Invalid */
ths923617a2007-05-11 00:16:06 +000015563 MIPS_INVAL("major opcode");
bellard6af0bf92005-07-02 14:58:51 +000015564 generate_exception(ctx, EXCP_RI);
15565 break;
15566 }
bellard6af0bf92005-07-02 14:58:51 +000015567}
15568
ths2cfc5f12008-07-18 18:01:29 +000015569static inline void
Andreas Färber7db13fa2012-03-14 01:38:22 +010015570gen_intermediate_code_internal (CPUMIPSState *env, TranslationBlock *tb,
ths820e00f2007-03-19 21:46:06 +000015571 int search_pc)
bellard6af0bf92005-07-02 14:58:51 +000015572{
ths278d0702007-05-31 23:42:46 +000015573 DisasContext ctx;
bellard6af0bf92005-07-02 14:58:51 +000015574 target_ulong pc_start;
15575 uint16_t *gen_opc_end;
aliguoria1d1bb32008-11-18 20:07:32 +000015576 CPUBreakpoint *bp;
bellard6af0bf92005-07-02 14:58:51 +000015577 int j, lj = -1;
pbrook2e70f6e2008-06-29 01:03:05 +000015578 int num_insns;
15579 int max_insns;
Nathan Froydc9602062009-12-08 08:06:27 -080015580 int insn_bytes;
15581 int is_branch;
bellard6af0bf92005-07-02 14:58:51 +000015582
aliguori93fcfe32009-01-15 22:34:14 +000015583 if (search_pc)
15584 qemu_log("search pc %d\n", search_pc);
bellard4ad40f32005-12-05 19:59:36 +000015585
bellard6af0bf92005-07-02 14:58:51 +000015586 pc_start = tb->pc;
Evgeny Voevodin92414b32012-11-12 13:27:47 +040015587 gen_opc_end = tcg_ctx.gen_opc_buf + OPC_MAX_SIZE;
bellard6af0bf92005-07-02 14:58:51 +000015588 ctx.pc = pc_start;
bellard4ad40f32005-12-05 19:59:36 +000015589 ctx.saved_pc = -1;
Nathan Froyd7b270ef2009-07-14 08:33:11 -070015590 ctx.singlestep_enabled = env->singlestep_enabled;
Aurelien Jarnod75c1352013-01-01 18:02:22 +010015591 ctx.insn_flags = env->insn_flags;
bellard6af0bf92005-07-02 14:58:51 +000015592 ctx.tb = tb;
15593 ctx.bstate = BS_NONE;
bellard4ad40f32005-12-05 19:59:36 +000015594 /* Restore delay slot state from the tb context. */
j_mayerc0686882007-09-20 22:47:42 +000015595 ctx.hflags = (uint32_t)tb->flags; /* FIXME: maybe use 64 bits here? */
thsfd4a04e2007-05-18 11:55:54 +000015596 restore_cpu_state(env, &ctx);
aurel32932e71c2009-01-12 21:33:13 +000015597#ifdef CONFIG_USER_ONLY
ths0eaef5a2008-07-23 16:14:22 +000015598 ctx.mem_idx = MIPS_HFLAG_UM;
aurel32932e71c2009-01-12 21:33:13 +000015599#else
ths0eaef5a2008-07-23 16:14:22 +000015600 ctx.mem_idx = ctx.hflags & MIPS_HFLAG_KSU;
aurel32932e71c2009-01-12 21:33:13 +000015601#endif
pbrook2e70f6e2008-06-29 01:03:05 +000015602 num_insns = 0;
pbrook2e70f6e2008-06-29 01:03:05 +000015603 max_insns = tb->cflags & CF_COUNT_MASK;
15604 if (max_insns == 0)
15605 max_insns = CF_COUNT_MASK;
aliguorid12d51d2009-01-15 21:48:06 +000015606 LOG_DISAS("\ntb %p idx %d hflags %04x\n", tb, ctx.mem_idx, ctx.hflags);
pbrook2e70f6e2008-06-29 01:03:05 +000015607 gen_icount_start();
thsfaf7aaa2008-06-11 12:26:29 +000015608 while (ctx.bstate == BS_NONE) {
Blue Swirl72cf2d42009-09-12 07:36:22 +000015609 if (unlikely(!QTAILQ_EMPTY(&env->breakpoints))) {
15610 QTAILQ_FOREACH(bp, &env->breakpoints, entry) {
aliguoria1d1bb32008-11-18 20:07:32 +000015611 if (bp->pc == ctx.pc) {
ths278d0702007-05-31 23:42:46 +000015612 save_cpu_state(&ctx, 1);
bellard4ad40f32005-12-05 19:59:36 +000015613 ctx.bstate = BS_BRANCH;
Blue Swirl895c2d02012-09-02 14:52:59 +000015614 gen_helper_0e0i(raise_exception, EXCP_DEBUG);
thsce62e5b2007-09-11 10:04:58 +000015615 /* Include the breakpoint location or the tb won't
15616 * be flushed when it must be. */
15617 ctx.pc += 4;
bellard4ad40f32005-12-05 19:59:36 +000015618 goto done_generating;
15619 }
15620 }
15621 }
15622
bellard6af0bf92005-07-02 14:58:51 +000015623 if (search_pc) {
Evgeny Voevodin92414b32012-11-12 13:27:47 +040015624 j = tcg_ctx.gen_opc_ptr - tcg_ctx.gen_opc_buf;
bellard6af0bf92005-07-02 14:58:51 +000015625 if (lj < j) {
15626 lj++;
15627 while (lj < j)
Evgeny Voevodinab1103d2012-11-21 11:43:06 +040015628 tcg_ctx.gen_opc_instr_start[lj++] = 0;
bellard6af0bf92005-07-02 14:58:51 +000015629 }
Evgeny Voevodin25983ca2012-11-21 11:43:04 +040015630 tcg_ctx.gen_opc_pc[lj] = ctx.pc;
bellard4ad40f32005-12-05 19:59:36 +000015631 gen_opc_hflags[lj] = ctx.hflags & MIPS_HFLAG_BMASK;
Aurelien Jarno46364012012-10-28 15:42:55 +010015632 gen_opc_btarget[lj] = ctx.btarget;
Evgeny Voevodinab1103d2012-11-21 11:43:06 +040015633 tcg_ctx.gen_opc_instr_start[lj] = 1;
Evgeny Voevodinc9c99c22012-11-21 11:43:05 +040015634 tcg_ctx.gen_opc_icount[lj] = num_insns;
bellard6af0bf92005-07-02 14:58:51 +000015635 }
pbrook2e70f6e2008-06-29 01:03:05 +000015636 if (num_insns + 1 == max_insns && (tb->cflags & CF_LAST_IO))
15637 gen_io_start();
Nathan Froydc9602062009-12-08 08:06:27 -080015638
15639 is_branch = 0;
Nathan Froyd364d4832009-12-08 08:06:29 -080015640 if (!(ctx.hflags & MIPS_HFLAG_M16)) {
Blue Swirl895c2d02012-09-02 14:52:59 +000015641 ctx.opcode = cpu_ldl_code(env, ctx.pc);
Nathan Froydc9602062009-12-08 08:06:27 -080015642 insn_bytes = 4;
15643 decode_opc(env, &ctx, &is_branch);
Aurelien Jarnod75c1352013-01-01 18:02:22 +010015644 } else if (ctx.insn_flags & ASE_MICROMIPS) {
Blue Swirl895c2d02012-09-02 14:52:59 +000015645 ctx.opcode = cpu_lduw_code(env, ctx.pc);
Nathan Froyd3c824102010-06-08 13:29:59 -070015646 insn_bytes = decode_micromips_opc(env, &ctx, &is_branch);
Aurelien Jarnod75c1352013-01-01 18:02:22 +010015647 } else if (ctx.insn_flags & ASE_MIPS16) {
Blue Swirl895c2d02012-09-02 14:52:59 +000015648 ctx.opcode = cpu_lduw_code(env, ctx.pc);
Nathan Froyd364d4832009-12-08 08:06:29 -080015649 insn_bytes = decode_mips16_opc(env, &ctx, &is_branch);
Nathan Froydc9602062009-12-08 08:06:27 -080015650 } else {
15651 generate_exception(&ctx, EXCP_RI);
Nathan Froyd3c824102010-06-08 13:29:59 -070015652 ctx.bstate = BS_STOP;
Nathan Froydc9602062009-12-08 08:06:27 -080015653 break;
15654 }
15655 if (!is_branch) {
Aurelien Jarnod75c1352013-01-01 18:02:22 +010015656 handle_delay_slot(&ctx, insn_bytes);
Nathan Froydc9602062009-12-08 08:06:27 -080015657 }
15658 ctx.pc += insn_bytes;
15659
pbrook2e70f6e2008-06-29 01:03:05 +000015660 num_insns++;
bellard4ad40f32005-12-05 19:59:36 +000015661
Nathan Froyd7b270ef2009-07-14 08:33:11 -070015662 /* Execute a branch and its delay slot as a single instruction.
15663 This is what GDB expects and is consistent with what the
15664 hardware does (e.g. if a delay slot instruction faults, the
15665 reported PC is the PC of the branch). */
15666 if (env->singlestep_enabled && (ctx.hflags & MIPS_HFLAG_BMASK) == 0)
bellard4ad40f32005-12-05 19:59:36 +000015667 break;
15668
bellard6af0bf92005-07-02 14:58:51 +000015669 if ((ctx.pc & (TARGET_PAGE_SIZE - 1)) == 0)
15670 break;
bellard4ad40f32005-12-05 19:59:36 +000015671
Evgeny Voevodinefd7f482012-11-12 13:27:45 +040015672 if (tcg_ctx.gen_opc_ptr >= gen_opc_end) {
thsfaf7aaa2008-06-11 12:26:29 +000015673 break;
Evgeny Voevodinefd7f482012-11-12 13:27:45 +040015674 }
thsfaf7aaa2008-06-11 12:26:29 +000015675
pbrook2e70f6e2008-06-29 01:03:05 +000015676 if (num_insns >= max_insns)
15677 break;
aurel321b530a62009-04-05 20:08:59 +000015678
15679 if (singlestep)
15680 break;
bellard6af0bf92005-07-02 14:58:51 +000015681 }
pbrook2e70f6e2008-06-29 01:03:05 +000015682 if (tb->cflags & CF_LAST_IO)
15683 gen_io_end();
Nathan Froyd7b270ef2009-07-14 08:33:11 -070015684 if (env->singlestep_enabled && ctx.bstate != BS_BRANCH) {
ths278d0702007-05-31 23:42:46 +000015685 save_cpu_state(&ctx, ctx.bstate == BS_NONE);
Blue Swirl895c2d02012-09-02 14:52:59 +000015686 gen_helper_0e0i(raise_exception, EXCP_DEBUG);
ths16c00cb2007-04-14 12:56:46 +000015687 } else {
aurel3269585492009-01-14 19:40:36 +000015688 switch (ctx.bstate) {
ths16c00cb2007-04-14 12:56:46 +000015689 case BS_STOP:
thsdf1561e2007-05-23 08:18:27 +000015690 gen_goto_tb(&ctx, 0, ctx.pc);
15691 break;
ths16c00cb2007-04-14 12:56:46 +000015692 case BS_NONE:
ths278d0702007-05-31 23:42:46 +000015693 save_cpu_state(&ctx, 0);
ths16c00cb2007-04-14 12:56:46 +000015694 gen_goto_tb(&ctx, 0, ctx.pc);
15695 break;
ths5a5012e2007-05-07 13:55:33 +000015696 case BS_EXCP:
bellard57fec1f2008-02-01 10:50:11 +000015697 tcg_gen_exit_tb(0);
ths5a5012e2007-05-07 13:55:33 +000015698 break;
ths16c00cb2007-04-14 12:56:46 +000015699 case BS_BRANCH:
15700 default:
15701 break;
aurel3269585492009-01-14 19:40:36 +000015702 }
bellard4ad40f32005-12-05 19:59:36 +000015703 }
bellard4ad40f32005-12-05 19:59:36 +000015704done_generating:
pbrook2e70f6e2008-06-29 01:03:05 +000015705 gen_icount_end(tb, num_insns);
Evgeny Voevodinefd7f482012-11-12 13:27:45 +040015706 *tcg_ctx.gen_opc_ptr = INDEX_op_end;
bellard6af0bf92005-07-02 14:58:51 +000015707 if (search_pc) {
Evgeny Voevodin92414b32012-11-12 13:27:47 +040015708 j = tcg_ctx.gen_opc_ptr - tcg_ctx.gen_opc_buf;
bellard6af0bf92005-07-02 14:58:51 +000015709 lj++;
15710 while (lj <= j)
Evgeny Voevodinab1103d2012-11-21 11:43:06 +040015711 tcg_ctx.gen_opc_instr_start[lj++] = 0;
bellard6af0bf92005-07-02 14:58:51 +000015712 } else {
15713 tb->size = ctx.pc - pc_start;
pbrook2e70f6e2008-06-29 01:03:05 +000015714 tb->icount = num_insns;
bellard6af0bf92005-07-02 14:58:51 +000015715 }
15716#ifdef DEBUG_DISAS
aliguorid12d51d2009-01-15 21:48:06 +000015717 LOG_DISAS("\n");
aliguori8fec2b82009-01-15 22:36:53 +000015718 if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) {
aliguori93fcfe32009-01-15 22:34:14 +000015719 qemu_log("IN: %s\n", lookup_symbol(pc_start));
Blue Swirlf4359b92012-09-08 12:40:00 +000015720 log_target_disas(env, pc_start, ctx.pc - pc_start, 0);
aliguori93fcfe32009-01-15 22:34:14 +000015721 qemu_log("\n");
bellard6af0bf92005-07-02 14:58:51 +000015722 }
bellard6af0bf92005-07-02 14:58:51 +000015723#endif
bellard6af0bf92005-07-02 14:58:51 +000015724}
15725
Andreas Färber7db13fa2012-03-14 01:38:22 +010015726void gen_intermediate_code (CPUMIPSState *env, struct TranslationBlock *tb)
bellard6af0bf92005-07-02 14:58:51 +000015727{
ths2cfc5f12008-07-18 18:01:29 +000015728 gen_intermediate_code_internal(env, tb, 0);
bellard6af0bf92005-07-02 14:58:51 +000015729}
15730
Andreas Färber7db13fa2012-03-14 01:38:22 +010015731void gen_intermediate_code_pc (CPUMIPSState *env, struct TranslationBlock *tb)
bellard6af0bf92005-07-02 14:58:51 +000015732{
ths2cfc5f12008-07-18 18:01:29 +000015733 gen_intermediate_code_internal(env, tb, 1);
bellard6af0bf92005-07-02 14:58:51 +000015734}
15735
Andreas Färber7db13fa2012-03-14 01:38:22 +010015736static void fpu_dump_state(CPUMIPSState *env, FILE *f, fprintf_function fpu_fprintf,
ths8706c382008-07-21 21:38:04 +000015737 int flags)
bellard6ea83fe2006-06-14 12:56:19 +000015738{
15739 int i;
ths5e755512007-05-29 16:52:57 +000015740 int is_fpu64 = !!(env->hflags & MIPS_HFLAG_F64);
bellard6ea83fe2006-06-14 12:56:19 +000015741
Stefan Weil2a5612e2010-04-01 23:05:14 +020015742#define printfpr(fp) \
15743 do { \
15744 if (is_fpu64) \
15745 fpu_fprintf(f, "w:%08x d:%016" PRIx64 \
15746 " fd:%13g fs:%13g psu: %13g\n", \
15747 (fp)->w[FP_ENDIAN_IDX], (fp)->d, \
15748 (double)(fp)->fd, \
15749 (double)(fp)->fs[FP_ENDIAN_IDX], \
15750 (double)(fp)->fs[!FP_ENDIAN_IDX]); \
15751 else { \
15752 fpr_t tmp; \
15753 tmp.w[FP_ENDIAN_IDX] = (fp)->w[FP_ENDIAN_IDX]; \
15754 tmp.w[!FP_ENDIAN_IDX] = ((fp) + 1)->w[FP_ENDIAN_IDX]; \
15755 fpu_fprintf(f, "w:%08x d:%016" PRIx64 \
15756 " fd:%13g fs:%13g psu:%13g\n", \
15757 tmp.w[FP_ENDIAN_IDX], tmp.d, \
15758 (double)tmp.fd, \
15759 (double)tmp.fs[FP_ENDIAN_IDX], \
15760 (double)tmp.fs[!FP_ENDIAN_IDX]); \
15761 } \
bellard6ea83fe2006-06-14 12:56:19 +000015762 } while(0)
15763
ths5a5012e2007-05-07 13:55:33 +000015764
Stefan Weil9a78eea2010-10-22 23:03:33 +020015765 fpu_fprintf(f, "CP1 FCR0 0x%08x FCR31 0x%08x SR.FR %d fp_status 0x%02x\n",
15766 env->active_fpu.fcr0, env->active_fpu.fcr31, is_fpu64,
thsf01be152008-09-18 11:57:27 +000015767 get_float_exception_flags(&env->active_fpu.fp_status));
ths5a5012e2007-05-07 13:55:33 +000015768 for (i = 0; i < 32; (is_fpu64) ? i++ : (i += 2)) {
15769 fpu_fprintf(f, "%3s: ", fregnames[i]);
thsf01be152008-09-18 11:57:27 +000015770 printfpr(&env->active_fpu.fpr[i]);
bellard6ea83fe2006-06-14 12:56:19 +000015771 }
15772
15773#undef printfpr
15774}
15775
thsd26bc212007-11-08 18:05:37 +000015776#if defined(TARGET_MIPS64) && defined(MIPS_DEBUG_SIGN_EXTENSIONS)
thsc570fd12006-12-21 01:19:56 +000015777/* Debug help: The architecture requires 32bit code to maintain proper
thsc7e8a932008-07-05 21:54:32 +000015778 sign-extended values on 64bit machines. */
thsc570fd12006-12-21 01:19:56 +000015779
15780#define SIGN_EXT_P(val) ((((val) & ~0x7fffffff) == 0) || (((val) & ~0x7fffffff) == ~0x7fffffff))
15781
ths8706c382008-07-21 21:38:04 +000015782static void
Andreas Färber7db13fa2012-03-14 01:38:22 +010015783cpu_mips_check_sign_extensions (CPUMIPSState *env, FILE *f,
Stefan Weil9a78eea2010-10-22 23:03:33 +020015784 fprintf_function cpu_fprintf,
ths8706c382008-07-21 21:38:04 +000015785 int flags)
thsc570fd12006-12-21 01:19:56 +000015786{
15787 int i;
15788
thsb5dc7732008-06-27 10:02:35 +000015789 if (!SIGN_EXT_P(env->active_tc.PC))
15790 cpu_fprintf(f, "BROKEN: pc=0x" TARGET_FMT_lx "\n", env->active_tc.PC);
15791 if (!SIGN_EXT_P(env->active_tc.HI[0]))
15792 cpu_fprintf(f, "BROKEN: HI=0x" TARGET_FMT_lx "\n", env->active_tc.HI[0]);
15793 if (!SIGN_EXT_P(env->active_tc.LO[0]))
15794 cpu_fprintf(f, "BROKEN: LO=0x" TARGET_FMT_lx "\n", env->active_tc.LO[0]);
thsc570fd12006-12-21 01:19:56 +000015795 if (!SIGN_EXT_P(env->btarget))
ths3594c772007-02-20 23:37:21 +000015796 cpu_fprintf(f, "BROKEN: btarget=0x" TARGET_FMT_lx "\n", env->btarget);
thsc570fd12006-12-21 01:19:56 +000015797
15798 for (i = 0; i < 32; i++) {
thsb5dc7732008-06-27 10:02:35 +000015799 if (!SIGN_EXT_P(env->active_tc.gpr[i]))
15800 cpu_fprintf(f, "BROKEN: %s=0x" TARGET_FMT_lx "\n", regnames[i], env->active_tc.gpr[i]);
thsc570fd12006-12-21 01:19:56 +000015801 }
15802
15803 if (!SIGN_EXT_P(env->CP0_EPC))
ths3594c772007-02-20 23:37:21 +000015804 cpu_fprintf(f, "BROKEN: EPC=0x" TARGET_FMT_lx "\n", env->CP0_EPC);
Aurelien Jarno5499b6f2009-11-22 13:08:14 +010015805 if (!SIGN_EXT_P(env->lladdr))
15806 cpu_fprintf(f, "BROKEN: LLAddr=0x" TARGET_FMT_lx "\n", env->lladdr);
thsc570fd12006-12-21 01:19:56 +000015807}
15808#endif
15809
Andreas Färber7db13fa2012-03-14 01:38:22 +010015810void cpu_dump_state (CPUMIPSState *env, FILE *f, fprintf_function cpu_fprintf,
bellard6af0bf92005-07-02 14:58:51 +000015811 int flags)
15812{
15813 int i;
ths3b46e622007-09-17 08:09:54 +000015814
Stefan Weila7200c92010-04-02 23:19:48 +020015815 cpu_fprintf(f, "pc=0x" TARGET_FMT_lx " HI=0x" TARGET_FMT_lx
15816 " LO=0x" TARGET_FMT_lx " ds %04x "
15817 TARGET_FMT_lx " " TARGET_FMT_ld "\n",
ths3d5be872008-07-21 07:46:03 +000015818 env->active_tc.PC, env->active_tc.HI[0], env->active_tc.LO[0],
15819 env->hflags, env->btarget, env->bcond);
bellard6af0bf92005-07-02 14:58:51 +000015820 for (i = 0; i < 32; i++) {
15821 if ((i & 3) == 0)
15822 cpu_fprintf(f, "GPR%02d:", i);
thsb5dc7732008-06-27 10:02:35 +000015823 cpu_fprintf(f, " %s " TARGET_FMT_lx, regnames[i], env->active_tc.gpr[i]);
bellard6af0bf92005-07-02 14:58:51 +000015824 if ((i & 3) == 3)
15825 cpu_fprintf(f, "\n");
15826 }
bellard568b6002005-07-02 15:28:16 +000015827
ths3594c772007-02-20 23:37:21 +000015828 cpu_fprintf(f, "CP0 Status 0x%08x Cause 0x%08x EPC 0x" TARGET_FMT_lx "\n",
ths5e755512007-05-29 16:52:57 +000015829 env->CP0_Status, env->CP0_Cause, env->CP0_EPC);
ths3594c772007-02-20 23:37:21 +000015830 cpu_fprintf(f, " Config0 0x%08x Config1 0x%08x LLAddr 0x" TARGET_FMT_lx "\n",
Aurelien Jarno5499b6f2009-11-22 13:08:14 +010015831 env->CP0_Config0, env->CP0_Config1, env->lladdr);
ths5e755512007-05-29 16:52:57 +000015832 if (env->hflags & MIPS_HFLAG_FPU)
ths7a387ff2006-12-06 20:17:30 +000015833 fpu_dump_state(env, f, cpu_fprintf, flags);
thsd26bc212007-11-08 18:05:37 +000015834#if defined(TARGET_MIPS64) && defined(MIPS_DEBUG_SIGN_EXTENSIONS)
thsc570fd12006-12-21 01:19:56 +000015835 cpu_mips_check_sign_extensions(env, f, cpu_fprintf, flags);
15836#endif
bellard6af0bf92005-07-02 14:58:51 +000015837}
15838
Andreas Färber78ce64f2013-01-20 01:22:25 +010015839void mips_tcg_init(void)
ths39454622008-05-04 08:16:10 +000015840{
thsf01be152008-09-18 11:57:27 +000015841 int i;
ths39454622008-05-04 08:16:10 +000015842 static int inited;
15843
15844 /* Initialize various static tables. */
15845 if (inited)
aurel3269585492009-01-14 19:40:36 +000015846 return;
ths39454622008-05-04 08:16:10 +000015847
pbrooka7812ae2008-11-17 14:43:54 +000015848 cpu_env = tcg_global_reg_new_ptr(TCG_AREG0, "env");
aurel32f2c94b92009-04-15 14:42:00 +000015849 TCGV_UNUSED(cpu_gpr[0]);
aurel32bb928db2009-04-11 18:43:20 +000015850 for (i = 1; i < 32; i++)
pbrooka7812ae2008-11-17 14:43:54 +000015851 cpu_gpr[i] = tcg_global_mem_new(TCG_AREG0,
Andreas Färber7db13fa2012-03-14 01:38:22 +010015852 offsetof(CPUMIPSState, active_tc.gpr[i]),
ths4b2eb8d2008-09-18 11:59:03 +000015853 regnames[i]);
Richard Hendersond73ee8a2012-10-09 21:53:19 +020015854
15855 for (i = 0; i < 32; i++) {
15856 int off = offsetof(CPUMIPSState, active_fpu.fpr[i]);
15857 fpu_f64[i] = tcg_global_mem_new_i64(TCG_AREG0, off, fregnames[i]);
15858 }
15859
pbrooka7812ae2008-11-17 14:43:54 +000015860 cpu_PC = tcg_global_mem_new(TCG_AREG0,
Andreas Färber7db13fa2012-03-14 01:38:22 +010015861 offsetof(CPUMIPSState, active_tc.PC), "PC");
ths4b2eb8d2008-09-18 11:59:03 +000015862 for (i = 0; i < MIPS_DSP_ACC; i++) {
pbrooka7812ae2008-11-17 14:43:54 +000015863 cpu_HI[i] = tcg_global_mem_new(TCG_AREG0,
Andreas Färber7db13fa2012-03-14 01:38:22 +010015864 offsetof(CPUMIPSState, active_tc.HI[i]),
ths4b2eb8d2008-09-18 11:59:03 +000015865 regnames_HI[i]);
pbrooka7812ae2008-11-17 14:43:54 +000015866 cpu_LO[i] = tcg_global_mem_new(TCG_AREG0,
Andreas Färber7db13fa2012-03-14 01:38:22 +010015867 offsetof(CPUMIPSState, active_tc.LO[i]),
ths4b2eb8d2008-09-18 11:59:03 +000015868 regnames_LO[i]);
pbrooka7812ae2008-11-17 14:43:54 +000015869 cpu_ACX[i] = tcg_global_mem_new(TCG_AREG0,
Andreas Färber7db13fa2012-03-14 01:38:22 +010015870 offsetof(CPUMIPSState, active_tc.ACX[i]),
ths4b2eb8d2008-09-18 11:59:03 +000015871 regnames_ACX[i]);
15872 }
pbrooka7812ae2008-11-17 14:43:54 +000015873 cpu_dspctrl = tcg_global_mem_new(TCG_AREG0,
Andreas Färber7db13fa2012-03-14 01:38:22 +010015874 offsetof(CPUMIPSState, active_tc.DSPControl),
ths4b2eb8d2008-09-18 11:59:03 +000015875 "DSPControl");
aurel321ba74fb2009-03-29 01:18:52 +000015876 bcond = tcg_global_mem_new(TCG_AREG0,
Andreas Färber7db13fa2012-03-14 01:38:22 +010015877 offsetof(CPUMIPSState, bcond), "bcond");
pbrooka7812ae2008-11-17 14:43:54 +000015878 btarget = tcg_global_mem_new(TCG_AREG0,
Andreas Färber7db13fa2012-03-14 01:38:22 +010015879 offsetof(CPUMIPSState, btarget), "btarget");
aurel3241db4602009-03-29 01:28:29 +000015880 hflags = tcg_global_mem_new_i32(TCG_AREG0,
Andreas Färber7db13fa2012-03-14 01:38:22 +010015881 offsetof(CPUMIPSState, hflags), "hflags");
aurel3241db4602009-03-29 01:28:29 +000015882
pbrooka7812ae2008-11-17 14:43:54 +000015883 fpu_fcr0 = tcg_global_mem_new_i32(TCG_AREG0,
Andreas Färber7db13fa2012-03-14 01:38:22 +010015884 offsetof(CPUMIPSState, active_fpu.fcr0),
pbrooka7812ae2008-11-17 14:43:54 +000015885 "fcr0");
15886 fpu_fcr31 = tcg_global_mem_new_i32(TCG_AREG0,
Andreas Färber7db13fa2012-03-14 01:38:22 +010015887 offsetof(CPUMIPSState, active_fpu.fcr31),
pbrooka7812ae2008-11-17 14:43:54 +000015888 "fcr31");
ths39454622008-05-04 08:16:10 +000015889
ths7dd9e552008-06-08 07:42:23 +000015890 /* register helpers */
pbrooka7812ae2008-11-17 14:43:54 +000015891#define GEN_HELPER 2
ths7dd9e552008-06-08 07:42:23 +000015892#include "helper.h"
15893
ths39454622008-05-04 08:16:10 +000015894 inited = 1;
15895}
15896
bellardaaed9092007-11-10 15:15:54 +000015897#include "translate_init.c"
15898
Andreas Färber30bf9422012-05-05 13:33:04 +020015899MIPSCPU *cpu_mips_init(const char *cpu_model)
bellard6af0bf92005-07-02 14:58:51 +000015900{
Andreas Färber0f71a702012-04-15 23:29:19 +020015901 MIPSCPU *cpu;
bellard6af0bf92005-07-02 14:58:51 +000015902 CPUMIPSState *env;
Anthony Liguoric227f092009-10-01 16:12:16 -050015903 const mips_def_t *def;
bellard6af0bf92005-07-02 14:58:51 +000015904
bellardaaed9092007-11-10 15:15:54 +000015905 def = cpu_mips_find_by_name(cpu_model);
15906 if (!def)
15907 return NULL;
Andreas Färber0f71a702012-04-15 23:29:19 +020015908 cpu = MIPS_CPU(object_new(TYPE_MIPS_CPU));
15909 env = &cpu->env;
bellardaaed9092007-11-10 15:15:54 +000015910 env->cpu_model = def;
Blue Swirl51cc2e72009-11-08 12:50:21 +020015911 env->cpu_model_str = cpu_model;
bellardaaed9092007-11-10 15:15:54 +000015912
Blue Swirl51cc2e72009-11-08 12:50:21 +020015913#ifndef CONFIG_USER_ONLY
15914 mmu_init(env, def);
15915#endif
15916 fpu_init(env, def);
15917 mvp_init(env, def);
Andreas Färberc1caf1d2013-01-16 03:48:37 +010015918
15919 object_property_set_bool(OBJECT(cpu), true, "realized", NULL);
15920
Andreas Färber30bf9422012-05-05 13:33:04 +020015921 return cpu;
ths6ae81772006-12-06 17:48:52 +000015922}
15923
Andreas Färber1bba0dc2012-02-08 03:03:33 +010015924void cpu_state_reset(CPUMIPSState *env)
ths6ae81772006-12-06 17:48:52 +000015925{
Andreas Färber55e5c282012-12-17 06:18:02 +010015926#ifndef CONFIG_USER_ONLY
15927 MIPSCPU *cpu = mips_env_get_cpu(env);
15928 CPUState *cs = CPU(cpu);
15929#endif
ths6ae81772006-12-06 17:48:52 +000015930
Blue Swirl51cc2e72009-11-08 12:50:21 +020015931 /* Reset registers to their default values */
15932 env->CP0_PRid = env->cpu_model->CP0_PRid;
15933 env->CP0_Config0 = env->cpu_model->CP0_Config0;
15934#ifdef TARGET_WORDS_BIGENDIAN
15935 env->CP0_Config0 |= (1 << CP0C0_BE);
15936#endif
15937 env->CP0_Config1 = env->cpu_model->CP0_Config1;
15938 env->CP0_Config2 = env->cpu_model->CP0_Config2;
15939 env->CP0_Config3 = env->cpu_model->CP0_Config3;
15940 env->CP0_Config6 = env->cpu_model->CP0_Config6;
15941 env->CP0_Config7 = env->cpu_model->CP0_Config7;
Aurelien Jarno2a6e32d2009-11-22 13:22:54 +010015942 env->CP0_LLAddr_rw_bitmask = env->cpu_model->CP0_LLAddr_rw_bitmask
15943 << env->cpu_model->CP0_LLAddr_shift;
15944 env->CP0_LLAddr_shift = env->cpu_model->CP0_LLAddr_shift;
Blue Swirl51cc2e72009-11-08 12:50:21 +020015945 env->SYNCI_Step = env->cpu_model->SYNCI_Step;
15946 env->CCRes = env->cpu_model->CCRes;
15947 env->CP0_Status_rw_bitmask = env->cpu_model->CP0_Status_rw_bitmask;
15948 env->CP0_TCStatus_rw_bitmask = env->cpu_model->CP0_TCStatus_rw_bitmask;
15949 env->CP0_SRSCtl = env->cpu_model->CP0_SRSCtl;
15950 env->current_tc = 0;
15951 env->SEGBITS = env->cpu_model->SEGBITS;
15952 env->SEGMask = (target_ulong)((1ULL << env->cpu_model->SEGBITS) - 1);
15953#if defined(TARGET_MIPS64)
15954 if (env->cpu_model->insn_flags & ISA_MIPS3) {
15955 env->SEGMask |= 3ULL << 62;
15956 }
15957#endif
15958 env->PABITS = env->cpu_model->PABITS;
15959 env->PAMask = (target_ulong)((1ULL << env->cpu_model->PABITS) - 1);
15960 env->CP0_SRSConf0_rw_bitmask = env->cpu_model->CP0_SRSConf0_rw_bitmask;
15961 env->CP0_SRSConf0 = env->cpu_model->CP0_SRSConf0;
15962 env->CP0_SRSConf1_rw_bitmask = env->cpu_model->CP0_SRSConf1_rw_bitmask;
15963 env->CP0_SRSConf1 = env->cpu_model->CP0_SRSConf1;
15964 env->CP0_SRSConf2_rw_bitmask = env->cpu_model->CP0_SRSConf2_rw_bitmask;
15965 env->CP0_SRSConf2 = env->cpu_model->CP0_SRSConf2;
15966 env->CP0_SRSConf3_rw_bitmask = env->cpu_model->CP0_SRSConf3_rw_bitmask;
15967 env->CP0_SRSConf3 = env->cpu_model->CP0_SRSConf3;
15968 env->CP0_SRSConf4_rw_bitmask = env->cpu_model->CP0_SRSConf4_rw_bitmask;
15969 env->CP0_SRSConf4 = env->cpu_model->CP0_SRSConf4;
Nathan Froydf1cb0952012-06-07 15:04:14 +000015970 env->active_fpu.fcr0 = env->cpu_model->CP1_fcr0;
Blue Swirl51cc2e72009-11-08 12:50:21 +020015971 env->insn_flags = env->cpu_model->insn_flags;
15972
bellardeeef26c2005-11-26 18:47:06 +000015973#if defined(CONFIG_USER_ONLY)
Maciej W. Rozycki03e6e502012-06-08 02:04:40 +010015974 env->CP0_Status = (MIPS_HFLAG_UM << CP0St_KSU);
Meador Inge94159132012-08-21 12:31:37 -050015975 /* Enable access to the CPUNum, SYNCI_Step, CC, and CCRes RDHWR
15976 hardware registers. */
15977 env->CP0_HWREna |= 0x0000000F;
Nathan Froyd91a75932009-12-11 09:29:20 -080015978 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
Maciej W. Rozycki03e6e502012-06-08 02:04:40 +010015979 env->CP0_Status |= (1 << CP0St_CU1);
Nathan Froyd91a75932009-12-11 09:29:20 -080015980 }
Petar Jovanovic6f0af302013-01-23 03:57:02 +010015981 if (env->CP0_Config3 & (1 << CP0C3_DSPP)) {
15982 env->CP0_Status |= (1 << CP0St_MX);
Jia Liu853c3242012-10-24 22:17:02 +080015983 }
aurel32932e71c2009-01-12 21:33:13 +000015984#else
15985 if (env->hflags & MIPS_HFLAG_BMASK) {
15986 /* If the exception was raised from a delay slot,
15987 come back to the jump. */
15988 env->CP0_ErrorEPC = env->active_tc.PC - 4;
ths0eaef5a2008-07-23 16:14:22 +000015989 } else {
aurel32932e71c2009-01-12 21:33:13 +000015990 env->CP0_ErrorEPC = env->active_tc.PC;
ths0eaef5a2008-07-23 16:14:22 +000015991 }
aurel32932e71c2009-01-12 21:33:13 +000015992 env->active_tc.PC = (int32_t)0xBFC00000;
Blue Swirl51cc2e72009-11-08 12:50:21 +020015993 env->CP0_Random = env->tlb->nb_tlb - 1;
15994 env->tlb->tlb_in_use = env->tlb->nb_tlb;
aurel32932e71c2009-01-12 21:33:13 +000015995 env->CP0_Wired = 0;
Andreas Färber55e5c282012-12-17 06:18:02 +010015996 env->CP0_EBase = 0x80000000 | (cs->cpu_index & 0x3FF);
aurel32932e71c2009-01-12 21:33:13 +000015997 env->CP0_Status = (1 << CP0St_BEV) | (1 << CP0St_ERL);
15998 /* vectored interrupts not implemented, timer on int 7,
15999 no performance counters. */
16000 env->CP0_IntCtl = 0xe0000000;
16001 {
16002 int i;
16003
16004 for (i = 0; i < 7; i++) {
16005 env->CP0_WatchLo[i] = 0;
16006 env->CP0_WatchHi[i] = 0x80000000;
16007 }
16008 env->CP0_WatchLo[7] = 0;
16009 env->CP0_WatchHi[7] = 0;
16010 }
16011 /* Count register increments in debug mode, EJTAG version 1 */
16012 env->CP0_Debug = (1 << CP0DB_CNT) | (0x1 << CP0DB_VER);
Edgar E. Iglesias9e56e752011-08-29 23:07:39 +020016013
16014 if (env->CP0_Config3 & (1 << CP0C3_MT)) {
16015 int i;
16016
16017 /* Only TC0 on VPE 0 starts as active. */
16018 for (i = 0; i < ARRAY_SIZE(env->tcs); i++) {
Andreas Färber55e5c282012-12-17 06:18:02 +010016019 env->tcs[i].CP0_TCBind = cs->cpu_index << CP0TCBd_CurVPE;
Edgar E. Iglesias9e56e752011-08-29 23:07:39 +020016020 env->tcs[i].CP0_TCHalt = 1;
16021 }
16022 env->active_tc.CP0_TCHalt = 1;
16023 env->halted = 1;
16024
Andreas Färber55e5c282012-12-17 06:18:02 +010016025 if (cs->cpu_index == 0) {
Edgar E. Iglesias9e56e752011-08-29 23:07:39 +020016026 /* VPE0 starts up enabled. */
16027 env->mvp->CP0_MVPControl |= (1 << CP0MVPCo_EVP);
16028 env->CP0_VPEConf0 |= (1 << CP0VPEC0_MVP) | (1 << CP0VPEC0_VPA);
16029
16030 /* TC0 starts up unhalted. */
16031 env->halted = 0;
16032 env->active_tc.CP0_TCHalt = 0;
16033 env->tcs[0].CP0_TCHalt = 0;
16034 /* With thread 0 active. */
16035 env->active_tc.CP0_TCStatus = (1 << CP0TCSt_A);
16036 env->tcs[0].CP0_TCStatus = (1 << CP0TCSt_A);
16037 }
16038 }
aurel32932e71c2009-01-12 21:33:13 +000016039#endif
Maciej W. Rozycki03e6e502012-06-08 02:04:40 +010016040 compute_hflags(env);
ths0eaef5a2008-07-23 16:14:22 +000016041 env->exception_index = EXCP_NONE;
bellard6af0bf92005-07-02 14:58:51 +000016042}
aurel32d2856f12008-04-28 00:32:32 +000016043
Andreas Färber7db13fa2012-03-14 01:38:22 +010016044void restore_state_to_opc(CPUMIPSState *env, TranslationBlock *tb, int pc_pos)
aurel32d2856f12008-04-28 00:32:32 +000016045{
Evgeny Voevodin25983ca2012-11-21 11:43:04 +040016046 env->active_tc.PC = tcg_ctx.gen_opc_pc[pc_pos];
aurel32d2856f12008-04-28 00:32:32 +000016047 env->hflags &= ~MIPS_HFLAG_BMASK;
16048 env->hflags |= gen_opc_hflags[pc_pos];
Aurelien Jarno46364012012-10-28 15:42:55 +010016049 switch (env->hflags & MIPS_HFLAG_BMASK_BASE) {
16050 case MIPS_HFLAG_BR:
16051 break;
16052 case MIPS_HFLAG_BC:
16053 case MIPS_HFLAG_BL:
16054 case MIPS_HFLAG_B:
16055 env->btarget = gen_opc_btarget[pc_pos];
16056 break;
16057 }
aurel32d2856f12008-04-28 00:32:32 +000016058}