blob: f10a533e80b74b56bf3bb0044754a3bc239cbbbf [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 {
Richard Hendersonce1dd5d2013-02-19 23:52:10 -08002718 TCGv_i32 t2 = tcg_temp_new_i32();
2719 TCGv_i32 t3 = tcg_temp_new_i32();
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
Richard Hendersonce1dd5d2013-02-19 23:52:10 -08002725 tcg_gen_trunc_tl_i32(t2, t0);
2726 tcg_gen_trunc_tl_i32(t3, t1);
2727 tcg_gen_muls2_i32(t2, t3, t2, t3);
2728 tcg_gen_ext_i32_tl(cpu_LO[acc], t2);
2729 tcg_gen_ext_i32_tl(cpu_HI[acc], t3);
2730 tcg_temp_free_i32(t2);
2731 tcg_temp_free_i32(t3);
ths214c4652008-06-12 12:43:29 +00002732 }
bellard6af0bf92005-07-02 14:58:51 +00002733 opn = "mult";
2734 break;
2735 case OPC_MULTU:
ths214c4652008-06-12 12:43:29 +00002736 {
Richard Hendersonce1dd5d2013-02-19 23:52:10 -08002737 TCGv_i32 t2 = tcg_temp_new_i32();
2738 TCGv_i32 t3 = tcg_temp_new_i32();
Jia Liu41334982012-10-24 22:17:03 +08002739 acc = ((ctx->opcode) >> 11) & 0x03;
2740 if (acc != 0) {
2741 check_dsp(ctx);
2742 }
ths214c4652008-06-12 12:43:29 +00002743
Richard Hendersonce1dd5d2013-02-19 23:52:10 -08002744 tcg_gen_trunc_tl_i32(t2, t0);
2745 tcg_gen_trunc_tl_i32(t3, t1);
2746 tcg_gen_mulu2_i32(t2, t3, t2, t3);
2747 tcg_gen_ext_i32_tl(cpu_LO[acc], t2);
2748 tcg_gen_ext_i32_tl(cpu_HI[acc], t3);
2749 tcg_temp_free_i32(t2);
2750 tcg_temp_free_i32(t3);
ths214c4652008-06-12 12:43:29 +00002751 }
bellard6af0bf92005-07-02 14:58:51 +00002752 opn = "multu";
2753 break;
thsd26bc212007-11-08 18:05:37 +00002754#if defined(TARGET_MIPS64)
ths7a387ff2006-12-06 20:17:30 +00002755 case OPC_DDIV:
ths48d38ca2008-05-18 22:50:49 +00002756 {
Aurelien Jarno51127182012-10-09 21:53:21 +02002757 TCGv t2 = tcg_temp_new();
2758 TCGv t3 = tcg_temp_new();
2759 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, -1LL << 63);
2760 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1LL);
2761 tcg_gen_and_tl(t2, t2, t3);
2762 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
2763 tcg_gen_or_tl(t2, t2, t3);
2764 tcg_gen_movi_tl(t3, 0);
2765 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
2766 tcg_gen_div_tl(cpu_LO[0], t0, t1);
2767 tcg_gen_rem_tl(cpu_HI[0], t0, t1);
2768 tcg_temp_free(t3);
2769 tcg_temp_free(t2);
ths48d38ca2008-05-18 22:50:49 +00002770 }
ths7a387ff2006-12-06 20:17:30 +00002771 opn = "ddiv";
2772 break;
2773 case OPC_DDIVU:
ths48d38ca2008-05-18 22:50:49 +00002774 {
Aurelien Jarno51127182012-10-09 21:53:21 +02002775 TCGv t2 = tcg_const_tl(0);
2776 TCGv t3 = tcg_const_tl(1);
2777 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
aurel32b10fa3c2008-11-11 11:50:25 +00002778 tcg_gen_divu_i64(cpu_LO[0], t0, t1);
2779 tcg_gen_remu_i64(cpu_HI[0], t0, t1);
Aurelien Jarno51127182012-10-09 21:53:21 +02002780 tcg_temp_free(t3);
2781 tcg_temp_free(t2);
ths48d38ca2008-05-18 22:50:49 +00002782 }
ths7a387ff2006-12-06 20:17:30 +00002783 opn = "ddivu";
2784 break;
2785 case OPC_DMULT:
Richard Hendersonce1dd5d2013-02-19 23:52:10 -08002786 tcg_gen_muls2_i64(cpu_LO[0], cpu_HI[0], t0, t1);
ths7a387ff2006-12-06 20:17:30 +00002787 opn = "dmult";
2788 break;
2789 case OPC_DMULTU:
Richard Hendersonce1dd5d2013-02-19 23:52:10 -08002790 tcg_gen_mulu2_i64(cpu_LO[0], cpu_HI[0], t0, t1);
ths7a387ff2006-12-06 20:17:30 +00002791 opn = "dmultu";
2792 break;
2793#endif
bellard6af0bf92005-07-02 14:58:51 +00002794 case OPC_MADD:
ths214c4652008-06-12 12:43:29 +00002795 {
aurel32d45f89f2009-03-29 01:19:31 +00002796 TCGv_i64 t2 = tcg_temp_new_i64();
2797 TCGv_i64 t3 = tcg_temp_new_i64();
Jia Liu41334982012-10-24 22:17:03 +08002798 acc = ((ctx->opcode) >> 11) & 0x03;
2799 if (acc != 0) {
2800 check_dsp(ctx);
2801 }
ths214c4652008-06-12 12:43:29 +00002802
aurel32d45f89f2009-03-29 01:19:31 +00002803 tcg_gen_ext_tl_i64(t2, t0);
2804 tcg_gen_ext_tl_i64(t3, t1);
2805 tcg_gen_mul_i64(t2, t2, t3);
Jia Liu41334982012-10-24 22:17:03 +08002806 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
aurel32d45f89f2009-03-29 01:19:31 +00002807 tcg_gen_add_i64(t2, t2, t3);
2808 tcg_temp_free_i64(t3);
2809 tcg_gen_trunc_i64_tl(t0, t2);
2810 tcg_gen_shri_i64(t2, t2, 32);
2811 tcg_gen_trunc_i64_tl(t1, t2);
2812 tcg_temp_free_i64(t2);
Jia Liu41334982012-10-24 22:17:03 +08002813 tcg_gen_ext32s_tl(cpu_LO[acc], t0);
2814 tcg_gen_ext32s_tl(cpu_HI[acc], t1);
ths214c4652008-06-12 12:43:29 +00002815 }
bellard6af0bf92005-07-02 14:58:51 +00002816 opn = "madd";
2817 break;
2818 case OPC_MADDU:
Jia Liu41334982012-10-24 22:17:03 +08002819 {
aurel32d45f89f2009-03-29 01:19:31 +00002820 TCGv_i64 t2 = tcg_temp_new_i64();
2821 TCGv_i64 t3 = tcg_temp_new_i64();
Jia Liu41334982012-10-24 22:17:03 +08002822 acc = ((ctx->opcode) >> 11) & 0x03;
2823 if (acc != 0) {
2824 check_dsp(ctx);
2825 }
ths214c4652008-06-12 12:43:29 +00002826
ths78723682008-06-24 20:12:33 +00002827 tcg_gen_ext32u_tl(t0, t0);
2828 tcg_gen_ext32u_tl(t1, t1);
aurel32d45f89f2009-03-29 01:19:31 +00002829 tcg_gen_extu_tl_i64(t2, t0);
2830 tcg_gen_extu_tl_i64(t3, t1);
2831 tcg_gen_mul_i64(t2, t2, t3);
Jia Liu41334982012-10-24 22:17:03 +08002832 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
aurel32d45f89f2009-03-29 01:19:31 +00002833 tcg_gen_add_i64(t2, t2, t3);
2834 tcg_temp_free_i64(t3);
2835 tcg_gen_trunc_i64_tl(t0, t2);
2836 tcg_gen_shri_i64(t2, t2, 32);
2837 tcg_gen_trunc_i64_tl(t1, t2);
2838 tcg_temp_free_i64(t2);
Jia Liu41334982012-10-24 22:17:03 +08002839 tcg_gen_ext32s_tl(cpu_LO[acc], t0);
2840 tcg_gen_ext32s_tl(cpu_HI[acc], t1);
ths214c4652008-06-12 12:43:29 +00002841 }
bellard6af0bf92005-07-02 14:58:51 +00002842 opn = "maddu";
2843 break;
2844 case OPC_MSUB:
ths214c4652008-06-12 12:43:29 +00002845 {
aurel32d45f89f2009-03-29 01:19:31 +00002846 TCGv_i64 t2 = tcg_temp_new_i64();
2847 TCGv_i64 t3 = tcg_temp_new_i64();
Jia Liu41334982012-10-24 22:17:03 +08002848 acc = ((ctx->opcode) >> 11) & 0x03;
2849 if (acc != 0) {
2850 check_dsp(ctx);
2851 }
ths214c4652008-06-12 12:43:29 +00002852
aurel32d45f89f2009-03-29 01:19:31 +00002853 tcg_gen_ext_tl_i64(t2, t0);
2854 tcg_gen_ext_tl_i64(t3, t1);
2855 tcg_gen_mul_i64(t2, t2, t3);
Jia Liu41334982012-10-24 22:17:03 +08002856 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
Nathan Froyd98070ce2009-07-01 10:52:22 -07002857 tcg_gen_sub_i64(t2, t3, t2);
aurel32d45f89f2009-03-29 01:19:31 +00002858 tcg_temp_free_i64(t3);
2859 tcg_gen_trunc_i64_tl(t0, t2);
2860 tcg_gen_shri_i64(t2, t2, 32);
2861 tcg_gen_trunc_i64_tl(t1, t2);
2862 tcg_temp_free_i64(t2);
Jia Liu41334982012-10-24 22:17:03 +08002863 tcg_gen_ext32s_tl(cpu_LO[acc], t0);
2864 tcg_gen_ext32s_tl(cpu_HI[acc], t1);
ths214c4652008-06-12 12:43:29 +00002865 }
bellard6af0bf92005-07-02 14:58:51 +00002866 opn = "msub";
2867 break;
2868 case OPC_MSUBU:
ths214c4652008-06-12 12:43:29 +00002869 {
aurel32d45f89f2009-03-29 01:19:31 +00002870 TCGv_i64 t2 = tcg_temp_new_i64();
2871 TCGv_i64 t3 = tcg_temp_new_i64();
Jia Liu41334982012-10-24 22:17:03 +08002872 acc = ((ctx->opcode) >> 11) & 0x03;
2873 if (acc != 0) {
2874 check_dsp(ctx);
2875 }
ths214c4652008-06-12 12:43:29 +00002876
ths78723682008-06-24 20:12:33 +00002877 tcg_gen_ext32u_tl(t0, t0);
2878 tcg_gen_ext32u_tl(t1, t1);
aurel32d45f89f2009-03-29 01:19:31 +00002879 tcg_gen_extu_tl_i64(t2, t0);
2880 tcg_gen_extu_tl_i64(t3, t1);
2881 tcg_gen_mul_i64(t2, t2, t3);
Jia Liu41334982012-10-24 22:17:03 +08002882 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
Nathan Froyd98070ce2009-07-01 10:52:22 -07002883 tcg_gen_sub_i64(t2, t3, t2);
aurel32d45f89f2009-03-29 01:19:31 +00002884 tcg_temp_free_i64(t3);
2885 tcg_gen_trunc_i64_tl(t0, t2);
2886 tcg_gen_shri_i64(t2, t2, 32);
2887 tcg_gen_trunc_i64_tl(t1, t2);
2888 tcg_temp_free_i64(t2);
Jia Liu41334982012-10-24 22:17:03 +08002889 tcg_gen_ext32s_tl(cpu_LO[acc], t0);
2890 tcg_gen_ext32s_tl(cpu_HI[acc], t1);
ths214c4652008-06-12 12:43:29 +00002891 }
bellard6af0bf92005-07-02 14:58:51 +00002892 opn = "msubu";
2893 break;
2894 default:
ths923617a2007-05-11 00:16:06 +00002895 MIPS_INVAL(opn);
bellard6af0bf92005-07-02 14:58:51 +00002896 generate_exception(ctx, EXCP_RI);
ths78723682008-06-24 20:12:33 +00002897 goto out;
bellard6af0bf92005-07-02 14:58:51 +00002898 }
Blue Swirl2abf3142010-10-13 18:38:08 +00002899 (void)opn; /* avoid a compiler warning */
bellard6af0bf92005-07-02 14:58:51 +00002900 MIPS_DEBUG("%s %s %s", opn, regnames[rs], regnames[rt]);
ths78723682008-06-24 20:12:33 +00002901 out:
2902 tcg_temp_free(t0);
2903 tcg_temp_free(t1);
bellard6af0bf92005-07-02 14:58:51 +00002904}
2905
thse9c71dd2007-12-25 20:46:56 +00002906static void gen_mul_vr54xx (DisasContext *ctx, uint32_t opc,
2907 int rd, int rs, int rt)
2908{
2909 const char *opn = "mul vr54xx";
aurel32f157bfe2009-03-29 01:18:24 +00002910 TCGv t0 = tcg_temp_new();
2911 TCGv t1 = tcg_temp_new();
thse9c71dd2007-12-25 20:46:56 +00002912
ths6c5c1e22008-06-24 15:12:27 +00002913 gen_load_gpr(t0, rs);
2914 gen_load_gpr(t1, rt);
thse9c71dd2007-12-25 20:46:56 +00002915
2916 switch (opc) {
2917 case OPC_VR54XX_MULS:
Blue Swirl895c2d02012-09-02 14:52:59 +00002918 gen_helper_muls(t0, cpu_env, t0, t1);
thse9c71dd2007-12-25 20:46:56 +00002919 opn = "muls";
aurel3269585492009-01-14 19:40:36 +00002920 break;
thse9c71dd2007-12-25 20:46:56 +00002921 case OPC_VR54XX_MULSU:
Blue Swirl895c2d02012-09-02 14:52:59 +00002922 gen_helper_mulsu(t0, cpu_env, t0, t1);
thse9c71dd2007-12-25 20:46:56 +00002923 opn = "mulsu";
aurel3269585492009-01-14 19:40:36 +00002924 break;
thse9c71dd2007-12-25 20:46:56 +00002925 case OPC_VR54XX_MACC:
Blue Swirl895c2d02012-09-02 14:52:59 +00002926 gen_helper_macc(t0, cpu_env, t0, t1);
thse9c71dd2007-12-25 20:46:56 +00002927 opn = "macc";
aurel3269585492009-01-14 19:40:36 +00002928 break;
thse9c71dd2007-12-25 20:46:56 +00002929 case OPC_VR54XX_MACCU:
Blue Swirl895c2d02012-09-02 14:52:59 +00002930 gen_helper_maccu(t0, cpu_env, t0, t1);
thse9c71dd2007-12-25 20:46:56 +00002931 opn = "maccu";
aurel3269585492009-01-14 19:40:36 +00002932 break;
thse9c71dd2007-12-25 20:46:56 +00002933 case OPC_VR54XX_MSAC:
Blue Swirl895c2d02012-09-02 14:52:59 +00002934 gen_helper_msac(t0, cpu_env, t0, t1);
thse9c71dd2007-12-25 20:46:56 +00002935 opn = "msac";
aurel3269585492009-01-14 19:40:36 +00002936 break;
thse9c71dd2007-12-25 20:46:56 +00002937 case OPC_VR54XX_MSACU:
Blue Swirl895c2d02012-09-02 14:52:59 +00002938 gen_helper_msacu(t0, cpu_env, t0, t1);
thse9c71dd2007-12-25 20:46:56 +00002939 opn = "msacu";
aurel3269585492009-01-14 19:40:36 +00002940 break;
thse9c71dd2007-12-25 20:46:56 +00002941 case OPC_VR54XX_MULHI:
Blue Swirl895c2d02012-09-02 14:52:59 +00002942 gen_helper_mulhi(t0, cpu_env, t0, t1);
thse9c71dd2007-12-25 20:46:56 +00002943 opn = "mulhi";
aurel3269585492009-01-14 19:40:36 +00002944 break;
thse9c71dd2007-12-25 20:46:56 +00002945 case OPC_VR54XX_MULHIU:
Blue Swirl895c2d02012-09-02 14:52:59 +00002946 gen_helper_mulhiu(t0, cpu_env, t0, t1);
thse9c71dd2007-12-25 20:46:56 +00002947 opn = "mulhiu";
aurel3269585492009-01-14 19:40:36 +00002948 break;
thse9c71dd2007-12-25 20:46:56 +00002949 case OPC_VR54XX_MULSHI:
Blue Swirl895c2d02012-09-02 14:52:59 +00002950 gen_helper_mulshi(t0, cpu_env, t0, t1);
thse9c71dd2007-12-25 20:46:56 +00002951 opn = "mulshi";
aurel3269585492009-01-14 19:40:36 +00002952 break;
thse9c71dd2007-12-25 20:46:56 +00002953 case OPC_VR54XX_MULSHIU:
Blue Swirl895c2d02012-09-02 14:52:59 +00002954 gen_helper_mulshiu(t0, cpu_env, t0, t1);
thse9c71dd2007-12-25 20:46:56 +00002955 opn = "mulshiu";
aurel3269585492009-01-14 19:40:36 +00002956 break;
thse9c71dd2007-12-25 20:46:56 +00002957 case OPC_VR54XX_MACCHI:
Blue Swirl895c2d02012-09-02 14:52:59 +00002958 gen_helper_macchi(t0, cpu_env, t0, t1);
thse9c71dd2007-12-25 20:46:56 +00002959 opn = "macchi";
aurel3269585492009-01-14 19:40:36 +00002960 break;
thse9c71dd2007-12-25 20:46:56 +00002961 case OPC_VR54XX_MACCHIU:
Blue Swirl895c2d02012-09-02 14:52:59 +00002962 gen_helper_macchiu(t0, cpu_env, t0, t1);
thse9c71dd2007-12-25 20:46:56 +00002963 opn = "macchiu";
aurel3269585492009-01-14 19:40:36 +00002964 break;
thse9c71dd2007-12-25 20:46:56 +00002965 case OPC_VR54XX_MSACHI:
Blue Swirl895c2d02012-09-02 14:52:59 +00002966 gen_helper_msachi(t0, cpu_env, t0, t1);
thse9c71dd2007-12-25 20:46:56 +00002967 opn = "msachi";
aurel3269585492009-01-14 19:40:36 +00002968 break;
thse9c71dd2007-12-25 20:46:56 +00002969 case OPC_VR54XX_MSACHIU:
Blue Swirl895c2d02012-09-02 14:52:59 +00002970 gen_helper_msachiu(t0, cpu_env, t0, t1);
thse9c71dd2007-12-25 20:46:56 +00002971 opn = "msachiu";
aurel3269585492009-01-14 19:40:36 +00002972 break;
thse9c71dd2007-12-25 20:46:56 +00002973 default:
2974 MIPS_INVAL("mul vr54xx");
2975 generate_exception(ctx, EXCP_RI);
ths6c5c1e22008-06-24 15:12:27 +00002976 goto out;
thse9c71dd2007-12-25 20:46:56 +00002977 }
ths6c5c1e22008-06-24 15:12:27 +00002978 gen_store_gpr(t0, rd);
Blue Swirl2abf3142010-10-13 18:38:08 +00002979 (void)opn; /* avoid a compiler warning */
thse9c71dd2007-12-25 20:46:56 +00002980 MIPS_DEBUG("%s %s, %s, %s", opn, regnames[rd], regnames[rs], regnames[rt]);
ths6c5c1e22008-06-24 15:12:27 +00002981
2982 out:
2983 tcg_temp_free(t0);
2984 tcg_temp_free(t1);
thse9c71dd2007-12-25 20:46:56 +00002985}
2986
ths7a387ff2006-12-06 20:17:30 +00002987static void gen_cl (DisasContext *ctx, uint32_t opc,
bellard6af0bf92005-07-02 14:58:51 +00002988 int rd, int rs)
2989{
ths923617a2007-05-11 00:16:06 +00002990 const char *opn = "CLx";
aurel3220e1fb522009-03-29 01:18:16 +00002991 TCGv t0;
ths6c5c1e22008-06-24 15:12:27 +00002992
bellard6af0bf92005-07-02 14:58:51 +00002993 if (rd == 0) {
thsead93602007-09-06 00:18:15 +00002994 /* Treat as NOP. */
bellard6af0bf92005-07-02 14:58:51 +00002995 MIPS_DEBUG("NOP");
aurel3220e1fb522009-03-29 01:18:16 +00002996 return;
bellard6af0bf92005-07-02 14:58:51 +00002997 }
aurel3220e1fb522009-03-29 01:18:16 +00002998 t0 = tcg_temp_new();
ths6c5c1e22008-06-24 15:12:27 +00002999 gen_load_gpr(t0, rs);
bellard6af0bf92005-07-02 14:58:51 +00003000 switch (opc) {
3001 case OPC_CLO:
aurel3220e1fb522009-03-29 01:18:16 +00003002 gen_helper_clo(cpu_gpr[rd], t0);
bellard6af0bf92005-07-02 14:58:51 +00003003 opn = "clo";
3004 break;
3005 case OPC_CLZ:
aurel3220e1fb522009-03-29 01:18:16 +00003006 gen_helper_clz(cpu_gpr[rd], t0);
bellard6af0bf92005-07-02 14:58:51 +00003007 opn = "clz";
3008 break;
thsd26bc212007-11-08 18:05:37 +00003009#if defined(TARGET_MIPS64)
ths7a387ff2006-12-06 20:17:30 +00003010 case OPC_DCLO:
aurel3220e1fb522009-03-29 01:18:16 +00003011 gen_helper_dclo(cpu_gpr[rd], t0);
ths7a387ff2006-12-06 20:17:30 +00003012 opn = "dclo";
3013 break;
3014 case OPC_DCLZ:
aurel3220e1fb522009-03-29 01:18:16 +00003015 gen_helper_dclz(cpu_gpr[rd], t0);
ths7a387ff2006-12-06 20:17:30 +00003016 opn = "dclz";
3017 break;
3018#endif
bellard6af0bf92005-07-02 14:58:51 +00003019 }
Blue Swirl2abf3142010-10-13 18:38:08 +00003020 (void)opn; /* avoid a compiler warning */
bellard6af0bf92005-07-02 14:58:51 +00003021 MIPS_DEBUG("%s %s, %s", opn, regnames[rd], regnames[rs]);
ths6c5c1e22008-06-24 15:12:27 +00003022 tcg_temp_free(t0);
bellard6af0bf92005-07-02 14:58:51 +00003023}
3024
Aurelien Jarno161f85e2010-06-18 19:32:43 +02003025/* Godson integer instructions */
Richard Hendersonbd277fa2012-09-18 21:59:44 -07003026static void gen_loongson_integer(DisasContext *ctx, uint32_t opc,
3027 int rd, int rs, int rt)
Aurelien Jarno161f85e2010-06-18 19:32:43 +02003028{
3029 const char *opn = "loongson";
3030 TCGv t0, t1;
3031
3032 if (rd == 0) {
3033 /* Treat as NOP. */
3034 MIPS_DEBUG("NOP");
3035 return;
3036 }
3037
3038 switch (opc) {
3039 case OPC_MULT_G_2E:
3040 case OPC_MULT_G_2F:
3041 case OPC_MULTU_G_2E:
3042 case OPC_MULTU_G_2F:
3043#if defined(TARGET_MIPS64)
3044 case OPC_DMULT_G_2E:
3045 case OPC_DMULT_G_2F:
3046 case OPC_DMULTU_G_2E:
3047 case OPC_DMULTU_G_2F:
3048#endif
3049 t0 = tcg_temp_new();
3050 t1 = tcg_temp_new();
3051 break;
3052 default:
3053 t0 = tcg_temp_local_new();
3054 t1 = tcg_temp_local_new();
3055 break;
3056 }
3057
3058 gen_load_gpr(t0, rs);
3059 gen_load_gpr(t1, rt);
3060
3061 switch (opc) {
3062 case OPC_MULT_G_2E:
3063 case OPC_MULT_G_2F:
3064 tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
3065 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3066 opn = "mult.g";
3067 break;
3068 case OPC_MULTU_G_2E:
3069 case OPC_MULTU_G_2F:
3070 tcg_gen_ext32u_tl(t0, t0);
3071 tcg_gen_ext32u_tl(t1, t1);
3072 tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
3073 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3074 opn = "multu.g";
3075 break;
3076 case OPC_DIV_G_2E:
3077 case OPC_DIV_G_2F:
3078 {
3079 int l1 = gen_new_label();
3080 int l2 = gen_new_label();
3081 int l3 = gen_new_label();
3082 tcg_gen_ext32s_tl(t0, t0);
3083 tcg_gen_ext32s_tl(t1, t1);
3084 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
3085 tcg_gen_movi_tl(cpu_gpr[rd], 0);
3086 tcg_gen_br(l3);
3087 gen_set_label(l1);
3088 tcg_gen_brcondi_tl(TCG_COND_NE, t0, INT_MIN, l2);
3089 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1, l2);
3090 tcg_gen_mov_tl(cpu_gpr[rd], t0);
3091 tcg_gen_br(l3);
3092 gen_set_label(l2);
3093 tcg_gen_div_tl(cpu_gpr[rd], t0, t1);
3094 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3095 gen_set_label(l3);
3096 }
3097 opn = "div.g";
3098 break;
3099 case OPC_DIVU_G_2E:
3100 case OPC_DIVU_G_2F:
3101 {
3102 int l1 = gen_new_label();
3103 int l2 = gen_new_label();
3104 tcg_gen_ext32u_tl(t0, t0);
3105 tcg_gen_ext32u_tl(t1, t1);
3106 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
3107 tcg_gen_movi_tl(cpu_gpr[rd], 0);
3108 tcg_gen_br(l2);
3109 gen_set_label(l1);
3110 tcg_gen_divu_tl(cpu_gpr[rd], t0, t1);
3111 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3112 gen_set_label(l2);
3113 }
3114 opn = "divu.g";
3115 break;
3116 case OPC_MOD_G_2E:
3117 case OPC_MOD_G_2F:
3118 {
3119 int l1 = gen_new_label();
3120 int l2 = gen_new_label();
3121 int l3 = gen_new_label();
3122 tcg_gen_ext32u_tl(t0, t0);
3123 tcg_gen_ext32u_tl(t1, t1);
3124 tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
3125 tcg_gen_brcondi_tl(TCG_COND_NE, t0, INT_MIN, l2);
3126 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1, l2);
3127 gen_set_label(l1);
3128 tcg_gen_movi_tl(cpu_gpr[rd], 0);
3129 tcg_gen_br(l3);
3130 gen_set_label(l2);
3131 tcg_gen_rem_tl(cpu_gpr[rd], t0, t1);
3132 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3133 gen_set_label(l3);
3134 }
3135 opn = "mod.g";
3136 break;
3137 case OPC_MODU_G_2E:
3138 case OPC_MODU_G_2F:
3139 {
3140 int l1 = gen_new_label();
3141 int l2 = gen_new_label();
3142 tcg_gen_ext32u_tl(t0, t0);
3143 tcg_gen_ext32u_tl(t1, t1);
3144 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
3145 tcg_gen_movi_tl(cpu_gpr[rd], 0);
3146 tcg_gen_br(l2);
3147 gen_set_label(l1);
3148 tcg_gen_remu_tl(cpu_gpr[rd], t0, t1);
3149 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3150 gen_set_label(l2);
3151 }
3152 opn = "modu.g";
3153 break;
3154#if defined(TARGET_MIPS64)
3155 case OPC_DMULT_G_2E:
3156 case OPC_DMULT_G_2F:
3157 tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
3158 opn = "dmult.g";
3159 break;
3160 case OPC_DMULTU_G_2E:
3161 case OPC_DMULTU_G_2F:
3162 tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
3163 opn = "dmultu.g";
3164 break;
3165 case OPC_DDIV_G_2E:
3166 case OPC_DDIV_G_2F:
3167 {
3168 int l1 = gen_new_label();
3169 int l2 = gen_new_label();
3170 int l3 = gen_new_label();
3171 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
3172 tcg_gen_movi_tl(cpu_gpr[rd], 0);
3173 tcg_gen_br(l3);
3174 gen_set_label(l1);
3175 tcg_gen_brcondi_tl(TCG_COND_NE, t0, -1LL << 63, l2);
3176 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1LL, l2);
3177 tcg_gen_mov_tl(cpu_gpr[rd], t0);
3178 tcg_gen_br(l3);
3179 gen_set_label(l2);
3180 tcg_gen_div_tl(cpu_gpr[rd], t0, t1);
3181 gen_set_label(l3);
3182 }
3183 opn = "ddiv.g";
3184 break;
3185 case OPC_DDIVU_G_2E:
3186 case OPC_DDIVU_G_2F:
3187 {
3188 int l1 = gen_new_label();
3189 int l2 = gen_new_label();
3190 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
3191 tcg_gen_movi_tl(cpu_gpr[rd], 0);
3192 tcg_gen_br(l2);
3193 gen_set_label(l1);
3194 tcg_gen_divu_tl(cpu_gpr[rd], t0, t1);
3195 gen_set_label(l2);
3196 }
3197 opn = "ddivu.g";
3198 break;
3199 case OPC_DMOD_G_2E:
3200 case OPC_DMOD_G_2F:
3201 {
3202 int l1 = gen_new_label();
3203 int l2 = gen_new_label();
3204 int l3 = gen_new_label();
3205 tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
3206 tcg_gen_brcondi_tl(TCG_COND_NE, t0, -1LL << 63, l2);
3207 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1LL, l2);
3208 gen_set_label(l1);
3209 tcg_gen_movi_tl(cpu_gpr[rd], 0);
3210 tcg_gen_br(l3);
3211 gen_set_label(l2);
3212 tcg_gen_rem_tl(cpu_gpr[rd], t0, t1);
3213 gen_set_label(l3);
3214 }
3215 opn = "dmod.g";
3216 break;
3217 case OPC_DMODU_G_2E:
3218 case OPC_DMODU_G_2F:
3219 {
3220 int l1 = gen_new_label();
3221 int l2 = gen_new_label();
3222 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
3223 tcg_gen_movi_tl(cpu_gpr[rd], 0);
3224 tcg_gen_br(l2);
3225 gen_set_label(l1);
3226 tcg_gen_remu_tl(cpu_gpr[rd], t0, t1);
3227 gen_set_label(l2);
3228 }
3229 opn = "dmodu.g";
3230 break;
3231#endif
3232 }
3233
Blue Swirl2abf3142010-10-13 18:38:08 +00003234 (void)opn; /* avoid a compiler warning */
Aurelien Jarno161f85e2010-06-18 19:32:43 +02003235 MIPS_DEBUG("%s %s, %s", opn, regnames[rd], regnames[rs]);
3236 tcg_temp_free(t0);
3237 tcg_temp_free(t1);
3238}
3239
Richard Hendersonbd277fa2012-09-18 21:59:44 -07003240/* Loongson multimedia instructions */
3241static void gen_loongson_multimedia(DisasContext *ctx, int rd, int rs, int rt)
3242{
3243 const char *opn = "loongson_cp2";
3244 uint32_t opc, shift_max;
3245 TCGv_i64 t0, t1;
3246
3247 opc = MASK_LMI(ctx->opcode);
3248 switch (opc) {
3249 case OPC_ADD_CP2:
3250 case OPC_SUB_CP2:
3251 case OPC_DADD_CP2:
3252 case OPC_DSUB_CP2:
3253 t0 = tcg_temp_local_new_i64();
3254 t1 = tcg_temp_local_new_i64();
3255 break;
3256 default:
3257 t0 = tcg_temp_new_i64();
3258 t1 = tcg_temp_new_i64();
3259 break;
3260 }
3261
3262 gen_load_fpr64(ctx, t0, rs);
3263 gen_load_fpr64(ctx, t1, rt);
3264
3265#define LMI_HELPER(UP, LO) \
3266 case OPC_##UP: gen_helper_##LO(t0, t0, t1); opn = #LO; break
3267#define LMI_HELPER_1(UP, LO) \
3268 case OPC_##UP: gen_helper_##LO(t0, t0); opn = #LO; break
3269#define LMI_DIRECT(UP, LO, OP) \
3270 case OPC_##UP: tcg_gen_##OP##_i64(t0, t0, t1); opn = #LO; break
3271
3272 switch (opc) {
3273 LMI_HELPER(PADDSH, paddsh);
3274 LMI_HELPER(PADDUSH, paddush);
3275 LMI_HELPER(PADDH, paddh);
3276 LMI_HELPER(PADDW, paddw);
3277 LMI_HELPER(PADDSB, paddsb);
3278 LMI_HELPER(PADDUSB, paddusb);
3279 LMI_HELPER(PADDB, paddb);
3280
3281 LMI_HELPER(PSUBSH, psubsh);
3282 LMI_HELPER(PSUBUSH, psubush);
3283 LMI_HELPER(PSUBH, psubh);
3284 LMI_HELPER(PSUBW, psubw);
3285 LMI_HELPER(PSUBSB, psubsb);
3286 LMI_HELPER(PSUBUSB, psubusb);
3287 LMI_HELPER(PSUBB, psubb);
3288
3289 LMI_HELPER(PSHUFH, pshufh);
3290 LMI_HELPER(PACKSSWH, packsswh);
3291 LMI_HELPER(PACKSSHB, packsshb);
3292 LMI_HELPER(PACKUSHB, packushb);
3293
3294 LMI_HELPER(PUNPCKLHW, punpcklhw);
3295 LMI_HELPER(PUNPCKHHW, punpckhhw);
3296 LMI_HELPER(PUNPCKLBH, punpcklbh);
3297 LMI_HELPER(PUNPCKHBH, punpckhbh);
3298 LMI_HELPER(PUNPCKLWD, punpcklwd);
3299 LMI_HELPER(PUNPCKHWD, punpckhwd);
3300
3301 LMI_HELPER(PAVGH, pavgh);
3302 LMI_HELPER(PAVGB, pavgb);
3303 LMI_HELPER(PMAXSH, pmaxsh);
3304 LMI_HELPER(PMINSH, pminsh);
3305 LMI_HELPER(PMAXUB, pmaxub);
3306 LMI_HELPER(PMINUB, pminub);
3307
3308 LMI_HELPER(PCMPEQW, pcmpeqw);
3309 LMI_HELPER(PCMPGTW, pcmpgtw);
3310 LMI_HELPER(PCMPEQH, pcmpeqh);
3311 LMI_HELPER(PCMPGTH, pcmpgth);
3312 LMI_HELPER(PCMPEQB, pcmpeqb);
3313 LMI_HELPER(PCMPGTB, pcmpgtb);
3314
3315 LMI_HELPER(PSLLW, psllw);
3316 LMI_HELPER(PSLLH, psllh);
3317 LMI_HELPER(PSRLW, psrlw);
3318 LMI_HELPER(PSRLH, psrlh);
3319 LMI_HELPER(PSRAW, psraw);
3320 LMI_HELPER(PSRAH, psrah);
3321
3322 LMI_HELPER(PMULLH, pmullh);
3323 LMI_HELPER(PMULHH, pmulhh);
3324 LMI_HELPER(PMULHUH, pmulhuh);
3325 LMI_HELPER(PMADDHW, pmaddhw);
3326
3327 LMI_HELPER(PASUBUB, pasubub);
3328 LMI_HELPER_1(BIADD, biadd);
3329 LMI_HELPER_1(PMOVMSKB, pmovmskb);
3330
3331 LMI_DIRECT(PADDD, paddd, add);
3332 LMI_DIRECT(PSUBD, psubd, sub);
3333 LMI_DIRECT(XOR_CP2, xor, xor);
3334 LMI_DIRECT(NOR_CP2, nor, nor);
3335 LMI_DIRECT(AND_CP2, and, and);
3336 LMI_DIRECT(PANDN, pandn, andc);
3337 LMI_DIRECT(OR, or, or);
3338
3339 case OPC_PINSRH_0:
3340 tcg_gen_deposit_i64(t0, t0, t1, 0, 16);
3341 opn = "pinsrh_0";
3342 break;
3343 case OPC_PINSRH_1:
3344 tcg_gen_deposit_i64(t0, t0, t1, 16, 16);
3345 opn = "pinsrh_1";
3346 break;
3347 case OPC_PINSRH_2:
3348 tcg_gen_deposit_i64(t0, t0, t1, 32, 16);
3349 opn = "pinsrh_2";
3350 break;
3351 case OPC_PINSRH_3:
3352 tcg_gen_deposit_i64(t0, t0, t1, 48, 16);
3353 opn = "pinsrh_3";
3354 break;
3355
3356 case OPC_PEXTRH:
3357 tcg_gen_andi_i64(t1, t1, 3);
3358 tcg_gen_shli_i64(t1, t1, 4);
3359 tcg_gen_shr_i64(t0, t0, t1);
3360 tcg_gen_ext16u_i64(t0, t0);
3361 opn = "pextrh";
3362 break;
3363
3364 case OPC_ADDU_CP2:
3365 tcg_gen_add_i64(t0, t0, t1);
3366 tcg_gen_ext32s_i64(t0, t0);
3367 opn = "addu";
3368 break;
3369 case OPC_SUBU_CP2:
3370 tcg_gen_sub_i64(t0, t0, t1);
3371 tcg_gen_ext32s_i64(t0, t0);
3372 opn = "addu";
3373 break;
3374
3375 case OPC_SLL_CP2:
3376 opn = "sll";
3377 shift_max = 32;
3378 goto do_shift;
3379 case OPC_SRL_CP2:
3380 opn = "srl";
3381 shift_max = 32;
3382 goto do_shift;
3383 case OPC_SRA_CP2:
3384 opn = "sra";
3385 shift_max = 32;
3386 goto do_shift;
3387 case OPC_DSLL_CP2:
3388 opn = "dsll";
3389 shift_max = 64;
3390 goto do_shift;
3391 case OPC_DSRL_CP2:
3392 opn = "dsrl";
3393 shift_max = 64;
3394 goto do_shift;
3395 case OPC_DSRA_CP2:
3396 opn = "dsra";
3397 shift_max = 64;
3398 goto do_shift;
3399 do_shift:
3400 /* Make sure shift count isn't TCG undefined behaviour. */
3401 tcg_gen_andi_i64(t1, t1, shift_max - 1);
3402
3403 switch (opc) {
3404 case OPC_SLL_CP2:
3405 case OPC_DSLL_CP2:
3406 tcg_gen_shl_i64(t0, t0, t1);
3407 break;
3408 case OPC_SRA_CP2:
3409 case OPC_DSRA_CP2:
3410 /* Since SRA is UndefinedResult without sign-extended inputs,
3411 we can treat SRA and DSRA the same. */
3412 tcg_gen_sar_i64(t0, t0, t1);
3413 break;
3414 case OPC_SRL_CP2:
3415 /* We want to shift in zeros for SRL; zero-extend first. */
3416 tcg_gen_ext32u_i64(t0, t0);
3417 /* FALLTHRU */
3418 case OPC_DSRL_CP2:
3419 tcg_gen_shr_i64(t0, t0, t1);
3420 break;
3421 }
3422
3423 if (shift_max == 32) {
3424 tcg_gen_ext32s_i64(t0, t0);
3425 }
3426
3427 /* Shifts larger than MAX produce zero. */
3428 tcg_gen_setcondi_i64(TCG_COND_LTU, t1, t1, shift_max);
3429 tcg_gen_neg_i64(t1, t1);
3430 tcg_gen_and_i64(t0, t0, t1);
3431 break;
3432
3433 case OPC_ADD_CP2:
3434 case OPC_DADD_CP2:
3435 {
3436 TCGv_i64 t2 = tcg_temp_new_i64();
3437 int lab = gen_new_label();
3438
3439 tcg_gen_mov_i64(t2, t0);
3440 tcg_gen_add_i64(t0, t1, t2);
3441 if (opc == OPC_ADD_CP2) {
3442 tcg_gen_ext32s_i64(t0, t0);
3443 }
3444 tcg_gen_xor_i64(t1, t1, t2);
3445 tcg_gen_xor_i64(t2, t2, t0);
3446 tcg_gen_andc_i64(t1, t2, t1);
3447 tcg_temp_free_i64(t2);
3448 tcg_gen_brcondi_i64(TCG_COND_GE, t1, 0, lab);
3449 generate_exception(ctx, EXCP_OVERFLOW);
3450 gen_set_label(lab);
3451
3452 opn = (opc == OPC_ADD_CP2 ? "add" : "dadd");
3453 break;
3454 }
3455
3456 case OPC_SUB_CP2:
3457 case OPC_DSUB_CP2:
3458 {
3459 TCGv_i64 t2 = tcg_temp_new_i64();
3460 int lab = gen_new_label();
3461
3462 tcg_gen_mov_i64(t2, t0);
3463 tcg_gen_sub_i64(t0, t1, t2);
3464 if (opc == OPC_SUB_CP2) {
3465 tcg_gen_ext32s_i64(t0, t0);
3466 }
3467 tcg_gen_xor_i64(t1, t1, t2);
3468 tcg_gen_xor_i64(t2, t2, t0);
3469 tcg_gen_and_i64(t1, t1, t2);
3470 tcg_temp_free_i64(t2);
3471 tcg_gen_brcondi_i64(TCG_COND_GE, t1, 0, lab);
3472 generate_exception(ctx, EXCP_OVERFLOW);
3473 gen_set_label(lab);
3474
3475 opn = (opc == OPC_SUB_CP2 ? "sub" : "dsub");
3476 break;
3477 }
3478
3479 case OPC_PMULUW:
3480 tcg_gen_ext32u_i64(t0, t0);
3481 tcg_gen_ext32u_i64(t1, t1);
3482 tcg_gen_mul_i64(t0, t0, t1);
3483 opn = "pmuluw";
3484 break;
3485
3486 case OPC_SEQU_CP2:
3487 case OPC_SEQ_CP2:
3488 case OPC_SLTU_CP2:
3489 case OPC_SLT_CP2:
3490 case OPC_SLEU_CP2:
3491 case OPC_SLE_CP2:
3492 /* ??? Document is unclear: Set FCC[CC]. Does that mean the
3493 FD field is the CC field? */
3494 default:
3495 MIPS_INVAL(opn);
3496 generate_exception(ctx, EXCP_RI);
3497 return;
3498 }
3499
3500#undef LMI_HELPER
3501#undef LMI_DIRECT
3502
3503 gen_store_fpr64(ctx, t0, rd);
3504
3505 (void)opn; /* avoid a compiler warning */
3506 MIPS_DEBUG("%s %s, %s, %s", opn,
3507 fregnames[rd], fregnames[rs], fregnames[rt]);
3508 tcg_temp_free_i64(t0);
3509 tcg_temp_free_i64(t1);
3510}
3511
bellard6af0bf92005-07-02 14:58:51 +00003512/* Traps */
ths7a387ff2006-12-06 20:17:30 +00003513static void gen_trap (DisasContext *ctx, uint32_t opc,
bellard6af0bf92005-07-02 14:58:51 +00003514 int rs, int rt, int16_t imm)
3515{
3516 int cond;
aurel32cdc0faa2009-03-29 01:19:02 +00003517 TCGv t0 = tcg_temp_new();
aurel321ba74fb2009-03-29 01:18:52 +00003518 TCGv t1 = tcg_temp_new();
bellard6af0bf92005-07-02 14:58:51 +00003519
3520 cond = 0;
3521 /* Load needed operands */
3522 switch (opc) {
3523 case OPC_TEQ:
3524 case OPC_TGE:
3525 case OPC_TGEU:
3526 case OPC_TLT:
3527 case OPC_TLTU:
3528 case OPC_TNE:
3529 /* Compare two registers */
3530 if (rs != rt) {
thsbe24bb42008-06-23 12:57:09 +00003531 gen_load_gpr(t0, rs);
3532 gen_load_gpr(t1, rt);
bellard6af0bf92005-07-02 14:58:51 +00003533 cond = 1;
3534 }
ths179e32b2006-12-16 16:45:18 +00003535 break;
bellard6af0bf92005-07-02 14:58:51 +00003536 case OPC_TEQI:
3537 case OPC_TGEI:
3538 case OPC_TGEIU:
3539 case OPC_TLTI:
3540 case OPC_TLTIU:
3541 case OPC_TNEI:
3542 /* Compare register to immediate */
3543 if (rs != 0 || imm != 0) {
thsbe24bb42008-06-23 12:57:09 +00003544 gen_load_gpr(t0, rs);
3545 tcg_gen_movi_tl(t1, (int32_t)imm);
bellard6af0bf92005-07-02 14:58:51 +00003546 cond = 1;
3547 }
3548 break;
3549 }
3550 if (cond == 0) {
3551 switch (opc) {
3552 case OPC_TEQ: /* rs == rs */
3553 case OPC_TEQI: /* r0 == 0 */
3554 case OPC_TGE: /* rs >= rs */
3555 case OPC_TGEI: /* r0 >= 0 */
3556 case OPC_TGEU: /* rs >= rs unsigned */
3557 case OPC_TGEIU: /* r0 >= 0 unsigned */
3558 /* Always trap */
aurel32cdc0faa2009-03-29 01:19:02 +00003559 generate_exception(ctx, EXCP_TRAP);
bellard6af0bf92005-07-02 14:58:51 +00003560 break;
3561 case OPC_TLT: /* rs < rs */
3562 case OPC_TLTI: /* r0 < 0 */
3563 case OPC_TLTU: /* rs < rs unsigned */
3564 case OPC_TLTIU: /* r0 < 0 unsigned */
3565 case OPC_TNE: /* rs != rs */
3566 case OPC_TNEI: /* r0 != 0 */
thsead93602007-09-06 00:18:15 +00003567 /* Never trap: treat as NOP. */
aurel32cdc0faa2009-03-29 01:19:02 +00003568 break;
bellard6af0bf92005-07-02 14:58:51 +00003569 }
3570 } else {
aurel32cdc0faa2009-03-29 01:19:02 +00003571 int l1 = gen_new_label();
3572
bellard6af0bf92005-07-02 14:58:51 +00003573 switch (opc) {
3574 case OPC_TEQ:
3575 case OPC_TEQI:
aurel32cdc0faa2009-03-29 01:19:02 +00003576 tcg_gen_brcond_tl(TCG_COND_NE, t0, t1, l1);
bellard6af0bf92005-07-02 14:58:51 +00003577 break;
3578 case OPC_TGE:
3579 case OPC_TGEI:
aurel32cdc0faa2009-03-29 01:19:02 +00003580 tcg_gen_brcond_tl(TCG_COND_LT, t0, t1, l1);
bellard6af0bf92005-07-02 14:58:51 +00003581 break;
3582 case OPC_TGEU:
3583 case OPC_TGEIU:
aurel32cdc0faa2009-03-29 01:19:02 +00003584 tcg_gen_brcond_tl(TCG_COND_LTU, t0, t1, l1);
bellard6af0bf92005-07-02 14:58:51 +00003585 break;
3586 case OPC_TLT:
3587 case OPC_TLTI:
aurel32cdc0faa2009-03-29 01:19:02 +00003588 tcg_gen_brcond_tl(TCG_COND_GE, t0, t1, l1);
bellard6af0bf92005-07-02 14:58:51 +00003589 break;
3590 case OPC_TLTU:
3591 case OPC_TLTIU:
aurel32cdc0faa2009-03-29 01:19:02 +00003592 tcg_gen_brcond_tl(TCG_COND_GEU, t0, t1, l1);
bellard6af0bf92005-07-02 14:58:51 +00003593 break;
3594 case OPC_TNE:
3595 case OPC_TNEI:
aurel32cdc0faa2009-03-29 01:19:02 +00003596 tcg_gen_brcond_tl(TCG_COND_EQ, t0, t1, l1);
bellard6af0bf92005-07-02 14:58:51 +00003597 break;
bellard6af0bf92005-07-02 14:58:51 +00003598 }
aurel32cdc0faa2009-03-29 01:19:02 +00003599 generate_exception(ctx, EXCP_TRAP);
ths08ba7962008-06-12 03:15:13 +00003600 gen_set_label(l1);
3601 }
thsbe24bb42008-06-23 12:57:09 +00003602 tcg_temp_free(t0);
3603 tcg_temp_free(t1);
bellard6af0bf92005-07-02 14:58:51 +00003604}
3605
ths356265a2008-07-01 16:37:52 +00003606static inline void gen_goto_tb(DisasContext *ctx, int n, target_ulong dest)
bellardc53be332005-10-30 21:39:19 +00003607{
bellard6e256c92005-11-20 10:32:05 +00003608 TranslationBlock *tb;
3609 tb = ctx->tb;
Nathan Froyd7b270ef2009-07-14 08:33:11 -07003610 if ((tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK) &&
3611 likely(!ctx->singlestep_enabled)) {
bellard57fec1f2008-02-01 10:50:11 +00003612 tcg_gen_goto_tb(n);
ths9b9e4392007-05-28 17:03:28 +00003613 gen_save_pc(dest);
Stefan Weil4b4a72e2011-04-02 13:36:31 +02003614 tcg_gen_exit_tb((tcg_target_long)tb + n);
bellard6e256c92005-11-20 10:32:05 +00003615 } else {
ths9b9e4392007-05-28 17:03:28 +00003616 gen_save_pc(dest);
Nathan Froyd7b270ef2009-07-14 08:33:11 -07003617 if (ctx->singlestep_enabled) {
3618 save_cpu_state(ctx, 0);
Blue Swirl895c2d02012-09-02 14:52:59 +00003619 gen_helper_0e0i(raise_exception, EXCP_DEBUG);
Nathan Froyd7b270ef2009-07-14 08:33:11 -07003620 }
bellard57fec1f2008-02-01 10:50:11 +00003621 tcg_gen_exit_tb(0);
bellard6e256c92005-11-20 10:32:05 +00003622 }
bellardc53be332005-10-30 21:39:19 +00003623}
3624
bellard6af0bf92005-07-02 14:58:51 +00003625/* Branches (before delay slot) */
ths7a387ff2006-12-06 20:17:30 +00003626static void gen_compute_branch (DisasContext *ctx, uint32_t opc,
Nathan Froyd7dca4ad2009-12-08 08:06:25 -08003627 int insn_bytes,
bellard6af0bf92005-07-02 14:58:51 +00003628 int rs, int rt, int32_t offset)
3629{
thsd077b6f2008-06-30 11:30:34 +00003630 target_ulong btgt = -1;
ths3ad4bb22007-03-19 22:15:30 +00003631 int blink = 0;
aurel322fdbad22008-09-05 14:19:17 +00003632 int bcond_compute = 0;
aurel321ba74fb2009-03-29 01:18:52 +00003633 TCGv t0 = tcg_temp_new();
3634 TCGv t1 = tcg_temp_new();
bellard6af0bf92005-07-02 14:58:51 +00003635
ths3ad4bb22007-03-19 22:15:30 +00003636 if (ctx->hflags & MIPS_HFLAG_BMASK) {
ths923617a2007-05-11 00:16:06 +00003637#ifdef MIPS_DEBUG_DISAS
aliguorid12d51d2009-01-15 21:48:06 +00003638 LOG_DISAS("Branch in delay slot at PC 0x" TARGET_FMT_lx "\n", ctx->pc);
ths923617a2007-05-11 00:16:06 +00003639#endif
ths3ad4bb22007-03-19 22:15:30 +00003640 generate_exception(ctx, EXCP_RI);
ths6c5c1e22008-06-24 15:12:27 +00003641 goto out;
ths3ad4bb22007-03-19 22:15:30 +00003642 }
3643
bellard6af0bf92005-07-02 14:58:51 +00003644 /* Load needed operands */
3645 switch (opc) {
3646 case OPC_BEQ:
3647 case OPC_BEQL:
3648 case OPC_BNE:
3649 case OPC_BNEL:
3650 /* Compare two registers */
3651 if (rs != rt) {
ths6c5c1e22008-06-24 15:12:27 +00003652 gen_load_gpr(t0, rs);
3653 gen_load_gpr(t1, rt);
aurel322fdbad22008-09-05 14:19:17 +00003654 bcond_compute = 1;
bellard6af0bf92005-07-02 14:58:51 +00003655 }
Nathan Froyd7dca4ad2009-12-08 08:06:25 -08003656 btgt = ctx->pc + insn_bytes + offset;
bellard6af0bf92005-07-02 14:58:51 +00003657 break;
3658 case OPC_BGEZ:
3659 case OPC_BGEZAL:
Nathan Froyd3c824102010-06-08 13:29:59 -07003660 case OPC_BGEZALS:
bellard6af0bf92005-07-02 14:58:51 +00003661 case OPC_BGEZALL:
3662 case OPC_BGEZL:
3663 case OPC_BGTZ:
3664 case OPC_BGTZL:
3665 case OPC_BLEZ:
3666 case OPC_BLEZL:
3667 case OPC_BLTZ:
3668 case OPC_BLTZAL:
Nathan Froyd3c824102010-06-08 13:29:59 -07003669 case OPC_BLTZALS:
bellard6af0bf92005-07-02 14:58:51 +00003670 case OPC_BLTZALL:
3671 case OPC_BLTZL:
3672 /* Compare to zero */
3673 if (rs != 0) {
ths6c5c1e22008-06-24 15:12:27 +00003674 gen_load_gpr(t0, rs);
aurel322fdbad22008-09-05 14:19:17 +00003675 bcond_compute = 1;
bellard6af0bf92005-07-02 14:58:51 +00003676 }
Nathan Froyd7dca4ad2009-12-08 08:06:25 -08003677 btgt = ctx->pc + insn_bytes + offset;
bellard6af0bf92005-07-02 14:58:51 +00003678 break;
Jia Liue45a93e2012-10-24 22:17:04 +08003679 case OPC_BPOSGE32:
3680#if defined(TARGET_MIPS64)
3681 case OPC_BPOSGE64:
3682 tcg_gen_andi_tl(t0, cpu_dspctrl, 0x7F);
3683#else
3684 tcg_gen_andi_tl(t0, cpu_dspctrl, 0x3F);
3685#endif
3686 bcond_compute = 1;
3687 btgt = ctx->pc + insn_bytes + offset;
3688 break;
bellard6af0bf92005-07-02 14:58:51 +00003689 case OPC_J:
3690 case OPC_JAL:
Nathan Froyd364d4832009-12-08 08:06:29 -08003691 case OPC_JALX:
Nathan Froyd620e48f2010-06-08 13:29:58 -07003692 case OPC_JALS:
3693 case OPC_JALXS:
bellard6af0bf92005-07-02 14:58:51 +00003694 /* Jump to immediate */
Nathan Froyd7dca4ad2009-12-08 08:06:25 -08003695 btgt = ((ctx->pc + insn_bytes) & (int32_t)0xF0000000) | (uint32_t)offset;
bellard6af0bf92005-07-02 14:58:51 +00003696 break;
3697 case OPC_JR:
3698 case OPC_JALR:
Nathan Froyd364d4832009-12-08 08:06:29 -08003699 case OPC_JALRC:
Nathan Froyd620e48f2010-06-08 13:29:58 -07003700 case OPC_JALRS:
bellard6af0bf92005-07-02 14:58:51 +00003701 /* Jump to register */
ths7a387ff2006-12-06 20:17:30 +00003702 if (offset != 0 && offset != 16) {
3703 /* Hint = 0 is JR/JALR, hint 16 is JR.HB/JALR.HB, the
thscbeb0852007-04-07 01:11:15 +00003704 others are reserved. */
ths923617a2007-05-11 00:16:06 +00003705 MIPS_INVAL("jump hint");
bellard6af0bf92005-07-02 14:58:51 +00003706 generate_exception(ctx, EXCP_RI);
ths6c5c1e22008-06-24 15:12:27 +00003707 goto out;
bellard6af0bf92005-07-02 14:58:51 +00003708 }
thsd077b6f2008-06-30 11:30:34 +00003709 gen_load_gpr(btarget, rs);
bellard6af0bf92005-07-02 14:58:51 +00003710 break;
3711 default:
3712 MIPS_INVAL("branch/jump");
3713 generate_exception(ctx, EXCP_RI);
ths6c5c1e22008-06-24 15:12:27 +00003714 goto out;
bellard6af0bf92005-07-02 14:58:51 +00003715 }
aurel322fdbad22008-09-05 14:19:17 +00003716 if (bcond_compute == 0) {
bellard6af0bf92005-07-02 14:58:51 +00003717 /* No condition to be computed */
3718 switch (opc) {
3719 case OPC_BEQ: /* rx == rx */
3720 case OPC_BEQL: /* rx == rx likely */
3721 case OPC_BGEZ: /* 0 >= 0 */
3722 case OPC_BGEZL: /* 0 >= 0 likely */
3723 case OPC_BLEZ: /* 0 <= 0 */
3724 case OPC_BLEZL: /* 0 <= 0 likely */
3725 /* Always take */
bellard4ad40f32005-12-05 19:59:36 +00003726 ctx->hflags |= MIPS_HFLAG_B;
bellard6af0bf92005-07-02 14:58:51 +00003727 MIPS_DEBUG("balways");
3728 break;
Nathan Froyd3c824102010-06-08 13:29:59 -07003729 case OPC_BGEZALS:
bellard6af0bf92005-07-02 14:58:51 +00003730 case OPC_BGEZAL: /* 0 >= 0 */
3731 case OPC_BGEZALL: /* 0 >= 0 likely */
Nathan Froyd3c824102010-06-08 13:29:59 -07003732 ctx->hflags |= (opc == OPC_BGEZALS
3733 ? MIPS_HFLAG_BDS16
3734 : MIPS_HFLAG_BDS32);
bellard6af0bf92005-07-02 14:58:51 +00003735 /* Always take and link */
3736 blink = 31;
bellard4ad40f32005-12-05 19:59:36 +00003737 ctx->hflags |= MIPS_HFLAG_B;
bellard6af0bf92005-07-02 14:58:51 +00003738 MIPS_DEBUG("balways and link");
3739 break;
3740 case OPC_BNE: /* rx != rx */
3741 case OPC_BGTZ: /* 0 > 0 */
3742 case OPC_BLTZ: /* 0 < 0 */
thsead93602007-09-06 00:18:15 +00003743 /* Treat as NOP. */
bellard6af0bf92005-07-02 14:58:51 +00003744 MIPS_DEBUG("bnever (NOP)");
ths6c5c1e22008-06-24 15:12:27 +00003745 goto out;
Nathan Froyd3c824102010-06-08 13:29:59 -07003746 case OPC_BLTZALS:
bellardeeef26c2005-11-26 18:47:06 +00003747 case OPC_BLTZAL: /* 0 < 0 */
Nathan Froyd3c824102010-06-08 13:29:59 -07003748 ctx->hflags |= (opc == OPC_BLTZALS
3749 ? MIPS_HFLAG_BDS16
3750 : MIPS_HFLAG_BDS32);
3751 /* Handle as an unconditional branch to get correct delay
3752 slot checking. */
3753 blink = 31;
3754 btgt = ctx->pc + (opc == OPC_BLTZALS ? 6 : 8);
3755 ctx->hflags |= MIPS_HFLAG_B;
ths98981282007-04-16 01:35:29 +00003756 MIPS_DEBUG("bnever and link");
Nathan Froyd3c824102010-06-08 13:29:59 -07003757 break;
bellardeeef26c2005-11-26 18:47:06 +00003758 case OPC_BLTZALL: /* 0 < 0 likely */
aurel321ba74fb2009-03-29 01:18:52 +00003759 tcg_gen_movi_tl(cpu_gpr[31], ctx->pc + 8);
ths98981282007-04-16 01:35:29 +00003760 /* Skip the instruction in the delay slot */
3761 MIPS_DEBUG("bnever, link and skip");
3762 ctx->pc += 4;
ths6c5c1e22008-06-24 15:12:27 +00003763 goto out;
bellard6af0bf92005-07-02 14:58:51 +00003764 case OPC_BNEL: /* rx != rx likely */
3765 case OPC_BGTZL: /* 0 > 0 likely */
bellard6af0bf92005-07-02 14:58:51 +00003766 case OPC_BLTZL: /* 0 < 0 likely */
3767 /* Skip the instruction in the delay slot */
3768 MIPS_DEBUG("bnever and skip");
ths98981282007-04-16 01:35:29 +00003769 ctx->pc += 4;
ths6c5c1e22008-06-24 15:12:27 +00003770 goto out;
bellard6af0bf92005-07-02 14:58:51 +00003771 case OPC_J:
bellard4ad40f32005-12-05 19:59:36 +00003772 ctx->hflags |= MIPS_HFLAG_B;
thsd077b6f2008-06-30 11:30:34 +00003773 MIPS_DEBUG("j " TARGET_FMT_lx, btgt);
bellard6af0bf92005-07-02 14:58:51 +00003774 break;
Nathan Froyd620e48f2010-06-08 13:29:58 -07003775 case OPC_JALXS:
Nathan Froyd364d4832009-12-08 08:06:29 -08003776 case OPC_JALX:
3777 ctx->hflags |= MIPS_HFLAG_BX;
3778 /* Fallthrough */
Nathan Froyd620e48f2010-06-08 13:29:58 -07003779 case OPC_JALS:
bellard6af0bf92005-07-02 14:58:51 +00003780 case OPC_JAL:
3781 blink = 31;
bellard4ad40f32005-12-05 19:59:36 +00003782 ctx->hflags |= MIPS_HFLAG_B;
Nathan Froyd620e48f2010-06-08 13:29:58 -07003783 ctx->hflags |= ((opc == OPC_JALS || opc == OPC_JALXS)
Nathan Froyd364d4832009-12-08 08:06:29 -08003784 ? MIPS_HFLAG_BDS16
3785 : MIPS_HFLAG_BDS32);
thsd077b6f2008-06-30 11:30:34 +00003786 MIPS_DEBUG("jal " TARGET_FMT_lx, btgt);
bellard6af0bf92005-07-02 14:58:51 +00003787 break;
3788 case OPC_JR:
bellard4ad40f32005-12-05 19:59:36 +00003789 ctx->hflags |= MIPS_HFLAG_BR;
Nathan Froyd620e48f2010-06-08 13:29:58 -07003790 if (insn_bytes == 4)
3791 ctx->hflags |= MIPS_HFLAG_BDS32;
bellard6af0bf92005-07-02 14:58:51 +00003792 MIPS_DEBUG("jr %s", regnames[rs]);
3793 break;
Nathan Froyd620e48f2010-06-08 13:29:58 -07003794 case OPC_JALRS:
bellard6af0bf92005-07-02 14:58:51 +00003795 case OPC_JALR:
Nathan Froyd364d4832009-12-08 08:06:29 -08003796 case OPC_JALRC:
bellard6af0bf92005-07-02 14:58:51 +00003797 blink = rt;
bellard4ad40f32005-12-05 19:59:36 +00003798 ctx->hflags |= MIPS_HFLAG_BR;
Nathan Froyd620e48f2010-06-08 13:29:58 -07003799 ctx->hflags |= (opc == OPC_JALRS
3800 ? MIPS_HFLAG_BDS16
3801 : MIPS_HFLAG_BDS32);
bellard6af0bf92005-07-02 14:58:51 +00003802 MIPS_DEBUG("jalr %s, %s", regnames[rt], regnames[rs]);
3803 break;
3804 default:
3805 MIPS_INVAL("branch/jump");
3806 generate_exception(ctx, EXCP_RI);
ths6c5c1e22008-06-24 15:12:27 +00003807 goto out;
bellard6af0bf92005-07-02 14:58:51 +00003808 }
3809 } else {
3810 switch (opc) {
3811 case OPC_BEQ:
Aurelien Jarnoe68dd282010-02-08 15:50:58 +01003812 tcg_gen_setcond_tl(TCG_COND_EQ, bcond, t0, t1);
ths923617a2007-05-11 00:16:06 +00003813 MIPS_DEBUG("beq %s, %s, " TARGET_FMT_lx,
thsd077b6f2008-06-30 11:30:34 +00003814 regnames[rs], regnames[rt], btgt);
bellard6af0bf92005-07-02 14:58:51 +00003815 goto not_likely;
3816 case OPC_BEQL:
Aurelien Jarnoe68dd282010-02-08 15:50:58 +01003817 tcg_gen_setcond_tl(TCG_COND_EQ, bcond, t0, t1);
ths923617a2007-05-11 00:16:06 +00003818 MIPS_DEBUG("beql %s, %s, " TARGET_FMT_lx,
thsd077b6f2008-06-30 11:30:34 +00003819 regnames[rs], regnames[rt], btgt);
bellard6af0bf92005-07-02 14:58:51 +00003820 goto likely;
3821 case OPC_BNE:
Aurelien Jarnoe68dd282010-02-08 15:50:58 +01003822 tcg_gen_setcond_tl(TCG_COND_NE, bcond, t0, t1);
ths923617a2007-05-11 00:16:06 +00003823 MIPS_DEBUG("bne %s, %s, " TARGET_FMT_lx,
thsd077b6f2008-06-30 11:30:34 +00003824 regnames[rs], regnames[rt], btgt);
bellard6af0bf92005-07-02 14:58:51 +00003825 goto not_likely;
3826 case OPC_BNEL:
Aurelien Jarnoe68dd282010-02-08 15:50:58 +01003827 tcg_gen_setcond_tl(TCG_COND_NE, bcond, t0, t1);
ths923617a2007-05-11 00:16:06 +00003828 MIPS_DEBUG("bnel %s, %s, " TARGET_FMT_lx,
thsd077b6f2008-06-30 11:30:34 +00003829 regnames[rs], regnames[rt], btgt);
bellard6af0bf92005-07-02 14:58:51 +00003830 goto likely;
3831 case OPC_BGEZ:
Aurelien Jarnoe68dd282010-02-08 15:50:58 +01003832 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
thsd077b6f2008-06-30 11:30:34 +00003833 MIPS_DEBUG("bgez %s, " TARGET_FMT_lx, regnames[rs], btgt);
bellard6af0bf92005-07-02 14:58:51 +00003834 goto not_likely;
3835 case OPC_BGEZL:
Aurelien Jarnoe68dd282010-02-08 15:50:58 +01003836 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
thsd077b6f2008-06-30 11:30:34 +00003837 MIPS_DEBUG("bgezl %s, " TARGET_FMT_lx, regnames[rs], btgt);
bellard6af0bf92005-07-02 14:58:51 +00003838 goto likely;
Nathan Froyd3c824102010-06-08 13:29:59 -07003839 case OPC_BGEZALS:
bellard6af0bf92005-07-02 14:58:51 +00003840 case OPC_BGEZAL:
Nathan Froyd3c824102010-06-08 13:29:59 -07003841 ctx->hflags |= (opc == OPC_BGEZALS
3842 ? MIPS_HFLAG_BDS16
3843 : MIPS_HFLAG_BDS32);
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("bgezal %s, " TARGET_FMT_lx, regnames[rs], btgt);
bellard6af0bf92005-07-02 14:58:51 +00003846 blink = 31;
3847 goto not_likely;
3848 case OPC_BGEZALL:
Aurelien Jarnoe68dd282010-02-08 15:50:58 +01003849 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
bellard6af0bf92005-07-02 14:58:51 +00003850 blink = 31;
thsd077b6f2008-06-30 11:30:34 +00003851 MIPS_DEBUG("bgezall %s, " TARGET_FMT_lx, regnames[rs], btgt);
bellard6af0bf92005-07-02 14:58:51 +00003852 goto likely;
3853 case OPC_BGTZ:
Aurelien Jarnoe68dd282010-02-08 15:50:58 +01003854 tcg_gen_setcondi_tl(TCG_COND_GT, bcond, t0, 0);
thsd077b6f2008-06-30 11:30:34 +00003855 MIPS_DEBUG("bgtz %s, " TARGET_FMT_lx, regnames[rs], btgt);
bellard6af0bf92005-07-02 14:58:51 +00003856 goto not_likely;
3857 case OPC_BGTZL:
Aurelien Jarnoe68dd282010-02-08 15:50:58 +01003858 tcg_gen_setcondi_tl(TCG_COND_GT, bcond, t0, 0);
thsd077b6f2008-06-30 11:30:34 +00003859 MIPS_DEBUG("bgtzl %s, " TARGET_FMT_lx, regnames[rs], btgt);
bellard6af0bf92005-07-02 14:58:51 +00003860 goto likely;
3861 case OPC_BLEZ:
Aurelien Jarnoe68dd282010-02-08 15:50:58 +01003862 tcg_gen_setcondi_tl(TCG_COND_LE, bcond, t0, 0);
thsd077b6f2008-06-30 11:30:34 +00003863 MIPS_DEBUG("blez %s, " TARGET_FMT_lx, regnames[rs], btgt);
bellard6af0bf92005-07-02 14:58:51 +00003864 goto not_likely;
3865 case OPC_BLEZL:
Aurelien Jarnoe68dd282010-02-08 15:50:58 +01003866 tcg_gen_setcondi_tl(TCG_COND_LE, bcond, t0, 0);
thsd077b6f2008-06-30 11:30:34 +00003867 MIPS_DEBUG("blezl %s, " TARGET_FMT_lx, regnames[rs], btgt);
bellard6af0bf92005-07-02 14:58:51 +00003868 goto likely;
3869 case OPC_BLTZ:
Aurelien Jarnoe68dd282010-02-08 15:50:58 +01003870 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
thsd077b6f2008-06-30 11:30:34 +00003871 MIPS_DEBUG("bltz %s, " TARGET_FMT_lx, regnames[rs], btgt);
bellard6af0bf92005-07-02 14:58:51 +00003872 goto not_likely;
3873 case OPC_BLTZL:
Aurelien Jarnoe68dd282010-02-08 15:50:58 +01003874 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
thsd077b6f2008-06-30 11:30:34 +00003875 MIPS_DEBUG("bltzl %s, " TARGET_FMT_lx, regnames[rs], btgt);
bellard6af0bf92005-07-02 14:58:51 +00003876 goto likely;
Jia Liue45a93e2012-10-24 22:17:04 +08003877 case OPC_BPOSGE32:
3878 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 32);
3879 MIPS_DEBUG("bposge32 " TARGET_FMT_lx, btgt);
3880 goto not_likely;
3881#if defined(TARGET_MIPS64)
3882 case OPC_BPOSGE64:
3883 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 64);
3884 MIPS_DEBUG("bposge64 " TARGET_FMT_lx, btgt);
3885 goto not_likely;
3886#endif
Nathan Froyd3c824102010-06-08 13:29:59 -07003887 case OPC_BLTZALS:
bellard6af0bf92005-07-02 14:58:51 +00003888 case OPC_BLTZAL:
Nathan Froyd3c824102010-06-08 13:29:59 -07003889 ctx->hflags |= (opc == OPC_BLTZALS
3890 ? MIPS_HFLAG_BDS16
3891 : MIPS_HFLAG_BDS32);
Aurelien Jarnoe68dd282010-02-08 15:50:58 +01003892 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
bellard6af0bf92005-07-02 14:58:51 +00003893 blink = 31;
thsd077b6f2008-06-30 11:30:34 +00003894 MIPS_DEBUG("bltzal %s, " TARGET_FMT_lx, regnames[rs], btgt);
bellard6af0bf92005-07-02 14:58:51 +00003895 not_likely:
bellard4ad40f32005-12-05 19:59:36 +00003896 ctx->hflags |= MIPS_HFLAG_BC;
bellard6af0bf92005-07-02 14:58:51 +00003897 break;
3898 case OPC_BLTZALL:
Aurelien Jarnoe68dd282010-02-08 15:50:58 +01003899 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
bellard6af0bf92005-07-02 14:58:51 +00003900 blink = 31;
thsd077b6f2008-06-30 11:30:34 +00003901 MIPS_DEBUG("bltzall %s, " TARGET_FMT_lx, regnames[rs], btgt);
bellard6af0bf92005-07-02 14:58:51 +00003902 likely:
bellard4ad40f32005-12-05 19:59:36 +00003903 ctx->hflags |= MIPS_HFLAG_BL;
bellard6af0bf92005-07-02 14:58:51 +00003904 break;
thsc53f4a62007-04-05 23:21:37 +00003905 default:
3906 MIPS_INVAL("conditional branch/jump");
3907 generate_exception(ctx, EXCP_RI);
ths6c5c1e22008-06-24 15:12:27 +00003908 goto out;
bellard6af0bf92005-07-02 14:58:51 +00003909 }
bellard6af0bf92005-07-02 14:58:51 +00003910 }
ths923617a2007-05-11 00:16:06 +00003911 MIPS_DEBUG("enter ds: link %d cond %02x target " TARGET_FMT_lx,
thsd077b6f2008-06-30 11:30:34 +00003912 blink, ctx->hflags, btgt);
ths9b9e4392007-05-28 17:03:28 +00003913
thsd077b6f2008-06-30 11:30:34 +00003914 ctx->btarget = btgt;
bellard6af0bf92005-07-02 14:58:51 +00003915 if (blink > 0) {
Nathan Froyd364d4832009-12-08 08:06:29 -08003916 int post_delay = insn_bytes;
3917 int lowbit = !!(ctx->hflags & MIPS_HFLAG_M16);
3918
3919 if (opc != OPC_JALRC)
3920 post_delay += ((ctx->hflags & MIPS_HFLAG_BDS16) ? 2 : 4);
3921
3922 tcg_gen_movi_tl(cpu_gpr[blink], ctx->pc + post_delay + lowbit);
bellard6af0bf92005-07-02 14:58:51 +00003923 }
ths6c5c1e22008-06-24 15:12:27 +00003924
3925 out:
Nathan Froyd364d4832009-12-08 08:06:29 -08003926 if (insn_bytes == 2)
3927 ctx->hflags |= MIPS_HFLAG_B16;
ths6c5c1e22008-06-24 15:12:27 +00003928 tcg_temp_free(t0);
3929 tcg_temp_free(t1);
bellard6af0bf92005-07-02 14:58:51 +00003930}
3931
ths7a387ff2006-12-06 20:17:30 +00003932/* special3 bitfield operations */
3933static void gen_bitops (DisasContext *ctx, uint32_t opc, int rt,
ths356265a2008-07-01 16:37:52 +00003934 int rs, int lsb, int msb)
ths7a387ff2006-12-06 20:17:30 +00003935{
pbrooka7812ae2008-11-17 14:43:54 +00003936 TCGv t0 = tcg_temp_new();
3937 TCGv t1 = tcg_temp_new();
ths6c5c1e22008-06-24 15:12:27 +00003938
3939 gen_load_gpr(t1, rs);
ths7a387ff2006-12-06 20:17:30 +00003940 switch (opc) {
3941 case OPC_EXT:
3942 if (lsb + msb > 31)
3943 goto fail;
aurel32505ad7c2008-11-11 11:46:58 +00003944 tcg_gen_shri_tl(t0, t1, lsb);
3945 if (msb != 31) {
3946 tcg_gen_andi_tl(t0, t0, (1 << (msb + 1)) - 1);
3947 } else {
3948 tcg_gen_ext32s_tl(t0, t0);
3949 }
ths7a387ff2006-12-06 20:17:30 +00003950 break;
thsc6d6dd72007-11-18 03:36:07 +00003951#if defined(TARGET_MIPS64)
ths7a387ff2006-12-06 20:17:30 +00003952 case OPC_DEXTM:
aurel32505ad7c2008-11-11 11:46:58 +00003953 tcg_gen_shri_tl(t0, t1, lsb);
3954 if (msb != 31) {
3955 tcg_gen_andi_tl(t0, t0, (1ULL << (msb + 1 + 32)) - 1);
3956 }
ths7a387ff2006-12-06 20:17:30 +00003957 break;
3958 case OPC_DEXTU:
aurel32505ad7c2008-11-11 11:46:58 +00003959 tcg_gen_shri_tl(t0, t1, lsb + 32);
3960 tcg_gen_andi_tl(t0, t0, (1ULL << (msb + 1)) - 1);
ths7a387ff2006-12-06 20:17:30 +00003961 break;
3962 case OPC_DEXT:
aurel32505ad7c2008-11-11 11:46:58 +00003963 tcg_gen_shri_tl(t0, t1, lsb);
3964 tcg_gen_andi_tl(t0, t0, (1ULL << (msb + 1)) - 1);
ths7a387ff2006-12-06 20:17:30 +00003965 break;
thsc6d6dd72007-11-18 03:36:07 +00003966#endif
ths7a387ff2006-12-06 20:17:30 +00003967 case OPC_INS:
3968 if (lsb > msb)
3969 goto fail;
ths6c5c1e22008-06-24 15:12:27 +00003970 gen_load_gpr(t0, rt);
Aurelien Jarnoe0d002f2012-10-09 21:53:21 +02003971 tcg_gen_deposit_tl(t0, t0, t1, lsb, msb - lsb + 1);
aurel32505ad7c2008-11-11 11:46:58 +00003972 tcg_gen_ext32s_tl(t0, t0);
ths7a387ff2006-12-06 20:17:30 +00003973 break;
thsc6d6dd72007-11-18 03:36:07 +00003974#if defined(TARGET_MIPS64)
ths7a387ff2006-12-06 20:17:30 +00003975 case OPC_DINSM:
ths6c5c1e22008-06-24 15:12:27 +00003976 gen_load_gpr(t0, rt);
Aurelien Jarnoe0d002f2012-10-09 21:53:21 +02003977 tcg_gen_deposit_tl(t0, t0, t1, lsb, msb + 32 - lsb + 1);
ths7a387ff2006-12-06 20:17:30 +00003978 break;
3979 case OPC_DINSU:
ths6c5c1e22008-06-24 15:12:27 +00003980 gen_load_gpr(t0, rt);
Aurelien Jarnoe0d002f2012-10-09 21:53:21 +02003981 tcg_gen_deposit_tl(t0, t0, t1, lsb + 32, msb - lsb + 1);
ths7a387ff2006-12-06 20:17:30 +00003982 break;
3983 case OPC_DINS:
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 - lsb + 1);
ths7a387ff2006-12-06 20:17:30 +00003986 break;
thsc6d6dd72007-11-18 03:36:07 +00003987#endif
ths7a387ff2006-12-06 20:17:30 +00003988 default:
3989fail:
3990 MIPS_INVAL("bitops");
3991 generate_exception(ctx, EXCP_RI);
ths6c5c1e22008-06-24 15:12:27 +00003992 tcg_temp_free(t0);
3993 tcg_temp_free(t1);
ths7a387ff2006-12-06 20:17:30 +00003994 return;
3995 }
ths6c5c1e22008-06-24 15:12:27 +00003996 gen_store_gpr(t0, rt);
3997 tcg_temp_free(t0);
3998 tcg_temp_free(t1);
ths7a387ff2006-12-06 20:17:30 +00003999}
4000
aurel3249bcf332008-11-11 11:47:06 +00004001static void gen_bshfl (DisasContext *ctx, uint32_t op2, int rt, int rd)
4002{
aurel323a55fa42009-03-29 01:18:34 +00004003 TCGv t0;
aurel3249bcf332008-11-11 11:47:06 +00004004
aurel323a55fa42009-03-29 01:18:34 +00004005 if (rd == 0) {
4006 /* If no destination, treat it as a NOP. */
4007 MIPS_DEBUG("NOP");
4008 return;
4009 }
4010
4011 t0 = tcg_temp_new();
4012 gen_load_gpr(t0, rt);
aurel3249bcf332008-11-11 11:47:06 +00004013 switch (op2) {
4014 case OPC_WSBH:
aurel323a55fa42009-03-29 01:18:34 +00004015 {
4016 TCGv t1 = tcg_temp_new();
4017
4018 tcg_gen_shri_tl(t1, t0, 8);
4019 tcg_gen_andi_tl(t1, t1, 0x00FF00FF);
4020 tcg_gen_shli_tl(t0, t0, 8);
4021 tcg_gen_andi_tl(t0, t0, ~0x00FF00FF);
4022 tcg_gen_or_tl(t0, t0, t1);
4023 tcg_temp_free(t1);
4024 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
4025 }
aurel3249bcf332008-11-11 11:47:06 +00004026 break;
4027 case OPC_SEB:
aurel323a55fa42009-03-29 01:18:34 +00004028 tcg_gen_ext8s_tl(cpu_gpr[rd], t0);
aurel3249bcf332008-11-11 11:47:06 +00004029 break;
4030 case OPC_SEH:
aurel323a55fa42009-03-29 01:18:34 +00004031 tcg_gen_ext16s_tl(cpu_gpr[rd], t0);
aurel3249bcf332008-11-11 11:47:06 +00004032 break;
4033#if defined(TARGET_MIPS64)
4034 case OPC_DSBH:
aurel323a55fa42009-03-29 01:18:34 +00004035 {
4036 TCGv t1 = tcg_temp_new();
4037
4038 tcg_gen_shri_tl(t1, t0, 8);
4039 tcg_gen_andi_tl(t1, t1, 0x00FF00FF00FF00FFULL);
4040 tcg_gen_shli_tl(t0, t0, 8);
4041 tcg_gen_andi_tl(t0, t0, ~0x00FF00FF00FF00FFULL);
4042 tcg_gen_or_tl(cpu_gpr[rd], t0, t1);
4043 tcg_temp_free(t1);
4044 }
aurel3249bcf332008-11-11 11:47:06 +00004045 break;
4046 case OPC_DSHD:
aurel323a55fa42009-03-29 01:18:34 +00004047 {
4048 TCGv t1 = tcg_temp_new();
4049
4050 tcg_gen_shri_tl(t1, t0, 16);
4051 tcg_gen_andi_tl(t1, t1, 0x0000FFFF0000FFFFULL);
4052 tcg_gen_shli_tl(t0, t0, 16);
4053 tcg_gen_andi_tl(t0, t0, ~0x0000FFFF0000FFFFULL);
4054 tcg_gen_or_tl(t0, t0, t1);
4055 tcg_gen_shri_tl(t1, t0, 32);
4056 tcg_gen_shli_tl(t0, t0, 32);
4057 tcg_gen_or_tl(cpu_gpr[rd], t0, t1);
4058 tcg_temp_free(t1);
4059 }
aurel3249bcf332008-11-11 11:47:06 +00004060 break;
4061#endif
4062 default:
4063 MIPS_INVAL("bsfhl");
4064 generate_exception(ctx, EXCP_RI);
4065 tcg_temp_free(t0);
aurel3249bcf332008-11-11 11:47:06 +00004066 return;
4067 }
aurel3249bcf332008-11-11 11:47:06 +00004068 tcg_temp_free(t0);
aurel3249bcf332008-11-11 11:47:06 +00004069}
4070
thsf1aa6322008-06-09 07:13:38 +00004071#ifndef CONFIG_USER_ONLY
ths0eaef5a2008-07-23 16:14:22 +00004072/* CP0 (MMU and control) */
aurel32d9bea112009-04-15 14:41:44 +00004073static inline void gen_mfc0_load32 (TCGv arg, target_ulong off)
ths4f576892008-06-04 17:37:03 +00004074{
aurel32d9bea112009-04-15 14:41:44 +00004075 TCGv_i32 t0 = tcg_temp_new_i32();
ths4f576892008-06-04 17:37:03 +00004076
aurel32d9bea112009-04-15 14:41:44 +00004077 tcg_gen_ld_i32(t0, cpu_env, off);
4078 tcg_gen_ext_i32_tl(arg, t0);
4079 tcg_temp_free_i32(t0);
ths4f576892008-06-04 17:37:03 +00004080}
4081
aurel32d9bea112009-04-15 14:41:44 +00004082static inline void gen_mfc0_load64 (TCGv arg, target_ulong off)
ths4f576892008-06-04 17:37:03 +00004083{
aurel32d9bea112009-04-15 14:41:44 +00004084 tcg_gen_ld_tl(arg, cpu_env, off);
4085 tcg_gen_ext32s_tl(arg, arg);
ths4f576892008-06-04 17:37:03 +00004086}
4087
aurel32d9bea112009-04-15 14:41:44 +00004088static inline void gen_mtc0_store32 (TCGv arg, target_ulong off)
thsf1aa6322008-06-09 07:13:38 +00004089{
aurel32d9bea112009-04-15 14:41:44 +00004090 TCGv_i32 t0 = tcg_temp_new_i32();
thsf1aa6322008-06-09 07:13:38 +00004091
aurel32d9bea112009-04-15 14:41:44 +00004092 tcg_gen_trunc_tl_i32(t0, arg);
4093 tcg_gen_st_i32(t0, cpu_env, off);
4094 tcg_temp_free_i32(t0);
thsf1aa6322008-06-09 07:13:38 +00004095}
4096
aurel32d9bea112009-04-15 14:41:44 +00004097static inline void gen_mtc0_store64 (TCGv arg, target_ulong off)
thsf1aa6322008-06-09 07:13:38 +00004098{
aurel32d9bea112009-04-15 14:41:44 +00004099 tcg_gen_ext32s_tl(arg, arg);
4100 tcg_gen_st_tl(arg, cpu_env, off);
thsf1aa6322008-06-09 07:13:38 +00004101}
4102
Aurelien Jarnod75c1352013-01-01 18:02:22 +01004103static void gen_mfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
ths873eb012006-12-06 17:59:07 +00004104{
ths7a387ff2006-12-06 20:17:30 +00004105 const char *rn = "invalid";
ths873eb012006-12-06 17:59:07 +00004106
thse189e742007-09-24 12:48:00 +00004107 if (sel != 0)
Aurelien Jarnod75c1352013-01-01 18:02:22 +01004108 check_insn(ctx, ISA_MIPS32);
thse189e742007-09-24 12:48:00 +00004109
ths873eb012006-12-06 17:59:07 +00004110 switch (reg) {
4111 case 0:
ths7a387ff2006-12-06 20:17:30 +00004112 switch (sel) {
4113 case 0:
Andreas Färber7db13fa2012-03-14 01:38:22 +01004114 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Index));
ths7a387ff2006-12-06 20:17:30 +00004115 rn = "Index";
4116 break;
4117 case 1:
Aurelien Jarnod75c1352013-01-01 18:02:22 +01004118 check_insn(ctx, ASE_MT);
Blue Swirl895c2d02012-09-02 14:52:59 +00004119 gen_helper_mfc0_mvpcontrol(arg, cpu_env);
ths7a387ff2006-12-06 20:17:30 +00004120 rn = "MVPControl";
thsead93602007-09-06 00:18:15 +00004121 break;
ths7a387ff2006-12-06 20:17:30 +00004122 case 2:
Aurelien Jarnod75c1352013-01-01 18:02:22 +01004123 check_insn(ctx, ASE_MT);
Blue Swirl895c2d02012-09-02 14:52:59 +00004124 gen_helper_mfc0_mvpconf0(arg, cpu_env);
ths7a387ff2006-12-06 20:17:30 +00004125 rn = "MVPConf0";
thsead93602007-09-06 00:18:15 +00004126 break;
ths7a387ff2006-12-06 20:17:30 +00004127 case 3:
Aurelien Jarnod75c1352013-01-01 18:02:22 +01004128 check_insn(ctx, ASE_MT);
Blue Swirl895c2d02012-09-02 14:52:59 +00004129 gen_helper_mfc0_mvpconf1(arg, cpu_env);
ths7a387ff2006-12-06 20:17:30 +00004130 rn = "MVPConf1";
thsead93602007-09-06 00:18:15 +00004131 break;
ths7a387ff2006-12-06 20:17:30 +00004132 default:
4133 goto die;
4134 }
ths873eb012006-12-06 17:59:07 +00004135 break;
4136 case 1:
ths7a387ff2006-12-06 20:17:30 +00004137 switch (sel) {
4138 case 0:
Blue Swirl895c2d02012-09-02 14:52:59 +00004139 gen_helper_mfc0_random(arg, cpu_env);
ths7a387ff2006-12-06 20:17:30 +00004140 rn = "Random";
ths2423f662007-04-11 02:15:08 +00004141 break;
ths7a387ff2006-12-06 20:17:30 +00004142 case 1:
Aurelien Jarnod75c1352013-01-01 18:02:22 +01004143 check_insn(ctx, ASE_MT);
Andreas Färber7db13fa2012-03-14 01:38:22 +01004144 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEControl));
ths7a387ff2006-12-06 20:17:30 +00004145 rn = "VPEControl";
thsead93602007-09-06 00:18:15 +00004146 break;
ths7a387ff2006-12-06 20:17:30 +00004147 case 2:
Aurelien Jarnod75c1352013-01-01 18:02:22 +01004148 check_insn(ctx, ASE_MT);
Andreas Färber7db13fa2012-03-14 01:38:22 +01004149 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf0));
ths7a387ff2006-12-06 20:17:30 +00004150 rn = "VPEConf0";
thsead93602007-09-06 00:18:15 +00004151 break;
ths7a387ff2006-12-06 20:17:30 +00004152 case 3:
Aurelien Jarnod75c1352013-01-01 18:02:22 +01004153 check_insn(ctx, ASE_MT);
Andreas Färber7db13fa2012-03-14 01:38:22 +01004154 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf1));
ths7a387ff2006-12-06 20:17:30 +00004155 rn = "VPEConf1";
thsead93602007-09-06 00:18:15 +00004156 break;
ths7a387ff2006-12-06 20:17:30 +00004157 case 4:
Aurelien Jarnod75c1352013-01-01 18:02:22 +01004158 check_insn(ctx, ASE_MT);
Andreas Färber7db13fa2012-03-14 01:38:22 +01004159 gen_mfc0_load64(arg, offsetof(CPUMIPSState, CP0_YQMask));
ths7a387ff2006-12-06 20:17:30 +00004160 rn = "YQMask";
thsead93602007-09-06 00:18:15 +00004161 break;
ths7a387ff2006-12-06 20:17:30 +00004162 case 5:
Aurelien Jarnod75c1352013-01-01 18:02:22 +01004163 check_insn(ctx, ASE_MT);
Andreas Färber7db13fa2012-03-14 01:38:22 +01004164 gen_mfc0_load64(arg, offsetof(CPUMIPSState, CP0_VPESchedule));
ths7a387ff2006-12-06 20:17:30 +00004165 rn = "VPESchedule";
thsead93602007-09-06 00:18:15 +00004166 break;
ths7a387ff2006-12-06 20:17:30 +00004167 case 6:
Aurelien Jarnod75c1352013-01-01 18:02:22 +01004168 check_insn(ctx, ASE_MT);
Andreas Färber7db13fa2012-03-14 01:38:22 +01004169 gen_mfc0_load64(arg, offsetof(CPUMIPSState, CP0_VPEScheFBack));
ths7a387ff2006-12-06 20:17:30 +00004170 rn = "VPEScheFBack";
thsead93602007-09-06 00:18:15 +00004171 break;
ths7a387ff2006-12-06 20:17:30 +00004172 case 7:
Aurelien Jarnod75c1352013-01-01 18:02:22 +01004173 check_insn(ctx, ASE_MT);
Andreas Färber7db13fa2012-03-14 01:38:22 +01004174 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEOpt));
ths7a387ff2006-12-06 20:17:30 +00004175 rn = "VPEOpt";
thsead93602007-09-06 00:18:15 +00004176 break;
ths7a387ff2006-12-06 20:17:30 +00004177 default:
4178 goto die;
4179 }
ths873eb012006-12-06 17:59:07 +00004180 break;
4181 case 2:
ths7a387ff2006-12-06 20:17:30 +00004182 switch (sel) {
4183 case 0:
Andreas Färber7db13fa2012-03-14 01:38:22 +01004184 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryLo0));
aurel32d9bea112009-04-15 14:41:44 +00004185 tcg_gen_ext32s_tl(arg, arg);
ths2423f662007-04-11 02:15:08 +00004186 rn = "EntryLo0";
4187 break;
ths7a387ff2006-12-06 20:17:30 +00004188 case 1:
Aurelien Jarnod75c1352013-01-01 18:02:22 +01004189 check_insn(ctx, ASE_MT);
Blue Swirl895c2d02012-09-02 14:52:59 +00004190 gen_helper_mfc0_tcstatus(arg, cpu_env);
ths2423f662007-04-11 02:15:08 +00004191 rn = "TCStatus";
thsead93602007-09-06 00:18:15 +00004192 break;
ths7a387ff2006-12-06 20:17:30 +00004193 case 2:
Aurelien Jarnod75c1352013-01-01 18:02:22 +01004194 check_insn(ctx, ASE_MT);
Blue Swirl895c2d02012-09-02 14:52:59 +00004195 gen_helper_mfc0_tcbind(arg, cpu_env);
ths2423f662007-04-11 02:15:08 +00004196 rn = "TCBind";
thsead93602007-09-06 00:18:15 +00004197 break;
ths7a387ff2006-12-06 20:17:30 +00004198 case 3:
Aurelien Jarnod75c1352013-01-01 18:02:22 +01004199 check_insn(ctx, ASE_MT);
Blue Swirl895c2d02012-09-02 14:52:59 +00004200 gen_helper_mfc0_tcrestart(arg, cpu_env);
ths2423f662007-04-11 02:15:08 +00004201 rn = "TCRestart";
thsead93602007-09-06 00:18:15 +00004202 break;
ths7a387ff2006-12-06 20:17:30 +00004203 case 4:
Aurelien Jarnod75c1352013-01-01 18:02:22 +01004204 check_insn(ctx, ASE_MT);
Blue Swirl895c2d02012-09-02 14:52:59 +00004205 gen_helper_mfc0_tchalt(arg, cpu_env);
ths2423f662007-04-11 02:15:08 +00004206 rn = "TCHalt";
thsead93602007-09-06 00:18:15 +00004207 break;
ths7a387ff2006-12-06 20:17:30 +00004208 case 5:
Aurelien Jarnod75c1352013-01-01 18:02:22 +01004209 check_insn(ctx, ASE_MT);
Blue Swirl895c2d02012-09-02 14:52:59 +00004210 gen_helper_mfc0_tccontext(arg, cpu_env);
ths2423f662007-04-11 02:15:08 +00004211 rn = "TCContext";
thsead93602007-09-06 00:18:15 +00004212 break;
ths7a387ff2006-12-06 20:17:30 +00004213 case 6:
Aurelien Jarnod75c1352013-01-01 18:02:22 +01004214 check_insn(ctx, ASE_MT);
Blue Swirl895c2d02012-09-02 14:52:59 +00004215 gen_helper_mfc0_tcschedule(arg, cpu_env);
ths2423f662007-04-11 02:15:08 +00004216 rn = "TCSchedule";
thsead93602007-09-06 00:18:15 +00004217 break;
ths7a387ff2006-12-06 20:17:30 +00004218 case 7:
Aurelien Jarnod75c1352013-01-01 18:02:22 +01004219 check_insn(ctx, ASE_MT);
Blue Swirl895c2d02012-09-02 14:52:59 +00004220 gen_helper_mfc0_tcschefback(arg, cpu_env);
ths2423f662007-04-11 02:15:08 +00004221 rn = "TCScheFBack";
thsead93602007-09-06 00:18:15 +00004222 break;
ths7a387ff2006-12-06 20:17:30 +00004223 default:
4224 goto die;
4225 }
ths873eb012006-12-06 17:59:07 +00004226 break;
4227 case 3:
ths7a387ff2006-12-06 20:17:30 +00004228 switch (sel) {
4229 case 0:
Andreas Färber7db13fa2012-03-14 01:38:22 +01004230 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryLo1));
aurel32d9bea112009-04-15 14:41:44 +00004231 tcg_gen_ext32s_tl(arg, arg);
ths2423f662007-04-11 02:15:08 +00004232 rn = "EntryLo1";
4233 break;
ths7a387ff2006-12-06 20:17:30 +00004234 default:
4235 goto die;
ths1579a722007-04-05 23:16:25 +00004236 }
ths873eb012006-12-06 17:59:07 +00004237 break;
4238 case 4:
ths7a387ff2006-12-06 20:17:30 +00004239 switch (sel) {
4240 case 0:
Andreas Färber7db13fa2012-03-14 01:38:22 +01004241 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_Context));
aurel32d9bea112009-04-15 14:41:44 +00004242 tcg_gen_ext32s_tl(arg, arg);
ths2423f662007-04-11 02:15:08 +00004243 rn = "Context";
4244 break;
ths7a387ff2006-12-06 20:17:30 +00004245 case 1:
aurel32d9bea112009-04-15 14:41:44 +00004246// gen_helper_mfc0_contextconfig(arg); /* SmartMIPS ASE */
ths2423f662007-04-11 02:15:08 +00004247 rn = "ContextConfig";
4248// break;
ths7a387ff2006-12-06 20:17:30 +00004249 default:
4250 goto die;
ths1579a722007-04-05 23:16:25 +00004251 }
ths873eb012006-12-06 17:59:07 +00004252 break;
4253 case 5:
ths7a387ff2006-12-06 20:17:30 +00004254 switch (sel) {
4255 case 0:
Andreas Färber7db13fa2012-03-14 01:38:22 +01004256 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageMask));
ths2423f662007-04-11 02:15:08 +00004257 rn = "PageMask";
4258 break;
ths7a387ff2006-12-06 20:17:30 +00004259 case 1:
Aurelien Jarnod75c1352013-01-01 18:02:22 +01004260 check_insn(ctx, ISA_MIPS32R2);
Andreas Färber7db13fa2012-03-14 01:38:22 +01004261 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageGrain));
ths2423f662007-04-11 02:15:08 +00004262 rn = "PageGrain";
4263 break;
ths7a387ff2006-12-06 20:17:30 +00004264 default:
4265 goto die;
ths1579a722007-04-05 23:16:25 +00004266 }
ths873eb012006-12-06 17:59:07 +00004267 break;
4268 case 6:
ths7a387ff2006-12-06 20:17:30 +00004269 switch (sel) {
4270 case 0:
Andreas Färber7db13fa2012-03-14 01:38:22 +01004271 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Wired));
ths2423f662007-04-11 02:15:08 +00004272 rn = "Wired";
4273 break;
ths7a387ff2006-12-06 20:17:30 +00004274 case 1:
Aurelien Jarnod75c1352013-01-01 18:02:22 +01004275 check_insn(ctx, ISA_MIPS32R2);
Andreas Färber7db13fa2012-03-14 01:38:22 +01004276 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf0));
ths2423f662007-04-11 02:15:08 +00004277 rn = "SRSConf0";
thsead93602007-09-06 00:18:15 +00004278 break;
ths7a387ff2006-12-06 20:17:30 +00004279 case 2:
Aurelien Jarnod75c1352013-01-01 18:02:22 +01004280 check_insn(ctx, ISA_MIPS32R2);
Andreas Färber7db13fa2012-03-14 01:38:22 +01004281 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf1));
ths2423f662007-04-11 02:15:08 +00004282 rn = "SRSConf1";
thsead93602007-09-06 00:18:15 +00004283 break;
ths7a387ff2006-12-06 20:17:30 +00004284 case 3:
Aurelien Jarnod75c1352013-01-01 18:02:22 +01004285 check_insn(ctx, ISA_MIPS32R2);
Andreas Färber7db13fa2012-03-14 01:38:22 +01004286 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf2));
ths2423f662007-04-11 02:15:08 +00004287 rn = "SRSConf2";
thsead93602007-09-06 00:18:15 +00004288 break;
ths7a387ff2006-12-06 20:17:30 +00004289 case 4:
Aurelien Jarnod75c1352013-01-01 18:02:22 +01004290 check_insn(ctx, ISA_MIPS32R2);
Andreas Färber7db13fa2012-03-14 01:38:22 +01004291 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf3));
ths2423f662007-04-11 02:15:08 +00004292 rn = "SRSConf3";
thsead93602007-09-06 00:18:15 +00004293 break;
ths7a387ff2006-12-06 20:17:30 +00004294 case 5:
Aurelien Jarnod75c1352013-01-01 18:02:22 +01004295 check_insn(ctx, ISA_MIPS32R2);
Andreas Färber7db13fa2012-03-14 01:38:22 +01004296 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf4));
ths2423f662007-04-11 02:15:08 +00004297 rn = "SRSConf4";
thsead93602007-09-06 00:18:15 +00004298 break;
ths7a387ff2006-12-06 20:17:30 +00004299 default:
4300 goto die;
ths1579a722007-04-05 23:16:25 +00004301 }
ths873eb012006-12-06 17:59:07 +00004302 break;
ths8c0fdd82006-12-06 18:19:33 +00004303 case 7:
ths7a387ff2006-12-06 20:17:30 +00004304 switch (sel) {
4305 case 0:
Aurelien Jarnod75c1352013-01-01 18:02:22 +01004306 check_insn(ctx, ISA_MIPS32R2);
Andreas Färber7db13fa2012-03-14 01:38:22 +01004307 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_HWREna));
ths2423f662007-04-11 02:15:08 +00004308 rn = "HWREna";
4309 break;
ths7a387ff2006-12-06 20:17:30 +00004310 default:
4311 goto die;
ths1579a722007-04-05 23:16:25 +00004312 }
ths8c0fdd82006-12-06 18:19:33 +00004313 break;
ths873eb012006-12-06 17:59:07 +00004314 case 8:
ths7a387ff2006-12-06 20:17:30 +00004315 switch (sel) {
4316 case 0:
Andreas Färber7db13fa2012-03-14 01:38:22 +01004317 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_BadVAddr));
aurel32d9bea112009-04-15 14:41:44 +00004318 tcg_gen_ext32s_tl(arg, arg);
thsf0b3f3a2008-05-23 18:10:51 +00004319 rn = "BadVAddr";
ths2423f662007-04-11 02:15:08 +00004320 break;
ths7a387ff2006-12-06 20:17:30 +00004321 default:
4322 goto die;
4323 }
ths873eb012006-12-06 17:59:07 +00004324 break;
4325 case 9:
ths7a387ff2006-12-06 20:17:30 +00004326 switch (sel) {
4327 case 0:
pbrook2e70f6e2008-06-29 01:03:05 +00004328 /* Mark as an IO operation because we read the time. */
4329 if (use_icount)
4330 gen_io_start();
Blue Swirl895c2d02012-09-02 14:52:59 +00004331 gen_helper_mfc0_count(arg, cpu_env);
pbrook2e70f6e2008-06-29 01:03:05 +00004332 if (use_icount) {
4333 gen_io_end();
pbrook2e70f6e2008-06-29 01:03:05 +00004334 }
Edgar E. Iglesias55807222011-01-17 23:00:08 +01004335 /* Break the TB to be able to take timer interrupts immediately
4336 after reading count. */
4337 ctx->bstate = BS_STOP;
ths2423f662007-04-11 02:15:08 +00004338 rn = "Count";
4339 break;
4340 /* 6,7 are implementation dependent */
ths7a387ff2006-12-06 20:17:30 +00004341 default:
4342 goto die;
ths2423f662007-04-11 02:15:08 +00004343 }
ths873eb012006-12-06 17:59:07 +00004344 break;
4345 case 10:
ths7a387ff2006-12-06 20:17:30 +00004346 switch (sel) {
4347 case 0:
Andreas Färber7db13fa2012-03-14 01:38:22 +01004348 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryHi));
aurel32d9bea112009-04-15 14:41:44 +00004349 tcg_gen_ext32s_tl(arg, arg);
ths2423f662007-04-11 02:15:08 +00004350 rn = "EntryHi";
4351 break;
ths7a387ff2006-12-06 20:17:30 +00004352 default:
4353 goto die;
ths1579a722007-04-05 23:16:25 +00004354 }
ths873eb012006-12-06 17:59:07 +00004355 break;
4356 case 11:
ths7a387ff2006-12-06 20:17:30 +00004357 switch (sel) {
4358 case 0:
Andreas Färber7db13fa2012-03-14 01:38:22 +01004359 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Compare));
ths2423f662007-04-11 02:15:08 +00004360 rn = "Compare";
4361 break;
4362 /* 6,7 are implementation dependent */
ths7a387ff2006-12-06 20:17:30 +00004363 default:
4364 goto die;
ths2423f662007-04-11 02:15:08 +00004365 }
ths873eb012006-12-06 17:59:07 +00004366 break;
4367 case 12:
ths7a387ff2006-12-06 20:17:30 +00004368 switch (sel) {
4369 case 0:
Andreas Färber7db13fa2012-03-14 01:38:22 +01004370 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Status));
ths2423f662007-04-11 02:15:08 +00004371 rn = "Status";
4372 break;
ths7a387ff2006-12-06 20:17:30 +00004373 case 1:
Aurelien Jarnod75c1352013-01-01 18:02:22 +01004374 check_insn(ctx, ISA_MIPS32R2);
Andreas Färber7db13fa2012-03-14 01:38:22 +01004375 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_IntCtl));
ths2423f662007-04-11 02:15:08 +00004376 rn = "IntCtl";
4377 break;
ths7a387ff2006-12-06 20:17:30 +00004378 case 2:
Aurelien Jarnod75c1352013-01-01 18:02:22 +01004379 check_insn(ctx, ISA_MIPS32R2);
Andreas Färber7db13fa2012-03-14 01:38:22 +01004380 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSCtl));
ths2423f662007-04-11 02:15:08 +00004381 rn = "SRSCtl";
4382 break;
ths7a387ff2006-12-06 20:17:30 +00004383 case 3:
Aurelien Jarnod75c1352013-01-01 18:02:22 +01004384 check_insn(ctx, ISA_MIPS32R2);
Andreas Färber7db13fa2012-03-14 01:38:22 +01004385 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
ths2423f662007-04-11 02:15:08 +00004386 rn = "SRSMap";
thsfd88b6a2007-05-23 08:24:25 +00004387 break;
ths7a387ff2006-12-06 20:17:30 +00004388 default:
4389 goto die;
4390 }
ths873eb012006-12-06 17:59:07 +00004391 break;
4392 case 13:
ths7a387ff2006-12-06 20:17:30 +00004393 switch (sel) {
4394 case 0:
Andreas Färber7db13fa2012-03-14 01:38:22 +01004395 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Cause));
ths2423f662007-04-11 02:15:08 +00004396 rn = "Cause";
4397 break;
ths7a387ff2006-12-06 20:17:30 +00004398 default:
4399 goto die;
4400 }
ths873eb012006-12-06 17:59:07 +00004401 break;
4402 case 14:
ths7a387ff2006-12-06 20:17:30 +00004403 switch (sel) {
4404 case 0:
Andreas Färber7db13fa2012-03-14 01:38:22 +01004405 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EPC));
aurel32d9bea112009-04-15 14:41:44 +00004406 tcg_gen_ext32s_tl(arg, arg);
ths2423f662007-04-11 02:15:08 +00004407 rn = "EPC";
4408 break;
ths7a387ff2006-12-06 20:17:30 +00004409 default:
4410 goto die;
ths1579a722007-04-05 23:16:25 +00004411 }
ths873eb012006-12-06 17:59:07 +00004412 break;
4413 case 15:
ths7a387ff2006-12-06 20:17:30 +00004414 switch (sel) {
4415 case 0:
Andreas Färber7db13fa2012-03-14 01:38:22 +01004416 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PRid));
ths2423f662007-04-11 02:15:08 +00004417 rn = "PRid";
4418 break;
ths7a387ff2006-12-06 20:17:30 +00004419 case 1:
Aurelien Jarnod75c1352013-01-01 18:02:22 +01004420 check_insn(ctx, ISA_MIPS32R2);
Andreas Färber7db13fa2012-03-14 01:38:22 +01004421 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_EBase));
ths2423f662007-04-11 02:15:08 +00004422 rn = "EBase";
4423 break;
ths7a387ff2006-12-06 20:17:30 +00004424 default:
4425 goto die;
4426 }
ths873eb012006-12-06 17:59:07 +00004427 break;
4428 case 16:
4429 switch (sel) {
4430 case 0:
Andreas Färber7db13fa2012-03-14 01:38:22 +01004431 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config0));
ths873eb012006-12-06 17:59:07 +00004432 rn = "Config";
4433 break;
4434 case 1:
Andreas Färber7db13fa2012-03-14 01:38:22 +01004435 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config1));
ths873eb012006-12-06 17:59:07 +00004436 rn = "Config1";
4437 break;
ths7a387ff2006-12-06 20:17:30 +00004438 case 2:
Andreas Färber7db13fa2012-03-14 01:38:22 +01004439 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config2));
ths7a387ff2006-12-06 20:17:30 +00004440 rn = "Config2";
4441 break;
4442 case 3:
Andreas Färber7db13fa2012-03-14 01:38:22 +01004443 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config3));
ths7a387ff2006-12-06 20:17:30 +00004444 rn = "Config3";
4445 break;
thse397ee32007-03-23 00:43:28 +00004446 /* 4,5 are reserved */
4447 /* 6,7 are implementation dependent */
4448 case 6:
Andreas Färber7db13fa2012-03-14 01:38:22 +01004449 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config6));
thse397ee32007-03-23 00:43:28 +00004450 rn = "Config6";
4451 break;
4452 case 7:
Andreas Färber7db13fa2012-03-14 01:38:22 +01004453 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config7));
thse397ee32007-03-23 00:43:28 +00004454 rn = "Config7";
4455 break;
ths873eb012006-12-06 17:59:07 +00004456 default:
ths873eb012006-12-06 17:59:07 +00004457 goto die;
4458 }
4459 break;
4460 case 17:
ths7a387ff2006-12-06 20:17:30 +00004461 switch (sel) {
4462 case 0:
Blue Swirl895c2d02012-09-02 14:52:59 +00004463 gen_helper_mfc0_lladdr(arg, cpu_env);
ths2423f662007-04-11 02:15:08 +00004464 rn = "LLAddr";
4465 break;
ths7a387ff2006-12-06 20:17:30 +00004466 default:
4467 goto die;
4468 }
ths873eb012006-12-06 17:59:07 +00004469 break;
4470 case 18:
ths7a387ff2006-12-06 20:17:30 +00004471 switch (sel) {
thsfd88b6a2007-05-23 08:24:25 +00004472 case 0 ... 7:
Blue Swirl895c2d02012-09-02 14:52:59 +00004473 gen_helper_1e0i(mfc0_watchlo, arg, sel);
ths2423f662007-04-11 02:15:08 +00004474 rn = "WatchLo";
4475 break;
ths7a387ff2006-12-06 20:17:30 +00004476 default:
4477 goto die;
4478 }
ths873eb012006-12-06 17:59:07 +00004479 break;
4480 case 19:
ths7a387ff2006-12-06 20:17:30 +00004481 switch (sel) {
thsfd88b6a2007-05-23 08:24:25 +00004482 case 0 ...7:
Blue Swirl895c2d02012-09-02 14:52:59 +00004483 gen_helper_1e0i(mfc0_watchhi, arg, sel);
ths2423f662007-04-11 02:15:08 +00004484 rn = "WatchHi";
4485 break;
ths7a387ff2006-12-06 20:17:30 +00004486 default:
4487 goto die;
4488 }
ths873eb012006-12-06 17:59:07 +00004489 break;
ths8c0fdd82006-12-06 18:19:33 +00004490 case 20:
ths7a387ff2006-12-06 20:17:30 +00004491 switch (sel) {
4492 case 0:
thsd26bc212007-11-08 18:05:37 +00004493#if defined(TARGET_MIPS64)
Aurelien Jarnod75c1352013-01-01 18:02:22 +01004494 check_insn(ctx, ISA_MIPS3);
Andreas Färber7db13fa2012-03-14 01:38:22 +01004495 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_XContext));
aurel32d9bea112009-04-15 14:41:44 +00004496 tcg_gen_ext32s_tl(arg, arg);
ths2423f662007-04-11 02:15:08 +00004497 rn = "XContext";
4498 break;
ths703eaf32007-05-13 14:42:18 +00004499#endif
ths7a387ff2006-12-06 20:17:30 +00004500 default:
4501 goto die;
4502 }
ths8c0fdd82006-12-06 18:19:33 +00004503 break;
4504 case 21:
ths7a387ff2006-12-06 20:17:30 +00004505 /* Officially reserved, but sel 0 is used for R1x000 framemask */
4506 switch (sel) {
4507 case 0:
Andreas Färber7db13fa2012-03-14 01:38:22 +01004508 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Framemask));
ths2423f662007-04-11 02:15:08 +00004509 rn = "Framemask";
4510 break;
ths7a387ff2006-12-06 20:17:30 +00004511 default:
4512 goto die;
4513 }
ths8c0fdd82006-12-06 18:19:33 +00004514 break;
4515 case 22:
aurel32d9bea112009-04-15 14:41:44 +00004516 tcg_gen_movi_tl(arg, 0); /* unimplemented */
ths2423f662007-04-11 02:15:08 +00004517 rn = "'Diagnostic"; /* implementation dependent */
4518 break;
ths873eb012006-12-06 17:59:07 +00004519 case 23:
ths7a387ff2006-12-06 20:17:30 +00004520 switch (sel) {
4521 case 0:
Blue Swirl895c2d02012-09-02 14:52:59 +00004522 gen_helper_mfc0_debug(arg, cpu_env); /* EJTAG support */
ths2423f662007-04-11 02:15:08 +00004523 rn = "Debug";
4524 break;
ths7a387ff2006-12-06 20:17:30 +00004525 case 1:
aurel32d9bea112009-04-15 14:41:44 +00004526// gen_helper_mfc0_tracecontrol(arg); /* PDtrace support */
ths2423f662007-04-11 02:15:08 +00004527 rn = "TraceControl";
4528// break;
ths7a387ff2006-12-06 20:17:30 +00004529 case 2:
aurel32d9bea112009-04-15 14:41:44 +00004530// gen_helper_mfc0_tracecontrol2(arg); /* PDtrace support */
ths2423f662007-04-11 02:15:08 +00004531 rn = "TraceControl2";
4532// break;
ths7a387ff2006-12-06 20:17:30 +00004533 case 3:
aurel32d9bea112009-04-15 14:41:44 +00004534// gen_helper_mfc0_usertracedata(arg); /* PDtrace support */
ths2423f662007-04-11 02:15:08 +00004535 rn = "UserTraceData";
4536// break;
ths7a387ff2006-12-06 20:17:30 +00004537 case 4:
aurel32d9bea112009-04-15 14:41:44 +00004538// gen_helper_mfc0_tracebpc(arg); /* PDtrace support */
ths2423f662007-04-11 02:15:08 +00004539 rn = "TraceBPC";
4540// break;
ths7a387ff2006-12-06 20:17:30 +00004541 default:
4542 goto die;
4543 }
ths873eb012006-12-06 17:59:07 +00004544 break;
4545 case 24:
ths7a387ff2006-12-06 20:17:30 +00004546 switch (sel) {
4547 case 0:
thsf0b3f3a2008-05-23 18:10:51 +00004548 /* EJTAG support */
Andreas Färber7db13fa2012-03-14 01:38:22 +01004549 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_DEPC));
aurel32d9bea112009-04-15 14:41:44 +00004550 tcg_gen_ext32s_tl(arg, arg);
ths2423f662007-04-11 02:15:08 +00004551 rn = "DEPC";
4552 break;
ths7a387ff2006-12-06 20:17:30 +00004553 default:
4554 goto die;
4555 }
ths873eb012006-12-06 17:59:07 +00004556 break;
ths8c0fdd82006-12-06 18:19:33 +00004557 case 25:
ths7a387ff2006-12-06 20:17:30 +00004558 switch (sel) {
4559 case 0:
Andreas Färber7db13fa2012-03-14 01:38:22 +01004560 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Performance0));
ths2423f662007-04-11 02:15:08 +00004561 rn = "Performance0";
ths7a387ff2006-12-06 20:17:30 +00004562 break;
4563 case 1:
aurel32d9bea112009-04-15 14:41:44 +00004564// gen_helper_mfc0_performance1(arg);
ths2423f662007-04-11 02:15:08 +00004565 rn = "Performance1";
4566// break;
ths7a387ff2006-12-06 20:17:30 +00004567 case 2:
aurel32d9bea112009-04-15 14:41:44 +00004568// gen_helper_mfc0_performance2(arg);
ths2423f662007-04-11 02:15:08 +00004569 rn = "Performance2";
4570// break;
ths7a387ff2006-12-06 20:17:30 +00004571 case 3:
aurel32d9bea112009-04-15 14:41:44 +00004572// gen_helper_mfc0_performance3(arg);
ths2423f662007-04-11 02:15:08 +00004573 rn = "Performance3";
4574// break;
ths7a387ff2006-12-06 20:17:30 +00004575 case 4:
aurel32d9bea112009-04-15 14:41:44 +00004576// gen_helper_mfc0_performance4(arg);
ths2423f662007-04-11 02:15:08 +00004577 rn = "Performance4";
4578// break;
ths7a387ff2006-12-06 20:17:30 +00004579 case 5:
aurel32d9bea112009-04-15 14:41:44 +00004580// gen_helper_mfc0_performance5(arg);
ths2423f662007-04-11 02:15:08 +00004581 rn = "Performance5";
4582// break;
ths7a387ff2006-12-06 20:17:30 +00004583 case 6:
aurel32d9bea112009-04-15 14:41:44 +00004584// gen_helper_mfc0_performance6(arg);
ths2423f662007-04-11 02:15:08 +00004585 rn = "Performance6";
4586// break;
ths7a387ff2006-12-06 20:17:30 +00004587 case 7:
aurel32d9bea112009-04-15 14:41:44 +00004588// gen_helper_mfc0_performance7(arg);
ths2423f662007-04-11 02:15:08 +00004589 rn = "Performance7";
4590// break;
ths7a387ff2006-12-06 20:17:30 +00004591 default:
4592 goto die;
4593 }
ths8c0fdd82006-12-06 18:19:33 +00004594 break;
4595 case 26:
aurel32d9bea112009-04-15 14:41:44 +00004596 tcg_gen_movi_tl(arg, 0); /* unimplemented */
aurel32da806822008-11-15 12:12:08 +00004597 rn = "ECC";
4598 break;
ths8c0fdd82006-12-06 18:19:33 +00004599 case 27:
ths7a387ff2006-12-06 20:17:30 +00004600 switch (sel) {
ths7a387ff2006-12-06 20:17:30 +00004601 case 0 ... 3:
aurel32d9bea112009-04-15 14:41:44 +00004602 tcg_gen_movi_tl(arg, 0); /* unimplemented */
ths2423f662007-04-11 02:15:08 +00004603 rn = "CacheErr";
4604 break;
ths7a387ff2006-12-06 20:17:30 +00004605 default:
4606 goto die;
4607 }
ths8c0fdd82006-12-06 18:19:33 +00004608 break;
ths873eb012006-12-06 17:59:07 +00004609 case 28:
4610 switch (sel) {
4611 case 0:
ths7a387ff2006-12-06 20:17:30 +00004612 case 2:
4613 case 4:
4614 case 6:
Andreas Färber7db13fa2012-03-14 01:38:22 +01004615 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_TagLo));
ths873eb012006-12-06 17:59:07 +00004616 rn = "TagLo";
4617 break;
4618 case 1:
ths7a387ff2006-12-06 20:17:30 +00004619 case 3:
4620 case 5:
4621 case 7:
Andreas Färber7db13fa2012-03-14 01:38:22 +01004622 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataLo));
ths873eb012006-12-06 17:59:07 +00004623 rn = "DataLo";
4624 break;
4625 default:
ths873eb012006-12-06 17:59:07 +00004626 goto die;
4627 }
4628 break;
ths8c0fdd82006-12-06 18:19:33 +00004629 case 29:
ths7a387ff2006-12-06 20:17:30 +00004630 switch (sel) {
4631 case 0:
4632 case 2:
4633 case 4:
4634 case 6:
Andreas Färber7db13fa2012-03-14 01:38:22 +01004635 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_TagHi));
ths7a387ff2006-12-06 20:17:30 +00004636 rn = "TagHi";
4637 break;
4638 case 1:
4639 case 3:
4640 case 5:
4641 case 7:
Andreas Färber7db13fa2012-03-14 01:38:22 +01004642 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataHi));
ths7a387ff2006-12-06 20:17:30 +00004643 rn = "DataHi";
4644 break;
4645 default:
4646 goto die;
4647 }
ths8c0fdd82006-12-06 18:19:33 +00004648 break;
ths873eb012006-12-06 17:59:07 +00004649 case 30:
ths7a387ff2006-12-06 20:17:30 +00004650 switch (sel) {
4651 case 0:
Andreas Färber7db13fa2012-03-14 01:38:22 +01004652 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_ErrorEPC));
aurel32d9bea112009-04-15 14:41:44 +00004653 tcg_gen_ext32s_tl(arg, arg);
ths2423f662007-04-11 02:15:08 +00004654 rn = "ErrorEPC";
4655 break;
ths7a387ff2006-12-06 20:17:30 +00004656 default:
4657 goto die;
4658 }
ths873eb012006-12-06 17:59:07 +00004659 break;
4660 case 31:
ths7a387ff2006-12-06 20:17:30 +00004661 switch (sel) {
4662 case 0:
thsf0b3f3a2008-05-23 18:10:51 +00004663 /* EJTAG support */
Andreas Färber7db13fa2012-03-14 01:38:22 +01004664 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
ths2423f662007-04-11 02:15:08 +00004665 rn = "DESAVE";
4666 break;
ths7a387ff2006-12-06 20:17:30 +00004667 default:
4668 goto die;
4669 }
ths873eb012006-12-06 17:59:07 +00004670 break;
4671 default:
ths873eb012006-12-06 17:59:07 +00004672 goto die;
4673 }
Blue Swirl2abf3142010-10-13 18:38:08 +00004674 (void)rn; /* avoid a compiler warning */
aliguorid12d51d2009-01-15 21:48:06 +00004675 LOG_DISAS("mfc0 %s (reg %d sel %d)\n", rn, reg, sel);
ths873eb012006-12-06 17:59:07 +00004676 return;
4677
4678die:
aliguorid12d51d2009-01-15 21:48:06 +00004679 LOG_DISAS("mfc0 %s (reg %d sel %d)\n", rn, reg, sel);
ths873eb012006-12-06 17:59:07 +00004680 generate_exception(ctx, EXCP_RI);
4681}
4682
Aurelien Jarnod75c1352013-01-01 18:02:22 +01004683static void gen_mtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
ths8c0fdd82006-12-06 18:19:33 +00004684{
ths7a387ff2006-12-06 20:17:30 +00004685 const char *rn = "invalid";
ths8c0fdd82006-12-06 18:19:33 +00004686
thse189e742007-09-24 12:48:00 +00004687 if (sel != 0)
Aurelien Jarnod75c1352013-01-01 18:02:22 +01004688 check_insn(ctx, ISA_MIPS32);
thse189e742007-09-24 12:48:00 +00004689
pbrook2e70f6e2008-06-29 01:03:05 +00004690 if (use_icount)
4691 gen_io_start();
4692
ths8c0fdd82006-12-06 18:19:33 +00004693 switch (reg) {
4694 case 0:
ths7a387ff2006-12-06 20:17:30 +00004695 switch (sel) {
4696 case 0:
Blue Swirl895c2d02012-09-02 14:52:59 +00004697 gen_helper_mtc0_index(cpu_env, arg);
ths7a387ff2006-12-06 20:17:30 +00004698 rn = "Index";
4699 break;
4700 case 1:
Aurelien Jarnod75c1352013-01-01 18:02:22 +01004701 check_insn(ctx, ASE_MT);
Blue Swirl895c2d02012-09-02 14:52:59 +00004702 gen_helper_mtc0_mvpcontrol(cpu_env, arg);
ths7a387ff2006-12-06 20:17:30 +00004703 rn = "MVPControl";
thsead93602007-09-06 00:18:15 +00004704 break;
ths7a387ff2006-12-06 20:17:30 +00004705 case 2:
Aurelien Jarnod75c1352013-01-01 18:02:22 +01004706 check_insn(ctx, ASE_MT);
thsead93602007-09-06 00:18:15 +00004707 /* ignored */
ths7a387ff2006-12-06 20:17:30 +00004708 rn = "MVPConf0";
thsead93602007-09-06 00:18:15 +00004709 break;
ths7a387ff2006-12-06 20:17:30 +00004710 case 3:
Aurelien Jarnod75c1352013-01-01 18:02:22 +01004711 check_insn(ctx, ASE_MT);
thsead93602007-09-06 00:18:15 +00004712 /* ignored */
ths7a387ff2006-12-06 20:17:30 +00004713 rn = "MVPConf1";
thsead93602007-09-06 00:18:15 +00004714 break;
ths7a387ff2006-12-06 20:17:30 +00004715 default:
4716 goto die;
4717 }
ths8c0fdd82006-12-06 18:19:33 +00004718 break;
4719 case 1:
ths7a387ff2006-12-06 20:17:30 +00004720 switch (sel) {
4721 case 0:
ths2423f662007-04-11 02:15:08 +00004722 /* ignored */
ths7a387ff2006-12-06 20:17:30 +00004723 rn = "Random";
ths2423f662007-04-11 02:15:08 +00004724 break;
ths7a387ff2006-12-06 20:17:30 +00004725 case 1:
Aurelien Jarnod75c1352013-01-01 18:02:22 +01004726 check_insn(ctx, ASE_MT);
Blue Swirl895c2d02012-09-02 14:52:59 +00004727 gen_helper_mtc0_vpecontrol(cpu_env, arg);
ths7a387ff2006-12-06 20:17:30 +00004728 rn = "VPEControl";
thsead93602007-09-06 00:18:15 +00004729 break;
ths7a387ff2006-12-06 20:17:30 +00004730 case 2:
Aurelien Jarnod75c1352013-01-01 18:02:22 +01004731 check_insn(ctx, ASE_MT);
Blue Swirl895c2d02012-09-02 14:52:59 +00004732 gen_helper_mtc0_vpeconf0(cpu_env, arg);
ths7a387ff2006-12-06 20:17:30 +00004733 rn = "VPEConf0";
thsead93602007-09-06 00:18:15 +00004734 break;
ths7a387ff2006-12-06 20:17:30 +00004735 case 3:
Aurelien Jarnod75c1352013-01-01 18:02:22 +01004736 check_insn(ctx, ASE_MT);
Blue Swirl895c2d02012-09-02 14:52:59 +00004737 gen_helper_mtc0_vpeconf1(cpu_env, arg);
ths7a387ff2006-12-06 20:17:30 +00004738 rn = "VPEConf1";
thsead93602007-09-06 00:18:15 +00004739 break;
ths7a387ff2006-12-06 20:17:30 +00004740 case 4:
Aurelien Jarnod75c1352013-01-01 18:02:22 +01004741 check_insn(ctx, ASE_MT);
Blue Swirl895c2d02012-09-02 14:52:59 +00004742 gen_helper_mtc0_yqmask(cpu_env, arg);
ths7a387ff2006-12-06 20:17:30 +00004743 rn = "YQMask";
thsead93602007-09-06 00:18:15 +00004744 break;
ths7a387ff2006-12-06 20:17:30 +00004745 case 5:
Aurelien Jarnod75c1352013-01-01 18:02:22 +01004746 check_insn(ctx, ASE_MT);
Andreas Färber7db13fa2012-03-14 01:38:22 +01004747 gen_mtc0_store64(arg, offsetof(CPUMIPSState, CP0_VPESchedule));
ths7a387ff2006-12-06 20:17:30 +00004748 rn = "VPESchedule";
thsead93602007-09-06 00:18:15 +00004749 break;
ths7a387ff2006-12-06 20:17:30 +00004750 case 6:
Aurelien Jarnod75c1352013-01-01 18:02:22 +01004751 check_insn(ctx, ASE_MT);
Andreas Färber7db13fa2012-03-14 01:38:22 +01004752 gen_mtc0_store64(arg, offsetof(CPUMIPSState, CP0_VPEScheFBack));
ths7a387ff2006-12-06 20:17:30 +00004753 rn = "VPEScheFBack";
thsead93602007-09-06 00:18:15 +00004754 break;
ths7a387ff2006-12-06 20:17:30 +00004755 case 7:
Aurelien Jarnod75c1352013-01-01 18:02:22 +01004756 check_insn(ctx, ASE_MT);
Blue Swirl895c2d02012-09-02 14:52:59 +00004757 gen_helper_mtc0_vpeopt(cpu_env, arg);
ths7a387ff2006-12-06 20:17:30 +00004758 rn = "VPEOpt";
thsead93602007-09-06 00:18:15 +00004759 break;
ths7a387ff2006-12-06 20:17:30 +00004760 default:
4761 goto die;
4762 }
ths8c0fdd82006-12-06 18:19:33 +00004763 break;
4764 case 2:
ths7a387ff2006-12-06 20:17:30 +00004765 switch (sel) {
4766 case 0:
Blue Swirl895c2d02012-09-02 14:52:59 +00004767 gen_helper_mtc0_entrylo0(cpu_env, arg);
ths2423f662007-04-11 02:15:08 +00004768 rn = "EntryLo0";
4769 break;
ths7a387ff2006-12-06 20:17:30 +00004770 case 1:
Aurelien Jarnod75c1352013-01-01 18:02:22 +01004771 check_insn(ctx, ASE_MT);
Blue Swirl895c2d02012-09-02 14:52:59 +00004772 gen_helper_mtc0_tcstatus(cpu_env, arg);
ths2423f662007-04-11 02:15:08 +00004773 rn = "TCStatus";
thsead93602007-09-06 00:18:15 +00004774 break;
ths7a387ff2006-12-06 20:17:30 +00004775 case 2:
Aurelien Jarnod75c1352013-01-01 18:02:22 +01004776 check_insn(ctx, ASE_MT);
Blue Swirl895c2d02012-09-02 14:52:59 +00004777 gen_helper_mtc0_tcbind(cpu_env, arg);
ths2423f662007-04-11 02:15:08 +00004778 rn = "TCBind";
thsead93602007-09-06 00:18:15 +00004779 break;
ths7a387ff2006-12-06 20:17:30 +00004780 case 3:
Aurelien Jarnod75c1352013-01-01 18:02:22 +01004781 check_insn(ctx, ASE_MT);
Blue Swirl895c2d02012-09-02 14:52:59 +00004782 gen_helper_mtc0_tcrestart(cpu_env, arg);
ths2423f662007-04-11 02:15:08 +00004783 rn = "TCRestart";
thsead93602007-09-06 00:18:15 +00004784 break;
ths7a387ff2006-12-06 20:17:30 +00004785 case 4:
Aurelien Jarnod75c1352013-01-01 18:02:22 +01004786 check_insn(ctx, ASE_MT);
Blue Swirl895c2d02012-09-02 14:52:59 +00004787 gen_helper_mtc0_tchalt(cpu_env, arg);
ths2423f662007-04-11 02:15:08 +00004788 rn = "TCHalt";
thsead93602007-09-06 00:18:15 +00004789 break;
ths7a387ff2006-12-06 20:17:30 +00004790 case 5:
Aurelien Jarnod75c1352013-01-01 18:02:22 +01004791 check_insn(ctx, ASE_MT);
Blue Swirl895c2d02012-09-02 14:52:59 +00004792 gen_helper_mtc0_tccontext(cpu_env, arg);
ths2423f662007-04-11 02:15:08 +00004793 rn = "TCContext";
thsead93602007-09-06 00:18:15 +00004794 break;
ths7a387ff2006-12-06 20:17:30 +00004795 case 6:
Aurelien Jarnod75c1352013-01-01 18:02:22 +01004796 check_insn(ctx, ASE_MT);
Blue Swirl895c2d02012-09-02 14:52:59 +00004797 gen_helper_mtc0_tcschedule(cpu_env, arg);
ths2423f662007-04-11 02:15:08 +00004798 rn = "TCSchedule";
thsead93602007-09-06 00:18:15 +00004799 break;
ths7a387ff2006-12-06 20:17:30 +00004800 case 7:
Aurelien Jarnod75c1352013-01-01 18:02:22 +01004801 check_insn(ctx, ASE_MT);
Blue Swirl895c2d02012-09-02 14:52:59 +00004802 gen_helper_mtc0_tcschefback(cpu_env, arg);
ths2423f662007-04-11 02:15:08 +00004803 rn = "TCScheFBack";
thsead93602007-09-06 00:18:15 +00004804 break;
ths7a387ff2006-12-06 20:17:30 +00004805 default:
4806 goto die;
4807 }
ths8c0fdd82006-12-06 18:19:33 +00004808 break;
4809 case 3:
ths7a387ff2006-12-06 20:17:30 +00004810 switch (sel) {
4811 case 0:
Blue Swirl895c2d02012-09-02 14:52:59 +00004812 gen_helper_mtc0_entrylo1(cpu_env, arg);
ths2423f662007-04-11 02:15:08 +00004813 rn = "EntryLo1";
4814 break;
ths7a387ff2006-12-06 20:17:30 +00004815 default:
4816 goto die;
ths876d4b02007-04-04 21:07:17 +00004817 }
ths8c0fdd82006-12-06 18:19:33 +00004818 break;
4819 case 4:
ths7a387ff2006-12-06 20:17:30 +00004820 switch (sel) {
4821 case 0:
Blue Swirl895c2d02012-09-02 14:52:59 +00004822 gen_helper_mtc0_context(cpu_env, arg);
ths2423f662007-04-11 02:15:08 +00004823 rn = "Context";
4824 break;
ths7a387ff2006-12-06 20:17:30 +00004825 case 1:
Blue Swirl895c2d02012-09-02 14:52:59 +00004826// gen_helper_mtc0_contextconfig(cpu_env, arg); /* SmartMIPS ASE */
ths2423f662007-04-11 02:15:08 +00004827 rn = "ContextConfig";
4828// break;
ths7a387ff2006-12-06 20:17:30 +00004829 default:
4830 goto die;
ths876d4b02007-04-04 21:07:17 +00004831 }
ths8c0fdd82006-12-06 18:19:33 +00004832 break;
4833 case 5:
ths7a387ff2006-12-06 20:17:30 +00004834 switch (sel) {
4835 case 0:
Blue Swirl895c2d02012-09-02 14:52:59 +00004836 gen_helper_mtc0_pagemask(cpu_env, arg);
ths2423f662007-04-11 02:15:08 +00004837 rn = "PageMask";
4838 break;
ths7a387ff2006-12-06 20:17:30 +00004839 case 1:
Aurelien Jarnod75c1352013-01-01 18:02:22 +01004840 check_insn(ctx, ISA_MIPS32R2);
Blue Swirl895c2d02012-09-02 14:52:59 +00004841 gen_helper_mtc0_pagegrain(cpu_env, arg);
ths2423f662007-04-11 02:15:08 +00004842 rn = "PageGrain";
4843 break;
ths7a387ff2006-12-06 20:17:30 +00004844 default:
4845 goto die;
ths876d4b02007-04-04 21:07:17 +00004846 }
ths8c0fdd82006-12-06 18:19:33 +00004847 break;
4848 case 6:
ths7a387ff2006-12-06 20:17:30 +00004849 switch (sel) {
4850 case 0:
Blue Swirl895c2d02012-09-02 14:52:59 +00004851 gen_helper_mtc0_wired(cpu_env, arg);
ths2423f662007-04-11 02:15:08 +00004852 rn = "Wired";
4853 break;
ths7a387ff2006-12-06 20:17:30 +00004854 case 1:
Aurelien Jarnod75c1352013-01-01 18:02:22 +01004855 check_insn(ctx, ISA_MIPS32R2);
Blue Swirl895c2d02012-09-02 14:52:59 +00004856 gen_helper_mtc0_srsconf0(cpu_env, arg);
ths2423f662007-04-11 02:15:08 +00004857 rn = "SRSConf0";
thsead93602007-09-06 00:18:15 +00004858 break;
ths7a387ff2006-12-06 20:17:30 +00004859 case 2:
Aurelien Jarnod75c1352013-01-01 18:02:22 +01004860 check_insn(ctx, ISA_MIPS32R2);
Blue Swirl895c2d02012-09-02 14:52:59 +00004861 gen_helper_mtc0_srsconf1(cpu_env, arg);
ths2423f662007-04-11 02:15:08 +00004862 rn = "SRSConf1";
thsead93602007-09-06 00:18:15 +00004863 break;
ths7a387ff2006-12-06 20:17:30 +00004864 case 3:
Aurelien Jarnod75c1352013-01-01 18:02:22 +01004865 check_insn(ctx, ISA_MIPS32R2);
Blue Swirl895c2d02012-09-02 14:52:59 +00004866 gen_helper_mtc0_srsconf2(cpu_env, arg);
ths2423f662007-04-11 02:15:08 +00004867 rn = "SRSConf2";
thsead93602007-09-06 00:18:15 +00004868 break;
ths7a387ff2006-12-06 20:17:30 +00004869 case 4:
Aurelien Jarnod75c1352013-01-01 18:02:22 +01004870 check_insn(ctx, ISA_MIPS32R2);
Blue Swirl895c2d02012-09-02 14:52:59 +00004871 gen_helper_mtc0_srsconf3(cpu_env, arg);
ths2423f662007-04-11 02:15:08 +00004872 rn = "SRSConf3";
thsead93602007-09-06 00:18:15 +00004873 break;
ths7a387ff2006-12-06 20:17:30 +00004874 case 5:
Aurelien Jarnod75c1352013-01-01 18:02:22 +01004875 check_insn(ctx, ISA_MIPS32R2);
Blue Swirl895c2d02012-09-02 14:52:59 +00004876 gen_helper_mtc0_srsconf4(cpu_env, arg);
ths2423f662007-04-11 02:15:08 +00004877 rn = "SRSConf4";
thsead93602007-09-06 00:18:15 +00004878 break;
ths7a387ff2006-12-06 20:17:30 +00004879 default:
4880 goto die;
ths876d4b02007-04-04 21:07:17 +00004881 }
ths8c0fdd82006-12-06 18:19:33 +00004882 break;
4883 case 7:
ths7a387ff2006-12-06 20:17:30 +00004884 switch (sel) {
4885 case 0:
Aurelien Jarnod75c1352013-01-01 18:02:22 +01004886 check_insn(ctx, ISA_MIPS32R2);
Blue Swirl895c2d02012-09-02 14:52:59 +00004887 gen_helper_mtc0_hwrena(cpu_env, arg);
ths2423f662007-04-11 02:15:08 +00004888 rn = "HWREna";
4889 break;
ths7a387ff2006-12-06 20:17:30 +00004890 default:
4891 goto die;
ths876d4b02007-04-04 21:07:17 +00004892 }
ths8c0fdd82006-12-06 18:19:33 +00004893 break;
4894 case 8:
ths7a387ff2006-12-06 20:17:30 +00004895 /* ignored */
thsf0b3f3a2008-05-23 18:10:51 +00004896 rn = "BadVAddr";
ths8c0fdd82006-12-06 18:19:33 +00004897 break;
4898 case 9:
ths7a387ff2006-12-06 20:17:30 +00004899 switch (sel) {
4900 case 0:
Blue Swirl895c2d02012-09-02 14:52:59 +00004901 gen_helper_mtc0_count(cpu_env, arg);
ths2423f662007-04-11 02:15:08 +00004902 rn = "Count";
4903 break;
ths876d4b02007-04-04 21:07:17 +00004904 /* 6,7 are implementation dependent */
ths7a387ff2006-12-06 20:17:30 +00004905 default:
4906 goto die;
ths876d4b02007-04-04 21:07:17 +00004907 }
ths8c0fdd82006-12-06 18:19:33 +00004908 break;
4909 case 10:
ths7a387ff2006-12-06 20:17:30 +00004910 switch (sel) {
4911 case 0:
Blue Swirl895c2d02012-09-02 14:52:59 +00004912 gen_helper_mtc0_entryhi(cpu_env, arg);
ths2423f662007-04-11 02:15:08 +00004913 rn = "EntryHi";
4914 break;
ths7a387ff2006-12-06 20:17:30 +00004915 default:
4916 goto die;
ths876d4b02007-04-04 21:07:17 +00004917 }
ths8c0fdd82006-12-06 18:19:33 +00004918 break;
4919 case 11:
ths7a387ff2006-12-06 20:17:30 +00004920 switch (sel) {
4921 case 0:
Blue Swirl895c2d02012-09-02 14:52:59 +00004922 gen_helper_mtc0_compare(cpu_env, arg);
ths2423f662007-04-11 02:15:08 +00004923 rn = "Compare";
4924 break;
4925 /* 6,7 are implementation dependent */
ths7a387ff2006-12-06 20:17:30 +00004926 default:
4927 goto die;
ths876d4b02007-04-04 21:07:17 +00004928 }
ths8c0fdd82006-12-06 18:19:33 +00004929 break;
4930 case 12:
ths7a387ff2006-12-06 20:17:30 +00004931 switch (sel) {
4932 case 0:
aurel32867abc72009-04-13 08:53:12 +00004933 save_cpu_state(ctx, 1);
Blue Swirl895c2d02012-09-02 14:52:59 +00004934 gen_helper_mtc0_status(cpu_env, arg);
ths84873272007-06-01 17:47:07 +00004935 /* BS_STOP isn't good enough here, hflags may have changed. */
4936 gen_save_pc(ctx->pc + 4);
4937 ctx->bstate = BS_EXCP;
ths2423f662007-04-11 02:15:08 +00004938 rn = "Status";
4939 break;
ths7a387ff2006-12-06 20:17:30 +00004940 case 1:
Aurelien Jarnod75c1352013-01-01 18:02:22 +01004941 check_insn(ctx, ISA_MIPS32R2);
Blue Swirl895c2d02012-09-02 14:52:59 +00004942 gen_helper_mtc0_intctl(cpu_env, arg);
ths84873272007-06-01 17:47:07 +00004943 /* Stop translation as we may have switched the execution mode */
4944 ctx->bstate = BS_STOP;
ths2423f662007-04-11 02:15:08 +00004945 rn = "IntCtl";
4946 break;
ths7a387ff2006-12-06 20:17:30 +00004947 case 2:
Aurelien Jarnod75c1352013-01-01 18:02:22 +01004948 check_insn(ctx, ISA_MIPS32R2);
Blue Swirl895c2d02012-09-02 14:52:59 +00004949 gen_helper_mtc0_srsctl(cpu_env, arg);
ths84873272007-06-01 17:47:07 +00004950 /* Stop translation as we may have switched the execution mode */
4951 ctx->bstate = BS_STOP;
ths2423f662007-04-11 02:15:08 +00004952 rn = "SRSCtl";
4953 break;
ths7a387ff2006-12-06 20:17:30 +00004954 case 3:
Aurelien Jarnod75c1352013-01-01 18:02:22 +01004955 check_insn(ctx, ISA_MIPS32R2);
Andreas Färber7db13fa2012-03-14 01:38:22 +01004956 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
ths84873272007-06-01 17:47:07 +00004957 /* Stop translation as we may have switched the execution mode */
4958 ctx->bstate = BS_STOP;
ths2423f662007-04-11 02:15:08 +00004959 rn = "SRSMap";
thsfd88b6a2007-05-23 08:24:25 +00004960 break;
ths7a387ff2006-12-06 20:17:30 +00004961 default:
4962 goto die;
ths876d4b02007-04-04 21:07:17 +00004963 }
ths8c0fdd82006-12-06 18:19:33 +00004964 break;
4965 case 13:
ths7a387ff2006-12-06 20:17:30 +00004966 switch (sel) {
4967 case 0:
aurel32867abc72009-04-13 08:53:12 +00004968 save_cpu_state(ctx, 1);
Blue Swirl895c2d02012-09-02 14:52:59 +00004969 gen_helper_mtc0_cause(cpu_env, arg);
ths2423f662007-04-11 02:15:08 +00004970 rn = "Cause";
4971 break;
ths7a387ff2006-12-06 20:17:30 +00004972 default:
4973 goto die;
ths876d4b02007-04-04 21:07:17 +00004974 }
ths8c0fdd82006-12-06 18:19:33 +00004975 break;
4976 case 14:
ths7a387ff2006-12-06 20:17:30 +00004977 switch (sel) {
4978 case 0:
Andreas Färber7db13fa2012-03-14 01:38:22 +01004979 gen_mtc0_store64(arg, offsetof(CPUMIPSState, CP0_EPC));
ths2423f662007-04-11 02:15:08 +00004980 rn = "EPC";
4981 break;
ths7a387ff2006-12-06 20:17:30 +00004982 default:
4983 goto die;
ths876d4b02007-04-04 21:07:17 +00004984 }
ths8c0fdd82006-12-06 18:19:33 +00004985 break;
4986 case 15:
ths7a387ff2006-12-06 20:17:30 +00004987 switch (sel) {
4988 case 0:
ths2423f662007-04-11 02:15:08 +00004989 /* ignored */
4990 rn = "PRid";
4991 break;
ths7a387ff2006-12-06 20:17:30 +00004992 case 1:
Aurelien Jarnod75c1352013-01-01 18:02:22 +01004993 check_insn(ctx, ISA_MIPS32R2);
Blue Swirl895c2d02012-09-02 14:52:59 +00004994 gen_helper_mtc0_ebase(cpu_env, arg);
ths2423f662007-04-11 02:15:08 +00004995 rn = "EBase";
4996 break;
ths7a387ff2006-12-06 20:17:30 +00004997 default:
4998 goto die;
ths1579a722007-04-05 23:16:25 +00004999 }
ths8c0fdd82006-12-06 18:19:33 +00005000 break;
5001 case 16:
5002 switch (sel) {
5003 case 0:
Blue Swirl895c2d02012-09-02 14:52:59 +00005004 gen_helper_mtc0_config0(cpu_env, arg);
ths7a387ff2006-12-06 20:17:30 +00005005 rn = "Config";
ths2423f662007-04-11 02:15:08 +00005006 /* Stop translation as we may have switched the execution mode */
5007 ctx->bstate = BS_STOP;
ths8c0fdd82006-12-06 18:19:33 +00005008 break;
ths7a387ff2006-12-06 20:17:30 +00005009 case 1:
thse397ee32007-03-23 00:43:28 +00005010 /* ignored, read only */
ths7a387ff2006-12-06 20:17:30 +00005011 rn = "Config1";
5012 break;
5013 case 2:
Blue Swirl895c2d02012-09-02 14:52:59 +00005014 gen_helper_mtc0_config2(cpu_env, arg);
ths7a387ff2006-12-06 20:17:30 +00005015 rn = "Config2";
ths2423f662007-04-11 02:15:08 +00005016 /* Stop translation as we may have switched the execution mode */
5017 ctx->bstate = BS_STOP;
ths7a387ff2006-12-06 20:17:30 +00005018 break;
5019 case 3:
thse397ee32007-03-23 00:43:28 +00005020 /* ignored, read only */
ths7a387ff2006-12-06 20:17:30 +00005021 rn = "Config3";
5022 break;
thse397ee32007-03-23 00:43:28 +00005023 /* 4,5 are reserved */
5024 /* 6,7 are implementation dependent */
5025 case 6:
5026 /* ignored */
5027 rn = "Config6";
5028 break;
5029 case 7:
5030 /* ignored */
5031 rn = "Config7";
5032 break;
ths8c0fdd82006-12-06 18:19:33 +00005033 default:
5034 rn = "Invalid config selector";
5035 goto die;
5036 }
5037 break;
5038 case 17:
ths7a387ff2006-12-06 20:17:30 +00005039 switch (sel) {
5040 case 0:
Blue Swirl895c2d02012-09-02 14:52:59 +00005041 gen_helper_mtc0_lladdr(cpu_env, arg);
ths2423f662007-04-11 02:15:08 +00005042 rn = "LLAddr";
5043 break;
ths7a387ff2006-12-06 20:17:30 +00005044 default:
5045 goto die;
5046 }
ths8c0fdd82006-12-06 18:19:33 +00005047 break;
5048 case 18:
ths7a387ff2006-12-06 20:17:30 +00005049 switch (sel) {
thsfd88b6a2007-05-23 08:24:25 +00005050 case 0 ... 7:
Blue Swirl895c2d02012-09-02 14:52:59 +00005051 gen_helper_0e1i(mtc0_watchlo, arg, sel);
ths2423f662007-04-11 02:15:08 +00005052 rn = "WatchLo";
5053 break;
ths7a387ff2006-12-06 20:17:30 +00005054 default:
5055 goto die;
5056 }
ths8c0fdd82006-12-06 18:19:33 +00005057 break;
5058 case 19:
ths7a387ff2006-12-06 20:17:30 +00005059 switch (sel) {
thsfd88b6a2007-05-23 08:24:25 +00005060 case 0 ... 7:
Blue Swirl895c2d02012-09-02 14:52:59 +00005061 gen_helper_0e1i(mtc0_watchhi, arg, sel);
ths2423f662007-04-11 02:15:08 +00005062 rn = "WatchHi";
5063 break;
ths7a387ff2006-12-06 20:17:30 +00005064 default:
5065 goto die;
5066 }
ths8c0fdd82006-12-06 18:19:33 +00005067 break;
5068 case 20:
ths7a387ff2006-12-06 20:17:30 +00005069 switch (sel) {
5070 case 0:
thsd26bc212007-11-08 18:05:37 +00005071#if defined(TARGET_MIPS64)
Aurelien Jarnod75c1352013-01-01 18:02:22 +01005072 check_insn(ctx, ISA_MIPS3);
Blue Swirl895c2d02012-09-02 14:52:59 +00005073 gen_helper_mtc0_xcontext(cpu_env, arg);
ths2423f662007-04-11 02:15:08 +00005074 rn = "XContext";
5075 break;
ths703eaf32007-05-13 14:42:18 +00005076#endif
ths7a387ff2006-12-06 20:17:30 +00005077 default:
5078 goto die;
5079 }
ths8c0fdd82006-12-06 18:19:33 +00005080 break;
5081 case 21:
ths7a387ff2006-12-06 20:17:30 +00005082 /* Officially reserved, but sel 0 is used for R1x000 framemask */
5083 switch (sel) {
5084 case 0:
Blue Swirl895c2d02012-09-02 14:52:59 +00005085 gen_helper_mtc0_framemask(cpu_env, arg);
ths2423f662007-04-11 02:15:08 +00005086 rn = "Framemask";
5087 break;
ths7a387ff2006-12-06 20:17:30 +00005088 default:
5089 goto die;
5090 }
5091 break;
ths8c0fdd82006-12-06 18:19:33 +00005092 case 22:
ths7a387ff2006-12-06 20:17:30 +00005093 /* ignored */
5094 rn = "Diagnostic"; /* implementation dependent */
ths2423f662007-04-11 02:15:08 +00005095 break;
ths8c0fdd82006-12-06 18:19:33 +00005096 case 23:
ths7a387ff2006-12-06 20:17:30 +00005097 switch (sel) {
5098 case 0:
Blue Swirl895c2d02012-09-02 14:52:59 +00005099 gen_helper_mtc0_debug(cpu_env, arg); /* EJTAG support */
ths84873272007-06-01 17:47:07 +00005100 /* BS_STOP isn't good enough here, hflags may have changed. */
5101 gen_save_pc(ctx->pc + 4);
5102 ctx->bstate = BS_EXCP;
ths2423f662007-04-11 02:15:08 +00005103 rn = "Debug";
5104 break;
ths7a387ff2006-12-06 20:17:30 +00005105 case 1:
Blue Swirl895c2d02012-09-02 14:52:59 +00005106// gen_helper_mtc0_tracecontrol(cpu_env, arg); /* PDtrace support */
ths2423f662007-04-11 02:15:08 +00005107 rn = "TraceControl";
ths84873272007-06-01 17:47:07 +00005108 /* Stop translation as we may have switched the execution mode */
5109 ctx->bstate = BS_STOP;
ths2423f662007-04-11 02:15:08 +00005110// break;
ths7a387ff2006-12-06 20:17:30 +00005111 case 2:
Blue Swirl895c2d02012-09-02 14:52:59 +00005112// gen_helper_mtc0_tracecontrol2(cpu_env, arg); /* PDtrace support */
ths2423f662007-04-11 02:15:08 +00005113 rn = "TraceControl2";
ths84873272007-06-01 17:47:07 +00005114 /* Stop translation as we may have switched the execution mode */
5115 ctx->bstate = BS_STOP;
ths2423f662007-04-11 02:15:08 +00005116// break;
ths7a387ff2006-12-06 20:17:30 +00005117 case 3:
ths84873272007-06-01 17:47:07 +00005118 /* Stop translation as we may have switched the execution mode */
5119 ctx->bstate = BS_STOP;
Blue Swirl895c2d02012-09-02 14:52:59 +00005120// gen_helper_mtc0_usertracedata(cpu_env, arg); /* PDtrace support */
ths2423f662007-04-11 02:15:08 +00005121 rn = "UserTraceData";
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 4:
Blue Swirl895c2d02012-09-02 14:52:59 +00005126// gen_helper_mtc0_tracebpc(cpu_env, arg); /* PDtrace support */
ths84873272007-06-01 17:47:07 +00005127 /* Stop translation as we may have switched the execution mode */
5128 ctx->bstate = BS_STOP;
ths2423f662007-04-11 02:15:08 +00005129 rn = "TraceBPC";
5130// break;
ths7a387ff2006-12-06 20:17:30 +00005131 default:
5132 goto die;
5133 }
ths8c0fdd82006-12-06 18:19:33 +00005134 break;
5135 case 24:
ths7a387ff2006-12-06 20:17:30 +00005136 switch (sel) {
5137 case 0:
thsf1aa6322008-06-09 07:13:38 +00005138 /* EJTAG support */
Andreas Färber7db13fa2012-03-14 01:38:22 +01005139 gen_mtc0_store64(arg, offsetof(CPUMIPSState, CP0_DEPC));
ths2423f662007-04-11 02:15:08 +00005140 rn = "DEPC";
5141 break;
ths7a387ff2006-12-06 20:17:30 +00005142 default:
5143 goto die;
5144 }
ths8c0fdd82006-12-06 18:19:33 +00005145 break;
5146 case 25:
ths7a387ff2006-12-06 20:17:30 +00005147 switch (sel) {
5148 case 0:
Blue Swirl895c2d02012-09-02 14:52:59 +00005149 gen_helper_mtc0_performance0(cpu_env, arg);
ths2423f662007-04-11 02:15:08 +00005150 rn = "Performance0";
5151 break;
ths7a387ff2006-12-06 20:17:30 +00005152 case 1:
aurel32d9bea112009-04-15 14:41:44 +00005153// gen_helper_mtc0_performance1(arg);
ths2423f662007-04-11 02:15:08 +00005154 rn = "Performance1";
5155// break;
ths7a387ff2006-12-06 20:17:30 +00005156 case 2:
aurel32d9bea112009-04-15 14:41:44 +00005157// gen_helper_mtc0_performance2(arg);
ths2423f662007-04-11 02:15:08 +00005158 rn = "Performance2";
5159// break;
ths7a387ff2006-12-06 20:17:30 +00005160 case 3:
aurel32d9bea112009-04-15 14:41:44 +00005161// gen_helper_mtc0_performance3(arg);
ths2423f662007-04-11 02:15:08 +00005162 rn = "Performance3";
5163// break;
ths7a387ff2006-12-06 20:17:30 +00005164 case 4:
aurel32d9bea112009-04-15 14:41:44 +00005165// gen_helper_mtc0_performance4(arg);
ths2423f662007-04-11 02:15:08 +00005166 rn = "Performance4";
5167// break;
ths7a387ff2006-12-06 20:17:30 +00005168 case 5:
aurel32d9bea112009-04-15 14:41:44 +00005169// gen_helper_mtc0_performance5(arg);
ths2423f662007-04-11 02:15:08 +00005170 rn = "Performance5";
5171// break;
ths7a387ff2006-12-06 20:17:30 +00005172 case 6:
aurel32d9bea112009-04-15 14:41:44 +00005173// gen_helper_mtc0_performance6(arg);
ths2423f662007-04-11 02:15:08 +00005174 rn = "Performance6";
5175// break;
ths7a387ff2006-12-06 20:17:30 +00005176 case 7:
aurel32d9bea112009-04-15 14:41:44 +00005177// gen_helper_mtc0_performance7(arg);
ths2423f662007-04-11 02:15:08 +00005178 rn = "Performance7";
5179// break;
ths7a387ff2006-12-06 20:17:30 +00005180 default:
5181 goto die;
5182 }
ths8c0fdd82006-12-06 18:19:33 +00005183 break;
5184 case 26:
ths2423f662007-04-11 02:15:08 +00005185 /* ignored */
ths8c0fdd82006-12-06 18:19:33 +00005186 rn = "ECC";
ths2423f662007-04-11 02:15:08 +00005187 break;
ths8c0fdd82006-12-06 18:19:33 +00005188 case 27:
ths7a387ff2006-12-06 20:17:30 +00005189 switch (sel) {
5190 case 0 ... 3:
ths2423f662007-04-11 02:15:08 +00005191 /* ignored */
5192 rn = "CacheErr";
5193 break;
ths7a387ff2006-12-06 20:17:30 +00005194 default:
5195 goto die;
5196 }
ths8c0fdd82006-12-06 18:19:33 +00005197 break;
5198 case 28:
5199 switch (sel) {
5200 case 0:
ths7a387ff2006-12-06 20:17:30 +00005201 case 2:
5202 case 4:
5203 case 6:
Blue Swirl895c2d02012-09-02 14:52:59 +00005204 gen_helper_mtc0_taglo(cpu_env, arg);
ths8c0fdd82006-12-06 18:19:33 +00005205 rn = "TagLo";
5206 break;
ths7a387ff2006-12-06 20:17:30 +00005207 case 1:
5208 case 3:
5209 case 5:
5210 case 7:
Blue Swirl895c2d02012-09-02 14:52:59 +00005211 gen_helper_mtc0_datalo(cpu_env, arg);
ths7a387ff2006-12-06 20:17:30 +00005212 rn = "DataLo";
5213 break;
5214 default:
5215 goto die;
5216 }
5217 break;
5218 case 29:
5219 switch (sel) {
5220 case 0:
5221 case 2:
5222 case 4:
5223 case 6:
Blue Swirl895c2d02012-09-02 14:52:59 +00005224 gen_helper_mtc0_taghi(cpu_env, arg);
ths7a387ff2006-12-06 20:17:30 +00005225 rn = "TagHi";
5226 break;
5227 case 1:
5228 case 3:
5229 case 5:
5230 case 7:
Blue Swirl895c2d02012-09-02 14:52:59 +00005231 gen_helper_mtc0_datahi(cpu_env, arg);
ths7a387ff2006-12-06 20:17:30 +00005232 rn = "DataHi";
5233 break;
ths8c0fdd82006-12-06 18:19:33 +00005234 default:
5235 rn = "invalid sel";
5236 goto die;
5237 }
ths8c0fdd82006-12-06 18:19:33 +00005238 break;
5239 case 30:
ths7a387ff2006-12-06 20:17:30 +00005240 switch (sel) {
5241 case 0:
Andreas Färber7db13fa2012-03-14 01:38:22 +01005242 gen_mtc0_store64(arg, offsetof(CPUMIPSState, CP0_ErrorEPC));
ths2423f662007-04-11 02:15:08 +00005243 rn = "ErrorEPC";
5244 break;
ths7a387ff2006-12-06 20:17:30 +00005245 default:
5246 goto die;
5247 }
ths8c0fdd82006-12-06 18:19:33 +00005248 break;
5249 case 31:
ths7a387ff2006-12-06 20:17:30 +00005250 switch (sel) {
5251 case 0:
thsf1aa6322008-06-09 07:13:38 +00005252 /* EJTAG support */
Andreas Färber7db13fa2012-03-14 01:38:22 +01005253 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
ths2423f662007-04-11 02:15:08 +00005254 rn = "DESAVE";
5255 break;
ths7a387ff2006-12-06 20:17:30 +00005256 default:
5257 goto die;
5258 }
ths2423f662007-04-11 02:15:08 +00005259 /* Stop translation as we may have switched the execution mode */
5260 ctx->bstate = BS_STOP;
ths8c0fdd82006-12-06 18:19:33 +00005261 break;
5262 default:
ths8c0fdd82006-12-06 18:19:33 +00005263 goto die;
5264 }
Blue Swirl2abf3142010-10-13 18:38:08 +00005265 (void)rn; /* avoid a compiler warning */
aliguorid12d51d2009-01-15 21:48:06 +00005266 LOG_DISAS("mtc0 %s (reg %d sel %d)\n", rn, reg, sel);
thsbf20dc02008-06-30 17:22:19 +00005267 /* For simplicity assume that all writes can cause interrupts. */
pbrook2e70f6e2008-06-29 01:03:05 +00005268 if (use_icount) {
5269 gen_io_end();
5270 ctx->bstate = BS_STOP;
5271 }
ths8c0fdd82006-12-06 18:19:33 +00005272 return;
5273
5274die:
aliguorid12d51d2009-01-15 21:48:06 +00005275 LOG_DISAS("mtc0 %s (reg %d sel %d)\n", rn, reg, sel);
ths8c0fdd82006-12-06 18:19:33 +00005276 generate_exception(ctx, EXCP_RI);
5277}
5278
thsd26bc212007-11-08 18:05:37 +00005279#if defined(TARGET_MIPS64)
Aurelien Jarnod75c1352013-01-01 18:02:22 +01005280static void gen_dmfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
ths9c2149c2007-01-23 22:45:22 +00005281{
5282 const char *rn = "invalid";
5283
thse189e742007-09-24 12:48:00 +00005284 if (sel != 0)
Aurelien Jarnod75c1352013-01-01 18:02:22 +01005285 check_insn(ctx, ISA_MIPS64);
thse189e742007-09-24 12:48:00 +00005286
ths9c2149c2007-01-23 22:45:22 +00005287 switch (reg) {
5288 case 0:
5289 switch (sel) {
5290 case 0:
Andreas Färber7db13fa2012-03-14 01:38:22 +01005291 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Index));
ths9c2149c2007-01-23 22:45:22 +00005292 rn = "Index";
5293 break;
5294 case 1:
Aurelien Jarnod75c1352013-01-01 18:02:22 +01005295 check_insn(ctx, ASE_MT);
Blue Swirl895c2d02012-09-02 14:52:59 +00005296 gen_helper_mfc0_mvpcontrol(arg, cpu_env);
ths9c2149c2007-01-23 22:45:22 +00005297 rn = "MVPControl";
thsead93602007-09-06 00:18:15 +00005298 break;
ths9c2149c2007-01-23 22:45:22 +00005299 case 2:
Aurelien Jarnod75c1352013-01-01 18:02:22 +01005300 check_insn(ctx, ASE_MT);
Blue Swirl895c2d02012-09-02 14:52:59 +00005301 gen_helper_mfc0_mvpconf0(arg, cpu_env);
ths9c2149c2007-01-23 22:45:22 +00005302 rn = "MVPConf0";
thsead93602007-09-06 00:18:15 +00005303 break;
ths9c2149c2007-01-23 22:45:22 +00005304 case 3:
Aurelien Jarnod75c1352013-01-01 18:02:22 +01005305 check_insn(ctx, ASE_MT);
Blue Swirl895c2d02012-09-02 14:52:59 +00005306 gen_helper_mfc0_mvpconf1(arg, cpu_env);
ths9c2149c2007-01-23 22:45:22 +00005307 rn = "MVPConf1";
thsead93602007-09-06 00:18:15 +00005308 break;
ths9c2149c2007-01-23 22:45:22 +00005309 default:
5310 goto die;
5311 }
5312 break;
5313 case 1:
5314 switch (sel) {
5315 case 0:
Blue Swirl895c2d02012-09-02 14:52:59 +00005316 gen_helper_mfc0_random(arg, cpu_env);
ths9c2149c2007-01-23 22:45:22 +00005317 rn = "Random";
ths2423f662007-04-11 02:15:08 +00005318 break;
ths9c2149c2007-01-23 22:45:22 +00005319 case 1:
Aurelien Jarnod75c1352013-01-01 18:02:22 +01005320 check_insn(ctx, ASE_MT);
Andreas Färber7db13fa2012-03-14 01:38:22 +01005321 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEControl));
ths9c2149c2007-01-23 22:45:22 +00005322 rn = "VPEControl";
thsead93602007-09-06 00:18:15 +00005323 break;
ths9c2149c2007-01-23 22:45:22 +00005324 case 2:
Aurelien Jarnod75c1352013-01-01 18:02:22 +01005325 check_insn(ctx, ASE_MT);
Andreas Färber7db13fa2012-03-14 01:38:22 +01005326 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf0));
ths9c2149c2007-01-23 22:45:22 +00005327 rn = "VPEConf0";
thsead93602007-09-06 00:18:15 +00005328 break;
ths9c2149c2007-01-23 22:45:22 +00005329 case 3:
Aurelien Jarnod75c1352013-01-01 18:02:22 +01005330 check_insn(ctx, ASE_MT);
Andreas Färber7db13fa2012-03-14 01:38:22 +01005331 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf1));
ths9c2149c2007-01-23 22:45:22 +00005332 rn = "VPEConf1";
thsead93602007-09-06 00:18:15 +00005333 break;
ths9c2149c2007-01-23 22:45:22 +00005334 case 4:
Aurelien Jarnod75c1352013-01-01 18:02:22 +01005335 check_insn(ctx, ASE_MT);
Andreas Färber7db13fa2012-03-14 01:38:22 +01005336 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_YQMask));
ths9c2149c2007-01-23 22:45:22 +00005337 rn = "YQMask";
thsead93602007-09-06 00:18:15 +00005338 break;
ths9c2149c2007-01-23 22:45:22 +00005339 case 5:
Aurelien Jarnod75c1352013-01-01 18:02:22 +01005340 check_insn(ctx, ASE_MT);
Andreas Färber7db13fa2012-03-14 01:38:22 +01005341 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_VPESchedule));
ths9c2149c2007-01-23 22:45:22 +00005342 rn = "VPESchedule";
thsead93602007-09-06 00:18:15 +00005343 break;
ths9c2149c2007-01-23 22:45:22 +00005344 case 6:
Aurelien Jarnod75c1352013-01-01 18:02:22 +01005345 check_insn(ctx, ASE_MT);
Andreas Färber7db13fa2012-03-14 01:38:22 +01005346 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_VPEScheFBack));
ths9c2149c2007-01-23 22:45:22 +00005347 rn = "VPEScheFBack";
thsead93602007-09-06 00:18:15 +00005348 break;
ths9c2149c2007-01-23 22:45:22 +00005349 case 7:
Aurelien Jarnod75c1352013-01-01 18:02:22 +01005350 check_insn(ctx, ASE_MT);
Andreas Färber7db13fa2012-03-14 01:38:22 +01005351 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEOpt));
ths9c2149c2007-01-23 22:45:22 +00005352 rn = "VPEOpt";
thsead93602007-09-06 00:18:15 +00005353 break;
ths9c2149c2007-01-23 22:45:22 +00005354 default:
5355 goto die;
5356 }
5357 break;
5358 case 2:
5359 switch (sel) {
5360 case 0:
Andreas Färber7db13fa2012-03-14 01:38:22 +01005361 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryLo0));
ths2423f662007-04-11 02:15:08 +00005362 rn = "EntryLo0";
5363 break;
ths9c2149c2007-01-23 22:45:22 +00005364 case 1:
Aurelien Jarnod75c1352013-01-01 18:02:22 +01005365 check_insn(ctx, ASE_MT);
Blue Swirl895c2d02012-09-02 14:52:59 +00005366 gen_helper_mfc0_tcstatus(arg, cpu_env);
ths2423f662007-04-11 02:15:08 +00005367 rn = "TCStatus";
thsead93602007-09-06 00:18:15 +00005368 break;
ths9c2149c2007-01-23 22:45:22 +00005369 case 2:
Aurelien Jarnod75c1352013-01-01 18:02:22 +01005370 check_insn(ctx, ASE_MT);
Blue Swirl895c2d02012-09-02 14:52:59 +00005371 gen_helper_mfc0_tcbind(arg, cpu_env);
ths2423f662007-04-11 02:15:08 +00005372 rn = "TCBind";
thsead93602007-09-06 00:18:15 +00005373 break;
ths9c2149c2007-01-23 22:45:22 +00005374 case 3:
Aurelien Jarnod75c1352013-01-01 18:02:22 +01005375 check_insn(ctx, ASE_MT);
Blue Swirl895c2d02012-09-02 14:52:59 +00005376 gen_helper_dmfc0_tcrestart(arg, cpu_env);
ths2423f662007-04-11 02:15:08 +00005377 rn = "TCRestart";
thsead93602007-09-06 00:18:15 +00005378 break;
ths9c2149c2007-01-23 22:45:22 +00005379 case 4:
Aurelien Jarnod75c1352013-01-01 18:02:22 +01005380 check_insn(ctx, ASE_MT);
Blue Swirl895c2d02012-09-02 14:52:59 +00005381 gen_helper_dmfc0_tchalt(arg, cpu_env);
ths2423f662007-04-11 02:15:08 +00005382 rn = "TCHalt";
thsead93602007-09-06 00:18:15 +00005383 break;
ths9c2149c2007-01-23 22:45:22 +00005384 case 5:
Aurelien Jarnod75c1352013-01-01 18:02:22 +01005385 check_insn(ctx, ASE_MT);
Blue Swirl895c2d02012-09-02 14:52:59 +00005386 gen_helper_dmfc0_tccontext(arg, cpu_env);
ths2423f662007-04-11 02:15:08 +00005387 rn = "TCContext";
thsead93602007-09-06 00:18:15 +00005388 break;
ths9c2149c2007-01-23 22:45:22 +00005389 case 6:
Aurelien Jarnod75c1352013-01-01 18:02:22 +01005390 check_insn(ctx, ASE_MT);
Blue Swirl895c2d02012-09-02 14:52:59 +00005391 gen_helper_dmfc0_tcschedule(arg, cpu_env);
ths2423f662007-04-11 02:15:08 +00005392 rn = "TCSchedule";
thsead93602007-09-06 00:18:15 +00005393 break;
ths9c2149c2007-01-23 22:45:22 +00005394 case 7:
Aurelien Jarnod75c1352013-01-01 18:02:22 +01005395 check_insn(ctx, ASE_MT);
Blue Swirl895c2d02012-09-02 14:52:59 +00005396 gen_helper_dmfc0_tcschefback(arg, cpu_env);
ths2423f662007-04-11 02:15:08 +00005397 rn = "TCScheFBack";
thsead93602007-09-06 00:18:15 +00005398 break;
ths9c2149c2007-01-23 22:45:22 +00005399 default:
5400 goto die;
5401 }
5402 break;
5403 case 3:
5404 switch (sel) {
5405 case 0:
Andreas Färber7db13fa2012-03-14 01:38:22 +01005406 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryLo1));
ths2423f662007-04-11 02:15:08 +00005407 rn = "EntryLo1";
5408 break;
ths9c2149c2007-01-23 22:45:22 +00005409 default:
5410 goto die;
ths1579a722007-04-05 23:16:25 +00005411 }
ths9c2149c2007-01-23 22:45:22 +00005412 break;
5413 case 4:
5414 switch (sel) {
5415 case 0:
Andreas Färber7db13fa2012-03-14 01:38:22 +01005416 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_Context));
ths2423f662007-04-11 02:15:08 +00005417 rn = "Context";
5418 break;
ths9c2149c2007-01-23 22:45:22 +00005419 case 1:
aurel32d9bea112009-04-15 14:41:44 +00005420// gen_helper_dmfc0_contextconfig(arg); /* SmartMIPS ASE */
ths2423f662007-04-11 02:15:08 +00005421 rn = "ContextConfig";
5422// break;
ths9c2149c2007-01-23 22:45:22 +00005423 default:
5424 goto die;
ths876d4b02007-04-04 21:07:17 +00005425 }
ths9c2149c2007-01-23 22:45:22 +00005426 break;
5427 case 5:
5428 switch (sel) {
5429 case 0:
Andreas Färber7db13fa2012-03-14 01:38:22 +01005430 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageMask));
ths2423f662007-04-11 02:15:08 +00005431 rn = "PageMask";
5432 break;
ths9c2149c2007-01-23 22:45:22 +00005433 case 1:
Aurelien Jarnod75c1352013-01-01 18:02:22 +01005434 check_insn(ctx, ISA_MIPS32R2);
Andreas Färber7db13fa2012-03-14 01:38:22 +01005435 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageGrain));
ths2423f662007-04-11 02:15:08 +00005436 rn = "PageGrain";
5437 break;
ths9c2149c2007-01-23 22:45:22 +00005438 default:
5439 goto die;
ths876d4b02007-04-04 21:07:17 +00005440 }
ths9c2149c2007-01-23 22:45:22 +00005441 break;
5442 case 6:
5443 switch (sel) {
5444 case 0:
Andreas Färber7db13fa2012-03-14 01:38:22 +01005445 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Wired));
ths2423f662007-04-11 02:15:08 +00005446 rn = "Wired";
5447 break;
ths9c2149c2007-01-23 22:45:22 +00005448 case 1:
Aurelien Jarnod75c1352013-01-01 18:02:22 +01005449 check_insn(ctx, ISA_MIPS32R2);
Andreas Färber7db13fa2012-03-14 01:38:22 +01005450 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf0));
ths2423f662007-04-11 02:15:08 +00005451 rn = "SRSConf0";
thsead93602007-09-06 00:18:15 +00005452 break;
ths9c2149c2007-01-23 22:45:22 +00005453 case 2:
Aurelien Jarnod75c1352013-01-01 18:02:22 +01005454 check_insn(ctx, ISA_MIPS32R2);
Andreas Färber7db13fa2012-03-14 01:38:22 +01005455 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf1));
ths2423f662007-04-11 02:15:08 +00005456 rn = "SRSConf1";
thsead93602007-09-06 00:18:15 +00005457 break;
ths9c2149c2007-01-23 22:45:22 +00005458 case 3:
Aurelien Jarnod75c1352013-01-01 18:02:22 +01005459 check_insn(ctx, ISA_MIPS32R2);
Andreas Färber7db13fa2012-03-14 01:38:22 +01005460 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf2));
ths2423f662007-04-11 02:15:08 +00005461 rn = "SRSConf2";
thsead93602007-09-06 00:18:15 +00005462 break;
ths9c2149c2007-01-23 22:45:22 +00005463 case 4:
Aurelien Jarnod75c1352013-01-01 18:02:22 +01005464 check_insn(ctx, ISA_MIPS32R2);
Andreas Färber7db13fa2012-03-14 01:38:22 +01005465 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf3));
ths2423f662007-04-11 02:15:08 +00005466 rn = "SRSConf3";
thsead93602007-09-06 00:18:15 +00005467 break;
ths9c2149c2007-01-23 22:45:22 +00005468 case 5:
Aurelien Jarnod75c1352013-01-01 18:02:22 +01005469 check_insn(ctx, ISA_MIPS32R2);
Andreas Färber7db13fa2012-03-14 01:38:22 +01005470 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf4));
ths2423f662007-04-11 02:15:08 +00005471 rn = "SRSConf4";
thsead93602007-09-06 00:18:15 +00005472 break;
ths9c2149c2007-01-23 22:45:22 +00005473 default:
5474 goto die;
ths876d4b02007-04-04 21:07:17 +00005475 }
ths9c2149c2007-01-23 22:45:22 +00005476 break;
5477 case 7:
5478 switch (sel) {
5479 case 0:
Aurelien Jarnod75c1352013-01-01 18:02:22 +01005480 check_insn(ctx, ISA_MIPS32R2);
Andreas Färber7db13fa2012-03-14 01:38:22 +01005481 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_HWREna));
ths2423f662007-04-11 02:15:08 +00005482 rn = "HWREna";
5483 break;
ths9c2149c2007-01-23 22:45:22 +00005484 default:
5485 goto die;
ths876d4b02007-04-04 21:07:17 +00005486 }
ths9c2149c2007-01-23 22:45:22 +00005487 break;
5488 case 8:
5489 switch (sel) {
5490 case 0:
Andreas Färber7db13fa2012-03-14 01:38:22 +01005491 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_BadVAddr));
thsf0b3f3a2008-05-23 18:10:51 +00005492 rn = "BadVAddr";
ths2423f662007-04-11 02:15:08 +00005493 break;
ths9c2149c2007-01-23 22:45:22 +00005494 default:
5495 goto die;
ths876d4b02007-04-04 21:07:17 +00005496 }
ths9c2149c2007-01-23 22:45:22 +00005497 break;
5498 case 9:
5499 switch (sel) {
5500 case 0:
pbrook2e70f6e2008-06-29 01:03:05 +00005501 /* Mark as an IO operation because we read the time. */
5502 if (use_icount)
5503 gen_io_start();
Blue Swirl895c2d02012-09-02 14:52:59 +00005504 gen_helper_mfc0_count(arg, cpu_env);
pbrook2e70f6e2008-06-29 01:03:05 +00005505 if (use_icount) {
5506 gen_io_end();
pbrook2e70f6e2008-06-29 01:03:05 +00005507 }
Edgar E. Iglesias55807222011-01-17 23:00:08 +01005508 /* Break the TB to be able to take timer interrupts immediately
5509 after reading count. */
5510 ctx->bstate = BS_STOP;
ths2423f662007-04-11 02:15:08 +00005511 rn = "Count";
5512 break;
5513 /* 6,7 are implementation dependent */
ths9c2149c2007-01-23 22:45:22 +00005514 default:
5515 goto die;
ths876d4b02007-04-04 21:07:17 +00005516 }
ths9c2149c2007-01-23 22:45:22 +00005517 break;
5518 case 10:
5519 switch (sel) {
5520 case 0:
Andreas Färber7db13fa2012-03-14 01:38:22 +01005521 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryHi));
ths2423f662007-04-11 02:15:08 +00005522 rn = "EntryHi";
5523 break;
ths9c2149c2007-01-23 22:45:22 +00005524 default:
5525 goto die;
ths876d4b02007-04-04 21:07:17 +00005526 }
ths9c2149c2007-01-23 22:45:22 +00005527 break;
5528 case 11:
5529 switch (sel) {
5530 case 0:
Andreas Färber7db13fa2012-03-14 01:38:22 +01005531 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Compare));
ths2423f662007-04-11 02:15:08 +00005532 rn = "Compare";
5533 break;
ths876d4b02007-04-04 21:07:17 +00005534 /* 6,7 are implementation dependent */
ths9c2149c2007-01-23 22:45:22 +00005535 default:
5536 goto die;
ths876d4b02007-04-04 21:07:17 +00005537 }
ths9c2149c2007-01-23 22:45:22 +00005538 break;
5539 case 12:
5540 switch (sel) {
5541 case 0:
Andreas Färber7db13fa2012-03-14 01:38:22 +01005542 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Status));
ths2423f662007-04-11 02:15:08 +00005543 rn = "Status";
5544 break;
ths9c2149c2007-01-23 22:45:22 +00005545 case 1:
Aurelien Jarnod75c1352013-01-01 18:02:22 +01005546 check_insn(ctx, ISA_MIPS32R2);
Andreas Färber7db13fa2012-03-14 01:38:22 +01005547 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_IntCtl));
ths2423f662007-04-11 02:15:08 +00005548 rn = "IntCtl";
5549 break;
ths9c2149c2007-01-23 22:45:22 +00005550 case 2:
Aurelien Jarnod75c1352013-01-01 18:02:22 +01005551 check_insn(ctx, ISA_MIPS32R2);
Andreas Färber7db13fa2012-03-14 01:38:22 +01005552 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSCtl));
ths2423f662007-04-11 02:15:08 +00005553 rn = "SRSCtl";
5554 break;
ths9c2149c2007-01-23 22:45:22 +00005555 case 3:
Aurelien Jarnod75c1352013-01-01 18:02:22 +01005556 check_insn(ctx, ISA_MIPS32R2);
Andreas Färber7db13fa2012-03-14 01:38:22 +01005557 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
ths2423f662007-04-11 02:15:08 +00005558 rn = "SRSMap";
5559 break;
ths9c2149c2007-01-23 22:45:22 +00005560 default:
5561 goto die;
ths876d4b02007-04-04 21:07:17 +00005562 }
ths9c2149c2007-01-23 22:45:22 +00005563 break;
5564 case 13:
5565 switch (sel) {
5566 case 0:
Andreas Färber7db13fa2012-03-14 01:38:22 +01005567 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Cause));
ths2423f662007-04-11 02:15:08 +00005568 rn = "Cause";
5569 break;
ths9c2149c2007-01-23 22:45:22 +00005570 default:
5571 goto die;
ths876d4b02007-04-04 21:07:17 +00005572 }
ths9c2149c2007-01-23 22:45:22 +00005573 break;
5574 case 14:
5575 switch (sel) {
5576 case 0:
Andreas Färber7db13fa2012-03-14 01:38:22 +01005577 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EPC));
ths2423f662007-04-11 02:15:08 +00005578 rn = "EPC";
5579 break;
ths9c2149c2007-01-23 22:45:22 +00005580 default:
5581 goto die;
ths876d4b02007-04-04 21:07:17 +00005582 }
ths9c2149c2007-01-23 22:45:22 +00005583 break;
5584 case 15:
5585 switch (sel) {
5586 case 0:
Andreas Färber7db13fa2012-03-14 01:38:22 +01005587 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PRid));
ths2423f662007-04-11 02:15:08 +00005588 rn = "PRid";
5589 break;
ths9c2149c2007-01-23 22:45:22 +00005590 case 1:
Aurelien Jarnod75c1352013-01-01 18:02:22 +01005591 check_insn(ctx, ISA_MIPS32R2);
Andreas Färber7db13fa2012-03-14 01:38:22 +01005592 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_EBase));
ths2423f662007-04-11 02:15:08 +00005593 rn = "EBase";
5594 break;
ths9c2149c2007-01-23 22:45:22 +00005595 default:
5596 goto die;
ths876d4b02007-04-04 21:07:17 +00005597 }
ths9c2149c2007-01-23 22:45:22 +00005598 break;
5599 case 16:
5600 switch (sel) {
5601 case 0:
Andreas Färber7db13fa2012-03-14 01:38:22 +01005602 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config0));
ths9c2149c2007-01-23 22:45:22 +00005603 rn = "Config";
5604 break;
5605 case 1:
Andreas Färber7db13fa2012-03-14 01:38:22 +01005606 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config1));
ths9c2149c2007-01-23 22:45:22 +00005607 rn = "Config1";
5608 break;
5609 case 2:
Andreas Färber7db13fa2012-03-14 01:38:22 +01005610 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config2));
ths9c2149c2007-01-23 22:45:22 +00005611 rn = "Config2";
5612 break;
5613 case 3:
Andreas Färber7db13fa2012-03-14 01:38:22 +01005614 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config3));
ths9c2149c2007-01-23 22:45:22 +00005615 rn = "Config3";
5616 break;
5617 /* 6,7 are implementation dependent */
thsf0b3f3a2008-05-23 18:10:51 +00005618 case 6:
Andreas Färber7db13fa2012-03-14 01:38:22 +01005619 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config6));
thsf0b3f3a2008-05-23 18:10:51 +00005620 rn = "Config6";
5621 break;
5622 case 7:
Andreas Färber7db13fa2012-03-14 01:38:22 +01005623 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config7));
thsf0b3f3a2008-05-23 18:10:51 +00005624 rn = "Config7";
5625 break;
ths9c2149c2007-01-23 22:45:22 +00005626 default:
5627 goto die;
5628 }
5629 break;
5630 case 17:
5631 switch (sel) {
5632 case 0:
Blue Swirl895c2d02012-09-02 14:52:59 +00005633 gen_helper_dmfc0_lladdr(arg, cpu_env);
ths2423f662007-04-11 02:15:08 +00005634 rn = "LLAddr";
5635 break;
ths9c2149c2007-01-23 22:45:22 +00005636 default:
5637 goto die;
5638 }
5639 break;
5640 case 18:
5641 switch (sel) {
thsfd88b6a2007-05-23 08:24:25 +00005642 case 0 ... 7:
Blue Swirl895c2d02012-09-02 14:52:59 +00005643 gen_helper_1e0i(dmfc0_watchlo, arg, sel);
ths2423f662007-04-11 02:15:08 +00005644 rn = "WatchLo";
5645 break;
ths9c2149c2007-01-23 22:45:22 +00005646 default:
5647 goto die;
5648 }
5649 break;
5650 case 19:
5651 switch (sel) {
thsfd88b6a2007-05-23 08:24:25 +00005652 case 0 ... 7:
Blue Swirl895c2d02012-09-02 14:52:59 +00005653 gen_helper_1e0i(mfc0_watchhi, arg, sel);
ths2423f662007-04-11 02:15:08 +00005654 rn = "WatchHi";
5655 break;
ths9c2149c2007-01-23 22:45:22 +00005656 default:
5657 goto die;
5658 }
5659 break;
5660 case 20:
5661 switch (sel) {
5662 case 0:
Aurelien Jarnod75c1352013-01-01 18:02:22 +01005663 check_insn(ctx, ISA_MIPS3);
Andreas Färber7db13fa2012-03-14 01:38:22 +01005664 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_XContext));
ths2423f662007-04-11 02:15:08 +00005665 rn = "XContext";
5666 break;
ths9c2149c2007-01-23 22:45:22 +00005667 default:
5668 goto die;
5669 }
5670 break;
5671 case 21:
5672 /* Officially reserved, but sel 0 is used for R1x000 framemask */
5673 switch (sel) {
5674 case 0:
Andreas Färber7db13fa2012-03-14 01:38:22 +01005675 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Framemask));
ths2423f662007-04-11 02:15:08 +00005676 rn = "Framemask";
5677 break;
ths9c2149c2007-01-23 22:45:22 +00005678 default:
5679 goto die;
5680 }
5681 break;
5682 case 22:
aurel32d9bea112009-04-15 14:41:44 +00005683 tcg_gen_movi_tl(arg, 0); /* unimplemented */
ths2423f662007-04-11 02:15:08 +00005684 rn = "'Diagnostic"; /* implementation dependent */
5685 break;
ths9c2149c2007-01-23 22:45:22 +00005686 case 23:
5687 switch (sel) {
5688 case 0:
Blue Swirl895c2d02012-09-02 14:52:59 +00005689 gen_helper_mfc0_debug(arg, cpu_env); /* EJTAG support */
ths2423f662007-04-11 02:15:08 +00005690 rn = "Debug";
5691 break;
ths9c2149c2007-01-23 22:45:22 +00005692 case 1:
Blue Swirl895c2d02012-09-02 14:52:59 +00005693// gen_helper_dmfc0_tracecontrol(arg, cpu_env); /* PDtrace support */
ths2423f662007-04-11 02:15:08 +00005694 rn = "TraceControl";
5695// break;
ths9c2149c2007-01-23 22:45:22 +00005696 case 2:
Blue Swirl895c2d02012-09-02 14:52:59 +00005697// gen_helper_dmfc0_tracecontrol2(arg, cpu_env); /* PDtrace support */
ths2423f662007-04-11 02:15:08 +00005698 rn = "TraceControl2";
5699// break;
ths9c2149c2007-01-23 22:45:22 +00005700 case 3:
Blue Swirl895c2d02012-09-02 14:52:59 +00005701// gen_helper_dmfc0_usertracedata(arg, cpu_env); /* PDtrace support */
ths2423f662007-04-11 02:15:08 +00005702 rn = "UserTraceData";
5703// break;
ths9c2149c2007-01-23 22:45:22 +00005704 case 4:
Blue Swirl895c2d02012-09-02 14:52:59 +00005705// gen_helper_dmfc0_tracebpc(arg, cpu_env); /* PDtrace support */
ths2423f662007-04-11 02:15:08 +00005706 rn = "TraceBPC";
5707// break;
ths9c2149c2007-01-23 22:45:22 +00005708 default:
5709 goto die;
5710 }
5711 break;
5712 case 24:
5713 switch (sel) {
5714 case 0:
thsf0b3f3a2008-05-23 18:10:51 +00005715 /* EJTAG support */
Andreas Färber7db13fa2012-03-14 01:38:22 +01005716 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_DEPC));
ths2423f662007-04-11 02:15:08 +00005717 rn = "DEPC";
5718 break;
ths9c2149c2007-01-23 22:45:22 +00005719 default:
5720 goto die;
5721 }
5722 break;
5723 case 25:
5724 switch (sel) {
5725 case 0:
Andreas Färber7db13fa2012-03-14 01:38:22 +01005726 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Performance0));
ths2423f662007-04-11 02:15:08 +00005727 rn = "Performance0";
ths9c2149c2007-01-23 22:45:22 +00005728 break;
5729 case 1:
aurel32d9bea112009-04-15 14:41:44 +00005730// gen_helper_dmfc0_performance1(arg);
ths2423f662007-04-11 02:15:08 +00005731 rn = "Performance1";
5732// break;
ths9c2149c2007-01-23 22:45:22 +00005733 case 2:
aurel32d9bea112009-04-15 14:41:44 +00005734// gen_helper_dmfc0_performance2(arg);
ths2423f662007-04-11 02:15:08 +00005735 rn = "Performance2";
5736// break;
ths9c2149c2007-01-23 22:45:22 +00005737 case 3:
aurel32d9bea112009-04-15 14:41:44 +00005738// gen_helper_dmfc0_performance3(arg);
ths2423f662007-04-11 02:15:08 +00005739 rn = "Performance3";
5740// break;
ths9c2149c2007-01-23 22:45:22 +00005741 case 4:
aurel32d9bea112009-04-15 14:41:44 +00005742// gen_helper_dmfc0_performance4(arg);
ths2423f662007-04-11 02:15:08 +00005743 rn = "Performance4";
5744// break;
ths9c2149c2007-01-23 22:45:22 +00005745 case 5:
aurel32d9bea112009-04-15 14:41:44 +00005746// gen_helper_dmfc0_performance5(arg);
ths2423f662007-04-11 02:15:08 +00005747 rn = "Performance5";
5748// break;
ths9c2149c2007-01-23 22:45:22 +00005749 case 6:
aurel32d9bea112009-04-15 14:41:44 +00005750// gen_helper_dmfc0_performance6(arg);
ths2423f662007-04-11 02:15:08 +00005751 rn = "Performance6";
5752// break;
ths9c2149c2007-01-23 22:45:22 +00005753 case 7:
aurel32d9bea112009-04-15 14:41:44 +00005754// gen_helper_dmfc0_performance7(arg);
ths2423f662007-04-11 02:15:08 +00005755 rn = "Performance7";
5756// break;
ths9c2149c2007-01-23 22:45:22 +00005757 default:
5758 goto die;
5759 }
5760 break;
5761 case 26:
aurel32d9bea112009-04-15 14:41:44 +00005762 tcg_gen_movi_tl(arg, 0); /* unimplemented */
aurel32da806822008-11-15 12:12:08 +00005763 rn = "ECC";
5764 break;
ths9c2149c2007-01-23 22:45:22 +00005765 case 27:
5766 switch (sel) {
5767 /* ignored */
5768 case 0 ... 3:
aurel32d9bea112009-04-15 14:41:44 +00005769 tcg_gen_movi_tl(arg, 0); /* unimplemented */
ths2423f662007-04-11 02:15:08 +00005770 rn = "CacheErr";
5771 break;
ths9c2149c2007-01-23 22:45:22 +00005772 default:
5773 goto die;
5774 }
5775 break;
5776 case 28:
5777 switch (sel) {
5778 case 0:
5779 case 2:
5780 case 4:
5781 case 6:
Andreas Färber7db13fa2012-03-14 01:38:22 +01005782 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_TagLo));
ths9c2149c2007-01-23 22:45:22 +00005783 rn = "TagLo";
5784 break;
5785 case 1:
5786 case 3:
5787 case 5:
5788 case 7:
Andreas Färber7db13fa2012-03-14 01:38:22 +01005789 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataLo));
ths9c2149c2007-01-23 22:45:22 +00005790 rn = "DataLo";
5791 break;
5792 default:
5793 goto die;
5794 }
5795 break;
5796 case 29:
5797 switch (sel) {
5798 case 0:
5799 case 2:
5800 case 4:
5801 case 6:
Andreas Färber7db13fa2012-03-14 01:38:22 +01005802 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_TagHi));
ths9c2149c2007-01-23 22:45:22 +00005803 rn = "TagHi";
5804 break;
5805 case 1:
5806 case 3:
5807 case 5:
5808 case 7:
Andreas Färber7db13fa2012-03-14 01:38:22 +01005809 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataHi));
ths9c2149c2007-01-23 22:45:22 +00005810 rn = "DataHi";
5811 break;
5812 default:
5813 goto die;
5814 }
5815 break;
5816 case 30:
5817 switch (sel) {
5818 case 0:
Andreas Färber7db13fa2012-03-14 01:38:22 +01005819 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_ErrorEPC));
ths2423f662007-04-11 02:15:08 +00005820 rn = "ErrorEPC";
5821 break;
ths9c2149c2007-01-23 22:45:22 +00005822 default:
5823 goto die;
5824 }
5825 break;
5826 case 31:
5827 switch (sel) {
5828 case 0:
thsf0b3f3a2008-05-23 18:10:51 +00005829 /* EJTAG support */
Andreas Färber7db13fa2012-03-14 01:38:22 +01005830 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
ths2423f662007-04-11 02:15:08 +00005831 rn = "DESAVE";
5832 break;
ths9c2149c2007-01-23 22:45:22 +00005833 default:
5834 goto die;
5835 }
5836 break;
5837 default:
ths876d4b02007-04-04 21:07:17 +00005838 goto die;
ths9c2149c2007-01-23 22:45:22 +00005839 }
Blue Swirl2abf3142010-10-13 18:38:08 +00005840 (void)rn; /* avoid a compiler warning */
aliguorid12d51d2009-01-15 21:48:06 +00005841 LOG_DISAS("dmfc0 %s (reg %d sel %d)\n", rn, reg, sel);
ths9c2149c2007-01-23 22:45:22 +00005842 return;
5843
5844die:
aliguorid12d51d2009-01-15 21:48:06 +00005845 LOG_DISAS("dmfc0 %s (reg %d sel %d)\n", rn, reg, sel);
ths9c2149c2007-01-23 22:45:22 +00005846 generate_exception(ctx, EXCP_RI);
5847}
5848
Aurelien Jarnod75c1352013-01-01 18:02:22 +01005849static void gen_dmtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
ths9c2149c2007-01-23 22:45:22 +00005850{
5851 const char *rn = "invalid";
5852
thse189e742007-09-24 12:48:00 +00005853 if (sel != 0)
Aurelien Jarnod75c1352013-01-01 18:02:22 +01005854 check_insn(ctx, ISA_MIPS64);
thse189e742007-09-24 12:48:00 +00005855
pbrook2e70f6e2008-06-29 01:03:05 +00005856 if (use_icount)
5857 gen_io_start();
5858
ths9c2149c2007-01-23 22:45:22 +00005859 switch (reg) {
5860 case 0:
5861 switch (sel) {
5862 case 0:
Blue Swirl895c2d02012-09-02 14:52:59 +00005863 gen_helper_mtc0_index(cpu_env, arg);
ths9c2149c2007-01-23 22:45:22 +00005864 rn = "Index";
5865 break;
5866 case 1:
Aurelien Jarnod75c1352013-01-01 18:02:22 +01005867 check_insn(ctx, ASE_MT);
Blue Swirl895c2d02012-09-02 14:52:59 +00005868 gen_helper_mtc0_mvpcontrol(cpu_env, arg);
ths9c2149c2007-01-23 22:45:22 +00005869 rn = "MVPControl";
thsead93602007-09-06 00:18:15 +00005870 break;
ths9c2149c2007-01-23 22:45:22 +00005871 case 2:
Aurelien Jarnod75c1352013-01-01 18:02:22 +01005872 check_insn(ctx, ASE_MT);
thsead93602007-09-06 00:18:15 +00005873 /* ignored */
ths9c2149c2007-01-23 22:45:22 +00005874 rn = "MVPConf0";
thsead93602007-09-06 00:18:15 +00005875 break;
ths9c2149c2007-01-23 22:45:22 +00005876 case 3:
Aurelien Jarnod75c1352013-01-01 18:02:22 +01005877 check_insn(ctx, ASE_MT);
thsead93602007-09-06 00:18:15 +00005878 /* ignored */
ths9c2149c2007-01-23 22:45:22 +00005879 rn = "MVPConf1";
thsead93602007-09-06 00:18:15 +00005880 break;
ths9c2149c2007-01-23 22:45:22 +00005881 default:
5882 goto die;
5883 }
5884 break;
5885 case 1:
5886 switch (sel) {
5887 case 0:
ths2423f662007-04-11 02:15:08 +00005888 /* ignored */
ths9c2149c2007-01-23 22:45:22 +00005889 rn = "Random";
ths2423f662007-04-11 02:15:08 +00005890 break;
ths9c2149c2007-01-23 22:45:22 +00005891 case 1:
Aurelien Jarnod75c1352013-01-01 18:02:22 +01005892 check_insn(ctx, ASE_MT);
Blue Swirl895c2d02012-09-02 14:52:59 +00005893 gen_helper_mtc0_vpecontrol(cpu_env, arg);
ths9c2149c2007-01-23 22:45:22 +00005894 rn = "VPEControl";
thsead93602007-09-06 00:18:15 +00005895 break;
ths9c2149c2007-01-23 22:45:22 +00005896 case 2:
Aurelien Jarnod75c1352013-01-01 18:02:22 +01005897 check_insn(ctx, ASE_MT);
Blue Swirl895c2d02012-09-02 14:52:59 +00005898 gen_helper_mtc0_vpeconf0(cpu_env, arg);
ths9c2149c2007-01-23 22:45:22 +00005899 rn = "VPEConf0";
thsead93602007-09-06 00:18:15 +00005900 break;
ths9c2149c2007-01-23 22:45:22 +00005901 case 3:
Aurelien Jarnod75c1352013-01-01 18:02:22 +01005902 check_insn(ctx, ASE_MT);
Blue Swirl895c2d02012-09-02 14:52:59 +00005903 gen_helper_mtc0_vpeconf1(cpu_env, arg);
ths9c2149c2007-01-23 22:45:22 +00005904 rn = "VPEConf1";
thsead93602007-09-06 00:18:15 +00005905 break;
ths9c2149c2007-01-23 22:45:22 +00005906 case 4:
Aurelien Jarnod75c1352013-01-01 18:02:22 +01005907 check_insn(ctx, ASE_MT);
Blue Swirl895c2d02012-09-02 14:52:59 +00005908 gen_helper_mtc0_yqmask(cpu_env, arg);
ths9c2149c2007-01-23 22:45:22 +00005909 rn = "YQMask";
thsead93602007-09-06 00:18:15 +00005910 break;
ths9c2149c2007-01-23 22:45:22 +00005911 case 5:
Aurelien Jarnod75c1352013-01-01 18:02:22 +01005912 check_insn(ctx, ASE_MT);
Andreas Färber7db13fa2012-03-14 01:38:22 +01005913 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_VPESchedule));
ths9c2149c2007-01-23 22:45:22 +00005914 rn = "VPESchedule";
thsead93602007-09-06 00:18:15 +00005915 break;
ths9c2149c2007-01-23 22:45:22 +00005916 case 6:
Aurelien Jarnod75c1352013-01-01 18:02:22 +01005917 check_insn(ctx, ASE_MT);
Andreas Färber7db13fa2012-03-14 01:38:22 +01005918 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_VPEScheFBack));
ths9c2149c2007-01-23 22:45:22 +00005919 rn = "VPEScheFBack";
thsead93602007-09-06 00:18:15 +00005920 break;
ths9c2149c2007-01-23 22:45:22 +00005921 case 7:
Aurelien Jarnod75c1352013-01-01 18:02:22 +01005922 check_insn(ctx, ASE_MT);
Blue Swirl895c2d02012-09-02 14:52:59 +00005923 gen_helper_mtc0_vpeopt(cpu_env, arg);
ths9c2149c2007-01-23 22:45:22 +00005924 rn = "VPEOpt";
thsead93602007-09-06 00:18:15 +00005925 break;
ths9c2149c2007-01-23 22:45:22 +00005926 default:
5927 goto die;
5928 }
5929 break;
5930 case 2:
5931 switch (sel) {
5932 case 0:
Blue Swirl895c2d02012-09-02 14:52:59 +00005933 gen_helper_mtc0_entrylo0(cpu_env, arg);
ths2423f662007-04-11 02:15:08 +00005934 rn = "EntryLo0";
5935 break;
ths9c2149c2007-01-23 22:45:22 +00005936 case 1:
Aurelien Jarnod75c1352013-01-01 18:02:22 +01005937 check_insn(ctx, ASE_MT);
Blue Swirl895c2d02012-09-02 14:52:59 +00005938 gen_helper_mtc0_tcstatus(cpu_env, arg);
ths2423f662007-04-11 02:15:08 +00005939 rn = "TCStatus";
thsead93602007-09-06 00:18:15 +00005940 break;
ths9c2149c2007-01-23 22:45:22 +00005941 case 2:
Aurelien Jarnod75c1352013-01-01 18:02:22 +01005942 check_insn(ctx, ASE_MT);
Blue Swirl895c2d02012-09-02 14:52:59 +00005943 gen_helper_mtc0_tcbind(cpu_env, arg);
ths2423f662007-04-11 02:15:08 +00005944 rn = "TCBind";
thsead93602007-09-06 00:18:15 +00005945 break;
ths9c2149c2007-01-23 22:45:22 +00005946 case 3:
Aurelien Jarnod75c1352013-01-01 18:02:22 +01005947 check_insn(ctx, ASE_MT);
Blue Swirl895c2d02012-09-02 14:52:59 +00005948 gen_helper_mtc0_tcrestart(cpu_env, arg);
ths2423f662007-04-11 02:15:08 +00005949 rn = "TCRestart";
thsead93602007-09-06 00:18:15 +00005950 break;
ths9c2149c2007-01-23 22:45:22 +00005951 case 4:
Aurelien Jarnod75c1352013-01-01 18:02:22 +01005952 check_insn(ctx, ASE_MT);
Blue Swirl895c2d02012-09-02 14:52:59 +00005953 gen_helper_mtc0_tchalt(cpu_env, arg);
ths2423f662007-04-11 02:15:08 +00005954 rn = "TCHalt";
thsead93602007-09-06 00:18:15 +00005955 break;
ths9c2149c2007-01-23 22:45:22 +00005956 case 5:
Aurelien Jarnod75c1352013-01-01 18:02:22 +01005957 check_insn(ctx, ASE_MT);
Blue Swirl895c2d02012-09-02 14:52:59 +00005958 gen_helper_mtc0_tccontext(cpu_env, arg);
ths2423f662007-04-11 02:15:08 +00005959 rn = "TCContext";
thsead93602007-09-06 00:18:15 +00005960 break;
ths9c2149c2007-01-23 22:45:22 +00005961 case 6:
Aurelien Jarnod75c1352013-01-01 18:02:22 +01005962 check_insn(ctx, ASE_MT);
Blue Swirl895c2d02012-09-02 14:52:59 +00005963 gen_helper_mtc0_tcschedule(cpu_env, arg);
ths2423f662007-04-11 02:15:08 +00005964 rn = "TCSchedule";
thsead93602007-09-06 00:18:15 +00005965 break;
ths9c2149c2007-01-23 22:45:22 +00005966 case 7:
Aurelien Jarnod75c1352013-01-01 18:02:22 +01005967 check_insn(ctx, ASE_MT);
Blue Swirl895c2d02012-09-02 14:52:59 +00005968 gen_helper_mtc0_tcschefback(cpu_env, arg);
ths2423f662007-04-11 02:15:08 +00005969 rn = "TCScheFBack";
thsead93602007-09-06 00:18:15 +00005970 break;
ths9c2149c2007-01-23 22:45:22 +00005971 default:
5972 goto die;
5973 }
5974 break;
5975 case 3:
5976 switch (sel) {
5977 case 0:
Blue Swirl895c2d02012-09-02 14:52:59 +00005978 gen_helper_mtc0_entrylo1(cpu_env, arg);
ths2423f662007-04-11 02:15:08 +00005979 rn = "EntryLo1";
5980 break;
ths9c2149c2007-01-23 22:45:22 +00005981 default:
5982 goto die;
ths876d4b02007-04-04 21:07:17 +00005983 }
ths9c2149c2007-01-23 22:45:22 +00005984 break;
5985 case 4:
5986 switch (sel) {
5987 case 0:
Blue Swirl895c2d02012-09-02 14:52:59 +00005988 gen_helper_mtc0_context(cpu_env, arg);
ths2423f662007-04-11 02:15:08 +00005989 rn = "Context";
5990 break;
ths9c2149c2007-01-23 22:45:22 +00005991 case 1:
Blue Swirl895c2d02012-09-02 14:52:59 +00005992// gen_helper_mtc0_contextconfig(cpu_env, arg); /* SmartMIPS ASE */
ths2423f662007-04-11 02:15:08 +00005993 rn = "ContextConfig";
5994// break;
ths9c2149c2007-01-23 22:45:22 +00005995 default:
5996 goto die;
ths876d4b02007-04-04 21:07:17 +00005997 }
ths9c2149c2007-01-23 22:45:22 +00005998 break;
5999 case 5:
6000 switch (sel) {
6001 case 0:
Blue Swirl895c2d02012-09-02 14:52:59 +00006002 gen_helper_mtc0_pagemask(cpu_env, arg);
ths2423f662007-04-11 02:15:08 +00006003 rn = "PageMask";
6004 break;
ths9c2149c2007-01-23 22:45:22 +00006005 case 1:
Aurelien Jarnod75c1352013-01-01 18:02:22 +01006006 check_insn(ctx, ISA_MIPS32R2);
Blue Swirl895c2d02012-09-02 14:52:59 +00006007 gen_helper_mtc0_pagegrain(cpu_env, arg);
ths2423f662007-04-11 02:15:08 +00006008 rn = "PageGrain";
6009 break;
ths9c2149c2007-01-23 22:45:22 +00006010 default:
6011 goto die;
ths876d4b02007-04-04 21:07:17 +00006012 }
ths9c2149c2007-01-23 22:45:22 +00006013 break;
6014 case 6:
6015 switch (sel) {
6016 case 0:
Blue Swirl895c2d02012-09-02 14:52:59 +00006017 gen_helper_mtc0_wired(cpu_env, arg);
ths2423f662007-04-11 02:15:08 +00006018 rn = "Wired";
6019 break;
ths9c2149c2007-01-23 22:45:22 +00006020 case 1:
Aurelien Jarnod75c1352013-01-01 18:02:22 +01006021 check_insn(ctx, ISA_MIPS32R2);
Blue Swirl895c2d02012-09-02 14:52:59 +00006022 gen_helper_mtc0_srsconf0(cpu_env, arg);
ths2423f662007-04-11 02:15:08 +00006023 rn = "SRSConf0";
thsead93602007-09-06 00:18:15 +00006024 break;
ths9c2149c2007-01-23 22:45:22 +00006025 case 2:
Aurelien Jarnod75c1352013-01-01 18:02:22 +01006026 check_insn(ctx, ISA_MIPS32R2);
Blue Swirl895c2d02012-09-02 14:52:59 +00006027 gen_helper_mtc0_srsconf1(cpu_env, arg);
ths2423f662007-04-11 02:15:08 +00006028 rn = "SRSConf1";
thsead93602007-09-06 00:18:15 +00006029 break;
ths9c2149c2007-01-23 22:45:22 +00006030 case 3:
Aurelien Jarnod75c1352013-01-01 18:02:22 +01006031 check_insn(ctx, ISA_MIPS32R2);
Blue Swirl895c2d02012-09-02 14:52:59 +00006032 gen_helper_mtc0_srsconf2(cpu_env, arg);
ths2423f662007-04-11 02:15:08 +00006033 rn = "SRSConf2";
thsead93602007-09-06 00:18:15 +00006034 break;
ths9c2149c2007-01-23 22:45:22 +00006035 case 4:
Aurelien Jarnod75c1352013-01-01 18:02:22 +01006036 check_insn(ctx, ISA_MIPS32R2);
Blue Swirl895c2d02012-09-02 14:52:59 +00006037 gen_helper_mtc0_srsconf3(cpu_env, arg);
ths2423f662007-04-11 02:15:08 +00006038 rn = "SRSConf3";
thsead93602007-09-06 00:18:15 +00006039 break;
ths9c2149c2007-01-23 22:45:22 +00006040 case 5:
Aurelien Jarnod75c1352013-01-01 18:02:22 +01006041 check_insn(ctx, ISA_MIPS32R2);
Blue Swirl895c2d02012-09-02 14:52:59 +00006042 gen_helper_mtc0_srsconf4(cpu_env, arg);
ths2423f662007-04-11 02:15:08 +00006043 rn = "SRSConf4";
thsead93602007-09-06 00:18:15 +00006044 break;
ths9c2149c2007-01-23 22:45:22 +00006045 default:
6046 goto die;
ths876d4b02007-04-04 21:07:17 +00006047 }
ths9c2149c2007-01-23 22:45:22 +00006048 break;
6049 case 7:
6050 switch (sel) {
6051 case 0:
Aurelien Jarnod75c1352013-01-01 18:02:22 +01006052 check_insn(ctx, ISA_MIPS32R2);
Blue Swirl895c2d02012-09-02 14:52:59 +00006053 gen_helper_mtc0_hwrena(cpu_env, arg);
ths2423f662007-04-11 02:15:08 +00006054 rn = "HWREna";
6055 break;
ths9c2149c2007-01-23 22:45:22 +00006056 default:
6057 goto die;
ths876d4b02007-04-04 21:07:17 +00006058 }
ths9c2149c2007-01-23 22:45:22 +00006059 break;
6060 case 8:
6061 /* ignored */
thsf0b3f3a2008-05-23 18:10:51 +00006062 rn = "BadVAddr";
ths9c2149c2007-01-23 22:45:22 +00006063 break;
6064 case 9:
6065 switch (sel) {
6066 case 0:
Blue Swirl895c2d02012-09-02 14:52:59 +00006067 gen_helper_mtc0_count(cpu_env, arg);
ths2423f662007-04-11 02:15:08 +00006068 rn = "Count";
6069 break;
ths876d4b02007-04-04 21:07:17 +00006070 /* 6,7 are implementation dependent */
ths9c2149c2007-01-23 22:45:22 +00006071 default:
6072 goto die;
ths876d4b02007-04-04 21:07:17 +00006073 }
6074 /* Stop translation as we may have switched the execution mode */
6075 ctx->bstate = BS_STOP;
ths9c2149c2007-01-23 22:45:22 +00006076 break;
6077 case 10:
6078 switch (sel) {
6079 case 0:
Blue Swirl895c2d02012-09-02 14:52:59 +00006080 gen_helper_mtc0_entryhi(cpu_env, arg);
ths2423f662007-04-11 02:15:08 +00006081 rn = "EntryHi";
6082 break;
ths9c2149c2007-01-23 22:45:22 +00006083 default:
6084 goto die;
ths876d4b02007-04-04 21:07:17 +00006085 }
ths9c2149c2007-01-23 22:45:22 +00006086 break;
6087 case 11:
6088 switch (sel) {
6089 case 0:
Blue Swirl895c2d02012-09-02 14:52:59 +00006090 gen_helper_mtc0_compare(cpu_env, arg);
ths2423f662007-04-11 02:15:08 +00006091 rn = "Compare";
6092 break;
ths876d4b02007-04-04 21:07:17 +00006093 /* 6,7 are implementation dependent */
ths9c2149c2007-01-23 22:45:22 +00006094 default:
6095 goto die;
ths876d4b02007-04-04 21:07:17 +00006096 }
aurel32de9a95f2008-11-11 13:41:01 +00006097 /* Stop translation as we may have switched the execution mode */
6098 ctx->bstate = BS_STOP;
ths9c2149c2007-01-23 22:45:22 +00006099 break;
6100 case 12:
6101 switch (sel) {
6102 case 0:
aurel32867abc72009-04-13 08:53:12 +00006103 save_cpu_state(ctx, 1);
Blue Swirl895c2d02012-09-02 14:52:59 +00006104 gen_helper_mtc0_status(cpu_env, arg);
ths84873272007-06-01 17:47:07 +00006105 /* BS_STOP isn't good enough here, hflags may have changed. */
6106 gen_save_pc(ctx->pc + 4);
6107 ctx->bstate = BS_EXCP;
ths2423f662007-04-11 02:15:08 +00006108 rn = "Status";
6109 break;
ths9c2149c2007-01-23 22:45:22 +00006110 case 1:
Aurelien Jarnod75c1352013-01-01 18:02:22 +01006111 check_insn(ctx, ISA_MIPS32R2);
Blue Swirl895c2d02012-09-02 14:52:59 +00006112 gen_helper_mtc0_intctl(cpu_env, arg);
ths84873272007-06-01 17:47:07 +00006113 /* Stop translation as we may have switched the execution mode */
6114 ctx->bstate = BS_STOP;
ths2423f662007-04-11 02:15:08 +00006115 rn = "IntCtl";
6116 break;
ths9c2149c2007-01-23 22:45:22 +00006117 case 2:
Aurelien Jarnod75c1352013-01-01 18:02:22 +01006118 check_insn(ctx, ISA_MIPS32R2);
Blue Swirl895c2d02012-09-02 14:52:59 +00006119 gen_helper_mtc0_srsctl(cpu_env, arg);
ths84873272007-06-01 17:47:07 +00006120 /* Stop translation as we may have switched the execution mode */
6121 ctx->bstate = BS_STOP;
ths2423f662007-04-11 02:15:08 +00006122 rn = "SRSCtl";
6123 break;
ths9c2149c2007-01-23 22:45:22 +00006124 case 3:
Aurelien Jarnod75c1352013-01-01 18:02:22 +01006125 check_insn(ctx, ISA_MIPS32R2);
Andreas Färber7db13fa2012-03-14 01:38:22 +01006126 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
ths84873272007-06-01 17:47:07 +00006127 /* Stop translation as we may have switched the execution mode */
6128 ctx->bstate = BS_STOP;
ths2423f662007-04-11 02:15:08 +00006129 rn = "SRSMap";
6130 break;
6131 default:
ths9c2149c2007-01-23 22:45:22 +00006132 goto die;
ths876d4b02007-04-04 21:07:17 +00006133 }
ths9c2149c2007-01-23 22:45:22 +00006134 break;
6135 case 13:
6136 switch (sel) {
6137 case 0:
aurel32867abc72009-04-13 08:53:12 +00006138 save_cpu_state(ctx, 1);
Aurelien Jarno5dc5d9f2010-07-25 16:51:29 +02006139 /* Mark as an IO operation because we may trigger a software
6140 interrupt. */
6141 if (use_icount) {
6142 gen_io_start();
6143 }
Blue Swirl895c2d02012-09-02 14:52:59 +00006144 gen_helper_mtc0_cause(cpu_env, arg);
Aurelien Jarno5dc5d9f2010-07-25 16:51:29 +02006145 if (use_icount) {
6146 gen_io_end();
6147 }
6148 /* Stop translation as we may have triggered an intetrupt */
6149 ctx->bstate = BS_STOP;
ths2423f662007-04-11 02:15:08 +00006150 rn = "Cause";
6151 break;
ths9c2149c2007-01-23 22:45:22 +00006152 default:
6153 goto die;
ths876d4b02007-04-04 21:07:17 +00006154 }
ths9c2149c2007-01-23 22:45:22 +00006155 break;
6156 case 14:
6157 switch (sel) {
6158 case 0:
Andreas Färber7db13fa2012-03-14 01:38:22 +01006159 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EPC));
ths2423f662007-04-11 02:15:08 +00006160 rn = "EPC";
6161 break;
ths9c2149c2007-01-23 22:45:22 +00006162 default:
6163 goto die;
ths876d4b02007-04-04 21:07:17 +00006164 }
ths9c2149c2007-01-23 22:45:22 +00006165 break;
6166 case 15:
6167 switch (sel) {
6168 case 0:
ths2423f662007-04-11 02:15:08 +00006169 /* ignored */
6170 rn = "PRid";
6171 break;
ths9c2149c2007-01-23 22:45:22 +00006172 case 1:
Aurelien Jarnod75c1352013-01-01 18:02:22 +01006173 check_insn(ctx, ISA_MIPS32R2);
Blue Swirl895c2d02012-09-02 14:52:59 +00006174 gen_helper_mtc0_ebase(cpu_env, arg);
ths2423f662007-04-11 02:15:08 +00006175 rn = "EBase";
6176 break;
ths9c2149c2007-01-23 22:45:22 +00006177 default:
6178 goto die;
ths876d4b02007-04-04 21:07:17 +00006179 }
ths9c2149c2007-01-23 22:45:22 +00006180 break;
6181 case 16:
6182 switch (sel) {
6183 case 0:
Blue Swirl895c2d02012-09-02 14:52:59 +00006184 gen_helper_mtc0_config0(cpu_env, arg);
ths9c2149c2007-01-23 22:45:22 +00006185 rn = "Config";
ths2423f662007-04-11 02:15:08 +00006186 /* Stop translation as we may have switched the execution mode */
6187 ctx->bstate = BS_STOP;
ths9c2149c2007-01-23 22:45:22 +00006188 break;
6189 case 1:
aurel321fc7bf62009-04-08 21:47:35 +00006190 /* ignored, read only */
ths9c2149c2007-01-23 22:45:22 +00006191 rn = "Config1";
6192 break;
6193 case 2:
Blue Swirl895c2d02012-09-02 14:52:59 +00006194 gen_helper_mtc0_config2(cpu_env, arg);
ths9c2149c2007-01-23 22:45:22 +00006195 rn = "Config2";
ths2423f662007-04-11 02:15:08 +00006196 /* Stop translation as we may have switched the execution mode */
6197 ctx->bstate = BS_STOP;
ths9c2149c2007-01-23 22:45:22 +00006198 break;
6199 case 3:
ths2423f662007-04-11 02:15:08 +00006200 /* ignored */
ths9c2149c2007-01-23 22:45:22 +00006201 rn = "Config3";
6202 break;
6203 /* 6,7 are implementation dependent */
6204 default:
6205 rn = "Invalid config selector";
6206 goto die;
6207 }
ths9c2149c2007-01-23 22:45:22 +00006208 break;
6209 case 17:
6210 switch (sel) {
6211 case 0:
Blue Swirl895c2d02012-09-02 14:52:59 +00006212 gen_helper_mtc0_lladdr(cpu_env, arg);
ths2423f662007-04-11 02:15:08 +00006213 rn = "LLAddr";
6214 break;
ths9c2149c2007-01-23 22:45:22 +00006215 default:
6216 goto die;
6217 }
6218 break;
6219 case 18:
6220 switch (sel) {
thsfd88b6a2007-05-23 08:24:25 +00006221 case 0 ... 7:
Blue Swirl895c2d02012-09-02 14:52:59 +00006222 gen_helper_0e1i(mtc0_watchlo, arg, sel);
ths2423f662007-04-11 02:15:08 +00006223 rn = "WatchLo";
6224 break;
ths9c2149c2007-01-23 22:45:22 +00006225 default:
6226 goto die;
6227 }
6228 break;
6229 case 19:
6230 switch (sel) {
thsfd88b6a2007-05-23 08:24:25 +00006231 case 0 ... 7:
Blue Swirl895c2d02012-09-02 14:52:59 +00006232 gen_helper_0e1i(mtc0_watchhi, arg, sel);
ths2423f662007-04-11 02:15:08 +00006233 rn = "WatchHi";
6234 break;
ths9c2149c2007-01-23 22:45:22 +00006235 default:
6236 goto die;
6237 }
6238 break;
6239 case 20:
6240 switch (sel) {
6241 case 0:
Aurelien Jarnod75c1352013-01-01 18:02:22 +01006242 check_insn(ctx, ISA_MIPS3);
Blue Swirl895c2d02012-09-02 14:52:59 +00006243 gen_helper_mtc0_xcontext(cpu_env, arg);
ths2423f662007-04-11 02:15:08 +00006244 rn = "XContext";
6245 break;
ths9c2149c2007-01-23 22:45:22 +00006246 default:
6247 goto die;
6248 }
6249 break;
6250 case 21:
6251 /* Officially reserved, but sel 0 is used for R1x000 framemask */
6252 switch (sel) {
6253 case 0:
Blue Swirl895c2d02012-09-02 14:52:59 +00006254 gen_helper_mtc0_framemask(cpu_env, arg);
ths2423f662007-04-11 02:15:08 +00006255 rn = "Framemask";
6256 break;
ths9c2149c2007-01-23 22:45:22 +00006257 default:
6258 goto die;
6259 }
6260 break;
6261 case 22:
6262 /* ignored */
6263 rn = "Diagnostic"; /* implementation dependent */
ths876d4b02007-04-04 21:07:17 +00006264 break;
ths9c2149c2007-01-23 22:45:22 +00006265 case 23:
6266 switch (sel) {
6267 case 0:
Blue Swirl895c2d02012-09-02 14:52:59 +00006268 gen_helper_mtc0_debug(cpu_env, arg); /* EJTAG support */
ths84873272007-06-01 17:47:07 +00006269 /* BS_STOP isn't good enough here, hflags may have changed. */
6270 gen_save_pc(ctx->pc + 4);
6271 ctx->bstate = BS_EXCP;
ths2423f662007-04-11 02:15:08 +00006272 rn = "Debug";
6273 break;
ths9c2149c2007-01-23 22:45:22 +00006274 case 1:
Blue Swirl895c2d02012-09-02 14:52:59 +00006275// gen_helper_mtc0_tracecontrol(cpu_env, arg); /* PDtrace support */
ths84873272007-06-01 17:47:07 +00006276 /* Stop translation as we may have switched the execution mode */
6277 ctx->bstate = BS_STOP;
ths2423f662007-04-11 02:15:08 +00006278 rn = "TraceControl";
6279// break;
ths9c2149c2007-01-23 22:45:22 +00006280 case 2:
Blue Swirl895c2d02012-09-02 14:52:59 +00006281// gen_helper_mtc0_tracecontrol2(cpu_env, arg); /* PDtrace support */
ths84873272007-06-01 17:47:07 +00006282 /* Stop translation as we may have switched the execution mode */
6283 ctx->bstate = BS_STOP;
ths2423f662007-04-11 02:15:08 +00006284 rn = "TraceControl2";
6285// break;
ths9c2149c2007-01-23 22:45:22 +00006286 case 3:
Blue Swirl895c2d02012-09-02 14:52:59 +00006287// gen_helper_mtc0_usertracedata(cpu_env, arg); /* PDtrace support */
ths84873272007-06-01 17:47:07 +00006288 /* Stop translation as we may have switched the execution mode */
6289 ctx->bstate = BS_STOP;
ths2423f662007-04-11 02:15:08 +00006290 rn = "UserTraceData";
6291// break;
ths9c2149c2007-01-23 22:45:22 +00006292 case 4:
Blue Swirl895c2d02012-09-02 14:52:59 +00006293// gen_helper_mtc0_tracebpc(cpu_env, arg); /* PDtrace support */
ths84873272007-06-01 17:47:07 +00006294 /* Stop translation as we may have switched the execution mode */
6295 ctx->bstate = BS_STOP;
ths2423f662007-04-11 02:15:08 +00006296 rn = "TraceBPC";
6297// break;
ths9c2149c2007-01-23 22:45:22 +00006298 default:
6299 goto die;
6300 }
ths9c2149c2007-01-23 22:45:22 +00006301 break;
6302 case 24:
6303 switch (sel) {
6304 case 0:
thsf1aa6322008-06-09 07:13:38 +00006305 /* EJTAG support */
Andreas Färber7db13fa2012-03-14 01:38:22 +01006306 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_DEPC));
ths2423f662007-04-11 02:15:08 +00006307 rn = "DEPC";
6308 break;
ths9c2149c2007-01-23 22:45:22 +00006309 default:
6310 goto die;
6311 }
6312 break;
6313 case 25:
6314 switch (sel) {
6315 case 0:
Blue Swirl895c2d02012-09-02 14:52:59 +00006316 gen_helper_mtc0_performance0(cpu_env, arg);
ths2423f662007-04-11 02:15:08 +00006317 rn = "Performance0";
6318 break;
ths9c2149c2007-01-23 22:45:22 +00006319 case 1:
Blue Swirl895c2d02012-09-02 14:52:59 +00006320// gen_helper_mtc0_performance1(cpu_env, arg);
ths2423f662007-04-11 02:15:08 +00006321 rn = "Performance1";
6322// break;
ths9c2149c2007-01-23 22:45:22 +00006323 case 2:
Blue Swirl895c2d02012-09-02 14:52:59 +00006324// gen_helper_mtc0_performance2(cpu_env, arg);
ths2423f662007-04-11 02:15:08 +00006325 rn = "Performance2";
6326// break;
ths9c2149c2007-01-23 22:45:22 +00006327 case 3:
Blue Swirl895c2d02012-09-02 14:52:59 +00006328// gen_helper_mtc0_performance3(cpu_env, arg);
ths2423f662007-04-11 02:15:08 +00006329 rn = "Performance3";
6330// break;
ths9c2149c2007-01-23 22:45:22 +00006331 case 4:
Blue Swirl895c2d02012-09-02 14:52:59 +00006332// gen_helper_mtc0_performance4(cpu_env, arg);
ths2423f662007-04-11 02:15:08 +00006333 rn = "Performance4";
6334// break;
ths9c2149c2007-01-23 22:45:22 +00006335 case 5:
Blue Swirl895c2d02012-09-02 14:52:59 +00006336// gen_helper_mtc0_performance5(cpu_env, arg);
ths2423f662007-04-11 02:15:08 +00006337 rn = "Performance5";
6338// break;
ths9c2149c2007-01-23 22:45:22 +00006339 case 6:
Blue Swirl895c2d02012-09-02 14:52:59 +00006340// gen_helper_mtc0_performance6(cpu_env, arg);
ths2423f662007-04-11 02:15:08 +00006341 rn = "Performance6";
6342// break;
ths9c2149c2007-01-23 22:45:22 +00006343 case 7:
Blue Swirl895c2d02012-09-02 14:52:59 +00006344// gen_helper_mtc0_performance7(cpu_env, arg);
ths2423f662007-04-11 02:15:08 +00006345 rn = "Performance7";
6346// break;
ths9c2149c2007-01-23 22:45:22 +00006347 default:
6348 goto die;
6349 }
ths876d4b02007-04-04 21:07:17 +00006350 break;
ths9c2149c2007-01-23 22:45:22 +00006351 case 26:
ths876d4b02007-04-04 21:07:17 +00006352 /* ignored */
ths9c2149c2007-01-23 22:45:22 +00006353 rn = "ECC";
ths876d4b02007-04-04 21:07:17 +00006354 break;
ths9c2149c2007-01-23 22:45:22 +00006355 case 27:
6356 switch (sel) {
6357 case 0 ... 3:
ths2423f662007-04-11 02:15:08 +00006358 /* ignored */
6359 rn = "CacheErr";
6360 break;
ths9c2149c2007-01-23 22:45:22 +00006361 default:
6362 goto die;
6363 }
ths876d4b02007-04-04 21:07:17 +00006364 break;
ths9c2149c2007-01-23 22:45:22 +00006365 case 28:
6366 switch (sel) {
6367 case 0:
6368 case 2:
6369 case 4:
6370 case 6:
Blue Swirl895c2d02012-09-02 14:52:59 +00006371 gen_helper_mtc0_taglo(cpu_env, arg);
ths9c2149c2007-01-23 22:45:22 +00006372 rn = "TagLo";
6373 break;
6374 case 1:
6375 case 3:
6376 case 5:
6377 case 7:
Blue Swirl895c2d02012-09-02 14:52:59 +00006378 gen_helper_mtc0_datalo(cpu_env, arg);
ths9c2149c2007-01-23 22:45:22 +00006379 rn = "DataLo";
6380 break;
6381 default:
6382 goto die;
6383 }
6384 break;
6385 case 29:
6386 switch (sel) {
6387 case 0:
6388 case 2:
6389 case 4:
6390 case 6:
Blue Swirl895c2d02012-09-02 14:52:59 +00006391 gen_helper_mtc0_taghi(cpu_env, arg);
ths9c2149c2007-01-23 22:45:22 +00006392 rn = "TagHi";
6393 break;
6394 case 1:
6395 case 3:
6396 case 5:
6397 case 7:
Blue Swirl895c2d02012-09-02 14:52:59 +00006398 gen_helper_mtc0_datahi(cpu_env, arg);
ths9c2149c2007-01-23 22:45:22 +00006399 rn = "DataHi";
6400 break;
6401 default:
6402 rn = "invalid sel";
6403 goto die;
6404 }
ths876d4b02007-04-04 21:07:17 +00006405 break;
ths9c2149c2007-01-23 22:45:22 +00006406 case 30:
6407 switch (sel) {
6408 case 0:
Andreas Färber7db13fa2012-03-14 01:38:22 +01006409 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_ErrorEPC));
ths2423f662007-04-11 02:15:08 +00006410 rn = "ErrorEPC";
6411 break;
ths9c2149c2007-01-23 22:45:22 +00006412 default:
6413 goto die;
6414 }
6415 break;
6416 case 31:
6417 switch (sel) {
6418 case 0:
thsf1aa6322008-06-09 07:13:38 +00006419 /* EJTAG support */
Andreas Färber7db13fa2012-03-14 01:38:22 +01006420 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
ths2423f662007-04-11 02:15:08 +00006421 rn = "DESAVE";
6422 break;
ths9c2149c2007-01-23 22:45:22 +00006423 default:
6424 goto die;
6425 }
ths876d4b02007-04-04 21:07:17 +00006426 /* Stop translation as we may have switched the execution mode */
6427 ctx->bstate = BS_STOP;
ths9c2149c2007-01-23 22:45:22 +00006428 break;
6429 default:
ths876d4b02007-04-04 21:07:17 +00006430 goto die;
ths9c2149c2007-01-23 22:45:22 +00006431 }
Blue Swirl2abf3142010-10-13 18:38:08 +00006432 (void)rn; /* avoid a compiler warning */
aliguorid12d51d2009-01-15 21:48:06 +00006433 LOG_DISAS("dmtc0 %s (reg %d sel %d)\n", rn, reg, sel);
thsbf20dc02008-06-30 17:22:19 +00006434 /* For simplicity assume that all writes can cause interrupts. */
pbrook2e70f6e2008-06-29 01:03:05 +00006435 if (use_icount) {
6436 gen_io_end();
6437 ctx->bstate = BS_STOP;
6438 }
ths9c2149c2007-01-23 22:45:22 +00006439 return;
6440
6441die:
aliguorid12d51d2009-01-15 21:48:06 +00006442 LOG_DISAS("dmtc0 %s (reg %d sel %d)\n", rn, reg, sel);
ths9c2149c2007-01-23 22:45:22 +00006443 generate_exception(ctx, EXCP_RI);
6444}
thsd26bc212007-11-08 18:05:37 +00006445#endif /* TARGET_MIPS64 */
ths9c2149c2007-01-23 22:45:22 +00006446
Andreas Färber7db13fa2012-03-14 01:38:22 +01006447static void gen_mftr(CPUMIPSState *env, DisasContext *ctx, int rt, int rd,
thsead93602007-09-06 00:18:15 +00006448 int u, int sel, int h)
6449{
6450 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
pbrooka7812ae2008-11-17 14:43:54 +00006451 TCGv t0 = tcg_temp_local_new();
thsead93602007-09-06 00:18:15 +00006452
6453 if ((env->CP0_VPEConf0 & (1 << CP0VPEC0_MVP)) == 0 &&
thsb5dc7732008-06-27 10:02:35 +00006454 ((env->tcs[other_tc].CP0_TCBind & (0xf << CP0TCBd_CurVPE)) !=
6455 (env->active_tc.CP0_TCBind & (0xf << CP0TCBd_CurVPE))))
ths1a3fd9c2008-06-24 21:58:35 +00006456 tcg_gen_movi_tl(t0, -1);
thsead93602007-09-06 00:18:15 +00006457 else if ((env->CP0_VPEControl & (0xff << CP0VPECo_TargTC)) >
6458 (env->mvp->CP0_MVPConf0 & (0xff << CP0MVPC0_PTC)))
ths1a3fd9c2008-06-24 21:58:35 +00006459 tcg_gen_movi_tl(t0, -1);
thsead93602007-09-06 00:18:15 +00006460 else if (u == 0) {
6461 switch (rt) {
Edgar E. Iglesias5a25ce92011-08-29 23:07:34 +02006462 case 1:
6463 switch (sel) {
6464 case 1:
Blue Swirl895c2d02012-09-02 14:52:59 +00006465 gen_helper_mftc0_vpecontrol(t0, cpu_env);
Edgar E. Iglesias5a25ce92011-08-29 23:07:34 +02006466 break;
6467 case 2:
Blue Swirl895c2d02012-09-02 14:52:59 +00006468 gen_helper_mftc0_vpeconf0(t0, cpu_env);
Edgar E. Iglesias5a25ce92011-08-29 23:07:34 +02006469 break;
6470 default:
6471 goto die;
6472 break;
6473 }
6474 break;
thsead93602007-09-06 00:18:15 +00006475 case 2:
6476 switch (sel) {
6477 case 1:
Blue Swirl895c2d02012-09-02 14:52:59 +00006478 gen_helper_mftc0_tcstatus(t0, cpu_env);
thsead93602007-09-06 00:18:15 +00006479 break;
6480 case 2:
Blue Swirl895c2d02012-09-02 14:52:59 +00006481 gen_helper_mftc0_tcbind(t0, cpu_env);
thsead93602007-09-06 00:18:15 +00006482 break;
6483 case 3:
Blue Swirl895c2d02012-09-02 14:52:59 +00006484 gen_helper_mftc0_tcrestart(t0, cpu_env);
thsead93602007-09-06 00:18:15 +00006485 break;
6486 case 4:
Blue Swirl895c2d02012-09-02 14:52:59 +00006487 gen_helper_mftc0_tchalt(t0, cpu_env);
thsead93602007-09-06 00:18:15 +00006488 break;
6489 case 5:
Blue Swirl895c2d02012-09-02 14:52:59 +00006490 gen_helper_mftc0_tccontext(t0, cpu_env);
thsead93602007-09-06 00:18:15 +00006491 break;
6492 case 6:
Blue Swirl895c2d02012-09-02 14:52:59 +00006493 gen_helper_mftc0_tcschedule(t0, cpu_env);
thsead93602007-09-06 00:18:15 +00006494 break;
6495 case 7:
Blue Swirl895c2d02012-09-02 14:52:59 +00006496 gen_helper_mftc0_tcschefback(t0, cpu_env);
thsead93602007-09-06 00:18:15 +00006497 break;
6498 default:
Aurelien Jarnod75c1352013-01-01 18:02:22 +01006499 gen_mfc0(ctx, t0, rt, sel);
thsead93602007-09-06 00:18:15 +00006500 break;
6501 }
6502 break;
6503 case 10:
6504 switch (sel) {
6505 case 0:
Blue Swirl895c2d02012-09-02 14:52:59 +00006506 gen_helper_mftc0_entryhi(t0, cpu_env);
thsead93602007-09-06 00:18:15 +00006507 break;
6508 default:
Aurelien Jarnod75c1352013-01-01 18:02:22 +01006509 gen_mfc0(ctx, t0, rt, sel);
thsead93602007-09-06 00:18:15 +00006510 break;
6511 }
6512 case 12:
6513 switch (sel) {
6514 case 0:
Blue Swirl895c2d02012-09-02 14:52:59 +00006515 gen_helper_mftc0_status(t0, cpu_env);
thsead93602007-09-06 00:18:15 +00006516 break;
6517 default:
Aurelien Jarnod75c1352013-01-01 18:02:22 +01006518 gen_mfc0(ctx, t0, rt, sel);
thsead93602007-09-06 00:18:15 +00006519 break;
6520 }
Edgar E. Iglesias5a25ce92011-08-29 23:07:34 +02006521 case 13:
6522 switch (sel) {
6523 case 0:
Blue Swirl895c2d02012-09-02 14:52:59 +00006524 gen_helper_mftc0_cause(t0, cpu_env);
Edgar E. Iglesias5a25ce92011-08-29 23:07:34 +02006525 break;
6526 default:
6527 goto die;
6528 break;
6529 }
6530 break;
6531 case 14:
6532 switch (sel) {
6533 case 0:
Blue Swirl895c2d02012-09-02 14:52:59 +00006534 gen_helper_mftc0_epc(t0, cpu_env);
Edgar E. Iglesias5a25ce92011-08-29 23:07:34 +02006535 break;
6536 default:
6537 goto die;
6538 break;
6539 }
6540 break;
6541 case 15:
6542 switch (sel) {
6543 case 1:
Blue Swirl895c2d02012-09-02 14:52:59 +00006544 gen_helper_mftc0_ebase(t0, cpu_env);
Edgar E. Iglesias5a25ce92011-08-29 23:07:34 +02006545 break;
6546 default:
6547 goto die;
6548 break;
6549 }
6550 break;
6551 case 16:
6552 switch (sel) {
6553 case 0 ... 7:
Blue Swirl895c2d02012-09-02 14:52:59 +00006554 gen_helper_mftc0_configx(t0, cpu_env, tcg_const_tl(sel));
Edgar E. Iglesias5a25ce92011-08-29 23:07:34 +02006555 break;
6556 default:
6557 goto die;
6558 break;
6559 }
6560 break;
thsead93602007-09-06 00:18:15 +00006561 case 23:
6562 switch (sel) {
6563 case 0:
Blue Swirl895c2d02012-09-02 14:52:59 +00006564 gen_helper_mftc0_debug(t0, cpu_env);
thsead93602007-09-06 00:18:15 +00006565 break;
6566 default:
Aurelien Jarnod75c1352013-01-01 18:02:22 +01006567 gen_mfc0(ctx, t0, rt, sel);
thsead93602007-09-06 00:18:15 +00006568 break;
6569 }
6570 break;
6571 default:
Aurelien Jarnod75c1352013-01-01 18:02:22 +01006572 gen_mfc0(ctx, t0, rt, sel);
thsead93602007-09-06 00:18:15 +00006573 }
6574 } else switch (sel) {
6575 /* GPR registers. */
6576 case 0:
Blue Swirl895c2d02012-09-02 14:52:59 +00006577 gen_helper_1e0i(mftgpr, t0, rt);
thsead93602007-09-06 00:18:15 +00006578 break;
6579 /* Auxiliary CPU registers */
6580 case 1:
6581 switch (rt) {
6582 case 0:
Blue Swirl895c2d02012-09-02 14:52:59 +00006583 gen_helper_1e0i(mftlo, t0, 0);
thsead93602007-09-06 00:18:15 +00006584 break;
6585 case 1:
Blue Swirl895c2d02012-09-02 14:52:59 +00006586 gen_helper_1e0i(mfthi, t0, 0);
thsead93602007-09-06 00:18:15 +00006587 break;
6588 case 2:
Blue Swirl895c2d02012-09-02 14:52:59 +00006589 gen_helper_1e0i(mftacx, t0, 0);
thsead93602007-09-06 00:18:15 +00006590 break;
6591 case 4:
Blue Swirl895c2d02012-09-02 14:52:59 +00006592 gen_helper_1e0i(mftlo, t0, 1);
thsead93602007-09-06 00:18:15 +00006593 break;
6594 case 5:
Blue Swirl895c2d02012-09-02 14:52:59 +00006595 gen_helper_1e0i(mfthi, t0, 1);
thsead93602007-09-06 00:18:15 +00006596 break;
6597 case 6:
Blue Swirl895c2d02012-09-02 14:52:59 +00006598 gen_helper_1e0i(mftacx, t0, 1);
thsead93602007-09-06 00:18:15 +00006599 break;
6600 case 8:
Blue Swirl895c2d02012-09-02 14:52:59 +00006601 gen_helper_1e0i(mftlo, t0, 2);
thsead93602007-09-06 00:18:15 +00006602 break;
6603 case 9:
Blue Swirl895c2d02012-09-02 14:52:59 +00006604 gen_helper_1e0i(mfthi, t0, 2);
thsead93602007-09-06 00:18:15 +00006605 break;
6606 case 10:
Blue Swirl895c2d02012-09-02 14:52:59 +00006607 gen_helper_1e0i(mftacx, t0, 2);
thsead93602007-09-06 00:18:15 +00006608 break;
6609 case 12:
Blue Swirl895c2d02012-09-02 14:52:59 +00006610 gen_helper_1e0i(mftlo, t0, 3);
thsead93602007-09-06 00:18:15 +00006611 break;
6612 case 13:
Blue Swirl895c2d02012-09-02 14:52:59 +00006613 gen_helper_1e0i(mfthi, t0, 3);
thsead93602007-09-06 00:18:15 +00006614 break;
6615 case 14:
Blue Swirl895c2d02012-09-02 14:52:59 +00006616 gen_helper_1e0i(mftacx, t0, 3);
thsead93602007-09-06 00:18:15 +00006617 break;
6618 case 16:
Blue Swirl895c2d02012-09-02 14:52:59 +00006619 gen_helper_mftdsp(t0, cpu_env);
thsead93602007-09-06 00:18:15 +00006620 break;
6621 default:
6622 goto die;
6623 }
6624 break;
6625 /* Floating point (COP1). */
6626 case 2:
6627 /* XXX: For now we support only a single FPU context. */
6628 if (h == 0) {
pbrooka7812ae2008-11-17 14:43:54 +00006629 TCGv_i32 fp0 = tcg_temp_new_i32();
thsb6d96be2008-07-09 11:05:10 +00006630
6631 gen_load_fpr32(fp0, rt);
6632 tcg_gen_ext_i32_tl(t0, fp0);
pbrooka7812ae2008-11-17 14:43:54 +00006633 tcg_temp_free_i32(fp0);
thsead93602007-09-06 00:18:15 +00006634 } else {
pbrooka7812ae2008-11-17 14:43:54 +00006635 TCGv_i32 fp0 = tcg_temp_new_i32();
thsb6d96be2008-07-09 11:05:10 +00006636
6637 gen_load_fpr32h(fp0, rt);
6638 tcg_gen_ext_i32_tl(t0, fp0);
pbrooka7812ae2008-11-17 14:43:54 +00006639 tcg_temp_free_i32(fp0);
thsead93602007-09-06 00:18:15 +00006640 }
6641 break;
6642 case 3:
6643 /* XXX: For now we support only a single FPU context. */
Blue Swirl895c2d02012-09-02 14:52:59 +00006644 gen_helper_1e0i(cfc1, t0, rt);
thsead93602007-09-06 00:18:15 +00006645 break;
6646 /* COP2: Not implemented. */
6647 case 4:
6648 case 5:
6649 /* fall through */
6650 default:
6651 goto die;
6652 }
aliguorid12d51d2009-01-15 21:48:06 +00006653 LOG_DISAS("mftr (reg %d u %d sel %d h %d)\n", rt, u, sel, h);
ths1a3fd9c2008-06-24 21:58:35 +00006654 gen_store_gpr(t0, rd);
6655 tcg_temp_free(t0);
thsead93602007-09-06 00:18:15 +00006656 return;
6657
6658die:
ths1a3fd9c2008-06-24 21:58:35 +00006659 tcg_temp_free(t0);
aliguorid12d51d2009-01-15 21:48:06 +00006660 LOG_DISAS("mftr (reg %d u %d sel %d h %d)\n", rt, u, sel, h);
thsead93602007-09-06 00:18:15 +00006661 generate_exception(ctx, EXCP_RI);
6662}
6663
Andreas Färber7db13fa2012-03-14 01:38:22 +01006664static void gen_mttr(CPUMIPSState *env, DisasContext *ctx, int rd, int rt,
thsead93602007-09-06 00:18:15 +00006665 int u, int sel, int h)
6666{
6667 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
pbrooka7812ae2008-11-17 14:43:54 +00006668 TCGv t0 = tcg_temp_local_new();
thsead93602007-09-06 00:18:15 +00006669
ths1a3fd9c2008-06-24 21:58:35 +00006670 gen_load_gpr(t0, rt);
thsead93602007-09-06 00:18:15 +00006671 if ((env->CP0_VPEConf0 & (1 << CP0VPEC0_MVP)) == 0 &&
thsb5dc7732008-06-27 10:02:35 +00006672 ((env->tcs[other_tc].CP0_TCBind & (0xf << CP0TCBd_CurVPE)) !=
6673 (env->active_tc.CP0_TCBind & (0xf << CP0TCBd_CurVPE))))
thsead93602007-09-06 00:18:15 +00006674 /* NOP */ ;
6675 else if ((env->CP0_VPEControl & (0xff << CP0VPECo_TargTC)) >
6676 (env->mvp->CP0_MVPConf0 & (0xff << CP0MVPC0_PTC)))
6677 /* NOP */ ;
6678 else if (u == 0) {
6679 switch (rd) {
Edgar E. Iglesias5a25ce92011-08-29 23:07:34 +02006680 case 1:
6681 switch (sel) {
6682 case 1:
Blue Swirl895c2d02012-09-02 14:52:59 +00006683 gen_helper_mttc0_vpecontrol(cpu_env, t0);
Edgar E. Iglesias5a25ce92011-08-29 23:07:34 +02006684 break;
6685 case 2:
Blue Swirl895c2d02012-09-02 14:52:59 +00006686 gen_helper_mttc0_vpeconf0(cpu_env, t0);
Edgar E. Iglesias5a25ce92011-08-29 23:07:34 +02006687 break;
6688 default:
6689 goto die;
6690 break;
6691 }
6692 break;
thsead93602007-09-06 00:18:15 +00006693 case 2:
6694 switch (sel) {
6695 case 1:
Blue Swirl895c2d02012-09-02 14:52:59 +00006696 gen_helper_mttc0_tcstatus(cpu_env, t0);
thsead93602007-09-06 00:18:15 +00006697 break;
6698 case 2:
Blue Swirl895c2d02012-09-02 14:52:59 +00006699 gen_helper_mttc0_tcbind(cpu_env, t0);
thsead93602007-09-06 00:18:15 +00006700 break;
6701 case 3:
Blue Swirl895c2d02012-09-02 14:52:59 +00006702 gen_helper_mttc0_tcrestart(cpu_env, t0);
thsead93602007-09-06 00:18:15 +00006703 break;
6704 case 4:
Blue Swirl895c2d02012-09-02 14:52:59 +00006705 gen_helper_mttc0_tchalt(cpu_env, t0);
thsead93602007-09-06 00:18:15 +00006706 break;
6707 case 5:
Blue Swirl895c2d02012-09-02 14:52:59 +00006708 gen_helper_mttc0_tccontext(cpu_env, t0);
thsead93602007-09-06 00:18:15 +00006709 break;
6710 case 6:
Blue Swirl895c2d02012-09-02 14:52:59 +00006711 gen_helper_mttc0_tcschedule(cpu_env, t0);
thsead93602007-09-06 00:18:15 +00006712 break;
6713 case 7:
Blue Swirl895c2d02012-09-02 14:52:59 +00006714 gen_helper_mttc0_tcschefback(cpu_env, t0);
thsead93602007-09-06 00:18:15 +00006715 break;
6716 default:
Aurelien Jarnod75c1352013-01-01 18:02:22 +01006717 gen_mtc0(ctx, t0, rd, sel);
thsead93602007-09-06 00:18:15 +00006718 break;
6719 }
6720 break;
6721 case 10:
6722 switch (sel) {
6723 case 0:
Blue Swirl895c2d02012-09-02 14:52:59 +00006724 gen_helper_mttc0_entryhi(cpu_env, t0);
thsead93602007-09-06 00:18:15 +00006725 break;
6726 default:
Aurelien Jarnod75c1352013-01-01 18:02:22 +01006727 gen_mtc0(ctx, t0, rd, sel);
thsead93602007-09-06 00:18:15 +00006728 break;
6729 }
6730 case 12:
6731 switch (sel) {
6732 case 0:
Blue Swirl895c2d02012-09-02 14:52:59 +00006733 gen_helper_mttc0_status(cpu_env, t0);
thsead93602007-09-06 00:18:15 +00006734 break;
6735 default:
Aurelien Jarnod75c1352013-01-01 18:02:22 +01006736 gen_mtc0(ctx, t0, rd, sel);
thsead93602007-09-06 00:18:15 +00006737 break;
6738 }
Edgar E. Iglesias5a25ce92011-08-29 23:07:34 +02006739 case 13:
6740 switch (sel) {
6741 case 0:
Blue Swirl895c2d02012-09-02 14:52:59 +00006742 gen_helper_mttc0_cause(cpu_env, t0);
Edgar E. Iglesias5a25ce92011-08-29 23:07:34 +02006743 break;
6744 default:
6745 goto die;
6746 break;
6747 }
6748 break;
6749 case 15:
6750 switch (sel) {
6751 case 1:
Blue Swirl895c2d02012-09-02 14:52:59 +00006752 gen_helper_mttc0_ebase(cpu_env, t0);
Edgar E. Iglesias5a25ce92011-08-29 23:07:34 +02006753 break;
6754 default:
6755 goto die;
6756 break;
6757 }
6758 break;
thsead93602007-09-06 00:18:15 +00006759 case 23:
6760 switch (sel) {
6761 case 0:
Blue Swirl895c2d02012-09-02 14:52:59 +00006762 gen_helper_mttc0_debug(cpu_env, t0);
thsead93602007-09-06 00:18:15 +00006763 break;
6764 default:
Aurelien Jarnod75c1352013-01-01 18:02:22 +01006765 gen_mtc0(ctx, t0, rd, sel);
thsead93602007-09-06 00:18:15 +00006766 break;
6767 }
6768 break;
6769 default:
Aurelien Jarnod75c1352013-01-01 18:02:22 +01006770 gen_mtc0(ctx, t0, rd, sel);
thsead93602007-09-06 00:18:15 +00006771 }
6772 } else switch (sel) {
6773 /* GPR registers. */
6774 case 0:
Blue Swirl895c2d02012-09-02 14:52:59 +00006775 gen_helper_0e1i(mttgpr, t0, rd);
thsead93602007-09-06 00:18:15 +00006776 break;
6777 /* Auxiliary CPU registers */
6778 case 1:
6779 switch (rd) {
6780 case 0:
Blue Swirl895c2d02012-09-02 14:52:59 +00006781 gen_helper_0e1i(mttlo, t0, 0);
thsead93602007-09-06 00:18:15 +00006782 break;
6783 case 1:
Blue Swirl895c2d02012-09-02 14:52:59 +00006784 gen_helper_0e1i(mtthi, t0, 0);
thsead93602007-09-06 00:18:15 +00006785 break;
6786 case 2:
Blue Swirl895c2d02012-09-02 14:52:59 +00006787 gen_helper_0e1i(mttacx, t0, 0);
thsead93602007-09-06 00:18:15 +00006788 break;
6789 case 4:
Blue Swirl895c2d02012-09-02 14:52:59 +00006790 gen_helper_0e1i(mttlo, t0, 1);
thsead93602007-09-06 00:18:15 +00006791 break;
6792 case 5:
Blue Swirl895c2d02012-09-02 14:52:59 +00006793 gen_helper_0e1i(mtthi, t0, 1);
thsead93602007-09-06 00:18:15 +00006794 break;
6795 case 6:
Blue Swirl895c2d02012-09-02 14:52:59 +00006796 gen_helper_0e1i(mttacx, t0, 1);
thsead93602007-09-06 00:18:15 +00006797 break;
6798 case 8:
Blue Swirl895c2d02012-09-02 14:52:59 +00006799 gen_helper_0e1i(mttlo, t0, 2);
thsead93602007-09-06 00:18:15 +00006800 break;
6801 case 9:
Blue Swirl895c2d02012-09-02 14:52:59 +00006802 gen_helper_0e1i(mtthi, t0, 2);
thsead93602007-09-06 00:18:15 +00006803 break;
6804 case 10:
Blue Swirl895c2d02012-09-02 14:52:59 +00006805 gen_helper_0e1i(mttacx, t0, 2);
thsead93602007-09-06 00:18:15 +00006806 break;
6807 case 12:
Blue Swirl895c2d02012-09-02 14:52:59 +00006808 gen_helper_0e1i(mttlo, t0, 3);
thsead93602007-09-06 00:18:15 +00006809 break;
6810 case 13:
Blue Swirl895c2d02012-09-02 14:52:59 +00006811 gen_helper_0e1i(mtthi, t0, 3);
thsead93602007-09-06 00:18:15 +00006812 break;
6813 case 14:
Blue Swirl895c2d02012-09-02 14:52:59 +00006814 gen_helper_0e1i(mttacx, t0, 3);
thsead93602007-09-06 00:18:15 +00006815 break;
6816 case 16:
Blue Swirl895c2d02012-09-02 14:52:59 +00006817 gen_helper_mttdsp(cpu_env, t0);
thsead93602007-09-06 00:18:15 +00006818 break;
6819 default:
6820 goto die;
6821 }
6822 break;
6823 /* Floating point (COP1). */
6824 case 2:
6825 /* XXX: For now we support only a single FPU context. */
6826 if (h == 0) {
pbrooka7812ae2008-11-17 14:43:54 +00006827 TCGv_i32 fp0 = tcg_temp_new_i32();
thsb6d96be2008-07-09 11:05:10 +00006828
6829 tcg_gen_trunc_tl_i32(fp0, t0);
6830 gen_store_fpr32(fp0, rd);
pbrooka7812ae2008-11-17 14:43:54 +00006831 tcg_temp_free_i32(fp0);
thsead93602007-09-06 00:18:15 +00006832 } else {
pbrooka7812ae2008-11-17 14:43:54 +00006833 TCGv_i32 fp0 = tcg_temp_new_i32();
thsb6d96be2008-07-09 11:05:10 +00006834
6835 tcg_gen_trunc_tl_i32(fp0, t0);
6836 gen_store_fpr32h(fp0, rd);
pbrooka7812ae2008-11-17 14:43:54 +00006837 tcg_temp_free_i32(fp0);
thsead93602007-09-06 00:18:15 +00006838 }
6839 break;
6840 case 3:
6841 /* XXX: For now we support only a single FPU context. */
Blue Swirl895c2d02012-09-02 14:52:59 +00006842 gen_helper_0e1i(ctc1, t0, rd);
thsead93602007-09-06 00:18:15 +00006843 break;
6844 /* COP2: Not implemented. */
6845 case 4:
6846 case 5:
6847 /* fall through */
6848 default:
6849 goto die;
6850 }
aliguorid12d51d2009-01-15 21:48:06 +00006851 LOG_DISAS("mttr (reg %d u %d sel %d h %d)\n", rd, u, sel, h);
ths1a3fd9c2008-06-24 21:58:35 +00006852 tcg_temp_free(t0);
thsead93602007-09-06 00:18:15 +00006853 return;
6854
6855die:
ths1a3fd9c2008-06-24 21:58:35 +00006856 tcg_temp_free(t0);
aliguorid12d51d2009-01-15 21:48:06 +00006857 LOG_DISAS("mttr (reg %d u %d sel %d h %d)\n", rd, u, sel, h);
thsead93602007-09-06 00:18:15 +00006858 generate_exception(ctx, EXCP_RI);
6859}
6860
Andreas Färber7db13fa2012-03-14 01:38:22 +01006861static void gen_cp0 (CPUMIPSState *env, DisasContext *ctx, uint32_t opc, int rt, int rd)
bellard6af0bf92005-07-02 14:58:51 +00006862{
ths287c4b82007-05-11 10:43:55 +00006863 const char *opn = "ldst";
bellard6af0bf92005-07-02 14:58:51 +00006864
Eric Johnson2e154972011-09-17 17:05:32 -07006865 check_cp0_enabled(ctx);
bellard6af0bf92005-07-02 14:58:51 +00006866 switch (opc) {
6867 case OPC_MFC0:
6868 if (rt == 0) {
thsead93602007-09-06 00:18:15 +00006869 /* Treat as NOP. */
bellard6af0bf92005-07-02 14:58:51 +00006870 return;
6871 }
Aurelien Jarnod75c1352013-01-01 18:02:22 +01006872 gen_mfc0(ctx, cpu_gpr[rt], rd, ctx->opcode & 0x7);
bellard6af0bf92005-07-02 14:58:51 +00006873 opn = "mfc0";
6874 break;
6875 case OPC_MTC0:
ths1a3fd9c2008-06-24 21:58:35 +00006876 {
aurel321fc7bf62009-04-08 21:47:35 +00006877 TCGv t0 = tcg_temp_new();
ths1a3fd9c2008-06-24 21:58:35 +00006878
6879 gen_load_gpr(t0, rt);
Aurelien Jarnod75c1352013-01-01 18:02:22 +01006880 gen_mtc0(ctx, t0, rd, ctx->opcode & 0x7);
ths1a3fd9c2008-06-24 21:58:35 +00006881 tcg_temp_free(t0);
6882 }
bellard6af0bf92005-07-02 14:58:51 +00006883 opn = "mtc0";
6884 break;
thsd26bc212007-11-08 18:05:37 +00006885#if defined(TARGET_MIPS64)
ths9c2149c2007-01-23 22:45:22 +00006886 case OPC_DMFC0:
Aurelien Jarnod75c1352013-01-01 18:02:22 +01006887 check_insn(ctx, ISA_MIPS3);
ths9c2149c2007-01-23 22:45:22 +00006888 if (rt == 0) {
thsead93602007-09-06 00:18:15 +00006889 /* Treat as NOP. */
ths9c2149c2007-01-23 22:45:22 +00006890 return;
6891 }
Aurelien Jarnod75c1352013-01-01 18:02:22 +01006892 gen_dmfc0(ctx, cpu_gpr[rt], rd, ctx->opcode & 0x7);
ths9c2149c2007-01-23 22:45:22 +00006893 opn = "dmfc0";
6894 break;
6895 case OPC_DMTC0:
Aurelien Jarnod75c1352013-01-01 18:02:22 +01006896 check_insn(ctx, ISA_MIPS3);
ths1a3fd9c2008-06-24 21:58:35 +00006897 {
aurel321fc7bf62009-04-08 21:47:35 +00006898 TCGv t0 = tcg_temp_new();
ths1a3fd9c2008-06-24 21:58:35 +00006899
6900 gen_load_gpr(t0, rt);
Aurelien Jarnod75c1352013-01-01 18:02:22 +01006901 gen_dmtc0(ctx, t0, rd, ctx->opcode & 0x7);
ths1a3fd9c2008-06-24 21:58:35 +00006902 tcg_temp_free(t0);
6903 }
ths9c2149c2007-01-23 22:45:22 +00006904 opn = "dmtc0";
6905 break;
ths534ce692007-04-11 02:13:00 +00006906#endif
thsead93602007-09-06 00:18:15 +00006907 case OPC_MFTR:
Aurelien Jarnod75c1352013-01-01 18:02:22 +01006908 check_insn(ctx, ASE_MT);
thsead93602007-09-06 00:18:15 +00006909 if (rd == 0) {
6910 /* Treat as NOP. */
6911 return;
6912 }
ths6c5c1e22008-06-24 15:12:27 +00006913 gen_mftr(env, ctx, rt, rd, (ctx->opcode >> 5) & 1,
thsead93602007-09-06 00:18:15 +00006914 ctx->opcode & 0x7, (ctx->opcode >> 4) & 1);
thsead93602007-09-06 00:18:15 +00006915 opn = "mftr";
6916 break;
6917 case OPC_MTTR:
Aurelien Jarnod75c1352013-01-01 18:02:22 +01006918 check_insn(ctx, ASE_MT);
ths6c5c1e22008-06-24 15:12:27 +00006919 gen_mttr(env, ctx, rd, rt, (ctx->opcode >> 5) & 1,
thsead93602007-09-06 00:18:15 +00006920 ctx->opcode & 0x7, (ctx->opcode >> 4) & 1);
6921 opn = "mttr";
6922 break;
bellard6af0bf92005-07-02 14:58:51 +00006923 case OPC_TLBWI:
bellard6af0bf92005-07-02 14:58:51 +00006924 opn = "tlbwi";
aurel32c01fccd2009-03-08 00:06:01 +00006925 if (!env->tlb->helper_tlbwi)
ths29929e32007-05-13 13:49:44 +00006926 goto die;
Blue Swirl895c2d02012-09-02 14:52:59 +00006927 gen_helper_tlbwi(cpu_env);
bellard6af0bf92005-07-02 14:58:51 +00006928 break;
6929 case OPC_TLBWR:
bellard6af0bf92005-07-02 14:58:51 +00006930 opn = "tlbwr";
aurel32c01fccd2009-03-08 00:06:01 +00006931 if (!env->tlb->helper_tlbwr)
ths29929e32007-05-13 13:49:44 +00006932 goto die;
Blue Swirl895c2d02012-09-02 14:52:59 +00006933 gen_helper_tlbwr(cpu_env);
bellard6af0bf92005-07-02 14:58:51 +00006934 break;
6935 case OPC_TLBP:
bellard6af0bf92005-07-02 14:58:51 +00006936 opn = "tlbp";
aurel32c01fccd2009-03-08 00:06:01 +00006937 if (!env->tlb->helper_tlbp)
ths29929e32007-05-13 13:49:44 +00006938 goto die;
Blue Swirl895c2d02012-09-02 14:52:59 +00006939 gen_helper_tlbp(cpu_env);
bellard6af0bf92005-07-02 14:58:51 +00006940 break;
6941 case OPC_TLBR:
bellard6af0bf92005-07-02 14:58:51 +00006942 opn = "tlbr";
aurel32c01fccd2009-03-08 00:06:01 +00006943 if (!env->tlb->helper_tlbr)
ths29929e32007-05-13 13:49:44 +00006944 goto die;
Blue Swirl895c2d02012-09-02 14:52:59 +00006945 gen_helper_tlbr(cpu_env);
bellard6af0bf92005-07-02 14:58:51 +00006946 break;
bellard6af0bf92005-07-02 14:58:51 +00006947 case OPC_ERET:
6948 opn = "eret";
Aurelien Jarnod75c1352013-01-01 18:02:22 +01006949 check_insn(ctx, ISA_MIPS2);
Blue Swirl895c2d02012-09-02 14:52:59 +00006950 gen_helper_eret(cpu_env);
bellard6af0bf92005-07-02 14:58:51 +00006951 ctx->bstate = BS_EXCP;
6952 break;
6953 case OPC_DERET:
6954 opn = "deret";
Aurelien Jarnod75c1352013-01-01 18:02:22 +01006955 check_insn(ctx, ISA_MIPS32);
bellard6af0bf92005-07-02 14:58:51 +00006956 if (!(ctx->hflags & MIPS_HFLAG_DM)) {
ths923617a2007-05-11 00:16:06 +00006957 MIPS_INVAL(opn);
bellard6af0bf92005-07-02 14:58:51 +00006958 generate_exception(ctx, EXCP_RI);
6959 } else {
Blue Swirl895c2d02012-09-02 14:52:59 +00006960 gen_helper_deret(cpu_env);
bellard6af0bf92005-07-02 14:58:51 +00006961 ctx->bstate = BS_EXCP;
6962 }
6963 break;
bellard4ad40f32005-12-05 19:59:36 +00006964 case OPC_WAIT:
6965 opn = "wait";
Aurelien Jarnod75c1352013-01-01 18:02:22 +01006966 check_insn(ctx, ISA_MIPS3 | ISA_MIPS32);
bellard4ad40f32005-12-05 19:59:36 +00006967 /* If we get an exception, we want to restart at next instruction */
6968 ctx->pc += 4;
6969 save_cpu_state(ctx, 1);
6970 ctx->pc -= 4;
Blue Swirl895c2d02012-09-02 14:52:59 +00006971 gen_helper_wait(cpu_env);
bellard4ad40f32005-12-05 19:59:36 +00006972 ctx->bstate = BS_EXCP;
6973 break;
bellard6af0bf92005-07-02 14:58:51 +00006974 default:
ths29929e32007-05-13 13:49:44 +00006975 die:
ths923617a2007-05-11 00:16:06 +00006976 MIPS_INVAL(opn);
bellard6af0bf92005-07-02 14:58:51 +00006977 generate_exception(ctx, EXCP_RI);
6978 return;
6979 }
Blue Swirl2abf3142010-10-13 18:38:08 +00006980 (void)opn; /* avoid a compiler warning */
bellard6af0bf92005-07-02 14:58:51 +00006981 MIPS_DEBUG("%s %s %d", opn, regnames[rt], rd);
6982}
thsf1aa6322008-06-09 07:13:38 +00006983#endif /* !CONFIG_USER_ONLY */
bellard6af0bf92005-07-02 14:58:51 +00006984
bellard6ea83fe2006-06-14 12:56:19 +00006985/* CP1 Branches (before delay slot) */
Aurelien Jarnod75c1352013-01-01 18:02:22 +01006986static void gen_compute_branch1(DisasContext *ctx, uint32_t op,
6987 int32_t cc, int32_t offset)
bellard6ea83fe2006-06-14 12:56:19 +00006988{
6989 target_ulong btarget;
ths923617a2007-05-11 00:16:06 +00006990 const char *opn = "cp1 cond branch";
pbrooka7812ae2008-11-17 14:43:54 +00006991 TCGv_i32 t0 = tcg_temp_new_i32();
bellard6ea83fe2006-06-14 12:56:19 +00006992
thse189e742007-09-24 12:48:00 +00006993 if (cc != 0)
Aurelien Jarnod75c1352013-01-01 18:02:22 +01006994 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32);
thse189e742007-09-24 12:48:00 +00006995
bellard6ea83fe2006-06-14 12:56:19 +00006996 btarget = ctx->pc + 4 + offset;
6997
ths7a387ff2006-12-06 20:17:30 +00006998 switch (op) {
6999 case OPC_BC1F:
aurel32d94536f2009-03-29 15:44:34 +00007000 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
7001 tcg_gen_not_i32(t0, t0);
7002 tcg_gen_andi_i32(t0, t0, 1);
7003 tcg_gen_extu_i32_tl(bcond, t0);
ths923617a2007-05-11 00:16:06 +00007004 opn = "bc1f";
bellard6ea83fe2006-06-14 12:56:19 +00007005 goto not_likely;
ths7a387ff2006-12-06 20:17:30 +00007006 case OPC_BC1FL:
aurel32d94536f2009-03-29 15:44:34 +00007007 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
7008 tcg_gen_not_i32(t0, t0);
7009 tcg_gen_andi_i32(t0, t0, 1);
7010 tcg_gen_extu_i32_tl(bcond, t0);
ths923617a2007-05-11 00:16:06 +00007011 opn = "bc1fl";
bellard6ea83fe2006-06-14 12:56:19 +00007012 goto likely;
ths7a387ff2006-12-06 20:17:30 +00007013 case OPC_BC1T:
aurel32d94536f2009-03-29 15:44:34 +00007014 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
7015 tcg_gen_andi_i32(t0, t0, 1);
7016 tcg_gen_extu_i32_tl(bcond, t0);
ths923617a2007-05-11 00:16:06 +00007017 opn = "bc1t";
ths5a5012e2007-05-07 13:55:33 +00007018 goto not_likely;
ths7a387ff2006-12-06 20:17:30 +00007019 case OPC_BC1TL:
aurel32d94536f2009-03-29 15:44:34 +00007020 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
7021 tcg_gen_andi_i32(t0, t0, 1);
7022 tcg_gen_extu_i32_tl(bcond, t0);
ths923617a2007-05-11 00:16:06 +00007023 opn = "bc1tl";
bellard6ea83fe2006-06-14 12:56:19 +00007024 likely:
7025 ctx->hflags |= MIPS_HFLAG_BL;
7026 break;
ths5a5012e2007-05-07 13:55:33 +00007027 case OPC_BC1FANY2:
thsa16336e2008-06-19 18:35:02 +00007028 {
aurel32d94536f2009-03-29 15:44:34 +00007029 TCGv_i32 t1 = tcg_temp_new_i32();
7030 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
7031 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+1));
Richard Sandifordd7f66b52011-11-26 03:37:07 +00007032 tcg_gen_nand_i32(t0, t0, t1);
aurel32d94536f2009-03-29 15:44:34 +00007033 tcg_temp_free_i32(t1);
aurel32d94536f2009-03-29 15:44:34 +00007034 tcg_gen_andi_i32(t0, t0, 1);
7035 tcg_gen_extu_i32_tl(bcond, t0);
thsa16336e2008-06-19 18:35:02 +00007036 }
thsfd4a04e2007-05-18 11:55:54 +00007037 opn = "bc1any2f";
ths5a5012e2007-05-07 13:55:33 +00007038 goto not_likely;
7039 case OPC_BC1TANY2:
thsa16336e2008-06-19 18:35:02 +00007040 {
aurel32d94536f2009-03-29 15:44:34 +00007041 TCGv_i32 t1 = tcg_temp_new_i32();
7042 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
7043 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+1));
7044 tcg_gen_or_i32(t0, t0, t1);
7045 tcg_temp_free_i32(t1);
7046 tcg_gen_andi_i32(t0, t0, 1);
7047 tcg_gen_extu_i32_tl(bcond, t0);
thsa16336e2008-06-19 18:35:02 +00007048 }
thsfd4a04e2007-05-18 11:55:54 +00007049 opn = "bc1any2t";
ths5a5012e2007-05-07 13:55:33 +00007050 goto not_likely;
7051 case OPC_BC1FANY4:
thsa16336e2008-06-19 18:35:02 +00007052 {
aurel32d94536f2009-03-29 15:44:34 +00007053 TCGv_i32 t1 = tcg_temp_new_i32();
7054 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
7055 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+1));
Richard Sandifordd7f66b52011-11-26 03:37:07 +00007056 tcg_gen_and_i32(t0, t0, t1);
aurel32d94536f2009-03-29 15:44:34 +00007057 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+2));
Richard Sandifordd7f66b52011-11-26 03:37:07 +00007058 tcg_gen_and_i32(t0, t0, t1);
aurel32d94536f2009-03-29 15:44:34 +00007059 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+3));
Richard Sandifordd7f66b52011-11-26 03:37:07 +00007060 tcg_gen_nand_i32(t0, t0, t1);
aurel32d94536f2009-03-29 15:44:34 +00007061 tcg_temp_free_i32(t1);
aurel32d94536f2009-03-29 15:44:34 +00007062 tcg_gen_andi_i32(t0, t0, 1);
7063 tcg_gen_extu_i32_tl(bcond, t0);
thsa16336e2008-06-19 18:35:02 +00007064 }
thsfd4a04e2007-05-18 11:55:54 +00007065 opn = "bc1any4f";
ths5a5012e2007-05-07 13:55:33 +00007066 goto not_likely;
7067 case OPC_BC1TANY4:
thsa16336e2008-06-19 18:35:02 +00007068 {
aurel32d94536f2009-03-29 15:44:34 +00007069 TCGv_i32 t1 = tcg_temp_new_i32();
7070 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
7071 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+1));
7072 tcg_gen_or_i32(t0, t0, t1);
7073 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+2));
7074 tcg_gen_or_i32(t0, t0, t1);
7075 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+3));
7076 tcg_gen_or_i32(t0, t0, t1);
7077 tcg_temp_free_i32(t1);
7078 tcg_gen_andi_i32(t0, t0, 1);
7079 tcg_gen_extu_i32_tl(bcond, t0);
thsa16336e2008-06-19 18:35:02 +00007080 }
thsfd4a04e2007-05-18 11:55:54 +00007081 opn = "bc1any4t";
ths5a5012e2007-05-07 13:55:33 +00007082 not_likely:
7083 ctx->hflags |= MIPS_HFLAG_BC;
ths5a5012e2007-05-07 13:55:33 +00007084 break;
7085 default:
ths923617a2007-05-11 00:16:06 +00007086 MIPS_INVAL(opn);
thse397ee32007-03-23 00:43:28 +00007087 generate_exception (ctx, EXCP_RI);
ths6c5c1e22008-06-24 15:12:27 +00007088 goto out;
bellard6ea83fe2006-06-14 12:56:19 +00007089 }
Blue Swirl2abf3142010-10-13 18:38:08 +00007090 (void)opn; /* avoid a compiler warning */
ths923617a2007-05-11 00:16:06 +00007091 MIPS_DEBUG("%s: cond %02x target " TARGET_FMT_lx, opn,
bellard6ea83fe2006-06-14 12:56:19 +00007092 ctx->hflags, btarget);
7093 ctx->btarget = btarget;
ths6c5c1e22008-06-24 15:12:27 +00007094
7095 out:
pbrooka7812ae2008-11-17 14:43:54 +00007096 tcg_temp_free_i32(t0);
bellard6ea83fe2006-06-14 12:56:19 +00007097}
7098
bellard6af0bf92005-07-02 14:58:51 +00007099/* Coprocessor 1 (FPU) */
ths5a5012e2007-05-07 13:55:33 +00007100
ths5a5012e2007-05-07 13:55:33 +00007101#define FOP(func, fmt) (((fmt) << 21) | (func))
7102
Nathan Froydbf4120a2010-06-08 13:29:56 -07007103enum fopcode {
7104 OPC_ADD_S = FOP(0, FMT_S),
7105 OPC_SUB_S = FOP(1, FMT_S),
7106 OPC_MUL_S = FOP(2, FMT_S),
7107 OPC_DIV_S = FOP(3, FMT_S),
7108 OPC_SQRT_S = FOP(4, FMT_S),
7109 OPC_ABS_S = FOP(5, FMT_S),
7110 OPC_MOV_S = FOP(6, FMT_S),
7111 OPC_NEG_S = FOP(7, FMT_S),
7112 OPC_ROUND_L_S = FOP(8, FMT_S),
7113 OPC_TRUNC_L_S = FOP(9, FMT_S),
7114 OPC_CEIL_L_S = FOP(10, FMT_S),
7115 OPC_FLOOR_L_S = FOP(11, FMT_S),
7116 OPC_ROUND_W_S = FOP(12, FMT_S),
7117 OPC_TRUNC_W_S = FOP(13, FMT_S),
7118 OPC_CEIL_W_S = FOP(14, FMT_S),
7119 OPC_FLOOR_W_S = FOP(15, FMT_S),
7120 OPC_MOVCF_S = FOP(17, FMT_S),
7121 OPC_MOVZ_S = FOP(18, FMT_S),
7122 OPC_MOVN_S = FOP(19, FMT_S),
7123 OPC_RECIP_S = FOP(21, FMT_S),
7124 OPC_RSQRT_S = FOP(22, FMT_S),
7125 OPC_RECIP2_S = FOP(28, FMT_S),
7126 OPC_RECIP1_S = FOP(29, FMT_S),
7127 OPC_RSQRT1_S = FOP(30, FMT_S),
7128 OPC_RSQRT2_S = FOP(31, FMT_S),
7129 OPC_CVT_D_S = FOP(33, FMT_S),
7130 OPC_CVT_W_S = FOP(36, FMT_S),
7131 OPC_CVT_L_S = FOP(37, FMT_S),
7132 OPC_CVT_PS_S = FOP(38, FMT_S),
7133 OPC_CMP_F_S = FOP (48, FMT_S),
7134 OPC_CMP_UN_S = FOP (49, FMT_S),
7135 OPC_CMP_EQ_S = FOP (50, FMT_S),
7136 OPC_CMP_UEQ_S = FOP (51, FMT_S),
7137 OPC_CMP_OLT_S = FOP (52, FMT_S),
7138 OPC_CMP_ULT_S = FOP (53, FMT_S),
7139 OPC_CMP_OLE_S = FOP (54, FMT_S),
7140 OPC_CMP_ULE_S = FOP (55, FMT_S),
7141 OPC_CMP_SF_S = FOP (56, FMT_S),
7142 OPC_CMP_NGLE_S = FOP (57, FMT_S),
7143 OPC_CMP_SEQ_S = FOP (58, FMT_S),
7144 OPC_CMP_NGL_S = FOP (59, FMT_S),
7145 OPC_CMP_LT_S = FOP (60, FMT_S),
7146 OPC_CMP_NGE_S = FOP (61, FMT_S),
7147 OPC_CMP_LE_S = FOP (62, FMT_S),
7148 OPC_CMP_NGT_S = FOP (63, FMT_S),
7149
7150 OPC_ADD_D = FOP(0, FMT_D),
7151 OPC_SUB_D = FOP(1, FMT_D),
7152 OPC_MUL_D = FOP(2, FMT_D),
7153 OPC_DIV_D = FOP(3, FMT_D),
7154 OPC_SQRT_D = FOP(4, FMT_D),
7155 OPC_ABS_D = FOP(5, FMT_D),
7156 OPC_MOV_D = FOP(6, FMT_D),
7157 OPC_NEG_D = FOP(7, FMT_D),
7158 OPC_ROUND_L_D = FOP(8, FMT_D),
7159 OPC_TRUNC_L_D = FOP(9, FMT_D),
7160 OPC_CEIL_L_D = FOP(10, FMT_D),
7161 OPC_FLOOR_L_D = FOP(11, FMT_D),
7162 OPC_ROUND_W_D = FOP(12, FMT_D),
7163 OPC_TRUNC_W_D = FOP(13, FMT_D),
7164 OPC_CEIL_W_D = FOP(14, FMT_D),
7165 OPC_FLOOR_W_D = FOP(15, FMT_D),
7166 OPC_MOVCF_D = FOP(17, FMT_D),
7167 OPC_MOVZ_D = FOP(18, FMT_D),
7168 OPC_MOVN_D = FOP(19, FMT_D),
7169 OPC_RECIP_D = FOP(21, FMT_D),
7170 OPC_RSQRT_D = FOP(22, FMT_D),
7171 OPC_RECIP2_D = FOP(28, FMT_D),
7172 OPC_RECIP1_D = FOP(29, FMT_D),
7173 OPC_RSQRT1_D = FOP(30, FMT_D),
7174 OPC_RSQRT2_D = FOP(31, FMT_D),
7175 OPC_CVT_S_D = FOP(32, FMT_D),
7176 OPC_CVT_W_D = FOP(36, FMT_D),
7177 OPC_CVT_L_D = FOP(37, FMT_D),
7178 OPC_CMP_F_D = FOP (48, FMT_D),
7179 OPC_CMP_UN_D = FOP (49, FMT_D),
7180 OPC_CMP_EQ_D = FOP (50, FMT_D),
7181 OPC_CMP_UEQ_D = FOP (51, FMT_D),
7182 OPC_CMP_OLT_D = FOP (52, FMT_D),
7183 OPC_CMP_ULT_D = FOP (53, FMT_D),
7184 OPC_CMP_OLE_D = FOP (54, FMT_D),
7185 OPC_CMP_ULE_D = FOP (55, FMT_D),
7186 OPC_CMP_SF_D = FOP (56, FMT_D),
7187 OPC_CMP_NGLE_D = FOP (57, FMT_D),
7188 OPC_CMP_SEQ_D = FOP (58, FMT_D),
7189 OPC_CMP_NGL_D = FOP (59, FMT_D),
7190 OPC_CMP_LT_D = FOP (60, FMT_D),
7191 OPC_CMP_NGE_D = FOP (61, FMT_D),
7192 OPC_CMP_LE_D = FOP (62, FMT_D),
7193 OPC_CMP_NGT_D = FOP (63, FMT_D),
7194
7195 OPC_CVT_S_W = FOP(32, FMT_W),
7196 OPC_CVT_D_W = FOP(33, FMT_W),
7197 OPC_CVT_S_L = FOP(32, FMT_L),
7198 OPC_CVT_D_L = FOP(33, FMT_L),
7199 OPC_CVT_PS_PW = FOP(38, FMT_W),
7200
7201 OPC_ADD_PS = FOP(0, FMT_PS),
7202 OPC_SUB_PS = FOP(1, FMT_PS),
7203 OPC_MUL_PS = FOP(2, FMT_PS),
7204 OPC_DIV_PS = FOP(3, FMT_PS),
7205 OPC_ABS_PS = FOP(5, FMT_PS),
7206 OPC_MOV_PS = FOP(6, FMT_PS),
7207 OPC_NEG_PS = FOP(7, FMT_PS),
7208 OPC_MOVCF_PS = FOP(17, FMT_PS),
7209 OPC_MOVZ_PS = FOP(18, FMT_PS),
7210 OPC_MOVN_PS = FOP(19, FMT_PS),
7211 OPC_ADDR_PS = FOP(24, FMT_PS),
7212 OPC_MULR_PS = FOP(26, FMT_PS),
7213 OPC_RECIP2_PS = FOP(28, FMT_PS),
7214 OPC_RECIP1_PS = FOP(29, FMT_PS),
7215 OPC_RSQRT1_PS = FOP(30, FMT_PS),
7216 OPC_RSQRT2_PS = FOP(31, FMT_PS),
7217
7218 OPC_CVT_S_PU = FOP(32, FMT_PS),
7219 OPC_CVT_PW_PS = FOP(36, FMT_PS),
7220 OPC_CVT_S_PL = FOP(40, FMT_PS),
7221 OPC_PLL_PS = FOP(44, FMT_PS),
7222 OPC_PLU_PS = FOP(45, FMT_PS),
7223 OPC_PUL_PS = FOP(46, FMT_PS),
7224 OPC_PUU_PS = FOP(47, FMT_PS),
7225 OPC_CMP_F_PS = FOP (48, FMT_PS),
7226 OPC_CMP_UN_PS = FOP (49, FMT_PS),
7227 OPC_CMP_EQ_PS = FOP (50, FMT_PS),
7228 OPC_CMP_UEQ_PS = FOP (51, FMT_PS),
7229 OPC_CMP_OLT_PS = FOP (52, FMT_PS),
7230 OPC_CMP_ULT_PS = FOP (53, FMT_PS),
7231 OPC_CMP_OLE_PS = FOP (54, FMT_PS),
7232 OPC_CMP_ULE_PS = FOP (55, FMT_PS),
7233 OPC_CMP_SF_PS = FOP (56, FMT_PS),
7234 OPC_CMP_NGLE_PS = FOP (57, FMT_PS),
7235 OPC_CMP_SEQ_PS = FOP (58, FMT_PS),
7236 OPC_CMP_NGL_PS = FOP (59, FMT_PS),
7237 OPC_CMP_LT_PS = FOP (60, FMT_PS),
7238 OPC_CMP_NGE_PS = FOP (61, FMT_PS),
7239 OPC_CMP_LE_PS = FOP (62, FMT_PS),
7240 OPC_CMP_NGT_PS = FOP (63, FMT_PS),
7241};
7242
ths7a387ff2006-12-06 20:17:30 +00007243static void gen_cp1 (DisasContext *ctx, uint32_t opc, int rt, int fs)
bellard6ea83fe2006-06-14 12:56:19 +00007244{
ths923617a2007-05-11 00:16:06 +00007245 const char *opn = "cp1 move";
aurel3272c3a3e2009-04-08 21:47:44 +00007246 TCGv t0 = tcg_temp_new();
bellard6ea83fe2006-06-14 12:56:19 +00007247
7248 switch (opc) {
7249 case OPC_MFC1:
thsb6d96be2008-07-09 11:05:10 +00007250 {
pbrooka7812ae2008-11-17 14:43:54 +00007251 TCGv_i32 fp0 = tcg_temp_new_i32();
thsb6d96be2008-07-09 11:05:10 +00007252
7253 gen_load_fpr32(fp0, fs);
7254 tcg_gen_ext_i32_tl(t0, fp0);
pbrooka7812ae2008-11-17 14:43:54 +00007255 tcg_temp_free_i32(fp0);
aurel3269585492009-01-14 19:40:36 +00007256 }
ths6c5c1e22008-06-24 15:12:27 +00007257 gen_store_gpr(t0, rt);
bellard6ea83fe2006-06-14 12:56:19 +00007258 opn = "mfc1";
7259 break;
7260 case OPC_MTC1:
ths6c5c1e22008-06-24 15:12:27 +00007261 gen_load_gpr(t0, rt);
thsb6d96be2008-07-09 11:05:10 +00007262 {
pbrooka7812ae2008-11-17 14:43:54 +00007263 TCGv_i32 fp0 = tcg_temp_new_i32();
thsb6d96be2008-07-09 11:05:10 +00007264
7265 tcg_gen_trunc_tl_i32(fp0, t0);
7266 gen_store_fpr32(fp0, fs);
pbrooka7812ae2008-11-17 14:43:54 +00007267 tcg_temp_free_i32(fp0);
aurel3269585492009-01-14 19:40:36 +00007268 }
bellard6ea83fe2006-06-14 12:56:19 +00007269 opn = "mtc1";
7270 break;
7271 case OPC_CFC1:
Blue Swirl895c2d02012-09-02 14:52:59 +00007272 gen_helper_1e0i(cfc1, t0, fs);
ths6c5c1e22008-06-24 15:12:27 +00007273 gen_store_gpr(t0, rt);
bellard6ea83fe2006-06-14 12:56:19 +00007274 opn = "cfc1";
7275 break;
7276 case OPC_CTC1:
ths6c5c1e22008-06-24 15:12:27 +00007277 gen_load_gpr(t0, rt);
Blue Swirl895c2d02012-09-02 14:52:59 +00007278 gen_helper_0e1i(ctc1, t0, fs);
bellard6ea83fe2006-06-14 12:56:19 +00007279 opn = "ctc1";
7280 break;
aurel3272c3a3e2009-04-08 21:47:44 +00007281#if defined(TARGET_MIPS64)
ths9c2149c2007-01-23 22:45:22 +00007282 case OPC_DMFC1:
aurel3272c3a3e2009-04-08 21:47:44 +00007283 gen_load_fpr64(ctx, t0, fs);
ths6c5c1e22008-06-24 15:12:27 +00007284 gen_store_gpr(t0, rt);
ths5a5012e2007-05-07 13:55:33 +00007285 opn = "dmfc1";
7286 break;
ths9c2149c2007-01-23 22:45:22 +00007287 case OPC_DMTC1:
ths6c5c1e22008-06-24 15:12:27 +00007288 gen_load_gpr(t0, rt);
aurel3272c3a3e2009-04-08 21:47:44 +00007289 gen_store_fpr64(ctx, t0, fs);
ths5a5012e2007-05-07 13:55:33 +00007290 opn = "dmtc1";
7291 break;
aurel3272c3a3e2009-04-08 21:47:44 +00007292#endif
ths5a5012e2007-05-07 13:55:33 +00007293 case OPC_MFHC1:
thsb6d96be2008-07-09 11:05:10 +00007294 {
pbrooka7812ae2008-11-17 14:43:54 +00007295 TCGv_i32 fp0 = tcg_temp_new_i32();
thsb6d96be2008-07-09 11:05:10 +00007296
7297 gen_load_fpr32h(fp0, fs);
7298 tcg_gen_ext_i32_tl(t0, fp0);
pbrooka7812ae2008-11-17 14:43:54 +00007299 tcg_temp_free_i32(fp0);
aurel3269585492009-01-14 19:40:36 +00007300 }
ths6c5c1e22008-06-24 15:12:27 +00007301 gen_store_gpr(t0, rt);
ths5a5012e2007-05-07 13:55:33 +00007302 opn = "mfhc1";
7303 break;
7304 case OPC_MTHC1:
ths6c5c1e22008-06-24 15:12:27 +00007305 gen_load_gpr(t0, rt);
thsb6d96be2008-07-09 11:05:10 +00007306 {
pbrooka7812ae2008-11-17 14:43:54 +00007307 TCGv_i32 fp0 = tcg_temp_new_i32();
thsb6d96be2008-07-09 11:05:10 +00007308
7309 tcg_gen_trunc_tl_i32(fp0, t0);
7310 gen_store_fpr32h(fp0, fs);
pbrooka7812ae2008-11-17 14:43:54 +00007311 tcg_temp_free_i32(fp0);
aurel3269585492009-01-14 19:40:36 +00007312 }
ths5a5012e2007-05-07 13:55:33 +00007313 opn = "mthc1";
7314 break;
bellard6ea83fe2006-06-14 12:56:19 +00007315 default:
ths923617a2007-05-11 00:16:06 +00007316 MIPS_INVAL(opn);
thse397ee32007-03-23 00:43:28 +00007317 generate_exception (ctx, EXCP_RI);
ths6c5c1e22008-06-24 15:12:27 +00007318 goto out;
bellard6ea83fe2006-06-14 12:56:19 +00007319 }
Blue Swirl2abf3142010-10-13 18:38:08 +00007320 (void)opn; /* avoid a compiler warning */
bellard6ea83fe2006-06-14 12:56:19 +00007321 MIPS_DEBUG("%s %s %s", opn, regnames[rt], fregnames[fs]);
ths6c5c1e22008-06-24 15:12:27 +00007322
7323 out:
7324 tcg_temp_free(t0);
bellard6ea83fe2006-06-14 12:56:19 +00007325}
7326
ths5a5012e2007-05-07 13:55:33 +00007327static void gen_movci (DisasContext *ctx, int rd, int rs, int cc, int tf)
7328{
aurel32af58f9c2009-03-29 15:44:50 +00007329 int l1;
thse214b9b2008-05-23 18:06:27 +00007330 TCGCond cond;
aurel32af58f9c2009-03-29 15:44:50 +00007331 TCGv_i32 t0;
bellard6ea83fe2006-06-14 12:56:19 +00007332
aurel32af58f9c2009-03-29 15:44:50 +00007333 if (rd == 0) {
7334 /* Treat as NOP. */
7335 return;
7336 }
7337
thse214b9b2008-05-23 18:06:27 +00007338 if (tf)
thse214b9b2008-05-23 18:06:27 +00007339 cond = TCG_COND_EQ;
ths27848472008-05-24 19:06:07 +00007340 else
7341 cond = TCG_COND_NE;
thse214b9b2008-05-23 18:06:27 +00007342
aurel32af58f9c2009-03-29 15:44:50 +00007343 l1 = gen_new_label();
7344 t0 = tcg_temp_new_i32();
Nathan Froydfa31af02009-08-25 08:20:00 -07007345 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
aurel32af58f9c2009-03-29 15:44:50 +00007346 tcg_gen_brcondi_i32(cond, t0, 0, l1);
aurel32a4e83382009-04-10 21:41:53 +00007347 tcg_temp_free_i32(t0);
aurel32af58f9c2009-03-29 15:44:50 +00007348 if (rs == 0) {
7349 tcg_gen_movi_tl(cpu_gpr[rd], 0);
7350 } else {
7351 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
7352 }
thse214b9b2008-05-23 18:06:27 +00007353 gen_set_label(l1);
ths5a5012e2007-05-07 13:55:33 +00007354}
bellard6ea83fe2006-06-14 12:56:19 +00007355
thsb6d96be2008-07-09 11:05:10 +00007356static inline void gen_movcf_s (int fs, int fd, int cc, int tf)
thsa16336e2008-06-19 18:35:02 +00007357{
thsa16336e2008-06-19 18:35:02 +00007358 int cond;
aurel32cbc37b22009-03-29 15:45:02 +00007359 TCGv_i32 t0 = tcg_temp_new_i32();
thsa16336e2008-06-19 18:35:02 +00007360 int l1 = gen_new_label();
7361
thsa16336e2008-06-19 18:35:02 +00007362 if (tf)
7363 cond = TCG_COND_EQ;
7364 else
7365 cond = TCG_COND_NE;
7366
Nathan Froydfa31af02009-08-25 08:20:00 -07007367 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
aurel32cbc37b22009-03-29 15:45:02 +00007368 tcg_gen_brcondi_i32(cond, t0, 0, l1);
7369 gen_load_fpr32(t0, fs);
7370 gen_store_fpr32(t0, fd);
thsa16336e2008-06-19 18:35:02 +00007371 gen_set_label(l1);
aurel32cbc37b22009-03-29 15:45:02 +00007372 tcg_temp_free_i32(t0);
ths5a5012e2007-05-07 13:55:33 +00007373}
thsa16336e2008-06-19 18:35:02 +00007374
thsb6d96be2008-07-09 11:05:10 +00007375static inline void gen_movcf_d (DisasContext *ctx, int fs, int fd, int cc, int tf)
thsa16336e2008-06-19 18:35:02 +00007376{
thsa16336e2008-06-19 18:35:02 +00007377 int cond;
aurel32cbc37b22009-03-29 15:45:02 +00007378 TCGv_i32 t0 = tcg_temp_new_i32();
7379 TCGv_i64 fp0;
thsa16336e2008-06-19 18:35:02 +00007380 int l1 = gen_new_label();
7381
thsa16336e2008-06-19 18:35:02 +00007382 if (tf)
7383 cond = TCG_COND_EQ;
7384 else
7385 cond = TCG_COND_NE;
7386
Nathan Froydfa31af02009-08-25 08:20:00 -07007387 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
aurel32cbc37b22009-03-29 15:45:02 +00007388 tcg_gen_brcondi_i32(cond, t0, 0, l1);
aurel32a4e83382009-04-10 21:41:53 +00007389 tcg_temp_free_i32(t0);
aurel3211f94252009-04-10 21:42:18 +00007390 fp0 = tcg_temp_new_i64();
aurel329bf3eb22008-11-11 11:50:43 +00007391 gen_load_fpr64(ctx, fp0, fs);
aurel329bf3eb22008-11-11 11:50:43 +00007392 gen_store_fpr64(ctx, fp0, fd);
pbrooka7812ae2008-11-17 14:43:54 +00007393 tcg_temp_free_i64(fp0);
aurel32cbc37b22009-03-29 15:45:02 +00007394 gen_set_label(l1);
thsa16336e2008-06-19 18:35:02 +00007395}
7396
thsb6d96be2008-07-09 11:05:10 +00007397static inline void gen_movcf_ps (int fs, int fd, int cc, int tf)
thsa16336e2008-06-19 18:35:02 +00007398{
7399 int cond;
aurel32cbc37b22009-03-29 15:45:02 +00007400 TCGv_i32 t0 = tcg_temp_new_i32();
thsa16336e2008-06-19 18:35:02 +00007401 int l1 = gen_new_label();
7402 int l2 = gen_new_label();
7403
7404 if (tf)
7405 cond = TCG_COND_EQ;
7406 else
7407 cond = TCG_COND_NE;
7408
Nathan Froydfa31af02009-08-25 08:20:00 -07007409 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
aurel32cbc37b22009-03-29 15:45:02 +00007410 tcg_gen_brcondi_i32(cond, t0, 0, l1);
7411 gen_load_fpr32(t0, fs);
7412 gen_store_fpr32(t0, fd);
thsa16336e2008-06-19 18:35:02 +00007413 gen_set_label(l1);
aurel329bf3eb22008-11-11 11:50:43 +00007414
Nathan Froydfa31af02009-08-25 08:20:00 -07007415 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc+1));
aurel32cbc37b22009-03-29 15:45:02 +00007416 tcg_gen_brcondi_i32(cond, t0, 0, l2);
7417 gen_load_fpr32h(t0, fs);
7418 gen_store_fpr32h(t0, fd);
aurel3252a0e9e2009-04-10 21:56:32 +00007419 tcg_temp_free_i32(t0);
thsa16336e2008-06-19 18:35:02 +00007420 gen_set_label(l2);
thsa16336e2008-06-19 18:35:02 +00007421}
7422
ths5a5012e2007-05-07 13:55:33 +00007423
Nathan Froydbf4120a2010-06-08 13:29:56 -07007424static void gen_farith (DisasContext *ctx, enum fopcode op1,
ths5e755512007-05-29 16:52:57 +00007425 int ft, int fs, int fd, int cc)
bellard6ea83fe2006-06-14 12:56:19 +00007426{
ths923617a2007-05-11 00:16:06 +00007427 const char *opn = "farith";
bellard6ea83fe2006-06-14 12:56:19 +00007428 const char *condnames[] = {
7429 "c.f",
7430 "c.un",
7431 "c.eq",
7432 "c.ueq",
7433 "c.olt",
7434 "c.ult",
7435 "c.ole",
7436 "c.ule",
7437 "c.sf",
7438 "c.ngle",
7439 "c.seq",
7440 "c.ngl",
7441 "c.lt",
7442 "c.nge",
7443 "c.le",
7444 "c.ngt",
7445 };
ths5a1e8ff2007-05-11 17:08:26 +00007446 const char *condnames_abs[] = {
7447 "cabs.f",
7448 "cabs.un",
7449 "cabs.eq",
7450 "cabs.ueq",
7451 "cabs.olt",
7452 "cabs.ult",
7453 "cabs.ole",
7454 "cabs.ule",
7455 "cabs.sf",
7456 "cabs.ngle",
7457 "cabs.seq",
7458 "cabs.ngl",
7459 "cabs.lt",
7460 "cabs.nge",
7461 "cabs.le",
7462 "cabs.ngt",
7463 };
7464 enum { BINOP, CMPOP, OTHEROP } optype = OTHEROP;
ths7a387ff2006-12-06 20:17:30 +00007465 uint32_t func = ctx->opcode & 0x3f;
7466
Nathan Froydbf4120a2010-06-08 13:29:56 -07007467 switch (op1) {
7468 case OPC_ADD_S:
thsb6d96be2008-07-09 11:05:10 +00007469 {
pbrooka7812ae2008-11-17 14:43:54 +00007470 TCGv_i32 fp0 = tcg_temp_new_i32();
7471 TCGv_i32 fp1 = tcg_temp_new_i32();
thsb6d96be2008-07-09 11:05:10 +00007472
7473 gen_load_fpr32(fp0, fs);
7474 gen_load_fpr32(fp1, ft);
Blue Swirl895c2d02012-09-02 14:52:59 +00007475 gen_helper_float_add_s(fp0, cpu_env, fp0, fp1);
pbrooka7812ae2008-11-17 14:43:54 +00007476 tcg_temp_free_i32(fp1);
thsb6d96be2008-07-09 11:05:10 +00007477 gen_store_fpr32(fp0, fd);
pbrooka7812ae2008-11-17 14:43:54 +00007478 tcg_temp_free_i32(fp0);
thsb6d96be2008-07-09 11:05:10 +00007479 }
ths5a5012e2007-05-07 13:55:33 +00007480 opn = "add.s";
ths5a1e8ff2007-05-11 17:08:26 +00007481 optype = BINOP;
ths5a5012e2007-05-07 13:55:33 +00007482 break;
Nathan Froydbf4120a2010-06-08 13:29:56 -07007483 case OPC_SUB_S:
thsb6d96be2008-07-09 11:05:10 +00007484 {
pbrooka7812ae2008-11-17 14:43:54 +00007485 TCGv_i32 fp0 = tcg_temp_new_i32();
7486 TCGv_i32 fp1 = tcg_temp_new_i32();
thsb6d96be2008-07-09 11:05:10 +00007487
7488 gen_load_fpr32(fp0, fs);
7489 gen_load_fpr32(fp1, ft);
Blue Swirl895c2d02012-09-02 14:52:59 +00007490 gen_helper_float_sub_s(fp0, cpu_env, fp0, fp1);
pbrooka7812ae2008-11-17 14:43:54 +00007491 tcg_temp_free_i32(fp1);
thsb6d96be2008-07-09 11:05:10 +00007492 gen_store_fpr32(fp0, fd);
pbrooka7812ae2008-11-17 14:43:54 +00007493 tcg_temp_free_i32(fp0);
thsb6d96be2008-07-09 11:05:10 +00007494 }
ths5a5012e2007-05-07 13:55:33 +00007495 opn = "sub.s";
ths5a1e8ff2007-05-11 17:08:26 +00007496 optype = BINOP;
ths5a5012e2007-05-07 13:55:33 +00007497 break;
Nathan Froydbf4120a2010-06-08 13:29:56 -07007498 case OPC_MUL_S:
thsb6d96be2008-07-09 11:05:10 +00007499 {
pbrooka7812ae2008-11-17 14:43:54 +00007500 TCGv_i32 fp0 = tcg_temp_new_i32();
7501 TCGv_i32 fp1 = tcg_temp_new_i32();
thsb6d96be2008-07-09 11:05:10 +00007502
7503 gen_load_fpr32(fp0, fs);
7504 gen_load_fpr32(fp1, ft);
Blue Swirl895c2d02012-09-02 14:52:59 +00007505 gen_helper_float_mul_s(fp0, cpu_env, fp0, fp1);
pbrooka7812ae2008-11-17 14:43:54 +00007506 tcg_temp_free_i32(fp1);
thsb6d96be2008-07-09 11:05:10 +00007507 gen_store_fpr32(fp0, fd);
pbrooka7812ae2008-11-17 14:43:54 +00007508 tcg_temp_free_i32(fp0);
thsb6d96be2008-07-09 11:05:10 +00007509 }
ths5a5012e2007-05-07 13:55:33 +00007510 opn = "mul.s";
ths5a1e8ff2007-05-11 17:08:26 +00007511 optype = BINOP;
ths5a5012e2007-05-07 13:55:33 +00007512 break;
Nathan Froydbf4120a2010-06-08 13:29:56 -07007513 case OPC_DIV_S:
thsb6d96be2008-07-09 11:05:10 +00007514 {
pbrooka7812ae2008-11-17 14:43:54 +00007515 TCGv_i32 fp0 = tcg_temp_new_i32();
7516 TCGv_i32 fp1 = tcg_temp_new_i32();
thsb6d96be2008-07-09 11:05:10 +00007517
7518 gen_load_fpr32(fp0, fs);
7519 gen_load_fpr32(fp1, ft);
Blue Swirl895c2d02012-09-02 14:52:59 +00007520 gen_helper_float_div_s(fp0, cpu_env, fp0, fp1);
pbrooka7812ae2008-11-17 14:43:54 +00007521 tcg_temp_free_i32(fp1);
thsb6d96be2008-07-09 11:05:10 +00007522 gen_store_fpr32(fp0, fd);
pbrooka7812ae2008-11-17 14:43:54 +00007523 tcg_temp_free_i32(fp0);
thsb6d96be2008-07-09 11:05:10 +00007524 }
ths5a5012e2007-05-07 13:55:33 +00007525 opn = "div.s";
ths5a1e8ff2007-05-11 17:08:26 +00007526 optype = BINOP;
ths5a5012e2007-05-07 13:55:33 +00007527 break;
Nathan Froydbf4120a2010-06-08 13:29:56 -07007528 case OPC_SQRT_S:
thsb6d96be2008-07-09 11:05:10 +00007529 {
pbrooka7812ae2008-11-17 14:43:54 +00007530 TCGv_i32 fp0 = tcg_temp_new_i32();
thsb6d96be2008-07-09 11:05:10 +00007531
7532 gen_load_fpr32(fp0, fs);
Blue Swirl895c2d02012-09-02 14:52:59 +00007533 gen_helper_float_sqrt_s(fp0, cpu_env, fp0);
thsb6d96be2008-07-09 11:05:10 +00007534 gen_store_fpr32(fp0, fd);
pbrooka7812ae2008-11-17 14:43:54 +00007535 tcg_temp_free_i32(fp0);
thsb6d96be2008-07-09 11:05:10 +00007536 }
ths5a5012e2007-05-07 13:55:33 +00007537 opn = "sqrt.s";
7538 break;
Nathan Froydbf4120a2010-06-08 13:29:56 -07007539 case OPC_ABS_S:
thsb6d96be2008-07-09 11:05:10 +00007540 {
pbrooka7812ae2008-11-17 14:43:54 +00007541 TCGv_i32 fp0 = tcg_temp_new_i32();
thsb6d96be2008-07-09 11:05:10 +00007542
7543 gen_load_fpr32(fp0, fs);
pbrooka7812ae2008-11-17 14:43:54 +00007544 gen_helper_float_abs_s(fp0, fp0);
thsb6d96be2008-07-09 11:05:10 +00007545 gen_store_fpr32(fp0, fd);
pbrooka7812ae2008-11-17 14:43:54 +00007546 tcg_temp_free_i32(fp0);
thsb6d96be2008-07-09 11:05:10 +00007547 }
ths5a5012e2007-05-07 13:55:33 +00007548 opn = "abs.s";
7549 break;
Nathan Froydbf4120a2010-06-08 13:29:56 -07007550 case OPC_MOV_S:
thsb6d96be2008-07-09 11:05:10 +00007551 {
pbrooka7812ae2008-11-17 14:43:54 +00007552 TCGv_i32 fp0 = tcg_temp_new_i32();
thsb6d96be2008-07-09 11:05:10 +00007553
7554 gen_load_fpr32(fp0, fs);
7555 gen_store_fpr32(fp0, fd);
pbrooka7812ae2008-11-17 14:43:54 +00007556 tcg_temp_free_i32(fp0);
thsb6d96be2008-07-09 11:05:10 +00007557 }
ths5a5012e2007-05-07 13:55:33 +00007558 opn = "mov.s";
7559 break;
Nathan Froydbf4120a2010-06-08 13:29:56 -07007560 case OPC_NEG_S:
thsb6d96be2008-07-09 11:05:10 +00007561 {
pbrooka7812ae2008-11-17 14:43:54 +00007562 TCGv_i32 fp0 = tcg_temp_new_i32();
thsb6d96be2008-07-09 11:05:10 +00007563
7564 gen_load_fpr32(fp0, fs);
pbrooka7812ae2008-11-17 14:43:54 +00007565 gen_helper_float_chs_s(fp0, fp0);
thsb6d96be2008-07-09 11:05:10 +00007566 gen_store_fpr32(fp0, fd);
pbrooka7812ae2008-11-17 14:43:54 +00007567 tcg_temp_free_i32(fp0);
thsb6d96be2008-07-09 11:05:10 +00007568 }
ths5a5012e2007-05-07 13:55:33 +00007569 opn = "neg.s";
7570 break;
Nathan Froydbf4120a2010-06-08 13:29:56 -07007571 case OPC_ROUND_L_S:
ths5e755512007-05-29 16:52:57 +00007572 check_cp1_64bitmode(ctx);
thsb6d96be2008-07-09 11:05:10 +00007573 {
pbrooka7812ae2008-11-17 14:43:54 +00007574 TCGv_i32 fp32 = tcg_temp_new_i32();
7575 TCGv_i64 fp64 = tcg_temp_new_i64();
thsb6d96be2008-07-09 11:05:10 +00007576
7577 gen_load_fpr32(fp32, fs);
Blue Swirl895c2d02012-09-02 14:52:59 +00007578 gen_helper_float_roundl_s(fp64, cpu_env, fp32);
pbrooka7812ae2008-11-17 14:43:54 +00007579 tcg_temp_free_i32(fp32);
thsb6d96be2008-07-09 11:05:10 +00007580 gen_store_fpr64(ctx, fp64, fd);
pbrooka7812ae2008-11-17 14:43:54 +00007581 tcg_temp_free_i64(fp64);
thsb6d96be2008-07-09 11:05:10 +00007582 }
ths5a5012e2007-05-07 13:55:33 +00007583 opn = "round.l.s";
7584 break;
Nathan Froydbf4120a2010-06-08 13:29:56 -07007585 case OPC_TRUNC_L_S:
ths5e755512007-05-29 16:52:57 +00007586 check_cp1_64bitmode(ctx);
thsb6d96be2008-07-09 11:05:10 +00007587 {
pbrooka7812ae2008-11-17 14:43:54 +00007588 TCGv_i32 fp32 = tcg_temp_new_i32();
7589 TCGv_i64 fp64 = tcg_temp_new_i64();
thsb6d96be2008-07-09 11:05:10 +00007590
7591 gen_load_fpr32(fp32, fs);
Blue Swirl895c2d02012-09-02 14:52:59 +00007592 gen_helper_float_truncl_s(fp64, cpu_env, fp32);
pbrooka7812ae2008-11-17 14:43:54 +00007593 tcg_temp_free_i32(fp32);
thsb6d96be2008-07-09 11:05:10 +00007594 gen_store_fpr64(ctx, fp64, fd);
pbrooka7812ae2008-11-17 14:43:54 +00007595 tcg_temp_free_i64(fp64);
thsb6d96be2008-07-09 11:05:10 +00007596 }
ths5a5012e2007-05-07 13:55:33 +00007597 opn = "trunc.l.s";
7598 break;
Nathan Froydbf4120a2010-06-08 13:29:56 -07007599 case OPC_CEIL_L_S:
ths5e755512007-05-29 16:52:57 +00007600 check_cp1_64bitmode(ctx);
thsb6d96be2008-07-09 11:05:10 +00007601 {
pbrooka7812ae2008-11-17 14:43:54 +00007602 TCGv_i32 fp32 = tcg_temp_new_i32();
7603 TCGv_i64 fp64 = tcg_temp_new_i64();
thsb6d96be2008-07-09 11:05:10 +00007604
7605 gen_load_fpr32(fp32, fs);
Blue Swirl895c2d02012-09-02 14:52:59 +00007606 gen_helper_float_ceill_s(fp64, cpu_env, fp32);
pbrooka7812ae2008-11-17 14:43:54 +00007607 tcg_temp_free_i32(fp32);
thsb6d96be2008-07-09 11:05:10 +00007608 gen_store_fpr64(ctx, fp64, fd);
pbrooka7812ae2008-11-17 14:43:54 +00007609 tcg_temp_free_i64(fp64);
thsb6d96be2008-07-09 11:05:10 +00007610 }
ths5a5012e2007-05-07 13:55:33 +00007611 opn = "ceil.l.s";
7612 break;
Nathan Froydbf4120a2010-06-08 13:29:56 -07007613 case OPC_FLOOR_L_S:
ths5e755512007-05-29 16:52:57 +00007614 check_cp1_64bitmode(ctx);
thsb6d96be2008-07-09 11:05:10 +00007615 {
pbrooka7812ae2008-11-17 14:43:54 +00007616 TCGv_i32 fp32 = tcg_temp_new_i32();
7617 TCGv_i64 fp64 = tcg_temp_new_i64();
thsb6d96be2008-07-09 11:05:10 +00007618
7619 gen_load_fpr32(fp32, fs);
Blue Swirl895c2d02012-09-02 14:52:59 +00007620 gen_helper_float_floorl_s(fp64, cpu_env, fp32);
pbrooka7812ae2008-11-17 14:43:54 +00007621 tcg_temp_free_i32(fp32);
thsb6d96be2008-07-09 11:05:10 +00007622 gen_store_fpr64(ctx, fp64, fd);
pbrooka7812ae2008-11-17 14:43:54 +00007623 tcg_temp_free_i64(fp64);
thsb6d96be2008-07-09 11:05:10 +00007624 }
ths5a5012e2007-05-07 13:55:33 +00007625 opn = "floor.l.s";
7626 break;
Nathan Froydbf4120a2010-06-08 13:29:56 -07007627 case OPC_ROUND_W_S:
thsb6d96be2008-07-09 11:05:10 +00007628 {
pbrooka7812ae2008-11-17 14:43:54 +00007629 TCGv_i32 fp0 = tcg_temp_new_i32();
thsb6d96be2008-07-09 11:05:10 +00007630
7631 gen_load_fpr32(fp0, fs);
Blue Swirl895c2d02012-09-02 14:52:59 +00007632 gen_helper_float_roundw_s(fp0, cpu_env, fp0);
thsb6d96be2008-07-09 11:05:10 +00007633 gen_store_fpr32(fp0, fd);
pbrooka7812ae2008-11-17 14:43:54 +00007634 tcg_temp_free_i32(fp0);
thsb6d96be2008-07-09 11:05:10 +00007635 }
ths5a5012e2007-05-07 13:55:33 +00007636 opn = "round.w.s";
7637 break;
Nathan Froydbf4120a2010-06-08 13:29:56 -07007638 case OPC_TRUNC_W_S:
thsb6d96be2008-07-09 11:05:10 +00007639 {
pbrooka7812ae2008-11-17 14:43:54 +00007640 TCGv_i32 fp0 = tcg_temp_new_i32();
thsb6d96be2008-07-09 11:05:10 +00007641
7642 gen_load_fpr32(fp0, fs);
Blue Swirl895c2d02012-09-02 14:52:59 +00007643 gen_helper_float_truncw_s(fp0, cpu_env, fp0);
thsb6d96be2008-07-09 11:05:10 +00007644 gen_store_fpr32(fp0, fd);
pbrooka7812ae2008-11-17 14:43:54 +00007645 tcg_temp_free_i32(fp0);
thsb6d96be2008-07-09 11:05:10 +00007646 }
ths5a5012e2007-05-07 13:55:33 +00007647 opn = "trunc.w.s";
7648 break;
Nathan Froydbf4120a2010-06-08 13:29:56 -07007649 case OPC_CEIL_W_S:
thsb6d96be2008-07-09 11:05:10 +00007650 {
pbrooka7812ae2008-11-17 14:43:54 +00007651 TCGv_i32 fp0 = tcg_temp_new_i32();
thsb6d96be2008-07-09 11:05:10 +00007652
7653 gen_load_fpr32(fp0, fs);
Blue Swirl895c2d02012-09-02 14:52:59 +00007654 gen_helper_float_ceilw_s(fp0, cpu_env, fp0);
thsb6d96be2008-07-09 11:05:10 +00007655 gen_store_fpr32(fp0, fd);
pbrooka7812ae2008-11-17 14:43:54 +00007656 tcg_temp_free_i32(fp0);
thsb6d96be2008-07-09 11:05:10 +00007657 }
ths5a5012e2007-05-07 13:55:33 +00007658 opn = "ceil.w.s";
7659 break;
Nathan Froydbf4120a2010-06-08 13:29:56 -07007660 case OPC_FLOOR_W_S:
thsb6d96be2008-07-09 11:05:10 +00007661 {
pbrooka7812ae2008-11-17 14:43:54 +00007662 TCGv_i32 fp0 = tcg_temp_new_i32();
thsb6d96be2008-07-09 11:05:10 +00007663
7664 gen_load_fpr32(fp0, fs);
Blue Swirl895c2d02012-09-02 14:52:59 +00007665 gen_helper_float_floorw_s(fp0, cpu_env, fp0);
thsb6d96be2008-07-09 11:05:10 +00007666 gen_store_fpr32(fp0, fd);
pbrooka7812ae2008-11-17 14:43:54 +00007667 tcg_temp_free_i32(fp0);
thsb6d96be2008-07-09 11:05:10 +00007668 }
ths5a5012e2007-05-07 13:55:33 +00007669 opn = "floor.w.s";
7670 break;
Nathan Froydbf4120a2010-06-08 13:29:56 -07007671 case OPC_MOVCF_S:
thsb6d96be2008-07-09 11:05:10 +00007672 gen_movcf_s(fs, fd, (ft >> 2) & 0x7, ft & 0x1);
ths5a5012e2007-05-07 13:55:33 +00007673 opn = "movcf.s";
7674 break;
Nathan Froydbf4120a2010-06-08 13:29:56 -07007675 case OPC_MOVZ_S:
thsa16336e2008-06-19 18:35:02 +00007676 {
7677 int l1 = gen_new_label();
aurel32c9297f42009-04-08 21:48:27 +00007678 TCGv_i32 fp0;
thsa16336e2008-06-19 18:35:02 +00007679
aurel32c9297f42009-04-08 21:48:27 +00007680 if (ft != 0) {
7681 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[ft], 0, l1);
7682 }
7683 fp0 = tcg_temp_new_i32();
thsb6d96be2008-07-09 11:05:10 +00007684 gen_load_fpr32(fp0, fs);
7685 gen_store_fpr32(fp0, fd);
pbrooka7812ae2008-11-17 14:43:54 +00007686 tcg_temp_free_i32(fp0);
thsa16336e2008-06-19 18:35:02 +00007687 gen_set_label(l1);
7688 }
ths5a5012e2007-05-07 13:55:33 +00007689 opn = "movz.s";
7690 break;
Nathan Froydbf4120a2010-06-08 13:29:56 -07007691 case OPC_MOVN_S:
thsa16336e2008-06-19 18:35:02 +00007692 {
7693 int l1 = gen_new_label();
aurel32c9297f42009-04-08 21:48:27 +00007694 TCGv_i32 fp0;
thsa16336e2008-06-19 18:35:02 +00007695
aurel32c9297f42009-04-08 21:48:27 +00007696 if (ft != 0) {
7697 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[ft], 0, l1);
7698 fp0 = tcg_temp_new_i32();
7699 gen_load_fpr32(fp0, fs);
7700 gen_store_fpr32(fp0, fd);
7701 tcg_temp_free_i32(fp0);
7702 gen_set_label(l1);
7703 }
thsa16336e2008-06-19 18:35:02 +00007704 }
ths5a5012e2007-05-07 13:55:33 +00007705 opn = "movn.s";
7706 break;
Nathan Froydbf4120a2010-06-08 13:29:56 -07007707 case OPC_RECIP_S:
thsb8aa4592007-12-30 15:36:58 +00007708 check_cop1x(ctx);
thsb6d96be2008-07-09 11:05:10 +00007709 {
pbrooka7812ae2008-11-17 14:43:54 +00007710 TCGv_i32 fp0 = tcg_temp_new_i32();
thsb6d96be2008-07-09 11:05:10 +00007711
7712 gen_load_fpr32(fp0, fs);
Blue Swirl895c2d02012-09-02 14:52:59 +00007713 gen_helper_float_recip_s(fp0, cpu_env, fp0);
thsb6d96be2008-07-09 11:05:10 +00007714 gen_store_fpr32(fp0, fd);
pbrooka7812ae2008-11-17 14:43:54 +00007715 tcg_temp_free_i32(fp0);
thsb6d96be2008-07-09 11:05:10 +00007716 }
ths57fa1fb2007-05-19 20:29:41 +00007717 opn = "recip.s";
7718 break;
Nathan Froydbf4120a2010-06-08 13:29:56 -07007719 case OPC_RSQRT_S:
thsb8aa4592007-12-30 15:36:58 +00007720 check_cop1x(ctx);
thsb6d96be2008-07-09 11:05:10 +00007721 {
pbrooka7812ae2008-11-17 14:43:54 +00007722 TCGv_i32 fp0 = tcg_temp_new_i32();
thsb6d96be2008-07-09 11:05:10 +00007723
7724 gen_load_fpr32(fp0, fs);
Blue Swirl895c2d02012-09-02 14:52:59 +00007725 gen_helper_float_rsqrt_s(fp0, cpu_env, fp0);
thsb6d96be2008-07-09 11:05:10 +00007726 gen_store_fpr32(fp0, fd);
pbrooka7812ae2008-11-17 14:43:54 +00007727 tcg_temp_free_i32(fp0);
thsb6d96be2008-07-09 11:05:10 +00007728 }
ths57fa1fb2007-05-19 20:29:41 +00007729 opn = "rsqrt.s";
7730 break;
Nathan Froydbf4120a2010-06-08 13:29:56 -07007731 case OPC_RECIP2_S:
ths5e755512007-05-29 16:52:57 +00007732 check_cp1_64bitmode(ctx);
thsb6d96be2008-07-09 11:05:10 +00007733 {
pbrooka7812ae2008-11-17 14:43:54 +00007734 TCGv_i32 fp0 = tcg_temp_new_i32();
7735 TCGv_i32 fp1 = tcg_temp_new_i32();
thsb6d96be2008-07-09 11:05:10 +00007736
7737 gen_load_fpr32(fp0, fs);
Richard Sandifordd22d7282012-08-27 09:50:38 +01007738 gen_load_fpr32(fp1, ft);
Blue Swirl895c2d02012-09-02 14:52:59 +00007739 gen_helper_float_recip2_s(fp0, cpu_env, fp0, fp1);
pbrooka7812ae2008-11-17 14:43:54 +00007740 tcg_temp_free_i32(fp1);
thsb6d96be2008-07-09 11:05:10 +00007741 gen_store_fpr32(fp0, fd);
pbrooka7812ae2008-11-17 14:43:54 +00007742 tcg_temp_free_i32(fp0);
thsb6d96be2008-07-09 11:05:10 +00007743 }
ths57fa1fb2007-05-19 20:29:41 +00007744 opn = "recip2.s";
7745 break;
Nathan Froydbf4120a2010-06-08 13:29:56 -07007746 case OPC_RECIP1_S:
ths5e755512007-05-29 16:52:57 +00007747 check_cp1_64bitmode(ctx);
thsb6d96be2008-07-09 11:05:10 +00007748 {
pbrooka7812ae2008-11-17 14:43:54 +00007749 TCGv_i32 fp0 = tcg_temp_new_i32();
thsb6d96be2008-07-09 11:05:10 +00007750
7751 gen_load_fpr32(fp0, fs);
Blue Swirl895c2d02012-09-02 14:52:59 +00007752 gen_helper_float_recip1_s(fp0, cpu_env, fp0);
thsb6d96be2008-07-09 11:05:10 +00007753 gen_store_fpr32(fp0, fd);
pbrooka7812ae2008-11-17 14:43:54 +00007754 tcg_temp_free_i32(fp0);
thsb6d96be2008-07-09 11:05:10 +00007755 }
ths57fa1fb2007-05-19 20:29:41 +00007756 opn = "recip1.s";
7757 break;
Nathan Froydbf4120a2010-06-08 13:29:56 -07007758 case OPC_RSQRT1_S:
ths5e755512007-05-29 16:52:57 +00007759 check_cp1_64bitmode(ctx);
thsb6d96be2008-07-09 11:05:10 +00007760 {
pbrooka7812ae2008-11-17 14:43:54 +00007761 TCGv_i32 fp0 = tcg_temp_new_i32();
thsb6d96be2008-07-09 11:05:10 +00007762
7763 gen_load_fpr32(fp0, fs);
Blue Swirl895c2d02012-09-02 14:52:59 +00007764 gen_helper_float_rsqrt1_s(fp0, cpu_env, fp0);
thsb6d96be2008-07-09 11:05:10 +00007765 gen_store_fpr32(fp0, fd);
pbrooka7812ae2008-11-17 14:43:54 +00007766 tcg_temp_free_i32(fp0);
thsb6d96be2008-07-09 11:05:10 +00007767 }
ths57fa1fb2007-05-19 20:29:41 +00007768 opn = "rsqrt1.s";
7769 break;
Nathan Froydbf4120a2010-06-08 13:29:56 -07007770 case OPC_RSQRT2_S:
ths5e755512007-05-29 16:52:57 +00007771 check_cp1_64bitmode(ctx);
thsb6d96be2008-07-09 11:05:10 +00007772 {
pbrooka7812ae2008-11-17 14:43:54 +00007773 TCGv_i32 fp0 = tcg_temp_new_i32();
7774 TCGv_i32 fp1 = tcg_temp_new_i32();
thsb6d96be2008-07-09 11:05:10 +00007775
7776 gen_load_fpr32(fp0, fs);
7777 gen_load_fpr32(fp1, ft);
Blue Swirl895c2d02012-09-02 14:52:59 +00007778 gen_helper_float_rsqrt2_s(fp0, cpu_env, fp0, fp1);
pbrooka7812ae2008-11-17 14:43:54 +00007779 tcg_temp_free_i32(fp1);
thsb6d96be2008-07-09 11:05:10 +00007780 gen_store_fpr32(fp0, fd);
pbrooka7812ae2008-11-17 14:43:54 +00007781 tcg_temp_free_i32(fp0);
thsb6d96be2008-07-09 11:05:10 +00007782 }
ths57fa1fb2007-05-19 20:29:41 +00007783 opn = "rsqrt2.s";
7784 break;
Nathan Froydbf4120a2010-06-08 13:29:56 -07007785 case OPC_CVT_D_S:
ths5e755512007-05-29 16:52:57 +00007786 check_cp1_registers(ctx, fd);
thsb6d96be2008-07-09 11:05:10 +00007787 {
pbrooka7812ae2008-11-17 14:43:54 +00007788 TCGv_i32 fp32 = tcg_temp_new_i32();
7789 TCGv_i64 fp64 = tcg_temp_new_i64();
thsb6d96be2008-07-09 11:05:10 +00007790
7791 gen_load_fpr32(fp32, fs);
Blue Swirl895c2d02012-09-02 14:52:59 +00007792 gen_helper_float_cvtd_s(fp64, cpu_env, fp32);
pbrooka7812ae2008-11-17 14:43:54 +00007793 tcg_temp_free_i32(fp32);
thsb6d96be2008-07-09 11:05:10 +00007794 gen_store_fpr64(ctx, fp64, fd);
pbrooka7812ae2008-11-17 14:43:54 +00007795 tcg_temp_free_i64(fp64);
thsb6d96be2008-07-09 11:05:10 +00007796 }
ths5a5012e2007-05-07 13:55:33 +00007797 opn = "cvt.d.s";
7798 break;
Nathan Froydbf4120a2010-06-08 13:29:56 -07007799 case OPC_CVT_W_S:
thsb6d96be2008-07-09 11:05:10 +00007800 {
pbrooka7812ae2008-11-17 14:43:54 +00007801 TCGv_i32 fp0 = tcg_temp_new_i32();
thsb6d96be2008-07-09 11:05:10 +00007802
7803 gen_load_fpr32(fp0, fs);
Blue Swirl895c2d02012-09-02 14:52:59 +00007804 gen_helper_float_cvtw_s(fp0, cpu_env, fp0);
thsb6d96be2008-07-09 11:05:10 +00007805 gen_store_fpr32(fp0, fd);
pbrooka7812ae2008-11-17 14:43:54 +00007806 tcg_temp_free_i32(fp0);
thsb6d96be2008-07-09 11:05:10 +00007807 }
ths5a5012e2007-05-07 13:55:33 +00007808 opn = "cvt.w.s";
7809 break;
Nathan Froydbf4120a2010-06-08 13:29:56 -07007810 case OPC_CVT_L_S:
ths5e755512007-05-29 16:52:57 +00007811 check_cp1_64bitmode(ctx);
thsb6d96be2008-07-09 11:05:10 +00007812 {
pbrooka7812ae2008-11-17 14:43:54 +00007813 TCGv_i32 fp32 = tcg_temp_new_i32();
7814 TCGv_i64 fp64 = tcg_temp_new_i64();
thsb6d96be2008-07-09 11:05:10 +00007815
7816 gen_load_fpr32(fp32, fs);
Blue Swirl895c2d02012-09-02 14:52:59 +00007817 gen_helper_float_cvtl_s(fp64, cpu_env, fp32);
pbrooka7812ae2008-11-17 14:43:54 +00007818 tcg_temp_free_i32(fp32);
thsb6d96be2008-07-09 11:05:10 +00007819 gen_store_fpr64(ctx, fp64, fd);
pbrooka7812ae2008-11-17 14:43:54 +00007820 tcg_temp_free_i64(fp64);
thsb6d96be2008-07-09 11:05:10 +00007821 }
ths5a5012e2007-05-07 13:55:33 +00007822 opn = "cvt.l.s";
7823 break;
Nathan Froydbf4120a2010-06-08 13:29:56 -07007824 case OPC_CVT_PS_S:
ths5e755512007-05-29 16:52:57 +00007825 check_cp1_64bitmode(ctx);
thsb6d96be2008-07-09 11:05:10 +00007826 {
pbrooka7812ae2008-11-17 14:43:54 +00007827 TCGv_i64 fp64 = tcg_temp_new_i64();
7828 TCGv_i32 fp32_0 = tcg_temp_new_i32();
7829 TCGv_i32 fp32_1 = tcg_temp_new_i32();
thsb6d96be2008-07-09 11:05:10 +00007830
7831 gen_load_fpr32(fp32_0, fs);
7832 gen_load_fpr32(fp32_1, ft);
Richard Sandiford13d24f42012-08-27 09:53:29 +01007833 tcg_gen_concat_i32_i64(fp64, fp32_1, fp32_0);
pbrooka7812ae2008-11-17 14:43:54 +00007834 tcg_temp_free_i32(fp32_1);
7835 tcg_temp_free_i32(fp32_0);
pbrook36aa55d2008-09-21 13:48:32 +00007836 gen_store_fpr64(ctx, fp64, fd);
pbrooka7812ae2008-11-17 14:43:54 +00007837 tcg_temp_free_i64(fp64);
thsb6d96be2008-07-09 11:05:10 +00007838 }
ths5a5012e2007-05-07 13:55:33 +00007839 opn = "cvt.ps.s";
7840 break;
Nathan Froydbf4120a2010-06-08 13:29:56 -07007841 case OPC_CMP_F_S:
7842 case OPC_CMP_UN_S:
7843 case OPC_CMP_EQ_S:
7844 case OPC_CMP_UEQ_S:
7845 case OPC_CMP_OLT_S:
7846 case OPC_CMP_ULT_S:
7847 case OPC_CMP_OLE_S:
7848 case OPC_CMP_ULE_S:
7849 case OPC_CMP_SF_S:
7850 case OPC_CMP_NGLE_S:
7851 case OPC_CMP_SEQ_S:
7852 case OPC_CMP_NGL_S:
7853 case OPC_CMP_LT_S:
7854 case OPC_CMP_NGE_S:
7855 case OPC_CMP_LE_S:
7856 case OPC_CMP_NGT_S:
Nathan Froyd8153667c2010-06-08 13:29:57 -07007857 if (ctx->opcode & (1 << 6)) {
7858 gen_cmpabs_s(ctx, func-48, ft, fs, cc);
7859 opn = condnames_abs[func-48];
7860 } else {
7861 gen_cmp_s(ctx, func-48, ft, fs, cc);
7862 opn = condnames[func-48];
ths5a1e8ff2007-05-11 17:08:26 +00007863 }
ths5a5012e2007-05-07 13:55:33 +00007864 break;
Nathan Froydbf4120a2010-06-08 13:29:56 -07007865 case OPC_ADD_D:
ths5e755512007-05-29 16:52:57 +00007866 check_cp1_registers(ctx, fs | ft | fd);
thsb6d96be2008-07-09 11:05:10 +00007867 {
pbrooka7812ae2008-11-17 14:43:54 +00007868 TCGv_i64 fp0 = tcg_temp_new_i64();
7869 TCGv_i64 fp1 = tcg_temp_new_i64();
thsb6d96be2008-07-09 11:05:10 +00007870
7871 gen_load_fpr64(ctx, fp0, fs);
7872 gen_load_fpr64(ctx, fp1, ft);
Blue Swirl895c2d02012-09-02 14:52:59 +00007873 gen_helper_float_add_d(fp0, cpu_env, fp0, fp1);
pbrooka7812ae2008-11-17 14:43:54 +00007874 tcg_temp_free_i64(fp1);
thsb6d96be2008-07-09 11:05:10 +00007875 gen_store_fpr64(ctx, fp0, fd);
pbrooka7812ae2008-11-17 14:43:54 +00007876 tcg_temp_free_i64(fp0);
thsb6d96be2008-07-09 11:05:10 +00007877 }
bellard6ea83fe2006-06-14 12:56:19 +00007878 opn = "add.d";
ths5a1e8ff2007-05-11 17:08:26 +00007879 optype = BINOP;
bellard6ea83fe2006-06-14 12:56:19 +00007880 break;
Nathan Froydbf4120a2010-06-08 13:29:56 -07007881 case OPC_SUB_D:
ths5e755512007-05-29 16:52:57 +00007882 check_cp1_registers(ctx, fs | ft | fd);
thsb6d96be2008-07-09 11:05:10 +00007883 {
pbrooka7812ae2008-11-17 14:43:54 +00007884 TCGv_i64 fp0 = tcg_temp_new_i64();
7885 TCGv_i64 fp1 = tcg_temp_new_i64();
thsb6d96be2008-07-09 11:05:10 +00007886
7887 gen_load_fpr64(ctx, fp0, fs);
7888 gen_load_fpr64(ctx, fp1, ft);
Blue Swirl895c2d02012-09-02 14:52:59 +00007889 gen_helper_float_sub_d(fp0, cpu_env, fp0, fp1);
pbrooka7812ae2008-11-17 14:43:54 +00007890 tcg_temp_free_i64(fp1);
thsb6d96be2008-07-09 11:05:10 +00007891 gen_store_fpr64(ctx, fp0, fd);
pbrooka7812ae2008-11-17 14:43:54 +00007892 tcg_temp_free_i64(fp0);
thsb6d96be2008-07-09 11:05:10 +00007893 }
bellard6ea83fe2006-06-14 12:56:19 +00007894 opn = "sub.d";
ths5a1e8ff2007-05-11 17:08:26 +00007895 optype = BINOP;
bellard6ea83fe2006-06-14 12:56:19 +00007896 break;
Nathan Froydbf4120a2010-06-08 13:29:56 -07007897 case OPC_MUL_D:
ths5e755512007-05-29 16:52:57 +00007898 check_cp1_registers(ctx, fs | ft | fd);
thsb6d96be2008-07-09 11:05:10 +00007899 {
pbrooka7812ae2008-11-17 14:43:54 +00007900 TCGv_i64 fp0 = tcg_temp_new_i64();
7901 TCGv_i64 fp1 = tcg_temp_new_i64();
thsb6d96be2008-07-09 11:05:10 +00007902
7903 gen_load_fpr64(ctx, fp0, fs);
7904 gen_load_fpr64(ctx, fp1, ft);
Blue Swirl895c2d02012-09-02 14:52:59 +00007905 gen_helper_float_mul_d(fp0, cpu_env, fp0, fp1);
pbrooka7812ae2008-11-17 14:43:54 +00007906 tcg_temp_free_i64(fp1);
thsb6d96be2008-07-09 11:05:10 +00007907 gen_store_fpr64(ctx, fp0, fd);
pbrooka7812ae2008-11-17 14:43:54 +00007908 tcg_temp_free_i64(fp0);
thsb6d96be2008-07-09 11:05:10 +00007909 }
bellard6ea83fe2006-06-14 12:56:19 +00007910 opn = "mul.d";
ths5a1e8ff2007-05-11 17:08:26 +00007911 optype = BINOP;
bellard6ea83fe2006-06-14 12:56:19 +00007912 break;
Nathan Froydbf4120a2010-06-08 13:29:56 -07007913 case OPC_DIV_D:
ths5e755512007-05-29 16:52:57 +00007914 check_cp1_registers(ctx, fs | ft | fd);
thsb6d96be2008-07-09 11:05:10 +00007915 {
pbrooka7812ae2008-11-17 14:43:54 +00007916 TCGv_i64 fp0 = tcg_temp_new_i64();
7917 TCGv_i64 fp1 = tcg_temp_new_i64();
thsb6d96be2008-07-09 11:05:10 +00007918
7919 gen_load_fpr64(ctx, fp0, fs);
7920 gen_load_fpr64(ctx, fp1, ft);
Blue Swirl895c2d02012-09-02 14:52:59 +00007921 gen_helper_float_div_d(fp0, cpu_env, fp0, fp1);
pbrooka7812ae2008-11-17 14:43:54 +00007922 tcg_temp_free_i64(fp1);
thsb6d96be2008-07-09 11:05:10 +00007923 gen_store_fpr64(ctx, fp0, fd);
pbrooka7812ae2008-11-17 14:43:54 +00007924 tcg_temp_free_i64(fp0);
thsb6d96be2008-07-09 11:05:10 +00007925 }
bellard6ea83fe2006-06-14 12:56:19 +00007926 opn = "div.d";
ths5a1e8ff2007-05-11 17:08:26 +00007927 optype = BINOP;
bellard6ea83fe2006-06-14 12:56:19 +00007928 break;
Nathan Froydbf4120a2010-06-08 13:29:56 -07007929 case OPC_SQRT_D:
ths5e755512007-05-29 16:52:57 +00007930 check_cp1_registers(ctx, fs | fd);
thsb6d96be2008-07-09 11:05:10 +00007931 {
pbrooka7812ae2008-11-17 14:43:54 +00007932 TCGv_i64 fp0 = tcg_temp_new_i64();
thsb6d96be2008-07-09 11:05:10 +00007933
7934 gen_load_fpr64(ctx, fp0, fs);
Blue Swirl895c2d02012-09-02 14:52:59 +00007935 gen_helper_float_sqrt_d(fp0, cpu_env, fp0);
thsb6d96be2008-07-09 11:05:10 +00007936 gen_store_fpr64(ctx, fp0, fd);
pbrooka7812ae2008-11-17 14:43:54 +00007937 tcg_temp_free_i64(fp0);
thsb6d96be2008-07-09 11:05:10 +00007938 }
bellard6ea83fe2006-06-14 12:56:19 +00007939 opn = "sqrt.d";
7940 break;
Nathan Froydbf4120a2010-06-08 13:29:56 -07007941 case OPC_ABS_D:
ths5e755512007-05-29 16:52:57 +00007942 check_cp1_registers(ctx, fs | fd);
thsb6d96be2008-07-09 11:05:10 +00007943 {
pbrooka7812ae2008-11-17 14:43:54 +00007944 TCGv_i64 fp0 = tcg_temp_new_i64();
thsb6d96be2008-07-09 11:05:10 +00007945
7946 gen_load_fpr64(ctx, fp0, fs);
pbrooka7812ae2008-11-17 14:43:54 +00007947 gen_helper_float_abs_d(fp0, fp0);
thsb6d96be2008-07-09 11:05:10 +00007948 gen_store_fpr64(ctx, fp0, fd);
pbrooka7812ae2008-11-17 14:43:54 +00007949 tcg_temp_free_i64(fp0);
thsb6d96be2008-07-09 11:05:10 +00007950 }
bellard6ea83fe2006-06-14 12:56:19 +00007951 opn = "abs.d";
7952 break;
Nathan Froydbf4120a2010-06-08 13:29:56 -07007953 case OPC_MOV_D:
ths5e755512007-05-29 16:52:57 +00007954 check_cp1_registers(ctx, fs | fd);
thsb6d96be2008-07-09 11:05:10 +00007955 {
pbrooka7812ae2008-11-17 14:43:54 +00007956 TCGv_i64 fp0 = tcg_temp_new_i64();
thsb6d96be2008-07-09 11:05:10 +00007957
7958 gen_load_fpr64(ctx, fp0, fs);
7959 gen_store_fpr64(ctx, fp0, fd);
pbrooka7812ae2008-11-17 14:43:54 +00007960 tcg_temp_free_i64(fp0);
thsb6d96be2008-07-09 11:05:10 +00007961 }
bellard6ea83fe2006-06-14 12:56:19 +00007962 opn = "mov.d";
7963 break;
Nathan Froydbf4120a2010-06-08 13:29:56 -07007964 case OPC_NEG_D:
ths5e755512007-05-29 16:52:57 +00007965 check_cp1_registers(ctx, fs | fd);
thsb6d96be2008-07-09 11:05:10 +00007966 {
pbrooka7812ae2008-11-17 14:43:54 +00007967 TCGv_i64 fp0 = tcg_temp_new_i64();
thsb6d96be2008-07-09 11:05:10 +00007968
7969 gen_load_fpr64(ctx, fp0, fs);
pbrooka7812ae2008-11-17 14:43:54 +00007970 gen_helper_float_chs_d(fp0, fp0);
thsb6d96be2008-07-09 11:05:10 +00007971 gen_store_fpr64(ctx, fp0, fd);
pbrooka7812ae2008-11-17 14:43:54 +00007972 tcg_temp_free_i64(fp0);
thsb6d96be2008-07-09 11:05:10 +00007973 }
bellard6ea83fe2006-06-14 12:56:19 +00007974 opn = "neg.d";
7975 break;
Nathan Froydbf4120a2010-06-08 13:29:56 -07007976 case OPC_ROUND_L_D:
ths5e755512007-05-29 16:52:57 +00007977 check_cp1_64bitmode(ctx);
thsb6d96be2008-07-09 11:05:10 +00007978 {
pbrooka7812ae2008-11-17 14:43:54 +00007979 TCGv_i64 fp0 = tcg_temp_new_i64();
thsb6d96be2008-07-09 11:05:10 +00007980
7981 gen_load_fpr64(ctx, fp0, fs);
Blue Swirl895c2d02012-09-02 14:52:59 +00007982 gen_helper_float_roundl_d(fp0, cpu_env, fp0);
thsb6d96be2008-07-09 11:05:10 +00007983 gen_store_fpr64(ctx, fp0, fd);
pbrooka7812ae2008-11-17 14:43:54 +00007984 tcg_temp_free_i64(fp0);
thsb6d96be2008-07-09 11:05:10 +00007985 }
ths5a5012e2007-05-07 13:55:33 +00007986 opn = "round.l.d";
7987 break;
Nathan Froydbf4120a2010-06-08 13:29:56 -07007988 case OPC_TRUNC_L_D:
ths5e755512007-05-29 16:52:57 +00007989 check_cp1_64bitmode(ctx);
thsb6d96be2008-07-09 11:05:10 +00007990 {
pbrooka7812ae2008-11-17 14:43:54 +00007991 TCGv_i64 fp0 = tcg_temp_new_i64();
thsb6d96be2008-07-09 11:05:10 +00007992
7993 gen_load_fpr64(ctx, fp0, fs);
Blue Swirl895c2d02012-09-02 14:52:59 +00007994 gen_helper_float_truncl_d(fp0, cpu_env, fp0);
thsb6d96be2008-07-09 11:05:10 +00007995 gen_store_fpr64(ctx, fp0, fd);
pbrooka7812ae2008-11-17 14:43:54 +00007996 tcg_temp_free_i64(fp0);
thsb6d96be2008-07-09 11:05:10 +00007997 }
ths5a5012e2007-05-07 13:55:33 +00007998 opn = "trunc.l.d";
7999 break;
Nathan Froydbf4120a2010-06-08 13:29:56 -07008000 case OPC_CEIL_L_D:
ths5e755512007-05-29 16:52:57 +00008001 check_cp1_64bitmode(ctx);
thsb6d96be2008-07-09 11:05:10 +00008002 {
pbrooka7812ae2008-11-17 14:43:54 +00008003 TCGv_i64 fp0 = tcg_temp_new_i64();
thsb6d96be2008-07-09 11:05:10 +00008004
8005 gen_load_fpr64(ctx, fp0, fs);
Blue Swirl895c2d02012-09-02 14:52:59 +00008006 gen_helper_float_ceill_d(fp0, cpu_env, fp0);
thsb6d96be2008-07-09 11:05:10 +00008007 gen_store_fpr64(ctx, fp0, fd);
pbrooka7812ae2008-11-17 14:43:54 +00008008 tcg_temp_free_i64(fp0);
thsb6d96be2008-07-09 11:05:10 +00008009 }
ths5a5012e2007-05-07 13:55:33 +00008010 opn = "ceil.l.d";
8011 break;
Nathan Froydbf4120a2010-06-08 13:29:56 -07008012 case OPC_FLOOR_L_D:
ths5e755512007-05-29 16:52:57 +00008013 check_cp1_64bitmode(ctx);
thsb6d96be2008-07-09 11:05:10 +00008014 {
pbrooka7812ae2008-11-17 14:43:54 +00008015 TCGv_i64 fp0 = tcg_temp_new_i64();
thsb6d96be2008-07-09 11:05:10 +00008016
8017 gen_load_fpr64(ctx, fp0, fs);
Blue Swirl895c2d02012-09-02 14:52:59 +00008018 gen_helper_float_floorl_d(fp0, cpu_env, fp0);
thsb6d96be2008-07-09 11:05:10 +00008019 gen_store_fpr64(ctx, fp0, fd);
pbrooka7812ae2008-11-17 14:43:54 +00008020 tcg_temp_free_i64(fp0);
thsb6d96be2008-07-09 11:05:10 +00008021 }
ths5a5012e2007-05-07 13:55:33 +00008022 opn = "floor.l.d";
8023 break;
Nathan Froydbf4120a2010-06-08 13:29:56 -07008024 case OPC_ROUND_W_D:
ths5e755512007-05-29 16:52:57 +00008025 check_cp1_registers(ctx, fs);
thsb6d96be2008-07-09 11:05:10 +00008026 {
pbrooka7812ae2008-11-17 14:43:54 +00008027 TCGv_i32 fp32 = tcg_temp_new_i32();
8028 TCGv_i64 fp64 = tcg_temp_new_i64();
thsb6d96be2008-07-09 11:05:10 +00008029
8030 gen_load_fpr64(ctx, fp64, fs);
Blue Swirl895c2d02012-09-02 14:52:59 +00008031 gen_helper_float_roundw_d(fp32, cpu_env, fp64);
pbrooka7812ae2008-11-17 14:43:54 +00008032 tcg_temp_free_i64(fp64);
thsb6d96be2008-07-09 11:05:10 +00008033 gen_store_fpr32(fp32, fd);
pbrooka7812ae2008-11-17 14:43:54 +00008034 tcg_temp_free_i32(fp32);
thsb6d96be2008-07-09 11:05:10 +00008035 }
bellard6ea83fe2006-06-14 12:56:19 +00008036 opn = "round.w.d";
8037 break;
Nathan Froydbf4120a2010-06-08 13:29:56 -07008038 case OPC_TRUNC_W_D:
ths5e755512007-05-29 16:52:57 +00008039 check_cp1_registers(ctx, fs);
thsb6d96be2008-07-09 11:05:10 +00008040 {
pbrooka7812ae2008-11-17 14:43:54 +00008041 TCGv_i32 fp32 = tcg_temp_new_i32();
8042 TCGv_i64 fp64 = tcg_temp_new_i64();
thsb6d96be2008-07-09 11:05:10 +00008043
8044 gen_load_fpr64(ctx, fp64, fs);
Blue Swirl895c2d02012-09-02 14:52:59 +00008045 gen_helper_float_truncw_d(fp32, cpu_env, fp64);
pbrooka7812ae2008-11-17 14:43:54 +00008046 tcg_temp_free_i64(fp64);
thsb6d96be2008-07-09 11:05:10 +00008047 gen_store_fpr32(fp32, fd);
pbrooka7812ae2008-11-17 14:43:54 +00008048 tcg_temp_free_i32(fp32);
thsb6d96be2008-07-09 11:05:10 +00008049 }
bellard6ea83fe2006-06-14 12:56:19 +00008050 opn = "trunc.w.d";
8051 break;
Nathan Froydbf4120a2010-06-08 13:29:56 -07008052 case OPC_CEIL_W_D:
ths5e755512007-05-29 16:52:57 +00008053 check_cp1_registers(ctx, fs);
thsb6d96be2008-07-09 11:05:10 +00008054 {
pbrooka7812ae2008-11-17 14:43:54 +00008055 TCGv_i32 fp32 = tcg_temp_new_i32();
8056 TCGv_i64 fp64 = tcg_temp_new_i64();
thsb6d96be2008-07-09 11:05:10 +00008057
8058 gen_load_fpr64(ctx, fp64, fs);
Blue Swirl895c2d02012-09-02 14:52:59 +00008059 gen_helper_float_ceilw_d(fp32, cpu_env, fp64);
pbrooka7812ae2008-11-17 14:43:54 +00008060 tcg_temp_free_i64(fp64);
thsb6d96be2008-07-09 11:05:10 +00008061 gen_store_fpr32(fp32, fd);
pbrooka7812ae2008-11-17 14:43:54 +00008062 tcg_temp_free_i32(fp32);
thsb6d96be2008-07-09 11:05:10 +00008063 }
bellard6ea83fe2006-06-14 12:56:19 +00008064 opn = "ceil.w.d";
8065 break;
Nathan Froydbf4120a2010-06-08 13:29:56 -07008066 case OPC_FLOOR_W_D:
ths5e755512007-05-29 16:52:57 +00008067 check_cp1_registers(ctx, fs);
thsb6d96be2008-07-09 11:05:10 +00008068 {
pbrooka7812ae2008-11-17 14:43:54 +00008069 TCGv_i32 fp32 = tcg_temp_new_i32();
8070 TCGv_i64 fp64 = tcg_temp_new_i64();
thsb6d96be2008-07-09 11:05:10 +00008071
8072 gen_load_fpr64(ctx, fp64, fs);
Blue Swirl895c2d02012-09-02 14:52:59 +00008073 gen_helper_float_floorw_d(fp32, cpu_env, fp64);
pbrooka7812ae2008-11-17 14:43:54 +00008074 tcg_temp_free_i64(fp64);
thsb6d96be2008-07-09 11:05:10 +00008075 gen_store_fpr32(fp32, fd);
pbrooka7812ae2008-11-17 14:43:54 +00008076 tcg_temp_free_i32(fp32);
thsb6d96be2008-07-09 11:05:10 +00008077 }
ths7a387ff2006-12-06 20:17:30 +00008078 opn = "floor.w.d";
bellard6ea83fe2006-06-14 12:56:19 +00008079 break;
Nathan Froydbf4120a2010-06-08 13:29:56 -07008080 case OPC_MOVCF_D:
thsb6d96be2008-07-09 11:05:10 +00008081 gen_movcf_d(ctx, fs, fd, (ft >> 2) & 0x7, ft & 0x1);
ths5a5012e2007-05-07 13:55:33 +00008082 opn = "movcf.d";
bellarddd016882006-10-23 21:25:11 +00008083 break;
Nathan Froydbf4120a2010-06-08 13:29:56 -07008084 case OPC_MOVZ_D:
thsa16336e2008-06-19 18:35:02 +00008085 {
8086 int l1 = gen_new_label();
aurel32c9297f42009-04-08 21:48:27 +00008087 TCGv_i64 fp0;
thsa16336e2008-06-19 18:35:02 +00008088
aurel32c9297f42009-04-08 21:48:27 +00008089 if (ft != 0) {
8090 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[ft], 0, l1);
8091 }
8092 fp0 = tcg_temp_new_i64();
thsb6d96be2008-07-09 11:05:10 +00008093 gen_load_fpr64(ctx, fp0, fs);
8094 gen_store_fpr64(ctx, fp0, fd);
pbrooka7812ae2008-11-17 14:43:54 +00008095 tcg_temp_free_i64(fp0);
thsa16336e2008-06-19 18:35:02 +00008096 gen_set_label(l1);
8097 }
ths5a5012e2007-05-07 13:55:33 +00008098 opn = "movz.d";
8099 break;
Nathan Froydbf4120a2010-06-08 13:29:56 -07008100 case OPC_MOVN_D:
thsa16336e2008-06-19 18:35:02 +00008101 {
8102 int l1 = gen_new_label();
aurel32c9297f42009-04-08 21:48:27 +00008103 TCGv_i64 fp0;
thsa16336e2008-06-19 18:35:02 +00008104
aurel32c9297f42009-04-08 21:48:27 +00008105 if (ft != 0) {
8106 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[ft], 0, l1);
8107 fp0 = tcg_temp_new_i64();
8108 gen_load_fpr64(ctx, fp0, fs);
8109 gen_store_fpr64(ctx, fp0, fd);
8110 tcg_temp_free_i64(fp0);
8111 gen_set_label(l1);
8112 }
thsa16336e2008-06-19 18:35:02 +00008113 }
ths5a5012e2007-05-07 13:55:33 +00008114 opn = "movn.d";
bellard6ea83fe2006-06-14 12:56:19 +00008115 break;
Nathan Froydbf4120a2010-06-08 13:29:56 -07008116 case OPC_RECIP_D:
thsb8aa4592007-12-30 15:36:58 +00008117 check_cp1_64bitmode(ctx);
thsb6d96be2008-07-09 11:05:10 +00008118 {
pbrooka7812ae2008-11-17 14:43:54 +00008119 TCGv_i64 fp0 = tcg_temp_new_i64();
thsb6d96be2008-07-09 11:05:10 +00008120
8121 gen_load_fpr64(ctx, fp0, fs);
Blue Swirl895c2d02012-09-02 14:52:59 +00008122 gen_helper_float_recip_d(fp0, cpu_env, fp0);
thsb6d96be2008-07-09 11:05:10 +00008123 gen_store_fpr64(ctx, fp0, fd);
pbrooka7812ae2008-11-17 14:43:54 +00008124 tcg_temp_free_i64(fp0);
thsb6d96be2008-07-09 11:05:10 +00008125 }
ths57fa1fb2007-05-19 20:29:41 +00008126 opn = "recip.d";
8127 break;
Nathan Froydbf4120a2010-06-08 13:29:56 -07008128 case OPC_RSQRT_D:
thsb8aa4592007-12-30 15:36:58 +00008129 check_cp1_64bitmode(ctx);
thsb6d96be2008-07-09 11:05:10 +00008130 {
pbrooka7812ae2008-11-17 14:43:54 +00008131 TCGv_i64 fp0 = tcg_temp_new_i64();
thsb6d96be2008-07-09 11:05:10 +00008132
8133 gen_load_fpr64(ctx, fp0, fs);
Blue Swirl895c2d02012-09-02 14:52:59 +00008134 gen_helper_float_rsqrt_d(fp0, cpu_env, fp0);
thsb6d96be2008-07-09 11:05:10 +00008135 gen_store_fpr64(ctx, fp0, fd);
pbrooka7812ae2008-11-17 14:43:54 +00008136 tcg_temp_free_i64(fp0);
thsb6d96be2008-07-09 11:05:10 +00008137 }
ths57fa1fb2007-05-19 20:29:41 +00008138 opn = "rsqrt.d";
8139 break;
Nathan Froydbf4120a2010-06-08 13:29:56 -07008140 case OPC_RECIP2_D:
ths5e755512007-05-29 16:52:57 +00008141 check_cp1_64bitmode(ctx);
thsb6d96be2008-07-09 11:05:10 +00008142 {
pbrooka7812ae2008-11-17 14:43:54 +00008143 TCGv_i64 fp0 = tcg_temp_new_i64();
8144 TCGv_i64 fp1 = tcg_temp_new_i64();
thsb6d96be2008-07-09 11:05:10 +00008145
8146 gen_load_fpr64(ctx, fp0, fs);
8147 gen_load_fpr64(ctx, fp1, ft);
Blue Swirl895c2d02012-09-02 14:52:59 +00008148 gen_helper_float_recip2_d(fp0, cpu_env, fp0, fp1);
pbrooka7812ae2008-11-17 14:43:54 +00008149 tcg_temp_free_i64(fp1);
thsb6d96be2008-07-09 11:05:10 +00008150 gen_store_fpr64(ctx, fp0, fd);
pbrooka7812ae2008-11-17 14:43:54 +00008151 tcg_temp_free_i64(fp0);
thsb6d96be2008-07-09 11:05:10 +00008152 }
ths57fa1fb2007-05-19 20:29:41 +00008153 opn = "recip2.d";
8154 break;
Nathan Froydbf4120a2010-06-08 13:29:56 -07008155 case OPC_RECIP1_D:
ths5e755512007-05-29 16:52:57 +00008156 check_cp1_64bitmode(ctx);
thsb6d96be2008-07-09 11:05:10 +00008157 {
pbrooka7812ae2008-11-17 14:43:54 +00008158 TCGv_i64 fp0 = tcg_temp_new_i64();
thsb6d96be2008-07-09 11:05:10 +00008159
8160 gen_load_fpr64(ctx, fp0, fs);
Blue Swirl895c2d02012-09-02 14:52:59 +00008161 gen_helper_float_recip1_d(fp0, cpu_env, fp0);
thsb6d96be2008-07-09 11:05:10 +00008162 gen_store_fpr64(ctx, fp0, fd);
pbrooka7812ae2008-11-17 14:43:54 +00008163 tcg_temp_free_i64(fp0);
thsb6d96be2008-07-09 11:05:10 +00008164 }
ths57fa1fb2007-05-19 20:29:41 +00008165 opn = "recip1.d";
8166 break;
Nathan Froydbf4120a2010-06-08 13:29:56 -07008167 case OPC_RSQRT1_D:
ths5e755512007-05-29 16:52:57 +00008168 check_cp1_64bitmode(ctx);
thsb6d96be2008-07-09 11:05:10 +00008169 {
pbrooka7812ae2008-11-17 14:43:54 +00008170 TCGv_i64 fp0 = tcg_temp_new_i64();
thsb6d96be2008-07-09 11:05:10 +00008171
8172 gen_load_fpr64(ctx, fp0, fs);
Blue Swirl895c2d02012-09-02 14:52:59 +00008173 gen_helper_float_rsqrt1_d(fp0, cpu_env, fp0);
thsb6d96be2008-07-09 11:05:10 +00008174 gen_store_fpr64(ctx, fp0, fd);
pbrooka7812ae2008-11-17 14:43:54 +00008175 tcg_temp_free_i64(fp0);
thsb6d96be2008-07-09 11:05:10 +00008176 }
ths57fa1fb2007-05-19 20:29:41 +00008177 opn = "rsqrt1.d";
8178 break;
Nathan Froydbf4120a2010-06-08 13:29:56 -07008179 case OPC_RSQRT2_D:
ths5e755512007-05-29 16:52:57 +00008180 check_cp1_64bitmode(ctx);
thsb6d96be2008-07-09 11:05:10 +00008181 {
pbrooka7812ae2008-11-17 14:43:54 +00008182 TCGv_i64 fp0 = tcg_temp_new_i64();
8183 TCGv_i64 fp1 = tcg_temp_new_i64();
thsb6d96be2008-07-09 11:05:10 +00008184
8185 gen_load_fpr64(ctx, fp0, fs);
8186 gen_load_fpr64(ctx, fp1, ft);
Blue Swirl895c2d02012-09-02 14:52:59 +00008187 gen_helper_float_rsqrt2_d(fp0, cpu_env, fp0, fp1);
pbrooka7812ae2008-11-17 14:43:54 +00008188 tcg_temp_free_i64(fp1);
thsb6d96be2008-07-09 11:05:10 +00008189 gen_store_fpr64(ctx, fp0, fd);
pbrooka7812ae2008-11-17 14:43:54 +00008190 tcg_temp_free_i64(fp0);
thsb6d96be2008-07-09 11:05:10 +00008191 }
ths57fa1fb2007-05-19 20:29:41 +00008192 opn = "rsqrt2.d";
8193 break;
Nathan Froydbf4120a2010-06-08 13:29:56 -07008194 case OPC_CMP_F_D:
8195 case OPC_CMP_UN_D:
8196 case OPC_CMP_EQ_D:
8197 case OPC_CMP_UEQ_D:
8198 case OPC_CMP_OLT_D:
8199 case OPC_CMP_ULT_D:
8200 case OPC_CMP_OLE_D:
8201 case OPC_CMP_ULE_D:
8202 case OPC_CMP_SF_D:
8203 case OPC_CMP_NGLE_D:
8204 case OPC_CMP_SEQ_D:
8205 case OPC_CMP_NGL_D:
8206 case OPC_CMP_LT_D:
8207 case OPC_CMP_NGE_D:
8208 case OPC_CMP_LE_D:
8209 case OPC_CMP_NGT_D:
Nathan Froyd8153667c2010-06-08 13:29:57 -07008210 if (ctx->opcode & (1 << 6)) {
8211 gen_cmpabs_d(ctx, func-48, ft, fs, cc);
8212 opn = condnames_abs[func-48];
8213 } else {
8214 gen_cmp_d(ctx, func-48, ft, fs, cc);
8215 opn = condnames[func-48];
ths5a1e8ff2007-05-11 17:08:26 +00008216 }
bellard6ea83fe2006-06-14 12:56:19 +00008217 break;
Nathan Froydbf4120a2010-06-08 13:29:56 -07008218 case OPC_CVT_S_D:
ths5e755512007-05-29 16:52:57 +00008219 check_cp1_registers(ctx, fs);
thsb6d96be2008-07-09 11:05:10 +00008220 {
pbrooka7812ae2008-11-17 14:43:54 +00008221 TCGv_i32 fp32 = tcg_temp_new_i32();
8222 TCGv_i64 fp64 = tcg_temp_new_i64();
thsb6d96be2008-07-09 11:05:10 +00008223
8224 gen_load_fpr64(ctx, fp64, fs);
Blue Swirl895c2d02012-09-02 14:52:59 +00008225 gen_helper_float_cvts_d(fp32, cpu_env, fp64);
pbrooka7812ae2008-11-17 14:43:54 +00008226 tcg_temp_free_i64(fp64);
thsb6d96be2008-07-09 11:05:10 +00008227 gen_store_fpr32(fp32, fd);
pbrooka7812ae2008-11-17 14:43:54 +00008228 tcg_temp_free_i32(fp32);
thsb6d96be2008-07-09 11:05:10 +00008229 }
bellarddd016882006-10-23 21:25:11 +00008230 opn = "cvt.s.d";
8231 break;
Nathan Froydbf4120a2010-06-08 13:29:56 -07008232 case OPC_CVT_W_D:
ths5e755512007-05-29 16:52:57 +00008233 check_cp1_registers(ctx, fs);
thsb6d96be2008-07-09 11:05:10 +00008234 {
pbrooka7812ae2008-11-17 14:43:54 +00008235 TCGv_i32 fp32 = tcg_temp_new_i32();
8236 TCGv_i64 fp64 = tcg_temp_new_i64();
thsb6d96be2008-07-09 11:05:10 +00008237
8238 gen_load_fpr64(ctx, fp64, fs);
Blue Swirl895c2d02012-09-02 14:52:59 +00008239 gen_helper_float_cvtw_d(fp32, cpu_env, fp64);
pbrooka7812ae2008-11-17 14:43:54 +00008240 tcg_temp_free_i64(fp64);
thsb6d96be2008-07-09 11:05:10 +00008241 gen_store_fpr32(fp32, fd);
pbrooka7812ae2008-11-17 14:43:54 +00008242 tcg_temp_free_i32(fp32);
thsb6d96be2008-07-09 11:05:10 +00008243 }
bellard6ea83fe2006-06-14 12:56:19 +00008244 opn = "cvt.w.d";
8245 break;
Nathan Froydbf4120a2010-06-08 13:29:56 -07008246 case OPC_CVT_L_D:
ths5e755512007-05-29 16:52:57 +00008247 check_cp1_64bitmode(ctx);
thsb6d96be2008-07-09 11:05:10 +00008248 {
pbrooka7812ae2008-11-17 14:43:54 +00008249 TCGv_i64 fp0 = tcg_temp_new_i64();
thsb6d96be2008-07-09 11:05:10 +00008250
8251 gen_load_fpr64(ctx, fp0, fs);
Blue Swirl895c2d02012-09-02 14:52:59 +00008252 gen_helper_float_cvtl_d(fp0, cpu_env, fp0);
thsb6d96be2008-07-09 11:05:10 +00008253 gen_store_fpr64(ctx, fp0, fd);
pbrooka7812ae2008-11-17 14:43:54 +00008254 tcg_temp_free_i64(fp0);
thsb6d96be2008-07-09 11:05:10 +00008255 }
ths5a5012e2007-05-07 13:55:33 +00008256 opn = "cvt.l.d";
8257 break;
Nathan Froydbf4120a2010-06-08 13:29:56 -07008258 case OPC_CVT_S_W:
thsb6d96be2008-07-09 11:05:10 +00008259 {
pbrooka7812ae2008-11-17 14:43:54 +00008260 TCGv_i32 fp0 = tcg_temp_new_i32();
thsb6d96be2008-07-09 11:05:10 +00008261
8262 gen_load_fpr32(fp0, fs);
Blue Swirl895c2d02012-09-02 14:52:59 +00008263 gen_helper_float_cvts_w(fp0, cpu_env, fp0);
thsb6d96be2008-07-09 11:05:10 +00008264 gen_store_fpr32(fp0, fd);
pbrooka7812ae2008-11-17 14:43:54 +00008265 tcg_temp_free_i32(fp0);
thsb6d96be2008-07-09 11:05:10 +00008266 }
ths5a5012e2007-05-07 13:55:33 +00008267 opn = "cvt.s.w";
8268 break;
Nathan Froydbf4120a2010-06-08 13:29:56 -07008269 case OPC_CVT_D_W:
ths5e755512007-05-29 16:52:57 +00008270 check_cp1_registers(ctx, fd);
thsb6d96be2008-07-09 11:05:10 +00008271 {
pbrooka7812ae2008-11-17 14:43:54 +00008272 TCGv_i32 fp32 = tcg_temp_new_i32();
8273 TCGv_i64 fp64 = tcg_temp_new_i64();
thsb6d96be2008-07-09 11:05:10 +00008274
8275 gen_load_fpr32(fp32, fs);
Blue Swirl895c2d02012-09-02 14:52:59 +00008276 gen_helper_float_cvtd_w(fp64, cpu_env, fp32);
pbrooka7812ae2008-11-17 14:43:54 +00008277 tcg_temp_free_i32(fp32);
thsb6d96be2008-07-09 11:05:10 +00008278 gen_store_fpr64(ctx, fp64, fd);
pbrooka7812ae2008-11-17 14:43:54 +00008279 tcg_temp_free_i64(fp64);
thsb6d96be2008-07-09 11:05:10 +00008280 }
ths5a5012e2007-05-07 13:55:33 +00008281 opn = "cvt.d.w";
8282 break;
Nathan Froydbf4120a2010-06-08 13:29:56 -07008283 case OPC_CVT_S_L:
ths5e755512007-05-29 16:52:57 +00008284 check_cp1_64bitmode(ctx);
thsb6d96be2008-07-09 11:05:10 +00008285 {
pbrooka7812ae2008-11-17 14:43:54 +00008286 TCGv_i32 fp32 = tcg_temp_new_i32();
8287 TCGv_i64 fp64 = tcg_temp_new_i64();
thsb6d96be2008-07-09 11:05:10 +00008288
8289 gen_load_fpr64(ctx, fp64, fs);
Blue Swirl895c2d02012-09-02 14:52:59 +00008290 gen_helper_float_cvts_l(fp32, cpu_env, fp64);
pbrooka7812ae2008-11-17 14:43:54 +00008291 tcg_temp_free_i64(fp64);
thsb6d96be2008-07-09 11:05:10 +00008292 gen_store_fpr32(fp32, fd);
pbrooka7812ae2008-11-17 14:43:54 +00008293 tcg_temp_free_i32(fp32);
thsb6d96be2008-07-09 11:05:10 +00008294 }
ths5a5012e2007-05-07 13:55:33 +00008295 opn = "cvt.s.l";
8296 break;
Nathan Froydbf4120a2010-06-08 13:29:56 -07008297 case OPC_CVT_D_L:
ths5e755512007-05-29 16:52:57 +00008298 check_cp1_64bitmode(ctx);
thsb6d96be2008-07-09 11:05:10 +00008299 {
pbrooka7812ae2008-11-17 14:43:54 +00008300 TCGv_i64 fp0 = tcg_temp_new_i64();
thsb6d96be2008-07-09 11:05:10 +00008301
8302 gen_load_fpr64(ctx, fp0, fs);
Blue Swirl895c2d02012-09-02 14:52:59 +00008303 gen_helper_float_cvtd_l(fp0, cpu_env, fp0);
thsb6d96be2008-07-09 11:05:10 +00008304 gen_store_fpr64(ctx, fp0, fd);
pbrooka7812ae2008-11-17 14:43:54 +00008305 tcg_temp_free_i64(fp0);
thsb6d96be2008-07-09 11:05:10 +00008306 }
ths5a5012e2007-05-07 13:55:33 +00008307 opn = "cvt.d.l";
8308 break;
Nathan Froydbf4120a2010-06-08 13:29:56 -07008309 case OPC_CVT_PS_PW:
ths5e755512007-05-29 16:52:57 +00008310 check_cp1_64bitmode(ctx);
thsb6d96be2008-07-09 11:05:10 +00008311 {
pbrooka7812ae2008-11-17 14:43:54 +00008312 TCGv_i64 fp0 = tcg_temp_new_i64();
thsb6d96be2008-07-09 11:05:10 +00008313
8314 gen_load_fpr64(ctx, fp0, fs);
Blue Swirl895c2d02012-09-02 14:52:59 +00008315 gen_helper_float_cvtps_pw(fp0, cpu_env, fp0);
thsb6d96be2008-07-09 11:05:10 +00008316 gen_store_fpr64(ctx, fp0, fd);
pbrooka7812ae2008-11-17 14:43:54 +00008317 tcg_temp_free_i64(fp0);
thsb6d96be2008-07-09 11:05:10 +00008318 }
ths5a5012e2007-05-07 13:55:33 +00008319 opn = "cvt.ps.pw";
8320 break;
Nathan Froydbf4120a2010-06-08 13:29:56 -07008321 case OPC_ADD_PS:
ths5e755512007-05-29 16:52:57 +00008322 check_cp1_64bitmode(ctx);
thsb6d96be2008-07-09 11:05:10 +00008323 {
pbrooka7812ae2008-11-17 14:43:54 +00008324 TCGv_i64 fp0 = tcg_temp_new_i64();
8325 TCGv_i64 fp1 = tcg_temp_new_i64();
thsb6d96be2008-07-09 11:05:10 +00008326
8327 gen_load_fpr64(ctx, fp0, fs);
8328 gen_load_fpr64(ctx, fp1, ft);
Blue Swirl895c2d02012-09-02 14:52:59 +00008329 gen_helper_float_add_ps(fp0, cpu_env, fp0, fp1);
pbrooka7812ae2008-11-17 14:43:54 +00008330 tcg_temp_free_i64(fp1);
thsb6d96be2008-07-09 11:05:10 +00008331 gen_store_fpr64(ctx, fp0, fd);
pbrooka7812ae2008-11-17 14:43:54 +00008332 tcg_temp_free_i64(fp0);
thsb6d96be2008-07-09 11:05:10 +00008333 }
ths5a5012e2007-05-07 13:55:33 +00008334 opn = "add.ps";
8335 break;
Nathan Froydbf4120a2010-06-08 13:29:56 -07008336 case OPC_SUB_PS:
ths5e755512007-05-29 16:52:57 +00008337 check_cp1_64bitmode(ctx);
thsb6d96be2008-07-09 11:05:10 +00008338 {
pbrooka7812ae2008-11-17 14:43:54 +00008339 TCGv_i64 fp0 = tcg_temp_new_i64();
8340 TCGv_i64 fp1 = tcg_temp_new_i64();
thsb6d96be2008-07-09 11:05:10 +00008341
8342 gen_load_fpr64(ctx, fp0, fs);
8343 gen_load_fpr64(ctx, fp1, ft);
Blue Swirl895c2d02012-09-02 14:52:59 +00008344 gen_helper_float_sub_ps(fp0, cpu_env, fp0, fp1);
pbrooka7812ae2008-11-17 14:43:54 +00008345 tcg_temp_free_i64(fp1);
thsb6d96be2008-07-09 11:05:10 +00008346 gen_store_fpr64(ctx, fp0, fd);
pbrooka7812ae2008-11-17 14:43:54 +00008347 tcg_temp_free_i64(fp0);
thsb6d96be2008-07-09 11:05:10 +00008348 }
ths5a5012e2007-05-07 13:55:33 +00008349 opn = "sub.ps";
8350 break;
Nathan Froydbf4120a2010-06-08 13:29:56 -07008351 case OPC_MUL_PS:
ths5e755512007-05-29 16:52:57 +00008352 check_cp1_64bitmode(ctx);
thsb6d96be2008-07-09 11:05:10 +00008353 {
pbrooka7812ae2008-11-17 14:43:54 +00008354 TCGv_i64 fp0 = tcg_temp_new_i64();
8355 TCGv_i64 fp1 = tcg_temp_new_i64();
thsb6d96be2008-07-09 11:05:10 +00008356
8357 gen_load_fpr64(ctx, fp0, fs);
8358 gen_load_fpr64(ctx, fp1, ft);
Blue Swirl895c2d02012-09-02 14:52:59 +00008359 gen_helper_float_mul_ps(fp0, cpu_env, fp0, fp1);
pbrooka7812ae2008-11-17 14:43:54 +00008360 tcg_temp_free_i64(fp1);
thsb6d96be2008-07-09 11:05:10 +00008361 gen_store_fpr64(ctx, fp0, fd);
pbrooka7812ae2008-11-17 14:43:54 +00008362 tcg_temp_free_i64(fp0);
thsb6d96be2008-07-09 11:05:10 +00008363 }
ths5a5012e2007-05-07 13:55:33 +00008364 opn = "mul.ps";
8365 break;
Nathan Froydbf4120a2010-06-08 13:29:56 -07008366 case OPC_ABS_PS:
ths5e755512007-05-29 16:52:57 +00008367 check_cp1_64bitmode(ctx);
thsb6d96be2008-07-09 11:05:10 +00008368 {
pbrooka7812ae2008-11-17 14:43:54 +00008369 TCGv_i64 fp0 = tcg_temp_new_i64();
thsb6d96be2008-07-09 11:05:10 +00008370
8371 gen_load_fpr64(ctx, fp0, fs);
pbrooka7812ae2008-11-17 14:43:54 +00008372 gen_helper_float_abs_ps(fp0, fp0);
thsb6d96be2008-07-09 11:05:10 +00008373 gen_store_fpr64(ctx, fp0, fd);
pbrooka7812ae2008-11-17 14:43:54 +00008374 tcg_temp_free_i64(fp0);
thsb6d96be2008-07-09 11:05:10 +00008375 }
ths5a5012e2007-05-07 13:55:33 +00008376 opn = "abs.ps";
8377 break;
Nathan Froydbf4120a2010-06-08 13:29:56 -07008378 case OPC_MOV_PS:
ths5e755512007-05-29 16:52:57 +00008379 check_cp1_64bitmode(ctx);
thsb6d96be2008-07-09 11:05:10 +00008380 {
pbrooka7812ae2008-11-17 14:43:54 +00008381 TCGv_i64 fp0 = tcg_temp_new_i64();
thsb6d96be2008-07-09 11:05:10 +00008382
8383 gen_load_fpr64(ctx, fp0, fs);
8384 gen_store_fpr64(ctx, fp0, fd);
pbrooka7812ae2008-11-17 14:43:54 +00008385 tcg_temp_free_i64(fp0);
thsb6d96be2008-07-09 11:05:10 +00008386 }
ths5a5012e2007-05-07 13:55:33 +00008387 opn = "mov.ps";
8388 break;
Nathan Froydbf4120a2010-06-08 13:29:56 -07008389 case OPC_NEG_PS:
ths5e755512007-05-29 16:52:57 +00008390 check_cp1_64bitmode(ctx);
thsb6d96be2008-07-09 11:05:10 +00008391 {
pbrooka7812ae2008-11-17 14:43:54 +00008392 TCGv_i64 fp0 = tcg_temp_new_i64();
thsb6d96be2008-07-09 11:05:10 +00008393
8394 gen_load_fpr64(ctx, fp0, fs);
pbrooka7812ae2008-11-17 14:43:54 +00008395 gen_helper_float_chs_ps(fp0, fp0);
thsb6d96be2008-07-09 11:05:10 +00008396 gen_store_fpr64(ctx, fp0, fd);
pbrooka7812ae2008-11-17 14:43:54 +00008397 tcg_temp_free_i64(fp0);
thsb6d96be2008-07-09 11:05:10 +00008398 }
ths5a5012e2007-05-07 13:55:33 +00008399 opn = "neg.ps";
8400 break;
Nathan Froydbf4120a2010-06-08 13:29:56 -07008401 case OPC_MOVCF_PS:
ths5e755512007-05-29 16:52:57 +00008402 check_cp1_64bitmode(ctx);
thsb6d96be2008-07-09 11:05:10 +00008403 gen_movcf_ps(fs, fd, (ft >> 2) & 0x7, ft & 0x1);
ths5a5012e2007-05-07 13:55:33 +00008404 opn = "movcf.ps";
8405 break;
Nathan Froydbf4120a2010-06-08 13:29:56 -07008406 case OPC_MOVZ_PS:
ths5e755512007-05-29 16:52:57 +00008407 check_cp1_64bitmode(ctx);
thsa16336e2008-06-19 18:35:02 +00008408 {
8409 int l1 = gen_new_label();
aurel3230a38482009-04-12 08:32:45 +00008410 TCGv_i64 fp0;
thsa16336e2008-06-19 18:35:02 +00008411
aurel32c9297f42009-04-08 21:48:27 +00008412 if (ft != 0)
8413 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[ft], 0, l1);
8414 fp0 = tcg_temp_new_i64();
8415 gen_load_fpr64(ctx, fp0, fs);
8416 gen_store_fpr64(ctx, fp0, fd);
8417 tcg_temp_free_i64(fp0);
thsa16336e2008-06-19 18:35:02 +00008418 gen_set_label(l1);
8419 }
ths5a5012e2007-05-07 13:55:33 +00008420 opn = "movz.ps";
8421 break;
Nathan Froydbf4120a2010-06-08 13:29:56 -07008422 case OPC_MOVN_PS:
ths5e755512007-05-29 16:52:57 +00008423 check_cp1_64bitmode(ctx);
thsa16336e2008-06-19 18:35:02 +00008424 {
8425 int l1 = gen_new_label();
aurel3230a38482009-04-12 08:32:45 +00008426 TCGv_i64 fp0;
thsa16336e2008-06-19 18:35:02 +00008427
aurel32c9297f42009-04-08 21:48:27 +00008428 if (ft != 0) {
8429 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[ft], 0, l1);
8430 fp0 = tcg_temp_new_i64();
8431 gen_load_fpr64(ctx, fp0, fs);
8432 gen_store_fpr64(ctx, fp0, fd);
8433 tcg_temp_free_i64(fp0);
8434 gen_set_label(l1);
8435 }
thsa16336e2008-06-19 18:35:02 +00008436 }
ths5a5012e2007-05-07 13:55:33 +00008437 opn = "movn.ps";
8438 break;
Nathan Froydbf4120a2010-06-08 13:29:56 -07008439 case OPC_ADDR_PS:
ths5e755512007-05-29 16:52:57 +00008440 check_cp1_64bitmode(ctx);
thsb6d96be2008-07-09 11:05:10 +00008441 {
pbrooka7812ae2008-11-17 14:43:54 +00008442 TCGv_i64 fp0 = tcg_temp_new_i64();
8443 TCGv_i64 fp1 = tcg_temp_new_i64();
thsb6d96be2008-07-09 11:05:10 +00008444
8445 gen_load_fpr64(ctx, fp0, ft);
8446 gen_load_fpr64(ctx, fp1, fs);
Blue Swirl895c2d02012-09-02 14:52:59 +00008447 gen_helper_float_addr_ps(fp0, cpu_env, fp0, fp1);
pbrooka7812ae2008-11-17 14:43:54 +00008448 tcg_temp_free_i64(fp1);
thsb6d96be2008-07-09 11:05:10 +00008449 gen_store_fpr64(ctx, fp0, fd);
pbrooka7812ae2008-11-17 14:43:54 +00008450 tcg_temp_free_i64(fp0);
thsb6d96be2008-07-09 11:05:10 +00008451 }
thsfbcc6822007-05-11 09:59:10 +00008452 opn = "addr.ps";
8453 break;
Nathan Froydbf4120a2010-06-08 13:29:56 -07008454 case OPC_MULR_PS:
ths5e755512007-05-29 16:52:57 +00008455 check_cp1_64bitmode(ctx);
thsb6d96be2008-07-09 11:05:10 +00008456 {
pbrooka7812ae2008-11-17 14:43:54 +00008457 TCGv_i64 fp0 = tcg_temp_new_i64();
8458 TCGv_i64 fp1 = tcg_temp_new_i64();
thsb6d96be2008-07-09 11:05:10 +00008459
8460 gen_load_fpr64(ctx, fp0, ft);
8461 gen_load_fpr64(ctx, fp1, fs);
Blue Swirl895c2d02012-09-02 14:52:59 +00008462 gen_helper_float_mulr_ps(fp0, cpu_env, fp0, fp1);
pbrooka7812ae2008-11-17 14:43:54 +00008463 tcg_temp_free_i64(fp1);
thsb6d96be2008-07-09 11:05:10 +00008464 gen_store_fpr64(ctx, fp0, fd);
pbrooka7812ae2008-11-17 14:43:54 +00008465 tcg_temp_free_i64(fp0);
thsb6d96be2008-07-09 11:05:10 +00008466 }
ths57fa1fb2007-05-19 20:29:41 +00008467 opn = "mulr.ps";
8468 break;
Nathan Froydbf4120a2010-06-08 13:29:56 -07008469 case OPC_RECIP2_PS:
ths5e755512007-05-29 16:52:57 +00008470 check_cp1_64bitmode(ctx);
thsb6d96be2008-07-09 11:05:10 +00008471 {
pbrooka7812ae2008-11-17 14:43:54 +00008472 TCGv_i64 fp0 = tcg_temp_new_i64();
8473 TCGv_i64 fp1 = tcg_temp_new_i64();
thsb6d96be2008-07-09 11:05:10 +00008474
8475 gen_load_fpr64(ctx, fp0, fs);
Richard Sandifordd22d7282012-08-27 09:50:38 +01008476 gen_load_fpr64(ctx, fp1, ft);
Blue Swirl895c2d02012-09-02 14:52:59 +00008477 gen_helper_float_recip2_ps(fp0, cpu_env, fp0, fp1);
pbrooka7812ae2008-11-17 14:43:54 +00008478 tcg_temp_free_i64(fp1);
thsb6d96be2008-07-09 11:05:10 +00008479 gen_store_fpr64(ctx, fp0, fd);
pbrooka7812ae2008-11-17 14:43:54 +00008480 tcg_temp_free_i64(fp0);
thsb6d96be2008-07-09 11:05:10 +00008481 }
ths57fa1fb2007-05-19 20:29:41 +00008482 opn = "recip2.ps";
8483 break;
Nathan Froydbf4120a2010-06-08 13:29:56 -07008484 case OPC_RECIP1_PS:
ths5e755512007-05-29 16:52:57 +00008485 check_cp1_64bitmode(ctx);
thsb6d96be2008-07-09 11:05:10 +00008486 {
pbrooka7812ae2008-11-17 14:43:54 +00008487 TCGv_i64 fp0 = tcg_temp_new_i64();
thsb6d96be2008-07-09 11:05:10 +00008488
8489 gen_load_fpr64(ctx, fp0, fs);
Blue Swirl895c2d02012-09-02 14:52:59 +00008490 gen_helper_float_recip1_ps(fp0, cpu_env, fp0);
thsb6d96be2008-07-09 11:05:10 +00008491 gen_store_fpr64(ctx, fp0, fd);
pbrooka7812ae2008-11-17 14:43:54 +00008492 tcg_temp_free_i64(fp0);
thsb6d96be2008-07-09 11:05:10 +00008493 }
ths57fa1fb2007-05-19 20:29:41 +00008494 opn = "recip1.ps";
8495 break;
Nathan Froydbf4120a2010-06-08 13:29:56 -07008496 case OPC_RSQRT1_PS:
ths5e755512007-05-29 16:52:57 +00008497 check_cp1_64bitmode(ctx);
thsb6d96be2008-07-09 11:05:10 +00008498 {
pbrooka7812ae2008-11-17 14:43:54 +00008499 TCGv_i64 fp0 = tcg_temp_new_i64();
thsb6d96be2008-07-09 11:05:10 +00008500
8501 gen_load_fpr64(ctx, fp0, fs);
Blue Swirl895c2d02012-09-02 14:52:59 +00008502 gen_helper_float_rsqrt1_ps(fp0, cpu_env, fp0);
thsb6d96be2008-07-09 11:05:10 +00008503 gen_store_fpr64(ctx, fp0, fd);
pbrooka7812ae2008-11-17 14:43:54 +00008504 tcg_temp_free_i64(fp0);
thsb6d96be2008-07-09 11:05:10 +00008505 }
ths57fa1fb2007-05-19 20:29:41 +00008506 opn = "rsqrt1.ps";
8507 break;
Nathan Froydbf4120a2010-06-08 13:29:56 -07008508 case OPC_RSQRT2_PS:
ths5e755512007-05-29 16:52:57 +00008509 check_cp1_64bitmode(ctx);
thsb6d96be2008-07-09 11:05:10 +00008510 {
pbrooka7812ae2008-11-17 14:43:54 +00008511 TCGv_i64 fp0 = tcg_temp_new_i64();
8512 TCGv_i64 fp1 = tcg_temp_new_i64();
thsb6d96be2008-07-09 11:05:10 +00008513
8514 gen_load_fpr64(ctx, fp0, fs);
8515 gen_load_fpr64(ctx, fp1, ft);
Blue Swirl895c2d02012-09-02 14:52:59 +00008516 gen_helper_float_rsqrt2_ps(fp0, cpu_env, fp0, fp1);
pbrooka7812ae2008-11-17 14:43:54 +00008517 tcg_temp_free_i64(fp1);
thsb6d96be2008-07-09 11:05:10 +00008518 gen_store_fpr64(ctx, fp0, fd);
pbrooka7812ae2008-11-17 14:43:54 +00008519 tcg_temp_free_i64(fp0);
thsb6d96be2008-07-09 11:05:10 +00008520 }
ths57fa1fb2007-05-19 20:29:41 +00008521 opn = "rsqrt2.ps";
8522 break;
Nathan Froydbf4120a2010-06-08 13:29:56 -07008523 case OPC_CVT_S_PU:
ths5e755512007-05-29 16:52:57 +00008524 check_cp1_64bitmode(ctx);
thsb6d96be2008-07-09 11:05:10 +00008525 {
pbrooka7812ae2008-11-17 14:43:54 +00008526 TCGv_i32 fp0 = tcg_temp_new_i32();
thsb6d96be2008-07-09 11:05:10 +00008527
8528 gen_load_fpr32h(fp0, fs);
Blue Swirl895c2d02012-09-02 14:52:59 +00008529 gen_helper_float_cvts_pu(fp0, cpu_env, fp0);
thsb6d96be2008-07-09 11:05:10 +00008530 gen_store_fpr32(fp0, fd);
pbrooka7812ae2008-11-17 14:43:54 +00008531 tcg_temp_free_i32(fp0);
thsb6d96be2008-07-09 11:05:10 +00008532 }
ths5a5012e2007-05-07 13:55:33 +00008533 opn = "cvt.s.pu";
8534 break;
Nathan Froydbf4120a2010-06-08 13:29:56 -07008535 case OPC_CVT_PW_PS:
ths5e755512007-05-29 16:52:57 +00008536 check_cp1_64bitmode(ctx);
thsb6d96be2008-07-09 11:05:10 +00008537 {
pbrooka7812ae2008-11-17 14:43:54 +00008538 TCGv_i64 fp0 = tcg_temp_new_i64();
thsb6d96be2008-07-09 11:05:10 +00008539
8540 gen_load_fpr64(ctx, fp0, fs);
Blue Swirl895c2d02012-09-02 14:52:59 +00008541 gen_helper_float_cvtpw_ps(fp0, cpu_env, fp0);
thsb6d96be2008-07-09 11:05:10 +00008542 gen_store_fpr64(ctx, fp0, fd);
pbrooka7812ae2008-11-17 14:43:54 +00008543 tcg_temp_free_i64(fp0);
thsb6d96be2008-07-09 11:05:10 +00008544 }
ths5a5012e2007-05-07 13:55:33 +00008545 opn = "cvt.pw.ps";
8546 break;
Nathan Froydbf4120a2010-06-08 13:29:56 -07008547 case OPC_CVT_S_PL:
ths5e755512007-05-29 16:52:57 +00008548 check_cp1_64bitmode(ctx);
thsb6d96be2008-07-09 11:05:10 +00008549 {
pbrooka7812ae2008-11-17 14:43:54 +00008550 TCGv_i32 fp0 = tcg_temp_new_i32();
thsb6d96be2008-07-09 11:05:10 +00008551
8552 gen_load_fpr32(fp0, fs);
Blue Swirl895c2d02012-09-02 14:52:59 +00008553 gen_helper_float_cvts_pl(fp0, cpu_env, fp0);
thsb6d96be2008-07-09 11:05:10 +00008554 gen_store_fpr32(fp0, fd);
pbrooka7812ae2008-11-17 14:43:54 +00008555 tcg_temp_free_i32(fp0);
thsb6d96be2008-07-09 11:05:10 +00008556 }
ths5a5012e2007-05-07 13:55:33 +00008557 opn = "cvt.s.pl";
8558 break;
Nathan Froydbf4120a2010-06-08 13:29:56 -07008559 case OPC_PLL_PS:
ths5e755512007-05-29 16:52:57 +00008560 check_cp1_64bitmode(ctx);
thsb6d96be2008-07-09 11:05:10 +00008561 {
pbrooka7812ae2008-11-17 14:43:54 +00008562 TCGv_i32 fp0 = tcg_temp_new_i32();
8563 TCGv_i32 fp1 = tcg_temp_new_i32();
thsb6d96be2008-07-09 11:05:10 +00008564
8565 gen_load_fpr32(fp0, fs);
8566 gen_load_fpr32(fp1, ft);
8567 gen_store_fpr32h(fp0, fd);
8568 gen_store_fpr32(fp1, fd);
pbrooka7812ae2008-11-17 14:43:54 +00008569 tcg_temp_free_i32(fp0);
8570 tcg_temp_free_i32(fp1);
thsb6d96be2008-07-09 11:05:10 +00008571 }
ths5a5012e2007-05-07 13:55:33 +00008572 opn = "pll.ps";
8573 break;
Nathan Froydbf4120a2010-06-08 13:29:56 -07008574 case OPC_PLU_PS:
ths5e755512007-05-29 16:52:57 +00008575 check_cp1_64bitmode(ctx);
thsb6d96be2008-07-09 11:05:10 +00008576 {
pbrooka7812ae2008-11-17 14:43:54 +00008577 TCGv_i32 fp0 = tcg_temp_new_i32();
8578 TCGv_i32 fp1 = tcg_temp_new_i32();
thsb6d96be2008-07-09 11:05:10 +00008579
8580 gen_load_fpr32(fp0, fs);
8581 gen_load_fpr32h(fp1, ft);
8582 gen_store_fpr32(fp1, fd);
8583 gen_store_fpr32h(fp0, fd);
pbrooka7812ae2008-11-17 14:43:54 +00008584 tcg_temp_free_i32(fp0);
8585 tcg_temp_free_i32(fp1);
thsb6d96be2008-07-09 11:05:10 +00008586 }
ths5a5012e2007-05-07 13:55:33 +00008587 opn = "plu.ps";
8588 break;
Nathan Froydbf4120a2010-06-08 13:29:56 -07008589 case OPC_PUL_PS:
ths5e755512007-05-29 16:52:57 +00008590 check_cp1_64bitmode(ctx);
thsb6d96be2008-07-09 11:05:10 +00008591 {
pbrooka7812ae2008-11-17 14:43:54 +00008592 TCGv_i32 fp0 = tcg_temp_new_i32();
8593 TCGv_i32 fp1 = tcg_temp_new_i32();
thsb6d96be2008-07-09 11:05:10 +00008594
8595 gen_load_fpr32h(fp0, fs);
8596 gen_load_fpr32(fp1, ft);
8597 gen_store_fpr32(fp1, fd);
8598 gen_store_fpr32h(fp0, fd);
pbrooka7812ae2008-11-17 14:43:54 +00008599 tcg_temp_free_i32(fp0);
8600 tcg_temp_free_i32(fp1);
thsb6d96be2008-07-09 11:05:10 +00008601 }
ths5a5012e2007-05-07 13:55:33 +00008602 opn = "pul.ps";
8603 break;
Nathan Froydbf4120a2010-06-08 13:29:56 -07008604 case OPC_PUU_PS:
ths5e755512007-05-29 16:52:57 +00008605 check_cp1_64bitmode(ctx);
thsb6d96be2008-07-09 11:05:10 +00008606 {
pbrooka7812ae2008-11-17 14:43:54 +00008607 TCGv_i32 fp0 = tcg_temp_new_i32();
8608 TCGv_i32 fp1 = tcg_temp_new_i32();
thsb6d96be2008-07-09 11:05:10 +00008609
8610 gen_load_fpr32h(fp0, fs);
8611 gen_load_fpr32h(fp1, ft);
8612 gen_store_fpr32(fp1, fd);
8613 gen_store_fpr32h(fp0, fd);
pbrooka7812ae2008-11-17 14:43:54 +00008614 tcg_temp_free_i32(fp0);
8615 tcg_temp_free_i32(fp1);
thsb6d96be2008-07-09 11:05:10 +00008616 }
ths5a5012e2007-05-07 13:55:33 +00008617 opn = "puu.ps";
8618 break;
Nathan Froydbf4120a2010-06-08 13:29:56 -07008619 case OPC_CMP_F_PS:
8620 case OPC_CMP_UN_PS:
8621 case OPC_CMP_EQ_PS:
8622 case OPC_CMP_UEQ_PS:
8623 case OPC_CMP_OLT_PS:
8624 case OPC_CMP_ULT_PS:
8625 case OPC_CMP_OLE_PS:
8626 case OPC_CMP_ULE_PS:
8627 case OPC_CMP_SF_PS:
8628 case OPC_CMP_NGLE_PS:
8629 case OPC_CMP_SEQ_PS:
8630 case OPC_CMP_NGL_PS:
8631 case OPC_CMP_LT_PS:
8632 case OPC_CMP_NGE_PS:
8633 case OPC_CMP_LE_PS:
8634 case OPC_CMP_NGT_PS:
Nathan Froyd8153667c2010-06-08 13:29:57 -07008635 if (ctx->opcode & (1 << 6)) {
8636 gen_cmpabs_ps(ctx, func-48, ft, fs, cc);
8637 opn = condnames_abs[func-48];
8638 } else {
8639 gen_cmp_ps(ctx, func-48, ft, fs, cc);
8640 opn = condnames[func-48];
ths5a1e8ff2007-05-11 17:08:26 +00008641 }
bellard6ea83fe2006-06-14 12:56:19 +00008642 break;
ths5a5012e2007-05-07 13:55:33 +00008643 default:
ths923617a2007-05-11 00:16:06 +00008644 MIPS_INVAL(opn);
thse397ee32007-03-23 00:43:28 +00008645 generate_exception (ctx, EXCP_RI);
bellard6ea83fe2006-06-14 12:56:19 +00008646 return;
8647 }
Blue Swirl2abf3142010-10-13 18:38:08 +00008648 (void)opn; /* avoid a compiler warning */
ths5a1e8ff2007-05-11 17:08:26 +00008649 switch (optype) {
8650 case BINOP:
bellard6ea83fe2006-06-14 12:56:19 +00008651 MIPS_DEBUG("%s %s, %s, %s", opn, fregnames[fd], fregnames[fs], fregnames[ft]);
ths5a1e8ff2007-05-11 17:08:26 +00008652 break;
8653 case CMPOP:
8654 MIPS_DEBUG("%s %s,%s", opn, fregnames[fs], fregnames[ft]);
8655 break;
8656 default:
bellard6ea83fe2006-06-14 12:56:19 +00008657 MIPS_DEBUG("%s %s,%s", opn, fregnames[fd], fregnames[fs]);
ths5a1e8ff2007-05-11 17:08:26 +00008658 break;
8659 }
bellard6ea83fe2006-06-14 12:56:19 +00008660}
bellard6af0bf92005-07-02 14:58:51 +00008661
ths5a5012e2007-05-07 13:55:33 +00008662/* Coprocessor 3 (FPU) */
ths5e755512007-05-29 16:52:57 +00008663static void gen_flt3_ldst (DisasContext *ctx, uint32_t opc,
8664 int fd, int fs, int base, int index)
ths7a387ff2006-12-06 20:17:30 +00008665{
ths923617a2007-05-11 00:16:06 +00008666 const char *opn = "extended float load/store";
ths93b12cc2007-05-20 01:36:29 +00008667 int store = 0;
aurel324e2474d2009-04-08 21:48:10 +00008668 TCGv t0 = tcg_temp_new();
ths7a387ff2006-12-06 20:17:30 +00008669
ths93b12cc2007-05-20 01:36:29 +00008670 if (base == 0) {
ths6c5c1e22008-06-24 15:12:27 +00008671 gen_load_gpr(t0, index);
ths93b12cc2007-05-20 01:36:29 +00008672 } else if (index == 0) {
ths6c5c1e22008-06-24 15:12:27 +00008673 gen_load_gpr(t0, base);
ths93b12cc2007-05-20 01:36:29 +00008674 } else {
Richard Henderson05168672012-03-30 13:16:36 -04008675 gen_op_addr_add(ctx, t0, cpu_gpr[base], cpu_gpr[index]);
ths93b12cc2007-05-20 01:36:29 +00008676 }
ths5a5012e2007-05-07 13:55:33 +00008677 /* Don't do NOP if destination is zero: we must perform the actual
thsead93602007-09-06 00:18:15 +00008678 memory access. */
ths5a5012e2007-05-07 13:55:33 +00008679 switch (opc) {
8680 case OPC_LWXC1:
aurel328c0ab412009-04-17 13:17:26 +00008681 check_cop1x(ctx);
thsb6d96be2008-07-09 11:05:10 +00008682 {
pbrooka7812ae2008-11-17 14:43:54 +00008683 TCGv_i32 fp0 = tcg_temp_new_i32();
thsb6d96be2008-07-09 11:05:10 +00008684
aurel32585c88d2009-04-16 11:51:11 +00008685 tcg_gen_qemu_ld32s(t0, t0, ctx->mem_idx);
8686 tcg_gen_trunc_tl_i32(fp0, t0);
thsb6d96be2008-07-09 11:05:10 +00008687 gen_store_fpr32(fp0, fd);
pbrooka7812ae2008-11-17 14:43:54 +00008688 tcg_temp_free_i32(fp0);
thsb6d96be2008-07-09 11:05:10 +00008689 }
ths5a5012e2007-05-07 13:55:33 +00008690 opn = "lwxc1";
8691 break;
8692 case OPC_LDXC1:
aurel328c0ab412009-04-17 13:17:26 +00008693 check_cop1x(ctx);
8694 check_cp1_registers(ctx, fd);
thsb6d96be2008-07-09 11:05:10 +00008695 {
pbrooka7812ae2008-11-17 14:43:54 +00008696 TCGv_i64 fp0 = tcg_temp_new_i64();
thsb6d96be2008-07-09 11:05:10 +00008697
8698 tcg_gen_qemu_ld64(fp0, t0, ctx->mem_idx);
8699 gen_store_fpr64(ctx, fp0, fd);
pbrooka7812ae2008-11-17 14:43:54 +00008700 tcg_temp_free_i64(fp0);
thsb6d96be2008-07-09 11:05:10 +00008701 }
ths5a5012e2007-05-07 13:55:33 +00008702 opn = "ldxc1";
8703 break;
8704 case OPC_LUXC1:
aurel328c0ab412009-04-17 13:17:26 +00008705 check_cp1_64bitmode(ctx);
ths6c5c1e22008-06-24 15:12:27 +00008706 tcg_gen_andi_tl(t0, t0, ~0x7);
thsb6d96be2008-07-09 11:05:10 +00008707 {
pbrooka7812ae2008-11-17 14:43:54 +00008708 TCGv_i64 fp0 = tcg_temp_new_i64();
thsb6d96be2008-07-09 11:05:10 +00008709
8710 tcg_gen_qemu_ld64(fp0, t0, ctx->mem_idx);
8711 gen_store_fpr64(ctx, fp0, fd);
pbrooka7812ae2008-11-17 14:43:54 +00008712 tcg_temp_free_i64(fp0);
thsb6d96be2008-07-09 11:05:10 +00008713 }
ths5a5012e2007-05-07 13:55:33 +00008714 opn = "luxc1";
8715 break;
8716 case OPC_SWXC1:
aurel328c0ab412009-04-17 13:17:26 +00008717 check_cop1x(ctx);
thsb6d96be2008-07-09 11:05:10 +00008718 {
pbrooka7812ae2008-11-17 14:43:54 +00008719 TCGv_i32 fp0 = tcg_temp_new_i32();
aurel32585c88d2009-04-16 11:51:11 +00008720 TCGv t1 = tcg_temp_new();
thsb6d96be2008-07-09 11:05:10 +00008721
8722 gen_load_fpr32(fp0, fs);
pbrooka7812ae2008-11-17 14:43:54 +00008723 tcg_gen_extu_i32_tl(t1, fp0);
8724 tcg_gen_qemu_st32(t1, t0, ctx->mem_idx);
8725 tcg_temp_free_i32(fp0);
aurel32a6035852009-04-16 12:57:50 +00008726 tcg_temp_free(t1);
thsb6d96be2008-07-09 11:05:10 +00008727 }
ths5a5012e2007-05-07 13:55:33 +00008728 opn = "swxc1";
ths93b12cc2007-05-20 01:36:29 +00008729 store = 1;
ths5a5012e2007-05-07 13:55:33 +00008730 break;
8731 case OPC_SDXC1:
aurel328c0ab412009-04-17 13:17:26 +00008732 check_cop1x(ctx);
8733 check_cp1_registers(ctx, fs);
thsb6d96be2008-07-09 11:05:10 +00008734 {
pbrooka7812ae2008-11-17 14:43:54 +00008735 TCGv_i64 fp0 = tcg_temp_new_i64();
thsb6d96be2008-07-09 11:05:10 +00008736
8737 gen_load_fpr64(ctx, fp0, fs);
8738 tcg_gen_qemu_st64(fp0, t0, ctx->mem_idx);
pbrooka7812ae2008-11-17 14:43:54 +00008739 tcg_temp_free_i64(fp0);
thsb6d96be2008-07-09 11:05:10 +00008740 }
ths5a5012e2007-05-07 13:55:33 +00008741 opn = "sdxc1";
ths93b12cc2007-05-20 01:36:29 +00008742 store = 1;
ths5a5012e2007-05-07 13:55:33 +00008743 break;
8744 case OPC_SUXC1:
aurel328c0ab412009-04-17 13:17:26 +00008745 check_cp1_64bitmode(ctx);
ths6c5c1e22008-06-24 15:12:27 +00008746 tcg_gen_andi_tl(t0, t0, ~0x7);
thsb6d96be2008-07-09 11:05:10 +00008747 {
pbrooka7812ae2008-11-17 14:43:54 +00008748 TCGv_i64 fp0 = tcg_temp_new_i64();
thsb6d96be2008-07-09 11:05:10 +00008749
8750 gen_load_fpr64(ctx, fp0, fs);
8751 tcg_gen_qemu_st64(fp0, t0, ctx->mem_idx);
pbrooka7812ae2008-11-17 14:43:54 +00008752 tcg_temp_free_i64(fp0);
thsb6d96be2008-07-09 11:05:10 +00008753 }
ths5a5012e2007-05-07 13:55:33 +00008754 opn = "suxc1";
ths93b12cc2007-05-20 01:36:29 +00008755 store = 1;
ths5a5012e2007-05-07 13:55:33 +00008756 break;
ths5a5012e2007-05-07 13:55:33 +00008757 }
ths6c5c1e22008-06-24 15:12:27 +00008758 tcg_temp_free(t0);
Blue Swirl2abf3142010-10-13 18:38:08 +00008759 (void)opn; (void)store; /* avoid compiler warnings */
ths93b12cc2007-05-20 01:36:29 +00008760 MIPS_DEBUG("%s %s, %s(%s)", opn, fregnames[store ? fs : fd],
8761 regnames[index], regnames[base]);
ths5a5012e2007-05-07 13:55:33 +00008762}
8763
ths5e755512007-05-29 16:52:57 +00008764static void gen_flt3_arith (DisasContext *ctx, uint32_t opc,
8765 int fd, int fr, int fs, int ft)
ths5a5012e2007-05-07 13:55:33 +00008766{
ths923617a2007-05-11 00:16:06 +00008767 const char *opn = "flt3_arith";
ths5a5012e2007-05-07 13:55:33 +00008768
ths5a5012e2007-05-07 13:55:33 +00008769 switch (opc) {
8770 case OPC_ALNV_PS:
thsb8aa4592007-12-30 15:36:58 +00008771 check_cp1_64bitmode(ctx);
thsa16336e2008-06-19 18:35:02 +00008772 {
pbrooka7812ae2008-11-17 14:43:54 +00008773 TCGv t0 = tcg_temp_local_new();
aurel32c905fda2009-04-08 21:48:18 +00008774 TCGv_i32 fp = tcg_temp_new_i32();
8775 TCGv_i32 fph = tcg_temp_new_i32();
thsa16336e2008-06-19 18:35:02 +00008776 int l1 = gen_new_label();
8777 int l2 = gen_new_label();
8778
ths6c5c1e22008-06-24 15:12:27 +00008779 gen_load_gpr(t0, fr);
8780 tcg_gen_andi_tl(t0, t0, 0x7);
ths6c5c1e22008-06-24 15:12:27 +00008781
8782 tcg_gen_brcondi_tl(TCG_COND_NE, t0, 0, l1);
aurel32c905fda2009-04-08 21:48:18 +00008783 gen_load_fpr32(fp, fs);
8784 gen_load_fpr32h(fph, fs);
8785 gen_store_fpr32(fp, fd);
8786 gen_store_fpr32h(fph, fd);
thsa16336e2008-06-19 18:35:02 +00008787 tcg_gen_br(l2);
8788 gen_set_label(l1);
ths6c5c1e22008-06-24 15:12:27 +00008789 tcg_gen_brcondi_tl(TCG_COND_NE, t0, 4, l2);
8790 tcg_temp_free(t0);
thsa16336e2008-06-19 18:35:02 +00008791#ifdef TARGET_WORDS_BIGENDIAN
aurel32c905fda2009-04-08 21:48:18 +00008792 gen_load_fpr32(fp, fs);
8793 gen_load_fpr32h(fph, ft);
8794 gen_store_fpr32h(fp, fd);
8795 gen_store_fpr32(fph, fd);
thsa16336e2008-06-19 18:35:02 +00008796#else
aurel32c905fda2009-04-08 21:48:18 +00008797 gen_load_fpr32h(fph, fs);
8798 gen_load_fpr32(fp, ft);
8799 gen_store_fpr32(fph, fd);
8800 gen_store_fpr32h(fp, fd);
thsa16336e2008-06-19 18:35:02 +00008801#endif
8802 gen_set_label(l2);
aurel32c905fda2009-04-08 21:48:18 +00008803 tcg_temp_free_i32(fp);
8804 tcg_temp_free_i32(fph);
thsa16336e2008-06-19 18:35:02 +00008805 }
ths5a5012e2007-05-07 13:55:33 +00008806 opn = "alnv.ps";
8807 break;
8808 case OPC_MADD_S:
thsb8aa4592007-12-30 15:36:58 +00008809 check_cop1x(ctx);
thsb6d96be2008-07-09 11:05:10 +00008810 {
pbrooka7812ae2008-11-17 14:43:54 +00008811 TCGv_i32 fp0 = tcg_temp_new_i32();
8812 TCGv_i32 fp1 = tcg_temp_new_i32();
8813 TCGv_i32 fp2 = tcg_temp_new_i32();
thsb6d96be2008-07-09 11:05:10 +00008814
8815 gen_load_fpr32(fp0, fs);
8816 gen_load_fpr32(fp1, ft);
8817 gen_load_fpr32(fp2, fr);
Aurelien Jarnob3d6cd42012-10-09 21:53:20 +02008818 gen_helper_float_madd_s(fp2, cpu_env, fp0, fp1, fp2);
pbrooka7812ae2008-11-17 14:43:54 +00008819 tcg_temp_free_i32(fp0);
8820 tcg_temp_free_i32(fp1);
thsb6d96be2008-07-09 11:05:10 +00008821 gen_store_fpr32(fp2, fd);
pbrooka7812ae2008-11-17 14:43:54 +00008822 tcg_temp_free_i32(fp2);
thsb6d96be2008-07-09 11:05:10 +00008823 }
ths5a5012e2007-05-07 13:55:33 +00008824 opn = "madd.s";
8825 break;
8826 case OPC_MADD_D:
thsb8aa4592007-12-30 15:36:58 +00008827 check_cop1x(ctx);
8828 check_cp1_registers(ctx, fd | fs | ft | fr);
thsb6d96be2008-07-09 11:05:10 +00008829 {
pbrooka7812ae2008-11-17 14:43:54 +00008830 TCGv_i64 fp0 = tcg_temp_new_i64();
8831 TCGv_i64 fp1 = tcg_temp_new_i64();
8832 TCGv_i64 fp2 = tcg_temp_new_i64();
thsb6d96be2008-07-09 11:05:10 +00008833
8834 gen_load_fpr64(ctx, fp0, fs);
8835 gen_load_fpr64(ctx, fp1, ft);
8836 gen_load_fpr64(ctx, fp2, fr);
Aurelien Jarnob3d6cd42012-10-09 21:53:20 +02008837 gen_helper_float_madd_d(fp2, cpu_env, fp0, fp1, fp2);
pbrooka7812ae2008-11-17 14:43:54 +00008838 tcg_temp_free_i64(fp0);
8839 tcg_temp_free_i64(fp1);
thsb6d96be2008-07-09 11:05:10 +00008840 gen_store_fpr64(ctx, fp2, fd);
pbrooka7812ae2008-11-17 14:43:54 +00008841 tcg_temp_free_i64(fp2);
thsb6d96be2008-07-09 11:05:10 +00008842 }
ths5a5012e2007-05-07 13:55:33 +00008843 opn = "madd.d";
8844 break;
8845 case OPC_MADD_PS:
thsb8aa4592007-12-30 15:36:58 +00008846 check_cp1_64bitmode(ctx);
thsb6d96be2008-07-09 11:05:10 +00008847 {
pbrooka7812ae2008-11-17 14:43:54 +00008848 TCGv_i64 fp0 = tcg_temp_new_i64();
8849 TCGv_i64 fp1 = tcg_temp_new_i64();
8850 TCGv_i64 fp2 = tcg_temp_new_i64();
thsb6d96be2008-07-09 11:05:10 +00008851
8852 gen_load_fpr64(ctx, fp0, fs);
8853 gen_load_fpr64(ctx, fp1, ft);
8854 gen_load_fpr64(ctx, fp2, fr);
Aurelien Jarnob3d6cd42012-10-09 21:53:20 +02008855 gen_helper_float_madd_ps(fp2, cpu_env, fp0, fp1, fp2);
pbrooka7812ae2008-11-17 14:43:54 +00008856 tcg_temp_free_i64(fp0);
8857 tcg_temp_free_i64(fp1);
thsb6d96be2008-07-09 11:05:10 +00008858 gen_store_fpr64(ctx, fp2, fd);
pbrooka7812ae2008-11-17 14:43:54 +00008859 tcg_temp_free_i64(fp2);
thsb6d96be2008-07-09 11:05:10 +00008860 }
ths5a5012e2007-05-07 13:55:33 +00008861 opn = "madd.ps";
8862 break;
8863 case OPC_MSUB_S:
thsb8aa4592007-12-30 15:36:58 +00008864 check_cop1x(ctx);
thsb6d96be2008-07-09 11:05:10 +00008865 {
pbrooka7812ae2008-11-17 14:43:54 +00008866 TCGv_i32 fp0 = tcg_temp_new_i32();
8867 TCGv_i32 fp1 = tcg_temp_new_i32();
8868 TCGv_i32 fp2 = tcg_temp_new_i32();
thsb6d96be2008-07-09 11:05:10 +00008869
8870 gen_load_fpr32(fp0, fs);
8871 gen_load_fpr32(fp1, ft);
8872 gen_load_fpr32(fp2, fr);
Aurelien Jarnob3d6cd42012-10-09 21:53:20 +02008873 gen_helper_float_msub_s(fp2, cpu_env, fp0, fp1, fp2);
pbrooka7812ae2008-11-17 14:43:54 +00008874 tcg_temp_free_i32(fp0);
8875 tcg_temp_free_i32(fp1);
thsb6d96be2008-07-09 11:05:10 +00008876 gen_store_fpr32(fp2, fd);
pbrooka7812ae2008-11-17 14:43:54 +00008877 tcg_temp_free_i32(fp2);
thsb6d96be2008-07-09 11:05:10 +00008878 }
ths5a5012e2007-05-07 13:55:33 +00008879 opn = "msub.s";
8880 break;
8881 case OPC_MSUB_D:
thsb8aa4592007-12-30 15:36:58 +00008882 check_cop1x(ctx);
8883 check_cp1_registers(ctx, fd | fs | ft | fr);
thsb6d96be2008-07-09 11:05:10 +00008884 {
pbrooka7812ae2008-11-17 14:43:54 +00008885 TCGv_i64 fp0 = tcg_temp_new_i64();
8886 TCGv_i64 fp1 = tcg_temp_new_i64();
8887 TCGv_i64 fp2 = tcg_temp_new_i64();
thsb6d96be2008-07-09 11:05:10 +00008888
8889 gen_load_fpr64(ctx, fp0, fs);
8890 gen_load_fpr64(ctx, fp1, ft);
8891 gen_load_fpr64(ctx, fp2, fr);
Aurelien Jarnob3d6cd42012-10-09 21:53:20 +02008892 gen_helper_float_msub_d(fp2, cpu_env, fp0, fp1, fp2);
pbrooka7812ae2008-11-17 14:43:54 +00008893 tcg_temp_free_i64(fp0);
8894 tcg_temp_free_i64(fp1);
thsb6d96be2008-07-09 11:05:10 +00008895 gen_store_fpr64(ctx, fp2, fd);
pbrooka7812ae2008-11-17 14:43:54 +00008896 tcg_temp_free_i64(fp2);
thsb6d96be2008-07-09 11:05:10 +00008897 }
ths5a5012e2007-05-07 13:55:33 +00008898 opn = "msub.d";
8899 break;
8900 case OPC_MSUB_PS:
thsb8aa4592007-12-30 15:36:58 +00008901 check_cp1_64bitmode(ctx);
thsb6d96be2008-07-09 11:05:10 +00008902 {
pbrooka7812ae2008-11-17 14:43:54 +00008903 TCGv_i64 fp0 = tcg_temp_new_i64();
8904 TCGv_i64 fp1 = tcg_temp_new_i64();
8905 TCGv_i64 fp2 = tcg_temp_new_i64();
thsb6d96be2008-07-09 11:05:10 +00008906
8907 gen_load_fpr64(ctx, fp0, fs);
8908 gen_load_fpr64(ctx, fp1, ft);
8909 gen_load_fpr64(ctx, fp2, fr);
Aurelien Jarnob3d6cd42012-10-09 21:53:20 +02008910 gen_helper_float_msub_ps(fp2, cpu_env, fp0, fp1, fp2);
pbrooka7812ae2008-11-17 14:43:54 +00008911 tcg_temp_free_i64(fp0);
8912 tcg_temp_free_i64(fp1);
thsb6d96be2008-07-09 11:05:10 +00008913 gen_store_fpr64(ctx, fp2, fd);
pbrooka7812ae2008-11-17 14:43:54 +00008914 tcg_temp_free_i64(fp2);
thsb6d96be2008-07-09 11:05:10 +00008915 }
ths5a5012e2007-05-07 13:55:33 +00008916 opn = "msub.ps";
8917 break;
8918 case OPC_NMADD_S:
thsb8aa4592007-12-30 15:36:58 +00008919 check_cop1x(ctx);
thsb6d96be2008-07-09 11:05:10 +00008920 {
pbrooka7812ae2008-11-17 14:43:54 +00008921 TCGv_i32 fp0 = tcg_temp_new_i32();
8922 TCGv_i32 fp1 = tcg_temp_new_i32();
8923 TCGv_i32 fp2 = tcg_temp_new_i32();
thsb6d96be2008-07-09 11:05:10 +00008924
8925 gen_load_fpr32(fp0, fs);
8926 gen_load_fpr32(fp1, ft);
8927 gen_load_fpr32(fp2, fr);
Aurelien Jarnob3d6cd42012-10-09 21:53:20 +02008928 gen_helper_float_nmadd_s(fp2, cpu_env, fp0, fp1, fp2);
pbrooka7812ae2008-11-17 14:43:54 +00008929 tcg_temp_free_i32(fp0);
8930 tcg_temp_free_i32(fp1);
thsb6d96be2008-07-09 11:05:10 +00008931 gen_store_fpr32(fp2, fd);
pbrooka7812ae2008-11-17 14:43:54 +00008932 tcg_temp_free_i32(fp2);
thsb6d96be2008-07-09 11:05:10 +00008933 }
ths5a5012e2007-05-07 13:55:33 +00008934 opn = "nmadd.s";
8935 break;
8936 case OPC_NMADD_D:
thsb8aa4592007-12-30 15:36:58 +00008937 check_cop1x(ctx);
8938 check_cp1_registers(ctx, fd | fs | ft | fr);
thsb6d96be2008-07-09 11:05:10 +00008939 {
pbrooka7812ae2008-11-17 14:43:54 +00008940 TCGv_i64 fp0 = tcg_temp_new_i64();
8941 TCGv_i64 fp1 = tcg_temp_new_i64();
8942 TCGv_i64 fp2 = tcg_temp_new_i64();
thsb6d96be2008-07-09 11:05:10 +00008943
8944 gen_load_fpr64(ctx, fp0, fs);
8945 gen_load_fpr64(ctx, fp1, ft);
8946 gen_load_fpr64(ctx, fp2, fr);
Aurelien Jarnob3d6cd42012-10-09 21:53:20 +02008947 gen_helper_float_nmadd_d(fp2, cpu_env, fp0, fp1, fp2);
pbrooka7812ae2008-11-17 14:43:54 +00008948 tcg_temp_free_i64(fp0);
8949 tcg_temp_free_i64(fp1);
thsb6d96be2008-07-09 11:05:10 +00008950 gen_store_fpr64(ctx, fp2, fd);
pbrooka7812ae2008-11-17 14:43:54 +00008951 tcg_temp_free_i64(fp2);
thsb6d96be2008-07-09 11:05:10 +00008952 }
ths5a5012e2007-05-07 13:55:33 +00008953 opn = "nmadd.d";
8954 break;
8955 case OPC_NMADD_PS:
thsb8aa4592007-12-30 15:36:58 +00008956 check_cp1_64bitmode(ctx);
thsb6d96be2008-07-09 11:05:10 +00008957 {
pbrooka7812ae2008-11-17 14:43:54 +00008958 TCGv_i64 fp0 = tcg_temp_new_i64();
8959 TCGv_i64 fp1 = tcg_temp_new_i64();
8960 TCGv_i64 fp2 = tcg_temp_new_i64();
thsb6d96be2008-07-09 11:05:10 +00008961
8962 gen_load_fpr64(ctx, fp0, fs);
8963 gen_load_fpr64(ctx, fp1, ft);
8964 gen_load_fpr64(ctx, fp2, fr);
Aurelien Jarnob3d6cd42012-10-09 21:53:20 +02008965 gen_helper_float_nmadd_ps(fp2, cpu_env, fp0, fp1, fp2);
pbrooka7812ae2008-11-17 14:43:54 +00008966 tcg_temp_free_i64(fp0);
8967 tcg_temp_free_i64(fp1);
thsb6d96be2008-07-09 11:05:10 +00008968 gen_store_fpr64(ctx, fp2, fd);
pbrooka7812ae2008-11-17 14:43:54 +00008969 tcg_temp_free_i64(fp2);
thsb6d96be2008-07-09 11:05:10 +00008970 }
ths5a5012e2007-05-07 13:55:33 +00008971 opn = "nmadd.ps";
8972 break;
8973 case OPC_NMSUB_S:
thsb8aa4592007-12-30 15:36:58 +00008974 check_cop1x(ctx);
thsb6d96be2008-07-09 11:05:10 +00008975 {
pbrooka7812ae2008-11-17 14:43:54 +00008976 TCGv_i32 fp0 = tcg_temp_new_i32();
8977 TCGv_i32 fp1 = tcg_temp_new_i32();
8978 TCGv_i32 fp2 = tcg_temp_new_i32();
thsb6d96be2008-07-09 11:05:10 +00008979
8980 gen_load_fpr32(fp0, fs);
8981 gen_load_fpr32(fp1, ft);
8982 gen_load_fpr32(fp2, fr);
Aurelien Jarnob3d6cd42012-10-09 21:53:20 +02008983 gen_helper_float_nmsub_s(fp2, cpu_env, fp0, fp1, fp2);
pbrooka7812ae2008-11-17 14:43:54 +00008984 tcg_temp_free_i32(fp0);
8985 tcg_temp_free_i32(fp1);
thsb6d96be2008-07-09 11:05:10 +00008986 gen_store_fpr32(fp2, fd);
pbrooka7812ae2008-11-17 14:43:54 +00008987 tcg_temp_free_i32(fp2);
thsb6d96be2008-07-09 11:05:10 +00008988 }
ths5a5012e2007-05-07 13:55:33 +00008989 opn = "nmsub.s";
8990 break;
8991 case OPC_NMSUB_D:
thsb8aa4592007-12-30 15:36:58 +00008992 check_cop1x(ctx);
8993 check_cp1_registers(ctx, fd | fs | ft | fr);
thsb6d96be2008-07-09 11:05:10 +00008994 {
pbrooka7812ae2008-11-17 14:43:54 +00008995 TCGv_i64 fp0 = tcg_temp_new_i64();
8996 TCGv_i64 fp1 = tcg_temp_new_i64();
8997 TCGv_i64 fp2 = tcg_temp_new_i64();
thsb6d96be2008-07-09 11:05:10 +00008998
8999 gen_load_fpr64(ctx, fp0, fs);
9000 gen_load_fpr64(ctx, fp1, ft);
9001 gen_load_fpr64(ctx, fp2, fr);
Aurelien Jarnob3d6cd42012-10-09 21:53:20 +02009002 gen_helper_float_nmsub_d(fp2, cpu_env, fp0, fp1, fp2);
pbrooka7812ae2008-11-17 14:43:54 +00009003 tcg_temp_free_i64(fp0);
9004 tcg_temp_free_i64(fp1);
thsb6d96be2008-07-09 11:05:10 +00009005 gen_store_fpr64(ctx, fp2, fd);
pbrooka7812ae2008-11-17 14:43:54 +00009006 tcg_temp_free_i64(fp2);
thsb6d96be2008-07-09 11:05:10 +00009007 }
ths5a5012e2007-05-07 13:55:33 +00009008 opn = "nmsub.d";
9009 break;
9010 case OPC_NMSUB_PS:
thsb8aa4592007-12-30 15:36:58 +00009011 check_cp1_64bitmode(ctx);
thsb6d96be2008-07-09 11:05:10 +00009012 {
pbrooka7812ae2008-11-17 14:43:54 +00009013 TCGv_i64 fp0 = tcg_temp_new_i64();
9014 TCGv_i64 fp1 = tcg_temp_new_i64();
9015 TCGv_i64 fp2 = tcg_temp_new_i64();
thsb6d96be2008-07-09 11:05:10 +00009016
9017 gen_load_fpr64(ctx, fp0, fs);
9018 gen_load_fpr64(ctx, fp1, ft);
9019 gen_load_fpr64(ctx, fp2, fr);
Aurelien Jarnob3d6cd42012-10-09 21:53:20 +02009020 gen_helper_float_nmsub_ps(fp2, cpu_env, fp0, fp1, fp2);
pbrooka7812ae2008-11-17 14:43:54 +00009021 tcg_temp_free_i64(fp0);
9022 tcg_temp_free_i64(fp1);
thsb6d96be2008-07-09 11:05:10 +00009023 gen_store_fpr64(ctx, fp2, fd);
pbrooka7812ae2008-11-17 14:43:54 +00009024 tcg_temp_free_i64(fp2);
thsb6d96be2008-07-09 11:05:10 +00009025 }
ths5a5012e2007-05-07 13:55:33 +00009026 opn = "nmsub.ps";
9027 break;
ths923617a2007-05-11 00:16:06 +00009028 default:
9029 MIPS_INVAL(opn);
ths5a5012e2007-05-07 13:55:33 +00009030 generate_exception (ctx, EXCP_RI);
9031 return;
9032 }
Blue Swirl2abf3142010-10-13 18:38:08 +00009033 (void)opn; /* avoid a compiler warning */
ths5a5012e2007-05-07 13:55:33 +00009034 MIPS_DEBUG("%s %s, %s, %s, %s", opn, fregnames[fd], fregnames[fr],
9035 fregnames[fs], fregnames[ft]);
ths7a387ff2006-12-06 20:17:30 +00009036}
9037
Aurelien Jarnod75c1352013-01-01 18:02:22 +01009038static void gen_rdhwr(DisasContext *ctx, int rt, int rd)
Nathan Froyd26ebe462010-05-24 09:19:35 -07009039{
9040 TCGv t0;
9041
Richard Hendersonb3167282012-03-30 13:16:37 -04009042#if !defined(CONFIG_USER_ONLY)
9043 /* The Linux kernel will emulate rdhwr if it's not supported natively.
9044 Therefore only check the ISA in system mode. */
Aurelien Jarnod75c1352013-01-01 18:02:22 +01009045 check_insn(ctx, ISA_MIPS32R2);
Richard Hendersonb3167282012-03-30 13:16:37 -04009046#endif
Nathan Froyd26ebe462010-05-24 09:19:35 -07009047 t0 = tcg_temp_new();
9048
9049 switch (rd) {
9050 case 0:
9051 save_cpu_state(ctx, 1);
Blue Swirl895c2d02012-09-02 14:52:59 +00009052 gen_helper_rdhwr_cpunum(t0, cpu_env);
Nathan Froyd26ebe462010-05-24 09:19:35 -07009053 gen_store_gpr(t0, rt);
9054 break;
9055 case 1:
9056 save_cpu_state(ctx, 1);
Blue Swirl895c2d02012-09-02 14:52:59 +00009057 gen_helper_rdhwr_synci_step(t0, cpu_env);
Nathan Froyd26ebe462010-05-24 09:19:35 -07009058 gen_store_gpr(t0, rt);
9059 break;
9060 case 2:
9061 save_cpu_state(ctx, 1);
Blue Swirl895c2d02012-09-02 14:52:59 +00009062 gen_helper_rdhwr_cc(t0, cpu_env);
Nathan Froyd26ebe462010-05-24 09:19:35 -07009063 gen_store_gpr(t0, rt);
9064 break;
9065 case 3:
9066 save_cpu_state(ctx, 1);
Blue Swirl895c2d02012-09-02 14:52:59 +00009067 gen_helper_rdhwr_ccres(t0, cpu_env);
Nathan Froyd26ebe462010-05-24 09:19:35 -07009068 gen_store_gpr(t0, rt);
9069 break;
9070 case 29:
9071#if defined(CONFIG_USER_ONLY)
Andreas Färber7db13fa2012-03-14 01:38:22 +01009072 tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUMIPSState, tls_value));
Nathan Froyd26ebe462010-05-24 09:19:35 -07009073 gen_store_gpr(t0, rt);
9074 break;
9075#else
9076 /* XXX: Some CPUs implement this in hardware.
9077 Not supported yet. */
9078#endif
9079 default: /* Invalid */
9080 MIPS_INVAL("rdhwr");
9081 generate_exception(ctx, EXCP_RI);
9082 break;
9083 }
9084 tcg_temp_free(t0);
9085}
9086
Aurelien Jarnod75c1352013-01-01 18:02:22 +01009087static void handle_delay_slot(DisasContext *ctx, int insn_bytes)
Nathan Froydc9602062009-12-08 08:06:27 -08009088{
9089 if (ctx->hflags & MIPS_HFLAG_BMASK) {
Nathan Froyd364d4832009-12-08 08:06:29 -08009090 int proc_hflags = ctx->hflags & MIPS_HFLAG_BMASK;
Nathan Froydc9602062009-12-08 08:06:27 -08009091 /* Branches completion */
9092 ctx->hflags &= ~MIPS_HFLAG_BMASK;
9093 ctx->bstate = BS_BRANCH;
9094 save_cpu_state(ctx, 0);
9095 /* FIXME: Need to clear can_do_io. */
Nathan Froyd364d4832009-12-08 08:06:29 -08009096 switch (proc_hflags & MIPS_HFLAG_BMASK_BASE) {
Nathan Froydc9602062009-12-08 08:06:27 -08009097 case MIPS_HFLAG_B:
9098 /* unconditional branch */
9099 MIPS_DEBUG("unconditional branch");
Nathan Froyd364d4832009-12-08 08:06:29 -08009100 if (proc_hflags & MIPS_HFLAG_BX) {
9101 tcg_gen_xori_i32(hflags, hflags, MIPS_HFLAG_M16);
9102 }
Nathan Froydc9602062009-12-08 08:06:27 -08009103 gen_goto_tb(ctx, 0, ctx->btarget);
9104 break;
9105 case MIPS_HFLAG_BL:
9106 /* blikely taken case */
9107 MIPS_DEBUG("blikely branch taken");
9108 gen_goto_tb(ctx, 0, ctx->btarget);
9109 break;
9110 case MIPS_HFLAG_BC:
9111 /* Conditional branch */
9112 MIPS_DEBUG("conditional branch");
9113 {
9114 int l1 = gen_new_label();
9115
9116 tcg_gen_brcondi_tl(TCG_COND_NE, bcond, 0, l1);
9117 gen_goto_tb(ctx, 1, ctx->pc + insn_bytes);
9118 gen_set_label(l1);
9119 gen_goto_tb(ctx, 0, ctx->btarget);
9120 }
9121 break;
9122 case MIPS_HFLAG_BR:
9123 /* unconditional branch to register */
9124 MIPS_DEBUG("branch to register");
Aurelien Jarnod75c1352013-01-01 18:02:22 +01009125 if (ctx->insn_flags & (ASE_MIPS16 | ASE_MICROMIPS)) {
Nathan Froyd364d4832009-12-08 08:06:29 -08009126 TCGv t0 = tcg_temp_new();
9127 TCGv_i32 t1 = tcg_temp_new_i32();
9128
9129 tcg_gen_andi_tl(t0, btarget, 0x1);
9130 tcg_gen_trunc_tl_i32(t1, t0);
9131 tcg_temp_free(t0);
9132 tcg_gen_andi_i32(hflags, hflags, ~(uint32_t)MIPS_HFLAG_M16);
9133 tcg_gen_shli_i32(t1, t1, MIPS_HFLAG_M16_SHIFT);
9134 tcg_gen_or_i32(hflags, hflags, t1);
9135 tcg_temp_free_i32(t1);
9136
9137 tcg_gen_andi_tl(cpu_PC, btarget, ~(target_ulong)0x1);
9138 } else {
9139 tcg_gen_mov_tl(cpu_PC, btarget);
9140 }
Nathan Froydc9602062009-12-08 08:06:27 -08009141 if (ctx->singlestep_enabled) {
9142 save_cpu_state(ctx, 0);
Blue Swirl895c2d02012-09-02 14:52:59 +00009143 gen_helper_0e0i(raise_exception, EXCP_DEBUG);
Nathan Froydc9602062009-12-08 08:06:27 -08009144 }
9145 tcg_gen_exit_tb(0);
9146 break;
9147 default:
9148 MIPS_DEBUG("unknown branch");
9149 break;
9150 }
9151 }
9152}
9153
ths7a387ff2006-12-06 20:17:30 +00009154/* ISA extensions (ASEs) */
bellard6af0bf92005-07-02 14:58:51 +00009155/* MIPS16 extension to MIPS32 */
Nathan Froyd6ea219d2009-12-08 08:06:28 -08009156
9157/* MIPS16 major opcodes */
9158enum {
9159 M16_OPC_ADDIUSP = 0x00,
9160 M16_OPC_ADDIUPC = 0x01,
9161 M16_OPC_B = 0x02,
9162 M16_OPC_JAL = 0x03,
9163 M16_OPC_BEQZ = 0x04,
9164 M16_OPC_BNEQZ = 0x05,
9165 M16_OPC_SHIFT = 0x06,
9166 M16_OPC_LD = 0x07,
9167 M16_OPC_RRIA = 0x08,
9168 M16_OPC_ADDIU8 = 0x09,
9169 M16_OPC_SLTI = 0x0a,
9170 M16_OPC_SLTIU = 0x0b,
9171 M16_OPC_I8 = 0x0c,
9172 M16_OPC_LI = 0x0d,
9173 M16_OPC_CMPI = 0x0e,
9174 M16_OPC_SD = 0x0f,
9175 M16_OPC_LB = 0x10,
9176 M16_OPC_LH = 0x11,
9177 M16_OPC_LWSP = 0x12,
9178 M16_OPC_LW = 0x13,
9179 M16_OPC_LBU = 0x14,
9180 M16_OPC_LHU = 0x15,
9181 M16_OPC_LWPC = 0x16,
9182 M16_OPC_LWU = 0x17,
9183 M16_OPC_SB = 0x18,
9184 M16_OPC_SH = 0x19,
9185 M16_OPC_SWSP = 0x1a,
9186 M16_OPC_SW = 0x1b,
9187 M16_OPC_RRR = 0x1c,
9188 M16_OPC_RR = 0x1d,
9189 M16_OPC_EXTEND = 0x1e,
9190 M16_OPC_I64 = 0x1f
9191};
9192
9193/* I8 funct field */
9194enum {
9195 I8_BTEQZ = 0x0,
9196 I8_BTNEZ = 0x1,
9197 I8_SWRASP = 0x2,
9198 I8_ADJSP = 0x3,
9199 I8_SVRS = 0x4,
9200 I8_MOV32R = 0x5,
9201 I8_MOVR32 = 0x7
9202};
9203
9204/* RRR f field */
9205enum {
9206 RRR_DADDU = 0x0,
9207 RRR_ADDU = 0x1,
9208 RRR_DSUBU = 0x2,
9209 RRR_SUBU = 0x3
9210};
9211
9212/* RR funct field */
9213enum {
9214 RR_JR = 0x00,
9215 RR_SDBBP = 0x01,
9216 RR_SLT = 0x02,
9217 RR_SLTU = 0x03,
9218 RR_SLLV = 0x04,
9219 RR_BREAK = 0x05,
9220 RR_SRLV = 0x06,
9221 RR_SRAV = 0x07,
9222 RR_DSRL = 0x08,
9223 RR_CMP = 0x0a,
9224 RR_NEG = 0x0b,
9225 RR_AND = 0x0c,
9226 RR_OR = 0x0d,
9227 RR_XOR = 0x0e,
9228 RR_NOT = 0x0f,
9229 RR_MFHI = 0x10,
9230 RR_CNVT = 0x11,
9231 RR_MFLO = 0x12,
9232 RR_DSRA = 0x13,
9233 RR_DSLLV = 0x14,
9234 RR_DSRLV = 0x16,
9235 RR_DSRAV = 0x17,
9236 RR_MULT = 0x18,
9237 RR_MULTU = 0x19,
9238 RR_DIV = 0x1a,
9239 RR_DIVU = 0x1b,
9240 RR_DMULT = 0x1c,
9241 RR_DMULTU = 0x1d,
9242 RR_DDIV = 0x1e,
9243 RR_DDIVU = 0x1f
9244};
9245
9246/* I64 funct field */
9247enum {
9248 I64_LDSP = 0x0,
9249 I64_SDSP = 0x1,
9250 I64_SDRASP = 0x2,
9251 I64_DADJSP = 0x3,
9252 I64_LDPC = 0x4,
Nathan Froyd364d4832009-12-08 08:06:29 -08009253 I64_DADDIU5 = 0x5,
Nathan Froyd6ea219d2009-12-08 08:06:28 -08009254 I64_DADDIUPC = 0x6,
9255 I64_DADDIUSP = 0x7
9256};
9257
9258/* RR ry field for CNVT */
9259enum {
9260 RR_RY_CNVT_ZEB = 0x0,
9261 RR_RY_CNVT_ZEH = 0x1,
9262 RR_RY_CNVT_ZEW = 0x2,
9263 RR_RY_CNVT_SEB = 0x4,
9264 RR_RY_CNVT_SEH = 0x5,
9265 RR_RY_CNVT_SEW = 0x6,
9266};
9267
Nathan Froyd364d4832009-12-08 08:06:29 -08009268static int xlat (int r)
9269{
9270 static int map[] = { 16, 17, 2, 3, 4, 5, 6, 7 };
9271
9272 return map[r];
9273}
9274
9275static void gen_mips16_save (DisasContext *ctx,
9276 int xsregs, int aregs,
9277 int do_ra, int do_s0, int do_s1,
9278 int framesize)
9279{
9280 TCGv t0 = tcg_temp_new();
9281 TCGv t1 = tcg_temp_new();
9282 int args, astatic;
9283
9284 switch (aregs) {
9285 case 0:
9286 case 1:
9287 case 2:
9288 case 3:
9289 case 11:
9290 args = 0;
9291 break;
9292 case 4:
9293 case 5:
9294 case 6:
9295 case 7:
9296 args = 1;
9297 break;
9298 case 8:
9299 case 9:
9300 case 10:
9301 args = 2;
9302 break;
9303 case 12:
9304 case 13:
9305 args = 3;
9306 break;
9307 case 14:
9308 args = 4;
9309 break;
9310 default:
9311 generate_exception(ctx, EXCP_RI);
9312 return;
9313 }
9314
9315 switch (args) {
9316 case 4:
9317 gen_base_offset_addr(ctx, t0, 29, 12);
9318 gen_load_gpr(t1, 7);
Aurelien Jarno2910c6cb2012-10-09 21:53:20 +02009319 tcg_gen_qemu_st32(t1, t0, ctx->mem_idx);
Nathan Froyd364d4832009-12-08 08:06:29 -08009320 /* Fall through */
9321 case 3:
9322 gen_base_offset_addr(ctx, t0, 29, 8);
9323 gen_load_gpr(t1, 6);
Aurelien Jarno2910c6cb2012-10-09 21:53:20 +02009324 tcg_gen_qemu_st32(t1, t0, ctx->mem_idx);
Nathan Froyd364d4832009-12-08 08:06:29 -08009325 /* Fall through */
9326 case 2:
9327 gen_base_offset_addr(ctx, t0, 29, 4);
9328 gen_load_gpr(t1, 5);
Aurelien Jarno2910c6cb2012-10-09 21:53:20 +02009329 tcg_gen_qemu_st32(t1, t0, ctx->mem_idx);
Nathan Froyd364d4832009-12-08 08:06:29 -08009330 /* Fall through */
9331 case 1:
9332 gen_base_offset_addr(ctx, t0, 29, 0);
9333 gen_load_gpr(t1, 4);
Aurelien Jarno2910c6cb2012-10-09 21:53:20 +02009334 tcg_gen_qemu_st32(t1, t0, ctx->mem_idx);
Nathan Froyd364d4832009-12-08 08:06:29 -08009335 }
9336
9337 gen_load_gpr(t0, 29);
9338
9339#define DECR_AND_STORE(reg) do { \
9340 tcg_gen_subi_tl(t0, t0, 4); \
9341 gen_load_gpr(t1, reg); \
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 } while (0)
9344
9345 if (do_ra) {
9346 DECR_AND_STORE(31);
9347 }
9348
9349 switch (xsregs) {
9350 case 7:
9351 DECR_AND_STORE(30);
9352 /* Fall through */
9353 case 6:
9354 DECR_AND_STORE(23);
9355 /* Fall through */
9356 case 5:
9357 DECR_AND_STORE(22);
9358 /* Fall through */
9359 case 4:
9360 DECR_AND_STORE(21);
9361 /* Fall through */
9362 case 3:
9363 DECR_AND_STORE(20);
9364 /* Fall through */
9365 case 2:
9366 DECR_AND_STORE(19);
9367 /* Fall through */
9368 case 1:
9369 DECR_AND_STORE(18);
9370 }
9371
9372 if (do_s1) {
9373 DECR_AND_STORE(17);
9374 }
9375 if (do_s0) {
9376 DECR_AND_STORE(16);
9377 }
9378
9379 switch (aregs) {
9380 case 0:
9381 case 4:
9382 case 8:
9383 case 12:
9384 case 14:
9385 astatic = 0;
9386 break;
9387 case 1:
9388 case 5:
9389 case 9:
9390 case 13:
9391 astatic = 1;
9392 break;
9393 case 2:
9394 case 6:
9395 case 10:
9396 astatic = 2;
9397 break;
9398 case 3:
9399 case 7:
9400 astatic = 3;
9401 break;
9402 case 11:
9403 astatic = 4;
9404 break;
9405 default:
9406 generate_exception(ctx, EXCP_RI);
9407 return;
9408 }
9409
9410 if (astatic > 0) {
9411 DECR_AND_STORE(7);
9412 if (astatic > 1) {
9413 DECR_AND_STORE(6);
9414 if (astatic > 2) {
9415 DECR_AND_STORE(5);
9416 if (astatic > 3) {
9417 DECR_AND_STORE(4);
9418 }
9419 }
9420 }
9421 }
9422#undef DECR_AND_STORE
9423
9424 tcg_gen_subi_tl(cpu_gpr[29], cpu_gpr[29], framesize);
9425 tcg_temp_free(t0);
9426 tcg_temp_free(t1);
9427}
9428
9429static void gen_mips16_restore (DisasContext *ctx,
9430 int xsregs, int aregs,
9431 int do_ra, int do_s0, int do_s1,
9432 int framesize)
9433{
9434 int astatic;
9435 TCGv t0 = tcg_temp_new();
9436 TCGv t1 = tcg_temp_new();
9437
9438 tcg_gen_addi_tl(t0, cpu_gpr[29], framesize);
9439
Aurelien Jarno2910c6cb2012-10-09 21:53:20 +02009440#define DECR_AND_LOAD(reg) do { \
9441 tcg_gen_subi_tl(t0, t0, 4); \
Richard Sandiford17e8fef2013-01-20 19:28:48 +00009442 tcg_gen_qemu_ld32s(t1, t0, ctx->mem_idx); \
Aurelien Jarno2910c6cb2012-10-09 21:53:20 +02009443 gen_store_gpr(t1, reg); \
Nathan Froyd364d4832009-12-08 08:06:29 -08009444 } while (0)
9445
9446 if (do_ra) {
9447 DECR_AND_LOAD(31);
9448 }
9449
9450 switch (xsregs) {
9451 case 7:
9452 DECR_AND_LOAD(30);
9453 /* Fall through */
9454 case 6:
9455 DECR_AND_LOAD(23);
9456 /* Fall through */
9457 case 5:
9458 DECR_AND_LOAD(22);
9459 /* Fall through */
9460 case 4:
9461 DECR_AND_LOAD(21);
9462 /* Fall through */
9463 case 3:
9464 DECR_AND_LOAD(20);
9465 /* Fall through */
9466 case 2:
9467 DECR_AND_LOAD(19);
9468 /* Fall through */
9469 case 1:
9470 DECR_AND_LOAD(18);
9471 }
9472
9473 if (do_s1) {
9474 DECR_AND_LOAD(17);
9475 }
9476 if (do_s0) {
9477 DECR_AND_LOAD(16);
9478 }
9479
9480 switch (aregs) {
9481 case 0:
9482 case 4:
9483 case 8:
9484 case 12:
9485 case 14:
9486 astatic = 0;
9487 break;
9488 case 1:
9489 case 5:
9490 case 9:
9491 case 13:
9492 astatic = 1;
9493 break;
9494 case 2:
9495 case 6:
9496 case 10:
9497 astatic = 2;
9498 break;
9499 case 3:
9500 case 7:
9501 astatic = 3;
9502 break;
9503 case 11:
9504 astatic = 4;
9505 break;
9506 default:
9507 generate_exception(ctx, EXCP_RI);
9508 return;
9509 }
9510
9511 if (astatic > 0) {
9512 DECR_AND_LOAD(7);
9513 if (astatic > 1) {
9514 DECR_AND_LOAD(6);
9515 if (astatic > 2) {
9516 DECR_AND_LOAD(5);
9517 if (astatic > 3) {
9518 DECR_AND_LOAD(4);
9519 }
9520 }
9521 }
9522 }
9523#undef DECR_AND_LOAD
9524
9525 tcg_gen_addi_tl(cpu_gpr[29], cpu_gpr[29], framesize);
9526 tcg_temp_free(t0);
9527 tcg_temp_free(t1);
9528}
9529
9530static void gen_addiupc (DisasContext *ctx, int rx, int imm,
9531 int is_64_bit, int extended)
9532{
9533 TCGv t0;
9534
9535 if (extended && (ctx->hflags & MIPS_HFLAG_BMASK)) {
9536 generate_exception(ctx, EXCP_RI);
9537 return;
9538 }
9539
9540 t0 = tcg_temp_new();
9541
9542 tcg_gen_movi_tl(t0, pc_relative_pc(ctx));
9543 tcg_gen_addi_tl(cpu_gpr[rx], t0, imm);
9544 if (!is_64_bit) {
9545 tcg_gen_ext32s_tl(cpu_gpr[rx], cpu_gpr[rx]);
9546 }
9547
9548 tcg_temp_free(t0);
9549}
9550
9551#if defined(TARGET_MIPS64)
Aurelien Jarnod75c1352013-01-01 18:02:22 +01009552static void decode_i64_mips16 (DisasContext *ctx,
Nathan Froyd364d4832009-12-08 08:06:29 -08009553 int ry, int funct, int16_t offset,
9554 int extended)
9555{
9556 switch (funct) {
9557 case I64_LDSP:
9558 check_mips_64(ctx);
9559 offset = extended ? offset : offset << 3;
Aurelien Jarnod75c1352013-01-01 18:02:22 +01009560 gen_ld(ctx, OPC_LD, ry, 29, offset);
Nathan Froyd364d4832009-12-08 08:06:29 -08009561 break;
9562 case I64_SDSP:
9563 check_mips_64(ctx);
9564 offset = extended ? offset : offset << 3;
Aurelien Jarno5c13fdf2010-07-01 07:47:00 +02009565 gen_st(ctx, OPC_SD, ry, 29, offset);
Nathan Froyd364d4832009-12-08 08:06:29 -08009566 break;
9567 case I64_SDRASP:
9568 check_mips_64(ctx);
9569 offset = extended ? offset : (ctx->opcode & 0xff) << 3;
Aurelien Jarno5c13fdf2010-07-01 07:47:00 +02009570 gen_st(ctx, OPC_SD, 31, 29, offset);
Nathan Froyd364d4832009-12-08 08:06:29 -08009571 break;
9572 case I64_DADJSP:
9573 check_mips_64(ctx);
9574 offset = extended ? offset : ((int8_t)ctx->opcode) << 3;
Aurelien Jarnod75c1352013-01-01 18:02:22 +01009575 gen_arith_imm(ctx, OPC_DADDIU, 29, 29, offset);
Nathan Froyd364d4832009-12-08 08:06:29 -08009576 break;
9577 case I64_LDPC:
9578 if (extended && (ctx->hflags & MIPS_HFLAG_BMASK)) {
9579 generate_exception(ctx, EXCP_RI);
9580 } else {
9581 offset = extended ? offset : offset << 3;
Aurelien Jarnod75c1352013-01-01 18:02:22 +01009582 gen_ld(ctx, OPC_LDPC, ry, 0, offset);
Nathan Froyd364d4832009-12-08 08:06:29 -08009583 }
9584 break;
9585 case I64_DADDIU5:
9586 check_mips_64(ctx);
9587 offset = extended ? offset : ((int8_t)(offset << 3)) >> 3;
Aurelien Jarnod75c1352013-01-01 18:02:22 +01009588 gen_arith_imm(ctx, OPC_DADDIU, ry, ry, offset);
Nathan Froyd364d4832009-12-08 08:06:29 -08009589 break;
9590 case I64_DADDIUPC:
9591 check_mips_64(ctx);
9592 offset = extended ? offset : offset << 2;
9593 gen_addiupc(ctx, ry, offset, 1, extended);
9594 break;
9595 case I64_DADDIUSP:
9596 check_mips_64(ctx);
9597 offset = extended ? offset : offset << 2;
Aurelien Jarnod75c1352013-01-01 18:02:22 +01009598 gen_arith_imm(ctx, OPC_DADDIU, ry, 29, offset);
Nathan Froyd364d4832009-12-08 08:06:29 -08009599 break;
9600 }
9601}
9602#endif
9603
Andreas Färber7db13fa2012-03-14 01:38:22 +01009604static int decode_extended_mips16_opc (CPUMIPSState *env, DisasContext *ctx,
Nathan Froyd364d4832009-12-08 08:06:29 -08009605 int *is_branch)
9606{
Blue Swirl895c2d02012-09-02 14:52:59 +00009607 int extend = cpu_lduw_code(env, ctx->pc + 2);
Nathan Froyd364d4832009-12-08 08:06:29 -08009608 int op, rx, ry, funct, sa;
9609 int16_t imm, offset;
9610
9611 ctx->opcode = (ctx->opcode << 16) | extend;
9612 op = (ctx->opcode >> 11) & 0x1f;
9613 sa = (ctx->opcode >> 22) & 0x1f;
9614 funct = (ctx->opcode >> 8) & 0x7;
9615 rx = xlat((ctx->opcode >> 8) & 0x7);
9616 ry = xlat((ctx->opcode >> 5) & 0x7);
9617 offset = imm = (int16_t) (((ctx->opcode >> 16) & 0x1f) << 11
9618 | ((ctx->opcode >> 21) & 0x3f) << 5
9619 | (ctx->opcode & 0x1f));
9620
9621 /* The extended opcodes cleverly reuse the opcodes from their 16-bit
9622 counterparts. */
9623 switch (op) {
9624 case M16_OPC_ADDIUSP:
Aurelien Jarnod75c1352013-01-01 18:02:22 +01009625 gen_arith_imm(ctx, OPC_ADDIU, rx, 29, imm);
Nathan Froyd364d4832009-12-08 08:06:29 -08009626 break;
9627 case M16_OPC_ADDIUPC:
9628 gen_addiupc(ctx, rx, imm, 0, 1);
9629 break;
9630 case M16_OPC_B:
9631 gen_compute_branch(ctx, OPC_BEQ, 4, 0, 0, offset << 1);
9632 /* No delay slot, so just process as a normal instruction */
9633 break;
9634 case M16_OPC_BEQZ:
9635 gen_compute_branch(ctx, OPC_BEQ, 4, rx, 0, offset << 1);
9636 /* No delay slot, so just process as a normal instruction */
9637 break;
9638 case M16_OPC_BNEQZ:
9639 gen_compute_branch(ctx, OPC_BNE, 4, rx, 0, offset << 1);
9640 /* No delay slot, so just process as a normal instruction */
9641 break;
9642 case M16_OPC_SHIFT:
9643 switch (ctx->opcode & 0x3) {
9644 case 0x0:
Aurelien Jarnod75c1352013-01-01 18:02:22 +01009645 gen_shift_imm(ctx, OPC_SLL, rx, ry, sa);
Nathan Froyd364d4832009-12-08 08:06:29 -08009646 break;
9647 case 0x1:
9648#if defined(TARGET_MIPS64)
9649 check_mips_64(ctx);
Aurelien Jarnod75c1352013-01-01 18:02:22 +01009650 gen_shift_imm(ctx, OPC_DSLL, rx, ry, sa);
Nathan Froyd364d4832009-12-08 08:06:29 -08009651#else
9652 generate_exception(ctx, EXCP_RI);
9653#endif
9654 break;
9655 case 0x2:
Aurelien Jarnod75c1352013-01-01 18:02:22 +01009656 gen_shift_imm(ctx, OPC_SRL, rx, ry, sa);
Nathan Froyd364d4832009-12-08 08:06:29 -08009657 break;
9658 case 0x3:
Aurelien Jarnod75c1352013-01-01 18:02:22 +01009659 gen_shift_imm(ctx, OPC_SRA, rx, ry, sa);
Nathan Froyd364d4832009-12-08 08:06:29 -08009660 break;
9661 }
9662 break;
9663#if defined(TARGET_MIPS64)
9664 case M16_OPC_LD:
9665 check_mips_64(ctx);
Aurelien Jarnod75c1352013-01-01 18:02:22 +01009666 gen_ld(ctx, OPC_LD, ry, rx, offset);
Nathan Froyd364d4832009-12-08 08:06:29 -08009667 break;
9668#endif
9669 case M16_OPC_RRIA:
9670 imm = ctx->opcode & 0xf;
9671 imm = imm | ((ctx->opcode >> 20) & 0x7f) << 4;
9672 imm = imm | ((ctx->opcode >> 16) & 0xf) << 11;
9673 imm = (int16_t) (imm << 1) >> 1;
9674 if ((ctx->opcode >> 4) & 0x1) {
9675#if defined(TARGET_MIPS64)
9676 check_mips_64(ctx);
Aurelien Jarnod75c1352013-01-01 18:02:22 +01009677 gen_arith_imm(ctx, OPC_DADDIU, ry, rx, imm);
Nathan Froyd364d4832009-12-08 08:06:29 -08009678#else
9679 generate_exception(ctx, EXCP_RI);
9680#endif
9681 } else {
Aurelien Jarnod75c1352013-01-01 18:02:22 +01009682 gen_arith_imm(ctx, OPC_ADDIU, ry, rx, imm);
Nathan Froyd364d4832009-12-08 08:06:29 -08009683 }
9684 break;
9685 case M16_OPC_ADDIU8:
Aurelien Jarnod75c1352013-01-01 18:02:22 +01009686 gen_arith_imm(ctx, OPC_ADDIU, rx, rx, imm);
Nathan Froyd364d4832009-12-08 08:06:29 -08009687 break;
9688 case M16_OPC_SLTI:
Aurelien Jarnod75c1352013-01-01 18:02:22 +01009689 gen_slt_imm(ctx, OPC_SLTI, 24, rx, imm);
Nathan Froyd364d4832009-12-08 08:06:29 -08009690 break;
9691 case M16_OPC_SLTIU:
Aurelien Jarnod75c1352013-01-01 18:02:22 +01009692 gen_slt_imm(ctx, OPC_SLTIU, 24, rx, imm);
Nathan Froyd364d4832009-12-08 08:06:29 -08009693 break;
9694 case M16_OPC_I8:
9695 switch (funct) {
9696 case I8_BTEQZ:
9697 gen_compute_branch(ctx, OPC_BEQ, 4, 24, 0, offset << 1);
9698 break;
9699 case I8_BTNEZ:
9700 gen_compute_branch(ctx, OPC_BNE, 4, 24, 0, offset << 1);
9701 break;
9702 case I8_SWRASP:
Aurelien Jarno5c13fdf2010-07-01 07:47:00 +02009703 gen_st(ctx, OPC_SW, 31, 29, imm);
Nathan Froyd364d4832009-12-08 08:06:29 -08009704 break;
9705 case I8_ADJSP:
Aurelien Jarnod75c1352013-01-01 18:02:22 +01009706 gen_arith_imm(ctx, OPC_ADDIU, 29, 29, imm);
Nathan Froyd364d4832009-12-08 08:06:29 -08009707 break;
9708 case I8_SVRS:
9709 {
9710 int xsregs = (ctx->opcode >> 24) & 0x7;
9711 int aregs = (ctx->opcode >> 16) & 0xf;
9712 int do_ra = (ctx->opcode >> 6) & 0x1;
9713 int do_s0 = (ctx->opcode >> 5) & 0x1;
9714 int do_s1 = (ctx->opcode >> 4) & 0x1;
9715 int framesize = (((ctx->opcode >> 20) & 0xf) << 4
9716 | (ctx->opcode & 0xf)) << 3;
9717
9718 if (ctx->opcode & (1 << 7)) {
9719 gen_mips16_save(ctx, xsregs, aregs,
9720 do_ra, do_s0, do_s1,
9721 framesize);
9722 } else {
9723 gen_mips16_restore(ctx, xsregs, aregs,
9724 do_ra, do_s0, do_s1,
9725 framesize);
9726 }
9727 }
9728 break;
9729 default:
9730 generate_exception(ctx, EXCP_RI);
9731 break;
9732 }
9733 break;
9734 case M16_OPC_LI:
9735 tcg_gen_movi_tl(cpu_gpr[rx], (uint16_t) imm);
9736 break;
9737 case M16_OPC_CMPI:
9738 tcg_gen_xori_tl(cpu_gpr[24], cpu_gpr[rx], (uint16_t) imm);
9739 break;
9740#if defined(TARGET_MIPS64)
9741 case M16_OPC_SD:
Aurelien Jarno5c13fdf2010-07-01 07:47:00 +02009742 gen_st(ctx, OPC_SD, ry, rx, offset);
Nathan Froyd364d4832009-12-08 08:06:29 -08009743 break;
9744#endif
9745 case M16_OPC_LB:
Aurelien Jarnod75c1352013-01-01 18:02:22 +01009746 gen_ld(ctx, OPC_LB, ry, rx, offset);
Nathan Froyd364d4832009-12-08 08:06:29 -08009747 break;
9748 case M16_OPC_LH:
Aurelien Jarnod75c1352013-01-01 18:02:22 +01009749 gen_ld(ctx, OPC_LH, ry, rx, offset);
Nathan Froyd364d4832009-12-08 08:06:29 -08009750 break;
9751 case M16_OPC_LWSP:
Aurelien Jarnod75c1352013-01-01 18:02:22 +01009752 gen_ld(ctx, OPC_LW, rx, 29, offset);
Nathan Froyd364d4832009-12-08 08:06:29 -08009753 break;
9754 case M16_OPC_LW:
Aurelien Jarnod75c1352013-01-01 18:02:22 +01009755 gen_ld(ctx, OPC_LW, ry, rx, offset);
Nathan Froyd364d4832009-12-08 08:06:29 -08009756 break;
9757 case M16_OPC_LBU:
Aurelien Jarnod75c1352013-01-01 18:02:22 +01009758 gen_ld(ctx, OPC_LBU, ry, rx, offset);
Nathan Froyd364d4832009-12-08 08:06:29 -08009759 break;
9760 case M16_OPC_LHU:
Aurelien Jarnod75c1352013-01-01 18:02:22 +01009761 gen_ld(ctx, OPC_LHU, ry, rx, offset);
Nathan Froyd364d4832009-12-08 08:06:29 -08009762 break;
9763 case M16_OPC_LWPC:
Aurelien Jarnod75c1352013-01-01 18:02:22 +01009764 gen_ld(ctx, OPC_LWPC, rx, 0, offset);
Nathan Froyd364d4832009-12-08 08:06:29 -08009765 break;
9766#if defined(TARGET_MIPS64)
9767 case M16_OPC_LWU:
Aurelien Jarnod75c1352013-01-01 18:02:22 +01009768 gen_ld(ctx, OPC_LWU, ry, rx, offset);
Nathan Froyd364d4832009-12-08 08:06:29 -08009769 break;
9770#endif
9771 case M16_OPC_SB:
Aurelien Jarno5c13fdf2010-07-01 07:47:00 +02009772 gen_st(ctx, OPC_SB, ry, rx, offset);
Nathan Froyd364d4832009-12-08 08:06:29 -08009773 break;
9774 case M16_OPC_SH:
Aurelien Jarno5c13fdf2010-07-01 07:47:00 +02009775 gen_st(ctx, OPC_SH, ry, rx, offset);
Nathan Froyd364d4832009-12-08 08:06:29 -08009776 break;
9777 case M16_OPC_SWSP:
Aurelien Jarno5c13fdf2010-07-01 07:47:00 +02009778 gen_st(ctx, OPC_SW, rx, 29, offset);
Nathan Froyd364d4832009-12-08 08:06:29 -08009779 break;
9780 case M16_OPC_SW:
Aurelien Jarno5c13fdf2010-07-01 07:47:00 +02009781 gen_st(ctx, OPC_SW, ry, rx, offset);
Nathan Froyd364d4832009-12-08 08:06:29 -08009782 break;
9783#if defined(TARGET_MIPS64)
9784 case M16_OPC_I64:
Aurelien Jarnod75c1352013-01-01 18:02:22 +01009785 decode_i64_mips16(ctx, ry, funct, offset, 1);
Nathan Froyd364d4832009-12-08 08:06:29 -08009786 break;
9787#endif
9788 default:
9789 generate_exception(ctx, EXCP_RI);
9790 break;
9791 }
9792
9793 return 4;
9794}
9795
Andreas Färber7db13fa2012-03-14 01:38:22 +01009796static int decode_mips16_opc (CPUMIPSState *env, DisasContext *ctx,
Nathan Froyd364d4832009-12-08 08:06:29 -08009797 int *is_branch)
9798{
9799 int rx, ry;
9800 int sa;
9801 int op, cnvt_op, op1, offset;
9802 int funct;
9803 int n_bytes;
9804
9805 op = (ctx->opcode >> 11) & 0x1f;
9806 sa = (ctx->opcode >> 2) & 0x7;
9807 sa = sa == 0 ? 8 : sa;
9808 rx = xlat((ctx->opcode >> 8) & 0x7);
9809 cnvt_op = (ctx->opcode >> 5) & 0x7;
9810 ry = xlat((ctx->opcode >> 5) & 0x7);
9811 op1 = offset = ctx->opcode & 0x1f;
9812
9813 n_bytes = 2;
9814
9815 switch (op) {
9816 case M16_OPC_ADDIUSP:
9817 {
9818 int16_t imm = ((uint8_t) ctx->opcode) << 2;
9819
Aurelien Jarnod75c1352013-01-01 18:02:22 +01009820 gen_arith_imm(ctx, OPC_ADDIU, rx, 29, imm);
Nathan Froyd364d4832009-12-08 08:06:29 -08009821 }
9822 break;
9823 case M16_OPC_ADDIUPC:
9824 gen_addiupc(ctx, rx, ((uint8_t) ctx->opcode) << 2, 0, 0);
9825 break;
9826 case M16_OPC_B:
9827 offset = (ctx->opcode & 0x7ff) << 1;
9828 offset = (int16_t)(offset << 4) >> 4;
9829 gen_compute_branch(ctx, OPC_BEQ, 2, 0, 0, offset);
9830 /* No delay slot, so just process as a normal instruction */
9831 break;
9832 case M16_OPC_JAL:
Blue Swirl895c2d02012-09-02 14:52:59 +00009833 offset = cpu_lduw_code(env, ctx->pc + 2);
Nathan Froyd364d4832009-12-08 08:06:29 -08009834 offset = (((ctx->opcode & 0x1f) << 21)
9835 | ((ctx->opcode >> 5) & 0x1f) << 16
9836 | offset) << 2;
Nathan Froyd620e48f2010-06-08 13:29:58 -07009837 op = ((ctx->opcode >> 10) & 0x1) ? OPC_JALXS : OPC_JALS;
Nathan Froyd364d4832009-12-08 08:06:29 -08009838 gen_compute_branch(ctx, op, 4, rx, ry, offset);
9839 n_bytes = 4;
9840 *is_branch = 1;
9841 break;
9842 case M16_OPC_BEQZ:
9843 gen_compute_branch(ctx, OPC_BEQ, 2, rx, 0, ((int8_t)ctx->opcode) << 1);
9844 /* No delay slot, so just process as a normal instruction */
9845 break;
9846 case M16_OPC_BNEQZ:
9847 gen_compute_branch(ctx, OPC_BNE, 2, rx, 0, ((int8_t)ctx->opcode) << 1);
9848 /* No delay slot, so just process as a normal instruction */
9849 break;
9850 case M16_OPC_SHIFT:
9851 switch (ctx->opcode & 0x3) {
9852 case 0x0:
Aurelien Jarnod75c1352013-01-01 18:02:22 +01009853 gen_shift_imm(ctx, OPC_SLL, rx, ry, sa);
Nathan Froyd364d4832009-12-08 08:06:29 -08009854 break;
9855 case 0x1:
9856#if defined(TARGET_MIPS64)
9857 check_mips_64(ctx);
Aurelien Jarnod75c1352013-01-01 18:02:22 +01009858 gen_shift_imm(ctx, OPC_DSLL, rx, ry, sa);
Nathan Froyd364d4832009-12-08 08:06:29 -08009859#else
9860 generate_exception(ctx, EXCP_RI);
9861#endif
9862 break;
9863 case 0x2:
Aurelien Jarnod75c1352013-01-01 18:02:22 +01009864 gen_shift_imm(ctx, OPC_SRL, rx, ry, sa);
Nathan Froyd364d4832009-12-08 08:06:29 -08009865 break;
9866 case 0x3:
Aurelien Jarnod75c1352013-01-01 18:02:22 +01009867 gen_shift_imm(ctx, OPC_SRA, rx, ry, sa);
Nathan Froyd364d4832009-12-08 08:06:29 -08009868 break;
9869 }
9870 break;
9871#if defined(TARGET_MIPS64)
9872 case M16_OPC_LD:
9873 check_mips_64(ctx);
Aurelien Jarnod75c1352013-01-01 18:02:22 +01009874 gen_ld(ctx, OPC_LD, ry, rx, offset << 3);
Nathan Froyd364d4832009-12-08 08:06:29 -08009875 break;
9876#endif
9877 case M16_OPC_RRIA:
9878 {
9879 int16_t imm = (int8_t)((ctx->opcode & 0xf) << 4) >> 4;
9880
9881 if ((ctx->opcode >> 4) & 1) {
9882#if defined(TARGET_MIPS64)
9883 check_mips_64(ctx);
Aurelien Jarnod75c1352013-01-01 18:02:22 +01009884 gen_arith_imm(ctx, OPC_DADDIU, ry, rx, imm);
Nathan Froyd364d4832009-12-08 08:06:29 -08009885#else
9886 generate_exception(ctx, EXCP_RI);
9887#endif
9888 } else {
Aurelien Jarnod75c1352013-01-01 18:02:22 +01009889 gen_arith_imm(ctx, OPC_ADDIU, ry, rx, imm);
Nathan Froyd364d4832009-12-08 08:06:29 -08009890 }
9891 }
9892 break;
9893 case M16_OPC_ADDIU8:
9894 {
9895 int16_t imm = (int8_t) ctx->opcode;
9896
Aurelien Jarnod75c1352013-01-01 18:02:22 +01009897 gen_arith_imm(ctx, OPC_ADDIU, rx, rx, imm);
Nathan Froyd364d4832009-12-08 08:06:29 -08009898 }
9899 break;
9900 case M16_OPC_SLTI:
9901 {
9902 int16_t imm = (uint8_t) ctx->opcode;
Aurelien Jarnod75c1352013-01-01 18:02:22 +01009903 gen_slt_imm(ctx, OPC_SLTI, 24, rx, imm);
Nathan Froyd364d4832009-12-08 08:06:29 -08009904 }
9905 break;
9906 case M16_OPC_SLTIU:
9907 {
9908 int16_t imm = (uint8_t) ctx->opcode;
Aurelien Jarnod75c1352013-01-01 18:02:22 +01009909 gen_slt_imm(ctx, OPC_SLTIU, 24, rx, imm);
Nathan Froyd364d4832009-12-08 08:06:29 -08009910 }
9911 break;
9912 case M16_OPC_I8:
9913 {
9914 int reg32;
9915
9916 funct = (ctx->opcode >> 8) & 0x7;
9917 switch (funct) {
9918 case I8_BTEQZ:
9919 gen_compute_branch(ctx, OPC_BEQ, 2, 24, 0,
9920 ((int8_t)ctx->opcode) << 1);
9921 break;
9922 case I8_BTNEZ:
9923 gen_compute_branch(ctx, OPC_BNE, 2, 24, 0,
9924 ((int8_t)ctx->opcode) << 1);
9925 break;
9926 case I8_SWRASP:
Aurelien Jarno5c13fdf2010-07-01 07:47:00 +02009927 gen_st(ctx, OPC_SW, 31, 29, (ctx->opcode & 0xff) << 2);
Nathan Froyd364d4832009-12-08 08:06:29 -08009928 break;
9929 case I8_ADJSP:
Aurelien Jarnod75c1352013-01-01 18:02:22 +01009930 gen_arith_imm(ctx, OPC_ADDIU, 29, 29,
Nathan Froyd364d4832009-12-08 08:06:29 -08009931 ((int8_t)ctx->opcode) << 3);
9932 break;
9933 case I8_SVRS:
9934 {
9935 int do_ra = ctx->opcode & (1 << 6);
9936 int do_s0 = ctx->opcode & (1 << 5);
9937 int do_s1 = ctx->opcode & (1 << 4);
9938 int framesize = ctx->opcode & 0xf;
9939
9940 if (framesize == 0) {
9941 framesize = 128;
9942 } else {
9943 framesize = framesize << 3;
9944 }
9945
9946 if (ctx->opcode & (1 << 7)) {
9947 gen_mips16_save(ctx, 0, 0,
9948 do_ra, do_s0, do_s1, framesize);
9949 } else {
9950 gen_mips16_restore(ctx, 0, 0,
9951 do_ra, do_s0, do_s1, framesize);
9952 }
9953 }
9954 break;
9955 case I8_MOV32R:
9956 {
9957 int rz = xlat(ctx->opcode & 0x7);
9958
9959 reg32 = (((ctx->opcode >> 3) & 0x3) << 3) |
9960 ((ctx->opcode >> 5) & 0x7);
Aurelien Jarnod75c1352013-01-01 18:02:22 +01009961 gen_arith(ctx, OPC_ADDU, reg32, rz, 0);
Nathan Froyd364d4832009-12-08 08:06:29 -08009962 }
9963 break;
9964 case I8_MOVR32:
9965 reg32 = ctx->opcode & 0x1f;
Aurelien Jarnod75c1352013-01-01 18:02:22 +01009966 gen_arith(ctx, OPC_ADDU, ry, reg32, 0);
Nathan Froyd364d4832009-12-08 08:06:29 -08009967 break;
9968 default:
9969 generate_exception(ctx, EXCP_RI);
9970 break;
9971 }
9972 }
9973 break;
9974 case M16_OPC_LI:
9975 {
9976 int16_t imm = (uint8_t) ctx->opcode;
9977
Aurelien Jarnod75c1352013-01-01 18:02:22 +01009978 gen_arith_imm(ctx, OPC_ADDIU, rx, 0, imm);
Nathan Froyd364d4832009-12-08 08:06:29 -08009979 }
9980 break;
9981 case M16_OPC_CMPI:
9982 {
9983 int16_t imm = (uint8_t) ctx->opcode;
Aurelien Jarnod75c1352013-01-01 18:02:22 +01009984 gen_logic_imm(ctx, OPC_XORI, 24, rx, imm);
Nathan Froyd364d4832009-12-08 08:06:29 -08009985 }
9986 break;
9987#if defined(TARGET_MIPS64)
9988 case M16_OPC_SD:
9989 check_mips_64(ctx);
Aurelien Jarno5c13fdf2010-07-01 07:47:00 +02009990 gen_st(ctx, OPC_SD, ry, rx, offset << 3);
Nathan Froyd364d4832009-12-08 08:06:29 -08009991 break;
9992#endif
9993 case M16_OPC_LB:
Aurelien Jarnod75c1352013-01-01 18:02:22 +01009994 gen_ld(ctx, OPC_LB, ry, rx, offset);
Nathan Froyd364d4832009-12-08 08:06:29 -08009995 break;
9996 case M16_OPC_LH:
Aurelien Jarnod75c1352013-01-01 18:02:22 +01009997 gen_ld(ctx, OPC_LH, ry, rx, offset << 1);
Nathan Froyd364d4832009-12-08 08:06:29 -08009998 break;
9999 case M16_OPC_LWSP:
Aurelien Jarnod75c1352013-01-01 18:02:22 +010010000 gen_ld(ctx, OPC_LW, rx, 29, ((uint8_t)ctx->opcode) << 2);
Nathan Froyd364d4832009-12-08 08:06:29 -080010001 break;
10002 case M16_OPC_LW:
Aurelien Jarnod75c1352013-01-01 18:02:22 +010010003 gen_ld(ctx, OPC_LW, ry, rx, offset << 2);
Nathan Froyd364d4832009-12-08 08:06:29 -080010004 break;
10005 case M16_OPC_LBU:
Aurelien Jarnod75c1352013-01-01 18:02:22 +010010006 gen_ld(ctx, OPC_LBU, ry, rx, offset);
Nathan Froyd364d4832009-12-08 08:06:29 -080010007 break;
10008 case M16_OPC_LHU:
Aurelien Jarnod75c1352013-01-01 18:02:22 +010010009 gen_ld(ctx, OPC_LHU, ry, rx, offset << 1);
Nathan Froyd364d4832009-12-08 08:06:29 -080010010 break;
10011 case M16_OPC_LWPC:
Aurelien Jarnod75c1352013-01-01 18:02:22 +010010012 gen_ld(ctx, OPC_LWPC, rx, 0, ((uint8_t)ctx->opcode) << 2);
Nathan Froyd364d4832009-12-08 08:06:29 -080010013 break;
10014#if defined (TARGET_MIPS64)
10015 case M16_OPC_LWU:
10016 check_mips_64(ctx);
Aurelien Jarnod75c1352013-01-01 18:02:22 +010010017 gen_ld(ctx, OPC_LWU, ry, rx, offset << 2);
Nathan Froyd364d4832009-12-08 08:06:29 -080010018 break;
10019#endif
10020 case M16_OPC_SB:
Aurelien Jarno5c13fdf2010-07-01 07:47:00 +020010021 gen_st(ctx, OPC_SB, ry, rx, offset);
Nathan Froyd364d4832009-12-08 08:06:29 -080010022 break;
10023 case M16_OPC_SH:
Aurelien Jarno5c13fdf2010-07-01 07:47:00 +020010024 gen_st(ctx, OPC_SH, ry, rx, offset << 1);
Nathan Froyd364d4832009-12-08 08:06:29 -080010025 break;
10026 case M16_OPC_SWSP:
Aurelien Jarno5c13fdf2010-07-01 07:47:00 +020010027 gen_st(ctx, OPC_SW, rx, 29, ((uint8_t)ctx->opcode) << 2);
Nathan Froyd364d4832009-12-08 08:06:29 -080010028 break;
10029 case M16_OPC_SW:
Aurelien Jarno5c13fdf2010-07-01 07:47:00 +020010030 gen_st(ctx, OPC_SW, ry, rx, offset << 2);
Nathan Froyd364d4832009-12-08 08:06:29 -080010031 break;
10032 case M16_OPC_RRR:
10033 {
10034 int rz = xlat((ctx->opcode >> 2) & 0x7);
10035 int mips32_op;
10036
10037 switch (ctx->opcode & 0x3) {
10038 case RRR_ADDU:
10039 mips32_op = OPC_ADDU;
10040 break;
10041 case RRR_SUBU:
10042 mips32_op = OPC_SUBU;
10043 break;
10044#if defined(TARGET_MIPS64)
10045 case RRR_DADDU:
10046 mips32_op = OPC_DADDU;
10047 check_mips_64(ctx);
10048 break;
10049 case RRR_DSUBU:
10050 mips32_op = OPC_DSUBU;
10051 check_mips_64(ctx);
10052 break;
10053#endif
10054 default:
10055 generate_exception(ctx, EXCP_RI);
10056 goto done;
10057 }
10058
Aurelien Jarnod75c1352013-01-01 18:02:22 +010010059 gen_arith(ctx, mips32_op, rz, rx, ry);
Nathan Froyd364d4832009-12-08 08:06:29 -080010060 done:
10061 ;
10062 }
10063 break;
10064 case M16_OPC_RR:
10065 switch (op1) {
10066 case RR_JR:
10067 {
10068 int nd = (ctx->opcode >> 7) & 0x1;
10069 int link = (ctx->opcode >> 6) & 0x1;
10070 int ra = (ctx->opcode >> 5) & 0x1;
10071
10072 if (link) {
Nathan Froyd620e48f2010-06-08 13:29:58 -070010073 op = nd ? OPC_JALRC : OPC_JALRS;
Nathan Froyd364d4832009-12-08 08:06:29 -080010074 } else {
10075 op = OPC_JR;
10076 }
10077
10078 gen_compute_branch(ctx, op, 2, ra ? 31 : rx, 31, 0);
10079 if (!nd) {
10080 *is_branch = 1;
10081 }
10082 }
10083 break;
10084 case RR_SDBBP:
10085 /* XXX: not clear which exception should be raised
10086 * when in debug mode...
10087 */
Aurelien Jarnod75c1352013-01-01 18:02:22 +010010088 check_insn(ctx, ISA_MIPS32);
Nathan Froyd364d4832009-12-08 08:06:29 -080010089 if (!(ctx->hflags & MIPS_HFLAG_DM)) {
10090 generate_exception(ctx, EXCP_DBp);
10091 } else {
10092 generate_exception(ctx, EXCP_DBp);
10093 }
10094 break;
10095 case RR_SLT:
Aurelien Jarnod75c1352013-01-01 18:02:22 +010010096 gen_slt(ctx, OPC_SLT, 24, rx, ry);
Nathan Froyd364d4832009-12-08 08:06:29 -080010097 break;
10098 case RR_SLTU:
Aurelien Jarnod75c1352013-01-01 18:02:22 +010010099 gen_slt(ctx, OPC_SLTU, 24, rx, ry);
Nathan Froyd364d4832009-12-08 08:06:29 -080010100 break;
10101 case RR_BREAK:
10102 generate_exception(ctx, EXCP_BREAK);
10103 break;
10104 case RR_SLLV:
Aurelien Jarnod75c1352013-01-01 18:02:22 +010010105 gen_shift(ctx, OPC_SLLV, ry, rx, ry);
Nathan Froyd364d4832009-12-08 08:06:29 -080010106 break;
10107 case RR_SRLV:
Aurelien Jarnod75c1352013-01-01 18:02:22 +010010108 gen_shift(ctx, OPC_SRLV, ry, rx, ry);
Nathan Froyd364d4832009-12-08 08:06:29 -080010109 break;
10110 case RR_SRAV:
Aurelien Jarnod75c1352013-01-01 18:02:22 +010010111 gen_shift(ctx, OPC_SRAV, ry, rx, ry);
Nathan Froyd364d4832009-12-08 08:06:29 -080010112 break;
10113#if defined (TARGET_MIPS64)
10114 case RR_DSRL:
10115 check_mips_64(ctx);
Aurelien Jarnod75c1352013-01-01 18:02:22 +010010116 gen_shift_imm(ctx, OPC_DSRL, ry, ry, sa);
Nathan Froyd364d4832009-12-08 08:06:29 -080010117 break;
10118#endif
10119 case RR_CMP:
Aurelien Jarnod75c1352013-01-01 18:02:22 +010010120 gen_logic(ctx, OPC_XOR, 24, rx, ry);
Nathan Froyd364d4832009-12-08 08:06:29 -080010121 break;
10122 case RR_NEG:
Aurelien Jarnod75c1352013-01-01 18:02:22 +010010123 gen_arith(ctx, OPC_SUBU, rx, 0, ry);
Nathan Froyd364d4832009-12-08 08:06:29 -080010124 break;
10125 case RR_AND:
Aurelien Jarnod75c1352013-01-01 18:02:22 +010010126 gen_logic(ctx, OPC_AND, rx, rx, ry);
Nathan Froyd364d4832009-12-08 08:06:29 -080010127 break;
10128 case RR_OR:
Aurelien Jarnod75c1352013-01-01 18:02:22 +010010129 gen_logic(ctx, OPC_OR, rx, rx, ry);
Nathan Froyd364d4832009-12-08 08:06:29 -080010130 break;
10131 case RR_XOR:
Aurelien Jarnod75c1352013-01-01 18:02:22 +010010132 gen_logic(ctx, OPC_XOR, rx, rx, ry);
Nathan Froyd364d4832009-12-08 08:06:29 -080010133 break;
10134 case RR_NOT:
Aurelien Jarnod75c1352013-01-01 18:02:22 +010010135 gen_logic(ctx, OPC_NOR, rx, ry, 0);
Nathan Froyd364d4832009-12-08 08:06:29 -080010136 break;
10137 case RR_MFHI:
10138 gen_HILO(ctx, OPC_MFHI, rx);
10139 break;
10140 case RR_CNVT:
10141 switch (cnvt_op) {
10142 case RR_RY_CNVT_ZEB:
10143 tcg_gen_ext8u_tl(cpu_gpr[rx], cpu_gpr[rx]);
10144 break;
10145 case RR_RY_CNVT_ZEH:
10146 tcg_gen_ext16u_tl(cpu_gpr[rx], cpu_gpr[rx]);
10147 break;
10148 case RR_RY_CNVT_SEB:
10149 tcg_gen_ext8s_tl(cpu_gpr[rx], cpu_gpr[rx]);
10150 break;
10151 case RR_RY_CNVT_SEH:
10152 tcg_gen_ext16s_tl(cpu_gpr[rx], cpu_gpr[rx]);
10153 break;
10154#if defined (TARGET_MIPS64)
10155 case RR_RY_CNVT_ZEW:
10156 check_mips_64(ctx);
10157 tcg_gen_ext32u_tl(cpu_gpr[rx], cpu_gpr[rx]);
10158 break;
10159 case RR_RY_CNVT_SEW:
10160 check_mips_64(ctx);
10161 tcg_gen_ext32s_tl(cpu_gpr[rx], cpu_gpr[rx]);
10162 break;
10163#endif
10164 default:
10165 generate_exception(ctx, EXCP_RI);
10166 break;
10167 }
10168 break;
10169 case RR_MFLO:
10170 gen_HILO(ctx, OPC_MFLO, rx);
10171 break;
10172#if defined (TARGET_MIPS64)
10173 case RR_DSRA:
10174 check_mips_64(ctx);
Aurelien Jarnod75c1352013-01-01 18:02:22 +010010175 gen_shift_imm(ctx, OPC_DSRA, ry, ry, sa);
Nathan Froyd364d4832009-12-08 08:06:29 -080010176 break;
10177 case RR_DSLLV:
10178 check_mips_64(ctx);
Aurelien Jarnod75c1352013-01-01 18:02:22 +010010179 gen_shift(ctx, OPC_DSLLV, ry, rx, ry);
Nathan Froyd364d4832009-12-08 08:06:29 -080010180 break;
10181 case RR_DSRLV:
10182 check_mips_64(ctx);
Aurelien Jarnod75c1352013-01-01 18:02:22 +010010183 gen_shift(ctx, OPC_DSRLV, ry, rx, ry);
Nathan Froyd364d4832009-12-08 08:06:29 -080010184 break;
10185 case RR_DSRAV:
10186 check_mips_64(ctx);
Aurelien Jarnod75c1352013-01-01 18:02:22 +010010187 gen_shift(ctx, OPC_DSRAV, ry, rx, ry);
Nathan Froyd364d4832009-12-08 08:06:29 -080010188 break;
10189#endif
10190 case RR_MULT:
10191 gen_muldiv(ctx, OPC_MULT, rx, ry);
10192 break;
10193 case RR_MULTU:
10194 gen_muldiv(ctx, OPC_MULTU, rx, ry);
10195 break;
10196 case RR_DIV:
10197 gen_muldiv(ctx, OPC_DIV, rx, ry);
10198 break;
10199 case RR_DIVU:
10200 gen_muldiv(ctx, OPC_DIVU, rx, ry);
10201 break;
10202#if defined (TARGET_MIPS64)
10203 case RR_DMULT:
10204 check_mips_64(ctx);
10205 gen_muldiv(ctx, OPC_DMULT, rx, ry);
10206 break;
10207 case RR_DMULTU:
10208 check_mips_64(ctx);
10209 gen_muldiv(ctx, OPC_DMULTU, rx, ry);
10210 break;
10211 case RR_DDIV:
10212 check_mips_64(ctx);
10213 gen_muldiv(ctx, OPC_DDIV, rx, ry);
10214 break;
10215 case RR_DDIVU:
10216 check_mips_64(ctx);
10217 gen_muldiv(ctx, OPC_DDIVU, rx, ry);
10218 break;
10219#endif
10220 default:
10221 generate_exception(ctx, EXCP_RI);
10222 break;
10223 }
10224 break;
10225 case M16_OPC_EXTEND:
10226 decode_extended_mips16_opc(env, ctx, is_branch);
10227 n_bytes = 4;
10228 break;
10229#if defined(TARGET_MIPS64)
10230 case M16_OPC_I64:
10231 funct = (ctx->opcode >> 8) & 0x7;
Aurelien Jarnod75c1352013-01-01 18:02:22 +010010232 decode_i64_mips16(ctx, ry, funct, offset, 0);
Nathan Froyd364d4832009-12-08 08:06:29 -080010233 break;
10234#endif
10235 default:
10236 generate_exception(ctx, EXCP_RI);
10237 break;
10238 }
10239
10240 return n_bytes;
10241}
10242
陳韋任 (Wei-Ren Chen)211da992012-11-21 14:04:41 +080010243/* microMIPS extension to MIPS32/MIPS64 */
Nathan Froyd3c824102010-06-08 13:29:59 -070010244
陳韋任 (Wei-Ren Chen)211da992012-11-21 14:04:41 +080010245/*
10246 * microMIPS32/microMIPS64 major opcodes
10247 *
10248 * 1. MIPS Architecture for Programmers Volume II-B:
10249 * The microMIPS32 Instruction Set (Revision 3.05)
10250 *
10251 * Table 6.2 microMIPS32 Encoding of Major Opcode Field
10252 *
10253 * 2. MIPS Architecture For Programmers Volume II-A:
10254 * The MIPS64 Instruction Set (Revision 3.51)
10255 */
Nathan Froyd3c824102010-06-08 13:29:59 -070010256
10257enum {
10258 POOL32A = 0x00,
10259 POOL16A = 0x01,
10260 LBU16 = 0x02,
10261 MOVE16 = 0x03,
10262 ADDI32 = 0x04,
10263 LBU32 = 0x05,
10264 SB32 = 0x06,
10265 LB32 = 0x07,
10266
10267 POOL32B = 0x08,
10268 POOL16B = 0x09,
10269 LHU16 = 0x0a,
10270 ANDI16 = 0x0b,
10271 ADDIU32 = 0x0c,
10272 LHU32 = 0x0d,
10273 SH32 = 0x0e,
10274 LH32 = 0x0f,
10275
10276 POOL32I = 0x10,
10277 POOL16C = 0x11,
10278 LWSP16 = 0x12,
10279 POOL16D = 0x13,
10280 ORI32 = 0x14,
10281 POOL32F = 0x15,
陳韋任 (Wei-Ren Chen)211da992012-11-21 14:04:41 +080010282 POOL32S = 0x16, /* MIPS64 */
10283 DADDIU32 = 0x17, /* MIPS64 */
Nathan Froyd3c824102010-06-08 13:29:59 -070010284
陳韋任 (Wei-Ren Chen)211da992012-11-21 14:04:41 +080010285 /* 0x1f is reserved */
Nathan Froyd3c824102010-06-08 13:29:59 -070010286 POOL32C = 0x18,
10287 LWGP16 = 0x19,
10288 LW16 = 0x1a,
10289 POOL16E = 0x1b,
10290 XORI32 = 0x1c,
10291 JALS32 = 0x1d,
10292 ADDIUPC = 0x1e,
Nathan Froyd3c824102010-06-08 13:29:59 -070010293
10294 /* 0x20 is reserved */
10295 RES_20 = 0x20,
10296 POOL16F = 0x21,
10297 SB16 = 0x22,
10298 BEQZ16 = 0x23,
10299 SLTI32 = 0x24,
10300 BEQ32 = 0x25,
10301 SWC132 = 0x26,
10302 LWC132 = 0x27,
10303
10304 /* 0x28 and 0x29 are reserved */
10305 RES_28 = 0x28,
10306 RES_29 = 0x29,
10307 SH16 = 0x2a,
10308 BNEZ16 = 0x2b,
10309 SLTIU32 = 0x2c,
10310 BNE32 = 0x2d,
10311 SDC132 = 0x2e,
10312 LDC132 = 0x2f,
10313
10314 /* 0x30 and 0x31 are reserved */
10315 RES_30 = 0x30,
10316 RES_31 = 0x31,
10317 SWSP16 = 0x32,
10318 B16 = 0x33,
10319 ANDI32 = 0x34,
10320 J32 = 0x35,
陳韋任 (Wei-Ren Chen)211da992012-11-21 14:04:41 +080010321 SD32 = 0x36, /* MIPS64 */
10322 LD32 = 0x37, /* MIPS64 */
Nathan Froyd3c824102010-06-08 13:29:59 -070010323
10324 /* 0x38 and 0x39 are reserved */
10325 RES_38 = 0x38,
10326 RES_39 = 0x39,
10327 SW16 = 0x3a,
10328 LI16 = 0x3b,
10329 JALX32 = 0x3c,
10330 JAL32 = 0x3d,
10331 SW32 = 0x3e,
10332 LW32 = 0x3f
10333};
10334
10335/* POOL32A encoding of minor opcode field */
10336
10337enum {
10338 /* These opcodes are distinguished only by bits 9..6; those bits are
10339 * what are recorded below. */
10340 SLL32 = 0x0,
10341 SRL32 = 0x1,
10342 SRA = 0x2,
10343 ROTR = 0x3,
10344
10345 SLLV = 0x0,
10346 SRLV = 0x1,
10347 SRAV = 0x2,
10348 ROTRV = 0x3,
10349 ADD = 0x4,
10350 ADDU32 = 0x5,
10351 SUB = 0x6,
10352 SUBU32 = 0x7,
10353 MUL = 0x8,
10354 AND = 0x9,
10355 OR32 = 0xa,
10356 NOR = 0xb,
10357 XOR32 = 0xc,
10358 SLT = 0xd,
10359 SLTU = 0xe,
10360
10361 MOVN = 0x0,
10362 MOVZ = 0x1,
10363 LWXS = 0x4,
10364
10365 /* The following can be distinguished by their lower 6 bits. */
10366 INS = 0x0c,
10367 EXT = 0x2c,
10368 POOL32AXF = 0x3c
10369};
10370
10371/* POOL32AXF encoding of minor opcode field extension */
10372
陳韋任 (Wei-Ren Chen)d132c792012-11-21 13:50:45 +080010373/*
10374 * 1. MIPS Architecture for Programmers Volume II-B:
10375 * The microMIPS32 Instruction Set (Revision 3.05)
10376 *
10377 * Table 6.5 POOL32Axf Encoding of Minor Opcode Extension Field
10378 *
10379 * 2. MIPS Architecture for Programmers VolumeIV-e:
10380 * The MIPS DSP Application-Specific Extension
10381 * to the microMIPS32 Architecture (Revision 2.34)
10382 *
10383 * Table 5.5 POOL32Axf Encoding of Minor Opcode Extension Field
10384 */
10385
Nathan Froyd3c824102010-06-08 13:29:59 -070010386enum {
10387 /* bits 11..6 */
10388 TEQ = 0x00,
10389 TGE = 0x08,
10390 TGEU = 0x10,
10391 TLT = 0x20,
10392 TLTU = 0x28,
10393 TNE = 0x30,
10394
10395 MFC0 = 0x03,
10396 MTC0 = 0x0b,
10397
陳韋任 (Wei-Ren Chen)d132c792012-11-21 13:50:45 +080010398 /* begin of microMIPS32 DSP */
10399
Nathan Froyd3c824102010-06-08 13:29:59 -070010400 /* bits 13..12 for 0x01 */
10401 MFHI_ACC = 0x0,
10402 MFLO_ACC = 0x1,
10403 MTHI_ACC = 0x2,
10404 MTLO_ACC = 0x3,
10405
10406 /* bits 13..12 for 0x2a */
10407 MADD_ACC = 0x0,
10408 MADDU_ACC = 0x1,
10409 MSUB_ACC = 0x2,
10410 MSUBU_ACC = 0x3,
10411
10412 /* bits 13..12 for 0x32 */
10413 MULT_ACC = 0x0,
陳韋任 (Wei-Ren Chen)68010382012-11-14 10:49:55 +080010414 MULTU_ACC = 0x1,
Nathan Froyd3c824102010-06-08 13:29:59 -070010415
陳韋任 (Wei-Ren Chen)d132c792012-11-21 13:50:45 +080010416 /* end of microMIPS32 DSP */
10417
Nathan Froyd3c824102010-06-08 13:29:59 -070010418 /* bits 15..12 for 0x2c */
10419 SEB = 0x2,
10420 SEH = 0x3,
10421 CLO = 0x4,
10422 CLZ = 0x5,
10423 RDHWR = 0x6,
10424 WSBH = 0x7,
10425 MULT = 0x8,
10426 MULTU = 0x9,
10427 DIV = 0xa,
10428 DIVU = 0xb,
10429 MADD = 0xc,
10430 MADDU = 0xd,
10431 MSUB = 0xe,
10432 MSUBU = 0xf,
10433
10434 /* bits 15..12 for 0x34 */
10435 MFC2 = 0x4,
10436 MTC2 = 0x5,
10437 MFHC2 = 0x8,
10438 MTHC2 = 0x9,
10439 CFC2 = 0xc,
10440 CTC2 = 0xd,
10441
10442 /* bits 15..12 for 0x3c */
10443 JALR = 0x0,
10444 JR = 0x0, /* alias */
10445 JALR_HB = 0x1,
10446 JALRS = 0x4,
10447 JALRS_HB = 0x5,
10448
10449 /* bits 15..12 for 0x05 */
10450 RDPGPR = 0xe,
10451 WRPGPR = 0xf,
10452
10453 /* bits 15..12 for 0x0d */
10454 TLBP = 0x0,
10455 TLBR = 0x1,
10456 TLBWI = 0x2,
10457 TLBWR = 0x3,
10458 WAIT = 0x9,
10459 IRET = 0xd,
10460 DERET = 0xe,
10461 ERET = 0xf,
10462
10463 /* bits 15..12 for 0x15 */
10464 DMT = 0x0,
10465 DVPE = 0x1,
10466 EMT = 0x2,
10467 EVPE = 0x3,
10468
10469 /* bits 15..12 for 0x1d */
10470 DI = 0x4,
10471 EI = 0x5,
10472
10473 /* bits 15..12 for 0x2d */
10474 SYNC = 0x6,
10475 SYSCALL = 0x8,
10476 SDBBP = 0xd,
10477
10478 /* bits 15..12 for 0x35 */
10479 MFHI32 = 0x0,
10480 MFLO32 = 0x1,
10481 MTHI32 = 0x2,
10482 MTLO32 = 0x3,
10483};
10484
10485/* POOL32B encoding of minor opcode field (bits 15..12) */
10486
10487enum {
10488 LWC2 = 0x0,
10489 LWP = 0x1,
10490 LDP = 0x4,
10491 LWM32 = 0x5,
10492 CACHE = 0x6,
10493 LDM = 0x7,
10494 SWC2 = 0x8,
10495 SWP = 0x9,
10496 SDP = 0xc,
10497 SWM32 = 0xd,
10498 SDM = 0xf
10499};
10500
10501/* POOL32C encoding of minor opcode field (bits 15..12) */
10502
10503enum {
10504 LWL = 0x0,
10505 SWL = 0x8,
10506 LWR = 0x1,
10507 SWR = 0x9,
10508 PREF = 0x2,
10509 /* 0xa is reserved */
10510 LL = 0x3,
10511 SC = 0xb,
10512 LDL = 0x4,
10513 SDL = 0xc,
10514 LDR = 0x5,
10515 SDR = 0xd,
10516 /* 0x6 is reserved */
10517 LWU = 0xe,
10518 LLD = 0x7,
10519 SCD = 0xf
10520};
10521
10522/* POOL32F encoding of minor opcode field (bits 5..0) */
10523
10524enum {
10525 /* These are the bit 7..6 values */
10526 ADD_FMT = 0x0,
10527 MOVN_FMT = 0x0,
10528
10529 SUB_FMT = 0x1,
10530 MOVZ_FMT = 0x1,
10531
10532 MUL_FMT = 0x2,
10533
10534 DIV_FMT = 0x3,
10535
10536 /* These are the bit 8..6 values */
10537 RSQRT2_FMT = 0x0,
10538 MOVF_FMT = 0x0,
10539
10540 LWXC1 = 0x1,
10541 MOVT_FMT = 0x1,
10542
10543 PLL_PS = 0x2,
10544 SWXC1 = 0x2,
10545
10546 PLU_PS = 0x3,
10547 LDXC1 = 0x3,
10548
10549 PUL_PS = 0x4,
10550 SDXC1 = 0x4,
10551 RECIP2_FMT = 0x4,
10552
10553 PUU_PS = 0x5,
10554 LUXC1 = 0x5,
10555
10556 CVT_PS_S = 0x6,
10557 SUXC1 = 0x6,
10558 ADDR_PS = 0x6,
10559 PREFX = 0x6,
10560
10561 MULR_PS = 0x7,
10562
10563 MADD_S = 0x01,
10564 MADD_D = 0x09,
10565 MADD_PS = 0x11,
10566 ALNV_PS = 0x19,
10567 MSUB_S = 0x21,
10568 MSUB_D = 0x29,
10569 MSUB_PS = 0x31,
10570
10571 NMADD_S = 0x02,
10572 NMADD_D = 0x0a,
10573 NMADD_PS = 0x12,
10574 NMSUB_S = 0x22,
10575 NMSUB_D = 0x2a,
10576 NMSUB_PS = 0x32,
10577
10578 POOL32FXF = 0x3b,
10579
10580 CABS_COND_FMT = 0x1c, /* MIPS3D */
10581 C_COND_FMT = 0x3c
10582};
10583
10584/* POOL32Fxf encoding of minor opcode extension field */
10585
10586enum {
10587 CVT_L = 0x04,
10588 RSQRT_FMT = 0x08,
10589 FLOOR_L = 0x0c,
10590 CVT_PW_PS = 0x1c,
10591 CVT_W = 0x24,
10592 SQRT_FMT = 0x28,
10593 FLOOR_W = 0x2c,
10594 CVT_PS_PW = 0x3c,
10595 CFC1 = 0x40,
10596 RECIP_FMT = 0x48,
10597 CEIL_L = 0x4c,
10598 CTC1 = 0x60,
10599 CEIL_W = 0x6c,
10600 MFC1 = 0x80,
10601 CVT_S_PL = 0x84,
10602 TRUNC_L = 0x8c,
10603 MTC1 = 0xa0,
10604 CVT_S_PU = 0xa4,
10605 TRUNC_W = 0xac,
10606 MFHC1 = 0xc0,
10607 ROUND_L = 0xcc,
10608 MTHC1 = 0xe0,
10609 ROUND_W = 0xec,
10610
10611 MOV_FMT = 0x01,
10612 MOVF = 0x05,
10613 ABS_FMT = 0x0d,
10614 RSQRT1_FMT = 0x1d,
10615 MOVT = 0x25,
10616 NEG_FMT = 0x2d,
10617 CVT_D = 0x4d,
10618 RECIP1_FMT = 0x5d,
10619 CVT_S = 0x6d
10620};
10621
10622/* POOL32I encoding of minor opcode field (bits 25..21) */
10623
10624enum {
10625 BLTZ = 0x00,
10626 BLTZAL = 0x01,
10627 BGEZ = 0x02,
10628 BGEZAL = 0x03,
10629 BLEZ = 0x04,
10630 BNEZC = 0x05,
10631 BGTZ = 0x06,
10632 BEQZC = 0x07,
10633 TLTI = 0x08,
10634 TGEI = 0x09,
10635 TLTIU = 0x0a,
10636 TGEIU = 0x0b,
10637 TNEI = 0x0c,
10638 LUI = 0x0d,
10639 TEQI = 0x0e,
10640 SYNCI = 0x10,
10641 BLTZALS = 0x11,
10642 BGEZALS = 0x13,
10643 BC2F = 0x14,
10644 BC2T = 0x15,
10645 BPOSGE64 = 0x1a,
10646 BPOSGE32 = 0x1b,
10647 /* These overlap and are distinguished by bit16 of the instruction */
10648 BC1F = 0x1c,
10649 BC1T = 0x1d,
10650 BC1ANY2F = 0x1c,
10651 BC1ANY2T = 0x1d,
10652 BC1ANY4F = 0x1e,
10653 BC1ANY4T = 0x1f
10654};
10655
10656/* POOL16A encoding of minor opcode field */
10657
10658enum {
10659 ADDU16 = 0x0,
10660 SUBU16 = 0x1
10661};
10662
10663/* POOL16B encoding of minor opcode field */
10664
10665enum {
10666 SLL16 = 0x0,
10667 SRL16 = 0x1
10668};
10669
10670/* POOL16C encoding of minor opcode field */
10671
10672enum {
10673 NOT16 = 0x00,
10674 XOR16 = 0x04,
10675 AND16 = 0x08,
10676 OR16 = 0x0c,
10677 LWM16 = 0x10,
10678 SWM16 = 0x14,
10679 JR16 = 0x18,
10680 JRC16 = 0x1a,
10681 JALR16 = 0x1c,
10682 JALR16S = 0x1e,
10683 MFHI16 = 0x20,
10684 MFLO16 = 0x24,
10685 BREAK16 = 0x28,
10686 SDBBP16 = 0x2c,
10687 JRADDIUSP = 0x30
10688};
10689
10690/* POOL16D encoding of minor opcode field */
10691
10692enum {
10693 ADDIUS5 = 0x0,
10694 ADDIUSP = 0x1
10695};
10696
10697/* POOL16E encoding of minor opcode field */
10698
10699enum {
10700 ADDIUR2 = 0x0,
10701 ADDIUR1SP = 0x1
10702};
10703
10704static int mmreg (int r)
10705{
10706 static const int map[] = { 16, 17, 2, 3, 4, 5, 6, 7 };
10707
10708 return map[r];
10709}
10710
10711/* Used for 16-bit store instructions. */
10712static int mmreg2 (int r)
10713{
10714 static const int map[] = { 0, 17, 2, 3, 4, 5, 6, 7 };
10715
10716 return map[r];
10717}
10718
10719#define uMIPS_RD(op) ((op >> 7) & 0x7)
10720#define uMIPS_RS(op) ((op >> 4) & 0x7)
10721#define uMIPS_RS2(op) uMIPS_RS(op)
10722#define uMIPS_RS1(op) ((op >> 1) & 0x7)
10723#define uMIPS_RD5(op) ((op >> 5) & 0x1f)
10724#define uMIPS_RS5(op) (op & 0x1f)
10725
10726/* Signed immediate */
10727#define SIMM(op, start, width) \
10728 ((int32_t)(((op >> start) & ((~0U) >> (32-width))) \
10729 << (32-width)) \
10730 >> (32-width))
10731/* Zero-extended immediate */
10732#define ZIMM(op, start, width) ((op >> start) & ((~0U) >> (32-width)))
10733
Aurelien Jarnod75c1352013-01-01 18:02:22 +010010734static void gen_addiur1sp(DisasContext *ctx)
Nathan Froyd3c824102010-06-08 13:29:59 -070010735{
10736 int rd = mmreg(uMIPS_RD(ctx->opcode));
10737
Aurelien Jarnod75c1352013-01-01 18:02:22 +010010738 gen_arith_imm(ctx, OPC_ADDIU, rd, 29, ((ctx->opcode >> 1) & 0x3f) << 2);
Nathan Froyd3c824102010-06-08 13:29:59 -070010739}
10740
Aurelien Jarnod75c1352013-01-01 18:02:22 +010010741static void gen_addiur2(DisasContext *ctx)
Nathan Froyd3c824102010-06-08 13:29:59 -070010742{
10743 static const int decoded_imm[] = { 1, 4, 8, 12, 16, 20, 24, -1 };
10744 int rd = mmreg(uMIPS_RD(ctx->opcode));
10745 int rs = mmreg(uMIPS_RS(ctx->opcode));
10746
Aurelien Jarnod75c1352013-01-01 18:02:22 +010010747 gen_arith_imm(ctx, OPC_ADDIU, rd, rs, decoded_imm[ZIMM(ctx->opcode, 1, 3)]);
Nathan Froyd3c824102010-06-08 13:29:59 -070010748}
10749
Aurelien Jarnod75c1352013-01-01 18:02:22 +010010750static void gen_addiusp(DisasContext *ctx)
Nathan Froyd3c824102010-06-08 13:29:59 -070010751{
10752 int encoded = ZIMM(ctx->opcode, 1, 9);
10753 int decoded;
10754
10755 if (encoded <= 1) {
10756 decoded = 256 + encoded;
10757 } else if (encoded <= 255) {
10758 decoded = encoded;
10759 } else if (encoded <= 509) {
10760 decoded = encoded - 512;
10761 } else {
10762 decoded = encoded - 768;
10763 }
10764
Aurelien Jarnod75c1352013-01-01 18:02:22 +010010765 gen_arith_imm(ctx, OPC_ADDIU, 29, 29, decoded << 2);
Nathan Froyd3c824102010-06-08 13:29:59 -070010766}
10767
Aurelien Jarnod75c1352013-01-01 18:02:22 +010010768static void gen_addius5(DisasContext *ctx)
Nathan Froyd3c824102010-06-08 13:29:59 -070010769{
10770 int imm = SIMM(ctx->opcode, 1, 4);
10771 int rd = (ctx->opcode >> 5) & 0x1f;
10772
Aurelien Jarnod75c1352013-01-01 18:02:22 +010010773 gen_arith_imm(ctx, OPC_ADDIU, rd, rd, imm);
Nathan Froyd3c824102010-06-08 13:29:59 -070010774}
10775
Aurelien Jarnod75c1352013-01-01 18:02:22 +010010776static void gen_andi16(DisasContext *ctx)
Nathan Froyd3c824102010-06-08 13:29:59 -070010777{
10778 static const int decoded_imm[] = { 128, 1, 2, 3, 4, 7, 8, 15, 16,
10779 31, 32, 63, 64, 255, 32768, 65535 };
10780 int rd = mmreg(uMIPS_RD(ctx->opcode));
10781 int rs = mmreg(uMIPS_RS(ctx->opcode));
10782 int encoded = ZIMM(ctx->opcode, 0, 4);
10783
Aurelien Jarnod75c1352013-01-01 18:02:22 +010010784 gen_logic_imm(ctx, OPC_ANDI, rd, rs, decoded_imm[encoded]);
Nathan Froyd3c824102010-06-08 13:29:59 -070010785}
10786
10787static void gen_ldst_multiple (DisasContext *ctx, uint32_t opc, int reglist,
10788 int base, int16_t offset)
10789{
Richard Hendersone1050a72012-09-18 21:55:32 -070010790 const char *opn = "ldst_multiple";
Nathan Froyd3c824102010-06-08 13:29:59 -070010791 TCGv t0, t1;
10792 TCGv_i32 t2;
10793
10794 if (ctx->hflags & MIPS_HFLAG_BMASK) {
10795 generate_exception(ctx, EXCP_RI);
10796 return;
10797 }
10798
10799 t0 = tcg_temp_new();
10800
10801 gen_base_offset_addr(ctx, t0, base, offset);
10802
10803 t1 = tcg_const_tl(reglist);
10804 t2 = tcg_const_i32(ctx->mem_idx);
10805
10806 save_cpu_state(ctx, 1);
10807 switch (opc) {
10808 case LWM32:
Blue Swirl895c2d02012-09-02 14:52:59 +000010809 gen_helper_lwm(cpu_env, t0, t1, t2);
Richard Hendersone1050a72012-09-18 21:55:32 -070010810 opn = "lwm";
Nathan Froyd3c824102010-06-08 13:29:59 -070010811 break;
10812 case SWM32:
Blue Swirl895c2d02012-09-02 14:52:59 +000010813 gen_helper_swm(cpu_env, t0, t1, t2);
Richard Hendersone1050a72012-09-18 21:55:32 -070010814 opn = "swm";
Nathan Froyd3c824102010-06-08 13:29:59 -070010815 break;
10816#ifdef TARGET_MIPS64
10817 case LDM:
Blue Swirl895c2d02012-09-02 14:52:59 +000010818 gen_helper_ldm(cpu_env, t0, t1, t2);
Richard Hendersone1050a72012-09-18 21:55:32 -070010819 opn = "ldm";
Nathan Froyd3c824102010-06-08 13:29:59 -070010820 break;
10821 case SDM:
Blue Swirl895c2d02012-09-02 14:52:59 +000010822 gen_helper_sdm(cpu_env, t0, t1, t2);
Richard Hendersone1050a72012-09-18 21:55:32 -070010823 opn = "sdm";
Nathan Froyd3c824102010-06-08 13:29:59 -070010824 break;
10825#endif
10826 }
Richard Hendersone1050a72012-09-18 21:55:32 -070010827 (void)opn;
Nathan Froyd3c824102010-06-08 13:29:59 -070010828 MIPS_DEBUG("%s, %x, %d(%s)", opn, reglist, offset, regnames[base]);
10829 tcg_temp_free(t0);
Stefan Weil33087592010-06-09 22:09:40 +020010830 tcg_temp_free(t1);
Nathan Froyd3c824102010-06-08 13:29:59 -070010831 tcg_temp_free_i32(t2);
10832}
10833
10834
Aurelien Jarnod75c1352013-01-01 18:02:22 +010010835static void gen_pool16c_insn(DisasContext *ctx, int *is_branch)
Nathan Froyd3c824102010-06-08 13:29:59 -070010836{
10837 int rd = mmreg((ctx->opcode >> 3) & 0x7);
10838 int rs = mmreg(ctx->opcode & 0x7);
10839 int opc;
10840
10841 switch (((ctx->opcode) >> 4) & 0x3f) {
10842 case NOT16 + 0:
10843 case NOT16 + 1:
10844 case NOT16 + 2:
10845 case NOT16 + 3:
Aurelien Jarnod75c1352013-01-01 18:02:22 +010010846 gen_logic(ctx, OPC_NOR, rd, rs, 0);
Nathan Froyd3c824102010-06-08 13:29:59 -070010847 break;
10848 case XOR16 + 0:
10849 case XOR16 + 1:
10850 case XOR16 + 2:
10851 case XOR16 + 3:
Aurelien Jarnod75c1352013-01-01 18:02:22 +010010852 gen_logic(ctx, OPC_XOR, rd, rd, rs);
Nathan Froyd3c824102010-06-08 13:29:59 -070010853 break;
10854 case AND16 + 0:
10855 case AND16 + 1:
10856 case AND16 + 2:
10857 case AND16 + 3:
Aurelien Jarnod75c1352013-01-01 18:02:22 +010010858 gen_logic(ctx, OPC_AND, rd, rd, rs);
Nathan Froyd3c824102010-06-08 13:29:59 -070010859 break;
10860 case OR16 + 0:
10861 case OR16 + 1:
10862 case OR16 + 2:
10863 case OR16 + 3:
Aurelien Jarnod75c1352013-01-01 18:02:22 +010010864 gen_logic(ctx, OPC_OR, rd, rd, rs);
Nathan Froyd3c824102010-06-08 13:29:59 -070010865 break;
10866 case LWM16 + 0:
10867 case LWM16 + 1:
10868 case LWM16 + 2:
10869 case LWM16 + 3:
10870 {
10871 static const int lwm_convert[] = { 0x11, 0x12, 0x13, 0x14 };
10872 int offset = ZIMM(ctx->opcode, 0, 4);
10873
10874 gen_ldst_multiple(ctx, LWM32, lwm_convert[(ctx->opcode >> 4) & 0x3],
10875 29, offset << 2);
10876 }
10877 break;
10878 case SWM16 + 0:
10879 case SWM16 + 1:
10880 case SWM16 + 2:
10881 case SWM16 + 3:
10882 {
10883 static const int swm_convert[] = { 0x11, 0x12, 0x13, 0x14 };
10884 int offset = ZIMM(ctx->opcode, 0, 4);
10885
10886 gen_ldst_multiple(ctx, SWM32, swm_convert[(ctx->opcode >> 4) & 0x3],
10887 29, offset << 2);
10888 }
10889 break;
10890 case JR16 + 0:
10891 case JR16 + 1:
10892 {
10893 int reg = ctx->opcode & 0x1f;
10894
10895 gen_compute_branch(ctx, OPC_JR, 2, reg, 0, 0);
10896 }
10897 *is_branch = 1;
10898 break;
10899 case JRC16 + 0:
10900 case JRC16 + 1:
10901 {
10902 int reg = ctx->opcode & 0x1f;
10903
10904 gen_compute_branch(ctx, OPC_JR, 2, reg, 0, 0);
10905 /* Let normal delay slot handling in our caller take us
10906 to the branch target. */
10907 }
10908 break;
10909 case JALR16 + 0:
10910 case JALR16 + 1:
10911 opc = OPC_JALR;
10912 goto do_jalr;
10913 case JALR16S + 0:
10914 case JALR16S + 1:
10915 opc = OPC_JALRS;
10916 do_jalr:
10917 {
10918 int reg = ctx->opcode & 0x1f;
10919
10920 gen_compute_branch(ctx, opc, 2, reg, 31, 0);
10921 }
10922 *is_branch = 1;
10923 break;
10924 case MFHI16 + 0:
10925 case MFHI16 + 1:
10926 gen_HILO(ctx, OPC_MFHI, uMIPS_RS5(ctx->opcode));
10927 break;
10928 case MFLO16 + 0:
10929 case MFLO16 + 1:
10930 gen_HILO(ctx, OPC_MFLO, uMIPS_RS5(ctx->opcode));
10931 break;
10932 case BREAK16:
10933 generate_exception(ctx, EXCP_BREAK);
10934 break;
10935 case SDBBP16:
10936 /* XXX: not clear which exception should be raised
10937 * when in debug mode...
10938 */
Aurelien Jarnod75c1352013-01-01 18:02:22 +010010939 check_insn(ctx, ISA_MIPS32);
Nathan Froyd3c824102010-06-08 13:29:59 -070010940 if (!(ctx->hflags & MIPS_HFLAG_DM)) {
10941 generate_exception(ctx, EXCP_DBp);
10942 } else {
10943 generate_exception(ctx, EXCP_DBp);
10944 }
10945 break;
10946 case JRADDIUSP + 0:
10947 case JRADDIUSP + 1:
10948 {
10949 int imm = ZIMM(ctx->opcode, 0, 5);
10950
10951 gen_compute_branch(ctx, OPC_JR, 2, 31, 0, 0);
Aurelien Jarnod75c1352013-01-01 18:02:22 +010010952 gen_arith_imm(ctx, OPC_ADDIU, 29, 29, imm << 2);
Nathan Froyd3c824102010-06-08 13:29:59 -070010953 /* Let normal delay slot handling in our caller take us
10954 to the branch target. */
10955 }
10956 break;
10957 default:
10958 generate_exception(ctx, EXCP_RI);
10959 break;
10960 }
10961}
10962
10963static void gen_ldxs (DisasContext *ctx, int base, int index, int rd)
10964{
10965 TCGv t0 = tcg_temp_new();
10966 TCGv t1 = tcg_temp_new();
10967
10968 gen_load_gpr(t0, base);
10969
10970 if (index != 0) {
10971 gen_load_gpr(t1, index);
10972 tcg_gen_shli_tl(t1, t1, 2);
10973 gen_op_addr_add(ctx, t0, t1, t0);
10974 }
10975
Aurelien Jarno2910c6cb2012-10-09 21:53:20 +020010976 tcg_gen_qemu_ld32s(t1, t0, ctx->mem_idx);
Nathan Froyd3c824102010-06-08 13:29:59 -070010977 gen_store_gpr(t1, rd);
10978
10979 tcg_temp_free(t0);
10980 tcg_temp_free(t1);
10981}
10982
10983static void gen_ldst_pair (DisasContext *ctx, uint32_t opc, int rd,
10984 int base, int16_t offset)
10985{
10986 const char *opn = "ldst_pair";
10987 TCGv t0, t1;
10988
Eric Johnson36c67112011-09-17 17:28:16 -070010989 if (ctx->hflags & MIPS_HFLAG_BMASK || rd == 31) {
Nathan Froyd3c824102010-06-08 13:29:59 -070010990 generate_exception(ctx, EXCP_RI);
10991 return;
10992 }
10993
10994 t0 = tcg_temp_new();
10995 t1 = tcg_temp_new();
10996
10997 gen_base_offset_addr(ctx, t0, base, offset);
10998
10999 switch (opc) {
11000 case LWP:
Eric Johnson36c67112011-09-17 17:28:16 -070011001 if (rd == base) {
11002 generate_exception(ctx, EXCP_RI);
11003 return;
11004 }
Aurelien Jarno2910c6cb2012-10-09 21:53:20 +020011005 tcg_gen_qemu_ld32s(t1, t0, ctx->mem_idx);
Nathan Froyd3c824102010-06-08 13:29:59 -070011006 gen_store_gpr(t1, rd);
11007 tcg_gen_movi_tl(t1, 4);
11008 gen_op_addr_add(ctx, t0, t0, t1);
Aurelien Jarno2910c6cb2012-10-09 21:53:20 +020011009 tcg_gen_qemu_ld32s(t1, t0, ctx->mem_idx);
Nathan Froyd3c824102010-06-08 13:29:59 -070011010 gen_store_gpr(t1, rd+1);
11011 opn = "lwp";
11012 break;
11013 case SWP:
Nathan Froyd3c824102010-06-08 13:29:59 -070011014 gen_load_gpr(t1, rd);
Aurelien Jarno2910c6cb2012-10-09 21:53:20 +020011015 tcg_gen_qemu_st32(t1, t0, ctx->mem_idx);
Nathan Froyd3c824102010-06-08 13:29:59 -070011016 tcg_gen_movi_tl(t1, 4);
11017 gen_op_addr_add(ctx, t0, t0, t1);
11018 gen_load_gpr(t1, rd+1);
Aurelien Jarno2910c6cb2012-10-09 21:53:20 +020011019 tcg_gen_qemu_st32(t1, t0, ctx->mem_idx);
Nathan Froyd3c824102010-06-08 13:29:59 -070011020 opn = "swp";
11021 break;
11022#ifdef TARGET_MIPS64
11023 case LDP:
Eric Johnson36c67112011-09-17 17:28:16 -070011024 if (rd == base) {
11025 generate_exception(ctx, EXCP_RI);
11026 return;
11027 }
Aurelien Jarno2910c6cb2012-10-09 21:53:20 +020011028 tcg_gen_qemu_ld64(t1, t0, ctx->mem_idx);
Nathan Froyd3c824102010-06-08 13:29:59 -070011029 gen_store_gpr(t1, rd);
11030 tcg_gen_movi_tl(t1, 8);
11031 gen_op_addr_add(ctx, t0, t0, t1);
Aurelien Jarno2910c6cb2012-10-09 21:53:20 +020011032 tcg_gen_qemu_ld64(t1, t0, ctx->mem_idx);
Nathan Froyd3c824102010-06-08 13:29:59 -070011033 gen_store_gpr(t1, rd+1);
11034 opn = "ldp";
11035 break;
11036 case SDP:
Nathan Froyd3c824102010-06-08 13:29:59 -070011037 gen_load_gpr(t1, rd);
Aurelien Jarno2910c6cb2012-10-09 21:53:20 +020011038 tcg_gen_qemu_st64(t1, t0, ctx->mem_idx);
Nathan Froyd3c824102010-06-08 13:29:59 -070011039 tcg_gen_movi_tl(t1, 8);
11040 gen_op_addr_add(ctx, t0, t0, t1);
11041 gen_load_gpr(t1, rd+1);
Aurelien Jarno2910c6cb2012-10-09 21:53:20 +020011042 tcg_gen_qemu_st64(t1, t0, ctx->mem_idx);
Nathan Froyd3c824102010-06-08 13:29:59 -070011043 opn = "sdp";
11044 break;
11045#endif
11046 }
Blue Swirl2abf3142010-10-13 18:38:08 +000011047 (void)opn; /* avoid a compiler warning */
Nathan Froyd3c824102010-06-08 13:29:59 -070011048 MIPS_DEBUG("%s, %s, %d(%s)", opn, regnames[rd], offset, regnames[base]);
11049 tcg_temp_free(t0);
11050 tcg_temp_free(t1);
11051}
11052
Andreas Färber7db13fa2012-03-14 01:38:22 +010011053static void gen_pool32axf (CPUMIPSState *env, DisasContext *ctx, int rt, int rs,
Nathan Froyd3c824102010-06-08 13:29:59 -070011054 int *is_branch)
11055{
11056 int extension = (ctx->opcode >> 6) & 0x3f;
11057 int minor = (ctx->opcode >> 12) & 0xf;
11058 uint32_t mips32_op;
11059
11060 switch (extension) {
11061 case TEQ:
11062 mips32_op = OPC_TEQ;
11063 goto do_trap;
11064 case TGE:
11065 mips32_op = OPC_TGE;
11066 goto do_trap;
11067 case TGEU:
11068 mips32_op = OPC_TGEU;
11069 goto do_trap;
11070 case TLT:
11071 mips32_op = OPC_TLT;
11072 goto do_trap;
11073 case TLTU:
11074 mips32_op = OPC_TLTU;
11075 goto do_trap;
11076 case TNE:
11077 mips32_op = OPC_TNE;
11078 do_trap:
11079 gen_trap(ctx, mips32_op, rs, rt, -1);
11080 break;
11081#ifndef CONFIG_USER_ONLY
11082 case MFC0:
11083 case MFC0 + 32:
Eric Johnson2e154972011-09-17 17:05:32 -070011084 check_cp0_enabled(ctx);
Nathan Froyd3c824102010-06-08 13:29:59 -070011085 if (rt == 0) {
11086 /* Treat as NOP. */
11087 break;
11088 }
Aurelien Jarnod75c1352013-01-01 18:02:22 +010011089 gen_mfc0(ctx, cpu_gpr[rt], rs, (ctx->opcode >> 11) & 0x7);
Nathan Froyd3c824102010-06-08 13:29:59 -070011090 break;
11091 case MTC0:
11092 case MTC0 + 32:
Eric Johnson2e154972011-09-17 17:05:32 -070011093 check_cp0_enabled(ctx);
Nathan Froyd3c824102010-06-08 13:29:59 -070011094 {
11095 TCGv t0 = tcg_temp_new();
11096
11097 gen_load_gpr(t0, rt);
Aurelien Jarnod75c1352013-01-01 18:02:22 +010011098 gen_mtc0(ctx, t0, rs, (ctx->opcode >> 11) & 0x7);
Nathan Froyd3c824102010-06-08 13:29:59 -070011099 tcg_temp_free(t0);
11100 }
11101 break;
11102#endif
11103 case 0x2c:
11104 switch (minor) {
11105 case SEB:
11106 gen_bshfl(ctx, OPC_SEB, rs, rt);
11107 break;
11108 case SEH:
11109 gen_bshfl(ctx, OPC_SEH, rs, rt);
11110 break;
11111 case CLO:
11112 mips32_op = OPC_CLO;
11113 goto do_cl;
11114 case CLZ:
11115 mips32_op = OPC_CLZ;
11116 do_cl:
Aurelien Jarnod75c1352013-01-01 18:02:22 +010011117 check_insn(ctx, ISA_MIPS32);
Nathan Froyd3c824102010-06-08 13:29:59 -070011118 gen_cl(ctx, mips32_op, rt, rs);
11119 break;
11120 case RDHWR:
Aurelien Jarnod75c1352013-01-01 18:02:22 +010011121 gen_rdhwr(ctx, rt, rs);
Nathan Froyd3c824102010-06-08 13:29:59 -070011122 break;
11123 case WSBH:
11124 gen_bshfl(ctx, OPC_WSBH, rs, rt);
11125 break;
11126 case MULT:
11127 mips32_op = OPC_MULT;
11128 goto do_muldiv;
11129 case MULTU:
11130 mips32_op = OPC_MULTU;
11131 goto do_muldiv;
11132 case DIV:
11133 mips32_op = OPC_DIV;
11134 goto do_muldiv;
11135 case DIVU:
11136 mips32_op = OPC_DIVU;
11137 goto do_muldiv;
11138 case MADD:
11139 mips32_op = OPC_MADD;
11140 goto do_muldiv;
11141 case MADDU:
11142 mips32_op = OPC_MADDU;
11143 goto do_muldiv;
11144 case MSUB:
11145 mips32_op = OPC_MSUB;
11146 goto do_muldiv;
11147 case MSUBU:
11148 mips32_op = OPC_MSUBU;
11149 do_muldiv:
Aurelien Jarnod75c1352013-01-01 18:02:22 +010011150 check_insn(ctx, ISA_MIPS32);
Nathan Froyd3c824102010-06-08 13:29:59 -070011151 gen_muldiv(ctx, mips32_op, rs, rt);
11152 break;
11153 default:
11154 goto pool32axf_invalid;
11155 }
11156 break;
11157 case 0x34:
11158 switch (minor) {
11159 case MFC2:
11160 case MTC2:
11161 case MFHC2:
11162 case MTHC2:
11163 case CFC2:
11164 case CTC2:
11165 generate_exception_err(ctx, EXCP_CpU, 2);
11166 break;
11167 default:
11168 goto pool32axf_invalid;
11169 }
11170 break;
11171 case 0x3c:
11172 switch (minor) {
11173 case JALR:
11174 case JALR_HB:
11175 gen_compute_branch (ctx, OPC_JALR, 4, rs, rt, 0);
11176 *is_branch = 1;
11177 break;
11178 case JALRS:
11179 case JALRS_HB:
11180 gen_compute_branch (ctx, OPC_JALRS, 4, rs, rt, 0);
11181 *is_branch = 1;
11182 break;
11183 default:
11184 goto pool32axf_invalid;
11185 }
11186 break;
11187 case 0x05:
11188 switch (minor) {
11189 case RDPGPR:
Eric Johnson2e154972011-09-17 17:05:32 -070011190 check_cp0_enabled(ctx);
Aurelien Jarnod75c1352013-01-01 18:02:22 +010011191 check_insn(ctx, ISA_MIPS32R2);
Nathan Froyd3c824102010-06-08 13:29:59 -070011192 gen_load_srsgpr(rt, rs);
11193 break;
11194 case WRPGPR:
Eric Johnson2e154972011-09-17 17:05:32 -070011195 check_cp0_enabled(ctx);
Aurelien Jarnod75c1352013-01-01 18:02:22 +010011196 check_insn(ctx, ISA_MIPS32R2);
Nathan Froyd3c824102010-06-08 13:29:59 -070011197 gen_store_srsgpr(rt, rs);
11198 break;
11199 default:
11200 goto pool32axf_invalid;
11201 }
11202 break;
11203#ifndef CONFIG_USER_ONLY
11204 case 0x0d:
11205 switch (minor) {
11206 case TLBP:
11207 mips32_op = OPC_TLBP;
11208 goto do_cp0;
11209 case TLBR:
11210 mips32_op = OPC_TLBR;
11211 goto do_cp0;
11212 case TLBWI:
11213 mips32_op = OPC_TLBWI;
11214 goto do_cp0;
11215 case TLBWR:
11216 mips32_op = OPC_TLBWR;
11217 goto do_cp0;
11218 case WAIT:
11219 mips32_op = OPC_WAIT;
11220 goto do_cp0;
11221 case DERET:
11222 mips32_op = OPC_DERET;
11223 goto do_cp0;
11224 case ERET:
11225 mips32_op = OPC_ERET;
11226 do_cp0:
11227 gen_cp0(env, ctx, mips32_op, rt, rs);
11228 break;
11229 default:
11230 goto pool32axf_invalid;
11231 }
11232 break;
11233 case 0x1d:
11234 switch (minor) {
11235 case DI:
Eric Johnson2e154972011-09-17 17:05:32 -070011236 check_cp0_enabled(ctx);
Nathan Froyd3c824102010-06-08 13:29:59 -070011237 {
11238 TCGv t0 = tcg_temp_new();
11239
11240 save_cpu_state(ctx, 1);
Blue Swirl895c2d02012-09-02 14:52:59 +000011241 gen_helper_di(t0, cpu_env);
Nathan Froyd3c824102010-06-08 13:29:59 -070011242 gen_store_gpr(t0, rs);
11243 /* Stop translation as we may have switched the execution mode */
11244 ctx->bstate = BS_STOP;
11245 tcg_temp_free(t0);
11246 }
11247 break;
11248 case EI:
Eric Johnson2e154972011-09-17 17:05:32 -070011249 check_cp0_enabled(ctx);
Nathan Froyd3c824102010-06-08 13:29:59 -070011250 {
11251 TCGv t0 = tcg_temp_new();
11252
11253 save_cpu_state(ctx, 1);
Blue Swirl895c2d02012-09-02 14:52:59 +000011254 gen_helper_ei(t0, cpu_env);
Nathan Froyd3c824102010-06-08 13:29:59 -070011255 gen_store_gpr(t0, rs);
11256 /* Stop translation as we may have switched the execution mode */
11257 ctx->bstate = BS_STOP;
11258 tcg_temp_free(t0);
11259 }
11260 break;
11261 default:
11262 goto pool32axf_invalid;
11263 }
11264 break;
11265#endif
11266 case 0x2d:
11267 switch (minor) {
11268 case SYNC:
11269 /* NOP */
11270 break;
11271 case SYSCALL:
11272 generate_exception(ctx, EXCP_SYSCALL);
11273 ctx->bstate = BS_STOP;
11274 break;
11275 case SDBBP:
Aurelien Jarnod75c1352013-01-01 18:02:22 +010011276 check_insn(ctx, ISA_MIPS32);
Nathan Froyd3c824102010-06-08 13:29:59 -070011277 if (!(ctx->hflags & MIPS_HFLAG_DM)) {
11278 generate_exception(ctx, EXCP_DBp);
11279 } else {
11280 generate_exception(ctx, EXCP_DBp);
11281 }
11282 break;
11283 default:
11284 goto pool32axf_invalid;
11285 }
11286 break;
11287 case 0x35:
11288 switch (minor) {
11289 case MFHI32:
11290 gen_HILO(ctx, OPC_MFHI, rs);
11291 break;
11292 case MFLO32:
11293 gen_HILO(ctx, OPC_MFLO, rs);
11294 break;
11295 case MTHI32:
11296 gen_HILO(ctx, OPC_MTHI, rs);
11297 break;
11298 case MTLO32:
11299 gen_HILO(ctx, OPC_MTLO, rs);
11300 break;
11301 default:
11302 goto pool32axf_invalid;
11303 }
11304 break;
11305 default:
11306 pool32axf_invalid:
11307 MIPS_INVAL("pool32axf");
11308 generate_exception(ctx, EXCP_RI);
11309 break;
11310 }
11311}
11312
11313/* Values for microMIPS fmt field. Variable-width, depending on which
11314 formats the instruction supports. */
11315
11316enum {
11317 FMT_SD_S = 0,
11318 FMT_SD_D = 1,
11319
11320 FMT_SDPS_S = 0,
11321 FMT_SDPS_D = 1,
11322 FMT_SDPS_PS = 2,
11323
11324 FMT_SWL_S = 0,
11325 FMT_SWL_W = 1,
11326 FMT_SWL_L = 2,
11327
11328 FMT_DWL_D = 0,
11329 FMT_DWL_W = 1,
11330 FMT_DWL_L = 2
11331};
11332
Aurelien Jarnod75c1352013-01-01 18:02:22 +010011333static void gen_pool32fxf(DisasContext *ctx, int rt, int rs)
Nathan Froyd3c824102010-06-08 13:29:59 -070011334{
11335 int extension = (ctx->opcode >> 6) & 0x3ff;
11336 uint32_t mips32_op;
11337
11338#define FLOAT_1BIT_FMT(opc, fmt) (fmt << 8) | opc
11339#define FLOAT_2BIT_FMT(opc, fmt) (fmt << 7) | opc
11340#define COND_FLOAT_MOV(opc, cond) (cond << 7) | opc
11341
11342 switch (extension) {
11343 case FLOAT_1BIT_FMT(CFC1, 0):
11344 mips32_op = OPC_CFC1;
11345 goto do_cp1;
11346 case FLOAT_1BIT_FMT(CTC1, 0):
11347 mips32_op = OPC_CTC1;
11348 goto do_cp1;
11349 case FLOAT_1BIT_FMT(MFC1, 0):
11350 mips32_op = OPC_MFC1;
11351 goto do_cp1;
11352 case FLOAT_1BIT_FMT(MTC1, 0):
11353 mips32_op = OPC_MTC1;
11354 goto do_cp1;
11355 case FLOAT_1BIT_FMT(MFHC1, 0):
11356 mips32_op = OPC_MFHC1;
11357 goto do_cp1;
11358 case FLOAT_1BIT_FMT(MTHC1, 0):
11359 mips32_op = OPC_MTHC1;
11360 do_cp1:
11361 gen_cp1(ctx, mips32_op, rt, rs);
11362 break;
11363
11364 /* Reciprocal square root */
11365 case FLOAT_1BIT_FMT(RSQRT_FMT, FMT_SD_S):
11366 mips32_op = OPC_RSQRT_S;
11367 goto do_unaryfp;
11368 case FLOAT_1BIT_FMT(RSQRT_FMT, FMT_SD_D):
11369 mips32_op = OPC_RSQRT_D;
11370 goto do_unaryfp;
11371
11372 /* Square root */
11373 case FLOAT_1BIT_FMT(SQRT_FMT, FMT_SD_S):
11374 mips32_op = OPC_SQRT_S;
11375 goto do_unaryfp;
11376 case FLOAT_1BIT_FMT(SQRT_FMT, FMT_SD_D):
11377 mips32_op = OPC_SQRT_D;
11378 goto do_unaryfp;
11379
11380 /* Reciprocal */
11381 case FLOAT_1BIT_FMT(RECIP_FMT, FMT_SD_S):
11382 mips32_op = OPC_RECIP_S;
11383 goto do_unaryfp;
11384 case FLOAT_1BIT_FMT(RECIP_FMT, FMT_SD_D):
11385 mips32_op = OPC_RECIP_D;
11386 goto do_unaryfp;
11387
11388 /* Floor */
11389 case FLOAT_1BIT_FMT(FLOOR_L, FMT_SD_S):
11390 mips32_op = OPC_FLOOR_L_S;
11391 goto do_unaryfp;
11392 case FLOAT_1BIT_FMT(FLOOR_L, FMT_SD_D):
11393 mips32_op = OPC_FLOOR_L_D;
11394 goto do_unaryfp;
11395 case FLOAT_1BIT_FMT(FLOOR_W, FMT_SD_S):
11396 mips32_op = OPC_FLOOR_W_S;
11397 goto do_unaryfp;
11398 case FLOAT_1BIT_FMT(FLOOR_W, FMT_SD_D):
11399 mips32_op = OPC_FLOOR_W_D;
11400 goto do_unaryfp;
11401
11402 /* Ceiling */
11403 case FLOAT_1BIT_FMT(CEIL_L, FMT_SD_S):
11404 mips32_op = OPC_CEIL_L_S;
11405 goto do_unaryfp;
11406 case FLOAT_1BIT_FMT(CEIL_L, FMT_SD_D):
11407 mips32_op = OPC_CEIL_L_D;
11408 goto do_unaryfp;
11409 case FLOAT_1BIT_FMT(CEIL_W, FMT_SD_S):
11410 mips32_op = OPC_CEIL_W_S;
11411 goto do_unaryfp;
11412 case FLOAT_1BIT_FMT(CEIL_W, FMT_SD_D):
11413 mips32_op = OPC_CEIL_W_D;
11414 goto do_unaryfp;
11415
11416 /* Truncation */
11417 case FLOAT_1BIT_FMT(TRUNC_L, FMT_SD_S):
11418 mips32_op = OPC_TRUNC_L_S;
11419 goto do_unaryfp;
11420 case FLOAT_1BIT_FMT(TRUNC_L, FMT_SD_D):
11421 mips32_op = OPC_TRUNC_L_D;
11422 goto do_unaryfp;
11423 case FLOAT_1BIT_FMT(TRUNC_W, FMT_SD_S):
11424 mips32_op = OPC_TRUNC_W_S;
11425 goto do_unaryfp;
11426 case FLOAT_1BIT_FMT(TRUNC_W, FMT_SD_D):
11427 mips32_op = OPC_TRUNC_W_D;
11428 goto do_unaryfp;
11429
11430 /* Round */
11431 case FLOAT_1BIT_FMT(ROUND_L, FMT_SD_S):
11432 mips32_op = OPC_ROUND_L_S;
11433 goto do_unaryfp;
11434 case FLOAT_1BIT_FMT(ROUND_L, FMT_SD_D):
11435 mips32_op = OPC_ROUND_L_D;
11436 goto do_unaryfp;
11437 case FLOAT_1BIT_FMT(ROUND_W, FMT_SD_S):
11438 mips32_op = OPC_ROUND_W_S;
11439 goto do_unaryfp;
11440 case FLOAT_1BIT_FMT(ROUND_W, FMT_SD_D):
11441 mips32_op = OPC_ROUND_W_D;
11442 goto do_unaryfp;
11443
11444 /* Integer to floating-point conversion */
11445 case FLOAT_1BIT_FMT(CVT_L, FMT_SD_S):
11446 mips32_op = OPC_CVT_L_S;
11447 goto do_unaryfp;
11448 case FLOAT_1BIT_FMT(CVT_L, FMT_SD_D):
11449 mips32_op = OPC_CVT_L_D;
11450 goto do_unaryfp;
11451 case FLOAT_1BIT_FMT(CVT_W, FMT_SD_S):
11452 mips32_op = OPC_CVT_W_S;
11453 goto do_unaryfp;
11454 case FLOAT_1BIT_FMT(CVT_W, FMT_SD_D):
11455 mips32_op = OPC_CVT_W_D;
11456 goto do_unaryfp;
11457
11458 /* Paired-foo conversions */
11459 case FLOAT_1BIT_FMT(CVT_S_PL, 0):
11460 mips32_op = OPC_CVT_S_PL;
11461 goto do_unaryfp;
11462 case FLOAT_1BIT_FMT(CVT_S_PU, 0):
11463 mips32_op = OPC_CVT_S_PU;
11464 goto do_unaryfp;
11465 case FLOAT_1BIT_FMT(CVT_PW_PS, 0):
11466 mips32_op = OPC_CVT_PW_PS;
11467 goto do_unaryfp;
11468 case FLOAT_1BIT_FMT(CVT_PS_PW, 0):
11469 mips32_op = OPC_CVT_PS_PW;
11470 goto do_unaryfp;
11471
11472 /* Floating-point moves */
11473 case FLOAT_2BIT_FMT(MOV_FMT, FMT_SDPS_S):
11474 mips32_op = OPC_MOV_S;
11475 goto do_unaryfp;
11476 case FLOAT_2BIT_FMT(MOV_FMT, FMT_SDPS_D):
11477 mips32_op = OPC_MOV_D;
11478 goto do_unaryfp;
11479 case FLOAT_2BIT_FMT(MOV_FMT, FMT_SDPS_PS):
11480 mips32_op = OPC_MOV_PS;
11481 goto do_unaryfp;
11482
11483 /* Absolute value */
11484 case FLOAT_2BIT_FMT(ABS_FMT, FMT_SDPS_S):
11485 mips32_op = OPC_ABS_S;
11486 goto do_unaryfp;
11487 case FLOAT_2BIT_FMT(ABS_FMT, FMT_SDPS_D):
11488 mips32_op = OPC_ABS_D;
11489 goto do_unaryfp;
11490 case FLOAT_2BIT_FMT(ABS_FMT, FMT_SDPS_PS):
11491 mips32_op = OPC_ABS_PS;
11492 goto do_unaryfp;
11493
11494 /* Negation */
11495 case FLOAT_2BIT_FMT(NEG_FMT, FMT_SDPS_S):
11496 mips32_op = OPC_NEG_S;
11497 goto do_unaryfp;
11498 case FLOAT_2BIT_FMT(NEG_FMT, FMT_SDPS_D):
11499 mips32_op = OPC_NEG_D;
11500 goto do_unaryfp;
11501 case FLOAT_2BIT_FMT(NEG_FMT, FMT_SDPS_PS):
11502 mips32_op = OPC_NEG_PS;
11503 goto do_unaryfp;
11504
11505 /* Reciprocal square root step */
11506 case FLOAT_2BIT_FMT(RSQRT1_FMT, FMT_SDPS_S):
11507 mips32_op = OPC_RSQRT1_S;
11508 goto do_unaryfp;
11509 case FLOAT_2BIT_FMT(RSQRT1_FMT, FMT_SDPS_D):
11510 mips32_op = OPC_RSQRT1_D;
11511 goto do_unaryfp;
11512 case FLOAT_2BIT_FMT(RSQRT1_FMT, FMT_SDPS_PS):
11513 mips32_op = OPC_RSQRT1_PS;
11514 goto do_unaryfp;
11515
11516 /* Reciprocal step */
11517 case FLOAT_2BIT_FMT(RECIP1_FMT, FMT_SDPS_S):
11518 mips32_op = OPC_RECIP1_S;
11519 goto do_unaryfp;
11520 case FLOAT_2BIT_FMT(RECIP1_FMT, FMT_SDPS_D):
11521 mips32_op = OPC_RECIP1_S;
11522 goto do_unaryfp;
11523 case FLOAT_2BIT_FMT(RECIP1_FMT, FMT_SDPS_PS):
11524 mips32_op = OPC_RECIP1_PS;
11525 goto do_unaryfp;
11526
11527 /* Conversions from double */
11528 case FLOAT_2BIT_FMT(CVT_D, FMT_SWL_S):
11529 mips32_op = OPC_CVT_D_S;
11530 goto do_unaryfp;
11531 case FLOAT_2BIT_FMT(CVT_D, FMT_SWL_W):
11532 mips32_op = OPC_CVT_D_W;
11533 goto do_unaryfp;
11534 case FLOAT_2BIT_FMT(CVT_D, FMT_SWL_L):
11535 mips32_op = OPC_CVT_D_L;
11536 goto do_unaryfp;
11537
11538 /* Conversions from single */
11539 case FLOAT_2BIT_FMT(CVT_S, FMT_DWL_D):
11540 mips32_op = OPC_CVT_S_D;
11541 goto do_unaryfp;
11542 case FLOAT_2BIT_FMT(CVT_S, FMT_DWL_W):
11543 mips32_op = OPC_CVT_S_W;
11544 goto do_unaryfp;
11545 case FLOAT_2BIT_FMT(CVT_S, FMT_DWL_L):
11546 mips32_op = OPC_CVT_S_L;
11547 do_unaryfp:
11548 gen_farith(ctx, mips32_op, -1, rs, rt, 0);
11549 break;
11550
11551 /* Conditional moves on floating-point codes */
11552 case COND_FLOAT_MOV(MOVT, 0):
11553 case COND_FLOAT_MOV(MOVT, 1):
11554 case COND_FLOAT_MOV(MOVT, 2):
11555 case COND_FLOAT_MOV(MOVT, 3):
11556 case COND_FLOAT_MOV(MOVT, 4):
11557 case COND_FLOAT_MOV(MOVT, 5):
11558 case COND_FLOAT_MOV(MOVT, 6):
11559 case COND_FLOAT_MOV(MOVT, 7):
11560 gen_movci(ctx, rt, rs, (ctx->opcode >> 13) & 0x7, 1);
11561 break;
11562 case COND_FLOAT_MOV(MOVF, 0):
11563 case COND_FLOAT_MOV(MOVF, 1):
11564 case COND_FLOAT_MOV(MOVF, 2):
11565 case COND_FLOAT_MOV(MOVF, 3):
11566 case COND_FLOAT_MOV(MOVF, 4):
11567 case COND_FLOAT_MOV(MOVF, 5):
11568 case COND_FLOAT_MOV(MOVF, 6):
11569 case COND_FLOAT_MOV(MOVF, 7):
11570 gen_movci(ctx, rt, rs, (ctx->opcode >> 13) & 0x7, 0);
11571 break;
11572 default:
11573 MIPS_INVAL("pool32fxf");
11574 generate_exception(ctx, EXCP_RI);
11575 break;
11576 }
11577}
11578
Andreas Färber7db13fa2012-03-14 01:38:22 +010011579static void decode_micromips32_opc (CPUMIPSState *env, DisasContext *ctx,
Nathan Froyd3c824102010-06-08 13:29:59 -070011580 uint16_t insn_hw1, int *is_branch)
11581{
11582 int32_t offset;
11583 uint16_t insn;
11584 int rt, rs, rd, rr;
11585 int16_t imm;
11586 uint32_t op, minor, mips32_op;
11587 uint32_t cond, fmt, cc;
11588
Blue Swirl895c2d02012-09-02 14:52:59 +000011589 insn = cpu_lduw_code(env, ctx->pc + 2);
Nathan Froyd3c824102010-06-08 13:29:59 -070011590 ctx->opcode = (ctx->opcode << 16) | insn;
11591
11592 rt = (ctx->opcode >> 21) & 0x1f;
11593 rs = (ctx->opcode >> 16) & 0x1f;
11594 rd = (ctx->opcode >> 11) & 0x1f;
11595 rr = (ctx->opcode >> 6) & 0x1f;
11596 imm = (int16_t) ctx->opcode;
11597
11598 op = (ctx->opcode >> 26) & 0x3f;
11599 switch (op) {
11600 case POOL32A:
11601 minor = ctx->opcode & 0x3f;
11602 switch (minor) {
11603 case 0x00:
11604 minor = (ctx->opcode >> 6) & 0xf;
11605 switch (minor) {
11606 case SLL32:
11607 mips32_op = OPC_SLL;
11608 goto do_shifti;
11609 case SRA:
11610 mips32_op = OPC_SRA;
11611 goto do_shifti;
11612 case SRL32:
11613 mips32_op = OPC_SRL;
11614 goto do_shifti;
11615 case ROTR:
11616 mips32_op = OPC_ROTR;
11617 do_shifti:
Aurelien Jarnod75c1352013-01-01 18:02:22 +010011618 gen_shift_imm(ctx, mips32_op, rt, rs, rd);
Nathan Froyd3c824102010-06-08 13:29:59 -070011619 break;
11620 default:
11621 goto pool32a_invalid;
11622 }
11623 break;
11624 case 0x10:
11625 minor = (ctx->opcode >> 6) & 0xf;
11626 switch (minor) {
11627 /* Arithmetic */
11628 case ADD:
11629 mips32_op = OPC_ADD;
11630 goto do_arith;
11631 case ADDU32:
11632 mips32_op = OPC_ADDU;
11633 goto do_arith;
11634 case SUB:
11635 mips32_op = OPC_SUB;
11636 goto do_arith;
11637 case SUBU32:
11638 mips32_op = OPC_SUBU;
11639 goto do_arith;
11640 case MUL:
11641 mips32_op = OPC_MUL;
11642 do_arith:
Aurelien Jarnod75c1352013-01-01 18:02:22 +010011643 gen_arith(ctx, mips32_op, rd, rs, rt);
Nathan Froyd3c824102010-06-08 13:29:59 -070011644 break;
11645 /* Shifts */
11646 case SLLV:
11647 mips32_op = OPC_SLLV;
11648 goto do_shift;
11649 case SRLV:
11650 mips32_op = OPC_SRLV;
11651 goto do_shift;
11652 case SRAV:
11653 mips32_op = OPC_SRAV;
11654 goto do_shift;
11655 case ROTRV:
11656 mips32_op = OPC_ROTRV;
11657 do_shift:
Aurelien Jarnod75c1352013-01-01 18:02:22 +010011658 gen_shift(ctx, mips32_op, rd, rs, rt);
Nathan Froyd3c824102010-06-08 13:29:59 -070011659 break;
11660 /* Logical operations */
11661 case AND:
11662 mips32_op = OPC_AND;
11663 goto do_logic;
11664 case OR32:
11665 mips32_op = OPC_OR;
11666 goto do_logic;
11667 case NOR:
11668 mips32_op = OPC_NOR;
11669 goto do_logic;
11670 case XOR32:
11671 mips32_op = OPC_XOR;
11672 do_logic:
Aurelien Jarnod75c1352013-01-01 18:02:22 +010011673 gen_logic(ctx, mips32_op, rd, rs, rt);
Nathan Froyd3c824102010-06-08 13:29:59 -070011674 break;
11675 /* Set less than */
11676 case SLT:
11677 mips32_op = OPC_SLT;
11678 goto do_slt;
11679 case SLTU:
11680 mips32_op = OPC_SLTU;
11681 do_slt:
Aurelien Jarnod75c1352013-01-01 18:02:22 +010011682 gen_slt(ctx, mips32_op, rd, rs, rt);
Nathan Froyd3c824102010-06-08 13:29:59 -070011683 break;
11684 default:
11685 goto pool32a_invalid;
11686 }
11687 break;
11688 case 0x18:
11689 minor = (ctx->opcode >> 6) & 0xf;
11690 switch (minor) {
11691 /* Conditional moves */
11692 case MOVN:
11693 mips32_op = OPC_MOVN;
11694 goto do_cmov;
11695 case MOVZ:
11696 mips32_op = OPC_MOVZ;
11697 do_cmov:
Aurelien Jarnod75c1352013-01-01 18:02:22 +010011698 gen_cond_move(ctx, mips32_op, rd, rs, rt);
Nathan Froyd3c824102010-06-08 13:29:59 -070011699 break;
11700 case LWXS:
11701 gen_ldxs(ctx, rs, rt, rd);
11702 break;
11703 default:
11704 goto pool32a_invalid;
11705 }
11706 break;
11707 case INS:
11708 gen_bitops(ctx, OPC_INS, rt, rs, rr, rd);
11709 return;
11710 case EXT:
11711 gen_bitops(ctx, OPC_EXT, rt, rs, rr, rd);
11712 return;
11713 case POOL32AXF:
11714 gen_pool32axf(env, ctx, rt, rs, is_branch);
11715 break;
11716 case 0x07:
11717 generate_exception(ctx, EXCP_BREAK);
11718 break;
11719 default:
11720 pool32a_invalid:
11721 MIPS_INVAL("pool32a");
11722 generate_exception(ctx, EXCP_RI);
11723 break;
11724 }
11725 break;
11726 case POOL32B:
11727 minor = (ctx->opcode >> 12) & 0xf;
11728 switch (minor) {
11729 case CACHE:
Eric Johnson2e154972011-09-17 17:05:32 -070011730 check_cp0_enabled(ctx);
Nathan Froyd3c824102010-06-08 13:29:59 -070011731 /* Treat as no-op. */
11732 break;
11733 case LWC2:
11734 case SWC2:
11735 /* COP2: Not implemented. */
11736 generate_exception_err(ctx, EXCP_CpU, 2);
11737 break;
11738 case LWP:
11739 case SWP:
11740#ifdef TARGET_MIPS64
11741 case LDP:
11742 case SDP:
11743#endif
11744 gen_ldst_pair(ctx, minor, rt, rs, SIMM(ctx->opcode, 0, 12));
11745 break;
11746 case LWM32:
11747 case SWM32:
11748#ifdef TARGET_MIPS64
11749 case LDM:
11750 case SDM:
11751#endif
11752 gen_ldst_multiple(ctx, minor, rt, rs, SIMM(ctx->opcode, 0, 12));
11753 break;
11754 default:
11755 MIPS_INVAL("pool32b");
11756 generate_exception(ctx, EXCP_RI);
11757 break;
11758 }
11759 break;
11760 case POOL32F:
11761 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
11762 minor = ctx->opcode & 0x3f;
11763 check_cp1_enabled(ctx);
11764 switch (minor) {
11765 case ALNV_PS:
11766 mips32_op = OPC_ALNV_PS;
11767 goto do_madd;
11768 case MADD_S:
11769 mips32_op = OPC_MADD_S;
11770 goto do_madd;
11771 case MADD_D:
11772 mips32_op = OPC_MADD_D;
11773 goto do_madd;
11774 case MADD_PS:
11775 mips32_op = OPC_MADD_PS;
11776 goto do_madd;
11777 case MSUB_S:
11778 mips32_op = OPC_MSUB_S;
11779 goto do_madd;
11780 case MSUB_D:
11781 mips32_op = OPC_MSUB_D;
11782 goto do_madd;
11783 case MSUB_PS:
11784 mips32_op = OPC_MSUB_PS;
11785 goto do_madd;
11786 case NMADD_S:
11787 mips32_op = OPC_NMADD_S;
11788 goto do_madd;
11789 case NMADD_D:
11790 mips32_op = OPC_NMADD_D;
11791 goto do_madd;
11792 case NMADD_PS:
11793 mips32_op = OPC_NMADD_PS;
11794 goto do_madd;
11795 case NMSUB_S:
11796 mips32_op = OPC_NMSUB_S;
11797 goto do_madd;
11798 case NMSUB_D:
11799 mips32_op = OPC_NMSUB_D;
11800 goto do_madd;
11801 case NMSUB_PS:
11802 mips32_op = OPC_NMSUB_PS;
11803 do_madd:
11804 gen_flt3_arith(ctx, mips32_op, rd, rr, rs, rt);
11805 break;
11806 case CABS_COND_FMT:
11807 cond = (ctx->opcode >> 6) & 0xf;
11808 cc = (ctx->opcode >> 13) & 0x7;
11809 fmt = (ctx->opcode >> 10) & 0x3;
11810 switch (fmt) {
11811 case 0x0:
11812 gen_cmpabs_s(ctx, cond, rt, rs, cc);
11813 break;
11814 case 0x1:
11815 gen_cmpabs_d(ctx, cond, rt, rs, cc);
11816 break;
11817 case 0x2:
11818 gen_cmpabs_ps(ctx, cond, rt, rs, cc);
11819 break;
11820 default:
11821 goto pool32f_invalid;
11822 }
11823 break;
11824 case C_COND_FMT:
11825 cond = (ctx->opcode >> 6) & 0xf;
11826 cc = (ctx->opcode >> 13) & 0x7;
11827 fmt = (ctx->opcode >> 10) & 0x3;
11828 switch (fmt) {
11829 case 0x0:
11830 gen_cmp_s(ctx, cond, rt, rs, cc);
11831 break;
11832 case 0x1:
11833 gen_cmp_d(ctx, cond, rt, rs, cc);
11834 break;
11835 case 0x2:
11836 gen_cmp_ps(ctx, cond, rt, rs, cc);
11837 break;
11838 default:
11839 goto pool32f_invalid;
11840 }
11841 break;
11842 case POOL32FXF:
Aurelien Jarnod75c1352013-01-01 18:02:22 +010011843 gen_pool32fxf(ctx, rt, rs);
Nathan Froyd3c824102010-06-08 13:29:59 -070011844 break;
11845 case 0x00:
11846 /* PLL foo */
11847 switch ((ctx->opcode >> 6) & 0x7) {
11848 case PLL_PS:
11849 mips32_op = OPC_PLL_PS;
11850 goto do_ps;
11851 case PLU_PS:
11852 mips32_op = OPC_PLU_PS;
11853 goto do_ps;
11854 case PUL_PS:
11855 mips32_op = OPC_PUL_PS;
11856 goto do_ps;
11857 case PUU_PS:
11858 mips32_op = OPC_PUU_PS;
11859 goto do_ps;
11860 case CVT_PS_S:
11861 mips32_op = OPC_CVT_PS_S;
11862 do_ps:
11863 gen_farith(ctx, mips32_op, rt, rs, rd, 0);
11864 break;
11865 default:
11866 goto pool32f_invalid;
11867 }
11868 break;
11869 case 0x08:
11870 /* [LS][WDU]XC1 */
11871 switch ((ctx->opcode >> 6) & 0x7) {
11872 case LWXC1:
11873 mips32_op = OPC_LWXC1;
11874 goto do_ldst_cp1;
11875 case SWXC1:
11876 mips32_op = OPC_SWXC1;
11877 goto do_ldst_cp1;
11878 case LDXC1:
11879 mips32_op = OPC_LDXC1;
11880 goto do_ldst_cp1;
11881 case SDXC1:
11882 mips32_op = OPC_SDXC1;
11883 goto do_ldst_cp1;
11884 case LUXC1:
11885 mips32_op = OPC_LUXC1;
11886 goto do_ldst_cp1;
11887 case SUXC1:
11888 mips32_op = OPC_SUXC1;
11889 do_ldst_cp1:
11890 gen_flt3_ldst(ctx, mips32_op, rd, rd, rt, rs);
11891 break;
11892 default:
11893 goto pool32f_invalid;
11894 }
11895 break;
11896 case 0x18:
11897 /* 3D insns */
11898 fmt = (ctx->opcode >> 9) & 0x3;
11899 switch ((ctx->opcode >> 6) & 0x7) {
11900 case RSQRT2_FMT:
11901 switch (fmt) {
11902 case FMT_SDPS_S:
11903 mips32_op = OPC_RSQRT2_S;
11904 goto do_3d;
11905 case FMT_SDPS_D:
11906 mips32_op = OPC_RSQRT2_D;
11907 goto do_3d;
11908 case FMT_SDPS_PS:
11909 mips32_op = OPC_RSQRT2_PS;
11910 goto do_3d;
11911 default:
11912 goto pool32f_invalid;
11913 }
11914 break;
11915 case RECIP2_FMT:
11916 switch (fmt) {
11917 case FMT_SDPS_S:
11918 mips32_op = OPC_RECIP2_S;
11919 goto do_3d;
11920 case FMT_SDPS_D:
11921 mips32_op = OPC_RECIP2_D;
11922 goto do_3d;
11923 case FMT_SDPS_PS:
11924 mips32_op = OPC_RECIP2_PS;
11925 goto do_3d;
11926 default:
11927 goto pool32f_invalid;
11928 }
11929 break;
11930 case ADDR_PS:
11931 mips32_op = OPC_ADDR_PS;
11932 goto do_3d;
11933 case MULR_PS:
11934 mips32_op = OPC_MULR_PS;
11935 do_3d:
11936 gen_farith(ctx, mips32_op, rt, rs, rd, 0);
11937 break;
11938 default:
11939 goto pool32f_invalid;
11940 }
11941 break;
11942 case 0x20:
11943 /* MOV[FT].fmt and PREFX */
11944 cc = (ctx->opcode >> 13) & 0x7;
11945 fmt = (ctx->opcode >> 9) & 0x3;
11946 switch ((ctx->opcode >> 6) & 0x7) {
11947 case MOVF_FMT:
11948 switch (fmt) {
11949 case FMT_SDPS_S:
11950 gen_movcf_s(rs, rt, cc, 0);
11951 break;
11952 case FMT_SDPS_D:
11953 gen_movcf_d(ctx, rs, rt, cc, 0);
11954 break;
11955 case FMT_SDPS_PS:
11956 gen_movcf_ps(rs, rt, cc, 0);
11957 break;
11958 default:
11959 goto pool32f_invalid;
11960 }
11961 break;
11962 case MOVT_FMT:
11963 switch (fmt) {
11964 case FMT_SDPS_S:
11965 gen_movcf_s(rs, rt, cc, 1);
11966 break;
11967 case FMT_SDPS_D:
11968 gen_movcf_d(ctx, rs, rt, cc, 1);
11969 break;
11970 case FMT_SDPS_PS:
11971 gen_movcf_ps(rs, rt, cc, 1);
11972 break;
11973 default:
11974 goto pool32f_invalid;
11975 }
11976 break;
11977 case PREFX:
11978 break;
11979 default:
11980 goto pool32f_invalid;
11981 }
11982 break;
11983#define FINSN_3ARG_SDPS(prfx) \
11984 switch ((ctx->opcode >> 8) & 0x3) { \
11985 case FMT_SDPS_S: \
11986 mips32_op = OPC_##prfx##_S; \
11987 goto do_fpop; \
11988 case FMT_SDPS_D: \
11989 mips32_op = OPC_##prfx##_D; \
11990 goto do_fpop; \
11991 case FMT_SDPS_PS: \
11992 mips32_op = OPC_##prfx##_PS; \
11993 goto do_fpop; \
11994 default: \
11995 goto pool32f_invalid; \
11996 }
11997 case 0x30:
11998 /* regular FP ops */
11999 switch ((ctx->opcode >> 6) & 0x3) {
12000 case ADD_FMT:
12001 FINSN_3ARG_SDPS(ADD);
12002 break;
12003 case SUB_FMT:
12004 FINSN_3ARG_SDPS(SUB);
12005 break;
12006 case MUL_FMT:
12007 FINSN_3ARG_SDPS(MUL);
12008 break;
12009 case DIV_FMT:
12010 fmt = (ctx->opcode >> 8) & 0x3;
12011 if (fmt == 1) {
12012 mips32_op = OPC_DIV_D;
12013 } else if (fmt == 0) {
12014 mips32_op = OPC_DIV_S;
12015 } else {
12016 goto pool32f_invalid;
12017 }
12018 goto do_fpop;
12019 default:
12020 goto pool32f_invalid;
12021 }
12022 break;
12023 case 0x38:
12024 /* cmovs */
12025 switch ((ctx->opcode >> 6) & 0x3) {
12026 case MOVN_FMT:
12027 FINSN_3ARG_SDPS(MOVN);
12028 break;
12029 case MOVZ_FMT:
12030 FINSN_3ARG_SDPS(MOVZ);
12031 break;
12032 default:
12033 goto pool32f_invalid;
12034 }
12035 break;
12036 do_fpop:
12037 gen_farith(ctx, mips32_op, rt, rs, rd, 0);
12038 break;
12039 default:
12040 pool32f_invalid:
12041 MIPS_INVAL("pool32f");
12042 generate_exception(ctx, EXCP_RI);
12043 break;
12044 }
12045 } else {
12046 generate_exception_err(ctx, EXCP_CpU, 1);
12047 }
12048 break;
12049 case POOL32I:
12050 minor = (ctx->opcode >> 21) & 0x1f;
12051 switch (minor) {
12052 case BLTZ:
12053 mips32_op = OPC_BLTZ;
12054 goto do_branch;
12055 case BLTZAL:
12056 mips32_op = OPC_BLTZAL;
12057 goto do_branch;
12058 case BLTZALS:
12059 mips32_op = OPC_BLTZALS;
12060 goto do_branch;
12061 case BGEZ:
12062 mips32_op = OPC_BGEZ;
12063 goto do_branch;
12064 case BGEZAL:
12065 mips32_op = OPC_BGEZAL;
12066 goto do_branch;
12067 case BGEZALS:
12068 mips32_op = OPC_BGEZALS;
12069 goto do_branch;
12070 case BLEZ:
12071 mips32_op = OPC_BLEZ;
12072 goto do_branch;
12073 case BGTZ:
12074 mips32_op = OPC_BGTZ;
12075 do_branch:
12076 gen_compute_branch(ctx, mips32_op, 4, rs, -1, imm << 1);
12077 *is_branch = 1;
12078 break;
12079
12080 /* Traps */
12081 case TLTI:
12082 mips32_op = OPC_TLTI;
12083 goto do_trapi;
12084 case TGEI:
12085 mips32_op = OPC_TGEI;
12086 goto do_trapi;
12087 case TLTIU:
12088 mips32_op = OPC_TLTIU;
12089 goto do_trapi;
12090 case TGEIU:
12091 mips32_op = OPC_TGEIU;
12092 goto do_trapi;
12093 case TNEI:
12094 mips32_op = OPC_TNEI;
12095 goto do_trapi;
12096 case TEQI:
12097 mips32_op = OPC_TEQI;
12098 do_trapi:
12099 gen_trap(ctx, mips32_op, rs, -1, imm);
12100 break;
12101
12102 case BNEZC:
12103 case BEQZC:
12104 gen_compute_branch(ctx, minor == BNEZC ? OPC_BNE : OPC_BEQ,
12105 4, rs, 0, imm << 1);
12106 /* Compact branches don't have a delay slot, so just let
12107 the normal delay slot handling take us to the branch
12108 target. */
12109 break;
12110 case LUI:
Aurelien Jarnod75c1352013-01-01 18:02:22 +010012111 gen_logic_imm(ctx, OPC_LUI, rs, -1, imm);
Nathan Froyd3c824102010-06-08 13:29:59 -070012112 break;
12113 case SYNCI:
12114 break;
12115 case BC2F:
12116 case BC2T:
12117 /* COP2: Not implemented. */
12118 generate_exception_err(ctx, EXCP_CpU, 2);
12119 break;
12120 case BC1F:
12121 mips32_op = (ctx->opcode & (1 << 16)) ? OPC_BC1FANY2 : OPC_BC1F;
12122 goto do_cp1branch;
12123 case BC1T:
12124 mips32_op = (ctx->opcode & (1 << 16)) ? OPC_BC1TANY2 : OPC_BC1T;
12125 goto do_cp1branch;
12126 case BC1ANY4F:
12127 mips32_op = OPC_BC1FANY4;
12128 goto do_cp1mips3d;
12129 case BC1ANY4T:
12130 mips32_op = OPC_BC1TANY4;
12131 do_cp1mips3d:
12132 check_cop1x(ctx);
Aurelien Jarnod75c1352013-01-01 18:02:22 +010012133 check_insn(ctx, ASE_MIPS3D);
Nathan Froyd3c824102010-06-08 13:29:59 -070012134 /* Fall through */
12135 do_cp1branch:
Aurelien Jarnod75c1352013-01-01 18:02:22 +010012136 gen_compute_branch1(ctx, mips32_op,
Nathan Froyd3c824102010-06-08 13:29:59 -070012137 (ctx->opcode >> 18) & 0x7, imm << 1);
12138 *is_branch = 1;
12139 break;
12140 case BPOSGE64:
12141 case BPOSGE32:
12142 /* MIPS DSP: not implemented */
12143 /* Fall through */
12144 default:
12145 MIPS_INVAL("pool32i");
12146 generate_exception(ctx, EXCP_RI);
12147 break;
12148 }
12149 break;
12150 case POOL32C:
12151 minor = (ctx->opcode >> 12) & 0xf;
12152 switch (minor) {
12153 case LWL:
12154 mips32_op = OPC_LWL;
Aurelien Jarno5c13fdf2010-07-01 07:47:00 +020012155 goto do_ld_lr;
Nathan Froyd3c824102010-06-08 13:29:59 -070012156 case SWL:
12157 mips32_op = OPC_SWL;
Aurelien Jarno5c13fdf2010-07-01 07:47:00 +020012158 goto do_st_lr;
Nathan Froyd3c824102010-06-08 13:29:59 -070012159 case LWR:
12160 mips32_op = OPC_LWR;
Aurelien Jarno5c13fdf2010-07-01 07:47:00 +020012161 goto do_ld_lr;
Nathan Froyd3c824102010-06-08 13:29:59 -070012162 case SWR:
12163 mips32_op = OPC_SWR;
Aurelien Jarno5c13fdf2010-07-01 07:47:00 +020012164 goto do_st_lr;
Nathan Froyd3c824102010-06-08 13:29:59 -070012165#if defined(TARGET_MIPS64)
12166 case LDL:
12167 mips32_op = OPC_LDL;
Aurelien Jarno5c13fdf2010-07-01 07:47:00 +020012168 goto do_ld_lr;
Nathan Froyd3c824102010-06-08 13:29:59 -070012169 case SDL:
12170 mips32_op = OPC_SDL;
Aurelien Jarno5c13fdf2010-07-01 07:47:00 +020012171 goto do_st_lr;
Nathan Froyd3c824102010-06-08 13:29:59 -070012172 case LDR:
12173 mips32_op = OPC_LDR;
Aurelien Jarno5c13fdf2010-07-01 07:47:00 +020012174 goto do_ld_lr;
Nathan Froyd3c824102010-06-08 13:29:59 -070012175 case SDR:
12176 mips32_op = OPC_SDR;
Aurelien Jarno5c13fdf2010-07-01 07:47:00 +020012177 goto do_st_lr;
Nathan Froyd3c824102010-06-08 13:29:59 -070012178 case LWU:
12179 mips32_op = OPC_LWU;
Aurelien Jarno5c13fdf2010-07-01 07:47:00 +020012180 goto do_ld_lr;
Nathan Froyd3c824102010-06-08 13:29:59 -070012181 case LLD:
12182 mips32_op = OPC_LLD;
Aurelien Jarno5c13fdf2010-07-01 07:47:00 +020012183 goto do_ld_lr;
Nathan Froyd3c824102010-06-08 13:29:59 -070012184#endif
12185 case LL:
12186 mips32_op = OPC_LL;
Aurelien Jarno5c13fdf2010-07-01 07:47:00 +020012187 goto do_ld_lr;
12188 do_ld_lr:
Aurelien Jarnod75c1352013-01-01 18:02:22 +010012189 gen_ld(ctx, mips32_op, rt, rs, SIMM(ctx->opcode, 0, 12));
Aurelien Jarno5c13fdf2010-07-01 07:47:00 +020012190 break;
12191 do_st_lr:
12192 gen_st(ctx, mips32_op, rt, rs, SIMM(ctx->opcode, 0, 12));
Nathan Froyd3c824102010-06-08 13:29:59 -070012193 break;
12194 case SC:
12195 gen_st_cond(ctx, OPC_SC, rt, rs, SIMM(ctx->opcode, 0, 12));
12196 break;
12197#if defined(TARGET_MIPS64)
12198 case SCD:
12199 gen_st_cond(ctx, OPC_SCD, rt, rs, SIMM(ctx->opcode, 0, 12));
12200 break;
12201#endif
12202 case PREF:
12203 /* Treat as no-op */
12204 break;
12205 default:
12206 MIPS_INVAL("pool32c");
12207 generate_exception(ctx, EXCP_RI);
12208 break;
12209 }
12210 break;
12211 case ADDI32:
12212 mips32_op = OPC_ADDI;
12213 goto do_addi;
12214 case ADDIU32:
12215 mips32_op = OPC_ADDIU;
12216 do_addi:
Aurelien Jarnod75c1352013-01-01 18:02:22 +010012217 gen_arith_imm(ctx, mips32_op, rt, rs, imm);
Nathan Froyd3c824102010-06-08 13:29:59 -070012218 break;
12219
12220 /* Logical operations */
12221 case ORI32:
12222 mips32_op = OPC_ORI;
12223 goto do_logici;
12224 case XORI32:
12225 mips32_op = OPC_XORI;
12226 goto do_logici;
12227 case ANDI32:
12228 mips32_op = OPC_ANDI;
12229 do_logici:
Aurelien Jarnod75c1352013-01-01 18:02:22 +010012230 gen_logic_imm(ctx, mips32_op, rt, rs, imm);
Nathan Froyd3c824102010-06-08 13:29:59 -070012231 break;
12232
12233 /* Set less than immediate */
12234 case SLTI32:
12235 mips32_op = OPC_SLTI;
12236 goto do_slti;
12237 case SLTIU32:
12238 mips32_op = OPC_SLTIU;
12239 do_slti:
Aurelien Jarnod75c1352013-01-01 18:02:22 +010012240 gen_slt_imm(ctx, mips32_op, rt, rs, imm);
Nathan Froyd3c824102010-06-08 13:29:59 -070012241 break;
12242 case JALX32:
12243 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2;
12244 gen_compute_branch(ctx, OPC_JALX, 4, rt, rs, offset);
12245 *is_branch = 1;
12246 break;
12247 case JALS32:
12248 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 1;
12249 gen_compute_branch(ctx, OPC_JALS, 4, rt, rs, offset);
12250 *is_branch = 1;
12251 break;
12252 case BEQ32:
12253 gen_compute_branch(ctx, OPC_BEQ, 4, rt, rs, imm << 1);
12254 *is_branch = 1;
12255 break;
12256 case BNE32:
12257 gen_compute_branch(ctx, OPC_BNE, 4, rt, rs, imm << 1);
12258 *is_branch = 1;
12259 break;
12260 case J32:
12261 gen_compute_branch(ctx, OPC_J, 4, rt, rs,
12262 (int32_t)(ctx->opcode & 0x3FFFFFF) << 1);
12263 *is_branch = 1;
12264 break;
12265 case JAL32:
12266 gen_compute_branch(ctx, OPC_JAL, 4, rt, rs,
12267 (int32_t)(ctx->opcode & 0x3FFFFFF) << 1);
12268 *is_branch = 1;
12269 break;
12270 /* Floating point (COP1) */
12271 case LWC132:
12272 mips32_op = OPC_LWC1;
12273 goto do_cop1;
12274 case LDC132:
12275 mips32_op = OPC_LDC1;
12276 goto do_cop1;
12277 case SWC132:
12278 mips32_op = OPC_SWC1;
12279 goto do_cop1;
12280 case SDC132:
12281 mips32_op = OPC_SDC1;
12282 do_cop1:
12283 gen_cop1_ldst(env, ctx, mips32_op, rt, rs, imm);
12284 break;
12285 case ADDIUPC:
12286 {
12287 int reg = mmreg(ZIMM(ctx->opcode, 23, 3));
12288 int offset = SIMM(ctx->opcode, 0, 23) << 2;
12289
12290 gen_addiupc(ctx, reg, offset, 0, 0);
12291 }
12292 break;
12293 /* Loads and stores */
12294 case LB32:
12295 mips32_op = OPC_LB;
Aurelien Jarno5c13fdf2010-07-01 07:47:00 +020012296 goto do_ld;
Nathan Froyd3c824102010-06-08 13:29:59 -070012297 case LBU32:
12298 mips32_op = OPC_LBU;
Aurelien Jarno5c13fdf2010-07-01 07:47:00 +020012299 goto do_ld;
Nathan Froyd3c824102010-06-08 13:29:59 -070012300 case LH32:
12301 mips32_op = OPC_LH;
Aurelien Jarno5c13fdf2010-07-01 07:47:00 +020012302 goto do_ld;
Nathan Froyd3c824102010-06-08 13:29:59 -070012303 case LHU32:
12304 mips32_op = OPC_LHU;
Aurelien Jarno5c13fdf2010-07-01 07:47:00 +020012305 goto do_ld;
Nathan Froyd3c824102010-06-08 13:29:59 -070012306 case LW32:
12307 mips32_op = OPC_LW;
Aurelien Jarno5c13fdf2010-07-01 07:47:00 +020012308 goto do_ld;
Nathan Froyd3c824102010-06-08 13:29:59 -070012309#ifdef TARGET_MIPS64
12310 case LD32:
12311 mips32_op = OPC_LD;
Aurelien Jarno5c13fdf2010-07-01 07:47:00 +020012312 goto do_ld;
Nathan Froyd3c824102010-06-08 13:29:59 -070012313 case SD32:
12314 mips32_op = OPC_SD;
Aurelien Jarno5c13fdf2010-07-01 07:47:00 +020012315 goto do_st;
Nathan Froyd3c824102010-06-08 13:29:59 -070012316#endif
12317 case SB32:
12318 mips32_op = OPC_SB;
Aurelien Jarno5c13fdf2010-07-01 07:47:00 +020012319 goto do_st;
Nathan Froyd3c824102010-06-08 13:29:59 -070012320 case SH32:
12321 mips32_op = OPC_SH;
Aurelien Jarno5c13fdf2010-07-01 07:47:00 +020012322 goto do_st;
Nathan Froyd3c824102010-06-08 13:29:59 -070012323 case SW32:
12324 mips32_op = OPC_SW;
Aurelien Jarno5c13fdf2010-07-01 07:47:00 +020012325 goto do_st;
12326 do_ld:
Aurelien Jarnod75c1352013-01-01 18:02:22 +010012327 gen_ld(ctx, mips32_op, rt, rs, imm);
Aurelien Jarno5c13fdf2010-07-01 07:47:00 +020012328 break;
12329 do_st:
12330 gen_st(ctx, mips32_op, rt, rs, imm);
Nathan Froyd3c824102010-06-08 13:29:59 -070012331 break;
12332 default:
12333 generate_exception(ctx, EXCP_RI);
12334 break;
12335 }
12336}
12337
Andreas Färber7db13fa2012-03-14 01:38:22 +010012338static int decode_micromips_opc (CPUMIPSState *env, DisasContext *ctx, int *is_branch)
Nathan Froyd3c824102010-06-08 13:29:59 -070012339{
12340 uint32_t op;
12341
12342 /* make sure instructions are on a halfword boundary */
12343 if (ctx->pc & 0x1) {
12344 env->CP0_BadVAddr = ctx->pc;
12345 generate_exception(ctx, EXCP_AdEL);
12346 ctx->bstate = BS_STOP;
12347 return 2;
12348 }
12349
12350 op = (ctx->opcode >> 10) & 0x3f;
12351 /* Enforce properly-sized instructions in a delay slot */
12352 if (ctx->hflags & MIPS_HFLAG_BMASK) {
12353 int bits = ctx->hflags & MIPS_HFLAG_BMASK_EXT;
12354
12355 switch (op) {
12356 case POOL32A:
12357 case POOL32B:
12358 case POOL32I:
12359 case POOL32C:
12360 case ADDI32:
12361 case ADDIU32:
12362 case ORI32:
12363 case XORI32:
12364 case SLTI32:
12365 case SLTIU32:
12366 case ANDI32:
12367 case JALX32:
12368 case LBU32:
12369 case LHU32:
12370 case POOL32F:
12371 case JALS32:
12372 case BEQ32:
12373 case BNE32:
12374 case J32:
12375 case JAL32:
12376 case SB32:
12377 case SH32:
12378 case POOL32S:
12379 case ADDIUPC:
12380 case SWC132:
12381 case SDC132:
12382 case SD32:
12383 case SW32:
12384 case LB32:
12385 case LH32:
12386 case DADDIU32:
Nathan Froyd3c824102010-06-08 13:29:59 -070012387 case LWC132:
12388 case LDC132:
12389 case LD32:
12390 case LW32:
12391 if (bits & MIPS_HFLAG_BDS16) {
12392 generate_exception(ctx, EXCP_RI);
12393 /* Just stop translation; the user is confused. */
12394 ctx->bstate = BS_STOP;
12395 return 2;
12396 }
12397 break;
12398 case POOL16A:
12399 case POOL16B:
12400 case POOL16C:
12401 case LWGP16:
12402 case POOL16F:
12403 case LBU16:
12404 case LHU16:
12405 case LWSP16:
12406 case LW16:
12407 case SB16:
12408 case SH16:
12409 case SWSP16:
12410 case SW16:
12411 case MOVE16:
12412 case ANDI16:
12413 case POOL16D:
12414 case POOL16E:
12415 case BEQZ16:
12416 case BNEZ16:
12417 case B16:
12418 case LI16:
12419 if (bits & MIPS_HFLAG_BDS32) {
12420 generate_exception(ctx, EXCP_RI);
12421 /* Just stop translation; the user is confused. */
12422 ctx->bstate = BS_STOP;
12423 return 2;
12424 }
12425 break;
12426 default:
12427 break;
12428 }
12429 }
12430 switch (op) {
12431 case POOL16A:
12432 {
12433 int rd = mmreg(uMIPS_RD(ctx->opcode));
12434 int rs1 = mmreg(uMIPS_RS1(ctx->opcode));
12435 int rs2 = mmreg(uMIPS_RS2(ctx->opcode));
12436 uint32_t opc = 0;
12437
12438 switch (ctx->opcode & 0x1) {
12439 case ADDU16:
12440 opc = OPC_ADDU;
12441 break;
12442 case SUBU16:
12443 opc = OPC_SUBU;
12444 break;
12445 }
12446
Aurelien Jarnod75c1352013-01-01 18:02:22 +010012447 gen_arith(ctx, opc, rd, rs1, rs2);
Nathan Froyd3c824102010-06-08 13:29:59 -070012448 }
12449 break;
12450 case POOL16B:
12451 {
12452 int rd = mmreg(uMIPS_RD(ctx->opcode));
12453 int rs = mmreg(uMIPS_RS(ctx->opcode));
12454 int amount = (ctx->opcode >> 1) & 0x7;
12455 uint32_t opc = 0;
12456 amount = amount == 0 ? 8 : amount;
12457
12458 switch (ctx->opcode & 0x1) {
12459 case SLL16:
12460 opc = OPC_SLL;
12461 break;
12462 case SRL16:
12463 opc = OPC_SRL;
12464 break;
12465 }
12466
Aurelien Jarnod75c1352013-01-01 18:02:22 +010012467 gen_shift_imm(ctx, opc, rd, rs, amount);
Nathan Froyd3c824102010-06-08 13:29:59 -070012468 }
12469 break;
12470 case POOL16C:
Aurelien Jarnod75c1352013-01-01 18:02:22 +010012471 gen_pool16c_insn(ctx, is_branch);
Nathan Froyd3c824102010-06-08 13:29:59 -070012472 break;
12473 case LWGP16:
12474 {
12475 int rd = mmreg(uMIPS_RD(ctx->opcode));
12476 int rb = 28; /* GP */
12477 int16_t offset = SIMM(ctx->opcode, 0, 7) << 2;
12478
Aurelien Jarnod75c1352013-01-01 18:02:22 +010012479 gen_ld(ctx, OPC_LW, rd, rb, offset);
Nathan Froyd3c824102010-06-08 13:29:59 -070012480 }
12481 break;
12482 case POOL16F:
12483 if (ctx->opcode & 1) {
12484 generate_exception(ctx, EXCP_RI);
12485 } else {
12486 /* MOVEP */
12487 int enc_dest = uMIPS_RD(ctx->opcode);
12488 int enc_rt = uMIPS_RS2(ctx->opcode);
12489 int enc_rs = uMIPS_RS1(ctx->opcode);
12490 int rd, rs, re, rt;
12491 static const int rd_enc[] = { 5, 5, 6, 4, 4, 4, 4, 4 };
12492 static const int re_enc[] = { 6, 7, 7, 21, 22, 5, 6, 7 };
12493 static const int rs_rt_enc[] = { 0, 17, 2, 3, 16, 18, 19, 20 };
12494
12495 rd = rd_enc[enc_dest];
12496 re = re_enc[enc_dest];
12497 rs = rs_rt_enc[enc_rs];
12498 rt = rs_rt_enc[enc_rt];
12499
Aurelien Jarnod75c1352013-01-01 18:02:22 +010012500 gen_arith_imm(ctx, OPC_ADDIU, rd, rs, 0);
12501 gen_arith_imm(ctx, OPC_ADDIU, re, rt, 0);
Nathan Froyd3c824102010-06-08 13:29:59 -070012502 }
12503 break;
12504 case LBU16:
12505 {
12506 int rd = mmreg(uMIPS_RD(ctx->opcode));
12507 int rb = mmreg(uMIPS_RS(ctx->opcode));
12508 int16_t offset = ZIMM(ctx->opcode, 0, 4);
12509 offset = (offset == 0xf ? -1 : offset);
12510
Aurelien Jarnod75c1352013-01-01 18:02:22 +010012511 gen_ld(ctx, OPC_LBU, rd, rb, offset);
Nathan Froyd3c824102010-06-08 13:29:59 -070012512 }
12513 break;
12514 case LHU16:
12515 {
12516 int rd = mmreg(uMIPS_RD(ctx->opcode));
12517 int rb = mmreg(uMIPS_RS(ctx->opcode));
12518 int16_t offset = ZIMM(ctx->opcode, 0, 4) << 1;
12519
Aurelien Jarnod75c1352013-01-01 18:02:22 +010012520 gen_ld(ctx, OPC_LHU, rd, rb, offset);
Nathan Froyd3c824102010-06-08 13:29:59 -070012521 }
12522 break;
12523 case LWSP16:
12524 {
12525 int rd = (ctx->opcode >> 5) & 0x1f;
12526 int rb = 29; /* SP */
12527 int16_t offset = ZIMM(ctx->opcode, 0, 5) << 2;
12528
Aurelien Jarnod75c1352013-01-01 18:02:22 +010012529 gen_ld(ctx, OPC_LW, rd, rb, offset);
Nathan Froyd3c824102010-06-08 13:29:59 -070012530 }
12531 break;
12532 case LW16:
12533 {
12534 int rd = mmreg(uMIPS_RD(ctx->opcode));
12535 int rb = mmreg(uMIPS_RS(ctx->opcode));
12536 int16_t offset = ZIMM(ctx->opcode, 0, 4) << 2;
12537
Aurelien Jarnod75c1352013-01-01 18:02:22 +010012538 gen_ld(ctx, OPC_LW, rd, rb, offset);
Nathan Froyd3c824102010-06-08 13:29:59 -070012539 }
12540 break;
12541 case SB16:
12542 {
12543 int rd = mmreg2(uMIPS_RD(ctx->opcode));
12544 int rb = mmreg(uMIPS_RS(ctx->opcode));
12545 int16_t offset = ZIMM(ctx->opcode, 0, 4);
12546
Aurelien Jarno5c13fdf2010-07-01 07:47:00 +020012547 gen_st(ctx, OPC_SB, rd, rb, offset);
Nathan Froyd3c824102010-06-08 13:29:59 -070012548 }
12549 break;
12550 case SH16:
12551 {
12552 int rd = mmreg2(uMIPS_RD(ctx->opcode));
12553 int rb = mmreg(uMIPS_RS(ctx->opcode));
12554 int16_t offset = ZIMM(ctx->opcode, 0, 4) << 1;
12555
Aurelien Jarno5c13fdf2010-07-01 07:47:00 +020012556 gen_st(ctx, OPC_SH, rd, rb, offset);
Nathan Froyd3c824102010-06-08 13:29:59 -070012557 }
12558 break;
12559 case SWSP16:
12560 {
12561 int rd = (ctx->opcode >> 5) & 0x1f;
12562 int rb = 29; /* SP */
12563 int16_t offset = ZIMM(ctx->opcode, 0, 5) << 2;
12564
Aurelien Jarno5c13fdf2010-07-01 07:47:00 +020012565 gen_st(ctx, OPC_SW, rd, rb, offset);
Nathan Froyd3c824102010-06-08 13:29:59 -070012566 }
12567 break;
12568 case SW16:
12569 {
12570 int rd = mmreg2(uMIPS_RD(ctx->opcode));
12571 int rb = mmreg(uMIPS_RS(ctx->opcode));
12572 int16_t offset = ZIMM(ctx->opcode, 0, 4) << 2;
12573
Aurelien Jarno5c13fdf2010-07-01 07:47:00 +020012574 gen_st(ctx, OPC_SW, rd, rb, offset);
Nathan Froyd3c824102010-06-08 13:29:59 -070012575 }
12576 break;
12577 case MOVE16:
12578 {
12579 int rd = uMIPS_RD5(ctx->opcode);
12580 int rs = uMIPS_RS5(ctx->opcode);
12581
Aurelien Jarnod75c1352013-01-01 18:02:22 +010012582 gen_arith_imm(ctx, OPC_ADDIU, rd, rs, 0);
Nathan Froyd3c824102010-06-08 13:29:59 -070012583 }
12584 break;
12585 case ANDI16:
Aurelien Jarnod75c1352013-01-01 18:02:22 +010012586 gen_andi16(ctx);
Nathan Froyd3c824102010-06-08 13:29:59 -070012587 break;
12588 case POOL16D:
12589 switch (ctx->opcode & 0x1) {
12590 case ADDIUS5:
Aurelien Jarnod75c1352013-01-01 18:02:22 +010012591 gen_addius5(ctx);
Nathan Froyd3c824102010-06-08 13:29:59 -070012592 break;
12593 case ADDIUSP:
Aurelien Jarnod75c1352013-01-01 18:02:22 +010012594 gen_addiusp(ctx);
Nathan Froyd3c824102010-06-08 13:29:59 -070012595 break;
12596 }
12597 break;
12598 case POOL16E:
12599 switch (ctx->opcode & 0x1) {
12600 case ADDIUR2:
Aurelien Jarnod75c1352013-01-01 18:02:22 +010012601 gen_addiur2(ctx);
Nathan Froyd3c824102010-06-08 13:29:59 -070012602 break;
12603 case ADDIUR1SP:
Aurelien Jarnod75c1352013-01-01 18:02:22 +010012604 gen_addiur1sp(ctx);
Nathan Froyd3c824102010-06-08 13:29:59 -070012605 break;
12606 }
12607 break;
12608 case B16:
12609 gen_compute_branch(ctx, OPC_BEQ, 2, 0, 0,
12610 SIMM(ctx->opcode, 0, 10) << 1);
12611 *is_branch = 1;
12612 break;
12613 case BNEZ16:
12614 case BEQZ16:
12615 gen_compute_branch(ctx, op == BNEZ16 ? OPC_BNE : OPC_BEQ, 2,
12616 mmreg(uMIPS_RD(ctx->opcode)),
12617 0, SIMM(ctx->opcode, 0, 7) << 1);
12618 *is_branch = 1;
12619 break;
12620 case LI16:
12621 {
12622 int reg = mmreg(uMIPS_RD(ctx->opcode));
12623 int imm = ZIMM(ctx->opcode, 0, 7);
12624
12625 imm = (imm == 0x7f ? -1 : imm);
12626 tcg_gen_movi_tl(cpu_gpr[reg], imm);
12627 }
12628 break;
12629 case RES_20:
12630 case RES_28:
12631 case RES_29:
12632 case RES_30:
12633 case RES_31:
12634 case RES_38:
12635 case RES_39:
12636 generate_exception(ctx, EXCP_RI);
12637 break;
12638 default:
12639 decode_micromips32_opc (env, ctx, op, is_branch);
12640 return 4;
12641 }
12642
12643 return 2;
12644}
12645
bellard6af0bf92005-07-02 14:58:51 +000012646/* SmartMIPS extension to MIPS32 */
12647
thsd26bc212007-11-08 18:05:37 +000012648#if defined(TARGET_MIPS64)
bellard6af0bf92005-07-02 14:58:51 +000012649
12650/* MDMX extension to MIPS64 */
bellard6af0bf92005-07-02 14:58:51 +000012651
12652#endif
12653
Jia Liu9b1a1d62012-10-24 22:17:05 +080012654/* MIPSDSP functions. */
Aurelien Jarnod75c1352013-01-01 18:02:22 +010012655static void gen_mipsdsp_ld(DisasContext *ctx, uint32_t opc,
Jia Liu9b1a1d62012-10-24 22:17:05 +080012656 int rd, int base, int offset)
12657{
12658 const char *opn = "ldx";
12659 TCGv t0;
12660
Jia Liu9b1a1d62012-10-24 22:17:05 +080012661 check_dsp(ctx);
12662 t0 = tcg_temp_new();
12663
12664 if (base == 0) {
12665 gen_load_gpr(t0, offset);
12666 } else if (offset == 0) {
12667 gen_load_gpr(t0, base);
12668 } else {
12669 gen_op_addr_add(ctx, t0, cpu_gpr[base], cpu_gpr[offset]);
12670 }
12671
Jia Liu9b1a1d62012-10-24 22:17:05 +080012672 switch (opc) {
12673 case OPC_LBUX:
Aurelien Jarno2910c6cb2012-10-09 21:53:20 +020012674 tcg_gen_qemu_ld8u(t0, t0, ctx->mem_idx);
Jia Liu9b1a1d62012-10-24 22:17:05 +080012675 gen_store_gpr(t0, rd);
12676 opn = "lbux";
12677 break;
12678 case OPC_LHX:
Aurelien Jarno2910c6cb2012-10-09 21:53:20 +020012679 tcg_gen_qemu_ld16s(t0, t0, ctx->mem_idx);
Jia Liu9b1a1d62012-10-24 22:17:05 +080012680 gen_store_gpr(t0, rd);
12681 opn = "lhx";
12682 break;
12683 case OPC_LWX:
Aurelien Jarno2910c6cb2012-10-09 21:53:20 +020012684 tcg_gen_qemu_ld32s(t0, t0, ctx->mem_idx);
Jia Liu9b1a1d62012-10-24 22:17:05 +080012685 gen_store_gpr(t0, rd);
12686 opn = "lwx";
12687 break;
12688#if defined(TARGET_MIPS64)
12689 case OPC_LDX:
Aurelien Jarno2910c6cb2012-10-09 21:53:20 +020012690 tcg_gen_qemu_ld64(t0, t0, ctx->mem_idx);
Jia Liu9b1a1d62012-10-24 22:17:05 +080012691 gen_store_gpr(t0, rd);
12692 opn = "ldx";
12693 break;
12694#endif
12695 }
12696 (void)opn; /* avoid a compiler warning */
12697 MIPS_DEBUG("%s %s, %s(%s)", opn,
12698 regnames[rd], regnames[offset], regnames[base]);
12699 tcg_temp_free(t0);
12700}
12701
Jia Liu461c08d2012-10-24 22:17:06 +080012702static void gen_mipsdsp_arith(DisasContext *ctx, uint32_t op1, uint32_t op2,
12703 int ret, int v1, int v2)
12704{
12705 const char *opn = "mipsdsp arith";
12706 TCGv v1_t;
12707 TCGv v2_t;
12708
12709 if (ret == 0) {
12710 /* Treat as NOP. */
12711 MIPS_DEBUG("NOP");
12712 return;
12713 }
12714
12715 v1_t = tcg_temp_new();
12716 v2_t = tcg_temp_new();
12717
12718 gen_load_gpr(v1_t, v1);
12719 gen_load_gpr(v2_t, v2);
12720
12721 switch (op1) {
12722 /* OPC_MULT_G_2E is equal OPC_ADDUH_QB_DSP */
12723 case OPC_MULT_G_2E:
12724 check_dspr2(ctx);
12725 switch (op2) {
12726 case OPC_ADDUH_QB:
12727 gen_helper_adduh_qb(cpu_gpr[ret], v1_t, v2_t);
12728 break;
12729 case OPC_ADDUH_R_QB:
12730 gen_helper_adduh_r_qb(cpu_gpr[ret], v1_t, v2_t);
12731 break;
12732 case OPC_ADDQH_PH:
12733 gen_helper_addqh_ph(cpu_gpr[ret], v1_t, v2_t);
12734 break;
12735 case OPC_ADDQH_R_PH:
12736 gen_helper_addqh_r_ph(cpu_gpr[ret], v1_t, v2_t);
12737 break;
12738 case OPC_ADDQH_W:
12739 gen_helper_addqh_w(cpu_gpr[ret], v1_t, v2_t);
12740 break;
12741 case OPC_ADDQH_R_W:
12742 gen_helper_addqh_r_w(cpu_gpr[ret], v1_t, v2_t);
12743 break;
12744 case OPC_SUBUH_QB:
12745 gen_helper_subuh_qb(cpu_gpr[ret], v1_t, v2_t);
12746 break;
12747 case OPC_SUBUH_R_QB:
12748 gen_helper_subuh_r_qb(cpu_gpr[ret], v1_t, v2_t);
12749 break;
12750 case OPC_SUBQH_PH:
12751 gen_helper_subqh_ph(cpu_gpr[ret], v1_t, v2_t);
12752 break;
12753 case OPC_SUBQH_R_PH:
12754 gen_helper_subqh_r_ph(cpu_gpr[ret], v1_t, v2_t);
12755 break;
12756 case OPC_SUBQH_W:
12757 gen_helper_subqh_w(cpu_gpr[ret], v1_t, v2_t);
12758 break;
12759 case OPC_SUBQH_R_W:
12760 gen_helper_subqh_r_w(cpu_gpr[ret], v1_t, v2_t);
12761 break;
12762 }
12763 break;
12764 case OPC_ABSQ_S_PH_DSP:
12765 switch (op2) {
12766 case OPC_ABSQ_S_QB:
12767 check_dspr2(ctx);
12768 gen_helper_absq_s_qb(cpu_gpr[ret], v2_t, cpu_env);
12769 break;
12770 case OPC_ABSQ_S_PH:
12771 check_dsp(ctx);
12772 gen_helper_absq_s_ph(cpu_gpr[ret], v2_t, cpu_env);
12773 break;
12774 case OPC_ABSQ_S_W:
12775 check_dsp(ctx);
12776 gen_helper_absq_s_w(cpu_gpr[ret], v2_t, cpu_env);
12777 break;
12778 case OPC_PRECEQ_W_PHL:
12779 check_dsp(ctx);
12780 tcg_gen_andi_tl(cpu_gpr[ret], v2_t, 0xFFFF0000);
12781 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
12782 break;
12783 case OPC_PRECEQ_W_PHR:
12784 check_dsp(ctx);
12785 tcg_gen_andi_tl(cpu_gpr[ret], v2_t, 0x0000FFFF);
12786 tcg_gen_shli_tl(cpu_gpr[ret], cpu_gpr[ret], 16);
12787 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
12788 break;
12789 case OPC_PRECEQU_PH_QBL:
12790 check_dsp(ctx);
12791 gen_helper_precequ_ph_qbl(cpu_gpr[ret], v2_t);
12792 break;
12793 case OPC_PRECEQU_PH_QBR:
12794 check_dsp(ctx);
12795 gen_helper_precequ_ph_qbr(cpu_gpr[ret], v2_t);
12796 break;
12797 case OPC_PRECEQU_PH_QBLA:
12798 check_dsp(ctx);
12799 gen_helper_precequ_ph_qbla(cpu_gpr[ret], v2_t);
12800 break;
12801 case OPC_PRECEQU_PH_QBRA:
12802 check_dsp(ctx);
12803 gen_helper_precequ_ph_qbra(cpu_gpr[ret], v2_t);
12804 break;
12805 case OPC_PRECEU_PH_QBL:
12806 check_dsp(ctx);
12807 gen_helper_preceu_ph_qbl(cpu_gpr[ret], v2_t);
12808 break;
12809 case OPC_PRECEU_PH_QBR:
12810 check_dsp(ctx);
12811 gen_helper_preceu_ph_qbr(cpu_gpr[ret], v2_t);
12812 break;
12813 case OPC_PRECEU_PH_QBLA:
12814 check_dsp(ctx);
12815 gen_helper_preceu_ph_qbla(cpu_gpr[ret], v2_t);
12816 break;
12817 case OPC_PRECEU_PH_QBRA:
12818 check_dsp(ctx);
12819 gen_helper_preceu_ph_qbra(cpu_gpr[ret], v2_t);
12820 break;
12821 }
12822 break;
12823 case OPC_ADDU_QB_DSP:
12824 switch (op2) {
12825 case OPC_ADDQ_PH:
12826 check_dsp(ctx);
12827 gen_helper_addq_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
12828 break;
12829 case OPC_ADDQ_S_PH:
12830 check_dsp(ctx);
12831 gen_helper_addq_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
12832 break;
12833 case OPC_ADDQ_S_W:
12834 check_dsp(ctx);
12835 gen_helper_addq_s_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
12836 break;
12837 case OPC_ADDU_QB:
12838 check_dsp(ctx);
12839 gen_helper_addu_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
12840 break;
12841 case OPC_ADDU_S_QB:
12842 check_dsp(ctx);
12843 gen_helper_addu_s_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
12844 break;
12845 case OPC_ADDU_PH:
12846 check_dspr2(ctx);
12847 gen_helper_addu_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
12848 break;
12849 case OPC_ADDU_S_PH:
12850 check_dspr2(ctx);
12851 gen_helper_addu_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
12852 break;
12853 case OPC_SUBQ_PH:
12854 check_dsp(ctx);
12855 gen_helper_subq_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
12856 break;
12857 case OPC_SUBQ_S_PH:
12858 check_dsp(ctx);
12859 gen_helper_subq_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
12860 break;
12861 case OPC_SUBQ_S_W:
12862 check_dsp(ctx);
12863 gen_helper_subq_s_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
12864 break;
12865 case OPC_SUBU_QB:
12866 check_dsp(ctx);
12867 gen_helper_subu_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
12868 break;
12869 case OPC_SUBU_S_QB:
12870 check_dsp(ctx);
12871 gen_helper_subu_s_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
12872 break;
12873 case OPC_SUBU_PH:
12874 check_dspr2(ctx);
12875 gen_helper_subu_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
12876 break;
12877 case OPC_SUBU_S_PH:
12878 check_dspr2(ctx);
12879 gen_helper_subu_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
12880 break;
12881 case OPC_ADDSC:
12882 check_dsp(ctx);
12883 gen_helper_addsc(cpu_gpr[ret], v1_t, v2_t, cpu_env);
12884 break;
12885 case OPC_ADDWC:
12886 check_dsp(ctx);
12887 gen_helper_addwc(cpu_gpr[ret], v1_t, v2_t, cpu_env);
12888 break;
12889 case OPC_MODSUB:
12890 check_dsp(ctx);
12891 gen_helper_modsub(cpu_gpr[ret], v1_t, v2_t);
12892 break;
12893 case OPC_RADDU_W_QB:
12894 check_dsp(ctx);
12895 gen_helper_raddu_w_qb(cpu_gpr[ret], v1_t);
12896 break;
12897 }
12898 break;
12899 case OPC_CMPU_EQ_QB_DSP:
12900 switch (op2) {
12901 case OPC_PRECR_QB_PH:
12902 check_dspr2(ctx);
12903 gen_helper_precr_qb_ph(cpu_gpr[ret], v1_t, v2_t);
12904 break;
12905 case OPC_PRECRQ_QB_PH:
12906 check_dsp(ctx);
12907 gen_helper_precrq_qb_ph(cpu_gpr[ret], v1_t, v2_t);
12908 break;
12909 case OPC_PRECR_SRA_PH_W:
12910 check_dspr2(ctx);
12911 {
12912 TCGv_i32 sa_t = tcg_const_i32(v2);
12913 gen_helper_precr_sra_ph_w(cpu_gpr[ret], sa_t, v1_t,
12914 cpu_gpr[ret]);
12915 tcg_temp_free_i32(sa_t);
12916 break;
12917 }
12918 case OPC_PRECR_SRA_R_PH_W:
12919 check_dspr2(ctx);
12920 {
12921 TCGv_i32 sa_t = tcg_const_i32(v2);
12922 gen_helper_precr_sra_r_ph_w(cpu_gpr[ret], sa_t, v1_t,
12923 cpu_gpr[ret]);
12924 tcg_temp_free_i32(sa_t);
12925 break;
12926 }
12927 case OPC_PRECRQ_PH_W:
12928 check_dsp(ctx);
12929 gen_helper_precrq_ph_w(cpu_gpr[ret], v1_t, v2_t);
12930 break;
12931 case OPC_PRECRQ_RS_PH_W:
12932 check_dsp(ctx);
12933 gen_helper_precrq_rs_ph_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
12934 break;
12935 case OPC_PRECRQU_S_QB_PH:
12936 check_dsp(ctx);
12937 gen_helper_precrqu_s_qb_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
12938 break;
12939 }
12940 break;
12941#ifdef TARGET_MIPS64
12942 case OPC_ABSQ_S_QH_DSP:
12943 switch (op2) {
12944 case OPC_PRECEQ_L_PWL:
12945 check_dsp(ctx);
12946 tcg_gen_andi_tl(cpu_gpr[ret], v2_t, 0xFFFFFFFF00000000ull);
12947 break;
12948 case OPC_PRECEQ_L_PWR:
12949 check_dsp(ctx);
12950 tcg_gen_shli_tl(cpu_gpr[ret], v2_t, 32);
12951 break;
12952 case OPC_PRECEQ_PW_QHL:
12953 check_dsp(ctx);
12954 gen_helper_preceq_pw_qhl(cpu_gpr[ret], v2_t);
12955 break;
12956 case OPC_PRECEQ_PW_QHR:
12957 check_dsp(ctx);
12958 gen_helper_preceq_pw_qhr(cpu_gpr[ret], v2_t);
12959 break;
12960 case OPC_PRECEQ_PW_QHLA:
12961 check_dsp(ctx);
12962 gen_helper_preceq_pw_qhla(cpu_gpr[ret], v2_t);
12963 break;
12964 case OPC_PRECEQ_PW_QHRA:
12965 check_dsp(ctx);
12966 gen_helper_preceq_pw_qhra(cpu_gpr[ret], v2_t);
12967 break;
12968 case OPC_PRECEQU_QH_OBL:
12969 check_dsp(ctx);
12970 gen_helper_precequ_qh_obl(cpu_gpr[ret], v2_t);
12971 break;
12972 case OPC_PRECEQU_QH_OBR:
12973 check_dsp(ctx);
12974 gen_helper_precequ_qh_obr(cpu_gpr[ret], v2_t);
12975 break;
12976 case OPC_PRECEQU_QH_OBLA:
12977 check_dsp(ctx);
12978 gen_helper_precequ_qh_obla(cpu_gpr[ret], v2_t);
12979 break;
12980 case OPC_PRECEQU_QH_OBRA:
12981 check_dsp(ctx);
12982 gen_helper_precequ_qh_obra(cpu_gpr[ret], v2_t);
12983 break;
12984 case OPC_PRECEU_QH_OBL:
12985 check_dsp(ctx);
12986 gen_helper_preceu_qh_obl(cpu_gpr[ret], v2_t);
12987 break;
12988 case OPC_PRECEU_QH_OBR:
12989 check_dsp(ctx);
12990 gen_helper_preceu_qh_obr(cpu_gpr[ret], v2_t);
12991 break;
12992 case OPC_PRECEU_QH_OBLA:
12993 check_dsp(ctx);
12994 gen_helper_preceu_qh_obla(cpu_gpr[ret], v2_t);
12995 break;
12996 case OPC_PRECEU_QH_OBRA:
12997 check_dsp(ctx);
12998 gen_helper_preceu_qh_obra(cpu_gpr[ret], v2_t);
12999 break;
13000 case OPC_ABSQ_S_OB:
13001 check_dspr2(ctx);
13002 gen_helper_absq_s_ob(cpu_gpr[ret], v2_t, cpu_env);
13003 break;
13004 case OPC_ABSQ_S_PW:
13005 check_dsp(ctx);
13006 gen_helper_absq_s_pw(cpu_gpr[ret], v2_t, cpu_env);
13007 break;
13008 case OPC_ABSQ_S_QH:
13009 check_dsp(ctx);
13010 gen_helper_absq_s_qh(cpu_gpr[ret], v2_t, cpu_env);
13011 break;
13012 }
13013 break;
13014 case OPC_ADDU_OB_DSP:
13015 switch (op2) {
13016 case OPC_RADDU_L_OB:
13017 check_dsp(ctx);
13018 gen_helper_raddu_l_ob(cpu_gpr[ret], v1_t);
13019 break;
13020 case OPC_SUBQ_PW:
13021 check_dsp(ctx);
13022 gen_helper_subq_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
13023 break;
13024 case OPC_SUBQ_S_PW:
13025 check_dsp(ctx);
13026 gen_helper_subq_s_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
13027 break;
13028 case OPC_SUBQ_QH:
13029 check_dsp(ctx);
13030 gen_helper_subq_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
13031 break;
13032 case OPC_SUBQ_S_QH:
13033 check_dsp(ctx);
13034 gen_helper_subq_s_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
13035 break;
13036 case OPC_SUBU_OB:
13037 check_dsp(ctx);
13038 gen_helper_subu_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
13039 break;
13040 case OPC_SUBU_S_OB:
13041 check_dsp(ctx);
13042 gen_helper_subu_s_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
13043 break;
13044 case OPC_SUBU_QH:
13045 check_dspr2(ctx);
13046 gen_helper_subu_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
13047 break;
13048 case OPC_SUBU_S_QH:
13049 check_dspr2(ctx);
13050 gen_helper_subu_s_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
13051 break;
13052 case OPC_SUBUH_OB:
13053 check_dspr2(ctx);
13054 gen_helper_subuh_ob(cpu_gpr[ret], v1_t, v2_t);
13055 break;
13056 case OPC_SUBUH_R_OB:
13057 check_dspr2(ctx);
13058 gen_helper_subuh_r_ob(cpu_gpr[ret], v1_t, v2_t);
13059 break;
13060 case OPC_ADDQ_PW:
13061 check_dsp(ctx);
13062 gen_helper_addq_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
13063 break;
13064 case OPC_ADDQ_S_PW:
13065 check_dsp(ctx);
13066 gen_helper_addq_s_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
13067 break;
13068 case OPC_ADDQ_QH:
13069 check_dsp(ctx);
13070 gen_helper_addq_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
13071 break;
13072 case OPC_ADDQ_S_QH:
13073 check_dsp(ctx);
13074 gen_helper_addq_s_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
13075 break;
13076 case OPC_ADDU_OB:
13077 check_dsp(ctx);
13078 gen_helper_addu_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
13079 break;
13080 case OPC_ADDU_S_OB:
13081 check_dsp(ctx);
13082 gen_helper_addu_s_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
13083 break;
13084 case OPC_ADDU_QH:
13085 check_dspr2(ctx);
13086 gen_helper_addu_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
13087 break;
13088 case OPC_ADDU_S_QH:
13089 check_dspr2(ctx);
13090 gen_helper_addu_s_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
13091 break;
13092 case OPC_ADDUH_OB:
13093 check_dspr2(ctx);
13094 gen_helper_adduh_ob(cpu_gpr[ret], v1_t, v2_t);
13095 break;
13096 case OPC_ADDUH_R_OB:
13097 check_dspr2(ctx);
13098 gen_helper_adduh_r_ob(cpu_gpr[ret], v1_t, v2_t);
13099 break;
13100 }
13101 break;
13102 case OPC_CMPU_EQ_OB_DSP:
13103 switch (op2) {
13104 case OPC_PRECR_OB_QH:
13105 check_dspr2(ctx);
13106 gen_helper_precr_ob_qh(cpu_gpr[ret], v1_t, v2_t);
13107 break;
13108 case OPC_PRECR_SRA_QH_PW:
13109 check_dspr2(ctx);
13110 {
13111 TCGv_i32 ret_t = tcg_const_i32(ret);
13112 gen_helper_precr_sra_qh_pw(v2_t, v1_t, v2_t, ret_t);
13113 tcg_temp_free_i32(ret_t);
13114 break;
13115 }
13116 case OPC_PRECR_SRA_R_QH_PW:
13117 check_dspr2(ctx);
13118 {
13119 TCGv_i32 sa_v = tcg_const_i32(ret);
13120 gen_helper_precr_sra_r_qh_pw(v2_t, v1_t, v2_t, sa_v);
13121 tcg_temp_free_i32(sa_v);
13122 break;
13123 }
13124 case OPC_PRECRQ_OB_QH:
13125 check_dsp(ctx);
13126 gen_helper_precrq_ob_qh(cpu_gpr[ret], v1_t, v2_t);
13127 break;
13128 case OPC_PRECRQ_PW_L:
13129 check_dsp(ctx);
13130 gen_helper_precrq_pw_l(cpu_gpr[ret], v1_t, v2_t);
13131 break;
13132 case OPC_PRECRQ_QH_PW:
13133 check_dsp(ctx);
13134 gen_helper_precrq_qh_pw(cpu_gpr[ret], v1_t, v2_t);
13135 break;
13136 case OPC_PRECRQ_RS_QH_PW:
13137 check_dsp(ctx);
13138 gen_helper_precrq_rs_qh_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
13139 break;
13140 case OPC_PRECRQU_S_OB_QH:
13141 check_dsp(ctx);
13142 gen_helper_precrqu_s_ob_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
13143 break;
13144 }
13145 break;
13146#endif
13147 }
13148
13149 tcg_temp_free(v1_t);
13150 tcg_temp_free(v2_t);
13151
13152 (void)opn; /* avoid a compiler warning */
13153 MIPS_DEBUG("%s", opn);
13154}
Jia Liu9b1a1d62012-10-24 22:17:05 +080013155
Jia Liu77c5fa82012-10-24 22:17:07 +080013156static void gen_mipsdsp_shift(DisasContext *ctx, uint32_t opc,
13157 int ret, int v1, int v2)
13158{
13159 uint32_t op2;
13160 const char *opn = "mipsdsp shift";
13161 TCGv t0;
13162 TCGv v1_t;
13163 TCGv v2_t;
13164
13165 if (ret == 0) {
13166 /* Treat as NOP. */
13167 MIPS_DEBUG("NOP");
13168 return;
13169 }
13170
13171 t0 = tcg_temp_new();
13172 v1_t = tcg_temp_new();
13173 v2_t = tcg_temp_new();
13174
13175 tcg_gen_movi_tl(t0, v1);
13176 gen_load_gpr(v1_t, v1);
13177 gen_load_gpr(v2_t, v2);
13178
13179 switch (opc) {
13180 case OPC_SHLL_QB_DSP:
13181 {
13182 op2 = MASK_SHLL_QB(ctx->opcode);
13183 switch (op2) {
13184 case OPC_SHLL_QB:
13185 check_dsp(ctx);
13186 gen_helper_shll_qb(cpu_gpr[ret], t0, v2_t, cpu_env);
13187 break;
13188 case OPC_SHLLV_QB:
13189 check_dsp(ctx);
13190 gen_helper_shll_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
13191 break;
13192 case OPC_SHLL_PH:
13193 check_dsp(ctx);
13194 gen_helper_shll_ph(cpu_gpr[ret], t0, v2_t, cpu_env);
13195 break;
13196 case OPC_SHLLV_PH:
13197 check_dsp(ctx);
13198 gen_helper_shll_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
13199 break;
13200 case OPC_SHLL_S_PH:
13201 check_dsp(ctx);
13202 gen_helper_shll_s_ph(cpu_gpr[ret], t0, v2_t, cpu_env);
13203 break;
13204 case OPC_SHLLV_S_PH:
13205 check_dsp(ctx);
13206 gen_helper_shll_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
13207 break;
13208 case OPC_SHLL_S_W:
13209 check_dsp(ctx);
13210 gen_helper_shll_s_w(cpu_gpr[ret], t0, v2_t, cpu_env);
13211 break;
13212 case OPC_SHLLV_S_W:
13213 check_dsp(ctx);
13214 gen_helper_shll_s_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
13215 break;
13216 case OPC_SHRL_QB:
13217 check_dsp(ctx);
13218 gen_helper_shrl_qb(cpu_gpr[ret], t0, v2_t);
13219 break;
13220 case OPC_SHRLV_QB:
13221 check_dsp(ctx);
13222 gen_helper_shrl_qb(cpu_gpr[ret], v1_t, v2_t);
13223 break;
13224 case OPC_SHRL_PH:
13225 check_dspr2(ctx);
13226 gen_helper_shrl_ph(cpu_gpr[ret], t0, v2_t);
13227 break;
13228 case OPC_SHRLV_PH:
13229 check_dspr2(ctx);
13230 gen_helper_shrl_ph(cpu_gpr[ret], v1_t, v2_t);
13231 break;
13232 case OPC_SHRA_QB:
13233 check_dspr2(ctx);
13234 gen_helper_shra_qb(cpu_gpr[ret], t0, v2_t);
13235 break;
13236 case OPC_SHRA_R_QB:
13237 check_dspr2(ctx);
13238 gen_helper_shra_r_qb(cpu_gpr[ret], t0, v2_t);
13239 break;
13240 case OPC_SHRAV_QB:
13241 check_dspr2(ctx);
13242 gen_helper_shra_qb(cpu_gpr[ret], v1_t, v2_t);
13243 break;
13244 case OPC_SHRAV_R_QB:
13245 check_dspr2(ctx);
13246 gen_helper_shra_r_qb(cpu_gpr[ret], v1_t, v2_t);
13247 break;
13248 case OPC_SHRA_PH:
13249 check_dsp(ctx);
13250 gen_helper_shra_ph(cpu_gpr[ret], t0, v2_t);
13251 break;
13252 case OPC_SHRA_R_PH:
13253 check_dsp(ctx);
13254 gen_helper_shra_r_ph(cpu_gpr[ret], t0, v2_t);
13255 break;
13256 case OPC_SHRAV_PH:
13257 check_dsp(ctx);
13258 gen_helper_shra_ph(cpu_gpr[ret], v1_t, v2_t);
13259 break;
13260 case OPC_SHRAV_R_PH:
13261 check_dsp(ctx);
13262 gen_helper_shra_r_ph(cpu_gpr[ret], v1_t, v2_t);
13263 break;
13264 case OPC_SHRA_R_W:
13265 check_dsp(ctx);
13266 gen_helper_shra_r_w(cpu_gpr[ret], t0, v2_t);
13267 break;
13268 case OPC_SHRAV_R_W:
13269 check_dsp(ctx);
13270 gen_helper_shra_r_w(cpu_gpr[ret], v1_t, v2_t);
13271 break;
13272 default: /* Invalid */
13273 MIPS_INVAL("MASK SHLL.QB");
13274 generate_exception(ctx, EXCP_RI);
13275 break;
13276 }
13277 break;
13278 }
13279#ifdef TARGET_MIPS64
13280 case OPC_SHLL_OB_DSP:
13281 op2 = MASK_SHLL_OB(ctx->opcode);
13282 switch (op2) {
13283 case OPC_SHLL_PW:
13284 check_dsp(ctx);
13285 gen_helper_shll_pw(cpu_gpr[ret], v2_t, t0, cpu_env);
13286 break;
13287 case OPC_SHLLV_PW:
13288 check_dsp(ctx);
13289 gen_helper_shll_pw(cpu_gpr[ret], v2_t, v1_t, cpu_env);
13290 break;
13291 case OPC_SHLL_S_PW:
13292 check_dsp(ctx);
13293 gen_helper_shll_s_pw(cpu_gpr[ret], v2_t, t0, cpu_env);
13294 break;
13295 case OPC_SHLLV_S_PW:
13296 check_dsp(ctx);
13297 gen_helper_shll_s_pw(cpu_gpr[ret], v2_t, v1_t, cpu_env);
13298 break;
13299 case OPC_SHLL_OB:
13300 check_dsp(ctx);
13301 gen_helper_shll_ob(cpu_gpr[ret], v2_t, t0, cpu_env);
13302 break;
13303 case OPC_SHLLV_OB:
13304 check_dsp(ctx);
13305 gen_helper_shll_ob(cpu_gpr[ret], v2_t, v1_t, cpu_env);
13306 break;
13307 case OPC_SHLL_QH:
13308 check_dsp(ctx);
13309 gen_helper_shll_qh(cpu_gpr[ret], v2_t, t0, cpu_env);
13310 break;
13311 case OPC_SHLLV_QH:
13312 check_dsp(ctx);
13313 gen_helper_shll_qh(cpu_gpr[ret], v2_t, v1_t, cpu_env);
13314 break;
13315 case OPC_SHLL_S_QH:
13316 check_dsp(ctx);
13317 gen_helper_shll_s_qh(cpu_gpr[ret], v2_t, t0, cpu_env);
13318 break;
13319 case OPC_SHLLV_S_QH:
13320 check_dsp(ctx);
13321 gen_helper_shll_s_qh(cpu_gpr[ret], v2_t, v1_t, cpu_env);
13322 break;
13323 case OPC_SHRA_OB:
13324 check_dspr2(ctx);
13325 gen_helper_shra_ob(cpu_gpr[ret], v2_t, t0);
13326 break;
13327 case OPC_SHRAV_OB:
13328 check_dspr2(ctx);
13329 gen_helper_shra_ob(cpu_gpr[ret], v2_t, v1_t);
13330 break;
13331 case OPC_SHRA_R_OB:
13332 check_dspr2(ctx);
13333 gen_helper_shra_r_ob(cpu_gpr[ret], v2_t, t0);
13334 break;
13335 case OPC_SHRAV_R_OB:
13336 check_dspr2(ctx);
13337 gen_helper_shra_r_ob(cpu_gpr[ret], v2_t, v1_t);
13338 break;
13339 case OPC_SHRA_PW:
13340 check_dsp(ctx);
13341 gen_helper_shra_pw(cpu_gpr[ret], v2_t, t0);
13342 break;
13343 case OPC_SHRAV_PW:
13344 check_dsp(ctx);
13345 gen_helper_shra_pw(cpu_gpr[ret], v2_t, v1_t);
13346 break;
13347 case OPC_SHRA_R_PW:
13348 check_dsp(ctx);
13349 gen_helper_shra_r_pw(cpu_gpr[ret], v2_t, t0);
13350 break;
13351 case OPC_SHRAV_R_PW:
13352 check_dsp(ctx);
13353 gen_helper_shra_r_pw(cpu_gpr[ret], v2_t, v1_t);
13354 break;
13355 case OPC_SHRA_QH:
13356 check_dsp(ctx);
13357 gen_helper_shra_qh(cpu_gpr[ret], v2_t, t0);
13358 break;
13359 case OPC_SHRAV_QH:
13360 check_dsp(ctx);
13361 gen_helper_shra_qh(cpu_gpr[ret], v2_t, v1_t);
13362 break;
13363 case OPC_SHRA_R_QH:
13364 check_dsp(ctx);
13365 gen_helper_shra_r_qh(cpu_gpr[ret], v2_t, t0);
13366 break;
13367 case OPC_SHRAV_R_QH:
13368 check_dsp(ctx);
13369 gen_helper_shra_r_qh(cpu_gpr[ret], v2_t, v1_t);
13370 break;
13371 case OPC_SHRL_OB:
13372 check_dsp(ctx);
13373 gen_helper_shrl_ob(cpu_gpr[ret], v2_t, t0);
13374 break;
13375 case OPC_SHRLV_OB:
13376 check_dsp(ctx);
13377 gen_helper_shrl_ob(cpu_gpr[ret], v2_t, v1_t);
13378 break;
13379 case OPC_SHRL_QH:
13380 check_dspr2(ctx);
13381 gen_helper_shrl_qh(cpu_gpr[ret], v2_t, t0);
13382 break;
13383 case OPC_SHRLV_QH:
13384 check_dspr2(ctx);
13385 gen_helper_shrl_qh(cpu_gpr[ret], v2_t, v1_t);
13386 break;
13387 default: /* Invalid */
13388 MIPS_INVAL("MASK SHLL.OB");
13389 generate_exception(ctx, EXCP_RI);
13390 break;
13391 }
13392 break;
13393#endif
13394 }
13395
13396 tcg_temp_free(t0);
13397 tcg_temp_free(v1_t);
13398 tcg_temp_free(v2_t);
13399 (void)opn; /* avoid a compiler warning */
13400 MIPS_DEBUG("%s", opn);
13401}
13402
Jia Liua22260a2012-10-24 22:17:08 +080013403static void gen_mipsdsp_multiply(DisasContext *ctx, uint32_t op1, uint32_t op2,
13404 int ret, int v1, int v2, int check_ret)
13405{
13406 const char *opn = "mipsdsp multiply";
13407 TCGv_i32 t0;
13408 TCGv v1_t;
13409 TCGv v2_t;
13410
13411 if ((ret == 0) && (check_ret == 1)) {
13412 /* Treat as NOP. */
13413 MIPS_DEBUG("NOP");
13414 return;
13415 }
13416
13417 t0 = tcg_temp_new_i32();
13418 v1_t = tcg_temp_new();
13419 v2_t = tcg_temp_new();
13420
13421 tcg_gen_movi_i32(t0, ret);
13422 gen_load_gpr(v1_t, v1);
13423 gen_load_gpr(v2_t, v2);
13424
13425 switch (op1) {
13426 /* OPC_MULT_G_2E, OPC_ADDUH_QB_DSP, OPC_MUL_PH_DSP have
13427 * the same mask and op1. */
13428 case OPC_MULT_G_2E:
13429 switch (op2) {
13430 case OPC_MUL_PH:
13431 gen_helper_mul_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
13432 break;
13433 case OPC_MUL_S_PH:
13434 gen_helper_mul_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
13435 break;
13436 case OPC_MULQ_S_W:
13437 gen_helper_mulq_s_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
13438 break;
13439 case OPC_MULQ_RS_W:
13440 gen_helper_mulq_rs_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
13441 break;
13442 }
13443 break;
13444 case OPC_DPA_W_PH_DSP:
13445 switch (op2) {
13446 case OPC_DPAU_H_QBL:
13447 check_dsp(ctx);
13448 gen_helper_dpau_h_qbl(t0, v1_t, v2_t, cpu_env);
13449 break;
13450 case OPC_DPAU_H_QBR:
13451 check_dsp(ctx);
13452 gen_helper_dpau_h_qbr(t0, v1_t, v2_t, cpu_env);
13453 break;
13454 case OPC_DPSU_H_QBL:
13455 check_dsp(ctx);
13456 gen_helper_dpsu_h_qbl(t0, v1_t, v2_t, cpu_env);
13457 break;
13458 case OPC_DPSU_H_QBR:
13459 check_dsp(ctx);
13460 gen_helper_dpsu_h_qbr(t0, v1_t, v2_t, cpu_env);
13461 break;
13462 case OPC_DPA_W_PH:
13463 check_dspr2(ctx);
13464 gen_helper_dpa_w_ph(t0, v1_t, v2_t, cpu_env);
13465 break;
13466 case OPC_DPAX_W_PH:
13467 check_dspr2(ctx);
13468 gen_helper_dpax_w_ph(t0, v1_t, v2_t, cpu_env);
13469 break;
13470 case OPC_DPAQ_S_W_PH:
13471 check_dsp(ctx);
13472 gen_helper_dpaq_s_w_ph(t0, v1_t, v2_t, cpu_env);
13473 break;
13474 case OPC_DPAQX_S_W_PH:
13475 check_dspr2(ctx);
13476 gen_helper_dpaqx_s_w_ph(t0, v1_t, v2_t, cpu_env);
13477 break;
13478 case OPC_DPAQX_SA_W_PH:
13479 check_dspr2(ctx);
13480 gen_helper_dpaqx_sa_w_ph(t0, v1_t, v2_t, cpu_env);
13481 break;
13482 case OPC_DPS_W_PH:
13483 check_dspr2(ctx);
13484 gen_helper_dps_w_ph(t0, v1_t, v2_t, cpu_env);
13485 break;
13486 case OPC_DPSX_W_PH:
13487 check_dspr2(ctx);
13488 gen_helper_dpsx_w_ph(t0, v1_t, v2_t, cpu_env);
13489 break;
13490 case OPC_DPSQ_S_W_PH:
13491 check_dsp(ctx);
13492 gen_helper_dpsq_s_w_ph(t0, v1_t, v2_t, cpu_env);
13493 break;
13494 case OPC_DPSQX_S_W_PH:
13495 check_dspr2(ctx);
13496 gen_helper_dpsqx_s_w_ph(t0, v1_t, v2_t, cpu_env);
13497 break;
13498 case OPC_DPSQX_SA_W_PH:
13499 check_dspr2(ctx);
13500 gen_helper_dpsqx_sa_w_ph(t0, v1_t, v2_t, cpu_env);
13501 break;
13502 case OPC_MULSAQ_S_W_PH:
13503 check_dsp(ctx);
13504 gen_helper_mulsaq_s_w_ph(t0, v1_t, v2_t, cpu_env);
13505 break;
13506 case OPC_DPAQ_SA_L_W:
13507 check_dsp(ctx);
13508 gen_helper_dpaq_sa_l_w(t0, v1_t, v2_t, cpu_env);
13509 break;
13510 case OPC_DPSQ_SA_L_W:
13511 check_dsp(ctx);
13512 gen_helper_dpsq_sa_l_w(t0, v1_t, v2_t, cpu_env);
13513 break;
13514 case OPC_MAQ_S_W_PHL:
13515 check_dsp(ctx);
13516 gen_helper_maq_s_w_phl(t0, v1_t, v2_t, cpu_env);
13517 break;
13518 case OPC_MAQ_S_W_PHR:
13519 check_dsp(ctx);
13520 gen_helper_maq_s_w_phr(t0, v1_t, v2_t, cpu_env);
13521 break;
13522 case OPC_MAQ_SA_W_PHL:
13523 check_dsp(ctx);
13524 gen_helper_maq_sa_w_phl(t0, v1_t, v2_t, cpu_env);
13525 break;
13526 case OPC_MAQ_SA_W_PHR:
13527 check_dsp(ctx);
13528 gen_helper_maq_sa_w_phr(t0, v1_t, v2_t, cpu_env);
13529 break;
13530 case OPC_MULSA_W_PH:
13531 check_dspr2(ctx);
13532 gen_helper_mulsa_w_ph(t0, v1_t, v2_t, cpu_env);
13533 break;
13534 }
13535 break;
13536#ifdef TARGET_MIPS64
13537 case OPC_DPAQ_W_QH_DSP:
13538 {
13539 int ac = ret & 0x03;
13540 tcg_gen_movi_i32(t0, ac);
13541
13542 switch (op2) {
13543 case OPC_DMADD:
13544 check_dsp(ctx);
13545 gen_helper_dmadd(v1_t, v2_t, t0, cpu_env);
13546 break;
13547 case OPC_DMADDU:
13548 check_dsp(ctx);
13549 gen_helper_dmaddu(v1_t, v2_t, t0, cpu_env);
13550 break;
13551 case OPC_DMSUB:
13552 check_dsp(ctx);
13553 gen_helper_dmsub(v1_t, v2_t, t0, cpu_env);
13554 break;
13555 case OPC_DMSUBU:
13556 check_dsp(ctx);
13557 gen_helper_dmsubu(v1_t, v2_t, t0, cpu_env);
13558 break;
13559 case OPC_DPA_W_QH:
13560 check_dspr2(ctx);
13561 gen_helper_dpa_w_qh(v1_t, v2_t, t0, cpu_env);
13562 break;
13563 case OPC_DPAQ_S_W_QH:
13564 check_dsp(ctx);
13565 gen_helper_dpaq_s_w_qh(v1_t, v2_t, t0, cpu_env);
13566 break;
13567 case OPC_DPAQ_SA_L_PW:
13568 check_dsp(ctx);
13569 gen_helper_dpaq_sa_l_pw(v1_t, v2_t, t0, cpu_env);
13570 break;
13571 case OPC_DPAU_H_OBL:
13572 check_dsp(ctx);
13573 gen_helper_dpau_h_obl(v1_t, v2_t, t0, cpu_env);
13574 break;
13575 case OPC_DPAU_H_OBR:
13576 check_dsp(ctx);
13577 gen_helper_dpau_h_obr(v1_t, v2_t, t0, cpu_env);
13578 break;
13579 case OPC_DPS_W_QH:
13580 check_dspr2(ctx);
13581 gen_helper_dps_w_qh(v1_t, v2_t, t0, cpu_env);
13582 break;
13583 case OPC_DPSQ_S_W_QH:
13584 check_dsp(ctx);
13585 gen_helper_dpsq_s_w_qh(v1_t, v2_t, t0, cpu_env);
13586 break;
13587 case OPC_DPSQ_SA_L_PW:
13588 check_dsp(ctx);
13589 gen_helper_dpsq_sa_l_pw(v1_t, v2_t, t0, cpu_env);
13590 break;
13591 case OPC_DPSU_H_OBL:
13592 check_dsp(ctx);
13593 gen_helper_dpsu_h_obl(v1_t, v2_t, t0, cpu_env);
13594 break;
13595 case OPC_DPSU_H_OBR:
13596 check_dsp(ctx);
13597 gen_helper_dpsu_h_obr(v1_t, v2_t, t0, cpu_env);
13598 break;
13599 case OPC_MAQ_S_L_PWL:
13600 check_dsp(ctx);
13601 gen_helper_maq_s_l_pwl(v1_t, v2_t, t0, cpu_env);
13602 break;
13603 case OPC_MAQ_S_L_PWR:
13604 check_dsp(ctx);
13605 gen_helper_maq_s_l_pwr(v1_t, v2_t, t0, cpu_env);
13606 break;
13607 case OPC_MAQ_S_W_QHLL:
13608 check_dsp(ctx);
13609 gen_helper_maq_s_w_qhll(v1_t, v2_t, t0, cpu_env);
13610 break;
13611 case OPC_MAQ_SA_W_QHLL:
13612 check_dsp(ctx);
13613 gen_helper_maq_sa_w_qhll(v1_t, v2_t, t0, cpu_env);
13614 break;
13615 case OPC_MAQ_S_W_QHLR:
13616 check_dsp(ctx);
13617 gen_helper_maq_s_w_qhlr(v1_t, v2_t, t0, cpu_env);
13618 break;
13619 case OPC_MAQ_SA_W_QHLR:
13620 check_dsp(ctx);
13621 gen_helper_maq_sa_w_qhlr(v1_t, v2_t, t0, cpu_env);
13622 break;
13623 case OPC_MAQ_S_W_QHRL:
13624 check_dsp(ctx);
13625 gen_helper_maq_s_w_qhrl(v1_t, v2_t, t0, cpu_env);
13626 break;
13627 case OPC_MAQ_SA_W_QHRL:
13628 check_dsp(ctx);
13629 gen_helper_maq_sa_w_qhrl(v1_t, v2_t, t0, cpu_env);
13630 break;
13631 case OPC_MAQ_S_W_QHRR:
13632 check_dsp(ctx);
13633 gen_helper_maq_s_w_qhrr(v1_t, v2_t, t0, cpu_env);
13634 break;
13635 case OPC_MAQ_SA_W_QHRR:
13636 check_dsp(ctx);
13637 gen_helper_maq_sa_w_qhrr(v1_t, v2_t, t0, cpu_env);
13638 break;
13639 case OPC_MULSAQ_S_L_PW:
13640 check_dsp(ctx);
13641 gen_helper_mulsaq_s_l_pw(v1_t, v2_t, t0, cpu_env);
13642 break;
13643 case OPC_MULSAQ_S_W_QH:
13644 check_dsp(ctx);
13645 gen_helper_mulsaq_s_w_qh(v1_t, v2_t, t0, cpu_env);
13646 break;
13647 }
13648 }
13649 break;
13650#endif
13651 case OPC_ADDU_QB_DSP:
13652 switch (op2) {
13653 case OPC_MULEU_S_PH_QBL:
13654 check_dsp(ctx);
13655 gen_helper_muleu_s_ph_qbl(cpu_gpr[ret], v1_t, v2_t, cpu_env);
13656 break;
13657 case OPC_MULEU_S_PH_QBR:
13658 check_dsp(ctx);
13659 gen_helper_muleu_s_ph_qbr(cpu_gpr[ret], v1_t, v2_t, cpu_env);
13660 break;
13661 case OPC_MULQ_RS_PH:
13662 check_dsp(ctx);
13663 gen_helper_mulq_rs_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
13664 break;
13665 case OPC_MULEQ_S_W_PHL:
13666 check_dsp(ctx);
13667 gen_helper_muleq_s_w_phl(cpu_gpr[ret], v1_t, v2_t, cpu_env);
13668 break;
13669 case OPC_MULEQ_S_W_PHR:
13670 check_dsp(ctx);
13671 gen_helper_muleq_s_w_phr(cpu_gpr[ret], v1_t, v2_t, cpu_env);
13672 break;
13673 case OPC_MULQ_S_PH:
13674 check_dspr2(ctx);
13675 gen_helper_mulq_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
13676 break;
13677 }
13678 break;
13679#ifdef TARGET_MIPS64
13680 case OPC_ADDU_OB_DSP:
13681 switch (op2) {
13682 case OPC_MULEQ_S_PW_QHL:
13683 check_dsp(ctx);
13684 gen_helper_muleq_s_pw_qhl(cpu_gpr[ret], v1_t, v2_t, cpu_env);
13685 break;
13686 case OPC_MULEQ_S_PW_QHR:
13687 check_dsp(ctx);
13688 gen_helper_muleq_s_pw_qhr(cpu_gpr[ret], v1_t, v2_t, cpu_env);
13689 break;
13690 case OPC_MULEU_S_QH_OBL:
13691 check_dsp(ctx);
13692 gen_helper_muleu_s_qh_obl(cpu_gpr[ret], v1_t, v2_t, cpu_env);
13693 break;
13694 case OPC_MULEU_S_QH_OBR:
13695 check_dsp(ctx);
13696 gen_helper_muleu_s_qh_obr(cpu_gpr[ret], v1_t, v2_t, cpu_env);
13697 break;
13698 case OPC_MULQ_RS_QH:
13699 check_dsp(ctx);
13700 gen_helper_mulq_rs_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
13701 break;
13702 }
13703 break;
13704#endif
13705 }
13706
13707 tcg_temp_free_i32(t0);
13708 tcg_temp_free(v1_t);
13709 tcg_temp_free(v2_t);
13710
13711 (void)opn; /* avoid a compiler warning */
13712 MIPS_DEBUG("%s", opn);
13713
13714}
13715
Aurelien Jarnod75c1352013-01-01 18:02:22 +010013716static void gen_mipsdsp_bitinsn(DisasContext *ctx, uint32_t op1, uint32_t op2,
Jia Liu1cb66862012-10-24 22:17:09 +080013717 int ret, int val)
13718{
13719 const char *opn = "mipsdsp Bit/ Manipulation";
13720 int16_t imm;
13721 TCGv t0;
13722 TCGv val_t;
13723
13724 if (ret == 0) {
13725 /* Treat as NOP. */
13726 MIPS_DEBUG("NOP");
13727 return;
13728 }
13729
13730 t0 = tcg_temp_new();
13731 val_t = tcg_temp_new();
13732 gen_load_gpr(val_t, val);
13733
13734 switch (op1) {
13735 case OPC_ABSQ_S_PH_DSP:
13736 switch (op2) {
13737 case OPC_BITREV:
13738 check_dsp(ctx);
13739 gen_helper_bitrev(cpu_gpr[ret], val_t);
13740 break;
13741 case OPC_REPL_QB:
13742 check_dsp(ctx);
13743 {
13744 target_long result;
13745 imm = (ctx->opcode >> 16) & 0xFF;
13746 result = (uint32_t)imm << 24 |
13747 (uint32_t)imm << 16 |
13748 (uint32_t)imm << 8 |
13749 (uint32_t)imm;
13750 result = (int32_t)result;
13751 tcg_gen_movi_tl(cpu_gpr[ret], result);
13752 }
13753 break;
13754 case OPC_REPLV_QB:
13755 check_dsp(ctx);
13756 tcg_gen_ext8u_tl(cpu_gpr[ret], val_t);
13757 tcg_gen_shli_tl(t0, cpu_gpr[ret], 8);
13758 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
13759 tcg_gen_shli_tl(t0, cpu_gpr[ret], 16);
13760 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
13761 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
13762 break;
13763 case OPC_REPL_PH:
13764 check_dsp(ctx);
13765 {
13766 imm = (ctx->opcode >> 16) & 0x03FF;
Jovanovic, Petarc4aaba92012-12-11 15:06:35 +000013767 imm = (int16_t)(imm << 6) >> 6;
Jia Liu1cb66862012-10-24 22:17:09 +080013768 tcg_gen_movi_tl(cpu_gpr[ret], \
13769 (target_long)((int32_t)imm << 16 | \
Jovanovic, Petarc4aaba92012-12-11 15:06:35 +000013770 (uint16_t)imm));
Jia Liu1cb66862012-10-24 22:17:09 +080013771 }
13772 break;
13773 case OPC_REPLV_PH:
13774 check_dsp(ctx);
13775 tcg_gen_ext16u_tl(cpu_gpr[ret], val_t);
13776 tcg_gen_shli_tl(t0, cpu_gpr[ret], 16);
13777 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
13778 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
13779 break;
13780 }
13781 break;
13782#ifdef TARGET_MIPS64
13783 case OPC_ABSQ_S_QH_DSP:
13784 switch (op2) {
13785 case OPC_REPL_OB:
13786 check_dsp(ctx);
13787 {
13788 target_long temp;
13789
13790 imm = (ctx->opcode >> 16) & 0xFF;
13791 temp = ((uint64_t)imm << 8) | (uint64_t)imm;
13792 temp = (temp << 16) | temp;
13793 temp = (temp << 32) | temp;
13794 tcg_gen_movi_tl(cpu_gpr[ret], temp);
13795 break;
13796 }
13797 case OPC_REPL_PW:
13798 check_dsp(ctx);
13799 {
13800 target_long temp;
13801
13802 imm = (ctx->opcode >> 16) & 0x03FF;
13803 imm = (int16_t)(imm << 6) >> 6;
13804 temp = ((target_long)imm << 32) \
13805 | ((target_long)imm & 0xFFFFFFFF);
13806 tcg_gen_movi_tl(cpu_gpr[ret], temp);
13807 break;
13808 }
13809 case OPC_REPL_QH:
13810 check_dsp(ctx);
13811 {
13812 target_long temp;
13813
13814 imm = (ctx->opcode >> 16) & 0x03FF;
13815 imm = (int16_t)(imm << 6) >> 6;
13816
13817 temp = ((uint64_t)(uint16_t)imm << 48) |
13818 ((uint64_t)(uint16_t)imm << 32) |
13819 ((uint64_t)(uint16_t)imm << 16) |
13820 (uint64_t)(uint16_t)imm;
13821 tcg_gen_movi_tl(cpu_gpr[ret], temp);
13822 break;
13823 }
13824 case OPC_REPLV_OB:
13825 check_dsp(ctx);
13826 tcg_gen_ext8u_tl(cpu_gpr[ret], val_t);
13827 tcg_gen_shli_tl(t0, cpu_gpr[ret], 8);
13828 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
13829 tcg_gen_shli_tl(t0, cpu_gpr[ret], 16);
13830 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
13831 tcg_gen_shli_tl(t0, cpu_gpr[ret], 32);
13832 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
13833 break;
13834 case OPC_REPLV_PW:
13835 check_dsp(ctx);
13836 tcg_gen_ext32u_i64(cpu_gpr[ret], val_t);
13837 tcg_gen_shli_tl(t0, cpu_gpr[ret], 32);
13838 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
13839 break;
13840 case OPC_REPLV_QH:
13841 check_dsp(ctx);
13842 tcg_gen_ext16u_tl(cpu_gpr[ret], val_t);
13843 tcg_gen_shli_tl(t0, cpu_gpr[ret], 16);
13844 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
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 }
13849 break;
13850#endif
13851 }
13852 tcg_temp_free(t0);
13853 tcg_temp_free(val_t);
13854
13855 (void)opn; /* avoid a compiler warning */
13856 MIPS_DEBUG("%s", opn);
13857}
13858
Jia Liu26690562012-10-24 22:17:10 +080013859static void gen_mipsdsp_add_cmp_pick(DisasContext *ctx,
13860 uint32_t op1, uint32_t op2,
13861 int ret, int v1, int v2, int check_ret)
13862{
13863 const char *opn = "mipsdsp add compare pick";
Jia Liu26690562012-10-24 22:17:10 +080013864 TCGv t1;
13865 TCGv v1_t;
13866 TCGv v2_t;
13867
13868 if ((ret == 0) && (check_ret == 1)) {
13869 /* Treat as NOP. */
13870 MIPS_DEBUG("NOP");
13871 return;
13872 }
13873
Jia Liu26690562012-10-24 22:17:10 +080013874 t1 = tcg_temp_new();
13875 v1_t = tcg_temp_new();
13876 v2_t = tcg_temp_new();
13877
13878 gen_load_gpr(v1_t, v1);
13879 gen_load_gpr(v2_t, v2);
13880
13881 switch (op1) {
Jia Liu26690562012-10-24 22:17:10 +080013882 case OPC_CMPU_EQ_QB_DSP:
13883 switch (op2) {
13884 case OPC_CMPU_EQ_QB:
13885 check_dsp(ctx);
13886 gen_helper_cmpu_eq_qb(v1_t, v2_t, cpu_env);
13887 break;
13888 case OPC_CMPU_LT_QB:
13889 check_dsp(ctx);
13890 gen_helper_cmpu_lt_qb(v1_t, v2_t, cpu_env);
13891 break;
13892 case OPC_CMPU_LE_QB:
13893 check_dsp(ctx);
13894 gen_helper_cmpu_le_qb(v1_t, v2_t, cpu_env);
13895 break;
13896 case OPC_CMPGU_EQ_QB:
13897 check_dsp(ctx);
13898 gen_helper_cmpgu_eq_qb(cpu_gpr[ret], v1_t, v2_t);
13899 break;
13900 case OPC_CMPGU_LT_QB:
13901 check_dsp(ctx);
13902 gen_helper_cmpgu_lt_qb(cpu_gpr[ret], v1_t, v2_t);
13903 break;
13904 case OPC_CMPGU_LE_QB:
13905 check_dsp(ctx);
13906 gen_helper_cmpgu_le_qb(cpu_gpr[ret], v1_t, v2_t);
13907 break;
13908 case OPC_CMPGDU_EQ_QB:
13909 check_dspr2(ctx);
13910 gen_helper_cmpgu_eq_qb(t1, v1_t, v2_t);
13911 tcg_gen_mov_tl(cpu_gpr[ret], t1);
13912 tcg_gen_andi_tl(cpu_dspctrl, cpu_dspctrl, 0xF0FFFFFF);
13913 tcg_gen_shli_tl(t1, t1, 24);
13914 tcg_gen_or_tl(cpu_dspctrl, cpu_dspctrl, t1);
13915 break;
13916 case OPC_CMPGDU_LT_QB:
13917 check_dspr2(ctx);
13918 gen_helper_cmpgu_lt_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_LE_QB:
13925 check_dspr2(ctx);
13926 gen_helper_cmpgu_le_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_CMP_EQ_PH:
13933 check_dsp(ctx);
13934 gen_helper_cmp_eq_ph(v1_t, v2_t, cpu_env);
13935 break;
13936 case OPC_CMP_LT_PH:
13937 check_dsp(ctx);
13938 gen_helper_cmp_lt_ph(v1_t, v2_t, cpu_env);
13939 break;
13940 case OPC_CMP_LE_PH:
13941 check_dsp(ctx);
13942 gen_helper_cmp_le_ph(v1_t, v2_t, cpu_env);
13943 break;
13944 case OPC_PICK_QB:
13945 check_dsp(ctx);
13946 gen_helper_pick_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
13947 break;
13948 case OPC_PICK_PH:
13949 check_dsp(ctx);
13950 gen_helper_pick_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
13951 break;
13952 case OPC_PACKRL_PH:
13953 check_dsp(ctx);
13954 gen_helper_packrl_ph(cpu_gpr[ret], v1_t, v2_t);
13955 break;
13956 }
13957 break;
13958#ifdef TARGET_MIPS64
13959 case OPC_CMPU_EQ_OB_DSP:
13960 switch (op2) {
13961 case OPC_CMP_EQ_PW:
13962 check_dsp(ctx);
13963 gen_helper_cmp_eq_pw(v1_t, v2_t, cpu_env);
13964 break;
13965 case OPC_CMP_LT_PW:
13966 check_dsp(ctx);
13967 gen_helper_cmp_lt_pw(v1_t, v2_t, cpu_env);
13968 break;
13969 case OPC_CMP_LE_PW:
13970 check_dsp(ctx);
13971 gen_helper_cmp_le_pw(v1_t, v2_t, cpu_env);
13972 break;
13973 case OPC_CMP_EQ_QH:
13974 check_dsp(ctx);
13975 gen_helper_cmp_eq_qh(v1_t, v2_t, cpu_env);
13976 break;
13977 case OPC_CMP_LT_QH:
13978 check_dsp(ctx);
13979 gen_helper_cmp_lt_qh(v1_t, v2_t, cpu_env);
13980 break;
13981 case OPC_CMP_LE_QH:
13982 check_dsp(ctx);
13983 gen_helper_cmp_le_qh(v1_t, v2_t, cpu_env);
13984 break;
13985 case OPC_CMPGDU_EQ_OB:
13986 check_dspr2(ctx);
13987 gen_helper_cmpgdu_eq_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
13988 break;
13989 case OPC_CMPGDU_LT_OB:
13990 check_dspr2(ctx);
13991 gen_helper_cmpgdu_lt_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
13992 break;
13993 case OPC_CMPGDU_LE_OB:
13994 check_dspr2(ctx);
13995 gen_helper_cmpgdu_le_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
13996 break;
13997 case OPC_CMPGU_EQ_OB:
13998 check_dsp(ctx);
13999 gen_helper_cmpgu_eq_ob(cpu_gpr[ret], v1_t, v2_t);
14000 break;
14001 case OPC_CMPGU_LT_OB:
14002 check_dsp(ctx);
14003 gen_helper_cmpgu_lt_ob(cpu_gpr[ret], v1_t, v2_t);
14004 break;
14005 case OPC_CMPGU_LE_OB:
14006 check_dsp(ctx);
14007 gen_helper_cmpgu_le_ob(cpu_gpr[ret], v1_t, v2_t);
14008 break;
14009 case OPC_CMPU_EQ_OB:
14010 check_dsp(ctx);
14011 gen_helper_cmpu_eq_ob(v1_t, v2_t, cpu_env);
14012 break;
14013 case OPC_CMPU_LT_OB:
14014 check_dsp(ctx);
14015 gen_helper_cmpu_lt_ob(v1_t, v2_t, cpu_env);
14016 break;
14017 case OPC_CMPU_LE_OB:
14018 check_dsp(ctx);
14019 gen_helper_cmpu_le_ob(v1_t, v2_t, cpu_env);
14020 break;
14021 case OPC_PACKRL_PW:
14022 check_dsp(ctx);
14023 gen_helper_packrl_pw(cpu_gpr[ret], v1_t, v2_t);
14024 break;
14025 case OPC_PICK_OB:
14026 check_dsp(ctx);
14027 gen_helper_pick_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
14028 break;
14029 case OPC_PICK_PW:
14030 check_dsp(ctx);
14031 gen_helper_pick_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
14032 break;
14033 case OPC_PICK_QH:
14034 check_dsp(ctx);
14035 gen_helper_pick_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
14036 break;
14037 }
14038 break;
Aurelien Jarnodf6126a2013-01-01 18:02:24 +010014039#endif
14040 }
14041
14042 tcg_temp_free(t1);
14043 tcg_temp_free(v1_t);
14044 tcg_temp_free(v2_t);
14045
14046 (void)opn; /* avoid a compiler warning */
14047 MIPS_DEBUG("%s", opn);
14048}
14049
14050static void gen_mipsdsp_append(CPUMIPSState *env, DisasContext *ctx,
14051 uint32_t op1, int rt, int rs, int sa)
14052{
14053 const char *opn = "mipsdsp append/dappend";
14054 TCGv t0;
14055
14056 check_dspr2(ctx);
14057
14058 if (rt == 0) {
14059 /* Treat as NOP. */
14060 MIPS_DEBUG("NOP");
14061 return;
14062 }
14063
14064 t0 = tcg_temp_new();
14065 gen_load_gpr(t0, rs);
14066
14067 switch (op1) {
14068 case OPC_APPEND_DSP:
14069 switch (MASK_APPEND(ctx->opcode)) {
14070 case OPC_APPEND:
14071 if (sa != 0) {
14072 tcg_gen_deposit_tl(cpu_gpr[rt], t0, cpu_gpr[rt], sa, 32 - sa);
14073 }
14074 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
14075 break;
14076 case OPC_PREPEND:
14077 if (sa != 0) {
14078 tcg_gen_ext32u_tl(cpu_gpr[rt], cpu_gpr[rt]);
14079 tcg_gen_shri_tl(cpu_gpr[rt], cpu_gpr[rt], sa);
14080 tcg_gen_shli_tl(t0, t0, 32 - sa);
14081 tcg_gen_or_tl(cpu_gpr[rt], cpu_gpr[rt], t0);
14082 }
14083 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
14084 break;
14085 case OPC_BALIGN:
14086 sa &= 3;
14087 if (sa != 0 && sa != 2) {
14088 tcg_gen_shli_tl(cpu_gpr[rt], cpu_gpr[rt], 8 * sa);
14089 tcg_gen_ext32u_tl(t0, t0);
14090 tcg_gen_shri_tl(t0, t0, 8 * (4 - sa));
14091 tcg_gen_or_tl(cpu_gpr[rt], cpu_gpr[rt], t0);
14092 }
14093 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
14094 break;
14095 default: /* Invalid */
14096 MIPS_INVAL("MASK APPEND");
14097 generate_exception(ctx, EXCP_RI);
14098 break;
14099 }
14100 break;
14101#ifdef TARGET_MIPS64
Jia Liu26690562012-10-24 22:17:10 +080014102 case OPC_DAPPEND_DSP:
Aurelien Jarnodf6126a2013-01-01 18:02:24 +010014103 switch (MASK_DAPPEND(ctx->opcode)) {
Jia Liu26690562012-10-24 22:17:10 +080014104 case OPC_DAPPEND:
Aurelien Jarnodf6126a2013-01-01 18:02:24 +010014105 if (sa != 0) {
14106 tcg_gen_deposit_tl(cpu_gpr[rt], t0, cpu_gpr[rt], sa, 64 - sa);
14107 }
Jia Liu26690562012-10-24 22:17:10 +080014108 break;
14109 case OPC_PREPENDD:
Aurelien Jarnodf6126a2013-01-01 18:02:24 +010014110 tcg_gen_shri_tl(cpu_gpr[rt], cpu_gpr[rt], 0x20 | sa);
14111 tcg_gen_shli_tl(t0, t0, 64 - (0x20 | sa));
14112 tcg_gen_or_tl(cpu_gpr[rt], t0, t0);
Jia Liu26690562012-10-24 22:17:10 +080014113 break;
14114 case OPC_PREPENDW:
Aurelien Jarnodf6126a2013-01-01 18:02:24 +010014115 if (sa != 0) {
14116 tcg_gen_shri_tl(cpu_gpr[rt], cpu_gpr[rt], sa);
14117 tcg_gen_shli_tl(t0, t0, 64 - sa);
14118 tcg_gen_or_tl(cpu_gpr[rt], cpu_gpr[rt], t0);
14119 }
Jia Liu26690562012-10-24 22:17:10 +080014120 break;
14121 case OPC_DBALIGN:
Aurelien Jarnodf6126a2013-01-01 18:02:24 +010014122 sa &= 7;
14123 if (sa != 0 && sa != 2 && sa != 4) {
14124 tcg_gen_shli_tl(cpu_gpr[rt], cpu_gpr[rt], 8 * sa);
14125 tcg_gen_shri_tl(t0, t0, 8 * (8 - sa));
14126 tcg_gen_or_tl(cpu_gpr[rt], cpu_gpr[rt], t0);
14127 }
Jia Liu26690562012-10-24 22:17:10 +080014128 break;
14129 default: /* Invalid */
14130 MIPS_INVAL("MASK DAPPEND");
14131 generate_exception(ctx, EXCP_RI);
14132 break;
14133 }
14134 break;
14135#endif
14136 }
Aurelien Jarnodf6126a2013-01-01 18:02:24 +010014137 tcg_temp_free(t0);
Jia Liu26690562012-10-24 22:17:10 +080014138 (void)opn; /* avoid a compiler warning */
14139 MIPS_DEBUG("%s", opn);
14140}
14141
Jia Liub53371e2012-10-24 22:17:11 +080014142static void gen_mipsdsp_accinsn(DisasContext *ctx, uint32_t op1, uint32_t op2,
14143 int ret, int v1, int v2, int check_ret)
14144
14145{
14146 const char *opn = "mipsdsp accumulator";
14147 TCGv t0;
14148 TCGv t1;
14149 TCGv v1_t;
14150 TCGv v2_t;
14151 int16_t imm;
14152
14153 if ((ret == 0) && (check_ret == 1)) {
14154 /* Treat as NOP. */
14155 MIPS_DEBUG("NOP");
14156 return;
14157 }
14158
14159 t0 = tcg_temp_new();
14160 t1 = tcg_temp_new();
14161 v1_t = tcg_temp_new();
14162 v2_t = tcg_temp_new();
14163
14164 gen_load_gpr(v1_t, v1);
14165 gen_load_gpr(v2_t, v2);
14166
14167 switch (op1) {
14168 case OPC_EXTR_W_DSP:
14169 check_dsp(ctx);
14170 switch (op2) {
14171 case OPC_EXTR_W:
14172 tcg_gen_movi_tl(t0, v2);
14173 tcg_gen_movi_tl(t1, v1);
14174 gen_helper_extr_w(cpu_gpr[ret], t0, t1, cpu_env);
14175 break;
14176 case OPC_EXTR_R_W:
14177 tcg_gen_movi_tl(t0, v2);
14178 tcg_gen_movi_tl(t1, v1);
14179 gen_helper_extr_r_w(cpu_gpr[ret], t0, t1, cpu_env);
14180 break;
14181 case OPC_EXTR_RS_W:
14182 tcg_gen_movi_tl(t0, v2);
14183 tcg_gen_movi_tl(t1, v1);
14184 gen_helper_extr_rs_w(cpu_gpr[ret], t0, t1, cpu_env);
14185 break;
14186 case OPC_EXTR_S_H:
14187 tcg_gen_movi_tl(t0, v2);
14188 tcg_gen_movi_tl(t1, v1);
14189 gen_helper_extr_s_h(cpu_gpr[ret], t0, t1, cpu_env);
14190 break;
14191 case OPC_EXTRV_S_H:
14192 tcg_gen_movi_tl(t0, v2);
14193 gen_helper_extr_s_h(cpu_gpr[ret], t0, v1_t, cpu_env);
14194 break;
14195 case OPC_EXTRV_W:
14196 tcg_gen_movi_tl(t0, v2);
14197 gen_helper_extr_w(cpu_gpr[ret], t0, v1_t, cpu_env);
14198 break;
14199 case OPC_EXTRV_R_W:
14200 tcg_gen_movi_tl(t0, v2);
14201 gen_helper_extr_r_w(cpu_gpr[ret], t0, v1_t, cpu_env);
14202 break;
14203 case OPC_EXTRV_RS_W:
14204 tcg_gen_movi_tl(t0, v2);
14205 gen_helper_extr_rs_w(cpu_gpr[ret], t0, v1_t, cpu_env);
14206 break;
14207 case OPC_EXTP:
14208 tcg_gen_movi_tl(t0, v2);
14209 tcg_gen_movi_tl(t1, v1);
14210 gen_helper_extp(cpu_gpr[ret], t0, t1, cpu_env);
14211 break;
14212 case OPC_EXTPV:
14213 tcg_gen_movi_tl(t0, v2);
14214 gen_helper_extp(cpu_gpr[ret], t0, v1_t, cpu_env);
14215 break;
14216 case OPC_EXTPDP:
14217 tcg_gen_movi_tl(t0, v2);
14218 tcg_gen_movi_tl(t1, v1);
14219 gen_helper_extpdp(cpu_gpr[ret], t0, t1, cpu_env);
14220 break;
14221 case OPC_EXTPDPV:
14222 tcg_gen_movi_tl(t0, v2);
14223 gen_helper_extpdp(cpu_gpr[ret], t0, v1_t, cpu_env);
14224 break;
14225 case OPC_SHILO:
14226 imm = (ctx->opcode >> 20) & 0x3F;
14227 tcg_gen_movi_tl(t0, ret);
14228 tcg_gen_movi_tl(t1, imm);
14229 gen_helper_shilo(t0, t1, cpu_env);
14230 break;
14231 case OPC_SHILOV:
14232 tcg_gen_movi_tl(t0, ret);
14233 gen_helper_shilo(t0, v1_t, cpu_env);
14234 break;
14235 case OPC_MTHLIP:
14236 tcg_gen_movi_tl(t0, ret);
14237 gen_helper_mthlip(t0, v1_t, cpu_env);
14238 break;
14239 case OPC_WRDSP:
14240 imm = (ctx->opcode >> 11) & 0x3FF;
14241 tcg_gen_movi_tl(t0, imm);
14242 gen_helper_wrdsp(v1_t, t0, cpu_env);
14243 break;
14244 case OPC_RDDSP:
14245 imm = (ctx->opcode >> 16) & 0x03FF;
14246 tcg_gen_movi_tl(t0, imm);
14247 gen_helper_rddsp(cpu_gpr[ret], t0, cpu_env);
14248 break;
14249 }
14250 break;
14251#ifdef TARGET_MIPS64
14252 case OPC_DEXTR_W_DSP:
14253 check_dsp(ctx);
14254 switch (op2) {
14255 case OPC_DMTHLIP:
14256 tcg_gen_movi_tl(t0, ret);
14257 gen_helper_dmthlip(v1_t, t0, cpu_env);
14258 break;
14259 case OPC_DSHILO:
14260 {
14261 int shift = (ctx->opcode >> 19) & 0x7F;
14262 int ac = (ctx->opcode >> 11) & 0x03;
14263 tcg_gen_movi_tl(t0, shift);
14264 tcg_gen_movi_tl(t1, ac);
14265 gen_helper_dshilo(t0, t1, cpu_env);
14266 break;
14267 }
14268 case OPC_DSHILOV:
14269 {
14270 int ac = (ctx->opcode >> 11) & 0x03;
14271 tcg_gen_movi_tl(t0, ac);
14272 gen_helper_dshilo(v1_t, t0, cpu_env);
14273 break;
14274 }
14275 case OPC_DEXTP:
14276 tcg_gen_movi_tl(t0, v2);
14277 tcg_gen_movi_tl(t1, v1);
14278
14279 gen_helper_dextp(cpu_gpr[ret], t0, t1, cpu_env);
14280 break;
14281 case OPC_DEXTPV:
14282 tcg_gen_movi_tl(t0, v2);
14283 gen_helper_dextp(cpu_gpr[ret], t0, v1_t, cpu_env);
14284 break;
14285 case OPC_DEXTPDP:
14286 tcg_gen_movi_tl(t0, v2);
14287 tcg_gen_movi_tl(t1, v1);
14288 gen_helper_dextpdp(cpu_gpr[ret], t0, t1, cpu_env);
14289 break;
14290 case OPC_DEXTPDPV:
14291 tcg_gen_movi_tl(t0, v2);
14292 gen_helper_dextpdp(cpu_gpr[ret], t0, v1_t, cpu_env);
14293 break;
14294 case OPC_DEXTR_L:
14295 tcg_gen_movi_tl(t0, v2);
14296 tcg_gen_movi_tl(t1, v1);
14297 gen_helper_dextr_l(cpu_gpr[ret], t0, t1, cpu_env);
14298 break;
14299 case OPC_DEXTR_R_L:
14300 tcg_gen_movi_tl(t0, v2);
14301 tcg_gen_movi_tl(t1, v1);
14302 gen_helper_dextr_r_l(cpu_gpr[ret], t0, t1, cpu_env);
14303 break;
14304 case OPC_DEXTR_RS_L:
14305 tcg_gen_movi_tl(t0, v2);
14306 tcg_gen_movi_tl(t1, v1);
14307 gen_helper_dextr_rs_l(cpu_gpr[ret], t0, t1, cpu_env);
14308 break;
14309 case OPC_DEXTR_W:
14310 tcg_gen_movi_tl(t0, v2);
14311 tcg_gen_movi_tl(t1, v1);
14312 gen_helper_dextr_w(cpu_gpr[ret], t0, t1, cpu_env);
14313 break;
14314 case OPC_DEXTR_R_W:
14315 tcg_gen_movi_tl(t0, v2);
14316 tcg_gen_movi_tl(t1, v1);
14317 gen_helper_dextr_r_w(cpu_gpr[ret], t0, t1, cpu_env);
14318 break;
14319 case OPC_DEXTR_RS_W:
14320 tcg_gen_movi_tl(t0, v2);
14321 tcg_gen_movi_tl(t1, v1);
14322 gen_helper_dextr_rs_w(cpu_gpr[ret], t0, t1, cpu_env);
14323 break;
14324 case OPC_DEXTR_S_H:
14325 tcg_gen_movi_tl(t0, v2);
14326 tcg_gen_movi_tl(t1, v1);
14327 gen_helper_dextr_s_h(cpu_gpr[ret], t0, t1, cpu_env);
14328 break;
14329 case OPC_DEXTRV_S_H:
14330 tcg_gen_movi_tl(t0, v2);
14331 tcg_gen_movi_tl(t1, v1);
14332 gen_helper_dextr_s_h(cpu_gpr[ret], t0, t1, cpu_env);
14333 break;
14334 case OPC_DEXTRV_L:
14335 tcg_gen_movi_tl(t0, v2);
14336 gen_helper_dextr_l(cpu_gpr[ret], t0, v1_t, cpu_env);
14337 break;
14338 case OPC_DEXTRV_R_L:
14339 tcg_gen_movi_tl(t0, v2);
14340 gen_helper_dextr_r_l(cpu_gpr[ret], t0, v1_t, cpu_env);
14341 break;
14342 case OPC_DEXTRV_RS_L:
14343 tcg_gen_movi_tl(t0, v2);
14344 gen_helper_dextr_rs_l(cpu_gpr[ret], t0, v1_t, cpu_env);
14345 break;
14346 case OPC_DEXTRV_W:
14347 tcg_gen_movi_tl(t0, v2);
14348 gen_helper_dextr_w(cpu_gpr[ret], t0, v1_t, cpu_env);
14349 break;
14350 case OPC_DEXTRV_R_W:
14351 tcg_gen_movi_tl(t0, v2);
14352 gen_helper_dextr_r_w(cpu_gpr[ret], t0, v1_t, cpu_env);
14353 break;
14354 case OPC_DEXTRV_RS_W:
14355 tcg_gen_movi_tl(t0, v2);
14356 gen_helper_dextr_rs_w(cpu_gpr[ret], t0, v1_t, cpu_env);
14357 break;
14358 }
14359 break;
14360#endif
14361 }
14362
14363 tcg_temp_free(t0);
14364 tcg_temp_free(t1);
14365 tcg_temp_free(v1_t);
14366 tcg_temp_free(v2_t);
14367
14368 (void)opn; /* avoid a compiler warning */
14369 MIPS_DEBUG("%s", opn);
14370}
14371
Jia Liu9b1a1d62012-10-24 22:17:05 +080014372/* End MIPSDSP functions. */
14373
Andreas Färber7db13fa2012-03-14 01:38:22 +010014374static void decode_opc (CPUMIPSState *env, DisasContext *ctx, int *is_branch)
bellard6af0bf92005-07-02 14:58:51 +000014375{
14376 int32_t offset;
14377 int rs, rt, rd, sa;
ths7a387ff2006-12-06 20:17:30 +000014378 uint32_t op, op1, op2;
bellard6af0bf92005-07-02 14:58:51 +000014379 int16_t imm;
14380
bellardd7963212006-06-26 20:02:45 +000014381 /* make sure instructions are on a word boundary */
14382 if (ctx->pc & 0x3) {
thscbeb0852007-04-07 01:11:15 +000014383 env->CP0_BadVAddr = ctx->pc;
bellardd7963212006-06-26 20:02:45 +000014384 generate_exception(ctx, EXCP_AdEL);
14385 return;
14386 }
14387
ths8e9ade62008-05-22 17:46:10 +000014388 /* Handle blikely not taken case */
Nathan Froydc9602062009-12-08 08:06:27 -080014389 if ((ctx->hflags & MIPS_HFLAG_BMASK_BASE) == MIPS_HFLAG_BL) {
ths8e9ade62008-05-22 17:46:10 +000014390 int l1 = gen_new_label();
14391
ths3594c772007-02-20 23:37:21 +000014392 MIPS_DEBUG("blikely condition (" TARGET_FMT_lx ")", ctx->pc + 4);
aurel321ba74fb2009-03-29 01:18:52 +000014393 tcg_gen_brcondi_tl(TCG_COND_NE, bcond, 0, l1);
aurel3241db4602009-03-29 01:28:29 +000014394 tcg_gen_movi_i32(hflags, ctx->hflags & ~MIPS_HFLAG_BMASK);
ths5a5012e2007-05-07 13:55:33 +000014395 gen_goto_tb(ctx, 1, ctx->pc + 4);
14396 gen_set_label(l1);
bellard6af0bf92005-07-02 14:58:51 +000014397 }
Aurelien Jarno618b0fe2009-09-28 13:03:30 +020014398
Richard Hendersonfdefe512012-09-24 14:55:47 -070014399 if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP | CPU_LOG_TB_OP_OPT))) {
Aurelien Jarno618b0fe2009-09-28 13:03:30 +020014400 tcg_gen_debug_insn_start(ctx->pc);
Richard Hendersonfdefe512012-09-24 14:55:47 -070014401 }
Aurelien Jarno618b0fe2009-09-28 13:03:30 +020014402
ths7a387ff2006-12-06 20:17:30 +000014403 op = MASK_OP_MAJOR(ctx->opcode);
14404 rs = (ctx->opcode >> 21) & 0x1f;
14405 rt = (ctx->opcode >> 16) & 0x1f;
14406 rd = (ctx->opcode >> 11) & 0x1f;
14407 sa = (ctx->opcode >> 6) & 0x1f;
bellard6af0bf92005-07-02 14:58:51 +000014408 imm = (int16_t)ctx->opcode;
14409 switch (op) {
ths7a387ff2006-12-06 20:17:30 +000014410 case OPC_SPECIAL:
14411 op1 = MASK_SPECIAL(ctx->opcode);
bellard6af0bf92005-07-02 14:58:51 +000014412 switch (op1) {
aurel32324d9e32009-04-11 18:42:17 +000014413 case OPC_SLL: /* Shift with immediate */
14414 case OPC_SRA:
Aurelien Jarnod75c1352013-01-01 18:02:22 +010014415 gen_shift_imm(ctx, op1, rd, rt, sa);
bellard6af0bf92005-07-02 14:58:51 +000014416 break;
Nathan Froydea63e2c2009-12-08 08:06:24 -080014417 case OPC_SRL:
14418 switch ((ctx->opcode >> 21) & 0x1f) {
14419 case 1:
14420 /* rotr is decoded as srl on non-R2 CPUs */
Aurelien Jarnod75c1352013-01-01 18:02:22 +010014421 if (ctx->insn_flags & ISA_MIPS32R2) {
Nathan Froydea63e2c2009-12-08 08:06:24 -080014422 op1 = OPC_ROTR;
14423 }
14424 /* Fallthrough */
14425 case 0:
Aurelien Jarnod75c1352013-01-01 18:02:22 +010014426 gen_shift_imm(ctx, op1, rd, rt, sa);
Nathan Froydea63e2c2009-12-08 08:06:24 -080014427 break;
14428 default:
14429 generate_exception(ctx, EXCP_RI);
14430 break;
14431 }
14432 break;
aurel32460f00c2009-04-08 21:48:02 +000014433 case OPC_MOVN: /* Conditional move */
14434 case OPC_MOVZ:
Aurelien Jarnod75c1352013-01-01 18:02:22 +010014435 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32 |
Aurelien Jarnoaa8f4002010-06-19 11:11:10 +020014436 INSN_LOONGSON2E | INSN_LOONGSON2F);
Aurelien Jarnod75c1352013-01-01 18:02:22 +010014437 gen_cond_move(ctx, op1, rd, rs, rt);
aurel32460f00c2009-04-08 21:48:02 +000014438 break;
14439 case OPC_ADD ... OPC_SUBU:
Aurelien Jarnod75c1352013-01-01 18:02:22 +010014440 gen_arith(ctx, op1, rd, rs, rt);
bellard6af0bf92005-07-02 14:58:51 +000014441 break;
aurel32460f00c2009-04-08 21:48:02 +000014442 case OPC_SLLV: /* Shifts */
aurel32460f00c2009-04-08 21:48:02 +000014443 case OPC_SRAV:
Aurelien Jarnod75c1352013-01-01 18:02:22 +010014444 gen_shift(ctx, op1, rd, rs, rt);
aurel32460f00c2009-04-08 21:48:02 +000014445 break;
Nathan Froydea63e2c2009-12-08 08:06:24 -080014446 case OPC_SRLV:
14447 switch ((ctx->opcode >> 6) & 0x1f) {
14448 case 1:
14449 /* rotrv is decoded as srlv on non-R2 CPUs */
Aurelien Jarnod75c1352013-01-01 18:02:22 +010014450 if (ctx->insn_flags & ISA_MIPS32R2) {
Nathan Froydea63e2c2009-12-08 08:06:24 -080014451 op1 = OPC_ROTRV;
14452 }
14453 /* Fallthrough */
14454 case 0:
Aurelien Jarnod75c1352013-01-01 18:02:22 +010014455 gen_shift(ctx, op1, rd, rs, rt);
Nathan Froydea63e2c2009-12-08 08:06:24 -080014456 break;
14457 default:
14458 generate_exception(ctx, EXCP_RI);
14459 break;
14460 }
14461 break;
aurel32460f00c2009-04-08 21:48:02 +000014462 case OPC_SLT: /* Set on less than */
14463 case OPC_SLTU:
Aurelien Jarnod75c1352013-01-01 18:02:22 +010014464 gen_slt(ctx, op1, rd, rs, rt);
aurel32460f00c2009-04-08 21:48:02 +000014465 break;
14466 case OPC_AND: /* Logic*/
14467 case OPC_OR:
14468 case OPC_NOR:
14469 case OPC_XOR:
Aurelien Jarnod75c1352013-01-01 18:02:22 +010014470 gen_logic(ctx, op1, rd, rs, rt);
aurel32460f00c2009-04-08 21:48:02 +000014471 break;
ths7a387ff2006-12-06 20:17:30 +000014472 case OPC_MULT ... OPC_DIVU:
thse9c71dd2007-12-25 20:46:56 +000014473 if (sa) {
Aurelien Jarnod75c1352013-01-01 18:02:22 +010014474 check_insn(ctx, INSN_VR54XX);
thse9c71dd2007-12-25 20:46:56 +000014475 op1 = MASK_MUL_VR54XX(ctx->opcode);
14476 gen_mul_vr54xx(ctx, op1, rd, rs, rt);
14477 } else
14478 gen_muldiv(ctx, op1, rs, rt);
bellard6af0bf92005-07-02 14:58:51 +000014479 break;
ths7a387ff2006-12-06 20:17:30 +000014480 case OPC_JR ... OPC_JALR:
Nathan Froyd7dca4ad2009-12-08 08:06:25 -080014481 gen_compute_branch(ctx, op1, 4, rs, rd, sa);
Nathan Froydc9602062009-12-08 08:06:27 -080014482 *is_branch = 1;
14483 break;
ths7a387ff2006-12-06 20:17:30 +000014484 case OPC_TGE ... OPC_TEQ: /* Traps */
14485 case OPC_TNE:
14486 gen_trap(ctx, op1, rs, rt, -1);
bellard6af0bf92005-07-02 14:58:51 +000014487 break;
ths7a387ff2006-12-06 20:17:30 +000014488 case OPC_MFHI: /* Move from HI/LO */
14489 case OPC_MFLO:
14490 gen_HILO(ctx, op1, rd);
bellard6af0bf92005-07-02 14:58:51 +000014491 break;
ths7a387ff2006-12-06 20:17:30 +000014492 case OPC_MTHI:
14493 case OPC_MTLO: /* Move to HI/LO */
14494 gen_HILO(ctx, op1, rs);
bellard6af0bf92005-07-02 14:58:51 +000014495 break;
thsb48cfdf2007-04-11 02:24:14 +000014496 case OPC_PMON: /* Pmon entry point, also R4010 selsl */
14497#ifdef MIPS_STRICT_STANDARD
14498 MIPS_INVAL("PMON / selsl");
14499 generate_exception(ctx, EXCP_RI);
14500#else
Blue Swirl895c2d02012-09-02 14:52:59 +000014501 gen_helper_0e0i(pmon, sa);
thsb48cfdf2007-04-11 02:24:14 +000014502#endif
ths7a387ff2006-12-06 20:17:30 +000014503 break;
14504 case OPC_SYSCALL:
bellard6af0bf92005-07-02 14:58:51 +000014505 generate_exception(ctx, EXCP_SYSCALL);
pbrook8e0f9502009-04-16 10:56:43 +000014506 ctx->bstate = BS_STOP;
bellard6af0bf92005-07-02 14:58:51 +000014507 break;
ths7a387ff2006-12-06 20:17:30 +000014508 case OPC_BREAK:
bellard6af0bf92005-07-02 14:58:51 +000014509 generate_exception(ctx, EXCP_BREAK);
14510 break;
thsb48cfdf2007-04-11 02:24:14 +000014511 case OPC_SPIM:
14512#ifdef MIPS_STRICT_STANDARD
14513 MIPS_INVAL("SPIM");
14514 generate_exception(ctx, EXCP_RI);
14515#else
ths7a387ff2006-12-06 20:17:30 +000014516 /* Implemented as RI exception for now. */
14517 MIPS_INVAL("spim (unofficial)");
14518 generate_exception(ctx, EXCP_RI);
thsb48cfdf2007-04-11 02:24:14 +000014519#endif
bellard6af0bf92005-07-02 14:58:51 +000014520 break;
ths7a387ff2006-12-06 20:17:30 +000014521 case OPC_SYNC:
thsead93602007-09-06 00:18:15 +000014522 /* Treat as NOP. */
bellard6af0bf92005-07-02 14:58:51 +000014523 break;
bellard4ad40f32005-12-05 19:59:36 +000014524
ths7a387ff2006-12-06 20:17:30 +000014525 case OPC_MOVCI:
Aurelien Jarnod75c1352013-01-01 18:02:22 +010014526 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32);
ths36d23952007-02-28 22:37:42 +000014527 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
ths5e755512007-05-29 16:52:57 +000014528 check_cp1_enabled(ctx);
ths36d23952007-02-28 22:37:42 +000014529 gen_movci(ctx, rd, rs, (ctx->opcode >> 18) & 0x7,
14530 (ctx->opcode >> 16) & 1);
14531 } else {
thse397ee32007-03-23 00:43:28 +000014532 generate_exception_err(ctx, EXCP_CpU, 1);
ths36d23952007-02-28 22:37:42 +000014533 }
bellard4ad40f32005-12-05 19:59:36 +000014534 break;
14535
thsd26bc212007-11-08 18:05:37 +000014536#if defined(TARGET_MIPS64)
ths7a387ff2006-12-06 20:17:30 +000014537 /* MIPS64 specific opcodes */
14538 case OPC_DSLL:
aurel32324d9e32009-04-11 18:42:17 +000014539 case OPC_DSRA:
ths7a387ff2006-12-06 20:17:30 +000014540 case OPC_DSLL32:
aurel32324d9e32009-04-11 18:42:17 +000014541 case OPC_DSRA32:
Aurelien Jarnod75c1352013-01-01 18:02:22 +010014542 check_insn(ctx, ISA_MIPS3);
thse189e742007-09-24 12:48:00 +000014543 check_mips_64(ctx);
Aurelien Jarnod75c1352013-01-01 18:02:22 +010014544 gen_shift_imm(ctx, op1, rd, rt, sa);
ths7a387ff2006-12-06 20:17:30 +000014545 break;
Nathan Froydea63e2c2009-12-08 08:06:24 -080014546 case OPC_DSRL:
14547 switch ((ctx->opcode >> 21) & 0x1f) {
14548 case 1:
14549 /* drotr is decoded as dsrl on non-R2 CPUs */
Aurelien Jarnod75c1352013-01-01 18:02:22 +010014550 if (ctx->insn_flags & ISA_MIPS32R2) {
Nathan Froydea63e2c2009-12-08 08:06:24 -080014551 op1 = OPC_DROTR;
14552 }
14553 /* Fallthrough */
14554 case 0:
Aurelien Jarnod75c1352013-01-01 18:02:22 +010014555 check_insn(ctx, ISA_MIPS3);
Nathan Froydea63e2c2009-12-08 08:06:24 -080014556 check_mips_64(ctx);
Aurelien Jarnod75c1352013-01-01 18:02:22 +010014557 gen_shift_imm(ctx, op1, rd, rt, sa);
Nathan Froydea63e2c2009-12-08 08:06:24 -080014558 break;
14559 default:
14560 generate_exception(ctx, EXCP_RI);
14561 break;
14562 }
14563 break;
14564 case OPC_DSRL32:
14565 switch ((ctx->opcode >> 21) & 0x1f) {
14566 case 1:
14567 /* drotr32 is decoded as dsrl32 on non-R2 CPUs */
Aurelien Jarnod75c1352013-01-01 18:02:22 +010014568 if (ctx->insn_flags & ISA_MIPS32R2) {
Nathan Froydea63e2c2009-12-08 08:06:24 -080014569 op1 = OPC_DROTR32;
14570 }
14571 /* Fallthrough */
14572 case 0:
Aurelien Jarnod75c1352013-01-01 18:02:22 +010014573 check_insn(ctx, ISA_MIPS3);
Nathan Froydea63e2c2009-12-08 08:06:24 -080014574 check_mips_64(ctx);
Aurelien Jarnod75c1352013-01-01 18:02:22 +010014575 gen_shift_imm(ctx, op1, rd, rt, sa);
Nathan Froydea63e2c2009-12-08 08:06:24 -080014576 break;
14577 default:
14578 generate_exception(ctx, EXCP_RI);
14579 break;
14580 }
14581 break;
ths7a387ff2006-12-06 20:17:30 +000014582 case OPC_DADD ... OPC_DSUBU:
Aurelien Jarnod75c1352013-01-01 18:02:22 +010014583 check_insn(ctx, ISA_MIPS3);
thse189e742007-09-24 12:48:00 +000014584 check_mips_64(ctx);
Aurelien Jarnod75c1352013-01-01 18:02:22 +010014585 gen_arith(ctx, op1, rd, rs, rt);
ths7a387ff2006-12-06 20:17:30 +000014586 break;
aurel32460f00c2009-04-08 21:48:02 +000014587 case OPC_DSLLV:
14588 case OPC_DSRAV:
Aurelien Jarnod75c1352013-01-01 18:02:22 +010014589 check_insn(ctx, ISA_MIPS3);
aurel32460f00c2009-04-08 21:48:02 +000014590 check_mips_64(ctx);
Aurelien Jarnod75c1352013-01-01 18:02:22 +010014591 gen_shift(ctx, op1, rd, rs, rt);
aurel32460f00c2009-04-08 21:48:02 +000014592 break;
Nathan Froydea63e2c2009-12-08 08:06:24 -080014593 case OPC_DSRLV:
14594 switch ((ctx->opcode >> 6) & 0x1f) {
14595 case 1:
14596 /* drotrv is decoded as dsrlv on non-R2 CPUs */
Aurelien Jarnod75c1352013-01-01 18:02:22 +010014597 if (ctx->insn_flags & ISA_MIPS32R2) {
Nathan Froydea63e2c2009-12-08 08:06:24 -080014598 op1 = OPC_DROTRV;
14599 }
14600 /* Fallthrough */
14601 case 0:
Aurelien Jarnod75c1352013-01-01 18:02:22 +010014602 check_insn(ctx, ISA_MIPS3);
Nathan Froydea63e2c2009-12-08 08:06:24 -080014603 check_mips_64(ctx);
Aurelien Jarnod75c1352013-01-01 18:02:22 +010014604 gen_shift(ctx, op1, rd, rs, rt);
Nathan Froydea63e2c2009-12-08 08:06:24 -080014605 break;
14606 default:
14607 generate_exception(ctx, EXCP_RI);
14608 break;
14609 }
14610 break;
ths7a387ff2006-12-06 20:17:30 +000014611 case OPC_DMULT ... OPC_DDIVU:
Aurelien Jarnod75c1352013-01-01 18:02:22 +010014612 check_insn(ctx, ISA_MIPS3);
thse189e742007-09-24 12:48:00 +000014613 check_mips_64(ctx);
ths7a387ff2006-12-06 20:17:30 +000014614 gen_muldiv(ctx, op1, rs, rt);
14615 break;
bellard6af0bf92005-07-02 14:58:51 +000014616#endif
14617 default: /* Invalid */
14618 MIPS_INVAL("special");
14619 generate_exception(ctx, EXCP_RI);
14620 break;
14621 }
14622 break;
ths7a387ff2006-12-06 20:17:30 +000014623 case OPC_SPECIAL2:
14624 op1 = MASK_SPECIAL2(ctx->opcode);
bellard6af0bf92005-07-02 14:58:51 +000014625 switch (op1) {
ths7a387ff2006-12-06 20:17:30 +000014626 case OPC_MADD ... OPC_MADDU: /* Multiply and add/sub */
14627 case OPC_MSUB ... OPC_MSUBU:
Aurelien Jarnod75c1352013-01-01 18:02:22 +010014628 check_insn(ctx, ISA_MIPS32);
ths7a387ff2006-12-06 20:17:30 +000014629 gen_muldiv(ctx, op1, rs, rt);
bellard6af0bf92005-07-02 14:58:51 +000014630 break;
ths7a387ff2006-12-06 20:17:30 +000014631 case OPC_MUL:
Aurelien Jarnod75c1352013-01-01 18:02:22 +010014632 gen_arith(ctx, op1, rd, rs, rt);
bellard6af0bf92005-07-02 14:58:51 +000014633 break;
aurel3220e1fb522009-03-29 01:18:16 +000014634 case OPC_CLO:
14635 case OPC_CLZ:
Aurelien Jarnod75c1352013-01-01 18:02:22 +010014636 check_insn(ctx, ISA_MIPS32);
ths7a387ff2006-12-06 20:17:30 +000014637 gen_cl(ctx, op1, rd, rs);
bellard6af0bf92005-07-02 14:58:51 +000014638 break;
ths7a387ff2006-12-06 20:17:30 +000014639 case OPC_SDBBP:
bellard6af0bf92005-07-02 14:58:51 +000014640 /* XXX: not clear which exception should be raised
14641 * when in debug mode...
14642 */
Aurelien Jarnod75c1352013-01-01 18:02:22 +010014643 check_insn(ctx, ISA_MIPS32);
bellard6af0bf92005-07-02 14:58:51 +000014644 if (!(ctx->hflags & MIPS_HFLAG_DM)) {
14645 generate_exception(ctx, EXCP_DBp);
14646 } else {
14647 generate_exception(ctx, EXCP_DBp);
14648 }
thsead93602007-09-06 00:18:15 +000014649 /* Treat as NOP. */
bellard6af0bf92005-07-02 14:58:51 +000014650 break;
Aurelien Jarno161f85e2010-06-18 19:32:43 +020014651 case OPC_DIV_G_2F:
14652 case OPC_DIVU_G_2F:
14653 case OPC_MULT_G_2F:
14654 case OPC_MULTU_G_2F:
14655 case OPC_MOD_G_2F:
14656 case OPC_MODU_G_2F:
Aurelien Jarnod75c1352013-01-01 18:02:22 +010014657 check_insn(ctx, INSN_LOONGSON2F);
Aurelien Jarno161f85e2010-06-18 19:32:43 +020014658 gen_loongson_integer(ctx, op1, rd, rs, rt);
14659 break;
thsd26bc212007-11-08 18:05:37 +000014660#if defined(TARGET_MIPS64)
aurel3220e1fb522009-03-29 01:18:16 +000014661 case OPC_DCLO:
14662 case OPC_DCLZ:
Aurelien Jarnod75c1352013-01-01 18:02:22 +010014663 check_insn(ctx, ISA_MIPS64);
thse189e742007-09-24 12:48:00 +000014664 check_mips_64(ctx);
ths7a387ff2006-12-06 20:17:30 +000014665 gen_cl(ctx, op1, rd, rs);
14666 break;
Aurelien Jarno161f85e2010-06-18 19:32:43 +020014667 case OPC_DMULT_G_2F:
14668 case OPC_DMULTU_G_2F:
14669 case OPC_DDIV_G_2F:
14670 case OPC_DDIVU_G_2F:
14671 case OPC_DMOD_G_2F:
14672 case OPC_DMODU_G_2F:
Aurelien Jarnod75c1352013-01-01 18:02:22 +010014673 check_insn(ctx, INSN_LOONGSON2F);
Aurelien Jarno161f85e2010-06-18 19:32:43 +020014674 gen_loongson_integer(ctx, op1, rd, rs, rt);
14675 break;
ths7a387ff2006-12-06 20:17:30 +000014676#endif
bellard6af0bf92005-07-02 14:58:51 +000014677 default: /* Invalid */
14678 MIPS_INVAL("special2");
14679 generate_exception(ctx, EXCP_RI);
14680 break;
14681 }
14682 break;
ths7a387ff2006-12-06 20:17:30 +000014683 case OPC_SPECIAL3:
ths2b0233a2008-06-12 12:42:35 +000014684 op1 = MASK_SPECIAL3(ctx->opcode);
14685 switch (op1) {
14686 case OPC_EXT:
14687 case OPC_INS:
Aurelien Jarnod75c1352013-01-01 18:02:22 +010014688 check_insn(ctx, ISA_MIPS32R2);
ths2b0233a2008-06-12 12:42:35 +000014689 gen_bitops(ctx, op1, rt, rs, sa, rd);
14690 break;
14691 case OPC_BSHFL:
Aurelien Jarnod75c1352013-01-01 18:02:22 +010014692 check_insn(ctx, ISA_MIPS32R2);
ths2b0233a2008-06-12 12:42:35 +000014693 op2 = MASK_BSHFL(ctx->opcode);
aurel3249bcf332008-11-11 11:47:06 +000014694 gen_bshfl(ctx, op2, rt, rd);
ths1579a722007-04-05 23:16:25 +000014695 break;
14696 case OPC_RDHWR:
Aurelien Jarnod75c1352013-01-01 18:02:22 +010014697 gen_rdhwr(ctx, rt, rd);
ths7a387ff2006-12-06 20:17:30 +000014698 break;
thsead93602007-09-06 00:18:15 +000014699 case OPC_FORK:
Aurelien Jarnod75c1352013-01-01 18:02:22 +010014700 check_insn(ctx, ASE_MT);
ths6c5c1e22008-06-24 15:12:27 +000014701 {
aurel3235fbce22009-04-08 21:47:55 +000014702 TCGv t0 = tcg_temp_new();
14703 TCGv t1 = tcg_temp_new();
ths6c5c1e22008-06-24 15:12:27 +000014704
14705 gen_load_gpr(t0, rt);
14706 gen_load_gpr(t1, rs);
pbrooka7812ae2008-11-17 14:43:54 +000014707 gen_helper_fork(t0, t1);
ths6c5c1e22008-06-24 15:12:27 +000014708 tcg_temp_free(t0);
14709 tcg_temp_free(t1);
14710 }
thsead93602007-09-06 00:18:15 +000014711 break;
14712 case OPC_YIELD:
Aurelien Jarnod75c1352013-01-01 18:02:22 +010014713 check_insn(ctx, ASE_MT);
ths6c5c1e22008-06-24 15:12:27 +000014714 {
aurel3235fbce22009-04-08 21:47:55 +000014715 TCGv t0 = tcg_temp_new();
ths6c5c1e22008-06-24 15:12:27 +000014716
aurel3235fbce22009-04-08 21:47:55 +000014717 save_cpu_state(ctx, 1);
ths6c5c1e22008-06-24 15:12:27 +000014718 gen_load_gpr(t0, rs);
Blue Swirl895c2d02012-09-02 14:52:59 +000014719 gen_helper_yield(t0, cpu_env, t0);
ths6c5c1e22008-06-24 15:12:27 +000014720 gen_store_gpr(t0, rd);
14721 tcg_temp_free(t0);
14722 }
thsead93602007-09-06 00:18:15 +000014723 break;
Aurelien Jarno161f85e2010-06-18 19:32:43 +020014724 case OPC_DIV_G_2E ... OPC_DIVU_G_2E:
Aurelien Jarno161f85e2010-06-18 19:32:43 +020014725 case OPC_MOD_G_2E ... OPC_MODU_G_2E:
Jia Liu461c08d2012-10-24 22:17:06 +080014726 case OPC_MULT_G_2E ... OPC_MULTU_G_2E:
14727 /* OPC_MULT_G_2E, OPC_ADDUH_QB_DSP, OPC_MUL_PH_DSP have
14728 * the same mask and op1. */
Aurelien Jarnod75c1352013-01-01 18:02:22 +010014729 if ((ctx->insn_flags & ASE_DSPR2) && (op1 == OPC_MULT_G_2E)) {
Jia Liu461c08d2012-10-24 22:17:06 +080014730 op2 = MASK_ADDUH_QB(ctx->opcode);
14731 switch (op2) {
14732 case OPC_ADDUH_QB:
14733 case OPC_ADDUH_R_QB:
14734 case OPC_ADDQH_PH:
14735 case OPC_ADDQH_R_PH:
14736 case OPC_ADDQH_W:
14737 case OPC_ADDQH_R_W:
14738 case OPC_SUBUH_QB:
14739 case OPC_SUBUH_R_QB:
14740 case OPC_SUBQH_PH:
14741 case OPC_SUBQH_R_PH:
14742 case OPC_SUBQH_W:
14743 case OPC_SUBQH_R_W:
14744 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
14745 break;
Jia Liua22260a2012-10-24 22:17:08 +080014746 case OPC_MUL_PH:
14747 case OPC_MUL_S_PH:
14748 case OPC_MULQ_S_W:
14749 case OPC_MULQ_RS_W:
14750 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 1);
14751 break;
Jia Liu461c08d2012-10-24 22:17:06 +080014752 default:
14753 MIPS_INVAL("MASK ADDUH.QB");
14754 generate_exception(ctx, EXCP_RI);
14755 break;
14756 }
Aurelien Jarnod75c1352013-01-01 18:02:22 +010014757 } else if (ctx->insn_flags & INSN_LOONGSON2E) {
Jia Liu461c08d2012-10-24 22:17:06 +080014758 gen_loongson_integer(ctx, op1, rd, rs, rt);
14759 } else {
14760 generate_exception(ctx, EXCP_RI);
14761 }
Aurelien Jarno161f85e2010-06-18 19:32:43 +020014762 break;
Jia Liu9b1a1d62012-10-24 22:17:05 +080014763 case OPC_LX_DSP:
14764 op2 = MASK_LX(ctx->opcode);
14765 switch (op2) {
14766#if defined(TARGET_MIPS64)
14767 case OPC_LDX:
14768#endif
14769 case OPC_LBUX:
14770 case OPC_LHX:
14771 case OPC_LWX:
Aurelien Jarnod75c1352013-01-01 18:02:22 +010014772 gen_mipsdsp_ld(ctx, op2, rd, rs, rt);
Jia Liu9b1a1d62012-10-24 22:17:05 +080014773 break;
14774 default: /* Invalid */
14775 MIPS_INVAL("MASK LX");
14776 generate_exception(ctx, EXCP_RI);
14777 break;
14778 }
14779 break;
Jia Liu461c08d2012-10-24 22:17:06 +080014780 case OPC_ABSQ_S_PH_DSP:
14781 op2 = MASK_ABSQ_S_PH(ctx->opcode);
14782 switch (op2) {
14783 case OPC_ABSQ_S_QB:
14784 case OPC_ABSQ_S_PH:
14785 case OPC_ABSQ_S_W:
14786 case OPC_PRECEQ_W_PHL:
14787 case OPC_PRECEQ_W_PHR:
14788 case OPC_PRECEQU_PH_QBL:
14789 case OPC_PRECEQU_PH_QBR:
14790 case OPC_PRECEQU_PH_QBLA:
14791 case OPC_PRECEQU_PH_QBRA:
14792 case OPC_PRECEU_PH_QBL:
14793 case OPC_PRECEU_PH_QBR:
14794 case OPC_PRECEU_PH_QBLA:
14795 case OPC_PRECEU_PH_QBRA:
14796 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
14797 break;
Jia Liu1cb66862012-10-24 22:17:09 +080014798 case OPC_BITREV:
14799 case OPC_REPL_QB:
14800 case OPC_REPLV_QB:
14801 case OPC_REPL_PH:
14802 case OPC_REPLV_PH:
Aurelien Jarnod75c1352013-01-01 18:02:22 +010014803 gen_mipsdsp_bitinsn(ctx, op1, op2, rd, rt);
Jia Liu1cb66862012-10-24 22:17:09 +080014804 break;
Jia Liu461c08d2012-10-24 22:17:06 +080014805 default:
14806 MIPS_INVAL("MASK ABSQ_S.PH");
14807 generate_exception(ctx, EXCP_RI);
14808 break;
14809 }
14810 break;
14811 case OPC_ADDU_QB_DSP:
14812 op2 = MASK_ADDU_QB(ctx->opcode);
14813 switch (op2) {
14814 case OPC_ADDQ_PH:
14815 case OPC_ADDQ_S_PH:
14816 case OPC_ADDQ_S_W:
14817 case OPC_ADDU_QB:
14818 case OPC_ADDU_S_QB:
14819 case OPC_ADDU_PH:
14820 case OPC_ADDU_S_PH:
14821 case OPC_SUBQ_PH:
14822 case OPC_SUBQ_S_PH:
14823 case OPC_SUBQ_S_W:
14824 case OPC_SUBU_QB:
14825 case OPC_SUBU_S_QB:
14826 case OPC_SUBU_PH:
14827 case OPC_SUBU_S_PH:
14828 case OPC_ADDSC:
14829 case OPC_ADDWC:
14830 case OPC_MODSUB:
14831 case OPC_RADDU_W_QB:
14832 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
14833 break;
Jia Liua22260a2012-10-24 22:17:08 +080014834 case OPC_MULEU_S_PH_QBL:
14835 case OPC_MULEU_S_PH_QBR:
14836 case OPC_MULQ_RS_PH:
14837 case OPC_MULEQ_S_W_PHL:
14838 case OPC_MULEQ_S_W_PHR:
14839 case OPC_MULQ_S_PH:
14840 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 1);
14841 break;
Jia Liu461c08d2012-10-24 22:17:06 +080014842 default: /* Invalid */
14843 MIPS_INVAL("MASK ADDU.QB");
14844 generate_exception(ctx, EXCP_RI);
14845 break;
14846
14847 }
14848 break;
14849 case OPC_CMPU_EQ_QB_DSP:
14850 op2 = MASK_CMPU_EQ_QB(ctx->opcode);
14851 switch (op2) {
14852 case OPC_PRECR_SRA_PH_W:
14853 case OPC_PRECR_SRA_R_PH_W:
14854 gen_mipsdsp_arith(ctx, op1, op2, rt, rs, rd);
14855 break;
14856 case OPC_PRECR_QB_PH:
14857 case OPC_PRECRQ_QB_PH:
14858 case OPC_PRECRQ_PH_W:
14859 case OPC_PRECRQ_RS_PH_W:
14860 case OPC_PRECRQU_S_QB_PH:
14861 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
14862 break;
Jia Liu26690562012-10-24 22:17:10 +080014863 case OPC_CMPU_EQ_QB:
14864 case OPC_CMPU_LT_QB:
14865 case OPC_CMPU_LE_QB:
14866 case OPC_CMP_EQ_PH:
14867 case OPC_CMP_LT_PH:
14868 case OPC_CMP_LE_PH:
14869 gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rd, rs, rt, 0);
14870 break;
14871 case OPC_CMPGU_EQ_QB:
14872 case OPC_CMPGU_LT_QB:
14873 case OPC_CMPGU_LE_QB:
14874 case OPC_CMPGDU_EQ_QB:
14875 case OPC_CMPGDU_LT_QB:
14876 case OPC_CMPGDU_LE_QB:
14877 case OPC_PICK_QB:
14878 case OPC_PICK_PH:
14879 case OPC_PACKRL_PH:
14880 gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rd, rs, rt, 1);
14881 break;
Jia Liu461c08d2012-10-24 22:17:06 +080014882 default: /* Invalid */
14883 MIPS_INVAL("MASK CMPU.EQ.QB");
14884 generate_exception(ctx, EXCP_RI);
14885 break;
14886 }
14887 break;
Jia Liu77c5fa82012-10-24 22:17:07 +080014888 case OPC_SHLL_QB_DSP:
14889 gen_mipsdsp_shift(ctx, op1, rd, rs, rt);
14890 break;
Jia Liua22260a2012-10-24 22:17:08 +080014891 case OPC_DPA_W_PH_DSP:
14892 op2 = MASK_DPA_W_PH(ctx->opcode);
14893 switch (op2) {
14894 case OPC_DPAU_H_QBL:
14895 case OPC_DPAU_H_QBR:
14896 case OPC_DPSU_H_QBL:
14897 case OPC_DPSU_H_QBR:
14898 case OPC_DPA_W_PH:
14899 case OPC_DPAX_W_PH:
14900 case OPC_DPAQ_S_W_PH:
14901 case OPC_DPAQX_S_W_PH:
14902 case OPC_DPAQX_SA_W_PH:
14903 case OPC_DPS_W_PH:
14904 case OPC_DPSX_W_PH:
14905 case OPC_DPSQ_S_W_PH:
14906 case OPC_DPSQX_S_W_PH:
14907 case OPC_DPSQX_SA_W_PH:
14908 case OPC_MULSAQ_S_W_PH:
14909 case OPC_DPAQ_SA_L_W:
14910 case OPC_DPSQ_SA_L_W:
14911 case OPC_MAQ_S_W_PHL:
14912 case OPC_MAQ_S_W_PHR:
14913 case OPC_MAQ_SA_W_PHL:
14914 case OPC_MAQ_SA_W_PHR:
14915 case OPC_MULSA_W_PH:
14916 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 0);
14917 break;
14918 default: /* Invalid */
14919 MIPS_INVAL("MASK DPAW.PH");
14920 generate_exception(ctx, EXCP_RI);
14921 break;
14922 }
14923 break;
Jia Liu1cb66862012-10-24 22:17:09 +080014924 case OPC_INSV_DSP:
14925 op2 = MASK_INSV(ctx->opcode);
14926 switch (op2) {
14927 case OPC_INSV:
14928 check_dsp(ctx);
14929 {
14930 TCGv t0, t1;
14931
14932 if (rt == 0) {
14933 MIPS_DEBUG("NOP");
14934 break;
14935 }
14936
14937 t0 = tcg_temp_new();
14938 t1 = tcg_temp_new();
14939
14940 gen_load_gpr(t0, rt);
14941 gen_load_gpr(t1, rs);
14942
14943 gen_helper_insv(cpu_gpr[rt], cpu_env, t1, t0);
14944
14945 tcg_temp_free(t0);
14946 tcg_temp_free(t1);
14947 break;
14948 }
14949 default: /* Invalid */
14950 MIPS_INVAL("MASK INSV");
14951 generate_exception(ctx, EXCP_RI);
14952 break;
14953 }
14954 break;
Jia Liu26690562012-10-24 22:17:10 +080014955 case OPC_APPEND_DSP:
Aurelien Jarnodf6126a2013-01-01 18:02:24 +010014956 gen_mipsdsp_append(env, ctx, op1, rt, rs, rd);
Jia Liu26690562012-10-24 22:17:10 +080014957 break;
Jia Liub53371e2012-10-24 22:17:11 +080014958 case OPC_EXTR_W_DSP:
14959 op2 = MASK_EXTR_W(ctx->opcode);
14960 switch (op2) {
14961 case OPC_EXTR_W:
14962 case OPC_EXTR_R_W:
14963 case OPC_EXTR_RS_W:
14964 case OPC_EXTR_S_H:
14965 case OPC_EXTRV_S_H:
14966 case OPC_EXTRV_W:
14967 case OPC_EXTRV_R_W:
14968 case OPC_EXTRV_RS_W:
14969 case OPC_EXTP:
14970 case OPC_EXTPV:
14971 case OPC_EXTPDP:
14972 case OPC_EXTPDPV:
14973 gen_mipsdsp_accinsn(ctx, op1, op2, rt, rs, rd, 1);
14974 break;
14975 case OPC_RDDSP:
14976 gen_mipsdsp_accinsn(ctx, op1, op2, rd, rs, rt, 1);
14977 break;
14978 case OPC_SHILO:
14979 case OPC_SHILOV:
14980 case OPC_MTHLIP:
14981 case OPC_WRDSP:
14982 gen_mipsdsp_accinsn(ctx, op1, op2, rd, rs, rt, 0);
14983 break;
14984 default: /* Invalid */
14985 MIPS_INVAL("MASK EXTR.W");
14986 generate_exception(ctx, EXCP_RI);
14987 break;
14988 }
14989 break;
thsd26bc212007-11-08 18:05:37 +000014990#if defined(TARGET_MIPS64)
ths1579a722007-04-05 23:16:25 +000014991 case OPC_DEXTM ... OPC_DEXT:
14992 case OPC_DINSM ... OPC_DINS:
Aurelien Jarnod75c1352013-01-01 18:02:22 +010014993 check_insn(ctx, ISA_MIPS64R2);
thse189e742007-09-24 12:48:00 +000014994 check_mips_64(ctx);
ths1579a722007-04-05 23:16:25 +000014995 gen_bitops(ctx, op1, rt, rs, sa, rd);
14996 break;
14997 case OPC_DBSHFL:
Aurelien Jarnod75c1352013-01-01 18:02:22 +010014998 check_insn(ctx, ISA_MIPS64R2);
thse189e742007-09-24 12:48:00 +000014999 check_mips_64(ctx);
ths1579a722007-04-05 23:16:25 +000015000 op2 = MASK_DBSHFL(ctx->opcode);
aurel3249bcf332008-11-11 11:47:06 +000015001 gen_bshfl(ctx, op2, rt, rd);
thsc6d6dd72007-11-18 03:36:07 +000015002 break;
Aurelien Jarno161f85e2010-06-18 19:32:43 +020015003 case OPC_DDIV_G_2E ... OPC_DDIVU_G_2E:
15004 case OPC_DMULT_G_2E ... OPC_DMULTU_G_2E:
15005 case OPC_DMOD_G_2E ... OPC_DMODU_G_2E:
Aurelien Jarnod75c1352013-01-01 18:02:22 +010015006 check_insn(ctx, INSN_LOONGSON2E);
Aurelien Jarno161f85e2010-06-18 19:32:43 +020015007 gen_loongson_integer(ctx, op1, rd, rs, rt);
15008 break;
Jia Liu461c08d2012-10-24 22:17:06 +080015009 case OPC_ABSQ_S_QH_DSP:
15010 op2 = MASK_ABSQ_S_QH(ctx->opcode);
15011 switch (op2) {
15012 case OPC_PRECEQ_L_PWL:
15013 case OPC_PRECEQ_L_PWR:
15014 case OPC_PRECEQ_PW_QHL:
15015 case OPC_PRECEQ_PW_QHR:
15016 case OPC_PRECEQ_PW_QHLA:
15017 case OPC_PRECEQ_PW_QHRA:
15018 case OPC_PRECEQU_QH_OBL:
15019 case OPC_PRECEQU_QH_OBR:
15020 case OPC_PRECEQU_QH_OBLA:
15021 case OPC_PRECEQU_QH_OBRA:
15022 case OPC_PRECEU_QH_OBL:
15023 case OPC_PRECEU_QH_OBR:
15024 case OPC_PRECEU_QH_OBLA:
15025 case OPC_PRECEU_QH_OBRA:
15026 case OPC_ABSQ_S_OB:
15027 case OPC_ABSQ_S_PW:
15028 case OPC_ABSQ_S_QH:
15029 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
15030 break;
Jia Liu1cb66862012-10-24 22:17:09 +080015031 case OPC_REPL_OB:
15032 case OPC_REPL_PW:
15033 case OPC_REPL_QH:
15034 case OPC_REPLV_OB:
15035 case OPC_REPLV_PW:
15036 case OPC_REPLV_QH:
Aurelien Jarnod75c1352013-01-01 18:02:22 +010015037 gen_mipsdsp_bitinsn(ctx, op1, op2, rd, rt);
Jia Liu1cb66862012-10-24 22:17:09 +080015038 break;
Jia Liu461c08d2012-10-24 22:17:06 +080015039 default: /* Invalid */
15040 MIPS_INVAL("MASK ABSQ_S.QH");
15041 generate_exception(ctx, EXCP_RI);
15042 break;
15043 }
15044 break;
15045 case OPC_ADDU_OB_DSP:
15046 op2 = MASK_ADDU_OB(ctx->opcode);
15047 switch (op2) {
15048 case OPC_RADDU_L_OB:
15049 case OPC_SUBQ_PW:
15050 case OPC_SUBQ_S_PW:
15051 case OPC_SUBQ_QH:
15052 case OPC_SUBQ_S_QH:
15053 case OPC_SUBU_OB:
15054 case OPC_SUBU_S_OB:
15055 case OPC_SUBU_QH:
15056 case OPC_SUBU_S_QH:
15057 case OPC_SUBUH_OB:
15058 case OPC_SUBUH_R_OB:
15059 case OPC_ADDQ_PW:
15060 case OPC_ADDQ_S_PW:
15061 case OPC_ADDQ_QH:
15062 case OPC_ADDQ_S_QH:
15063 case OPC_ADDU_OB:
15064 case OPC_ADDU_S_OB:
15065 case OPC_ADDU_QH:
15066 case OPC_ADDU_S_QH:
15067 case OPC_ADDUH_OB:
15068 case OPC_ADDUH_R_OB:
15069 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
15070 break;
Jia Liua22260a2012-10-24 22:17:08 +080015071 case OPC_MULEQ_S_PW_QHL:
15072 case OPC_MULEQ_S_PW_QHR:
15073 case OPC_MULEU_S_QH_OBL:
15074 case OPC_MULEU_S_QH_OBR:
15075 case OPC_MULQ_RS_QH:
15076 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 1);
15077 break;
Jia Liu461c08d2012-10-24 22:17:06 +080015078 default: /* Invalid */
15079 MIPS_INVAL("MASK ADDU.OB");
15080 generate_exception(ctx, EXCP_RI);
15081 break;
15082 }
15083 break;
15084 case OPC_CMPU_EQ_OB_DSP:
15085 op2 = MASK_CMPU_EQ_OB(ctx->opcode);
15086 switch (op2) {
15087 case OPC_PRECR_SRA_QH_PW:
15088 case OPC_PRECR_SRA_R_QH_PW:
15089 /* Return value is rt. */
15090 gen_mipsdsp_arith(ctx, op1, op2, rt, rs, rd);
15091 break;
15092 case OPC_PRECR_OB_QH:
15093 case OPC_PRECRQ_OB_QH:
15094 case OPC_PRECRQ_PW_L:
15095 case OPC_PRECRQ_QH_PW:
15096 case OPC_PRECRQ_RS_QH_PW:
15097 case OPC_PRECRQU_S_OB_QH:
15098 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
15099 break;
Jia Liu26690562012-10-24 22:17:10 +080015100 case OPC_CMPU_EQ_OB:
15101 case OPC_CMPU_LT_OB:
15102 case OPC_CMPU_LE_OB:
15103 case OPC_CMP_EQ_QH:
15104 case OPC_CMP_LT_QH:
15105 case OPC_CMP_LE_QH:
15106 case OPC_CMP_EQ_PW:
15107 case OPC_CMP_LT_PW:
15108 case OPC_CMP_LE_PW:
15109 gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rd, rs, rt, 0);
15110 break;
15111 case OPC_CMPGDU_EQ_OB:
15112 case OPC_CMPGDU_LT_OB:
15113 case OPC_CMPGDU_LE_OB:
15114 case OPC_CMPGU_EQ_OB:
15115 case OPC_CMPGU_LT_OB:
15116 case OPC_CMPGU_LE_OB:
15117 case OPC_PACKRL_PW:
15118 case OPC_PICK_OB:
15119 case OPC_PICK_PW:
15120 case OPC_PICK_QH:
15121 gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rd, rs, rt, 1);
15122 break;
Jia Liu461c08d2012-10-24 22:17:06 +080015123 default: /* Invalid */
15124 MIPS_INVAL("MASK CMPU_EQ.OB");
15125 generate_exception(ctx, EXCP_RI);
15126 break;
15127 }
15128 break;
Jia Liu26690562012-10-24 22:17:10 +080015129 case OPC_DAPPEND_DSP:
Aurelien Jarnodf6126a2013-01-01 18:02:24 +010015130 gen_mipsdsp_append(env, ctx, op1, rt, rs, rd);
Jia Liu26690562012-10-24 22:17:10 +080015131 break;
Jia Liub53371e2012-10-24 22:17:11 +080015132 case OPC_DEXTR_W_DSP:
15133 op2 = MASK_DEXTR_W(ctx->opcode);
15134 switch (op2) {
15135 case OPC_DEXTP:
15136 case OPC_DEXTPDP:
15137 case OPC_DEXTPDPV:
15138 case OPC_DEXTPV:
15139 case OPC_DEXTR_L:
15140 case OPC_DEXTR_R_L:
15141 case OPC_DEXTR_RS_L:
15142 case OPC_DEXTR_W:
15143 case OPC_DEXTR_R_W:
15144 case OPC_DEXTR_RS_W:
15145 case OPC_DEXTR_S_H:
15146 case OPC_DEXTRV_L:
15147 case OPC_DEXTRV_R_L:
15148 case OPC_DEXTRV_RS_L:
15149 case OPC_DEXTRV_S_H:
15150 case OPC_DEXTRV_W:
15151 case OPC_DEXTRV_R_W:
15152 case OPC_DEXTRV_RS_W:
15153 gen_mipsdsp_accinsn(ctx, op1, op2, rt, rs, rd, 1);
15154 break;
15155 case OPC_DMTHLIP:
15156 case OPC_DSHILO:
15157 case OPC_DSHILOV:
15158 gen_mipsdsp_accinsn(ctx, op1, op2, rd, rs, rt, 0);
15159 break;
15160 default: /* Invalid */
15161 MIPS_INVAL("MASK EXTR.W");
15162 generate_exception(ctx, EXCP_RI);
15163 break;
15164 }
15165 break;
Jia Liua22260a2012-10-24 22:17:08 +080015166 case OPC_DPAQ_W_QH_DSP:
15167 op2 = MASK_DPAQ_W_QH(ctx->opcode);
15168 switch (op2) {
15169 case OPC_DPAU_H_OBL:
15170 case OPC_DPAU_H_OBR:
15171 case OPC_DPSU_H_OBL:
15172 case OPC_DPSU_H_OBR:
15173 case OPC_DPA_W_QH:
15174 case OPC_DPAQ_S_W_QH:
15175 case OPC_DPS_W_QH:
15176 case OPC_DPSQ_S_W_QH:
15177 case OPC_MULSAQ_S_W_QH:
15178 case OPC_DPAQ_SA_L_PW:
15179 case OPC_DPSQ_SA_L_PW:
15180 case OPC_MULSAQ_S_L_PW:
15181 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 0);
15182 break;
15183 case OPC_MAQ_S_W_QHLL:
15184 case OPC_MAQ_S_W_QHLR:
15185 case OPC_MAQ_S_W_QHRL:
15186 case OPC_MAQ_S_W_QHRR:
15187 case OPC_MAQ_SA_W_QHLL:
15188 case OPC_MAQ_SA_W_QHLR:
15189 case OPC_MAQ_SA_W_QHRL:
15190 case OPC_MAQ_SA_W_QHRR:
15191 case OPC_MAQ_S_L_PWL:
15192 case OPC_MAQ_S_L_PWR:
15193 case OPC_DMADD:
15194 case OPC_DMADDU:
15195 case OPC_DMSUB:
15196 case OPC_DMSUBU:
15197 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 0);
15198 break;
15199 default: /* Invalid */
15200 MIPS_INVAL("MASK DPAQ.W.QH");
15201 generate_exception(ctx, EXCP_RI);
15202 break;
15203 }
15204 break;
Jia Liu1cb66862012-10-24 22:17:09 +080015205 case OPC_DINSV_DSP:
15206 op2 = MASK_INSV(ctx->opcode);
15207 switch (op2) {
15208 case OPC_DINSV:
15209 {
15210 TCGv t0, t1;
15211
15212 if (rt == 0) {
15213 MIPS_DEBUG("NOP");
15214 break;
15215 }
15216 check_dsp(ctx);
15217
15218 t0 = tcg_temp_new();
15219 t1 = tcg_temp_new();
15220
15221 gen_load_gpr(t0, rt);
15222 gen_load_gpr(t1, rs);
15223
15224 gen_helper_dinsv(cpu_gpr[rt], cpu_env, t1, t0);
15225 break;
15226 }
15227 default: /* Invalid */
15228 MIPS_INVAL("MASK DINSV");
15229 generate_exception(ctx, EXCP_RI);
15230 break;
15231 }
15232 break;
Jia Liu77c5fa82012-10-24 22:17:07 +080015233 case OPC_SHLL_OB_DSP:
15234 gen_mipsdsp_shift(ctx, op1, rd, rs, rt);
15235 break;
ths7a387ff2006-12-06 20:17:30 +000015236#endif
15237 default: /* Invalid */
15238 MIPS_INVAL("special3");
15239 generate_exception(ctx, EXCP_RI);
15240 break;
15241 }
15242 break;
15243 case OPC_REGIMM:
15244 op1 = MASK_REGIMM(ctx->opcode);
15245 switch (op1) {
15246 case OPC_BLTZ ... OPC_BGEZL: /* REGIMM branches */
15247 case OPC_BLTZAL ... OPC_BGEZALL:
Nathan Froyd7dca4ad2009-12-08 08:06:25 -080015248 gen_compute_branch(ctx, op1, 4, rs, -1, imm << 2);
Nathan Froydc9602062009-12-08 08:06:27 -080015249 *is_branch = 1;
15250 break;
ths7a387ff2006-12-06 20:17:30 +000015251 case OPC_TGEI ... OPC_TEQI: /* REGIMM traps */
15252 case OPC_TNEI:
15253 gen_trap(ctx, op1, rs, -1, imm);
15254 break;
15255 case OPC_SYNCI:
Aurelien Jarnod75c1352013-01-01 18:02:22 +010015256 check_insn(ctx, ISA_MIPS32R2);
thsead93602007-09-06 00:18:15 +000015257 /* Treat as NOP. */
bellard6af0bf92005-07-02 14:58:51 +000015258 break;
Jia Liue45a93e2012-10-24 22:17:04 +080015259 case OPC_BPOSGE32: /* MIPS DSP branch */
15260#if defined(TARGET_MIPS64)
15261 case OPC_BPOSGE64:
15262#endif
15263 check_dsp(ctx);
15264 gen_compute_branch(ctx, op1, 4, -1, -2, (int32_t)imm << 2);
15265 *is_branch = 1;
15266 break;
bellard6af0bf92005-07-02 14:58:51 +000015267 default: /* Invalid */
ths923617a2007-05-11 00:16:06 +000015268 MIPS_INVAL("regimm");
bellard6af0bf92005-07-02 14:58:51 +000015269 generate_exception(ctx, EXCP_RI);
15270 break;
15271 }
15272 break;
ths7a387ff2006-12-06 20:17:30 +000015273 case OPC_CP0:
ths387a8fe2007-09-25 14:49:47 +000015274 check_cp0_enabled(ctx);
ths7a387ff2006-12-06 20:17:30 +000015275 op1 = MASK_CP0(ctx->opcode);
bellard6af0bf92005-07-02 14:58:51 +000015276 switch (op1) {
ths7a387ff2006-12-06 20:17:30 +000015277 case OPC_MFC0:
15278 case OPC_MTC0:
thsead93602007-09-06 00:18:15 +000015279 case OPC_MFTR:
15280 case OPC_MTTR:
thsd26bc212007-11-08 18:05:37 +000015281#if defined(TARGET_MIPS64)
ths7a387ff2006-12-06 20:17:30 +000015282 case OPC_DMFC0:
15283 case OPC_DMTC0:
15284#endif
thsf1aa6322008-06-09 07:13:38 +000015285#ifndef CONFIG_USER_ONLY
aurel32932e71c2009-01-12 21:33:13 +000015286 gen_cp0(env, ctx, op1, rt, rd);
ths0eaef5a2008-07-23 16:14:22 +000015287#endif /* !CONFIG_USER_ONLY */
bellard6af0bf92005-07-02 14:58:51 +000015288 break;
ths7a387ff2006-12-06 20:17:30 +000015289 case OPC_C0_FIRST ... OPC_C0_LAST:
thsf1aa6322008-06-09 07:13:38 +000015290#ifndef CONFIG_USER_ONLY
aurel32932e71c2009-01-12 21:33:13 +000015291 gen_cp0(env, ctx, MASK_C0(ctx->opcode), rt, rd);
ths0eaef5a2008-07-23 16:14:22 +000015292#endif /* !CONFIG_USER_ONLY */
ths7a387ff2006-12-06 20:17:30 +000015293 break;
15294 case OPC_MFMC0:
ths8706c382008-07-21 21:38:04 +000015295#ifndef CONFIG_USER_ONLY
aurel32932e71c2009-01-12 21:33:13 +000015296 {
aurel3235fbce22009-04-08 21:47:55 +000015297 TCGv t0 = tcg_temp_new();
ths6c5c1e22008-06-24 15:12:27 +000015298
ths0eaef5a2008-07-23 16:14:22 +000015299 op2 = MASK_MFMC0(ctx->opcode);
ths6c5c1e22008-06-24 15:12:27 +000015300 switch (op2) {
15301 case OPC_DMT:
Aurelien Jarnod75c1352013-01-01 18:02:22 +010015302 check_insn(ctx, ASE_MT);
Nathan Froyd9ed57262010-10-29 07:48:46 -070015303 gen_helper_dmt(t0);
aurel3235fbce22009-04-08 21:47:55 +000015304 gen_store_gpr(t0, rt);
ths6c5c1e22008-06-24 15:12:27 +000015305 break;
15306 case OPC_EMT:
Aurelien Jarnod75c1352013-01-01 18:02:22 +010015307 check_insn(ctx, ASE_MT);
Nathan Froyd9ed57262010-10-29 07:48:46 -070015308 gen_helper_emt(t0);
aurel3235fbce22009-04-08 21:47:55 +000015309 gen_store_gpr(t0, rt);
aurel32da806822008-11-15 12:12:08 +000015310 break;
ths6c5c1e22008-06-24 15:12:27 +000015311 case OPC_DVPE:
Aurelien Jarnod75c1352013-01-01 18:02:22 +010015312 check_insn(ctx, ASE_MT);
Blue Swirl895c2d02012-09-02 14:52:59 +000015313 gen_helper_dvpe(t0, cpu_env);
aurel3235fbce22009-04-08 21:47:55 +000015314 gen_store_gpr(t0, rt);
ths6c5c1e22008-06-24 15:12:27 +000015315 break;
15316 case OPC_EVPE:
Aurelien Jarnod75c1352013-01-01 18:02:22 +010015317 check_insn(ctx, ASE_MT);
Blue Swirl895c2d02012-09-02 14:52:59 +000015318 gen_helper_evpe(t0, cpu_env);
aurel3235fbce22009-04-08 21:47:55 +000015319 gen_store_gpr(t0, rt);
ths6c5c1e22008-06-24 15:12:27 +000015320 break;
15321 case OPC_DI:
Aurelien Jarnod75c1352013-01-01 18:02:22 +010015322 check_insn(ctx, ISA_MIPS32R2);
aurel32867abc72009-04-13 08:53:12 +000015323 save_cpu_state(ctx, 1);
Blue Swirl895c2d02012-09-02 14:52:59 +000015324 gen_helper_di(t0, cpu_env);
aurel3235fbce22009-04-08 21:47:55 +000015325 gen_store_gpr(t0, rt);
ths6c5c1e22008-06-24 15:12:27 +000015326 /* Stop translation as we may have switched the execution mode */
15327 ctx->bstate = BS_STOP;
15328 break;
15329 case OPC_EI:
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_ei(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 default: /* Invalid */
15338 MIPS_INVAL("mfmc0");
15339 generate_exception(ctx, EXCP_RI);
15340 break;
15341 }
ths6c5c1e22008-06-24 15:12:27 +000015342 tcg_temp_free(t0);
ths7a387ff2006-12-06 20:17:30 +000015343 }
ths0eaef5a2008-07-23 16:14:22 +000015344#endif /* !CONFIG_USER_ONLY */
ths7a387ff2006-12-06 20:17:30 +000015345 break;
ths7a387ff2006-12-06 20:17:30 +000015346 case OPC_RDPGPR:
Aurelien Jarnod75c1352013-01-01 18:02:22 +010015347 check_insn(ctx, ISA_MIPS32R2);
thsbe24bb42008-06-23 12:57:09 +000015348 gen_load_srsgpr(rt, rd);
thsead93602007-09-06 00:18:15 +000015349 break;
ths7a387ff2006-12-06 20:17:30 +000015350 case OPC_WRPGPR:
Aurelien Jarnod75c1352013-01-01 18:02:22 +010015351 check_insn(ctx, ISA_MIPS32R2);
thsbe24bb42008-06-23 12:57:09 +000015352 gen_store_srsgpr(rt, rd);
ths38121542007-04-02 17:28:07 +000015353 break;
bellard6af0bf92005-07-02 14:58:51 +000015354 default:
ths923617a2007-05-11 00:16:06 +000015355 MIPS_INVAL("cp0");
ths7a387ff2006-12-06 20:17:30 +000015356 generate_exception(ctx, EXCP_RI);
bellard6af0bf92005-07-02 14:58:51 +000015357 break;
15358 }
15359 break;
aurel32324d9e32009-04-11 18:42:17 +000015360 case OPC_ADDI: /* Arithmetic with immediate opcode */
15361 case OPC_ADDIU:
Aurelien Jarnod75c1352013-01-01 18:02:22 +010015362 gen_arith_imm(ctx, op, rt, rs, imm);
ths7a387ff2006-12-06 20:17:30 +000015363 break;
aurel32324d9e32009-04-11 18:42:17 +000015364 case OPC_SLTI: /* Set on less than with immediate opcode */
15365 case OPC_SLTIU:
Aurelien Jarnod75c1352013-01-01 18:02:22 +010015366 gen_slt_imm(ctx, op, rt, rs, imm);
aurel32324d9e32009-04-11 18:42:17 +000015367 break;
15368 case OPC_ANDI: /* Arithmetic with immediate opcode */
15369 case OPC_LUI:
15370 case OPC_ORI:
15371 case OPC_XORI:
Aurelien Jarnod75c1352013-01-01 18:02:22 +010015372 gen_logic_imm(ctx, op, rt, rs, imm);
aurel32324d9e32009-04-11 18:42:17 +000015373 break;
ths7a387ff2006-12-06 20:17:30 +000015374 case OPC_J ... OPC_JAL: /* Jump */
15375 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2;
Nathan Froyd7dca4ad2009-12-08 08:06:25 -080015376 gen_compute_branch(ctx, op, 4, rs, rt, offset);
Nathan Froydc9602062009-12-08 08:06:27 -080015377 *is_branch = 1;
15378 break;
ths7a387ff2006-12-06 20:17:30 +000015379 case OPC_BEQ ... OPC_BGTZ: /* Branch */
15380 case OPC_BEQL ... OPC_BGTZL:
Nathan Froyd7dca4ad2009-12-08 08:06:25 -080015381 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2);
Nathan Froydc9602062009-12-08 08:06:27 -080015382 *is_branch = 1;
15383 break;
ths7a387ff2006-12-06 20:17:30 +000015384 case OPC_LB ... OPC_LWR: /* Load and stores */
Aurelien Jarno5c13fdf2010-07-01 07:47:00 +020015385 case OPC_LL:
Aurelien Jarnod75c1352013-01-01 18:02:22 +010015386 gen_ld(ctx, op, rt, rs, imm);
Aurelien Jarno5c13fdf2010-07-01 07:47:00 +020015387 break;
ths7a387ff2006-12-06 20:17:30 +000015388 case OPC_SB ... OPC_SW:
15389 case OPC_SWR:
Aurelien Jarno5c13fdf2010-07-01 07:47:00 +020015390 gen_st(ctx, op, rt, rs, imm);
ths7a387ff2006-12-06 20:17:30 +000015391 break;
aurel32d66c7132009-04-11 18:42:55 +000015392 case OPC_SC:
15393 gen_st_cond(ctx, op, rt, rs, imm);
15394 break;
ths7a387ff2006-12-06 20:17:30 +000015395 case OPC_CACHE:
Eric Johnson2e154972011-09-17 17:05:32 -070015396 check_cp0_enabled(ctx);
Aurelien Jarnod75c1352013-01-01 18:02:22 +010015397 check_insn(ctx, ISA_MIPS3 | ISA_MIPS32);
thsead93602007-09-06 00:18:15 +000015398 /* Treat as NOP. */
ths34ae7b52007-05-18 01:13:09 +000015399 break;
ths7a387ff2006-12-06 20:17:30 +000015400 case OPC_PREF:
Aurelien Jarnod75c1352013-01-01 18:02:22 +010015401 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32);
thsead93602007-09-06 00:18:15 +000015402 /* Treat as NOP. */
bellard6af0bf92005-07-02 14:58:51 +000015403 break;
bellard4ad40f32005-12-05 19:59:36 +000015404
ths923617a2007-05-11 00:16:06 +000015405 /* Floating point (COP1). */
ths7a387ff2006-12-06 20:17:30 +000015406 case OPC_LWC1:
15407 case OPC_LDC1:
15408 case OPC_SWC1:
15409 case OPC_SDC1:
Nathan Froyd26ebe462010-05-24 09:19:35 -070015410 gen_cop1_ldst(env, ctx, op, rt, rs, imm);
bellard6ea83fe2006-06-14 12:56:19 +000015411 break;
15412
ths7a387ff2006-12-06 20:17:30 +000015413 case OPC_CP1:
ths36d23952007-02-28 22:37:42 +000015414 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
ths5e755512007-05-29 16:52:57 +000015415 check_cp1_enabled(ctx);
ths36d23952007-02-28 22:37:42 +000015416 op1 = MASK_CP1(ctx->opcode);
15417 switch (op1) {
ths3a95e3a2007-06-02 00:25:12 +000015418 case OPC_MFHC1:
15419 case OPC_MTHC1:
Aurelien Jarnod75c1352013-01-01 18:02:22 +010015420 check_insn(ctx, ISA_MIPS32R2);
ths36d23952007-02-28 22:37:42 +000015421 case OPC_MFC1:
15422 case OPC_CFC1:
15423 case OPC_MTC1:
15424 case OPC_CTC1:
thse189e742007-09-24 12:48:00 +000015425 gen_cp1(ctx, op1, rt, rd);
15426 break;
thsd26bc212007-11-08 18:05:37 +000015427#if defined(TARGET_MIPS64)
ths36d23952007-02-28 22:37:42 +000015428 case OPC_DMFC1:
15429 case OPC_DMTC1:
Aurelien Jarnod75c1352013-01-01 18:02:22 +010015430 check_insn(ctx, ISA_MIPS3);
ths36d23952007-02-28 22:37:42 +000015431 gen_cp1(ctx, op1, rt, rd);
15432 break;
thse189e742007-09-24 12:48:00 +000015433#endif
thsfbcc6822007-05-11 09:59:10 +000015434 case OPC_BC1ANY2:
15435 case OPC_BC1ANY4:
thsb8aa4592007-12-30 15:36:58 +000015436 check_cop1x(ctx);
Aurelien Jarnod75c1352013-01-01 18:02:22 +010015437 check_insn(ctx, ASE_MIPS3D);
thsd8a59502007-10-23 13:15:33 +000015438 /* fall through */
15439 case OPC_BC1:
Aurelien Jarnod75c1352013-01-01 18:02:22 +010015440 gen_compute_branch1(ctx, MASK_BC1(ctx->opcode),
ths5a5012e2007-05-07 13:55:33 +000015441 (rt >> 2) & 0x7, imm << 2);
Nathan Froydc9602062009-12-08 08:06:27 -080015442 *is_branch = 1;
15443 break;
ths36d23952007-02-28 22:37:42 +000015444 case OPC_S_FMT:
15445 case OPC_D_FMT:
15446 case OPC_W_FMT:
15447 case OPC_L_FMT:
ths5a5012e2007-05-07 13:55:33 +000015448 case OPC_PS_FMT:
Nathan Froydbf4120a2010-06-08 13:29:56 -070015449 gen_farith(ctx, ctx->opcode & FOP(0x3f, 0x1f), rt, rd, sa,
ths5a5012e2007-05-07 13:55:33 +000015450 (imm >> 8) & 0x7);
ths36d23952007-02-28 22:37:42 +000015451 break;
15452 default:
ths923617a2007-05-11 00:16:06 +000015453 MIPS_INVAL("cp1");
thse397ee32007-03-23 00:43:28 +000015454 generate_exception (ctx, EXCP_RI);
ths36d23952007-02-28 22:37:42 +000015455 break;
15456 }
15457 } else {
15458 generate_exception_err(ctx, EXCP_CpU, 1);
bellard6ea83fe2006-06-14 12:56:19 +000015459 }
bellard4ad40f32005-12-05 19:59:36 +000015460 break;
15461
15462 /* COP2. */
ths7a387ff2006-12-06 20:17:30 +000015463 case OPC_LWC2:
15464 case OPC_LDC2:
15465 case OPC_SWC2:
15466 case OPC_SDC2:
ths7a387ff2006-12-06 20:17:30 +000015467 /* COP2: Not implemented. */
bellard4ad40f32005-12-05 19:59:36 +000015468 generate_exception_err(ctx, EXCP_CpU, 2);
15469 break;
Richard Hendersonbd277fa2012-09-18 21:59:44 -070015470 case OPC_CP2:
Aurelien Jarnod75c1352013-01-01 18:02:22 +010015471 check_insn(ctx, INSN_LOONGSON2F);
Richard Hendersonbd277fa2012-09-18 21:59:44 -070015472 /* Note that these instructions use different fields. */
15473 gen_loongson_multimedia(ctx, sa, rd, rt);
15474 break;
bellard4ad40f32005-12-05 19:59:36 +000015475
ths7a387ff2006-12-06 20:17:30 +000015476 case OPC_CP3:
ths36d23952007-02-28 22:37:42 +000015477 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
ths5e755512007-05-29 16:52:57 +000015478 check_cp1_enabled(ctx);
ths36d23952007-02-28 22:37:42 +000015479 op1 = MASK_CP3(ctx->opcode);
15480 switch (op1) {
ths5a5012e2007-05-07 13:55:33 +000015481 case OPC_LWXC1:
15482 case OPC_LDXC1:
15483 case OPC_LUXC1:
15484 case OPC_SWXC1:
15485 case OPC_SDXC1:
15486 case OPC_SUXC1:
ths93b12cc2007-05-20 01:36:29 +000015487 gen_flt3_ldst(ctx, op1, sa, rd, rs, rt);
ths5a5012e2007-05-07 13:55:33 +000015488 break;
thse0c84da2007-04-07 01:11:39 +000015489 case OPC_PREFX:
thsead93602007-09-06 00:18:15 +000015490 /* Treat as NOP. */
thse0c84da2007-04-07 01:11:39 +000015491 break;
ths5a5012e2007-05-07 13:55:33 +000015492 case OPC_ALNV_PS:
15493 case OPC_MADD_S:
15494 case OPC_MADD_D:
15495 case OPC_MADD_PS:
15496 case OPC_MSUB_S:
15497 case OPC_MSUB_D:
15498 case OPC_MSUB_PS:
15499 case OPC_NMADD_S:
15500 case OPC_NMADD_D:
15501 case OPC_NMADD_PS:
15502 case OPC_NMSUB_S:
15503 case OPC_NMSUB_D:
15504 case OPC_NMSUB_PS:
15505 gen_flt3_arith(ctx, op1, sa, rs, rd, rt);
15506 break;
ths36d23952007-02-28 22:37:42 +000015507 default:
ths923617a2007-05-11 00:16:06 +000015508 MIPS_INVAL("cp3");
thse397ee32007-03-23 00:43:28 +000015509 generate_exception (ctx, EXCP_RI);
ths36d23952007-02-28 22:37:42 +000015510 break;
15511 }
15512 } else {
thse397ee32007-03-23 00:43:28 +000015513 generate_exception_err(ctx, EXCP_CpU, 1);
ths7a387ff2006-12-06 20:17:30 +000015514 }
bellard4ad40f32005-12-05 19:59:36 +000015515 break;
15516
thsd26bc212007-11-08 18:05:37 +000015517#if defined(TARGET_MIPS64)
ths7a387ff2006-12-06 20:17:30 +000015518 /* MIPS64 opcodes */
15519 case OPC_LWU:
15520 case OPC_LDL ... OPC_LDR:
ths7a387ff2006-12-06 20:17:30 +000015521 case OPC_LLD:
15522 case OPC_LD:
Aurelien Jarnod75c1352013-01-01 18:02:22 +010015523 check_insn(ctx, ISA_MIPS3);
Aurelien Jarno5c13fdf2010-07-01 07:47:00 +020015524 check_mips_64(ctx);
Aurelien Jarnod75c1352013-01-01 18:02:22 +010015525 gen_ld(ctx, op, rt, rs, imm);
Aurelien Jarno5c13fdf2010-07-01 07:47:00 +020015526 break;
15527 case OPC_SDL ... OPC_SDR:
ths7a387ff2006-12-06 20:17:30 +000015528 case OPC_SD:
Aurelien Jarnod75c1352013-01-01 18:02:22 +010015529 check_insn(ctx, ISA_MIPS3);
thse189e742007-09-24 12:48:00 +000015530 check_mips_64(ctx);
Aurelien Jarno5c13fdf2010-07-01 07:47:00 +020015531 gen_st(ctx, op, rt, rs, imm);
ths7a387ff2006-12-06 20:17:30 +000015532 break;
aurel32d66c7132009-04-11 18:42:55 +000015533 case OPC_SCD:
Aurelien Jarnod75c1352013-01-01 18:02:22 +010015534 check_insn(ctx, ISA_MIPS3);
aurel32d66c7132009-04-11 18:42:55 +000015535 check_mips_64(ctx);
15536 gen_st_cond(ctx, op, rt, rs, imm);
15537 break;
aurel32324d9e32009-04-11 18:42:17 +000015538 case OPC_DADDI:
15539 case OPC_DADDIU:
Aurelien Jarnod75c1352013-01-01 18:02:22 +010015540 check_insn(ctx, ISA_MIPS3);
thse189e742007-09-24 12:48:00 +000015541 check_mips_64(ctx);
Aurelien Jarnod75c1352013-01-01 18:02:22 +010015542 gen_arith_imm(ctx, op, rt, rs, imm);
ths7a387ff2006-12-06 20:17:30 +000015543 break;
bellard6af0bf92005-07-02 14:58:51 +000015544#endif
ths7a387ff2006-12-06 20:17:30 +000015545 case OPC_JALX:
Aurelien Jarnod75c1352013-01-01 18:02:22 +010015546 check_insn(ctx, ASE_MIPS16 | ASE_MICROMIPS);
Nathan Froyd364d4832009-12-08 08:06:29 -080015547 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2;
15548 gen_compute_branch(ctx, op, 4, rs, rt, offset);
15549 *is_branch = 1;
15550 break;
ths7a387ff2006-12-06 20:17:30 +000015551 case OPC_MDMX:
Aurelien Jarnod75c1352013-01-01 18:02:22 +010015552 check_insn(ctx, ASE_MDMX);
ths7a387ff2006-12-06 20:17:30 +000015553 /* MDMX: Not implemented. */
bellard6af0bf92005-07-02 14:58:51 +000015554 default: /* Invalid */
ths923617a2007-05-11 00:16:06 +000015555 MIPS_INVAL("major opcode");
bellard6af0bf92005-07-02 14:58:51 +000015556 generate_exception(ctx, EXCP_RI);
15557 break;
15558 }
bellard6af0bf92005-07-02 14:58:51 +000015559}
15560
ths2cfc5f12008-07-18 18:01:29 +000015561static inline void
Andreas Färber7db13fa2012-03-14 01:38:22 +010015562gen_intermediate_code_internal (CPUMIPSState *env, TranslationBlock *tb,
ths820e00f2007-03-19 21:46:06 +000015563 int search_pc)
bellard6af0bf92005-07-02 14:58:51 +000015564{
ths278d0702007-05-31 23:42:46 +000015565 DisasContext ctx;
bellard6af0bf92005-07-02 14:58:51 +000015566 target_ulong pc_start;
15567 uint16_t *gen_opc_end;
aliguoria1d1bb32008-11-18 20:07:32 +000015568 CPUBreakpoint *bp;
bellard6af0bf92005-07-02 14:58:51 +000015569 int j, lj = -1;
pbrook2e70f6e2008-06-29 01:03:05 +000015570 int num_insns;
15571 int max_insns;
Nathan Froydc9602062009-12-08 08:06:27 -080015572 int insn_bytes;
15573 int is_branch;
bellard6af0bf92005-07-02 14:58:51 +000015574
aliguori93fcfe32009-01-15 22:34:14 +000015575 if (search_pc)
15576 qemu_log("search pc %d\n", search_pc);
bellard4ad40f32005-12-05 19:59:36 +000015577
bellard6af0bf92005-07-02 14:58:51 +000015578 pc_start = tb->pc;
Evgeny Voevodin92414b32012-11-12 13:27:47 +040015579 gen_opc_end = tcg_ctx.gen_opc_buf + OPC_MAX_SIZE;
bellard6af0bf92005-07-02 14:58:51 +000015580 ctx.pc = pc_start;
bellard4ad40f32005-12-05 19:59:36 +000015581 ctx.saved_pc = -1;
Nathan Froyd7b270ef2009-07-14 08:33:11 -070015582 ctx.singlestep_enabled = env->singlestep_enabled;
Aurelien Jarnod75c1352013-01-01 18:02:22 +010015583 ctx.insn_flags = env->insn_flags;
bellard6af0bf92005-07-02 14:58:51 +000015584 ctx.tb = tb;
15585 ctx.bstate = BS_NONE;
bellard4ad40f32005-12-05 19:59:36 +000015586 /* Restore delay slot state from the tb context. */
j_mayerc0686882007-09-20 22:47:42 +000015587 ctx.hflags = (uint32_t)tb->flags; /* FIXME: maybe use 64 bits here? */
thsfd4a04e2007-05-18 11:55:54 +000015588 restore_cpu_state(env, &ctx);
aurel32932e71c2009-01-12 21:33:13 +000015589#ifdef CONFIG_USER_ONLY
ths0eaef5a2008-07-23 16:14:22 +000015590 ctx.mem_idx = MIPS_HFLAG_UM;
aurel32932e71c2009-01-12 21:33:13 +000015591#else
ths0eaef5a2008-07-23 16:14:22 +000015592 ctx.mem_idx = ctx.hflags & MIPS_HFLAG_KSU;
aurel32932e71c2009-01-12 21:33:13 +000015593#endif
pbrook2e70f6e2008-06-29 01:03:05 +000015594 num_insns = 0;
pbrook2e70f6e2008-06-29 01:03:05 +000015595 max_insns = tb->cflags & CF_COUNT_MASK;
15596 if (max_insns == 0)
15597 max_insns = CF_COUNT_MASK;
aliguorid12d51d2009-01-15 21:48:06 +000015598 LOG_DISAS("\ntb %p idx %d hflags %04x\n", tb, ctx.mem_idx, ctx.hflags);
pbrook2e70f6e2008-06-29 01:03:05 +000015599 gen_icount_start();
thsfaf7aaa2008-06-11 12:26:29 +000015600 while (ctx.bstate == BS_NONE) {
Blue Swirl72cf2d42009-09-12 07:36:22 +000015601 if (unlikely(!QTAILQ_EMPTY(&env->breakpoints))) {
15602 QTAILQ_FOREACH(bp, &env->breakpoints, entry) {
aliguoria1d1bb32008-11-18 20:07:32 +000015603 if (bp->pc == ctx.pc) {
ths278d0702007-05-31 23:42:46 +000015604 save_cpu_state(&ctx, 1);
bellard4ad40f32005-12-05 19:59:36 +000015605 ctx.bstate = BS_BRANCH;
Blue Swirl895c2d02012-09-02 14:52:59 +000015606 gen_helper_0e0i(raise_exception, EXCP_DEBUG);
thsce62e5b2007-09-11 10:04:58 +000015607 /* Include the breakpoint location or the tb won't
15608 * be flushed when it must be. */
15609 ctx.pc += 4;
bellard4ad40f32005-12-05 19:59:36 +000015610 goto done_generating;
15611 }
15612 }
15613 }
15614
bellard6af0bf92005-07-02 14:58:51 +000015615 if (search_pc) {
Evgeny Voevodin92414b32012-11-12 13:27:47 +040015616 j = tcg_ctx.gen_opc_ptr - tcg_ctx.gen_opc_buf;
bellard6af0bf92005-07-02 14:58:51 +000015617 if (lj < j) {
15618 lj++;
15619 while (lj < j)
Evgeny Voevodinab1103d2012-11-21 11:43:06 +040015620 tcg_ctx.gen_opc_instr_start[lj++] = 0;
bellard6af0bf92005-07-02 14:58:51 +000015621 }
Evgeny Voevodin25983ca2012-11-21 11:43:04 +040015622 tcg_ctx.gen_opc_pc[lj] = ctx.pc;
bellard4ad40f32005-12-05 19:59:36 +000015623 gen_opc_hflags[lj] = ctx.hflags & MIPS_HFLAG_BMASK;
Aurelien Jarno46364012012-10-28 15:42:55 +010015624 gen_opc_btarget[lj] = ctx.btarget;
Evgeny Voevodinab1103d2012-11-21 11:43:06 +040015625 tcg_ctx.gen_opc_instr_start[lj] = 1;
Evgeny Voevodinc9c99c22012-11-21 11:43:05 +040015626 tcg_ctx.gen_opc_icount[lj] = num_insns;
bellard6af0bf92005-07-02 14:58:51 +000015627 }
pbrook2e70f6e2008-06-29 01:03:05 +000015628 if (num_insns + 1 == max_insns && (tb->cflags & CF_LAST_IO))
15629 gen_io_start();
Nathan Froydc9602062009-12-08 08:06:27 -080015630
15631 is_branch = 0;
Nathan Froyd364d4832009-12-08 08:06:29 -080015632 if (!(ctx.hflags & MIPS_HFLAG_M16)) {
Blue Swirl895c2d02012-09-02 14:52:59 +000015633 ctx.opcode = cpu_ldl_code(env, ctx.pc);
Nathan Froydc9602062009-12-08 08:06:27 -080015634 insn_bytes = 4;
15635 decode_opc(env, &ctx, &is_branch);
Aurelien Jarnod75c1352013-01-01 18:02:22 +010015636 } else if (ctx.insn_flags & ASE_MICROMIPS) {
Blue Swirl895c2d02012-09-02 14:52:59 +000015637 ctx.opcode = cpu_lduw_code(env, ctx.pc);
Nathan Froyd3c824102010-06-08 13:29:59 -070015638 insn_bytes = decode_micromips_opc(env, &ctx, &is_branch);
Aurelien Jarnod75c1352013-01-01 18:02:22 +010015639 } else if (ctx.insn_flags & ASE_MIPS16) {
Blue Swirl895c2d02012-09-02 14:52:59 +000015640 ctx.opcode = cpu_lduw_code(env, ctx.pc);
Nathan Froyd364d4832009-12-08 08:06:29 -080015641 insn_bytes = decode_mips16_opc(env, &ctx, &is_branch);
Nathan Froydc9602062009-12-08 08:06:27 -080015642 } else {
15643 generate_exception(&ctx, EXCP_RI);
Nathan Froyd3c824102010-06-08 13:29:59 -070015644 ctx.bstate = BS_STOP;
Nathan Froydc9602062009-12-08 08:06:27 -080015645 break;
15646 }
15647 if (!is_branch) {
Aurelien Jarnod75c1352013-01-01 18:02:22 +010015648 handle_delay_slot(&ctx, insn_bytes);
Nathan Froydc9602062009-12-08 08:06:27 -080015649 }
15650 ctx.pc += insn_bytes;
15651
pbrook2e70f6e2008-06-29 01:03:05 +000015652 num_insns++;
bellard4ad40f32005-12-05 19:59:36 +000015653
Nathan Froyd7b270ef2009-07-14 08:33:11 -070015654 /* Execute a branch and its delay slot as a single instruction.
15655 This is what GDB expects and is consistent with what the
15656 hardware does (e.g. if a delay slot instruction faults, the
15657 reported PC is the PC of the branch). */
15658 if (env->singlestep_enabled && (ctx.hflags & MIPS_HFLAG_BMASK) == 0)
bellard4ad40f32005-12-05 19:59:36 +000015659 break;
15660
bellard6af0bf92005-07-02 14:58:51 +000015661 if ((ctx.pc & (TARGET_PAGE_SIZE - 1)) == 0)
15662 break;
bellard4ad40f32005-12-05 19:59:36 +000015663
Evgeny Voevodinefd7f482012-11-12 13:27:45 +040015664 if (tcg_ctx.gen_opc_ptr >= gen_opc_end) {
thsfaf7aaa2008-06-11 12:26:29 +000015665 break;
Evgeny Voevodinefd7f482012-11-12 13:27:45 +040015666 }
thsfaf7aaa2008-06-11 12:26:29 +000015667
pbrook2e70f6e2008-06-29 01:03:05 +000015668 if (num_insns >= max_insns)
15669 break;
aurel321b530a62009-04-05 20:08:59 +000015670
15671 if (singlestep)
15672 break;
bellard6af0bf92005-07-02 14:58:51 +000015673 }
pbrook2e70f6e2008-06-29 01:03:05 +000015674 if (tb->cflags & CF_LAST_IO)
15675 gen_io_end();
Nathan Froyd7b270ef2009-07-14 08:33:11 -070015676 if (env->singlestep_enabled && ctx.bstate != BS_BRANCH) {
ths278d0702007-05-31 23:42:46 +000015677 save_cpu_state(&ctx, ctx.bstate == BS_NONE);
Blue Swirl895c2d02012-09-02 14:52:59 +000015678 gen_helper_0e0i(raise_exception, EXCP_DEBUG);
ths16c00cb2007-04-14 12:56:46 +000015679 } else {
aurel3269585492009-01-14 19:40:36 +000015680 switch (ctx.bstate) {
ths16c00cb2007-04-14 12:56:46 +000015681 case BS_STOP:
thsdf1561e2007-05-23 08:18:27 +000015682 gen_goto_tb(&ctx, 0, ctx.pc);
15683 break;
ths16c00cb2007-04-14 12:56:46 +000015684 case BS_NONE:
ths278d0702007-05-31 23:42:46 +000015685 save_cpu_state(&ctx, 0);
ths16c00cb2007-04-14 12:56:46 +000015686 gen_goto_tb(&ctx, 0, ctx.pc);
15687 break;
ths5a5012e2007-05-07 13:55:33 +000015688 case BS_EXCP:
bellard57fec1f2008-02-01 10:50:11 +000015689 tcg_gen_exit_tb(0);
ths5a5012e2007-05-07 13:55:33 +000015690 break;
ths16c00cb2007-04-14 12:56:46 +000015691 case BS_BRANCH:
15692 default:
15693 break;
aurel3269585492009-01-14 19:40:36 +000015694 }
bellard4ad40f32005-12-05 19:59:36 +000015695 }
bellard4ad40f32005-12-05 19:59:36 +000015696done_generating:
pbrook2e70f6e2008-06-29 01:03:05 +000015697 gen_icount_end(tb, num_insns);
Evgeny Voevodinefd7f482012-11-12 13:27:45 +040015698 *tcg_ctx.gen_opc_ptr = INDEX_op_end;
bellard6af0bf92005-07-02 14:58:51 +000015699 if (search_pc) {
Evgeny Voevodin92414b32012-11-12 13:27:47 +040015700 j = tcg_ctx.gen_opc_ptr - tcg_ctx.gen_opc_buf;
bellard6af0bf92005-07-02 14:58:51 +000015701 lj++;
15702 while (lj <= j)
Evgeny Voevodinab1103d2012-11-21 11:43:06 +040015703 tcg_ctx.gen_opc_instr_start[lj++] = 0;
bellard6af0bf92005-07-02 14:58:51 +000015704 } else {
15705 tb->size = ctx.pc - pc_start;
pbrook2e70f6e2008-06-29 01:03:05 +000015706 tb->icount = num_insns;
bellard6af0bf92005-07-02 14:58:51 +000015707 }
15708#ifdef DEBUG_DISAS
aliguorid12d51d2009-01-15 21:48:06 +000015709 LOG_DISAS("\n");
aliguori8fec2b82009-01-15 22:36:53 +000015710 if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) {
aliguori93fcfe32009-01-15 22:34:14 +000015711 qemu_log("IN: %s\n", lookup_symbol(pc_start));
Blue Swirlf4359b92012-09-08 12:40:00 +000015712 log_target_disas(env, pc_start, ctx.pc - pc_start, 0);
aliguori93fcfe32009-01-15 22:34:14 +000015713 qemu_log("\n");
bellard6af0bf92005-07-02 14:58:51 +000015714 }
bellard6af0bf92005-07-02 14:58:51 +000015715#endif
bellard6af0bf92005-07-02 14:58:51 +000015716}
15717
Andreas Färber7db13fa2012-03-14 01:38:22 +010015718void gen_intermediate_code (CPUMIPSState *env, struct TranslationBlock *tb)
bellard6af0bf92005-07-02 14:58:51 +000015719{
ths2cfc5f12008-07-18 18:01:29 +000015720 gen_intermediate_code_internal(env, tb, 0);
bellard6af0bf92005-07-02 14:58:51 +000015721}
15722
Andreas Färber7db13fa2012-03-14 01:38:22 +010015723void gen_intermediate_code_pc (CPUMIPSState *env, struct TranslationBlock *tb)
bellard6af0bf92005-07-02 14:58:51 +000015724{
ths2cfc5f12008-07-18 18:01:29 +000015725 gen_intermediate_code_internal(env, tb, 1);
bellard6af0bf92005-07-02 14:58:51 +000015726}
15727
Andreas Färber7db13fa2012-03-14 01:38:22 +010015728static void fpu_dump_state(CPUMIPSState *env, FILE *f, fprintf_function fpu_fprintf,
ths8706c382008-07-21 21:38:04 +000015729 int flags)
bellard6ea83fe2006-06-14 12:56:19 +000015730{
15731 int i;
ths5e755512007-05-29 16:52:57 +000015732 int is_fpu64 = !!(env->hflags & MIPS_HFLAG_F64);
bellard6ea83fe2006-06-14 12:56:19 +000015733
Stefan Weil2a5612e2010-04-01 23:05:14 +020015734#define printfpr(fp) \
15735 do { \
15736 if (is_fpu64) \
15737 fpu_fprintf(f, "w:%08x d:%016" PRIx64 \
15738 " fd:%13g fs:%13g psu: %13g\n", \
15739 (fp)->w[FP_ENDIAN_IDX], (fp)->d, \
15740 (double)(fp)->fd, \
15741 (double)(fp)->fs[FP_ENDIAN_IDX], \
15742 (double)(fp)->fs[!FP_ENDIAN_IDX]); \
15743 else { \
15744 fpr_t tmp; \
15745 tmp.w[FP_ENDIAN_IDX] = (fp)->w[FP_ENDIAN_IDX]; \
15746 tmp.w[!FP_ENDIAN_IDX] = ((fp) + 1)->w[FP_ENDIAN_IDX]; \
15747 fpu_fprintf(f, "w:%08x d:%016" PRIx64 \
15748 " fd:%13g fs:%13g psu:%13g\n", \
15749 tmp.w[FP_ENDIAN_IDX], tmp.d, \
15750 (double)tmp.fd, \
15751 (double)tmp.fs[FP_ENDIAN_IDX], \
15752 (double)tmp.fs[!FP_ENDIAN_IDX]); \
15753 } \
bellard6ea83fe2006-06-14 12:56:19 +000015754 } while(0)
15755
ths5a5012e2007-05-07 13:55:33 +000015756
Stefan Weil9a78eea2010-10-22 23:03:33 +020015757 fpu_fprintf(f, "CP1 FCR0 0x%08x FCR31 0x%08x SR.FR %d fp_status 0x%02x\n",
15758 env->active_fpu.fcr0, env->active_fpu.fcr31, is_fpu64,
thsf01be152008-09-18 11:57:27 +000015759 get_float_exception_flags(&env->active_fpu.fp_status));
ths5a5012e2007-05-07 13:55:33 +000015760 for (i = 0; i < 32; (is_fpu64) ? i++ : (i += 2)) {
15761 fpu_fprintf(f, "%3s: ", fregnames[i]);
thsf01be152008-09-18 11:57:27 +000015762 printfpr(&env->active_fpu.fpr[i]);
bellard6ea83fe2006-06-14 12:56:19 +000015763 }
15764
15765#undef printfpr
15766}
15767
thsd26bc212007-11-08 18:05:37 +000015768#if defined(TARGET_MIPS64) && defined(MIPS_DEBUG_SIGN_EXTENSIONS)
thsc570fd12006-12-21 01:19:56 +000015769/* Debug help: The architecture requires 32bit code to maintain proper
thsc7e8a932008-07-05 21:54:32 +000015770 sign-extended values on 64bit machines. */
thsc570fd12006-12-21 01:19:56 +000015771
15772#define SIGN_EXT_P(val) ((((val) & ~0x7fffffff) == 0) || (((val) & ~0x7fffffff) == ~0x7fffffff))
15773
ths8706c382008-07-21 21:38:04 +000015774static void
Andreas Färber7db13fa2012-03-14 01:38:22 +010015775cpu_mips_check_sign_extensions (CPUMIPSState *env, FILE *f,
Stefan Weil9a78eea2010-10-22 23:03:33 +020015776 fprintf_function cpu_fprintf,
ths8706c382008-07-21 21:38:04 +000015777 int flags)
thsc570fd12006-12-21 01:19:56 +000015778{
15779 int i;
15780
thsb5dc7732008-06-27 10:02:35 +000015781 if (!SIGN_EXT_P(env->active_tc.PC))
15782 cpu_fprintf(f, "BROKEN: pc=0x" TARGET_FMT_lx "\n", env->active_tc.PC);
15783 if (!SIGN_EXT_P(env->active_tc.HI[0]))
15784 cpu_fprintf(f, "BROKEN: HI=0x" TARGET_FMT_lx "\n", env->active_tc.HI[0]);
15785 if (!SIGN_EXT_P(env->active_tc.LO[0]))
15786 cpu_fprintf(f, "BROKEN: LO=0x" TARGET_FMT_lx "\n", env->active_tc.LO[0]);
thsc570fd12006-12-21 01:19:56 +000015787 if (!SIGN_EXT_P(env->btarget))
ths3594c772007-02-20 23:37:21 +000015788 cpu_fprintf(f, "BROKEN: btarget=0x" TARGET_FMT_lx "\n", env->btarget);
thsc570fd12006-12-21 01:19:56 +000015789
15790 for (i = 0; i < 32; i++) {
thsb5dc7732008-06-27 10:02:35 +000015791 if (!SIGN_EXT_P(env->active_tc.gpr[i]))
15792 cpu_fprintf(f, "BROKEN: %s=0x" TARGET_FMT_lx "\n", regnames[i], env->active_tc.gpr[i]);
thsc570fd12006-12-21 01:19:56 +000015793 }
15794
15795 if (!SIGN_EXT_P(env->CP0_EPC))
ths3594c772007-02-20 23:37:21 +000015796 cpu_fprintf(f, "BROKEN: EPC=0x" TARGET_FMT_lx "\n", env->CP0_EPC);
Aurelien Jarno5499b6f2009-11-22 13:08:14 +010015797 if (!SIGN_EXT_P(env->lladdr))
15798 cpu_fprintf(f, "BROKEN: LLAddr=0x" TARGET_FMT_lx "\n", env->lladdr);
thsc570fd12006-12-21 01:19:56 +000015799}
15800#endif
15801
Andreas Färber7db13fa2012-03-14 01:38:22 +010015802void cpu_dump_state (CPUMIPSState *env, FILE *f, fprintf_function cpu_fprintf,
bellard6af0bf92005-07-02 14:58:51 +000015803 int flags)
15804{
15805 int i;
ths3b46e622007-09-17 08:09:54 +000015806
Stefan Weila7200c92010-04-02 23:19:48 +020015807 cpu_fprintf(f, "pc=0x" TARGET_FMT_lx " HI=0x" TARGET_FMT_lx
15808 " LO=0x" TARGET_FMT_lx " ds %04x "
15809 TARGET_FMT_lx " " TARGET_FMT_ld "\n",
ths3d5be872008-07-21 07:46:03 +000015810 env->active_tc.PC, env->active_tc.HI[0], env->active_tc.LO[0],
15811 env->hflags, env->btarget, env->bcond);
bellard6af0bf92005-07-02 14:58:51 +000015812 for (i = 0; i < 32; i++) {
15813 if ((i & 3) == 0)
15814 cpu_fprintf(f, "GPR%02d:", i);
thsb5dc7732008-06-27 10:02:35 +000015815 cpu_fprintf(f, " %s " TARGET_FMT_lx, regnames[i], env->active_tc.gpr[i]);
bellard6af0bf92005-07-02 14:58:51 +000015816 if ((i & 3) == 3)
15817 cpu_fprintf(f, "\n");
15818 }
bellard568b6002005-07-02 15:28:16 +000015819
ths3594c772007-02-20 23:37:21 +000015820 cpu_fprintf(f, "CP0 Status 0x%08x Cause 0x%08x EPC 0x" TARGET_FMT_lx "\n",
ths5e755512007-05-29 16:52:57 +000015821 env->CP0_Status, env->CP0_Cause, env->CP0_EPC);
ths3594c772007-02-20 23:37:21 +000015822 cpu_fprintf(f, " Config0 0x%08x Config1 0x%08x LLAddr 0x" TARGET_FMT_lx "\n",
Aurelien Jarno5499b6f2009-11-22 13:08:14 +010015823 env->CP0_Config0, env->CP0_Config1, env->lladdr);
ths5e755512007-05-29 16:52:57 +000015824 if (env->hflags & MIPS_HFLAG_FPU)
ths7a387ff2006-12-06 20:17:30 +000015825 fpu_dump_state(env, f, cpu_fprintf, flags);
thsd26bc212007-11-08 18:05:37 +000015826#if defined(TARGET_MIPS64) && defined(MIPS_DEBUG_SIGN_EXTENSIONS)
thsc570fd12006-12-21 01:19:56 +000015827 cpu_mips_check_sign_extensions(env, f, cpu_fprintf, flags);
15828#endif
bellard6af0bf92005-07-02 14:58:51 +000015829}
15830
Andreas Färber78ce64f2013-01-20 01:22:25 +010015831void mips_tcg_init(void)
ths39454622008-05-04 08:16:10 +000015832{
thsf01be152008-09-18 11:57:27 +000015833 int i;
ths39454622008-05-04 08:16:10 +000015834 static int inited;
15835
15836 /* Initialize various static tables. */
15837 if (inited)
aurel3269585492009-01-14 19:40:36 +000015838 return;
ths39454622008-05-04 08:16:10 +000015839
pbrooka7812ae2008-11-17 14:43:54 +000015840 cpu_env = tcg_global_reg_new_ptr(TCG_AREG0, "env");
aurel32f2c94b92009-04-15 14:42:00 +000015841 TCGV_UNUSED(cpu_gpr[0]);
aurel32bb928db2009-04-11 18:43:20 +000015842 for (i = 1; i < 32; i++)
pbrooka7812ae2008-11-17 14:43:54 +000015843 cpu_gpr[i] = tcg_global_mem_new(TCG_AREG0,
Andreas Färber7db13fa2012-03-14 01:38:22 +010015844 offsetof(CPUMIPSState, active_tc.gpr[i]),
ths4b2eb8d2008-09-18 11:59:03 +000015845 regnames[i]);
Richard Hendersond73ee8a2012-10-09 21:53:19 +020015846
15847 for (i = 0; i < 32; i++) {
15848 int off = offsetof(CPUMIPSState, active_fpu.fpr[i]);
15849 fpu_f64[i] = tcg_global_mem_new_i64(TCG_AREG0, off, fregnames[i]);
15850 }
15851
pbrooka7812ae2008-11-17 14:43:54 +000015852 cpu_PC = tcg_global_mem_new(TCG_AREG0,
Andreas Färber7db13fa2012-03-14 01:38:22 +010015853 offsetof(CPUMIPSState, active_tc.PC), "PC");
ths4b2eb8d2008-09-18 11:59:03 +000015854 for (i = 0; i < MIPS_DSP_ACC; i++) {
pbrooka7812ae2008-11-17 14:43:54 +000015855 cpu_HI[i] = tcg_global_mem_new(TCG_AREG0,
Andreas Färber7db13fa2012-03-14 01:38:22 +010015856 offsetof(CPUMIPSState, active_tc.HI[i]),
ths4b2eb8d2008-09-18 11:59:03 +000015857 regnames_HI[i]);
pbrooka7812ae2008-11-17 14:43:54 +000015858 cpu_LO[i] = tcg_global_mem_new(TCG_AREG0,
Andreas Färber7db13fa2012-03-14 01:38:22 +010015859 offsetof(CPUMIPSState, active_tc.LO[i]),
ths4b2eb8d2008-09-18 11:59:03 +000015860 regnames_LO[i]);
pbrooka7812ae2008-11-17 14:43:54 +000015861 cpu_ACX[i] = tcg_global_mem_new(TCG_AREG0,
Andreas Färber7db13fa2012-03-14 01:38:22 +010015862 offsetof(CPUMIPSState, active_tc.ACX[i]),
ths4b2eb8d2008-09-18 11:59:03 +000015863 regnames_ACX[i]);
15864 }
pbrooka7812ae2008-11-17 14:43:54 +000015865 cpu_dspctrl = tcg_global_mem_new(TCG_AREG0,
Andreas Färber7db13fa2012-03-14 01:38:22 +010015866 offsetof(CPUMIPSState, active_tc.DSPControl),
ths4b2eb8d2008-09-18 11:59:03 +000015867 "DSPControl");
aurel321ba74fb2009-03-29 01:18:52 +000015868 bcond = tcg_global_mem_new(TCG_AREG0,
Andreas Färber7db13fa2012-03-14 01:38:22 +010015869 offsetof(CPUMIPSState, bcond), "bcond");
pbrooka7812ae2008-11-17 14:43:54 +000015870 btarget = tcg_global_mem_new(TCG_AREG0,
Andreas Färber7db13fa2012-03-14 01:38:22 +010015871 offsetof(CPUMIPSState, btarget), "btarget");
aurel3241db4602009-03-29 01:28:29 +000015872 hflags = tcg_global_mem_new_i32(TCG_AREG0,
Andreas Färber7db13fa2012-03-14 01:38:22 +010015873 offsetof(CPUMIPSState, hflags), "hflags");
aurel3241db4602009-03-29 01:28:29 +000015874
pbrooka7812ae2008-11-17 14:43:54 +000015875 fpu_fcr0 = tcg_global_mem_new_i32(TCG_AREG0,
Andreas Färber7db13fa2012-03-14 01:38:22 +010015876 offsetof(CPUMIPSState, active_fpu.fcr0),
pbrooka7812ae2008-11-17 14:43:54 +000015877 "fcr0");
15878 fpu_fcr31 = tcg_global_mem_new_i32(TCG_AREG0,
Andreas Färber7db13fa2012-03-14 01:38:22 +010015879 offsetof(CPUMIPSState, active_fpu.fcr31),
pbrooka7812ae2008-11-17 14:43:54 +000015880 "fcr31");
ths39454622008-05-04 08:16:10 +000015881
ths7dd9e552008-06-08 07:42:23 +000015882 /* register helpers */
pbrooka7812ae2008-11-17 14:43:54 +000015883#define GEN_HELPER 2
ths7dd9e552008-06-08 07:42:23 +000015884#include "helper.h"
15885
ths39454622008-05-04 08:16:10 +000015886 inited = 1;
15887}
15888
bellardaaed9092007-11-10 15:15:54 +000015889#include "translate_init.c"
15890
Andreas Färber30bf9422012-05-05 13:33:04 +020015891MIPSCPU *cpu_mips_init(const char *cpu_model)
bellard6af0bf92005-07-02 14:58:51 +000015892{
Andreas Färber0f71a702012-04-15 23:29:19 +020015893 MIPSCPU *cpu;
bellard6af0bf92005-07-02 14:58:51 +000015894 CPUMIPSState *env;
Anthony Liguoric227f092009-10-01 16:12:16 -050015895 const mips_def_t *def;
bellard6af0bf92005-07-02 14:58:51 +000015896
bellardaaed9092007-11-10 15:15:54 +000015897 def = cpu_mips_find_by_name(cpu_model);
15898 if (!def)
15899 return NULL;
Andreas Färber0f71a702012-04-15 23:29:19 +020015900 cpu = MIPS_CPU(object_new(TYPE_MIPS_CPU));
15901 env = &cpu->env;
bellardaaed9092007-11-10 15:15:54 +000015902 env->cpu_model = def;
Blue Swirl51cc2e72009-11-08 12:50:21 +020015903 env->cpu_model_str = cpu_model;
bellardaaed9092007-11-10 15:15:54 +000015904
Blue Swirl51cc2e72009-11-08 12:50:21 +020015905#ifndef CONFIG_USER_ONLY
15906 mmu_init(env, def);
15907#endif
15908 fpu_init(env, def);
15909 mvp_init(env, def);
Andreas Färberc1caf1d2013-01-16 03:48:37 +010015910
15911 object_property_set_bool(OBJECT(cpu), true, "realized", NULL);
15912
Andreas Färber30bf9422012-05-05 13:33:04 +020015913 return cpu;
ths6ae81772006-12-06 17:48:52 +000015914}
15915
Andreas Färber1bba0dc2012-02-08 03:03:33 +010015916void cpu_state_reset(CPUMIPSState *env)
ths6ae81772006-12-06 17:48:52 +000015917{
Andreas Färber55e5c282012-12-17 06:18:02 +010015918#ifndef CONFIG_USER_ONLY
15919 MIPSCPU *cpu = mips_env_get_cpu(env);
15920 CPUState *cs = CPU(cpu);
15921#endif
ths6ae81772006-12-06 17:48:52 +000015922
Blue Swirl51cc2e72009-11-08 12:50:21 +020015923 /* Reset registers to their default values */
15924 env->CP0_PRid = env->cpu_model->CP0_PRid;
15925 env->CP0_Config0 = env->cpu_model->CP0_Config0;
15926#ifdef TARGET_WORDS_BIGENDIAN
15927 env->CP0_Config0 |= (1 << CP0C0_BE);
15928#endif
15929 env->CP0_Config1 = env->cpu_model->CP0_Config1;
15930 env->CP0_Config2 = env->cpu_model->CP0_Config2;
15931 env->CP0_Config3 = env->cpu_model->CP0_Config3;
15932 env->CP0_Config6 = env->cpu_model->CP0_Config6;
15933 env->CP0_Config7 = env->cpu_model->CP0_Config7;
Aurelien Jarno2a6e32d2009-11-22 13:22:54 +010015934 env->CP0_LLAddr_rw_bitmask = env->cpu_model->CP0_LLAddr_rw_bitmask
15935 << env->cpu_model->CP0_LLAddr_shift;
15936 env->CP0_LLAddr_shift = env->cpu_model->CP0_LLAddr_shift;
Blue Swirl51cc2e72009-11-08 12:50:21 +020015937 env->SYNCI_Step = env->cpu_model->SYNCI_Step;
15938 env->CCRes = env->cpu_model->CCRes;
15939 env->CP0_Status_rw_bitmask = env->cpu_model->CP0_Status_rw_bitmask;
15940 env->CP0_TCStatus_rw_bitmask = env->cpu_model->CP0_TCStatus_rw_bitmask;
15941 env->CP0_SRSCtl = env->cpu_model->CP0_SRSCtl;
15942 env->current_tc = 0;
15943 env->SEGBITS = env->cpu_model->SEGBITS;
15944 env->SEGMask = (target_ulong)((1ULL << env->cpu_model->SEGBITS) - 1);
15945#if defined(TARGET_MIPS64)
15946 if (env->cpu_model->insn_flags & ISA_MIPS3) {
15947 env->SEGMask |= 3ULL << 62;
15948 }
15949#endif
15950 env->PABITS = env->cpu_model->PABITS;
15951 env->PAMask = (target_ulong)((1ULL << env->cpu_model->PABITS) - 1);
15952 env->CP0_SRSConf0_rw_bitmask = env->cpu_model->CP0_SRSConf0_rw_bitmask;
15953 env->CP0_SRSConf0 = env->cpu_model->CP0_SRSConf0;
15954 env->CP0_SRSConf1_rw_bitmask = env->cpu_model->CP0_SRSConf1_rw_bitmask;
15955 env->CP0_SRSConf1 = env->cpu_model->CP0_SRSConf1;
15956 env->CP0_SRSConf2_rw_bitmask = env->cpu_model->CP0_SRSConf2_rw_bitmask;
15957 env->CP0_SRSConf2 = env->cpu_model->CP0_SRSConf2;
15958 env->CP0_SRSConf3_rw_bitmask = env->cpu_model->CP0_SRSConf3_rw_bitmask;
15959 env->CP0_SRSConf3 = env->cpu_model->CP0_SRSConf3;
15960 env->CP0_SRSConf4_rw_bitmask = env->cpu_model->CP0_SRSConf4_rw_bitmask;
15961 env->CP0_SRSConf4 = env->cpu_model->CP0_SRSConf4;
Nathan Froydf1cb0952012-06-07 15:04:14 +000015962 env->active_fpu.fcr0 = env->cpu_model->CP1_fcr0;
Blue Swirl51cc2e72009-11-08 12:50:21 +020015963 env->insn_flags = env->cpu_model->insn_flags;
15964
bellardeeef26c2005-11-26 18:47:06 +000015965#if defined(CONFIG_USER_ONLY)
Maciej W. Rozycki03e6e502012-06-08 02:04:40 +010015966 env->CP0_Status = (MIPS_HFLAG_UM << CP0St_KSU);
Meador Inge94159132012-08-21 12:31:37 -050015967 /* Enable access to the CPUNum, SYNCI_Step, CC, and CCRes RDHWR
15968 hardware registers. */
15969 env->CP0_HWREna |= 0x0000000F;
Nathan Froyd91a75932009-12-11 09:29:20 -080015970 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
Maciej W. Rozycki03e6e502012-06-08 02:04:40 +010015971 env->CP0_Status |= (1 << CP0St_CU1);
Nathan Froyd91a75932009-12-11 09:29:20 -080015972 }
Petar Jovanovic6f0af302013-01-23 03:57:02 +010015973 if (env->CP0_Config3 & (1 << CP0C3_DSPP)) {
15974 env->CP0_Status |= (1 << CP0St_MX);
Jia Liu853c3242012-10-24 22:17:02 +080015975 }
aurel32932e71c2009-01-12 21:33:13 +000015976#else
15977 if (env->hflags & MIPS_HFLAG_BMASK) {
15978 /* If the exception was raised from a delay slot,
15979 come back to the jump. */
15980 env->CP0_ErrorEPC = env->active_tc.PC - 4;
ths0eaef5a2008-07-23 16:14:22 +000015981 } else {
aurel32932e71c2009-01-12 21:33:13 +000015982 env->CP0_ErrorEPC = env->active_tc.PC;
ths0eaef5a2008-07-23 16:14:22 +000015983 }
aurel32932e71c2009-01-12 21:33:13 +000015984 env->active_tc.PC = (int32_t)0xBFC00000;
Blue Swirl51cc2e72009-11-08 12:50:21 +020015985 env->CP0_Random = env->tlb->nb_tlb - 1;
15986 env->tlb->tlb_in_use = env->tlb->nb_tlb;
aurel32932e71c2009-01-12 21:33:13 +000015987 env->CP0_Wired = 0;
Andreas Färber55e5c282012-12-17 06:18:02 +010015988 env->CP0_EBase = 0x80000000 | (cs->cpu_index & 0x3FF);
aurel32932e71c2009-01-12 21:33:13 +000015989 env->CP0_Status = (1 << CP0St_BEV) | (1 << CP0St_ERL);
15990 /* vectored interrupts not implemented, timer on int 7,
15991 no performance counters. */
15992 env->CP0_IntCtl = 0xe0000000;
15993 {
15994 int i;
15995
15996 for (i = 0; i < 7; i++) {
15997 env->CP0_WatchLo[i] = 0;
15998 env->CP0_WatchHi[i] = 0x80000000;
15999 }
16000 env->CP0_WatchLo[7] = 0;
16001 env->CP0_WatchHi[7] = 0;
16002 }
16003 /* Count register increments in debug mode, EJTAG version 1 */
16004 env->CP0_Debug = (1 << CP0DB_CNT) | (0x1 << CP0DB_VER);
Edgar E. Iglesias9e56e752011-08-29 23:07:39 +020016005
16006 if (env->CP0_Config3 & (1 << CP0C3_MT)) {
16007 int i;
16008
16009 /* Only TC0 on VPE 0 starts as active. */
16010 for (i = 0; i < ARRAY_SIZE(env->tcs); i++) {
Andreas Färber55e5c282012-12-17 06:18:02 +010016011 env->tcs[i].CP0_TCBind = cs->cpu_index << CP0TCBd_CurVPE;
Edgar E. Iglesias9e56e752011-08-29 23:07:39 +020016012 env->tcs[i].CP0_TCHalt = 1;
16013 }
16014 env->active_tc.CP0_TCHalt = 1;
16015 env->halted = 1;
16016
Andreas Färber55e5c282012-12-17 06:18:02 +010016017 if (cs->cpu_index == 0) {
Edgar E. Iglesias9e56e752011-08-29 23:07:39 +020016018 /* VPE0 starts up enabled. */
16019 env->mvp->CP0_MVPControl |= (1 << CP0MVPCo_EVP);
16020 env->CP0_VPEConf0 |= (1 << CP0VPEC0_MVP) | (1 << CP0VPEC0_VPA);
16021
16022 /* TC0 starts up unhalted. */
16023 env->halted = 0;
16024 env->active_tc.CP0_TCHalt = 0;
16025 env->tcs[0].CP0_TCHalt = 0;
16026 /* With thread 0 active. */
16027 env->active_tc.CP0_TCStatus = (1 << CP0TCSt_A);
16028 env->tcs[0].CP0_TCStatus = (1 << CP0TCSt_A);
16029 }
16030 }
aurel32932e71c2009-01-12 21:33:13 +000016031#endif
Maciej W. Rozycki03e6e502012-06-08 02:04:40 +010016032 compute_hflags(env);
ths0eaef5a2008-07-23 16:14:22 +000016033 env->exception_index = EXCP_NONE;
bellard6af0bf92005-07-02 14:58:51 +000016034}
aurel32d2856f12008-04-28 00:32:32 +000016035
Andreas Färber7db13fa2012-03-14 01:38:22 +010016036void restore_state_to_opc(CPUMIPSState *env, TranslationBlock *tb, int pc_pos)
aurel32d2856f12008-04-28 00:32:32 +000016037{
Evgeny Voevodin25983ca2012-11-21 11:43:04 +040016038 env->active_tc.PC = tcg_ctx.gen_opc_pc[pc_pos];
aurel32d2856f12008-04-28 00:32:32 +000016039 env->hflags &= ~MIPS_HFLAG_BMASK;
16040 env->hflags |= gen_opc_hflags[pc_pos];
Aurelien Jarno46364012012-10-28 15:42:55 +010016041 switch (env->hflags & MIPS_HFLAG_BMASK_BASE) {
16042 case MIPS_HFLAG_BR:
16043 break;
16044 case MIPS_HFLAG_BC:
16045 case MIPS_HFLAG_BL:
16046 case MIPS_HFLAG_B:
16047 env->btarget = gen_opc_btarget[pc_pos];
16048 break;
16049 }
aurel32d2856f12008-04-28 00:32:32 +000016050}