translate.c 241.8 KB
Newer Older
B
bellard 已提交
1 2
/*
 *  MIPS32 emulation for qemu: main translation routines.
3
 *
B
bellard 已提交
4
 *  Copyright (c) 2004-2005 Jocelyn Mayer
B
bellard 已提交
5
 *  Copyright (c) 2006 Marius Groeger (FPU operations)
T
ths 已提交
6
 *  Copyright (c) 2006 Thiemo Seufer (MIPS32R2 support)
B
bellard 已提交
7 8 9 10 11 12 13 14 15 16 17 18 19
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
20
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA  02110-1301 USA
B
bellard 已提交
21 22 23 24 25 26 27 28 29 30 31
 */

#include <stdarg.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <inttypes.h>

#include "cpu.h"
#include "exec-all.h"
#include "disas.h"
B
bellard 已提交
32
#include "tcg-op.h"
33
#include "qemu-common.h"
B
bellard 已提交
34

P
pbrook 已提交
35 36 37 38
#include "helper.h"
#define GEN_HELPER 1
#include "helper.h"

39
//#define MIPS_DEBUG_DISAS
40
//#define MIPS_DEBUG_SIGN_EXTENSIONS
B
bellard 已提交
41

42 43
/* MIPS major opcodes */
#define MASK_OP_MAJOR(op)  (op & (0x3F << 26))
44 45 46

enum {
    /* indirect opcode tables */
47 48 49 50 51 52 53 54
    OPC_SPECIAL  = (0x00 << 26),
    OPC_REGIMM   = (0x01 << 26),
    OPC_CP0      = (0x10 << 26),
    OPC_CP1      = (0x11 << 26),
    OPC_CP2      = (0x12 << 26),
    OPC_CP3      = (0x13 << 26),
    OPC_SPECIAL2 = (0x1C << 26),
    OPC_SPECIAL3 = (0x1F << 26),
55
    /* arithmetic with immediate */
56 57 58 59 60 61 62 63 64 65
    OPC_ADDI     = (0x08 << 26),
    OPC_ADDIU    = (0x09 << 26),
    OPC_SLTI     = (0x0A << 26),
    OPC_SLTIU    = (0x0B << 26),
    OPC_ANDI     = (0x0C << 26),
    OPC_ORI      = (0x0D << 26),
    OPC_XORI     = (0x0E << 26),
    OPC_LUI      = (0x0F << 26),
    OPC_DADDI    = (0x18 << 26),
    OPC_DADDIU   = (0x19 << 26),
66
    /* Jump and branches */
67 68 69 70 71 72 73 74 75 76 77
    OPC_J        = (0x02 << 26),
    OPC_JAL      = (0x03 << 26),
    OPC_BEQ      = (0x04 << 26),  /* Unconditional if rs = rt = 0 (B) */
    OPC_BEQL     = (0x14 << 26),
    OPC_BNE      = (0x05 << 26),
    OPC_BNEL     = (0x15 << 26),
    OPC_BLEZ     = (0x06 << 26),
    OPC_BLEZL    = (0x16 << 26),
    OPC_BGTZ     = (0x07 << 26),
    OPC_BGTZL    = (0x17 << 26),
    OPC_JALX     = (0x1D << 26),  /* MIPS 16 only */
78
    /* Load and stores */
79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101
    OPC_LDL      = (0x1A << 26),
    OPC_LDR      = (0x1B << 26),
    OPC_LB       = (0x20 << 26),
    OPC_LH       = (0x21 << 26),
    OPC_LWL      = (0x22 << 26),
    OPC_LW       = (0x23 << 26),
    OPC_LBU      = (0x24 << 26),
    OPC_LHU      = (0x25 << 26),
    OPC_LWR      = (0x26 << 26),
    OPC_LWU      = (0x27 << 26),
    OPC_SB       = (0x28 << 26),
    OPC_SH       = (0x29 << 26),
    OPC_SWL      = (0x2A << 26),
    OPC_SW       = (0x2B << 26),
    OPC_SDL      = (0x2C << 26),
    OPC_SDR      = (0x2D << 26),
    OPC_SWR      = (0x2E << 26),
    OPC_LL       = (0x30 << 26),
    OPC_LLD      = (0x34 << 26),
    OPC_LD       = (0x37 << 26),
    OPC_SC       = (0x38 << 26),
    OPC_SCD      = (0x3C << 26),
    OPC_SD       = (0x3F << 26),
102
    /* Floating point load/store */
103 104 105 106 107 108 109 110 111 112
    OPC_LWC1     = (0x31 << 26),
    OPC_LWC2     = (0x32 << 26),
    OPC_LDC1     = (0x35 << 26),
    OPC_LDC2     = (0x36 << 26),
    OPC_SWC1     = (0x39 << 26),
    OPC_SWC2     = (0x3A << 26),
    OPC_SDC1     = (0x3D << 26),
    OPC_SDC2     = (0x3E << 26),
    /* MDMX ASE specific */
    OPC_MDMX     = (0x1E << 26),
113
    /* Cache and prefetch */
114 115 116 117
    OPC_CACHE    = (0x2F << 26),
    OPC_PREF     = (0x33 << 26),
    /* Reserved major opcode */
    OPC_MAJOR3B_RESERVED = (0x3B << 26),
118 119 120
};

/* MIPS special opcodes */
121 122
#define MASK_SPECIAL(op)   MASK_OP_MAJOR(op) | (op & 0x3F)

123 124
enum {
    /* Shifts */
125
    OPC_SLL      = 0x00 | OPC_SPECIAL,
126 127
    /* NOP is SLL r0, r0, 0   */
    /* SSNOP is SLL r0, r0, 1 */
128 129 130 131
    /* EHB is SLL r0, r0, 3 */
    OPC_SRL      = 0x02 | OPC_SPECIAL, /* also ROTR */
    OPC_SRA      = 0x03 | OPC_SPECIAL,
    OPC_SLLV     = 0x04 | OPC_SPECIAL,
132
    OPC_SRLV     = 0x06 | OPC_SPECIAL, /* also ROTRV */
133 134 135 136 137 138 139 140 141 142
    OPC_SRAV     = 0x07 | OPC_SPECIAL,
    OPC_DSLLV    = 0x14 | OPC_SPECIAL,
    OPC_DSRLV    = 0x16 | OPC_SPECIAL, /* also DROTRV */
    OPC_DSRAV    = 0x17 | OPC_SPECIAL,
    OPC_DSLL     = 0x38 | OPC_SPECIAL,
    OPC_DSRL     = 0x3A | OPC_SPECIAL, /* also DROTR */
    OPC_DSRA     = 0x3B | OPC_SPECIAL,
    OPC_DSLL32   = 0x3C | OPC_SPECIAL,
    OPC_DSRL32   = 0x3E | OPC_SPECIAL, /* also DROTR32 */
    OPC_DSRA32   = 0x3F | OPC_SPECIAL,
143
    /* Multiplication / division */
144 145 146 147 148 149 150 151
    OPC_MULT     = 0x18 | OPC_SPECIAL,
    OPC_MULTU    = 0x19 | OPC_SPECIAL,
    OPC_DIV      = 0x1A | OPC_SPECIAL,
    OPC_DIVU     = 0x1B | OPC_SPECIAL,
    OPC_DMULT    = 0x1C | OPC_SPECIAL,
    OPC_DMULTU   = 0x1D | OPC_SPECIAL,
    OPC_DDIV     = 0x1E | OPC_SPECIAL,
    OPC_DDIVU    = 0x1F | OPC_SPECIAL,
152
    /* 2 registers arithmetic / logic */
153 154 155 156 157 158 159 160 161 162 163 164 165 166
    OPC_ADD      = 0x20 | OPC_SPECIAL,
    OPC_ADDU     = 0x21 | OPC_SPECIAL,
    OPC_SUB      = 0x22 | OPC_SPECIAL,
    OPC_SUBU     = 0x23 | OPC_SPECIAL,
    OPC_AND      = 0x24 | OPC_SPECIAL,
    OPC_OR       = 0x25 | OPC_SPECIAL,
    OPC_XOR      = 0x26 | OPC_SPECIAL,
    OPC_NOR      = 0x27 | OPC_SPECIAL,
    OPC_SLT      = 0x2A | OPC_SPECIAL,
    OPC_SLTU     = 0x2B | OPC_SPECIAL,
    OPC_DADD     = 0x2C | OPC_SPECIAL,
    OPC_DADDU    = 0x2D | OPC_SPECIAL,
    OPC_DSUB     = 0x2E | OPC_SPECIAL,
    OPC_DSUBU    = 0x2F | OPC_SPECIAL,
167
    /* Jumps */
168 169
    OPC_JR       = 0x08 | OPC_SPECIAL, /* Also JR.HB */
    OPC_JALR     = 0x09 | OPC_SPECIAL, /* Also JALR.HB */
170
    /* Traps */
171 172 173 174 175 176
    OPC_TGE      = 0x30 | OPC_SPECIAL,
    OPC_TGEU     = 0x31 | OPC_SPECIAL,
    OPC_TLT      = 0x32 | OPC_SPECIAL,
    OPC_TLTU     = 0x33 | OPC_SPECIAL,
    OPC_TEQ      = 0x34 | OPC_SPECIAL,
    OPC_TNE      = 0x36 | OPC_SPECIAL,
177
    /* HI / LO registers load & stores */
178 179 180 181
    OPC_MFHI     = 0x10 | OPC_SPECIAL,
    OPC_MTHI     = 0x11 | OPC_SPECIAL,
    OPC_MFLO     = 0x12 | OPC_SPECIAL,
    OPC_MTLO     = 0x13 | OPC_SPECIAL,
182
    /* Conditional moves */
183 184
    OPC_MOVZ     = 0x0A | OPC_SPECIAL,
    OPC_MOVN     = 0x0B | OPC_SPECIAL,
185

186
    OPC_MOVCI    = 0x01 | OPC_SPECIAL,
187 188

    /* Special */
189 190 191 192 193 194 195 196 197 198 199 200 201 202 203
    OPC_PMON     = 0x05 | OPC_SPECIAL, /* inofficial */
    OPC_SYSCALL  = 0x0C | OPC_SPECIAL,
    OPC_BREAK    = 0x0D | OPC_SPECIAL,
    OPC_SPIM     = 0x0E | OPC_SPECIAL, /* inofficial */
    OPC_SYNC     = 0x0F | OPC_SPECIAL,

    OPC_SPECIAL15_RESERVED = 0x15 | OPC_SPECIAL,
    OPC_SPECIAL28_RESERVED = 0x28 | OPC_SPECIAL,
    OPC_SPECIAL29_RESERVED = 0x29 | OPC_SPECIAL,
    OPC_SPECIAL35_RESERVED = 0x35 | OPC_SPECIAL,
    OPC_SPECIAL37_RESERVED = 0x37 | OPC_SPECIAL,
    OPC_SPECIAL39_RESERVED = 0x39 | OPC_SPECIAL,
    OPC_SPECIAL3D_RESERVED = 0x3D | OPC_SPECIAL,
};

204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223
/* Multiplication variants of the vr54xx. */
#define MASK_MUL_VR54XX(op)   MASK_SPECIAL(op) | (op & (0x1F << 6))

enum {
    OPC_VR54XX_MULS    = (0x03 << 6) | OPC_MULT,
    OPC_VR54XX_MULSU   = (0x03 << 6) | OPC_MULTU,
    OPC_VR54XX_MACC    = (0x05 << 6) | OPC_MULT,
    OPC_VR54XX_MACCU   = (0x05 << 6) | OPC_MULTU,
    OPC_VR54XX_MSAC    = (0x07 << 6) | OPC_MULT,
    OPC_VR54XX_MSACU   = (0x07 << 6) | OPC_MULTU,
    OPC_VR54XX_MULHI   = (0x09 << 6) | OPC_MULT,
    OPC_VR54XX_MULHIU  = (0x09 << 6) | OPC_MULTU,
    OPC_VR54XX_MULSHI  = (0x0B << 6) | OPC_MULT,
    OPC_VR54XX_MULSHIU = (0x0B << 6) | OPC_MULTU,
    OPC_VR54XX_MACCHI  = (0x0D << 6) | OPC_MULT,
    OPC_VR54XX_MACCHIU = (0x0D << 6) | OPC_MULTU,
    OPC_VR54XX_MSACHI  = (0x0F << 6) | OPC_MULT,
    OPC_VR54XX_MSACHIU = (0x0F << 6) | OPC_MULTU,
};

224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242
/* REGIMM (rt field) opcodes */
#define MASK_REGIMM(op)    MASK_OP_MAJOR(op) | (op & (0x1F << 16))

enum {
    OPC_BLTZ     = (0x00 << 16) | OPC_REGIMM,
    OPC_BLTZL    = (0x02 << 16) | OPC_REGIMM,
    OPC_BGEZ     = (0x01 << 16) | OPC_REGIMM,
    OPC_BGEZL    = (0x03 << 16) | OPC_REGIMM,
    OPC_BLTZAL   = (0x10 << 16) | OPC_REGIMM,
    OPC_BLTZALL  = (0x12 << 16) | OPC_REGIMM,
    OPC_BGEZAL   = (0x11 << 16) | OPC_REGIMM,
    OPC_BGEZALL  = (0x13 << 16) | OPC_REGIMM,
    OPC_TGEI     = (0x08 << 16) | OPC_REGIMM,
    OPC_TGEIU    = (0x09 << 16) | OPC_REGIMM,
    OPC_TLTI     = (0x0A << 16) | OPC_REGIMM,
    OPC_TLTIU    = (0x0B << 16) | OPC_REGIMM,
    OPC_TEQI     = (0x0C << 16) | OPC_REGIMM,
    OPC_TNEI     = (0x0E << 16) | OPC_REGIMM,
    OPC_SYNCI    = (0x1F << 16) | OPC_REGIMM,
243 244
};

245 246 247
/* Special2 opcodes */
#define MASK_SPECIAL2(op)  MASK_OP_MAJOR(op) | (op & 0x3F)

248
enum {
249 250 251 252 253 254
    /* Multiply & xxx operations */
    OPC_MADD     = 0x00 | OPC_SPECIAL2,
    OPC_MADDU    = 0x01 | OPC_SPECIAL2,
    OPC_MUL      = 0x02 | OPC_SPECIAL2,
    OPC_MSUB     = 0x04 | OPC_SPECIAL2,
    OPC_MSUBU    = 0x05 | OPC_SPECIAL2,
255
    /* Misc */
256 257 258 259
    OPC_CLZ      = 0x20 | OPC_SPECIAL2,
    OPC_CLO      = 0x21 | OPC_SPECIAL2,
    OPC_DCLZ     = 0x24 | OPC_SPECIAL2,
    OPC_DCLO     = 0x25 | OPC_SPECIAL2,
260
    /* Special */
261 262 263 264 265 266 267 268 269 270 271 272 273 274 275
    OPC_SDBBP    = 0x3F | OPC_SPECIAL2,
};

/* Special3 opcodes */
#define MASK_SPECIAL3(op)  MASK_OP_MAJOR(op) | (op & 0x3F)

enum {
    OPC_EXT      = 0x00 | OPC_SPECIAL3,
    OPC_DEXTM    = 0x01 | OPC_SPECIAL3,
    OPC_DEXTU    = 0x02 | OPC_SPECIAL3,
    OPC_DEXT     = 0x03 | OPC_SPECIAL3,
    OPC_INS      = 0x04 | OPC_SPECIAL3,
    OPC_DINSM    = 0x05 | OPC_SPECIAL3,
    OPC_DINSU    = 0x06 | OPC_SPECIAL3,
    OPC_DINS     = 0x07 | OPC_SPECIAL3,
276 277
    OPC_FORK     = 0x08 | OPC_SPECIAL3,
    OPC_YIELD    = 0x09 | OPC_SPECIAL3,
278 279 280
    OPC_BSHFL    = 0x20 | OPC_SPECIAL3,
    OPC_DBSHFL   = 0x24 | OPC_SPECIAL3,
    OPC_RDHWR    = 0x3B | OPC_SPECIAL3,
281 282
};

283 284 285
/* BSHFL opcodes */
#define MASK_BSHFL(op)     MASK_SPECIAL3(op) | (op & (0x1F << 6))

286
enum {
287 288 289
    OPC_WSBH     = (0x02 << 6) | OPC_BSHFL,
    OPC_SEB      = (0x10 << 6) | OPC_BSHFL,
    OPC_SEH      = (0x18 << 6) | OPC_BSHFL,
290 291
};

292 293 294
/* DBSHFL opcodes */
#define MASK_DBSHFL(op)    MASK_SPECIAL3(op) | (op & (0x1F << 6))

295
enum {
296 297
    OPC_DSBH     = (0x02 << 6) | OPC_DBSHFL,
    OPC_DSHD     = (0x05 << 6) | OPC_DBSHFL,
298 299
};

300 301 302
/* Coprocessor 0 (rs field) */
#define MASK_CP0(op)       MASK_OP_MAJOR(op) | (op & (0x1F << 21))

B
bellard 已提交
303
enum {
304 305 306 307
    OPC_MFC0     = (0x00 << 21) | OPC_CP0,
    OPC_DMFC0    = (0x01 << 21) | OPC_CP0,
    OPC_MTC0     = (0x04 << 21) | OPC_CP0,
    OPC_DMTC0    = (0x05 << 21) | OPC_CP0,
308
    OPC_MFTR     = (0x08 << 21) | OPC_CP0,
309 310
    OPC_RDPGPR   = (0x0A << 21) | OPC_CP0,
    OPC_MFMC0    = (0x0B << 21) | OPC_CP0,
311
    OPC_MTTR     = (0x0C << 21) | OPC_CP0,
312 313 314 315
    OPC_WRPGPR   = (0x0E << 21) | OPC_CP0,
    OPC_C0       = (0x10 << 21) | OPC_CP0,
    OPC_C0_FIRST = (0x10 << 21) | OPC_CP0,
    OPC_C0_LAST  = (0x1F << 21) | OPC_CP0,
B
bellard 已提交
316
};
317 318

/* MFMC0 opcodes */
319
#define MASK_MFMC0(op)     MASK_CP0(op) | (op & 0xFFFF)
320 321

enum {
322 323 324 325
    OPC_DMT      = 0x01 | (0 << 5) | (0x0F << 6) | (0x01 << 11) | OPC_MFMC0,
    OPC_EMT      = 0x01 | (1 << 5) | (0x0F << 6) | (0x01 << 11) | OPC_MFMC0,
    OPC_DVPE     = 0x01 | (0 << 5) | OPC_MFMC0,
    OPC_EVPE     = 0x01 | (1 << 5) | OPC_MFMC0,
326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350
    OPC_DI       = (0 << 5) | (0x0C << 11) | OPC_MFMC0,
    OPC_EI       = (1 << 5) | (0x0C << 11) | OPC_MFMC0,
};

/* Coprocessor 0 (with rs == C0) */
#define MASK_C0(op)        MASK_CP0(op) | (op & 0x3F)

enum {
    OPC_TLBR     = 0x01 | OPC_C0,
    OPC_TLBWI    = 0x02 | OPC_C0,
    OPC_TLBWR    = 0x06 | OPC_C0,
    OPC_TLBP     = 0x08 | OPC_C0,
    OPC_RFE      = 0x10 | OPC_C0,
    OPC_ERET     = 0x18 | OPC_C0,
    OPC_DERET    = 0x1F | OPC_C0,
    OPC_WAIT     = 0x20 | OPC_C0,
};

/* Coprocessor 1 (rs field) */
#define MASK_CP1(op)       MASK_OP_MAJOR(op) | (op & (0x1F << 21))

enum {
    OPC_MFC1     = (0x00 << 21) | OPC_CP1,
    OPC_DMFC1    = (0x01 << 21) | OPC_CP1,
    OPC_CFC1     = (0x02 << 21) | OPC_CP1,
351
    OPC_MFHC1    = (0x03 << 21) | OPC_CP1,
352 353 354
    OPC_MTC1     = (0x04 << 21) | OPC_CP1,
    OPC_DMTC1    = (0x05 << 21) | OPC_CP1,
    OPC_CTC1     = (0x06 << 21) | OPC_CP1,
355
    OPC_MTHC1    = (0x07 << 21) | OPC_CP1,
356
    OPC_BC1      = (0x08 << 21) | OPC_CP1, /* bc */
357 358
    OPC_BC1ANY2  = (0x09 << 21) | OPC_CP1,
    OPC_BC1ANY4  = (0x0A << 21) | OPC_CP1,
359 360 361 362 363 364
    OPC_S_FMT    = (0x10 << 21) | OPC_CP1, /* 16: fmt=single fp */
    OPC_D_FMT    = (0x11 << 21) | OPC_CP1, /* 17: fmt=double fp */
    OPC_E_FMT    = (0x12 << 21) | OPC_CP1, /* 18: fmt=extended fp */
    OPC_Q_FMT    = (0x13 << 21) | OPC_CP1, /* 19: fmt=quad fp */
    OPC_W_FMT    = (0x14 << 21) | OPC_CP1, /* 20: fmt=32bit fixed */
    OPC_L_FMT    = (0x15 << 21) | OPC_CP1, /* 21: fmt=64bit fixed */
365
    OPC_PS_FMT   = (0x16 << 21) | OPC_CP1, /* 22: fmt=paired single fp */
366 367
};

368 369 370
#define MASK_CP1_FUNC(op)       MASK_CP1(op) | (op & 0x3F)
#define MASK_BC1(op)            MASK_CP1(op) | (op & (0x3 << 16))

371 372 373 374 375 376 377
enum {
    OPC_BC1F     = (0x00 << 16) | OPC_BC1,
    OPC_BC1T     = (0x01 << 16) | OPC_BC1,
    OPC_BC1FL    = (0x02 << 16) | OPC_BC1,
    OPC_BC1TL    = (0x03 << 16) | OPC_BC1,
};

378 379 380 381 382 383 384 385 386
enum {
    OPC_BC1FANY2     = (0x00 << 16) | OPC_BC1ANY2,
    OPC_BC1TANY2     = (0x01 << 16) | OPC_BC1ANY2,
};

enum {
    OPC_BC1FANY4     = (0x00 << 16) | OPC_BC1ANY4,
    OPC_BC1TANY4     = (0x01 << 16) | OPC_BC1ANY4,
};
387 388

#define MASK_CP2(op)       MASK_OP_MAJOR(op) | (op & (0x1F << 21))
T
ths 已提交
389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419

enum {
    OPC_MFC2    = (0x00 << 21) | OPC_CP2,
    OPC_DMFC2   = (0x01 << 21) | OPC_CP2,
    OPC_CFC2    = (0x02 << 21) | OPC_CP2,
    OPC_MFHC2   = (0x03 << 21) | OPC_CP2,
    OPC_MTC2    = (0x04 << 21) | OPC_CP2,
    OPC_DMTC2   = (0x05 << 21) | OPC_CP2,
    OPC_CTC2    = (0x06 << 21) | OPC_CP2,
    OPC_MTHC2   = (0x07 << 21) | OPC_CP2,
    OPC_BC2     = (0x08 << 21) | OPC_CP2,
};

#define MASK_CP3(op)       MASK_OP_MAJOR(op) | (op & 0x3F)

enum {
    OPC_LWXC1   = 0x00 | OPC_CP3,
    OPC_LDXC1   = 0x01 | OPC_CP3,
    OPC_LUXC1   = 0x05 | OPC_CP3,
    OPC_SWXC1   = 0x08 | OPC_CP3,
    OPC_SDXC1   = 0x09 | OPC_CP3,
    OPC_SUXC1   = 0x0D | OPC_CP3,
    OPC_PREFX   = 0x0F | OPC_CP3,
    OPC_ALNV_PS = 0x1E | OPC_CP3,
    OPC_MADD_S  = 0x20 | OPC_CP3,
    OPC_MADD_D  = 0x21 | OPC_CP3,
    OPC_MADD_PS = 0x26 | OPC_CP3,
    OPC_MSUB_S  = 0x28 | OPC_CP3,
    OPC_MSUB_D  = 0x29 | OPC_CP3,
    OPC_MSUB_PS = 0x2E | OPC_CP3,
    OPC_NMADD_S = 0x30 | OPC_CP3,
420
    OPC_NMADD_D = 0x31 | OPC_CP3,
T
ths 已提交
421 422 423 424 425 426
    OPC_NMADD_PS= 0x36 | OPC_CP3,
    OPC_NMSUB_S = 0x38 | OPC_CP3,
    OPC_NMSUB_D = 0x39 | OPC_CP3,
    OPC_NMSUB_PS= 0x3E | OPC_CP3,
};

427
/* global register indices */
P
pbrook 已提交
428 429
static TCGv_ptr cpu_env;
static TCGv cpu_gpr[32], cpu_PC;
430
static TCGv cpu_HI[MIPS_DSP_ACC], cpu_LO[MIPS_DSP_ACC], cpu_ACX[MIPS_DSP_ACC];
431 432
static TCGv cpu_dspctrl, btarget, bcond;
static TCGv_i32 hflags;
P
pbrook 已提交
433
static TCGv_i32 fpu_fcr0, fpu_fcr31;
T
ths 已提交
434

P
pbrook 已提交
435 436
#include "gen-icount.h"

P
pbrook 已提交
437 438 439 440 441
#define gen_helper_0i(name, arg) do {                             \
    TCGv_i32 helper_tmp = tcg_const_i32(arg);                     \
    gen_helper_##name(helper_tmp);                                \
    tcg_temp_free_i32(helper_tmp);                                \
    } while(0)
442

P
pbrook 已提交
443 444 445 446 447
#define gen_helper_1i(name, arg1, arg2) do {                      \
    TCGv_i32 helper_tmp = tcg_const_i32(arg2);                    \
    gen_helper_##name(arg1, helper_tmp);                          \
    tcg_temp_free_i32(helper_tmp);                                \
    } while(0)
448

P
pbrook 已提交
449 450 451 452 453
#define gen_helper_2i(name, arg1, arg2, arg3) do {                \
    TCGv_i32 helper_tmp = tcg_const_i32(arg3);                    \
    gen_helper_##name(arg1, arg2, helper_tmp);                    \
    tcg_temp_free_i32(helper_tmp);                                \
    } while(0)
454

P
pbrook 已提交
455 456 457 458 459
#define gen_helper_3i(name, arg1, arg2, arg3, arg4) do {          \
    TCGv_i32 helper_tmp = tcg_const_i32(arg4);                    \
    gen_helper_##name(arg1, arg2, arg3, helper_tmp);              \
    tcg_temp_free_i32(helper_tmp);                                \
    } while(0)
T
ths 已提交
460

461 462 463 464 465 466 467 468 469 470 471 472 473
typedef struct DisasContext {
    struct TranslationBlock *tb;
    target_ulong pc, saved_pc;
    uint32_t opcode;
    /* Routine used to access memory */
    int mem_idx;
    uint32_t hflags, saved_hflags;
    int bstate;
    target_ulong btarget;
} DisasContext;

enum {
    BS_NONE     = 0, /* We go out of the TB without reaching a branch or an
T
ths 已提交
474
                      * exception condition */
475 476 477 478 479 480
    BS_STOP     = 1, /* We want to stop translation for any reason */
    BS_BRANCH   = 2, /* We reached a branch condition     */
    BS_EXCP     = 3, /* We reached an exception condition */
};

static const char *regnames[] =
B
bellard 已提交
481 482 483 484 485
    { "r0", "at", "v0", "v1", "a0", "a1", "a2", "a3",
      "t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7",
      "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7",
      "t8", "t9", "k0", "k1", "gp", "sp", "s8", "ra", };

486 487 488 489 490 491 492 493 494
static const char *regnames_HI[] =
    { "HI0", "HI1", "HI2", "HI3", };

static const char *regnames_LO[] =
    { "LO0", "LO1", "LO2", "LO3", };

static const char *regnames_ACX[] =
    { "ACX0", "ACX1", "ACX2", "ACX3", };

495 496 497 498 499
static const char *fregnames[] =
    { "f0",  "f1",  "f2",  "f3",  "f4",  "f5",  "f6",  "f7",
      "f8",  "f9",  "f10", "f11", "f12", "f13", "f14", "f15",
      "f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23",
      "f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31", };
T
ths 已提交
500

501
#ifdef MIPS_DEBUG_DISAS
502 503 504 505 506
#define MIPS_DEBUG(fmt, args...)                         \
        qemu_log_mask(CPU_LOG_TB_IN_ASM,                \
                       TARGET_FMT_lx ": %08x " fmt "\n", \
                       ctx->pc, ctx->opcode , ##args)
#define LOG_DISAS(...) qemu_log_mask(CPU_LOG_TB_IN_ASM, ## __VA_ARGS__)
507 508
#else
#define MIPS_DEBUG(fmt, args...) do { } while(0)
509
#define LOG_DISAS(...) do { } while (0)
510
#endif
T
ths 已提交
511

512 513 514 515 516
#define MIPS_INVAL(op)                                                        \
do {                                                                          \
    MIPS_DEBUG("Invalid %s %03x %03x %03x", op, ctx->opcode >> 26,            \
               ctx->opcode & 0x3F, ((ctx->opcode >> 16) & 0x1F));             \
} while (0)
517

518 519
/* General purpose registers moves. */
static inline void gen_load_gpr (TCGv t, int reg)
520
{
521 522 523
    if (reg == 0)
        tcg_gen_movi_tl(t, 0);
    else
524
        tcg_gen_mov_tl(t, cpu_gpr[reg]);
525 526
}

527
static inline void gen_store_gpr (TCGv t, int reg)
528
{
529
    if (reg != 0)
530
        tcg_gen_mov_tl(cpu_gpr[reg], t);
531 532
}

A
aurel32 已提交
533
/* Moves to/from ACX register.  */
534
static inline void gen_load_ACX (TCGv t, int reg)
535
{
536
    tcg_gen_mov_tl(t, cpu_ACX[reg]);
537 538
}

539
static inline void gen_store_ACX (TCGv t, int reg)
540
{
541
    tcg_gen_mov_tl(cpu_ACX[reg], t);
542 543
}

544
/* Moves to/from shadow registers. */
545
static inline void gen_load_srsgpr (int from, int to)
546
{
P
pbrook 已提交
547
    TCGv r_tmp1 = tcg_temp_new();
548 549 550

    if (from == 0)
        tcg_gen_movi_tl(r_tmp1, 0);
551
    else {
P
pbrook 已提交
552 553
        TCGv_i32 r_tmp2 = tcg_temp_new_i32();
        TCGv_ptr addr = tcg_temp_new_ptr();
554

555 556 557 558
        tcg_gen_ld_i32(r_tmp2, cpu_env, offsetof(CPUState, CP0_SRSCtl));
        tcg_gen_shri_i32(r_tmp2, r_tmp2, CP0SRSCtl_PSS);
        tcg_gen_andi_i32(r_tmp2, r_tmp2, 0xf);
        tcg_gen_muli_i32(r_tmp2, r_tmp2, sizeof(target_ulong) * 32);
P
pbrook 已提交
559 560
        tcg_gen_ext_i32_ptr(addr, r_tmp2);
        tcg_gen_add_ptr(addr, cpu_env, addr);
561

P
pbrook 已提交
562 563 564
        tcg_gen_ld_tl(r_tmp1, addr, sizeof(target_ulong) * from);
        tcg_temp_free_ptr(addr);
        tcg_temp_free_i32(r_tmp2);
565
    }
566 567
    gen_store_gpr(r_tmp1, to);
    tcg_temp_free(r_tmp1);
568 569
}

570
static inline void gen_store_srsgpr (int from, int to)
571
{
572
    if (to != 0) {
P
pbrook 已提交
573 574 575
        TCGv r_tmp1 = tcg_temp_new();
        TCGv_i32 r_tmp2 = tcg_temp_new_i32();
        TCGv_ptr addr = tcg_temp_new_ptr();
576 577 578 579 580 581

        gen_load_gpr(r_tmp1, from);
        tcg_gen_ld_i32(r_tmp2, cpu_env, offsetof(CPUState, CP0_SRSCtl));
        tcg_gen_shri_i32(r_tmp2, r_tmp2, CP0SRSCtl_PSS);
        tcg_gen_andi_i32(r_tmp2, r_tmp2, 0xf);
        tcg_gen_muli_i32(r_tmp2, r_tmp2, sizeof(target_ulong) * 32);
P
pbrook 已提交
582 583
        tcg_gen_ext_i32_ptr(addr, r_tmp2);
        tcg_gen_add_ptr(addr, cpu_env, addr);
584

P
pbrook 已提交
585 586 587
        tcg_gen_st_tl(r_tmp1, addr, sizeof(target_ulong) * to);
        tcg_temp_free_ptr(addr);
        tcg_temp_free_i32(r_tmp2);
588
        tcg_temp_free(r_tmp1);
589
    }
590 591 592
}

/* Floating point register moves. */
P
pbrook 已提交
593
static inline void gen_load_fpr32 (TCGv_i32 t, int reg)
T
ths 已提交
594
{
595
    tcg_gen_ld_i32(t, cpu_env, offsetof(CPUState, active_fpu.fpr[reg].w[FP_ENDIAN_IDX]));
B
bellard 已提交
596 597
}

P
pbrook 已提交
598
static inline void gen_store_fpr32 (TCGv_i32 t, int reg)
T
ths 已提交
599
{
600 601 602 603 604 605 606 607 608 609 610
    tcg_gen_st_i32(t, cpu_env, offsetof(CPUState, active_fpu.fpr[reg].w[FP_ENDIAN_IDX]));
}

static inline void gen_load_fpr32h (TCGv_i32 t, int reg)
{
    tcg_gen_ld_i32(t, cpu_env, offsetof(CPUState, active_fpu.fpr[reg].w[!FP_ENDIAN_IDX]));
}

static inline void gen_store_fpr32h (TCGv_i32 t, int reg)
{
    tcg_gen_st_i32(t, cpu_env, offsetof(CPUState, active_fpu.fpr[reg].w[!FP_ENDIAN_IDX]));
T
ths 已提交
611
}
B
bellard 已提交
612

P
pbrook 已提交
613
static inline void gen_load_fpr64 (DisasContext *ctx, TCGv_i64 t, int reg)
T
ths 已提交
614
{
A
aurel32 已提交
615
    if (ctx->hflags & MIPS_HFLAG_F64) {
616
        tcg_gen_ld_i64(t, cpu_env, offsetof(CPUState, active_fpu.fpr[reg].d));
A
aurel32 已提交
617
    } else {
618 619 620 621 622 623 624
        TCGv_i32 t0 = tcg_temp_new_i32();
        TCGv_i32 t1 = tcg_temp_new_i32();
        gen_load_fpr32(t0, reg & ~1);
        gen_load_fpr32(t1, reg | 1);
        tcg_gen_concat_i32_i64(t, t0, t1);
        tcg_temp_free_i32(t0);
        tcg_temp_free_i32(t1);
T
ths 已提交
625 626
    }
}
B
bellard 已提交
627

P
pbrook 已提交
628
static inline void gen_store_fpr64 (DisasContext *ctx, TCGv_i64 t, int reg)
T
ths 已提交
629
{
A
aurel32 已提交
630
    if (ctx->hflags & MIPS_HFLAG_F64) {
631
        tcg_gen_st_i64(t, cpu_env, offsetof(CPUState, active_fpu.fpr[reg].d));
A
aurel32 已提交
632
    } else {
633 634 635 636 637 638 639 640 641
        TCGv_i64 t0 = tcg_temp_new_i64();
        TCGv_i32 t1 = tcg_temp_new_i32();
        tcg_gen_trunc_i64_i32(t1, t);
        gen_store_fpr32(t1, reg & ~1);
        tcg_gen_shri_i64(t0, t, 32);
        tcg_gen_trunc_i64_i32(t1, t0);
        gen_store_fpr32(t1, reg | 1);
        tcg_temp_free_i32(t1);
        tcg_temp_free_i64(t0);
T
ths 已提交
642 643
    }
}
B
bellard 已提交
644

645
static inline int get_fp_bit (int cc)
646
{
647 648 649 650
    if (cc)
        return 24 + cc;
    else
        return 23;
651 652
}

P
pbrook 已提交
653 654 655
#define FOP_CONDS(type, fmt, bits)                                            \
static inline void gen_cmp ## type ## _ ## fmt(int n, TCGv_i##bits a,         \
                                               TCGv_i##bits b, int cc)        \
656
{                                                                             \
P
pbrook 已提交
657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675
    switch (n) {                                                              \
    case  0: gen_helper_2i(cmp ## type ## _ ## fmt ## _f, a, b, cc);    break;\
    case  1: gen_helper_2i(cmp ## type ## _ ## fmt ## _un, a, b, cc);   break;\
    case  2: gen_helper_2i(cmp ## type ## _ ## fmt ## _eq, a, b, cc);   break;\
    case  3: gen_helper_2i(cmp ## type ## _ ## fmt ## _ueq, a, b, cc);  break;\
    case  4: gen_helper_2i(cmp ## type ## _ ## fmt ## _olt, a, b, cc);  break;\
    case  5: gen_helper_2i(cmp ## type ## _ ## fmt ## _ult, a, b, cc);  break;\
    case  6: gen_helper_2i(cmp ## type ## _ ## fmt ## _ole, a, b, cc);  break;\
    case  7: gen_helper_2i(cmp ## type ## _ ## fmt ## _ule, a, b, cc);  break;\
    case  8: gen_helper_2i(cmp ## type ## _ ## fmt ## _sf, a, b, cc);   break;\
    case  9: gen_helper_2i(cmp ## type ## _ ## fmt ## _ngle, a, b, cc); break;\
    case 10: gen_helper_2i(cmp ## type ## _ ## fmt ## _seq, a, b, cc);  break;\
    case 11: gen_helper_2i(cmp ## type ## _ ## fmt ## _ngl, a, b, cc);  break;\
    case 12: gen_helper_2i(cmp ## type ## _ ## fmt ## _lt, a, b, cc);   break;\
    case 13: gen_helper_2i(cmp ## type ## _ ## fmt ## _nge, a, b, cc);  break;\
    case 14: gen_helper_2i(cmp ## type ## _ ## fmt ## _le, a, b, cc);   break;\
    case 15: gen_helper_2i(cmp ## type ## _ ## fmt ## _ngt, a, b, cc);  break;\
    default: abort();                                                         \
    }                                                                         \
B
bellard 已提交
676 677
}

P
pbrook 已提交
678 679 680 681 682 683
FOP_CONDS(, d, 64)
FOP_CONDS(abs, d, 64)
FOP_CONDS(, s, 32)
FOP_CONDS(abs, s, 32)
FOP_CONDS(, ps, 64)
FOP_CONDS(abs, ps, 64)
684
#undef FOP_CONDS
B
bellard 已提交
685

686
/* Tests */
687 688 689 690 691 692 693 694 695 696 697 698
#define OP_COND(name, cond)                                         \
static inline void glue(gen_op_, name) (TCGv ret, TCGv t0, TCGv t1) \
{                                                                   \
    int l1 = gen_new_label();                                       \
    int l2 = gen_new_label();                                       \
                                                                    \
    tcg_gen_brcond_tl(cond, t0, t1, l1);                            \
    tcg_gen_movi_tl(ret, 0);                                        \
    tcg_gen_br(l2);                                                 \
    gen_set_label(l1);                                              \
    tcg_gen_movi_tl(ret, 1);                                        \
    gen_set_label(l2);                                              \
699 700 701 702 703 704 705 706 707
}
OP_COND(eq, TCG_COND_EQ);
OP_COND(ne, TCG_COND_NE);
OP_COND(ge, TCG_COND_GE);
OP_COND(geu, TCG_COND_GEU);
OP_COND(lt, TCG_COND_LT);
OP_COND(ltu, TCG_COND_LTU);
#undef OP_COND

708 709 710 711 712 713 714 715 716 717 718 719
#define OP_CONDI(name, cond)                                                 \
static inline void glue(gen_op_, name) (TCGv ret, TCGv t0, target_ulong val) \
{                                                                            \
    int l1 = gen_new_label();                                                \
    int l2 = gen_new_label();                                                \
                                                                             \
    tcg_gen_brcondi_tl(cond, t0, val, l1);                                   \
    tcg_gen_movi_tl(ret, 0);                                                 \
    tcg_gen_br(l2);                                                          \
    gen_set_label(l1);                                                       \
    tcg_gen_movi_tl(ret, 1);                                                 \
    gen_set_label(l2);                                                       \
720 721 722 723 724 725
}
OP_CONDI(lti, TCG_COND_LT);
OP_CONDI(ltiu, TCG_COND_LTU);
#undef OP_CONDI

#define OP_CONDZ(name, cond)                                  \
726
static inline void glue(gen_op_, name) (TCGv ret, TCGv t0)    \
727 728 729 730
{                                                             \
    int l1 = gen_new_label();                                 \
    int l2 = gen_new_label();                                 \
                                                              \
731 732
    tcg_gen_brcondi_tl(cond, t0, 0, l1);                      \
    tcg_gen_movi_tl(ret, 0);                                  \
733 734
    tcg_gen_br(l2);                                           \
    gen_set_label(l1);                                        \
735
    tcg_gen_movi_tl(ret, 1);                                  \
736 737 738 739 740 741 742 743
    gen_set_label(l2);                                        \
}
OP_CONDZ(gez, TCG_COND_GE);
OP_CONDZ(gtz, TCG_COND_GT);
OP_CONDZ(lez, TCG_COND_LE);
OP_CONDZ(ltz, TCG_COND_LT);
#undef OP_CONDZ

744 745
static inline void gen_save_pc(target_ulong pc)
{
A
aurel32 已提交
746
    tcg_gen_movi_tl(cpu_PC, pc);
747
}
748

749
static inline void save_cpu_state (DisasContext *ctx, int do_save_pc)
B
bellard 已提交
750
{
751
    LOG_DISAS("hflags %08x saved %08x\n", ctx->hflags, ctx->saved_hflags);
B
bellard 已提交
752
    if (do_save_pc && ctx->pc != ctx->saved_pc) {
753
        gen_save_pc(ctx->pc);
B
bellard 已提交
754 755 756
        ctx->saved_pc = ctx->pc;
    }
    if (ctx->hflags != ctx->saved_hflags) {
757
        tcg_gen_movi_i32(hflags, ctx->hflags);
B
bellard 已提交
758
        ctx->saved_hflags = ctx->hflags;
759 760 761 762 763 764
        switch (ctx->hflags & MIPS_HFLAG_BMASK) {
        case MIPS_HFLAG_BR:
            break;
        case MIPS_HFLAG_BC:
        case MIPS_HFLAG_BL:
        case MIPS_HFLAG_B:
T
ths 已提交
765
            tcg_gen_movi_tl(btarget, ctx->btarget);
766
            break;
B
bellard 已提交
767 768 769 770
        }
    }
}

771
static inline void restore_cpu_state (CPUState *env, DisasContext *ctx)
772
{
773 774 775 776 777 778
    ctx->saved_hflags = ctx->hflags;
    switch (ctx->hflags & MIPS_HFLAG_BMASK) {
    case MIPS_HFLAG_BR:
        break;
    case MIPS_HFLAG_BC:
    case MIPS_HFLAG_BL:
779
    case MIPS_HFLAG_B:
780 781
        ctx->btarget = env->btarget;
        break;
782 783 784
    }
}

785
static inline void
786
generate_exception_err (DisasContext *ctx, int excp, int err)
787
{
P
pbrook 已提交
788 789
    TCGv_i32 texcp = tcg_const_i32(excp);
    TCGv_i32 terr = tcg_const_i32(err);
790
    save_cpu_state(ctx, 1);
P
pbrook 已提交
791 792 793 794
    gen_helper_raise_exception_err(texcp, terr);
    tcg_temp_free_i32(terr);
    tcg_temp_free_i32(texcp);
    gen_helper_interrupt_restart();
795 796 797
    tcg_gen_exit_tb(0);
}

798
static inline void
799
generate_exception (DisasContext *ctx, int excp)
800
{
B
bellard 已提交
801
    save_cpu_state(ctx, 1);
P
pbrook 已提交
802 803
    gen_helper_0i(raise_exception, excp);
    gen_helper_interrupt_restart();
804
    tcg_gen_exit_tb(0);
B
bellard 已提交
805 806
}

807
/* Addresses computation */
808
static inline void gen_op_addr_add (DisasContext *ctx, TCGv t0, TCGv t1)
B
bellard 已提交
809
{
810
    tcg_gen_add_tl(t0, t0, t1);
811 812 813 814 815

#if defined(TARGET_MIPS64)
    /* For compatibility with 32-bit code, data reference in user mode
       with Status_UX = 0 should be casted to 32-bit and sign extended.
       See the MIPS64 PRA manual, section 4.10. */
816 817
    if (((ctx->hflags & MIPS_HFLAG_KSU) == MIPS_HFLAG_UM) &&
        !(ctx->hflags & MIPS_HFLAG_UX)) {
818
        tcg_gen_ext32s_i64(t0, t0);
819 820
    }
#endif
B
bellard 已提交
821 822
}

823
static inline void check_cp0_enabled(DisasContext *ctx)
824
{
825
    if (unlikely(!(ctx->hflags & MIPS_HFLAG_CP0)))
826 827 828
        generate_exception_err(ctx, EXCP_CpU, 1);
}

829
static inline void check_cp1_enabled(DisasContext *ctx)
830
{
831
    if (unlikely(!(ctx->hflags & MIPS_HFLAG_FPU)))
832 833 834
        generate_exception_err(ctx, EXCP_CpU, 1);
}

835 836 837 838
/* Verify that the processor is running with COP1X instructions enabled.
   This is associated with the nabla symbol in the MIPS32 and MIPS64
   opcode tables.  */

839
static inline void check_cop1x(DisasContext *ctx)
840 841 842 843 844 845 846 847
{
    if (unlikely(!(ctx->hflags & MIPS_HFLAG_COP1X)))
        generate_exception(ctx, EXCP_RI);
}

/* Verify that the processor is running with 64-bit floating-point
   operations enabled.  */

848
static inline void check_cp1_64bitmode(DisasContext *ctx)
849
{
850
    if (unlikely(~ctx->hflags & (MIPS_HFLAG_F64 | MIPS_HFLAG_COP1X)))
851 852 853 854 855 856 857 858 859 860 861 862 863 864
        generate_exception(ctx, EXCP_RI);
}

/*
 * Verify if floating point register is valid; an operation is not defined
 * if bit 0 of any register specification is set and the FR bit in the
 * Status register equals zero, since the register numbers specify an
 * even-odd pair of adjacent coprocessor general registers. When the FR bit
 * in the Status register equals one, both even and odd register numbers
 * are valid. This limitation exists only for 64 bit wide (d,l,ps) registers.
 *
 * Multiple 64 bit wide registers can be checked by calling
 * gen_op_cp1_registers(freg1 | freg2 | ... | fregN);
 */
865
static inline void check_cp1_registers(DisasContext *ctx, int regs)
866
{
867
    if (unlikely(!(ctx->hflags & MIPS_HFLAG_F64) && (regs & 1)))
868 869 870
        generate_exception(ctx, EXCP_RI);
}

871
/* This code generates a "reserved instruction" exception if the
872
   CPU does not support the instruction set corresponding to flags. */
873
static inline void check_insn(CPUState *env, DisasContext *ctx, int flags)
874
{
875
    if (unlikely(!(env->insn_flags & flags)))
876 877 878
        generate_exception(ctx, EXCP_RI);
}

879 880
/* This code generates a "reserved instruction" exception if 64-bit
   instructions are not enabled. */
881
static inline void check_mips_64(DisasContext *ctx)
882
{
883
    if (unlikely(!(ctx->hflags & MIPS_HFLAG_64)))
884 885 886
        generate_exception(ctx, EXCP_RI);
}

T
ths 已提交
887
/* load/store instructions. */
888
#define OP_LD(insn,fname)                                        \
889
static inline void op_ldst_##insn(TCGv t0, DisasContext *ctx)    \
890
{                                                                \
891
    tcg_gen_qemu_##fname(t0, t0, ctx->mem_idx);                  \
892 893 894 895 896 897 898 899 900 901 902 903 904
}
OP_LD(lb,ld8s);
OP_LD(lbu,ld8u);
OP_LD(lh,ld16s);
OP_LD(lhu,ld16u);
OP_LD(lw,ld32s);
#if defined(TARGET_MIPS64)
OP_LD(lwu,ld32u);
OP_LD(ld,ld64);
#endif
#undef OP_LD

#define OP_ST(insn,fname)                                        \
905
static inline void op_ldst_##insn(TCGv t0, TCGv t1, DisasContext *ctx) \
906
{                                                                \
907
    tcg_gen_qemu_##fname(t1, t0, ctx->mem_idx);                  \
908 909 910 911 912 913 914 915 916 917
}
OP_ST(sb,st8);
OP_ST(sh,st16);
OP_ST(sw,st32);
#if defined(TARGET_MIPS64)
OP_ST(sd,st64);
#endif
#undef OP_ST

#define OP_LD_ATOMIC(insn,fname)                                        \
918
static inline void op_ldst_##insn(TCGv t0, TCGv t1, DisasContext *ctx)  \
919
{                                                                       \
920 921 922
    tcg_gen_mov_tl(t1, t0);                                             \
    tcg_gen_qemu_##fname(t0, t0, ctx->mem_idx);                         \
    tcg_gen_st_tl(t1, cpu_env, offsetof(CPUState, CP0_LLAddr));         \
923 924 925 926 927 928 929 930
}
OP_LD_ATOMIC(ll,ld32s);
#if defined(TARGET_MIPS64)
OP_LD_ATOMIC(lld,ld64);
#endif
#undef OP_LD_ATOMIC

#define OP_ST_ATOMIC(insn,fname,almask)                                 \
931
static inline void op_ldst_##insn(TCGv t0, TCGv t1, DisasContext *ctx)  \
932
{                                                                       \
P
pbrook 已提交
933
    TCGv r_tmp = tcg_temp_local_new();                       \
934 935 936 937
    int l1 = gen_new_label();                                           \
    int l2 = gen_new_label();                                           \
    int l3 = gen_new_label();                                           \
                                                                        \
938
    tcg_gen_andi_tl(r_tmp, t0, almask);                                 \
P
pbrook 已提交
939
    tcg_gen_brcondi_tl(TCG_COND_EQ, r_tmp, 0, l1);                      \
940
    tcg_gen_st_tl(t0, cpu_env, offsetof(CPUState, CP0_BadVAddr));       \
T
ths 已提交
941
    generate_exception(ctx, EXCP_AdES);                                 \
942 943
    gen_set_label(l1);                                                  \
    tcg_gen_ld_tl(r_tmp, cpu_env, offsetof(CPUState, CP0_LLAddr));      \
944 945 946
    tcg_gen_brcond_tl(TCG_COND_NE, t0, r_tmp, l2);                      \
    tcg_gen_qemu_##fname(t1, t0, ctx->mem_idx);                         \
    tcg_gen_movi_tl(t0, 1);                                             \
947 948
    tcg_gen_br(l3);                                                     \
    gen_set_label(l2);                                                  \
949
    tcg_gen_movi_tl(t0, 0);                                             \
950
    gen_set_label(l3);                                                  \
951
    tcg_temp_free(r_tmp);                                               \
952 953 954 955 956 957 958
}
OP_ST_ATOMIC(sc,st32,0x3);
#if defined(TARGET_MIPS64)
OP_ST_ATOMIC(scd,st64,0x7);
#endif
#undef OP_ST_ATOMIC

B
bellard 已提交
959
/* Load and store */
960
static void gen_ldst (DisasContext *ctx, uint32_t opc, int rt,
B
bellard 已提交
961 962
                      int base, int16_t offset)
{
963
    const char *opn = "ldst";
P
pbrook 已提交
964 965
    TCGv t0 = tcg_temp_local_new();
    TCGv t1 = tcg_temp_local_new();
B
bellard 已提交
966 967

    if (base == 0) {
T
ths 已提交
968
        tcg_gen_movi_tl(t0, offset);
B
bellard 已提交
969
    } else if (offset == 0) {
T
ths 已提交
970
        gen_load_gpr(t0, base);
B
bellard 已提交
971
    } else {
972 973
        tcg_gen_movi_tl(t0, offset);
        gen_op_addr_add(ctx, t0, cpu_gpr[base]);
B
bellard 已提交
974 975
    }
    /* Don't do NOP if destination is zero: we must perform the actual
976
       memory access. */
B
bellard 已提交
977
    switch (opc) {
978
#if defined(TARGET_MIPS64)
979
    case OPC_LWU:
T
ths 已提交
980 981
        op_ldst_lwu(t0, ctx);
        gen_store_gpr(t0, rt);
982 983
        opn = "lwu";
        break;
B
bellard 已提交
984
    case OPC_LD:
T
ths 已提交
985 986
        op_ldst_ld(t0, ctx);
        gen_store_gpr(t0, rt);
B
bellard 已提交
987 988
        opn = "ld";
        break;
989
    case OPC_LLD:
T
ths 已提交
990 991
        op_ldst_lld(t0, t1, ctx);
        gen_store_gpr(t0, rt);
992 993
        opn = "lld";
        break;
B
bellard 已提交
994
    case OPC_SD:
T
ths 已提交
995 996
        gen_load_gpr(t1, rt);
        op_ldst_sd(t0, t1, ctx);
B
bellard 已提交
997 998
        opn = "sd";
        break;
999
    case OPC_SCD:
T
ths 已提交
1000
        save_cpu_state(ctx, 1);
T
ths 已提交
1001 1002 1003
        gen_load_gpr(t1, rt);
        op_ldst_scd(t0, t1, ctx);
        gen_store_gpr(t0, rt);
1004 1005
        opn = "scd";
        break;
B
bellard 已提交
1006
    case OPC_LDL:
T
ths 已提交
1007
        save_cpu_state(ctx, 1);
T
ths 已提交
1008
        gen_load_gpr(t1, rt);
P
pbrook 已提交
1009
        gen_helper_3i(ldl, t1, t0, t1, ctx->mem_idx);
T
ths 已提交
1010
        gen_store_gpr(t1, rt);
B
bellard 已提交
1011 1012 1013
        opn = "ldl";
        break;
    case OPC_SDL:
T
ths 已提交
1014
        save_cpu_state(ctx, 1);
T
ths 已提交
1015
        gen_load_gpr(t1, rt);
P
pbrook 已提交
1016
        gen_helper_2i(sdl, t0, t1, ctx->mem_idx);
B
bellard 已提交
1017 1018 1019
        opn = "sdl";
        break;
    case OPC_LDR:
T
ths 已提交
1020
        save_cpu_state(ctx, 1);
T
ths 已提交
1021
        gen_load_gpr(t1, rt);
P
pbrook 已提交
1022
        gen_helper_3i(ldr, t1, t0, t1, ctx->mem_idx);
T
ths 已提交
1023
        gen_store_gpr(t1, rt);
B
bellard 已提交
1024 1025 1026
        opn = "ldr";
        break;
    case OPC_SDR:
T
ths 已提交
1027
        save_cpu_state(ctx, 1);
T
ths 已提交
1028
        gen_load_gpr(t1, rt);
P
pbrook 已提交
1029
        gen_helper_2i(sdr, t0, t1, ctx->mem_idx);
B
bellard 已提交
1030 1031 1032 1033
        opn = "sdr";
        break;
#endif
    case OPC_LW:
T
ths 已提交
1034 1035
        op_ldst_lw(t0, ctx);
        gen_store_gpr(t0, rt);
B
bellard 已提交
1036 1037 1038
        opn = "lw";
        break;
    case OPC_SW:
T
ths 已提交
1039 1040
        gen_load_gpr(t1, rt);
        op_ldst_sw(t0, t1, ctx);
B
bellard 已提交
1041 1042 1043
        opn = "sw";
        break;
    case OPC_LH:
T
ths 已提交
1044 1045
        op_ldst_lh(t0, ctx);
        gen_store_gpr(t0, rt);
B
bellard 已提交
1046 1047 1048
        opn = "lh";
        break;
    case OPC_SH:
T
ths 已提交
1049 1050
        gen_load_gpr(t1, rt);
        op_ldst_sh(t0, t1, ctx);
B
bellard 已提交
1051 1052 1053
        opn = "sh";
        break;
    case OPC_LHU:
T
ths 已提交
1054 1055
        op_ldst_lhu(t0, ctx);
        gen_store_gpr(t0, rt);
B
bellard 已提交
1056 1057 1058
        opn = "lhu";
        break;
    case OPC_LB:
T
ths 已提交
1059 1060
        op_ldst_lb(t0, ctx);
        gen_store_gpr(t0, rt);
B
bellard 已提交
1061 1062 1063
        opn = "lb";
        break;
    case OPC_SB:
T
ths 已提交
1064 1065
        gen_load_gpr(t1, rt);
        op_ldst_sb(t0, t1, ctx);
B
bellard 已提交
1066 1067 1068
        opn = "sb";
        break;
    case OPC_LBU:
T
ths 已提交
1069 1070
        op_ldst_lbu(t0, ctx);
        gen_store_gpr(t0, rt);
B
bellard 已提交
1071 1072 1073
        opn = "lbu";
        break;
    case OPC_LWL:
T
ths 已提交
1074
        save_cpu_state(ctx, 1);
A
aurel32 已提交
1075
        gen_load_gpr(t1, rt);
P
pbrook 已提交
1076
        gen_helper_3i(lwl, t1, t0, t1, ctx->mem_idx);
T
ths 已提交
1077
        gen_store_gpr(t1, rt);
B
bellard 已提交
1078 1079 1080
        opn = "lwl";
        break;
    case OPC_SWL:
T
ths 已提交
1081
        save_cpu_state(ctx, 1);
T
ths 已提交
1082
        gen_load_gpr(t1, rt);
P
pbrook 已提交
1083
        gen_helper_2i(swl, t0, t1, ctx->mem_idx);
B
bellard 已提交
1084 1085 1086
        opn = "swr";
        break;
    case OPC_LWR:
T
ths 已提交
1087
        save_cpu_state(ctx, 1);
A
aurel32 已提交
1088
        gen_load_gpr(t1, rt);
P
pbrook 已提交
1089
        gen_helper_3i(lwr, t1, t0, t1, ctx->mem_idx);
T
ths 已提交
1090
        gen_store_gpr(t1, rt);
B
bellard 已提交
1091 1092 1093
        opn = "lwr";
        break;
    case OPC_SWR:
T
ths 已提交
1094
        save_cpu_state(ctx, 1);
T
ths 已提交
1095
        gen_load_gpr(t1, rt);
P
pbrook 已提交
1096
        gen_helper_2i(swr, t0, t1, ctx->mem_idx);
B
bellard 已提交
1097 1098 1099
        opn = "swr";
        break;
    case OPC_LL:
T
ths 已提交
1100 1101
        op_ldst_ll(t0, t1, ctx);
        gen_store_gpr(t0, rt);
B
bellard 已提交
1102 1103 1104
        opn = "ll";
        break;
    case OPC_SC:
T
ths 已提交
1105
        save_cpu_state(ctx, 1);
T
ths 已提交
1106 1107 1108
        gen_load_gpr(t1, rt);
        op_ldst_sc(t0, t1, ctx);
        gen_store_gpr(t0, rt);
B
bellard 已提交
1109 1110 1111
        opn = "sc";
        break;
    default:
1112
        MIPS_INVAL(opn);
B
bellard 已提交
1113
        generate_exception(ctx, EXCP_RI);
T
ths 已提交
1114
        goto out;
B
bellard 已提交
1115 1116
    }
    MIPS_DEBUG("%s %s, %d(%s)", opn, regnames[rt], offset, regnames[base]);
T
ths 已提交
1117 1118 1119
 out:
    tcg_temp_free(t0);
    tcg_temp_free(t1);
B
bellard 已提交
1120 1121
}

B
bellard 已提交
1122
/* Load and store */
1123
static void gen_flt_ldst (DisasContext *ctx, uint32_t opc, int ft,
1124
                          int base, int16_t offset)
B
bellard 已提交
1125
{
1126
    const char *opn = "flt_ldst";
P
pbrook 已提交
1127
    TCGv t0 = tcg_temp_local_new();
B
bellard 已提交
1128 1129

    if (base == 0) {
T
ths 已提交
1130
        tcg_gen_movi_tl(t0, offset);
B
bellard 已提交
1131
    } else if (offset == 0) {
T
ths 已提交
1132
        gen_load_gpr(t0, base);
B
bellard 已提交
1133
    } else {
1134 1135
        tcg_gen_movi_tl(t0, offset);
        gen_op_addr_add(ctx, t0, cpu_gpr[base]);
B
bellard 已提交
1136 1137
    }
    /* Don't do NOP if destination is zero: we must perform the actual
1138
       memory access. */
B
bellard 已提交
1139 1140
    switch (opc) {
    case OPC_LWC1:
1141
        {
P
pbrook 已提交
1142 1143
            TCGv_i32 fp0 = tcg_temp_new_i32();
            TCGv t1 = tcg_temp_new();
1144

P
pbrook 已提交
1145 1146
            tcg_gen_qemu_ld32s(t1, t0, ctx->mem_idx);
            tcg_gen_trunc_tl_i32(fp0, t1);
1147
            gen_store_fpr32(fp0, ft);
P
pbrook 已提交
1148 1149
            tcg_temp_free(t1);
            tcg_temp_free_i32(fp0);
1150
        }
B
bellard 已提交
1151 1152 1153
        opn = "lwc1";
        break;
    case OPC_SWC1:
1154
        {
P
pbrook 已提交
1155 1156
            TCGv_i32 fp0 = tcg_temp_new_i32();
            TCGv t1 = tcg_temp_new();
1157 1158

            gen_load_fpr32(fp0, ft);
P
pbrook 已提交
1159 1160 1161 1162
            tcg_gen_extu_i32_tl(t1, fp0);
            tcg_gen_qemu_st32(t1, t0, ctx->mem_idx);
            tcg_temp_free(t1);
            tcg_temp_free_i32(fp0);
1163
        }
B
bellard 已提交
1164 1165 1166
        opn = "swc1";
        break;
    case OPC_LDC1:
1167
        {
P
pbrook 已提交
1168
            TCGv_i64 fp0 = tcg_temp_new_i64();
1169 1170 1171

            tcg_gen_qemu_ld64(fp0, t0, ctx->mem_idx);
            gen_store_fpr64(ctx, fp0, ft);
P
pbrook 已提交
1172
            tcg_temp_free_i64(fp0);
1173
        }
B
bellard 已提交
1174 1175 1176
        opn = "ldc1";
        break;
    case OPC_SDC1:
1177
        {
P
pbrook 已提交
1178
            TCGv_i64 fp0 = tcg_temp_new_i64();
1179 1180 1181

            gen_load_fpr64(ctx, fp0, ft);
            tcg_gen_qemu_st64(fp0, t0, ctx->mem_idx);
P
pbrook 已提交
1182
            tcg_temp_free_i64(fp0);
1183
        }
B
bellard 已提交
1184 1185 1186
        opn = "sdc1";
        break;
    default:
1187
        MIPS_INVAL(opn);
1188
        generate_exception(ctx, EXCP_RI);
T
ths 已提交
1189
        goto out;
B
bellard 已提交
1190 1191
    }
    MIPS_DEBUG("%s %s, %d(%s)", opn, fregnames[ft], offset, regnames[base]);
T
ths 已提交
1192 1193
 out:
    tcg_temp_free(t0);
B
bellard 已提交
1194 1195
}

B
bellard 已提交
1196
/* Arithmetic with immediate operand */
1197 1198
static void gen_arith_imm (CPUState *env, DisasContext *ctx, uint32_t opc,
                           int rt, int rs, int16_t imm)
B
bellard 已提交
1199
{
1200
    target_ulong uimm;
1201
    const char *opn = "imm arith";
P
pbrook 已提交
1202
    TCGv t0 = tcg_temp_local_new();
B
bellard 已提交
1203

1204
    if (rt == 0 && opc != OPC_ADDI && opc != OPC_DADDI) {
1205 1206
        /* If no destination, treat it as a NOP.
           For addi, we must generate the overflow exception when needed. */
B
bellard 已提交
1207
        MIPS_DEBUG("NOP");
T
ths 已提交
1208
        goto out;
B
bellard 已提交
1209
    }
1210 1211 1212 1213
    uimm = (uint16_t)imm;
    switch (opc) {
    case OPC_ADDI:
    case OPC_ADDIU:
1214
#if defined(TARGET_MIPS64)
1215 1216 1217 1218 1219
    case OPC_DADDI:
    case OPC_DADDIU:
#endif
    case OPC_SLTI:
    case OPC_SLTIU:
1220
        uimm = (target_long)imm; /* Sign extend to 32/64 bits */
1221 1222 1223 1224
        /* Fall through. */
    case OPC_ANDI:
    case OPC_ORI:
    case OPC_XORI:
T
ths 已提交
1225
        gen_load_gpr(t0, rs);
1226 1227
        break;
    case OPC_LUI:
T
ths 已提交
1228
        tcg_gen_movi_tl(t0, imm << 16);
1229 1230 1231 1232
        break;
    case OPC_SLL:
    case OPC_SRA:
    case OPC_SRL:
1233
#if defined(TARGET_MIPS64)
1234 1235 1236 1237 1238 1239 1240 1241
    case OPC_DSLL:
    case OPC_DSRA:
    case OPC_DSRL:
    case OPC_DSLL32:
    case OPC_DSRA32:
    case OPC_DSRL32:
#endif
        uimm &= 0x1f;
T
ths 已提交
1242
        gen_load_gpr(t0, rs);
1243
        break;
B
bellard 已提交
1244 1245 1246
    }
    switch (opc) {
    case OPC_ADDI:
1247
        {
P
pbrook 已提交
1248 1249
            TCGv r_tmp1 = tcg_temp_new();
            TCGv r_tmp2 = tcg_temp_new();
1250 1251 1252
            int l1 = gen_new_label();

            save_cpu_state(ctx, 1);
T
ths 已提交
1253 1254
            tcg_gen_ext32s_tl(r_tmp1, t0);
            tcg_gen_addi_tl(t0, r_tmp1, uimm);
1255

1256
            tcg_gen_xori_tl(r_tmp1, r_tmp1, ~uimm);
T
ths 已提交
1257
            tcg_gen_xori_tl(r_tmp2, t0, uimm);
1258
            tcg_gen_and_tl(r_tmp1, r_tmp1, r_tmp2);
T
ths 已提交
1259
            tcg_temp_free(r_tmp2);
1260
            tcg_gen_brcondi_tl(TCG_COND_GE, r_tmp1, 0, l1);
1261 1262 1263
            /* operands of same sign, result different sign */
            generate_exception(ctx, EXCP_OVERFLOW);
            gen_set_label(l1);
1264
            tcg_temp_free(r_tmp1);
1265

T
ths 已提交
1266
            tcg_gen_ext32s_tl(t0, t0);
1267
        }
B
bellard 已提交
1268 1269 1270
        opn = "addi";
        break;
    case OPC_ADDIU:
T
ths 已提交
1271 1272
        tcg_gen_addi_tl(t0, t0, uimm);
        tcg_gen_ext32s_tl(t0, t0);
B
bellard 已提交
1273 1274
        opn = "addiu";
        break;
1275
#if defined(TARGET_MIPS64)
1276
    case OPC_DADDI:
1277
        {
P
pbrook 已提交
1278 1279
            TCGv r_tmp1 = tcg_temp_new();
            TCGv r_tmp2 = tcg_temp_new();
1280 1281 1282
            int l1 = gen_new_label();

            save_cpu_state(ctx, 1);
T
ths 已提交
1283 1284
            tcg_gen_mov_tl(r_tmp1, t0);
            tcg_gen_addi_tl(t0, t0, uimm);
1285

1286
            tcg_gen_xori_tl(r_tmp1, r_tmp1, ~uimm);
T
ths 已提交
1287
            tcg_gen_xori_tl(r_tmp2, t0, uimm);
1288
            tcg_gen_and_tl(r_tmp1, r_tmp1, r_tmp2);
T
ths 已提交
1289
            tcg_temp_free(r_tmp2);
1290
            tcg_gen_brcondi_tl(TCG_COND_GE, r_tmp1, 0, l1);
1291 1292 1293
            /* operands of same sign, result different sign */
            generate_exception(ctx, EXCP_OVERFLOW);
            gen_set_label(l1);
1294
            tcg_temp_free(r_tmp1);
1295
        }
1296 1297 1298
        opn = "daddi";
        break;
    case OPC_DADDIU:
T
ths 已提交
1299
        tcg_gen_addi_tl(t0, t0, uimm);
1300 1301 1302
        opn = "daddiu";
        break;
#endif
B
bellard 已提交
1303
    case OPC_SLTI:
1304
        gen_op_lti(t0, t0, uimm);
B
bellard 已提交
1305 1306 1307
        opn = "slti";
        break;
    case OPC_SLTIU:
1308
        gen_op_ltiu(t0, t0, uimm);
B
bellard 已提交
1309 1310 1311
        opn = "sltiu";
        break;
    case OPC_ANDI:
T
ths 已提交
1312
        tcg_gen_andi_tl(t0, t0, uimm);
B
bellard 已提交
1313 1314 1315
        opn = "andi";
        break;
    case OPC_ORI:
T
ths 已提交
1316
        tcg_gen_ori_tl(t0, t0, uimm);
B
bellard 已提交
1317 1318 1319
        opn = "ori";
        break;
    case OPC_XORI:
T
ths 已提交
1320
        tcg_gen_xori_tl(t0, t0, uimm);
B
bellard 已提交
1321 1322 1323 1324 1325 1326
        opn = "xori";
        break;
    case OPC_LUI:
        opn = "lui";
        break;
    case OPC_SLL:
T
ths 已提交
1327 1328
        tcg_gen_shli_tl(t0, t0, uimm);
        tcg_gen_ext32s_tl(t0, t0);
B
bellard 已提交
1329 1330 1331
        opn = "sll";
        break;
    case OPC_SRA:
T
ths 已提交
1332 1333
        tcg_gen_ext32s_tl(t0, t0);
        tcg_gen_sari_tl(t0, t0, uimm);
B
bellard 已提交
1334 1335 1336
        opn = "sra";
        break;
    case OPC_SRL:
1337 1338
        switch ((ctx->opcode >> 21) & 0x1f) {
        case 0:
1339 1340 1341 1342 1343 1344
            if (uimm != 0) {
                tcg_gen_ext32u_tl(t0, t0);
                tcg_gen_shri_tl(t0, t0, uimm);
            } else {
                tcg_gen_ext32s_tl(t0, t0);
            }
1345
            opn = "srl";
1346 1347
            break;
        case 1:
1348 1349
            /* rotr is decoded as srl on non-R2 CPUs */
            if (env->insn_flags & ISA_MIPS32R2) {
1350
                if (uimm != 0) {
P
pbrook 已提交
1351
                    TCGv_i32 r_tmp1 = tcg_temp_new_i32();
1352

T
ths 已提交
1353
                    tcg_gen_trunc_tl_i32(r_tmp1, t0);
1354
                    tcg_gen_rotri_i32(r_tmp1, r_tmp1, uimm);
T
ths 已提交
1355
                    tcg_gen_ext_i32_tl(t0, r_tmp1);
P
pbrook 已提交
1356
                    tcg_temp_free_i32(r_tmp1);
1357
                }
1358 1359
                opn = "rotr";
            } else {
1360 1361 1362 1363 1364 1365
                if (uimm != 0) {
                    tcg_gen_ext32u_tl(t0, t0);
                    tcg_gen_shri_tl(t0, t0, uimm);
                } else {
                    tcg_gen_ext32s_tl(t0, t0);
                }
1366 1367
                opn = "srl";
            }
1368 1369 1370 1371 1372 1373
            break;
        default:
            MIPS_INVAL("invalid srl flag");
            generate_exception(ctx, EXCP_RI);
            break;
        }
1374
        break;
1375
#if defined(TARGET_MIPS64)
1376
    case OPC_DSLL:
T
ths 已提交
1377
        tcg_gen_shli_tl(t0, t0, uimm);
1378 1379 1380
        opn = "dsll";
        break;
    case OPC_DSRA:
T
ths 已提交
1381
        tcg_gen_sari_tl(t0, t0, uimm);
1382 1383 1384
        opn = "dsra";
        break;
    case OPC_DSRL:
1385 1386
        switch ((ctx->opcode >> 21) & 0x1f) {
        case 0:
T
ths 已提交
1387
            tcg_gen_shri_tl(t0, t0, uimm);
1388
            opn = "dsrl";
1389 1390
            break;
        case 1:
1391 1392
            /* drotr is decoded as dsrl on non-R2 CPUs */
            if (env->insn_flags & ISA_MIPS32R2) {
1393
                if (uimm != 0) {
1394
                    tcg_gen_rotri_tl(t0, t0, uimm);
1395
                }
1396 1397
                opn = "drotr";
            } else {
T
ths 已提交
1398
                tcg_gen_shri_tl(t0, t0, uimm);
1399 1400
                opn = "dsrl";
            }
1401 1402 1403 1404 1405 1406
            break;
        default:
            MIPS_INVAL("invalid dsrl flag");
            generate_exception(ctx, EXCP_RI);
            break;
        }
1407 1408
        break;
    case OPC_DSLL32:
T
ths 已提交
1409
        tcg_gen_shli_tl(t0, t0, uimm + 32);
1410 1411 1412
        opn = "dsll32";
        break;
    case OPC_DSRA32:
T
ths 已提交
1413
        tcg_gen_sari_tl(t0, t0, uimm + 32);
1414 1415 1416
        opn = "dsra32";
        break;
    case OPC_DSRL32:
1417 1418
        switch ((ctx->opcode >> 21) & 0x1f) {
        case 0:
T
ths 已提交
1419
            tcg_gen_shri_tl(t0, t0, uimm + 32);
1420
            opn = "dsrl32";
1421 1422
            break;
        case 1:
1423 1424
            /* drotr32 is decoded as dsrl32 on non-R2 CPUs */
            if (env->insn_flags & ISA_MIPS32R2) {
1425
                tcg_gen_rotri_tl(t0, t0, uimm + 32);
1426 1427
                opn = "drotr32";
            } else {
T
ths 已提交
1428
                tcg_gen_shri_tl(t0, t0, uimm + 32);
1429 1430
                opn = "dsrl32";
            }
1431 1432 1433 1434 1435 1436
            break;
        default:
            MIPS_INVAL("invalid dsrl32 flag");
            generate_exception(ctx, EXCP_RI);
            break;
        }
B
bellard 已提交
1437
        break;
1438
#endif
B
bellard 已提交
1439
    default:
1440
        MIPS_INVAL(opn);
B
bellard 已提交
1441
        generate_exception(ctx, EXCP_RI);
T
ths 已提交
1442
        goto out;
B
bellard 已提交
1443
    }
T
ths 已提交
1444
    gen_store_gpr(t0, rt);
T
ths 已提交
1445
    MIPS_DEBUG("%s %s, %s, " TARGET_FMT_lx, opn, regnames[rt], regnames[rs], uimm);
T
ths 已提交
1446 1447
 out:
    tcg_temp_free(t0);
B
bellard 已提交
1448 1449 1450
}

/* Arithmetic */
1451
static void gen_arith (CPUState *env, DisasContext *ctx, uint32_t opc,
B
bellard 已提交
1452 1453
                       int rd, int rs, int rt)
{
1454
    const char *opn = "arith";
P
pbrook 已提交
1455 1456
    TCGv t0 = tcg_temp_local_new();
    TCGv t1 = tcg_temp_local_new();
B
bellard 已提交
1457

1458 1459
    if (rd == 0 && opc != OPC_ADD && opc != OPC_SUB
       && opc != OPC_DADD && opc != OPC_DSUB) {
1460 1461
        /* If no destination, treat it as a NOP.
           For add & sub, we must generate the overflow exception when needed. */
B
bellard 已提交
1462
        MIPS_DEBUG("NOP");
T
ths 已提交
1463
        goto out;
B
bellard 已提交
1464
    }
T
ths 已提交
1465
    gen_load_gpr(t0, rs);
T
ths 已提交
1466 1467 1468
    /* Specialcase the conventional move operation. */
    if (rt == 0 && (opc == OPC_ADDU || opc == OPC_DADDU
                    || opc == OPC_SUBU || opc == OPC_DSUBU)) {
T
ths 已提交
1469 1470
        gen_store_gpr(t0, rd);
        goto out;
T
ths 已提交
1471
    }
T
ths 已提交
1472
    gen_load_gpr(t1, rt);
B
bellard 已提交
1473 1474
    switch (opc) {
    case OPC_ADD:
1475
        {
P
pbrook 已提交
1476 1477
            TCGv r_tmp1 = tcg_temp_new();
            TCGv r_tmp2 = tcg_temp_new();
1478 1479 1480
            int l1 = gen_new_label();

            save_cpu_state(ctx, 1);
T
ths 已提交
1481 1482 1483
            tcg_gen_ext32s_tl(r_tmp1, t0);
            tcg_gen_ext32s_tl(r_tmp2, t1);
            tcg_gen_add_tl(t0, r_tmp1, r_tmp2);
1484

T
ths 已提交
1485
            tcg_gen_xor_tl(r_tmp1, r_tmp1, t1);
1486
            tcg_gen_xori_tl(r_tmp1, r_tmp1, -1);
T
ths 已提交
1487
            tcg_gen_xor_tl(r_tmp2, t0, t1);
1488
            tcg_gen_and_tl(r_tmp1, r_tmp1, r_tmp2);
T
ths 已提交
1489
            tcg_temp_free(r_tmp2);
1490
            tcg_gen_brcondi_tl(TCG_COND_GE, r_tmp1, 0, l1);
1491 1492 1493
            /* operands of same sign, result different sign */
            generate_exception(ctx, EXCP_OVERFLOW);
            gen_set_label(l1);
1494
            tcg_temp_free(r_tmp1);
1495

T
ths 已提交
1496
            tcg_gen_ext32s_tl(t0, t0);
1497
        }
B
bellard 已提交
1498 1499 1500
        opn = "add";
        break;
    case OPC_ADDU:
T
ths 已提交
1501 1502
        tcg_gen_add_tl(t0, t0, t1);
        tcg_gen_ext32s_tl(t0, t0);
B
bellard 已提交
1503 1504 1505
        opn = "addu";
        break;
    case OPC_SUB:
1506
        {
P
pbrook 已提交
1507 1508
            TCGv r_tmp1 = tcg_temp_new();
            TCGv r_tmp2 = tcg_temp_new();
1509 1510 1511
            int l1 = gen_new_label();

            save_cpu_state(ctx, 1);
T
ths 已提交
1512 1513 1514
            tcg_gen_ext32s_tl(r_tmp1, t0);
            tcg_gen_ext32s_tl(r_tmp2, t1);
            tcg_gen_sub_tl(t0, r_tmp1, r_tmp2);
1515

T
ths 已提交
1516 1517
            tcg_gen_xor_tl(r_tmp2, r_tmp1, t1);
            tcg_gen_xor_tl(r_tmp1, r_tmp1, t0);
1518
            tcg_gen_and_tl(r_tmp1, r_tmp1, r_tmp2);
T
ths 已提交
1519
            tcg_temp_free(r_tmp2);
1520
            tcg_gen_brcondi_tl(TCG_COND_GE, r_tmp1, 0, l1);
1521 1522 1523
            /* operands of different sign, first operand and result different sign */
            generate_exception(ctx, EXCP_OVERFLOW);
            gen_set_label(l1);
1524
            tcg_temp_free(r_tmp1);
1525

T
ths 已提交
1526
            tcg_gen_ext32s_tl(t0, t0);
1527
        }
B
bellard 已提交
1528 1529 1530
        opn = "sub";
        break;
    case OPC_SUBU:
T
ths 已提交
1531 1532
        tcg_gen_sub_tl(t0, t0, t1);
        tcg_gen_ext32s_tl(t0, t0);
B
bellard 已提交
1533 1534
        opn = "subu";
        break;
1535
#if defined(TARGET_MIPS64)
1536
    case OPC_DADD:
1537
        {
P
pbrook 已提交
1538 1539
            TCGv r_tmp1 = tcg_temp_new();
            TCGv r_tmp2 = tcg_temp_new();
1540 1541 1542
            int l1 = gen_new_label();

            save_cpu_state(ctx, 1);
T
ths 已提交
1543 1544
            tcg_gen_mov_tl(r_tmp1, t0);
            tcg_gen_add_tl(t0, t0, t1);
1545

T
ths 已提交
1546
            tcg_gen_xor_tl(r_tmp1, r_tmp1, t1);
1547
            tcg_gen_xori_tl(r_tmp1, r_tmp1, -1);
T
ths 已提交
1548
            tcg_gen_xor_tl(r_tmp2, t0, t1);
1549
            tcg_gen_and_tl(r_tmp1, r_tmp1, r_tmp2);
T
ths 已提交
1550
            tcg_temp_free(r_tmp2);
1551
            tcg_gen_brcondi_tl(TCG_COND_GE, r_tmp1, 0, l1);
1552 1553 1554
            /* operands of same sign, result different sign */
            generate_exception(ctx, EXCP_OVERFLOW);
            gen_set_label(l1);
1555
            tcg_temp_free(r_tmp1);
1556
        }
1557 1558 1559
        opn = "dadd";
        break;
    case OPC_DADDU:
T
ths 已提交
1560
        tcg_gen_add_tl(t0, t0, t1);
1561 1562 1563
        opn = "daddu";
        break;
    case OPC_DSUB:
1564
        {
P
pbrook 已提交
1565 1566
            TCGv r_tmp1 = tcg_temp_new();
            TCGv r_tmp2 = tcg_temp_new();
1567 1568 1569
            int l1 = gen_new_label();

            save_cpu_state(ctx, 1);
T
ths 已提交
1570 1571
            tcg_gen_mov_tl(r_tmp1, t0);
            tcg_gen_sub_tl(t0, t0, t1);
1572

T
ths 已提交
1573 1574
            tcg_gen_xor_tl(r_tmp2, r_tmp1, t1);
            tcg_gen_xor_tl(r_tmp1, r_tmp1, t0);
1575
            tcg_gen_and_tl(r_tmp1, r_tmp1, r_tmp2);
T
ths 已提交
1576
            tcg_temp_free(r_tmp2);
1577
            tcg_gen_brcondi_tl(TCG_COND_GE, r_tmp1, 0, l1);
1578 1579 1580
            /* operands of different sign, first operand and result different sign */
            generate_exception(ctx, EXCP_OVERFLOW);
            gen_set_label(l1);
1581
            tcg_temp_free(r_tmp1);
1582
        }
1583 1584 1585
        opn = "dsub";
        break;
    case OPC_DSUBU:
T
ths 已提交
1586
        tcg_gen_sub_tl(t0, t0, t1);
1587 1588 1589
        opn = "dsubu";
        break;
#endif
B
bellard 已提交
1590
    case OPC_SLT:
1591
        gen_op_lt(t0, t0, t1);
B
bellard 已提交
1592 1593 1594
        opn = "slt";
        break;
    case OPC_SLTU:
1595
        gen_op_ltu(t0, t0, t1);
B
bellard 已提交
1596 1597 1598
        opn = "sltu";
        break;
    case OPC_AND:
T
ths 已提交
1599
        tcg_gen_and_tl(t0, t0, t1);
B
bellard 已提交
1600 1601 1602
        opn = "and";
        break;
    case OPC_NOR:
1603
        tcg_gen_nor_tl(t0, t0, t1);
B
bellard 已提交
1604 1605 1606
        opn = "nor";
        break;
    case OPC_OR:
T
ths 已提交
1607
        tcg_gen_or_tl(t0, t0, t1);
B
bellard 已提交
1608 1609 1610
        opn = "or";
        break;
    case OPC_XOR:
T
ths 已提交
1611
        tcg_gen_xor_tl(t0, t0, t1);
B
bellard 已提交
1612 1613 1614
        opn = "xor";
        break;
    case OPC_MUL:
T
ths 已提交
1615 1616
        tcg_gen_mul_tl(t0, t0, t1);
        tcg_gen_ext32s_tl(t0, t0);
B
bellard 已提交
1617 1618 1619
        opn = "mul";
        break;
    case OPC_MOVN:
T
ths 已提交
1620 1621 1622
        {
            int l1 = gen_new_label();

T
ths 已提交
1623 1624
            tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
            gen_store_gpr(t0, rd);
T
ths 已提交
1625 1626
            gen_set_label(l1);
        }
B
bellard 已提交
1627 1628 1629
        opn = "movn";
        goto print;
    case OPC_MOVZ:
T
ths 已提交
1630 1631 1632
        {
            int l1 = gen_new_label();

T
ths 已提交
1633 1634
            tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
            gen_store_gpr(t0, rd);
T
ths 已提交
1635 1636
            gen_set_label(l1);
        }
B
bellard 已提交
1637 1638 1639
        opn = "movz";
        goto print;
    case OPC_SLLV:
T
ths 已提交
1640 1641 1642
        tcg_gen_andi_tl(t0, t0, 0x1f);
        tcg_gen_shl_tl(t0, t1, t0);
        tcg_gen_ext32s_tl(t0, t0);
B
bellard 已提交
1643 1644 1645
        opn = "sllv";
        break;
    case OPC_SRAV:
T
ths 已提交
1646 1647 1648
        tcg_gen_ext32s_tl(t1, t1);
        tcg_gen_andi_tl(t0, t0, 0x1f);
        tcg_gen_sar_tl(t0, t1, t0);
B
bellard 已提交
1649 1650 1651
        opn = "srav";
        break;
    case OPC_SRLV:
1652 1653
        switch ((ctx->opcode >> 6) & 0x1f) {
        case 0:
T
ths 已提交
1654 1655 1656 1657
            tcg_gen_ext32u_tl(t1, t1);
            tcg_gen_andi_tl(t0, t0, 0x1f);
            tcg_gen_shr_tl(t0, t1, t0);
            tcg_gen_ext32s_tl(t0, t0);
1658
            opn = "srlv";
1659 1660
            break;
        case 1:
1661 1662
            /* rotrv is decoded as srlv on non-R2 CPUs */
            if (env->insn_flags & ISA_MIPS32R2) {
1663 1664 1665
                int l1 = gen_new_label();
                int l2 = gen_new_label();

T
ths 已提交
1666 1667
                tcg_gen_andi_tl(t0, t0, 0x1f);
                tcg_gen_brcondi_tl(TCG_COND_EQ, t0, 0, l1);
1668
                {
P
pbrook 已提交
1669 1670
                    TCGv_i32 r_tmp1 = tcg_temp_new_i32();
                    TCGv_i32 r_tmp2 = tcg_temp_new_i32();
1671

T
ths 已提交
1672 1673
                    tcg_gen_trunc_tl_i32(r_tmp1, t0);
                    tcg_gen_trunc_tl_i32(r_tmp2, t1);
1674
                    tcg_gen_rotr_i32(r_tmp1, r_tmp1, r_tmp2);
P
pbrook 已提交
1675 1676
                    tcg_temp_free_i32(r_tmp1);
                    tcg_temp_free_i32(r_tmp2);
1677 1678 1679
                    tcg_gen_br(l2);
                }
                gen_set_label(l1);
T
ths 已提交
1680
                tcg_gen_mov_tl(t0, t1);
1681
                gen_set_label(l2);
1682 1683
                opn = "rotrv";
            } else {
T
ths 已提交
1684 1685 1686 1687
                tcg_gen_ext32u_tl(t1, t1);
                tcg_gen_andi_tl(t0, t0, 0x1f);
                tcg_gen_shr_tl(t0, t1, t0);
                tcg_gen_ext32s_tl(t0, t0);
1688 1689
                opn = "srlv";
            }
1690 1691 1692 1693 1694 1695
            break;
        default:
            MIPS_INVAL("invalid srlv flag");
            generate_exception(ctx, EXCP_RI);
            break;
        }
1696
        break;
1697
#if defined(TARGET_MIPS64)
1698
    case OPC_DSLLV:
T
ths 已提交
1699 1700
        tcg_gen_andi_tl(t0, t0, 0x3f);
        tcg_gen_shl_tl(t0, t1, t0);
1701 1702 1703
        opn = "dsllv";
        break;
    case OPC_DSRAV:
T
ths 已提交
1704 1705
        tcg_gen_andi_tl(t0, t0, 0x3f);
        tcg_gen_sar_tl(t0, t1, t0);
1706 1707 1708
        opn = "dsrav";
        break;
    case OPC_DSRLV:
1709 1710
        switch ((ctx->opcode >> 6) & 0x1f) {
        case 0:
T
ths 已提交
1711 1712
            tcg_gen_andi_tl(t0, t0, 0x3f);
            tcg_gen_shr_tl(t0, t1, t0);
1713
            opn = "dsrlv";
1714 1715
            break;
        case 1:
1716 1717
            /* drotrv is decoded as dsrlv on non-R2 CPUs */
            if (env->insn_flags & ISA_MIPS32R2) {
1718 1719 1720
                int l1 = gen_new_label();
                int l2 = gen_new_label();

T
ths 已提交
1721 1722
                tcg_gen_andi_tl(t0, t0, 0x3f);
                tcg_gen_brcondi_tl(TCG_COND_EQ, t0, 0, l1);
1723
                {
1724
                    tcg_gen_rotr_tl(t0, t1, t0);
1725 1726 1727
                    tcg_gen_br(l2);
                }
                gen_set_label(l1);
T
ths 已提交
1728
                tcg_gen_mov_tl(t0, t1);
1729
                gen_set_label(l2);
1730 1731
                opn = "drotrv";
            } else {
T
ths 已提交
1732 1733
                tcg_gen_andi_tl(t0, t0, 0x3f);
                tcg_gen_shr_tl(t0, t1, t0);
1734 1735
                opn = "dsrlv";
            }
1736 1737 1738 1739 1740 1741
            break;
        default:
            MIPS_INVAL("invalid dsrlv flag");
            generate_exception(ctx, EXCP_RI);
            break;
        }
B
bellard 已提交
1742
        break;
1743
#endif
B
bellard 已提交
1744
    default:
1745
        MIPS_INVAL(opn);
B
bellard 已提交
1746
        generate_exception(ctx, EXCP_RI);
T
ths 已提交
1747
        goto out;
B
bellard 已提交
1748
    }
T
ths 已提交
1749
    gen_store_gpr(t0, rd);
B
bellard 已提交
1750 1751
 print:
    MIPS_DEBUG("%s %s, %s, %s", opn, regnames[rd], regnames[rs], regnames[rt]);
T
ths 已提交
1752 1753 1754
 out:
    tcg_temp_free(t0);
    tcg_temp_free(t1);
B
bellard 已提交
1755 1756 1757
}

/* Arithmetic on HI/LO registers */
1758
static void gen_HILO (DisasContext *ctx, uint32_t opc, int reg)
B
bellard 已提交
1759
{
1760
    const char *opn = "hilo";
B
bellard 已提交
1761 1762

    if (reg == 0 && (opc == OPC_MFHI || opc == OPC_MFLO)) {
1763
        /* Treat as NOP. */
B
bellard 已提交
1764
        MIPS_DEBUG("NOP");
A
aurel32 已提交
1765
        return;
B
bellard 已提交
1766 1767 1768
    }
    switch (opc) {
    case OPC_MFHI:
A
aurel32 已提交
1769
        tcg_gen_mov_tl(cpu_gpr[reg], cpu_HI[0]);
B
bellard 已提交
1770 1771 1772
        opn = "mfhi";
        break;
    case OPC_MFLO:
A
aurel32 已提交
1773
        tcg_gen_mov_tl(cpu_gpr[reg], cpu_LO[0]);
B
bellard 已提交
1774 1775 1776
        opn = "mflo";
        break;
    case OPC_MTHI:
A
aurel32 已提交
1777 1778 1779 1780
        if (reg != 0)
            tcg_gen_mov_tl(cpu_HI[0], cpu_gpr[reg]);
        else
            tcg_gen_movi_tl(cpu_HI[0], 0);
B
bellard 已提交
1781 1782 1783
        opn = "mthi";
        break;
    case OPC_MTLO:
A
aurel32 已提交
1784 1785 1786 1787
        if (reg != 0)
            tcg_gen_mov_tl(cpu_LO[0], cpu_gpr[reg]);
        else
            tcg_gen_movi_tl(cpu_LO[0], 0);
B
bellard 已提交
1788 1789 1790 1791 1792 1793
        opn = "mtlo";
        break;
    }
    MIPS_DEBUG("%s %s", opn, regnames[reg]);
}

1794
static void gen_muldiv (DisasContext *ctx, uint32_t opc,
B
bellard 已提交
1795 1796
                        int rs, int rt)
{
1797
    const char *opn = "mul/div";
A
aurel32 已提交
1798 1799 1800 1801 1802 1803 1804 1805 1806 1807 1808 1809 1810 1811 1812 1813 1814
    TCGv t0, t1;

    switch (opc) {
    case OPC_DIV:
    case OPC_DIVU:
#if defined(TARGET_MIPS64)
    case OPC_DDIV:
    case OPC_DDIVU:
#endif
        t0 = tcg_temp_local_new();
        t1 = tcg_temp_local_new();
        break;
    default:
        t0 = tcg_temp_new();
        t1 = tcg_temp_new();
        break;
    }
B
bellard 已提交
1815

T
ths 已提交
1816 1817
    gen_load_gpr(t0, rs);
    gen_load_gpr(t1, rt);
B
bellard 已提交
1818 1819
    switch (opc) {
    case OPC_DIV:
1820 1821
        {
            int l1 = gen_new_label();
A
aurel32 已提交
1822
            int l2 = gen_new_label();
1823

A
aurel32 已提交
1824 1825
            tcg_gen_ext32s_tl(t0, t0);
            tcg_gen_ext32s_tl(t1, t1);
T
ths 已提交
1826
            tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
A
aurel32 已提交
1827 1828 1829 1830 1831 1832 1833 1834 1835 1836 1837
            tcg_gen_brcondi_tl(TCG_COND_NE, t0, INT_MIN, l2);
            tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1, l2);

            tcg_gen_mov_tl(cpu_LO[0], t0);
            tcg_gen_movi_tl(cpu_HI[0], 0);
            tcg_gen_br(l1);
            gen_set_label(l2);
            tcg_gen_div_tl(cpu_LO[0], t0, t1);
            tcg_gen_rem_tl(cpu_HI[0], t0, t1);
            tcg_gen_ext32s_tl(cpu_LO[0], cpu_LO[0]);
            tcg_gen_ext32s_tl(cpu_HI[0], cpu_HI[0]);
1838 1839
            gen_set_label(l1);
        }
B
bellard 已提交
1840 1841 1842
        opn = "div";
        break;
    case OPC_DIVU:
1843 1844 1845
        {
            int l1 = gen_new_label();

A
aurel32 已提交
1846 1847
            tcg_gen_ext32u_tl(t0, t0);
            tcg_gen_ext32u_tl(t1, t1);
T
ths 已提交
1848
            tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
A
aurel32 已提交
1849 1850 1851 1852
            tcg_gen_divu_tl(cpu_LO[0], t0, t1);
            tcg_gen_remu_tl(cpu_HI[0], t0, t1);
            tcg_gen_ext32s_tl(cpu_LO[0], cpu_LO[0]);
            tcg_gen_ext32s_tl(cpu_HI[0], cpu_HI[0]);
1853 1854
            gen_set_label(l1);
        }
B
bellard 已提交
1855 1856 1857
        opn = "divu";
        break;
    case OPC_MULT:
1858
        {
A
aurel32 已提交
1859 1860 1861 1862 1863 1864 1865 1866 1867 1868 1869
            TCGv_i64 t2 = tcg_temp_new_i64();
            TCGv_i64 t3 = tcg_temp_new_i64();

            tcg_gen_ext_tl_i64(t2, t0);
            tcg_gen_ext_tl_i64(t3, t1);
            tcg_gen_mul_i64(t2, t2, t3);
            tcg_temp_free_i64(t3);
            tcg_gen_trunc_i64_tl(t0, t2);
            tcg_gen_shri_i64(t2, t2, 32);
            tcg_gen_trunc_i64_tl(t1, t2);
            tcg_temp_free_i64(t2);
A
aurel32 已提交
1870 1871
            tcg_gen_ext32s_tl(cpu_LO[0], t0);
            tcg_gen_ext32s_tl(cpu_HI[0], t1);
1872
        }
B
bellard 已提交
1873 1874 1875
        opn = "mult";
        break;
    case OPC_MULTU:
1876
        {
A
aurel32 已提交
1877 1878
            TCGv_i64 t2 = tcg_temp_new_i64();
            TCGv_i64 t3 = tcg_temp_new_i64();
1879

T
ths 已提交
1880 1881
            tcg_gen_ext32u_tl(t0, t0);
            tcg_gen_ext32u_tl(t1, t1);
A
aurel32 已提交
1882 1883 1884 1885 1886 1887 1888 1889
            tcg_gen_extu_tl_i64(t2, t0);
            tcg_gen_extu_tl_i64(t3, t1);
            tcg_gen_mul_i64(t2, t2, t3);
            tcg_temp_free_i64(t3);
            tcg_gen_trunc_i64_tl(t0, t2);
            tcg_gen_shri_i64(t2, t2, 32);
            tcg_gen_trunc_i64_tl(t1, t2);
            tcg_temp_free_i64(t2);
A
aurel32 已提交
1890 1891
            tcg_gen_ext32s_tl(cpu_LO[0], t0);
            tcg_gen_ext32s_tl(cpu_HI[0], t1);
1892
        }
B
bellard 已提交
1893 1894
        opn = "multu";
        break;
1895
#if defined(TARGET_MIPS64)
1896
    case OPC_DDIV:
1897 1898
        {
            int l1 = gen_new_label();
A
aurel32 已提交
1899
            int l2 = gen_new_label();
1900

T
ths 已提交
1901
            tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
A
aurel32 已提交
1902 1903 1904 1905 1906 1907 1908 1909
            tcg_gen_brcondi_tl(TCG_COND_NE, t0, -1LL << 63, l2);
            tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1LL, l2);
            tcg_gen_mov_tl(cpu_LO[0], t0);
            tcg_gen_movi_tl(cpu_HI[0], 0);
            tcg_gen_br(l1);
            gen_set_label(l2);
            tcg_gen_div_i64(cpu_LO[0], t0, t1);
            tcg_gen_rem_i64(cpu_HI[0], t0, t1);
1910 1911
            gen_set_label(l1);
        }
1912 1913 1914
        opn = "ddiv";
        break;
    case OPC_DDIVU:
1915 1916 1917
        {
            int l1 = gen_new_label();

T
ths 已提交
1918
            tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
A
aurel32 已提交
1919 1920
            tcg_gen_divu_i64(cpu_LO[0], t0, t1);
            tcg_gen_remu_i64(cpu_HI[0], t0, t1);
1921 1922
            gen_set_label(l1);
        }
1923 1924 1925
        opn = "ddivu";
        break;
    case OPC_DMULT:
P
pbrook 已提交
1926
        gen_helper_dmult(t0, t1);
1927 1928 1929
        opn = "dmult";
        break;
    case OPC_DMULTU:
P
pbrook 已提交
1930
        gen_helper_dmultu(t0, t1);
1931 1932 1933
        opn = "dmultu";
        break;
#endif
B
bellard 已提交
1934
    case OPC_MADD:
1935
        {
A
aurel32 已提交
1936 1937 1938 1939 1940 1941 1942 1943 1944 1945 1946 1947 1948
            TCGv_i64 t2 = tcg_temp_new_i64();
            TCGv_i64 t3 = tcg_temp_new_i64();

            tcg_gen_ext_tl_i64(t2, t0);
            tcg_gen_ext_tl_i64(t3, t1);
            tcg_gen_mul_i64(t2, t2, t3);
            tcg_gen_concat_tl_i64(t3, cpu_LO[0], cpu_HI[0]);
            tcg_gen_add_i64(t2, t2, t3);
            tcg_temp_free_i64(t3);
            tcg_gen_trunc_i64_tl(t0, t2);
            tcg_gen_shri_i64(t2, t2, 32);
            tcg_gen_trunc_i64_tl(t1, t2);
            tcg_temp_free_i64(t2);
A
aurel32 已提交
1949 1950
            tcg_gen_ext32s_tl(cpu_LO[0], t0);
            tcg_gen_ext32s_tl(cpu_LO[1], t1);
1951
        }
B
bellard 已提交
1952 1953 1954
        opn = "madd";
        break;
    case OPC_MADDU:
1955
       {
A
aurel32 已提交
1956 1957
            TCGv_i64 t2 = tcg_temp_new_i64();
            TCGv_i64 t3 = tcg_temp_new_i64();
1958

T
ths 已提交
1959 1960
            tcg_gen_ext32u_tl(t0, t0);
            tcg_gen_ext32u_tl(t1, t1);
A
aurel32 已提交
1961 1962 1963 1964 1965 1966 1967 1968 1969 1970
            tcg_gen_extu_tl_i64(t2, t0);
            tcg_gen_extu_tl_i64(t3, t1);
            tcg_gen_mul_i64(t2, t2, t3);
            tcg_gen_concat_tl_i64(t3, cpu_LO[0], cpu_HI[0]);
            tcg_gen_add_i64(t2, t2, t3);
            tcg_temp_free_i64(t3);
            tcg_gen_trunc_i64_tl(t0, t2);
            tcg_gen_shri_i64(t2, t2, 32);
            tcg_gen_trunc_i64_tl(t1, t2);
            tcg_temp_free_i64(t2);
A
aurel32 已提交
1971 1972
            tcg_gen_ext32s_tl(cpu_LO[0], t0);
            tcg_gen_ext32s_tl(cpu_HI[0], t1);
1973
        }
B
bellard 已提交
1974 1975 1976
        opn = "maddu";
        break;
    case OPC_MSUB:
1977
        {
A
aurel32 已提交
1978 1979 1980 1981 1982 1983 1984 1985 1986 1987 1988 1989 1990
            TCGv_i64 t2 = tcg_temp_new_i64();
            TCGv_i64 t3 = tcg_temp_new_i64();

            tcg_gen_ext_tl_i64(t2, t0);
            tcg_gen_ext_tl_i64(t3, t1);
            tcg_gen_mul_i64(t2, t2, t3);
            tcg_gen_concat_tl_i64(t3, cpu_LO[0], cpu_HI[0]);
            tcg_gen_sub_i64(t2, t2, t3);
            tcg_temp_free_i64(t3);
            tcg_gen_trunc_i64_tl(t0, t2);
            tcg_gen_shri_i64(t2, t2, 32);
            tcg_gen_trunc_i64_tl(t1, t2);
            tcg_temp_free_i64(t2);
A
aurel32 已提交
1991 1992
            tcg_gen_ext32s_tl(cpu_LO[0], t0);
            tcg_gen_ext32s_tl(cpu_HI[0], t1);
1993
        }
B
bellard 已提交
1994 1995 1996
        opn = "msub";
        break;
    case OPC_MSUBU:
1997
        {
A
aurel32 已提交
1998 1999
            TCGv_i64 t2 = tcg_temp_new_i64();
            TCGv_i64 t3 = tcg_temp_new_i64();
2000

T
ths 已提交
2001 2002
            tcg_gen_ext32u_tl(t0, t0);
            tcg_gen_ext32u_tl(t1, t1);
A
aurel32 已提交
2003 2004 2005 2006 2007 2008 2009 2010 2011 2012
            tcg_gen_extu_tl_i64(t2, t0);
            tcg_gen_extu_tl_i64(t3, t1);
            tcg_gen_mul_i64(t2, t2, t3);
            tcg_gen_concat_tl_i64(t3, cpu_LO[0], cpu_HI[0]);
            tcg_gen_sub_i64(t2, t2, t3);
            tcg_temp_free_i64(t3);
            tcg_gen_trunc_i64_tl(t0, t2);
            tcg_gen_shri_i64(t2, t2, 32);
            tcg_gen_trunc_i64_tl(t1, t2);
            tcg_temp_free_i64(t2);
A
aurel32 已提交
2013 2014
            tcg_gen_ext32s_tl(cpu_LO[0], t0);
            tcg_gen_ext32s_tl(cpu_HI[0], t1);
2015
        }
B
bellard 已提交
2016 2017 2018
        opn = "msubu";
        break;
    default:
2019
        MIPS_INVAL(opn);
B
bellard 已提交
2020
        generate_exception(ctx, EXCP_RI);
T
ths 已提交
2021
        goto out;
B
bellard 已提交
2022 2023
    }
    MIPS_DEBUG("%s %s %s", opn, regnames[rs], regnames[rt]);
T
ths 已提交
2024 2025 2026
 out:
    tcg_temp_free(t0);
    tcg_temp_free(t1);
B
bellard 已提交
2027 2028
}

2029 2030 2031 2032
static void gen_mul_vr54xx (DisasContext *ctx, uint32_t opc,
                            int rd, int rs, int rt)
{
    const char *opn = "mul vr54xx";
A
aurel32 已提交
2033 2034
    TCGv t0 = tcg_temp_new();
    TCGv t1 = tcg_temp_new();
2035

2036 2037
    gen_load_gpr(t0, rs);
    gen_load_gpr(t1, rt);
2038 2039 2040

    switch (opc) {
    case OPC_VR54XX_MULS:
P
pbrook 已提交
2041
        gen_helper_muls(t0, t0, t1);
2042
        opn = "muls";
A
aurel32 已提交
2043
        break;
2044
    case OPC_VR54XX_MULSU:
P
pbrook 已提交
2045
        gen_helper_mulsu(t0, t0, t1);
2046
        opn = "mulsu";
A
aurel32 已提交
2047
        break;
2048
    case OPC_VR54XX_MACC:
P
pbrook 已提交
2049
        gen_helper_macc(t0, t0, t1);
2050
        opn = "macc";
A
aurel32 已提交
2051
        break;
2052
    case OPC_VR54XX_MACCU:
P
pbrook 已提交
2053
        gen_helper_maccu(t0, t0, t1);
2054
        opn = "maccu";
A
aurel32 已提交
2055
        break;
2056
    case OPC_VR54XX_MSAC:
P
pbrook 已提交
2057
        gen_helper_msac(t0, t0, t1);
2058
        opn = "msac";
A
aurel32 已提交
2059
        break;
2060
    case OPC_VR54XX_MSACU:
P
pbrook 已提交
2061
        gen_helper_msacu(t0, t0, t1);
2062
        opn = "msacu";
A
aurel32 已提交
2063
        break;
2064
    case OPC_VR54XX_MULHI:
P
pbrook 已提交
2065
        gen_helper_mulhi(t0, t0, t1);
2066
        opn = "mulhi";
A
aurel32 已提交
2067
        break;
2068
    case OPC_VR54XX_MULHIU:
P
pbrook 已提交
2069
        gen_helper_mulhiu(t0, t0, t1);
2070
        opn = "mulhiu";
A
aurel32 已提交
2071
        break;
2072
    case OPC_VR54XX_MULSHI:
P
pbrook 已提交
2073
        gen_helper_mulshi(t0, t0, t1);
2074
        opn = "mulshi";
A
aurel32 已提交
2075
        break;
2076
    case OPC_VR54XX_MULSHIU:
P
pbrook 已提交
2077
        gen_helper_mulshiu(t0, t0, t1);
2078
        opn = "mulshiu";
A
aurel32 已提交
2079
        break;
2080
    case OPC_VR54XX_MACCHI:
P
pbrook 已提交
2081
        gen_helper_macchi(t0, t0, t1);
2082
        opn = "macchi";
A
aurel32 已提交
2083
        break;
2084
    case OPC_VR54XX_MACCHIU:
P
pbrook 已提交
2085
        gen_helper_macchiu(t0, t0, t1);
2086
        opn = "macchiu";
A
aurel32 已提交
2087
        break;
2088
    case OPC_VR54XX_MSACHI:
P
pbrook 已提交
2089
        gen_helper_msachi(t0, t0, t1);
2090
        opn = "msachi";
A
aurel32 已提交
2091
        break;
2092
    case OPC_VR54XX_MSACHIU:
P
pbrook 已提交
2093
        gen_helper_msachiu(t0, t0, t1);
2094
        opn = "msachiu";
A
aurel32 已提交
2095
        break;
2096 2097 2098
    default:
        MIPS_INVAL("mul vr54xx");
        generate_exception(ctx, EXCP_RI);
2099
        goto out;
2100
    }
2101
    gen_store_gpr(t0, rd);
2102
    MIPS_DEBUG("%s %s, %s, %s", opn, regnames[rd], regnames[rs], regnames[rt]);
2103 2104 2105 2106

 out:
    tcg_temp_free(t0);
    tcg_temp_free(t1);
2107 2108
}

2109
static void gen_cl (DisasContext *ctx, uint32_t opc,
B
bellard 已提交
2110 2111
                    int rd, int rs)
{
2112
    const char *opn = "CLx";
A
aurel32 已提交
2113
    TCGv t0;
2114

B
bellard 已提交
2115
    if (rd == 0) {
2116
        /* Treat as NOP. */
B
bellard 已提交
2117
        MIPS_DEBUG("NOP");
A
aurel32 已提交
2118
        return;
B
bellard 已提交
2119
    }
A
aurel32 已提交
2120
    t0 = tcg_temp_new();
2121
    gen_load_gpr(t0, rs);
B
bellard 已提交
2122 2123
    switch (opc) {
    case OPC_CLO:
A
aurel32 已提交
2124
        gen_helper_clo(cpu_gpr[rd], t0);
B
bellard 已提交
2125 2126 2127
        opn = "clo";
        break;
    case OPC_CLZ:
A
aurel32 已提交
2128
        gen_helper_clz(cpu_gpr[rd], t0);
B
bellard 已提交
2129 2130
        opn = "clz";
        break;
2131
#if defined(TARGET_MIPS64)
2132
    case OPC_DCLO:
A
aurel32 已提交
2133
        gen_helper_dclo(cpu_gpr[rd], t0);
2134 2135 2136
        opn = "dclo";
        break;
    case OPC_DCLZ:
A
aurel32 已提交
2137
        gen_helper_dclz(cpu_gpr[rd], t0);
2138 2139 2140
        opn = "dclz";
        break;
#endif
B
bellard 已提交
2141 2142
    }
    MIPS_DEBUG("%s %s, %s", opn, regnames[rd], regnames[rs]);
2143
    tcg_temp_free(t0);
B
bellard 已提交
2144 2145 2146
}

/* Traps */
2147
static void gen_trap (DisasContext *ctx, uint32_t opc,
B
bellard 已提交
2148 2149 2150
                      int rs, int rt, int16_t imm)
{
    int cond;
A
aurel32 已提交
2151
    TCGv t0 = tcg_temp_new();
2152
    TCGv t1 = tcg_temp_new();
B
bellard 已提交
2153 2154 2155 2156 2157 2158 2159 2160 2161 2162 2163 2164

    cond = 0;
    /* Load needed operands */
    switch (opc) {
    case OPC_TEQ:
    case OPC_TGE:
    case OPC_TGEU:
    case OPC_TLT:
    case OPC_TLTU:
    case OPC_TNE:
        /* Compare two registers */
        if (rs != rt) {
2165 2166
            gen_load_gpr(t0, rs);
            gen_load_gpr(t1, rt);
B
bellard 已提交
2167 2168
            cond = 1;
        }
2169
        break;
B
bellard 已提交
2170 2171 2172 2173 2174 2175 2176 2177
    case OPC_TEQI:
    case OPC_TGEI:
    case OPC_TGEIU:
    case OPC_TLTI:
    case OPC_TLTIU:
    case OPC_TNEI:
        /* Compare register to immediate */
        if (rs != 0 || imm != 0) {
2178 2179
            gen_load_gpr(t0, rs);
            tcg_gen_movi_tl(t1, (int32_t)imm);
B
bellard 已提交
2180 2181 2182 2183 2184 2185 2186 2187 2188 2189 2190 2191 2192
            cond = 1;
        }
        break;
    }
    if (cond == 0) {
        switch (opc) {
        case OPC_TEQ:   /* rs == rs */
        case OPC_TEQI:  /* r0 == 0  */
        case OPC_TGE:   /* rs >= rs */
        case OPC_TGEI:  /* r0 >= 0  */
        case OPC_TGEU:  /* rs >= rs unsigned */
        case OPC_TGEIU: /* r0 >= 0  unsigned */
            /* Always trap */
A
aurel32 已提交
2193
            generate_exception(ctx, EXCP_TRAP);
B
bellard 已提交
2194 2195 2196 2197 2198 2199 2200
            break;
        case OPC_TLT:   /* rs < rs           */
        case OPC_TLTI:  /* r0 < 0            */
        case OPC_TLTU:  /* rs < rs unsigned  */
        case OPC_TLTIU: /* r0 < 0  unsigned  */
        case OPC_TNE:   /* rs != rs          */
        case OPC_TNEI:  /* r0 != 0           */
2201
            /* Never trap: treat as NOP. */
A
aurel32 已提交
2202
            break;
B
bellard 已提交
2203 2204
        }
    } else {
A
aurel32 已提交
2205 2206
        int l1 = gen_new_label();

B
bellard 已提交
2207 2208 2209
        switch (opc) {
        case OPC_TEQ:
        case OPC_TEQI:
A
aurel32 已提交
2210
            tcg_gen_brcond_tl(TCG_COND_NE, t0, t1, l1);
B
bellard 已提交
2211 2212 2213
            break;
        case OPC_TGE:
        case OPC_TGEI:
A
aurel32 已提交
2214
            tcg_gen_brcond_tl(TCG_COND_LT, t0, t1, l1);
B
bellard 已提交
2215 2216 2217
            break;
        case OPC_TGEU:
        case OPC_TGEIU:
A
aurel32 已提交
2218
            tcg_gen_brcond_tl(TCG_COND_LTU, t0, t1, l1);
B
bellard 已提交
2219 2220 2221
            break;
        case OPC_TLT:
        case OPC_TLTI:
A
aurel32 已提交
2222
            tcg_gen_brcond_tl(TCG_COND_GE, t0, t1, l1);
B
bellard 已提交
2223 2224 2225
            break;
        case OPC_TLTU:
        case OPC_TLTIU:
A
aurel32 已提交
2226
            tcg_gen_brcond_tl(TCG_COND_GEU, t0, t1, l1);
B
bellard 已提交
2227 2228 2229
            break;
        case OPC_TNE:
        case OPC_TNEI:
A
aurel32 已提交
2230
            tcg_gen_brcond_tl(TCG_COND_EQ, t0, t1, l1);
B
bellard 已提交
2231 2232
            break;
        }
A
aurel32 已提交
2233
        generate_exception(ctx, EXCP_TRAP);
T
ths 已提交
2234 2235
        gen_set_label(l1);
    }
2236 2237
    tcg_temp_free(t0);
    tcg_temp_free(t1);
B
bellard 已提交
2238 2239
}

2240
static inline void gen_goto_tb(DisasContext *ctx, int n, target_ulong dest)
B
bellard 已提交
2241
{
2242 2243 2244
    TranslationBlock *tb;
    tb = ctx->tb;
    if ((tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK)) {
B
bellard 已提交
2245
        tcg_gen_goto_tb(n);
2246
        gen_save_pc(dest);
B
bellard 已提交
2247
        tcg_gen_exit_tb((long)tb + n);
2248
    } else {
2249
        gen_save_pc(dest);
B
bellard 已提交
2250
        tcg_gen_exit_tb(0);
2251
    }
B
bellard 已提交
2252 2253
}

B
bellard 已提交
2254
/* Branches (before delay slot) */
2255
static void gen_compute_branch (DisasContext *ctx, uint32_t opc,
B
bellard 已提交
2256 2257
                                int rs, int rt, int32_t offset)
{
T
ths 已提交
2258
    target_ulong btgt = -1;
2259
    int blink = 0;
A
aurel32 已提交
2260
    int bcond_compute = 0;
2261 2262
    TCGv t0 = tcg_temp_new();
    TCGv t1 = tcg_temp_new();
2263 2264

    if (ctx->hflags & MIPS_HFLAG_BMASK) {
2265
#ifdef MIPS_DEBUG_DISAS
2266
        LOG_DISAS("Branch in delay slot at PC 0x" TARGET_FMT_lx "\n", ctx->pc);
2267
#endif
2268
        generate_exception(ctx, EXCP_RI);
2269
        goto out;
2270
    }
B
bellard 已提交
2271 2272 2273 2274 2275 2276 2277 2278 2279

    /* Load needed operands */
    switch (opc) {
    case OPC_BEQ:
    case OPC_BEQL:
    case OPC_BNE:
    case OPC_BNEL:
        /* Compare two registers */
        if (rs != rt) {
2280 2281
            gen_load_gpr(t0, rs);
            gen_load_gpr(t1, rt);
A
aurel32 已提交
2282
            bcond_compute = 1;
B
bellard 已提交
2283
        }
T
ths 已提交
2284
        btgt = ctx->pc + 4 + offset;
B
bellard 已提交
2285 2286 2287 2288 2289 2290 2291 2292 2293 2294 2295 2296 2297 2298 2299
        break;
    case OPC_BGEZ:
    case OPC_BGEZAL:
    case OPC_BGEZALL:
    case OPC_BGEZL:
    case OPC_BGTZ:
    case OPC_BGTZL:
    case OPC_BLEZ:
    case OPC_BLEZL:
    case OPC_BLTZ:
    case OPC_BLTZAL:
    case OPC_BLTZALL:
    case OPC_BLTZL:
        /* Compare to zero */
        if (rs != 0) {
2300
            gen_load_gpr(t0, rs);
A
aurel32 已提交
2301
            bcond_compute = 1;
B
bellard 已提交
2302
        }
T
ths 已提交
2303
        btgt = ctx->pc + 4 + offset;
B
bellard 已提交
2304 2305 2306 2307
        break;
    case OPC_J:
    case OPC_JAL:
        /* Jump to immediate */
T
ths 已提交
2308
        btgt = ((ctx->pc + 4) & (int32_t)0xF0000000) | (uint32_t)offset;
B
bellard 已提交
2309 2310 2311 2312
        break;
    case OPC_JR:
    case OPC_JALR:
        /* Jump to register */
2313 2314
        if (offset != 0 && offset != 16) {
            /* Hint = 0 is JR/JALR, hint 16 is JR.HB/JALR.HB, the
2315
               others are reserved. */
2316
            MIPS_INVAL("jump hint");
B
bellard 已提交
2317
            generate_exception(ctx, EXCP_RI);
2318
            goto out;
B
bellard 已提交
2319
        }
T
ths 已提交
2320
        gen_load_gpr(btarget, rs);
B
bellard 已提交
2321 2322 2323 2324
        break;
    default:
        MIPS_INVAL("branch/jump");
        generate_exception(ctx, EXCP_RI);
2325
        goto out;
B
bellard 已提交
2326
    }
A
aurel32 已提交
2327
    if (bcond_compute == 0) {
B
bellard 已提交
2328 2329 2330 2331 2332 2333 2334 2335 2336
        /* No condition to be computed */
        switch (opc) {
        case OPC_BEQ:     /* rx == rx        */
        case OPC_BEQL:    /* rx == rx likely */
        case OPC_BGEZ:    /* 0 >= 0          */
        case OPC_BGEZL:   /* 0 >= 0 likely   */
        case OPC_BLEZ:    /* 0 <= 0          */
        case OPC_BLEZL:   /* 0 <= 0 likely   */
            /* Always take */
B
bellard 已提交
2337
            ctx->hflags |= MIPS_HFLAG_B;
B
bellard 已提交
2338 2339 2340 2341 2342 2343
            MIPS_DEBUG("balways");
            break;
        case OPC_BGEZAL:  /* 0 >= 0          */
        case OPC_BGEZALL: /* 0 >= 0 likely   */
            /* Always take and link */
            blink = 31;
B
bellard 已提交
2344
            ctx->hflags |= MIPS_HFLAG_B;
B
bellard 已提交
2345 2346 2347 2348 2349
            MIPS_DEBUG("balways and link");
            break;
        case OPC_BNE:     /* rx != rx        */
        case OPC_BGTZ:    /* 0 > 0           */
        case OPC_BLTZ:    /* 0 < 0           */
2350
            /* Treat as NOP. */
B
bellard 已提交
2351
            MIPS_DEBUG("bnever (NOP)");
2352
            goto out;
2353
        case OPC_BLTZAL:  /* 0 < 0           */
2354
            tcg_gen_movi_tl(cpu_gpr[31], ctx->pc + 8);
T
ths 已提交
2355
            MIPS_DEBUG("bnever and link");
2356
            goto out;
2357
        case OPC_BLTZALL: /* 0 < 0 likely */
2358
            tcg_gen_movi_tl(cpu_gpr[31], ctx->pc + 8);
T
ths 已提交
2359 2360 2361
            /* Skip the instruction in the delay slot */
            MIPS_DEBUG("bnever, link and skip");
            ctx->pc += 4;
2362
            goto out;
B
bellard 已提交
2363 2364 2365 2366 2367
        case OPC_BNEL:    /* rx != rx likely */
        case OPC_BGTZL:   /* 0 > 0 likely */
        case OPC_BLTZL:   /* 0 < 0 likely */
            /* Skip the instruction in the delay slot */
            MIPS_DEBUG("bnever and skip");
T
ths 已提交
2368
            ctx->pc += 4;
2369
            goto out;
B
bellard 已提交
2370
        case OPC_J:
B
bellard 已提交
2371
            ctx->hflags |= MIPS_HFLAG_B;
T
ths 已提交
2372
            MIPS_DEBUG("j " TARGET_FMT_lx, btgt);
B
bellard 已提交
2373 2374 2375
            break;
        case OPC_JAL:
            blink = 31;
B
bellard 已提交
2376
            ctx->hflags |= MIPS_HFLAG_B;
T
ths 已提交
2377
            MIPS_DEBUG("jal " TARGET_FMT_lx, btgt);
B
bellard 已提交
2378 2379
            break;
        case OPC_JR:
B
bellard 已提交
2380
            ctx->hflags |= MIPS_HFLAG_BR;
B
bellard 已提交
2381 2382 2383 2384
            MIPS_DEBUG("jr %s", regnames[rs]);
            break;
        case OPC_JALR:
            blink = rt;
B
bellard 已提交
2385
            ctx->hflags |= MIPS_HFLAG_BR;
B
bellard 已提交
2386 2387 2388 2389 2390
            MIPS_DEBUG("jalr %s, %s", regnames[rt], regnames[rs]);
            break;
        default:
            MIPS_INVAL("branch/jump");
            generate_exception(ctx, EXCP_RI);
2391
            goto out;
B
bellard 已提交
2392 2393 2394 2395
        }
    } else {
        switch (opc) {
        case OPC_BEQ:
2396
            gen_op_eq(bcond, t0, t1);
2397
            MIPS_DEBUG("beq %s, %s, " TARGET_FMT_lx,
T
ths 已提交
2398
                       regnames[rs], regnames[rt], btgt);
B
bellard 已提交
2399 2400
            goto not_likely;
        case OPC_BEQL:
2401
            gen_op_eq(bcond, t0, t1);
2402
            MIPS_DEBUG("beql %s, %s, " TARGET_FMT_lx,
T
ths 已提交
2403
                       regnames[rs], regnames[rt], btgt);
B
bellard 已提交
2404 2405
            goto likely;
        case OPC_BNE:
2406
            gen_op_ne(bcond, t0, t1);
2407
            MIPS_DEBUG("bne %s, %s, " TARGET_FMT_lx,
T
ths 已提交
2408
                       regnames[rs], regnames[rt], btgt);
B
bellard 已提交
2409 2410
            goto not_likely;
        case OPC_BNEL:
2411
            gen_op_ne(bcond, t0, t1);
2412
            MIPS_DEBUG("bnel %s, %s, " TARGET_FMT_lx,
T
ths 已提交
2413
                       regnames[rs], regnames[rt], btgt);
B
bellard 已提交
2414 2415
            goto likely;
        case OPC_BGEZ:
2416
            gen_op_gez(bcond, t0);
T
ths 已提交
2417
            MIPS_DEBUG("bgez %s, " TARGET_FMT_lx, regnames[rs], btgt);
B
bellard 已提交
2418 2419
            goto not_likely;
        case OPC_BGEZL:
2420
            gen_op_gez(bcond, t0);
T
ths 已提交
2421
            MIPS_DEBUG("bgezl %s, " TARGET_FMT_lx, regnames[rs], btgt);
B
bellard 已提交
2422 2423
            goto likely;
        case OPC_BGEZAL:
2424
            gen_op_gez(bcond, t0);
T
ths 已提交
2425
            MIPS_DEBUG("bgezal %s, " TARGET_FMT_lx, regnames[rs], btgt);
B
bellard 已提交
2426 2427 2428
            blink = 31;
            goto not_likely;
        case OPC_BGEZALL:
2429
            gen_op_gez(bcond, t0);
B
bellard 已提交
2430
            blink = 31;
T
ths 已提交
2431
            MIPS_DEBUG("bgezall %s, " TARGET_FMT_lx, regnames[rs], btgt);
B
bellard 已提交
2432 2433
            goto likely;
        case OPC_BGTZ:
2434
            gen_op_gtz(bcond, t0);
T
ths 已提交
2435
            MIPS_DEBUG("bgtz %s, " TARGET_FMT_lx, regnames[rs], btgt);
B
bellard 已提交
2436 2437
            goto not_likely;
        case OPC_BGTZL:
2438
            gen_op_gtz(bcond, t0);
T
ths 已提交
2439
            MIPS_DEBUG("bgtzl %s, " TARGET_FMT_lx, regnames[rs], btgt);
B
bellard 已提交
2440 2441
            goto likely;
        case OPC_BLEZ:
2442
            gen_op_lez(bcond, t0);
T
ths 已提交
2443
            MIPS_DEBUG("blez %s, " TARGET_FMT_lx, regnames[rs], btgt);
B
bellard 已提交
2444 2445
            goto not_likely;
        case OPC_BLEZL:
2446
            gen_op_lez(bcond, t0);
T
ths 已提交
2447
            MIPS_DEBUG("blezl %s, " TARGET_FMT_lx, regnames[rs], btgt);
B
bellard 已提交
2448 2449
            goto likely;
        case OPC_BLTZ:
2450
            gen_op_ltz(bcond, t0);
T
ths 已提交
2451
            MIPS_DEBUG("bltz %s, " TARGET_FMT_lx, regnames[rs], btgt);
B
bellard 已提交
2452 2453
            goto not_likely;
        case OPC_BLTZL:
2454
            gen_op_ltz(bcond, t0);
T
ths 已提交
2455
            MIPS_DEBUG("bltzl %s, " TARGET_FMT_lx, regnames[rs], btgt);
B
bellard 已提交
2456 2457
            goto likely;
        case OPC_BLTZAL:
2458
            gen_op_ltz(bcond, t0);
B
bellard 已提交
2459
            blink = 31;
T
ths 已提交
2460
            MIPS_DEBUG("bltzal %s, " TARGET_FMT_lx, regnames[rs], btgt);
B
bellard 已提交
2461
        not_likely:
B
bellard 已提交
2462
            ctx->hflags |= MIPS_HFLAG_BC;
B
bellard 已提交
2463 2464
            break;
        case OPC_BLTZALL:
2465
            gen_op_ltz(bcond, t0);
B
bellard 已提交
2466
            blink = 31;
T
ths 已提交
2467
            MIPS_DEBUG("bltzall %s, " TARGET_FMT_lx, regnames[rs], btgt);
B
bellard 已提交
2468
        likely:
B
bellard 已提交
2469
            ctx->hflags |= MIPS_HFLAG_BL;
B
bellard 已提交
2470
            break;
T
ths 已提交
2471 2472 2473
        default:
            MIPS_INVAL("conditional branch/jump");
            generate_exception(ctx, EXCP_RI);
2474
            goto out;
B
bellard 已提交
2475 2476
        }
    }
2477
    MIPS_DEBUG("enter ds: link %d cond %02x target " TARGET_FMT_lx,
T
ths 已提交
2478
               blink, ctx->hflags, btgt);
2479

T
ths 已提交
2480
    ctx->btarget = btgt;
B
bellard 已提交
2481
    if (blink > 0) {
2482
        tcg_gen_movi_tl(cpu_gpr[blink], ctx->pc + 8);
B
bellard 已提交
2483
    }
2484 2485 2486 2487

 out:
    tcg_temp_free(t0);
    tcg_temp_free(t1);
B
bellard 已提交
2488 2489
}

2490 2491
/* special3 bitfield operations */
static void gen_bitops (DisasContext *ctx, uint32_t opc, int rt,
2492
                        int rs, int lsb, int msb)
2493
{
P
pbrook 已提交
2494 2495
    TCGv t0 = tcg_temp_new();
    TCGv t1 = tcg_temp_new();
A
aurel32 已提交
2496
    target_ulong mask;
2497 2498

    gen_load_gpr(t1, rs);
2499 2500 2501 2502
    switch (opc) {
    case OPC_EXT:
        if (lsb + msb > 31)
            goto fail;
A
aurel32 已提交
2503 2504 2505 2506 2507 2508
        tcg_gen_shri_tl(t0, t1, lsb);
        if (msb != 31) {
            tcg_gen_andi_tl(t0, t0, (1 << (msb + 1)) - 1);
        } else {
            tcg_gen_ext32s_tl(t0, t0);
        }
2509
        break;
T
ths 已提交
2510
#if defined(TARGET_MIPS64)
2511
    case OPC_DEXTM:
A
aurel32 已提交
2512 2513 2514 2515
        tcg_gen_shri_tl(t0, t1, lsb);
        if (msb != 31) {
            tcg_gen_andi_tl(t0, t0, (1ULL << (msb + 1 + 32)) - 1);
        }
2516 2517
        break;
    case OPC_DEXTU:
A
aurel32 已提交
2518 2519
        tcg_gen_shri_tl(t0, t1, lsb + 32);
        tcg_gen_andi_tl(t0, t0, (1ULL << (msb + 1)) - 1);
2520 2521
        break;
    case OPC_DEXT:
A
aurel32 已提交
2522 2523
        tcg_gen_shri_tl(t0, t1, lsb);
        tcg_gen_andi_tl(t0, t0, (1ULL << (msb + 1)) - 1);
2524
        break;
T
ths 已提交
2525
#endif
2526 2527 2528
    case OPC_INS:
        if (lsb > msb)
            goto fail;
A
aurel32 已提交
2529
        mask = ((msb - lsb + 1 < 32) ? ((1 << (msb - lsb + 1)) - 1) : ~0) << lsb;
2530
        gen_load_gpr(t0, rt);
A
aurel32 已提交
2531 2532 2533 2534 2535
        tcg_gen_andi_tl(t0, t0, ~mask);
        tcg_gen_shli_tl(t1, t1, lsb);
        tcg_gen_andi_tl(t1, t1, mask);
        tcg_gen_or_tl(t0, t0, t1);
        tcg_gen_ext32s_tl(t0, t0);
2536
        break;
T
ths 已提交
2537
#if defined(TARGET_MIPS64)
2538 2539 2540
    case OPC_DINSM:
        if (lsb > msb)
            goto fail;
A
aurel32 已提交
2541
        mask = ((msb - lsb + 1 + 32 < 64) ? ((1ULL << (msb - lsb + 1 + 32)) - 1) : ~0ULL) << lsb;
2542
        gen_load_gpr(t0, rt);
A
aurel32 已提交
2543 2544 2545 2546
        tcg_gen_andi_tl(t0, t0, ~mask);
        tcg_gen_shli_tl(t1, t1, lsb);
        tcg_gen_andi_tl(t1, t1, mask);
        tcg_gen_or_tl(t0, t0, t1);
2547 2548 2549 2550
        break;
    case OPC_DINSU:
        if (lsb > msb)
            goto fail;
A
aurel32 已提交
2551
        mask = ((1ULL << (msb - lsb + 1)) - 1) << lsb;
2552
        gen_load_gpr(t0, rt);
A
aurel32 已提交
2553 2554 2555 2556
        tcg_gen_andi_tl(t0, t0, ~mask);
        tcg_gen_shli_tl(t1, t1, lsb + 32);
        tcg_gen_andi_tl(t1, t1, mask);
        tcg_gen_or_tl(t0, t0, t1);
2557 2558 2559 2560
        break;
    case OPC_DINS:
        if (lsb > msb)
            goto fail;
2561
        gen_load_gpr(t0, rt);
A
aurel32 已提交
2562 2563 2564 2565 2566 2567
        mask = ((1ULL << (msb - lsb + 1)) - 1) << lsb;
        gen_load_gpr(t0, rt);
        tcg_gen_andi_tl(t0, t0, ~mask);
        tcg_gen_shli_tl(t1, t1, lsb);
        tcg_gen_andi_tl(t1, t1, mask);
        tcg_gen_or_tl(t0, t0, t1);
2568
        break;
T
ths 已提交
2569
#endif
2570 2571 2572 2573
    default:
fail:
        MIPS_INVAL("bitops");
        generate_exception(ctx, EXCP_RI);
2574 2575
        tcg_temp_free(t0);
        tcg_temp_free(t1);
2576 2577
        return;
    }
2578 2579 2580
    gen_store_gpr(t0, rt);
    tcg_temp_free(t0);
    tcg_temp_free(t1);
2581 2582
}

2583 2584
static void gen_bshfl (DisasContext *ctx, uint32_t op2, int rt, int rd)
{
A
aurel32 已提交
2585
    TCGv t0;
2586

A
aurel32 已提交
2587 2588 2589 2590 2591 2592 2593 2594
    if (rd == 0) {
        /* If no destination, treat it as a NOP. */
        MIPS_DEBUG("NOP");
        return;
    }

    t0 = tcg_temp_new();
    gen_load_gpr(t0, rt);
2595 2596
    switch (op2) {
    case OPC_WSBH:
A
aurel32 已提交
2597 2598 2599 2600 2601 2602 2603 2604 2605 2606 2607
        {
            TCGv t1 = tcg_temp_new();

            tcg_gen_shri_tl(t1, t0, 8);
            tcg_gen_andi_tl(t1, t1, 0x00FF00FF);
            tcg_gen_shli_tl(t0, t0, 8);
            tcg_gen_andi_tl(t0, t0, ~0x00FF00FF);
            tcg_gen_or_tl(t0, t0, t1);
            tcg_temp_free(t1);
            tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
        }
2608 2609
        break;
    case OPC_SEB:
A
aurel32 已提交
2610
        tcg_gen_ext8s_tl(cpu_gpr[rd], t0);
2611 2612
        break;
    case OPC_SEH:
A
aurel32 已提交
2613
        tcg_gen_ext16s_tl(cpu_gpr[rd], t0);
2614 2615 2616
        break;
#if defined(TARGET_MIPS64)
    case OPC_DSBH:
A
aurel32 已提交
2617 2618 2619 2620 2621 2622 2623 2624 2625 2626
        {
            TCGv t1 = tcg_temp_new();

            tcg_gen_shri_tl(t1, t0, 8);
            tcg_gen_andi_tl(t1, t1, 0x00FF00FF00FF00FFULL);
            tcg_gen_shli_tl(t0, t0, 8);
            tcg_gen_andi_tl(t0, t0, ~0x00FF00FF00FF00FFULL);
            tcg_gen_or_tl(cpu_gpr[rd], t0, t1);
            tcg_temp_free(t1);
        }
2627 2628
        break;
    case OPC_DSHD:
A
aurel32 已提交
2629 2630 2631 2632 2633 2634 2635 2636 2637 2638 2639 2640 2641
        {
            TCGv t1 = tcg_temp_new();

            tcg_gen_shri_tl(t1, t0, 16);
            tcg_gen_andi_tl(t1, t1, 0x0000FFFF0000FFFFULL);
            tcg_gen_shli_tl(t0, t0, 16);
            tcg_gen_andi_tl(t0, t0, ~0x0000FFFF0000FFFFULL);
            tcg_gen_or_tl(t0, t0, t1);
            tcg_gen_shri_tl(t1, t0, 32);
            tcg_gen_shli_tl(t0, t0, 32);
            tcg_gen_or_tl(cpu_gpr[rd], t0, t1);
            tcg_temp_free(t1);
        }
2642 2643 2644 2645 2646 2647 2648 2649 2650 2651 2652
        break;
#endif
    default:
        MIPS_INVAL("bsfhl");
        generate_exception(ctx, EXCP_RI);
        tcg_temp_free(t0);
        return;
    }
    tcg_temp_free(t0);
}

2653
#ifndef CONFIG_USER_ONLY
T
ths 已提交
2654
/* CP0 (MMU and control) */
T
ths 已提交
2655 2656
static inline void gen_mfc0_load32 (TCGv t, target_ulong off)
{
P
pbrook 已提交
2657
    TCGv_i32 r_tmp = tcg_temp_new_i32();
T
ths 已提交
2658 2659 2660

    tcg_gen_ld_i32(r_tmp, cpu_env, off);
    tcg_gen_ext_i32_tl(t, r_tmp);
P
pbrook 已提交
2661
    tcg_temp_free_i32(r_tmp);
T
ths 已提交
2662 2663 2664 2665
}

static inline void gen_mfc0_load64 (TCGv t, target_ulong off)
{
T
ths 已提交
2666 2667
    tcg_gen_ld_tl(t, cpu_env, off);
    tcg_gen_ext32s_tl(t, t);
T
ths 已提交
2668 2669
}

2670 2671
static inline void gen_mtc0_store32 (TCGv t, target_ulong off)
{
P
pbrook 已提交
2672
    TCGv_i32 r_tmp = tcg_temp_new_i32();
2673 2674 2675

    tcg_gen_trunc_tl_i32(r_tmp, t);
    tcg_gen_st_i32(r_tmp, cpu_env, off);
P
pbrook 已提交
2676
    tcg_temp_free_i32(r_tmp);
2677 2678 2679 2680
}

static inline void gen_mtc0_store64 (TCGv t, target_ulong off)
{
T
ths 已提交
2681 2682
    tcg_gen_ext32s_tl(t, t);
    tcg_gen_st_tl(t, cpu_env, off);
2683 2684
}

2685
static void gen_mfc0 (CPUState *env, DisasContext *ctx, TCGv t0, int reg, int sel)
2686
{
2687
    const char *rn = "invalid";
2688

2689 2690 2691
    if (sel != 0)
        check_insn(env, ctx, ISA_MIPS32);

2692 2693
    switch (reg) {
    case 0:
2694 2695
        switch (sel) {
        case 0:
2696
            gen_mfc0_load32(t0, offsetof(CPUState, CP0_Index));
2697 2698 2699
            rn = "Index";
            break;
        case 1:
2700
            check_insn(env, ctx, ASE_MT);
P
pbrook 已提交
2701
            gen_helper_mfc0_mvpcontrol(t0);
2702
            rn = "MVPControl";
2703
            break;
2704
        case 2:
2705
            check_insn(env, ctx, ASE_MT);
P
pbrook 已提交
2706
            gen_helper_mfc0_mvpconf0(t0);
2707
            rn = "MVPConf0";
2708
            break;
2709
        case 3:
2710
            check_insn(env, ctx, ASE_MT);
P
pbrook 已提交
2711
            gen_helper_mfc0_mvpconf1(t0);
2712
            rn = "MVPConf1";
2713
            break;
2714 2715 2716
        default:
            goto die;
        }
2717 2718
        break;
    case 1:
2719 2720
        switch (sel) {
        case 0:
P
pbrook 已提交
2721
            gen_helper_mfc0_random(t0);
2722
            rn = "Random";
T
ths 已提交
2723
            break;
2724
        case 1:
2725
            check_insn(env, ctx, ASE_MT);
2726
            gen_mfc0_load32(t0, offsetof(CPUState, CP0_VPEControl));
2727
            rn = "VPEControl";
2728
            break;
2729
        case 2:
2730
            check_insn(env, ctx, ASE_MT);
2731
            gen_mfc0_load32(t0, offsetof(CPUState, CP0_VPEConf0));
2732
            rn = "VPEConf0";
2733
            break;
2734
        case 3:
2735
            check_insn(env, ctx, ASE_MT);
2736
            gen_mfc0_load32(t0, offsetof(CPUState, CP0_VPEConf1));
2737
            rn = "VPEConf1";
2738
            break;
2739
        case 4:
2740
            check_insn(env, ctx, ASE_MT);
2741
            gen_mfc0_load64(t0, offsetof(CPUState, CP0_YQMask));
2742
            rn = "YQMask";
2743
            break;
2744
        case 5:
2745
            check_insn(env, ctx, ASE_MT);
2746
            gen_mfc0_load64(t0, offsetof(CPUState, CP0_VPESchedule));
2747
            rn = "VPESchedule";
2748
            break;
2749
        case 6:
2750
            check_insn(env, ctx, ASE_MT);
2751
            gen_mfc0_load64(t0, offsetof(CPUState, CP0_VPEScheFBack));
2752
            rn = "VPEScheFBack";
2753
            break;
2754
        case 7:
2755
            check_insn(env, ctx, ASE_MT);
2756
            gen_mfc0_load32(t0, offsetof(CPUState, CP0_VPEOpt));
2757
            rn = "VPEOpt";
2758
            break;
2759 2760 2761
        default:
            goto die;
        }
2762 2763
        break;
    case 2:
2764 2765
        switch (sel) {
        case 0:
2766 2767
            tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUState, CP0_EntryLo0));
            tcg_gen_ext32s_tl(t0, t0);
T
ths 已提交
2768 2769
            rn = "EntryLo0";
            break;
2770
        case 1:
2771
            check_insn(env, ctx, ASE_MT);
P
pbrook 已提交
2772
            gen_helper_mfc0_tcstatus(t0);
T
ths 已提交
2773
            rn = "TCStatus";
2774
            break;
2775
        case 2:
2776
            check_insn(env, ctx, ASE_MT);
P
pbrook 已提交
2777
            gen_helper_mfc0_tcbind(t0);
T
ths 已提交
2778
            rn = "TCBind";
2779
            break;
2780
        case 3:
2781
            check_insn(env, ctx, ASE_MT);
P
pbrook 已提交
2782
            gen_helper_mfc0_tcrestart(t0);
T
ths 已提交
2783
            rn = "TCRestart";
2784
            break;
2785
        case 4:
2786
            check_insn(env, ctx, ASE_MT);
P
pbrook 已提交
2787
            gen_helper_mfc0_tchalt(t0);
T
ths 已提交
2788
            rn = "TCHalt";
2789
            break;
2790
        case 5:
2791
            check_insn(env, ctx, ASE_MT);
P
pbrook 已提交
2792
            gen_helper_mfc0_tccontext(t0);
T
ths 已提交
2793
            rn = "TCContext";
2794
            break;
2795
        case 6:
2796
            check_insn(env, ctx, ASE_MT);
P
pbrook 已提交
2797
            gen_helper_mfc0_tcschedule(t0);
T
ths 已提交
2798
            rn = "TCSchedule";
2799
            break;
2800
        case 7:
2801
            check_insn(env, ctx, ASE_MT);
P
pbrook 已提交
2802
            gen_helper_mfc0_tcschefback(t0);
T
ths 已提交
2803
            rn = "TCScheFBack";
2804
            break;
2805 2806 2807
        default:
            goto die;
        }
2808 2809
        break;
    case 3:
2810 2811
        switch (sel) {
        case 0:
2812 2813
            tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUState, CP0_EntryLo1));
            tcg_gen_ext32s_tl(t0, t0);
T
ths 已提交
2814 2815
            rn = "EntryLo1";
            break;
2816 2817
        default:
            goto die;
2818
        }
2819 2820
        break;
    case 4:
2821 2822
        switch (sel) {
        case 0:
2823 2824
            tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUState, CP0_Context));
            tcg_gen_ext32s_tl(t0, t0);
T
ths 已提交
2825 2826
            rn = "Context";
            break;
2827
        case 1:
P
pbrook 已提交
2828
//            gen_helper_mfc0_contextconfig(t0); /* SmartMIPS ASE */
T
ths 已提交
2829 2830
            rn = "ContextConfig";
//            break;
2831 2832
        default:
            goto die;
2833
        }
2834 2835
        break;
    case 5:
2836 2837
        switch (sel) {
        case 0:
2838
            gen_mfc0_load32(t0, offsetof(CPUState, CP0_PageMask));
T
ths 已提交
2839 2840
            rn = "PageMask";
            break;
2841
        case 1:
2842
            check_insn(env, ctx, ISA_MIPS32R2);
2843
            gen_mfc0_load32(t0, offsetof(CPUState, CP0_PageGrain));
T
ths 已提交
2844 2845
            rn = "PageGrain";
            break;
2846 2847
        default:
            goto die;
2848
        }
2849 2850
        break;
    case 6:
2851 2852
        switch (sel) {
        case 0:
2853
            gen_mfc0_load32(t0, offsetof(CPUState, CP0_Wired));
T
ths 已提交
2854 2855
            rn = "Wired";
            break;
2856
        case 1:
2857
            check_insn(env, ctx, ISA_MIPS32R2);
2858
            gen_mfc0_load32(t0, offsetof(CPUState, CP0_SRSConf0));
T
ths 已提交
2859
            rn = "SRSConf0";
2860
            break;
2861
        case 2:
2862
            check_insn(env, ctx, ISA_MIPS32R2);
2863
            gen_mfc0_load32(t0, offsetof(CPUState, CP0_SRSConf1));
T
ths 已提交
2864
            rn = "SRSConf1";
2865
            break;
2866
        case 3:
2867
            check_insn(env, ctx, ISA_MIPS32R2);
2868
            gen_mfc0_load32(t0, offsetof(CPUState, CP0_SRSConf2));
T
ths 已提交
2869
            rn = "SRSConf2";
2870
            break;
2871
        case 4:
2872
            check_insn(env, ctx, ISA_MIPS32R2);
2873
            gen_mfc0_load32(t0, offsetof(CPUState, CP0_SRSConf3));
T
ths 已提交
2874
            rn = "SRSConf3";
2875
            break;
2876
        case 5:
2877
            check_insn(env, ctx, ISA_MIPS32R2);
2878
            gen_mfc0_load32(t0, offsetof(CPUState, CP0_SRSConf4));
T
ths 已提交
2879
            rn = "SRSConf4";
2880
            break;
2881 2882
        default:
            goto die;
2883
        }
2884
        break;
2885
    case 7:
2886 2887
        switch (sel) {
        case 0:
2888
            check_insn(env, ctx, ISA_MIPS32R2);
2889
            gen_mfc0_load32(t0, offsetof(CPUState, CP0_HWREna));
T
ths 已提交
2890 2891
            rn = "HWREna";
            break;
2892 2893
        default:
            goto die;
2894
        }
2895
        break;
2896
    case 8:
2897 2898
        switch (sel) {
        case 0:
2899 2900
            tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUState, CP0_BadVAddr));
            tcg_gen_ext32s_tl(t0, t0);
T
ths 已提交
2901
            rn = "BadVAddr";
T
ths 已提交
2902
            break;
2903 2904 2905
        default:
            goto die;
       }
2906 2907
        break;
    case 9:
2908 2909
        switch (sel) {
        case 0:
P
pbrook 已提交
2910 2911 2912
            /* Mark as an IO operation because we read the time.  */
            if (use_icount)
                gen_io_start();
P
pbrook 已提交
2913
            gen_helper_mfc0_count(t0);
P
pbrook 已提交
2914 2915 2916 2917
            if (use_icount) {
                gen_io_end();
                ctx->bstate = BS_STOP;
            }
T
ths 已提交
2918 2919 2920
            rn = "Count";
            break;
        /* 6,7 are implementation dependent */
2921 2922
        default:
            goto die;
T
ths 已提交
2923
        }
2924 2925
        break;
    case 10:
2926 2927
        switch (sel) {
        case 0:
2928 2929
            tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUState, CP0_EntryHi));
            tcg_gen_ext32s_tl(t0, t0);
T
ths 已提交
2930 2931
            rn = "EntryHi";
            break;
2932 2933
        default:
            goto die;
2934
        }
2935 2936
        break;
    case 11:
2937 2938
        switch (sel) {
        case 0:
2939
            gen_mfc0_load32(t0, offsetof(CPUState, CP0_Compare));
T
ths 已提交
2940 2941 2942
            rn = "Compare";
            break;
        /* 6,7 are implementation dependent */
2943 2944
        default:
            goto die;
T
ths 已提交
2945
        }
2946 2947
        break;
    case 12:
2948 2949
        switch (sel) {
        case 0:
2950
            gen_mfc0_load32(t0, offsetof(CPUState, CP0_Status));
T
ths 已提交
2951 2952
            rn = "Status";
            break;
2953
        case 1:
2954
            check_insn(env, ctx, ISA_MIPS32R2);
2955
            gen_mfc0_load32(t0, offsetof(CPUState, CP0_IntCtl));
T
ths 已提交
2956 2957
            rn = "IntCtl";
            break;
2958
        case 2:
2959
            check_insn(env, ctx, ISA_MIPS32R2);
2960
            gen_mfc0_load32(t0, offsetof(CPUState, CP0_SRSCtl));
T
ths 已提交
2961 2962
            rn = "SRSCtl";
            break;
2963
        case 3:
2964
            check_insn(env, ctx, ISA_MIPS32R2);
2965
            gen_mfc0_load32(t0, offsetof(CPUState, CP0_SRSMap));
T
ths 已提交
2966
            rn = "SRSMap";
2967
            break;
2968 2969 2970
        default:
            goto die;
       }
2971 2972
        break;
    case 13:
2973 2974
        switch (sel) {
        case 0:
2975
            gen_mfc0_load32(t0, offsetof(CPUState, CP0_Cause));
T
ths 已提交
2976 2977
            rn = "Cause";
            break;
2978 2979 2980
        default:
            goto die;
       }
2981 2982
        break;
    case 14:
2983 2984
        switch (sel) {
        case 0:
2985 2986
            tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUState, CP0_EPC));
            tcg_gen_ext32s_tl(t0, t0);
T
ths 已提交
2987 2988
            rn = "EPC";
            break;
2989 2990
        default:
            goto die;
2991
        }
2992 2993
        break;
    case 15:
2994 2995
        switch (sel) {
        case 0:
2996
            gen_mfc0_load32(t0, offsetof(CPUState, CP0_PRid));
T
ths 已提交
2997 2998
            rn = "PRid";
            break;
2999
        case 1:
3000
            check_insn(env, ctx, ISA_MIPS32R2);
3001
            gen_mfc0_load32(t0, offsetof(CPUState, CP0_EBase));
T
ths 已提交
3002 3003
            rn = "EBase";
            break;
3004 3005 3006
        default:
            goto die;
       }
3007 3008 3009 3010
        break;
    case 16:
        switch (sel) {
        case 0:
3011
            gen_mfc0_load32(t0, offsetof(CPUState, CP0_Config0));
3012 3013 3014
            rn = "Config";
            break;
        case 1:
3015
            gen_mfc0_load32(t0, offsetof(CPUState, CP0_Config1));
3016 3017
            rn = "Config1";
            break;
3018
        case 2:
3019
            gen_mfc0_load32(t0, offsetof(CPUState, CP0_Config2));
3020 3021 3022
            rn = "Config2";
            break;
        case 3:
3023
            gen_mfc0_load32(t0, offsetof(CPUState, CP0_Config3));
3024 3025
            rn = "Config3";
            break;
3026 3027 3028
        /* 4,5 are reserved */
        /* 6,7 are implementation dependent */
        case 6:
3029
            gen_mfc0_load32(t0, offsetof(CPUState, CP0_Config6));
3030 3031 3032
            rn = "Config6";
            break;
        case 7:
3033
            gen_mfc0_load32(t0, offsetof(CPUState, CP0_Config7));
3034 3035
            rn = "Config7";
            break;
3036 3037 3038 3039 3040
        default:
            goto die;
        }
        break;
    case 17:
3041 3042
        switch (sel) {
        case 0:
P
pbrook 已提交
3043
            gen_helper_mfc0_lladdr(t0);
T
ths 已提交
3044 3045
            rn = "LLAddr";
            break;
3046 3047 3048
        default:
            goto die;
        }
3049 3050
        break;
    case 18:
3051
        switch (sel) {
3052
        case 0 ... 7:
P
pbrook 已提交
3053
            gen_helper_1i(mfc0_watchlo, t0, sel);
T
ths 已提交
3054 3055
            rn = "WatchLo";
            break;
3056 3057 3058
        default:
            goto die;
        }
3059 3060
        break;
    case 19:
3061
        switch (sel) {
3062
        case 0 ...7:
P
pbrook 已提交
3063
            gen_helper_1i(mfc0_watchhi, t0, sel);
T
ths 已提交
3064 3065
            rn = "WatchHi";
            break;
3066 3067 3068
        default:
            goto die;
        }
3069
        break;
3070
    case 20:
3071 3072
        switch (sel) {
        case 0:
3073
#if defined(TARGET_MIPS64)
3074
            check_insn(env, ctx, ISA_MIPS3);
3075 3076
            tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUState, CP0_XContext));
            tcg_gen_ext32s_tl(t0, t0);
T
ths 已提交
3077 3078
            rn = "XContext";
            break;
T
ths 已提交
3079
#endif
3080 3081 3082
        default:
            goto die;
        }
3083 3084
        break;
    case 21:
3085 3086 3087
       /* Officially reserved, but sel 0 is used for R1x000 framemask */
        switch (sel) {
        case 0:
3088
            gen_mfc0_load32(t0, offsetof(CPUState, CP0_Framemask));
T
ths 已提交
3089 3090
            rn = "Framemask";
            break;
3091 3092 3093
        default:
            goto die;
        }
3094 3095
        break;
    case 22:
3096
        tcg_gen_movi_tl(t0, 0); /* unimplemented */
T
ths 已提交
3097 3098
        rn = "'Diagnostic"; /* implementation dependent */
        break;
3099
    case 23:
3100 3101
        switch (sel) {
        case 0:
P
pbrook 已提交
3102
            gen_helper_mfc0_debug(t0); /* EJTAG support */
T
ths 已提交
3103 3104
            rn = "Debug";
            break;
3105
        case 1:
P
pbrook 已提交
3106
//            gen_helper_mfc0_tracecontrol(t0); /* PDtrace support */
T
ths 已提交
3107 3108
            rn = "TraceControl";
//            break;
3109
        case 2:
P
pbrook 已提交
3110
//            gen_helper_mfc0_tracecontrol2(t0); /* PDtrace support */
T
ths 已提交
3111 3112
            rn = "TraceControl2";
//            break;
3113
        case 3:
P
pbrook 已提交
3114
//            gen_helper_mfc0_usertracedata(t0); /* PDtrace support */
T
ths 已提交
3115 3116
            rn = "UserTraceData";
//            break;
3117
        case 4:
P
pbrook 已提交
3118
//            gen_helper_mfc0_tracebpc(t0); /* PDtrace support */
T
ths 已提交
3119 3120
            rn = "TraceBPC";
//            break;
3121 3122 3123
        default:
            goto die;
        }
3124 3125
        break;
    case 24:
3126 3127
        switch (sel) {
        case 0:
T
ths 已提交
3128
            /* EJTAG support */
3129 3130
            tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUState, CP0_DEPC));
            tcg_gen_ext32s_tl(t0, t0);
T
ths 已提交
3131 3132
            rn = "DEPC";
            break;
3133 3134 3135
        default:
            goto die;
        }
3136
        break;
3137
    case 25:
3138 3139
        switch (sel) {
        case 0:
3140
            gen_mfc0_load32(t0, offsetof(CPUState, CP0_Performance0));
T
ths 已提交
3141
            rn = "Performance0";
3142 3143
            break;
        case 1:
P
pbrook 已提交
3144
//            gen_helper_mfc0_performance1(t0);
T
ths 已提交
3145 3146
            rn = "Performance1";
//            break;
3147
        case 2:
P
pbrook 已提交
3148
//            gen_helper_mfc0_performance2(t0);
T
ths 已提交
3149 3150
            rn = "Performance2";
//            break;
3151
        case 3:
P
pbrook 已提交
3152
//            gen_helper_mfc0_performance3(t0);
T
ths 已提交
3153 3154
            rn = "Performance3";
//            break;
3155
        case 4:
P
pbrook 已提交
3156
//            gen_helper_mfc0_performance4(t0);
T
ths 已提交
3157 3158
            rn = "Performance4";
//            break;
3159
        case 5:
P
pbrook 已提交
3160
//            gen_helper_mfc0_performance5(t0);
T
ths 已提交
3161 3162
            rn = "Performance5";
//            break;
3163
        case 6:
P
pbrook 已提交
3164
//            gen_helper_mfc0_performance6(t0);
T
ths 已提交
3165 3166
            rn = "Performance6";
//            break;
3167
        case 7:
P
pbrook 已提交
3168
//            gen_helper_mfc0_performance7(t0);
T
ths 已提交
3169 3170
            rn = "Performance7";
//            break;
3171 3172 3173
        default:
            goto die;
        }
3174 3175
        break;
    case 26:
3176 3177 3178
        tcg_gen_movi_tl(t0, 0); /* unimplemented */
        rn = "ECC";
        break;
3179
    case 27:
3180 3181
        switch (sel) {
        case 0 ... 3:
3182
            tcg_gen_movi_tl(t0, 0); /* unimplemented */
T
ths 已提交
3183 3184
            rn = "CacheErr";
            break;
3185 3186 3187
        default:
            goto die;
        }
3188
        break;
3189 3190 3191
    case 28:
        switch (sel) {
        case 0:
3192 3193 3194
        case 2:
        case 4:
        case 6:
3195
            gen_mfc0_load32(t0, offsetof(CPUState, CP0_TagLo));
3196 3197 3198
            rn = "TagLo";
            break;
        case 1:
3199 3200 3201
        case 3:
        case 5:
        case 7:
3202
            gen_mfc0_load32(t0, offsetof(CPUState, CP0_DataLo));
3203 3204 3205 3206 3207 3208
            rn = "DataLo";
            break;
        default:
            goto die;
        }
        break;
3209
    case 29:
3210 3211 3212 3213 3214
        switch (sel) {
        case 0:
        case 2:
        case 4:
        case 6:
3215
            gen_mfc0_load32(t0, offsetof(CPUState, CP0_TagHi));
3216 3217 3218 3219 3220 3221
            rn = "TagHi";
            break;
        case 1:
        case 3:
        case 5:
        case 7:
3222
            gen_mfc0_load32(t0, offsetof(CPUState, CP0_DataHi));
3223 3224 3225 3226 3227
            rn = "DataHi";
            break;
        default:
            goto die;
        }
3228
        break;
3229
    case 30:
3230 3231
        switch (sel) {
        case 0:
3232 3233
            tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUState, CP0_ErrorEPC));
            tcg_gen_ext32s_tl(t0, t0);
T
ths 已提交
3234 3235
            rn = "ErrorEPC";
            break;
3236 3237 3238
        default:
            goto die;
        }
3239 3240
        break;
    case 31:
3241 3242
        switch (sel) {
        case 0:
T
ths 已提交
3243
            /* EJTAG support */
3244
            gen_mfc0_load32(t0, offsetof(CPUState, CP0_DESAVE));
T
ths 已提交
3245 3246
            rn = "DESAVE";
            break;
3247 3248 3249
        default:
            goto die;
        }
3250 3251 3252 3253
        break;
    default:
       goto die;
    }
3254
    LOG_DISAS("mfc0 %s (reg %d sel %d)\n", rn, reg, sel);
3255 3256 3257
    return;

die:
3258
    LOG_DISAS("mfc0 %s (reg %d sel %d)\n", rn, reg, sel);
3259 3260 3261
    generate_exception(ctx, EXCP_RI);
}

3262
static void gen_mtc0 (CPUState *env, DisasContext *ctx, TCGv t0, int reg, int sel)
3263
{
3264 3265
    const char *rn = "invalid";

3266 3267 3268
    if (sel != 0)
        check_insn(env, ctx, ISA_MIPS32);

P
pbrook 已提交
3269 3270 3271
    if (use_icount)
        gen_io_start();

3272 3273
    switch (reg) {
    case 0:
3274 3275
        switch (sel) {
        case 0:
P
pbrook 已提交
3276
            gen_helper_mtc0_index(t0);
3277 3278 3279
            rn = "Index";
            break;
        case 1:
3280
            check_insn(env, ctx, ASE_MT);
P
pbrook 已提交
3281
            gen_helper_mtc0_mvpcontrol(t0);
3282
            rn = "MVPControl";
3283
            break;
3284
        case 2:
3285
            check_insn(env, ctx, ASE_MT);
3286
            /* ignored */
3287
            rn = "MVPConf0";
3288
            break;
3289
        case 3:
3290
            check_insn(env, ctx, ASE_MT);
3291
            /* ignored */
3292
            rn = "MVPConf1";
3293
            break;
3294 3295 3296
        default:
            goto die;
        }
3297 3298
        break;
    case 1:
3299 3300
        switch (sel) {
        case 0:
T
ths 已提交
3301
            /* ignored */
3302
            rn = "Random";
T
ths 已提交
3303
            break;
3304
        case 1:
3305
            check_insn(env, ctx, ASE_MT);
P
pbrook 已提交
3306
            gen_helper_mtc0_vpecontrol(t0);
3307
            rn = "VPEControl";
3308
            break;
3309
        case 2:
3310
            check_insn(env, ctx, ASE_MT);
P
pbrook 已提交
3311
            gen_helper_mtc0_vpeconf0(t0);
3312
            rn = "VPEConf0";
3313
            break;
3314
        case 3:
3315
            check_insn(env, ctx, ASE_MT);
P
pbrook 已提交
3316
            gen_helper_mtc0_vpeconf1(t0);
3317
            rn = "VPEConf1";
3318
            break;
3319
        case 4:
3320
            check_insn(env, ctx, ASE_MT);
P
pbrook 已提交
3321
            gen_helper_mtc0_yqmask(t0);
3322
            rn = "YQMask";
3323
            break;
3324
        case 5:
3325
            check_insn(env, ctx, ASE_MT);
3326
            gen_mtc0_store64(t0, offsetof(CPUState, CP0_VPESchedule));
3327
            rn = "VPESchedule";
3328
            break;
3329
        case 6:
3330
            check_insn(env, ctx, ASE_MT);
3331
            gen_mtc0_store64(t0, offsetof(CPUState, CP0_VPEScheFBack));
3332
            rn = "VPEScheFBack";
3333
            break;
3334
        case 7:
3335
            check_insn(env, ctx, ASE_MT);
P
pbrook 已提交
3336
            gen_helper_mtc0_vpeopt(t0);
3337
            rn = "VPEOpt";
3338
            break;
3339 3340 3341
        default:
            goto die;
        }
3342 3343
        break;
    case 2:
3344 3345
        switch (sel) {
        case 0:
P
pbrook 已提交
3346
            gen_helper_mtc0_entrylo0(t0);
T
ths 已提交
3347 3348
            rn = "EntryLo0";
            break;
3349
        case 1:
3350
            check_insn(env, ctx, ASE_MT);
P
pbrook 已提交
3351
            gen_helper_mtc0_tcstatus(t0);
T
ths 已提交
3352
            rn = "TCStatus";
3353
            break;
3354
        case 2:
3355
            check_insn(env, ctx, ASE_MT);
P
pbrook 已提交
3356
            gen_helper_mtc0_tcbind(t0);
T
ths 已提交
3357
            rn = "TCBind";
3358
            break;
3359
        case 3:
3360
            check_insn(env, ctx, ASE_MT);
P
pbrook 已提交
3361
            gen_helper_mtc0_tcrestart(t0);
T
ths 已提交
3362
            rn = "TCRestart";
3363
            break;
3364
        case 4:
3365
            check_insn(env, ctx, ASE_MT);
P
pbrook 已提交
3366
            gen_helper_mtc0_tchalt(t0);
T
ths 已提交
3367
            rn = "TCHalt";
3368
            break;
3369
        case 5:
3370
            check_insn(env, ctx, ASE_MT);
P
pbrook 已提交
3371
            gen_helper_mtc0_tccontext(t0);
T
ths 已提交
3372
            rn = "TCContext";
3373
            break;
3374
        case 6:
3375
            check_insn(env, ctx, ASE_MT);
P
pbrook 已提交
3376
            gen_helper_mtc0_tcschedule(t0);
T
ths 已提交
3377
            rn = "TCSchedule";
3378
            break;
3379
        case 7:
3380
            check_insn(env, ctx, ASE_MT);
P
pbrook 已提交
3381
            gen_helper_mtc0_tcschefback(t0);
T
ths 已提交
3382
            rn = "TCScheFBack";
3383
            break;
3384 3385 3386
        default:
            goto die;
        }
3387 3388
        break;
    case 3:
3389 3390
        switch (sel) {
        case 0:
P
pbrook 已提交
3391
            gen_helper_mtc0_entrylo1(t0);
T
ths 已提交
3392 3393
            rn = "EntryLo1";
            break;
3394 3395
        default:
            goto die;
T
ths 已提交
3396
        }
3397 3398
        break;
    case 4:
3399 3400
        switch (sel) {
        case 0:
P
pbrook 已提交
3401
            gen_helper_mtc0_context(t0);
T
ths 已提交
3402 3403
            rn = "Context";
            break;
3404
        case 1:
P
pbrook 已提交
3405
//            gen_helper_mtc0_contextconfig(t0); /* SmartMIPS ASE */
T
ths 已提交
3406 3407
            rn = "ContextConfig";
//            break;
3408 3409
        default:
            goto die;
T
ths 已提交
3410
        }
3411 3412
        break;
    case 5:
3413 3414
        switch (sel) {
        case 0:
P
pbrook 已提交
3415
            gen_helper_mtc0_pagemask(t0);
T
ths 已提交
3416 3417
            rn = "PageMask";
            break;
3418
        case 1:
3419
            check_insn(env, ctx, ISA_MIPS32R2);
P
pbrook 已提交
3420
            gen_helper_mtc0_pagegrain(t0);
T
ths 已提交
3421 3422
            rn = "PageGrain";
            break;
3423 3424
        default:
            goto die;
T
ths 已提交
3425
        }
3426 3427
        break;
    case 6:
3428 3429
        switch (sel) {
        case 0:
P
pbrook 已提交
3430
            gen_helper_mtc0_wired(t0);
T
ths 已提交
3431 3432
            rn = "Wired";
            break;
3433
        case 1:
3434
            check_insn(env, ctx, ISA_MIPS32R2);
P
pbrook 已提交
3435
            gen_helper_mtc0_srsconf0(t0);
T
ths 已提交
3436
            rn = "SRSConf0";
3437
            break;
3438
        case 2:
3439
            check_insn(env, ctx, ISA_MIPS32R2);
P
pbrook 已提交
3440
            gen_helper_mtc0_srsconf1(t0);
T
ths 已提交
3441
            rn = "SRSConf1";
3442
            break;
3443
        case 3:
3444
            check_insn(env, ctx, ISA_MIPS32R2);
P
pbrook 已提交
3445
            gen_helper_mtc0_srsconf2(t0);
T
ths 已提交
3446
            rn = "SRSConf2";
3447
            break;
3448
        case 4:
3449
            check_insn(env, ctx, ISA_MIPS32R2);
P
pbrook 已提交
3450
            gen_helper_mtc0_srsconf3(t0);
T
ths 已提交
3451
            rn = "SRSConf3";
3452
            break;
3453
        case 5:
3454
            check_insn(env, ctx, ISA_MIPS32R2);
P
pbrook 已提交
3455
            gen_helper_mtc0_srsconf4(t0);
T
ths 已提交
3456
            rn = "SRSConf4";
3457
            break;
3458 3459
        default:
            goto die;
T
ths 已提交
3460
        }
3461 3462
        break;
    case 7:
3463 3464
        switch (sel) {
        case 0:
3465
            check_insn(env, ctx, ISA_MIPS32R2);
P
pbrook 已提交
3466
            gen_helper_mtc0_hwrena(t0);
T
ths 已提交
3467 3468
            rn = "HWREna";
            break;
3469 3470
        default:
            goto die;
T
ths 已提交
3471
        }
3472 3473
        break;
    case 8:
3474
        /* ignored */
T
ths 已提交
3475
        rn = "BadVAddr";
3476 3477
        break;
    case 9:
3478 3479
        switch (sel) {
        case 0:
P
pbrook 已提交
3480
            gen_helper_mtc0_count(t0);
T
ths 已提交
3481 3482
            rn = "Count";
            break;
T
ths 已提交
3483
        /* 6,7 are implementation dependent */
3484 3485
        default:
            goto die;
T
ths 已提交
3486 3487 3488
        }
        /* Stop translation as we may have switched the execution mode */
        ctx->bstate = BS_STOP;
3489 3490
        break;
    case 10:
3491 3492
        switch (sel) {
        case 0:
P
pbrook 已提交
3493
            gen_helper_mtc0_entryhi(t0);
T
ths 已提交
3494 3495
            rn = "EntryHi";
            break;
3496 3497
        default:
            goto die;
T
ths 已提交
3498
        }
3499 3500
        break;
    case 11:
3501 3502
        switch (sel) {
        case 0:
P
pbrook 已提交
3503
            gen_helper_mtc0_compare(t0);
T
ths 已提交
3504 3505 3506
            rn = "Compare";
            break;
        /* 6,7 are implementation dependent */
3507 3508
        default:
            goto die;
T
ths 已提交
3509
        }
3510 3511
        /* Stop translation as we may have switched the execution mode */
        ctx->bstate = BS_STOP;
3512 3513
        break;
    case 12:
3514 3515
        switch (sel) {
        case 0:
P
pbrook 已提交
3516
            gen_helper_mtc0_status(t0);
3517 3518 3519
            /* BS_STOP isn't good enough here, hflags may have changed. */
            gen_save_pc(ctx->pc + 4);
            ctx->bstate = BS_EXCP;
T
ths 已提交
3520 3521
            rn = "Status";
            break;
3522
        case 1:
3523
            check_insn(env, ctx, ISA_MIPS32R2);
P
pbrook 已提交
3524
            gen_helper_mtc0_intctl(t0);
3525 3526
            /* Stop translation as we may have switched the execution mode */
            ctx->bstate = BS_STOP;
T
ths 已提交
3527 3528
            rn = "IntCtl";
            break;
3529
        case 2:
3530
            check_insn(env, ctx, ISA_MIPS32R2);
P
pbrook 已提交
3531
            gen_helper_mtc0_srsctl(t0);
3532 3533
            /* Stop translation as we may have switched the execution mode */
            ctx->bstate = BS_STOP;
T
ths 已提交
3534 3535
            rn = "SRSCtl";
            break;
3536
        case 3:
3537
            check_insn(env, ctx, ISA_MIPS32R2);
3538
            gen_mtc0_store32(t0, offsetof(CPUState, CP0_SRSMap));
3539 3540
            /* Stop translation as we may have switched the execution mode */
            ctx->bstate = BS_STOP;
T
ths 已提交
3541
            rn = "SRSMap";
3542
            break;
3543 3544
        default:
            goto die;
T
ths 已提交
3545
        }
3546 3547
        break;
    case 13:
3548 3549
        switch (sel) {
        case 0:
P
pbrook 已提交
3550
            gen_helper_mtc0_cause(t0);
T
ths 已提交
3551 3552
            rn = "Cause";
            break;
3553 3554
        default:
            goto die;
T
ths 已提交
3555 3556 3557
        }
        /* Stop translation as we may have switched the execution mode */
        ctx->bstate = BS_STOP;
3558 3559
        break;
    case 14:
3560 3561
        switch (sel) {
        case 0:
3562
            gen_mtc0_store64(t0, offsetof(CPUState, CP0_EPC));
T
ths 已提交
3563 3564
            rn = "EPC";
            break;
3565 3566
        default:
            goto die;
T
ths 已提交
3567
        }
3568 3569
        break;
    case 15:
3570 3571
        switch (sel) {
        case 0:
T
ths 已提交
3572 3573 3574
            /* ignored */
            rn = "PRid";
            break;
3575
        case 1:
3576
            check_insn(env, ctx, ISA_MIPS32R2);
P
pbrook 已提交
3577
            gen_helper_mtc0_ebase(t0);
T
ths 已提交
3578 3579
            rn = "EBase";
            break;
3580 3581
        default:
            goto die;
3582
        }
3583 3584 3585 3586
        break;
    case 16:
        switch (sel) {
        case 0:
P
pbrook 已提交
3587
            gen_helper_mtc0_config0(t0);
3588
            rn = "Config";
T
ths 已提交
3589 3590
            /* Stop translation as we may have switched the execution mode */
            ctx->bstate = BS_STOP;
3591 3592
            break;
        case 1:
3593
            /* ignored, read only */
3594 3595 3596
            rn = "Config1";
            break;
        case 2:
P
pbrook 已提交
3597
            gen_helper_mtc0_config2(t0);
3598
            rn = "Config2";
T
ths 已提交
3599 3600
            /* Stop translation as we may have switched the execution mode */
            ctx->bstate = BS_STOP;
3601
            break;
3602
        case 3:
3603
            /* ignored, read only */
3604 3605
            rn = "Config3";
            break;
3606 3607 3608 3609 3610 3611 3612 3613 3614 3615
        /* 4,5 are reserved */
        /* 6,7 are implementation dependent */
        case 6:
            /* ignored */
            rn = "Config6";
            break;
        case 7:
            /* ignored */
            rn = "Config7";
            break;
3616 3617 3618 3619 3620 3621
        default:
            rn = "Invalid config selector";
            goto die;
        }
        break;
    case 17:
3622 3623
        switch (sel) {
        case 0:
T
ths 已提交
3624 3625 3626
            /* ignored */
            rn = "LLAddr";
            break;
3627 3628 3629
        default:
            goto die;
        }
3630 3631
        break;
    case 18:
3632
        switch (sel) {
3633
        case 0 ... 7:
P
pbrook 已提交
3634
            gen_helper_1i(mtc0_watchlo, t0, sel);
T
ths 已提交
3635 3636
            rn = "WatchLo";
            break;
3637 3638 3639
        default:
            goto die;
        }
3640 3641
        break;
    case 19:
3642
        switch (sel) {
3643
        case 0 ... 7:
P
pbrook 已提交
3644
            gen_helper_1i(mtc0_watchhi, t0, sel);
T
ths 已提交
3645 3646
            rn = "WatchHi";
            break;
3647 3648 3649
        default:
            goto die;
        }
3650 3651
        break;
    case 20:
3652 3653
        switch (sel) {
        case 0:
3654
#if defined(TARGET_MIPS64)
3655
            check_insn(env, ctx, ISA_MIPS3);
P
pbrook 已提交
3656
            gen_helper_mtc0_xcontext(t0);
T
ths 已提交
3657 3658
            rn = "XContext";
            break;
T
ths 已提交
3659
#endif
3660 3661 3662
        default:
            goto die;
        }
3663 3664
        break;
    case 21:
3665 3666 3667
       /* Officially reserved, but sel 0 is used for R1x000 framemask */
        switch (sel) {
        case 0:
P
pbrook 已提交
3668
            gen_helper_mtc0_framemask(t0);
T
ths 已提交
3669 3670
            rn = "Framemask";
            break;
3671 3672 3673 3674
        default:
            goto die;
        }
        break;
3675
    case 22:
3676 3677
        /* ignored */
        rn = "Diagnostic"; /* implementation dependent */
T
ths 已提交
3678
        break;
3679
    case 23:
3680 3681
        switch (sel) {
        case 0:
P
pbrook 已提交
3682
            gen_helper_mtc0_debug(t0); /* EJTAG support */
3683 3684 3685
            /* BS_STOP isn't good enough here, hflags may have changed. */
            gen_save_pc(ctx->pc + 4);
            ctx->bstate = BS_EXCP;
T
ths 已提交
3686 3687
            rn = "Debug";
            break;
3688
        case 1:
P
pbrook 已提交
3689
//            gen_helper_mtc0_tracecontrol(t0); /* PDtrace support */
T
ths 已提交
3690
            rn = "TraceControl";
3691 3692
            /* Stop translation as we may have switched the execution mode */
            ctx->bstate = BS_STOP;
T
ths 已提交
3693
//            break;
3694
        case 2:
P
pbrook 已提交
3695
//            gen_helper_mtc0_tracecontrol2(t0); /* PDtrace support */
T
ths 已提交
3696
            rn = "TraceControl2";
3697 3698
            /* Stop translation as we may have switched the execution mode */
            ctx->bstate = BS_STOP;
T
ths 已提交
3699
//            break;
3700
        case 3:
3701 3702
            /* Stop translation as we may have switched the execution mode */
            ctx->bstate = BS_STOP;
P
pbrook 已提交
3703
//            gen_helper_mtc0_usertracedata(t0); /* PDtrace support */
T
ths 已提交
3704
            rn = "UserTraceData";
3705 3706
            /* Stop translation as we may have switched the execution mode */
            ctx->bstate = BS_STOP;
T
ths 已提交
3707
//            break;
3708
        case 4:
P
pbrook 已提交
3709
//            gen_helper_mtc0_tracebpc(t0); /* PDtrace support */
3710 3711
            /* Stop translation as we may have switched the execution mode */
            ctx->bstate = BS_STOP;
T
ths 已提交
3712 3713
            rn = "TraceBPC";
//            break;
3714 3715 3716
        default:
            goto die;
        }
3717 3718
        break;
    case 24:
3719 3720
        switch (sel) {
        case 0:
3721
            /* EJTAG support */
3722
            gen_mtc0_store64(t0, offsetof(CPUState, CP0_DEPC));
T
ths 已提交
3723 3724
            rn = "DEPC";
            break;
3725 3726 3727
        default:
            goto die;
        }
3728 3729
        break;
    case 25:
3730 3731
        switch (sel) {
        case 0:
P
pbrook 已提交
3732
            gen_helper_mtc0_performance0(t0);
T
ths 已提交
3733 3734
            rn = "Performance0";
            break;
3735
        case 1:
P
pbrook 已提交
3736
//            gen_helper_mtc0_performance1(t0);
T
ths 已提交
3737 3738
            rn = "Performance1";
//            break;
3739
        case 2:
P
pbrook 已提交
3740
//            gen_helper_mtc0_performance2(t0);
T
ths 已提交
3741 3742
            rn = "Performance2";
//            break;
3743
        case 3:
P
pbrook 已提交
3744
//            gen_helper_mtc0_performance3(t0);
T
ths 已提交
3745 3746
            rn = "Performance3";
//            break;
3747
        case 4:
P
pbrook 已提交
3748
//            gen_helper_mtc0_performance4(t0);
T
ths 已提交
3749 3750
            rn = "Performance4";
//            break;
3751
        case 5:
P
pbrook 已提交
3752
//            gen_helper_mtc0_performance5(t0);
T
ths 已提交
3753 3754
            rn = "Performance5";
//            break;
3755
        case 6:
P
pbrook 已提交
3756
//            gen_helper_mtc0_performance6(t0);
T
ths 已提交
3757 3758
            rn = "Performance6";
//            break;
3759
        case 7:
P
pbrook 已提交
3760
//            gen_helper_mtc0_performance7(t0);
T
ths 已提交
3761 3762
            rn = "Performance7";
//            break;
3763 3764 3765
        default:
            goto die;
        }
3766 3767
       break;
    case 26:
T
ths 已提交
3768
        /* ignored */
3769
        rn = "ECC";
T
ths 已提交
3770
        break;
3771
    case 27:
3772 3773
        switch (sel) {
        case 0 ... 3:
T
ths 已提交
3774 3775 3776
            /* ignored */
            rn = "CacheErr";
            break;
3777 3778 3779
        default:
            goto die;
        }
3780 3781 3782 3783
       break;
    case 28:
        switch (sel) {
        case 0:
3784 3785 3786
        case 2:
        case 4:
        case 6:
P
pbrook 已提交
3787
            gen_helper_mtc0_taglo(t0);
3788 3789
            rn = "TagLo";
            break;
3790 3791 3792 3793
        case 1:
        case 3:
        case 5:
        case 7:
P
pbrook 已提交
3794
            gen_helper_mtc0_datalo(t0);
3795 3796
            rn = "DataLo";
            break;
3797 3798 3799 3800 3801
        default:
            goto die;
        }
        break;
    case 29:
3802 3803 3804 3805 3806
        switch (sel) {
        case 0:
        case 2:
        case 4:
        case 6:
P
pbrook 已提交
3807
            gen_helper_mtc0_taghi(t0);
3808 3809 3810 3811 3812 3813
            rn = "TagHi";
            break;
        case 1:
        case 3:
        case 5:
        case 7:
P
pbrook 已提交
3814
            gen_helper_mtc0_datahi(t0);
3815 3816 3817 3818 3819 3820
            rn = "DataHi";
            break;
        default:
            rn = "invalid sel";
            goto die;
        }
3821 3822
       break;
    case 30:
3823 3824
        switch (sel) {
        case 0:
3825
            gen_mtc0_store64(t0, offsetof(CPUState, CP0_ErrorEPC));
T
ths 已提交
3826 3827
            rn = "ErrorEPC";
            break;
3828 3829 3830
        default:
            goto die;
        }
3831 3832
        break;
    case 31:
3833 3834
        switch (sel) {
        case 0:
3835
            /* EJTAG support */
3836
            gen_mtc0_store32(t0, offsetof(CPUState, CP0_DESAVE));
T
ths 已提交
3837 3838
            rn = "DESAVE";
            break;
3839 3840 3841
        default:
            goto die;
        }
T
ths 已提交
3842 3843
        /* Stop translation as we may have switched the execution mode */
        ctx->bstate = BS_STOP;
3844 3845 3846 3847
        break;
    default:
       goto die;
    }
3848
    LOG_DISAS("mtc0 %s (reg %d sel %d)\n", rn, reg, sel);
T
ths 已提交
3849
    /* For simplicity assume that all writes can cause interrupts.  */
P
pbrook 已提交
3850 3851 3852 3853
    if (use_icount) {
        gen_io_end();
        ctx->bstate = BS_STOP;
    }
3854 3855 3856
    return;

die:
3857
    LOG_DISAS("mtc0 %s (reg %d sel %d)\n", rn, reg, sel);
3858 3859 3860
    generate_exception(ctx, EXCP_RI);
}

3861
#if defined(TARGET_MIPS64)
3862
static void gen_dmfc0 (CPUState *env, DisasContext *ctx, TCGv t0, int reg, int sel)
T
ths 已提交
3863 3864 3865
{
    const char *rn = "invalid";

3866 3867 3868
    if (sel != 0)
        check_insn(env, ctx, ISA_MIPS64);

T
ths 已提交
3869 3870 3871 3872
    switch (reg) {
    case 0:
        switch (sel) {
        case 0:
3873
            gen_mfc0_load32(t0, offsetof(CPUState, CP0_Index));
T
ths 已提交
3874 3875 3876
            rn = "Index";
            break;
        case 1:
3877
            check_insn(env, ctx, ASE_MT);
P
pbrook 已提交
3878
            gen_helper_mfc0_mvpcontrol(t0);
T
ths 已提交
3879
            rn = "MVPControl";
3880
            break;
T
ths 已提交
3881
        case 2:
3882
            check_insn(env, ctx, ASE_MT);
P
pbrook 已提交
3883
            gen_helper_mfc0_mvpconf0(t0);
T
ths 已提交
3884
            rn = "MVPConf0";
3885
            break;
T
ths 已提交
3886
        case 3:
3887
            check_insn(env, ctx, ASE_MT);
P
pbrook 已提交
3888
            gen_helper_mfc0_mvpconf1(t0);
T
ths 已提交
3889
            rn = "MVPConf1";
3890
            break;
T
ths 已提交
3891 3892 3893 3894 3895 3896 3897
        default:
            goto die;
        }
        break;
    case 1:
        switch (sel) {
        case 0:
P
pbrook 已提交
3898
            gen_helper_mfc0_random(t0);
T
ths 已提交
3899
            rn = "Random";
T
ths 已提交
3900
            break;
T
ths 已提交
3901
        case 1:
3902
            check_insn(env, ctx, ASE_MT);
3903
            gen_mfc0_load32(t0, offsetof(CPUState, CP0_VPEControl));
T
ths 已提交
3904
            rn = "VPEControl";
3905
            break;
T
ths 已提交
3906
        case 2:
3907
            check_insn(env, ctx, ASE_MT);
3908
            gen_mfc0_load32(t0, offsetof(CPUState, CP0_VPEConf0));
T
ths 已提交
3909
            rn = "VPEConf0";
3910
            break;
T
ths 已提交
3911
        case 3:
3912
            check_insn(env, ctx, ASE_MT);
3913
            gen_mfc0_load32(t0, offsetof(CPUState, CP0_VPEConf1));
T
ths 已提交
3914
            rn = "VPEConf1";
3915
            break;
T
ths 已提交
3916
        case 4:
3917
            check_insn(env, ctx, ASE_MT);
3918
            tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUState, CP0_YQMask));
T
ths 已提交
3919
            rn = "YQMask";
3920
            break;
T
ths 已提交
3921
        case 5:
3922
            check_insn(env, ctx, ASE_MT);
3923
            tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUState, CP0_VPESchedule));
T
ths 已提交
3924
            rn = "VPESchedule";
3925
            break;
T
ths 已提交
3926
        case 6:
3927
            check_insn(env, ctx, ASE_MT);
3928
            tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUState, CP0_VPEScheFBack));
T
ths 已提交
3929
            rn = "VPEScheFBack";
3930
            break;
T
ths 已提交
3931
        case 7:
3932
            check_insn(env, ctx, ASE_MT);
3933
            gen_mfc0_load32(t0, offsetof(CPUState, CP0_VPEOpt));
T
ths 已提交
3934
            rn = "VPEOpt";
3935
            break;
T
ths 已提交
3936 3937 3938 3939 3940 3941 3942
        default:
            goto die;
        }
        break;
    case 2:
        switch (sel) {
        case 0:
3943
            tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUState, CP0_EntryLo0));
T
ths 已提交
3944 3945
            rn = "EntryLo0";
            break;
T
ths 已提交
3946
        case 1:
3947
            check_insn(env, ctx, ASE_MT);
P
pbrook 已提交
3948
            gen_helper_mfc0_tcstatus(t0);
T
ths 已提交
3949
            rn = "TCStatus";
3950
            break;
T
ths 已提交
3951
        case 2:
3952
            check_insn(env, ctx, ASE_MT);
P
pbrook 已提交
3953
            gen_helper_mfc0_tcbind(t0);
T
ths 已提交
3954
            rn = "TCBind";
3955
            break;
T
ths 已提交
3956
        case 3:
3957
            check_insn(env, ctx, ASE_MT);
P
pbrook 已提交
3958
            gen_helper_dmfc0_tcrestart(t0);
T
ths 已提交
3959
            rn = "TCRestart";
3960
            break;
T
ths 已提交
3961
        case 4:
3962
            check_insn(env, ctx, ASE_MT);
P
pbrook 已提交
3963
            gen_helper_dmfc0_tchalt(t0);
T
ths 已提交
3964
            rn = "TCHalt";
3965
            break;
T
ths 已提交
3966
        case 5:
3967
            check_insn(env, ctx, ASE_MT);
P
pbrook 已提交
3968
            gen_helper_dmfc0_tccontext(t0);
T
ths 已提交
3969
            rn = "TCContext";
3970
            break;
T
ths 已提交
3971
        case 6:
3972
            check_insn(env, ctx, ASE_MT);
P
pbrook 已提交
3973
            gen_helper_dmfc0_tcschedule(t0);
T
ths 已提交
3974
            rn = "TCSchedule";
3975
            break;
T
ths 已提交
3976
        case 7:
3977
            check_insn(env, ctx, ASE_MT);
P
pbrook 已提交
3978
            gen_helper_dmfc0_tcschefback(t0);
T
ths 已提交
3979
            rn = "TCScheFBack";
3980
            break;
T
ths 已提交
3981 3982 3983 3984 3985 3986 3987
        default:
            goto die;
        }
        break;
    case 3:
        switch (sel) {
        case 0:
3988
            tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUState, CP0_EntryLo1));
T
ths 已提交
3989 3990
            rn = "EntryLo1";
            break;
T
ths 已提交
3991 3992
        default:
            goto die;
3993
        }
T
ths 已提交
3994 3995 3996 3997
        break;
    case 4:
        switch (sel) {
        case 0:
3998
            tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUState, CP0_Context));
T
ths 已提交
3999 4000
            rn = "Context";
            break;
T
ths 已提交
4001
        case 1:
P
pbrook 已提交
4002
//            gen_helper_dmfc0_contextconfig(t0); /* SmartMIPS ASE */
T
ths 已提交
4003 4004
            rn = "ContextConfig";
//            break;
T
ths 已提交
4005 4006
        default:
            goto die;
T
ths 已提交
4007
        }
T
ths 已提交
4008 4009 4010 4011
        break;
    case 5:
        switch (sel) {
        case 0:
4012
            gen_mfc0_load32(t0, offsetof(CPUState, CP0_PageMask));
T
ths 已提交
4013 4014
            rn = "PageMask";
            break;
T
ths 已提交
4015
        case 1:
4016
            check_insn(env, ctx, ISA_MIPS32R2);
4017
            gen_mfc0_load32(t0, offsetof(CPUState, CP0_PageGrain));
T
ths 已提交
4018 4019
            rn = "PageGrain";
            break;
T
ths 已提交
4020 4021
        default:
            goto die;
T
ths 已提交
4022
        }
T
ths 已提交
4023 4024 4025 4026
        break;
    case 6:
        switch (sel) {
        case 0:
4027
            gen_mfc0_load32(t0, offsetof(CPUState, CP0_Wired));
T
ths 已提交
4028 4029
            rn = "Wired";
            break;
T
ths 已提交
4030
        case 1:
4031
            check_insn(env, ctx, ISA_MIPS32R2);
4032
            gen_mfc0_load32(t0, offsetof(CPUState, CP0_SRSConf0));
T
ths 已提交
4033
            rn = "SRSConf0";
4034
            break;
T
ths 已提交
4035
        case 2:
4036
            check_insn(env, ctx, ISA_MIPS32R2);
4037
            gen_mfc0_load32(t0, offsetof(CPUState, CP0_SRSConf1));
T
ths 已提交
4038
            rn = "SRSConf1";
4039
            break;
T
ths 已提交
4040
        case 3:
4041
            check_insn(env, ctx, ISA_MIPS32R2);
4042
            gen_mfc0_load32(t0, offsetof(CPUState, CP0_SRSConf2));
T
ths 已提交
4043
            rn = "SRSConf2";
4044
            break;
T
ths 已提交
4045
        case 4:
4046
            check_insn(env, ctx, ISA_MIPS32R2);
4047
            gen_mfc0_load32(t0, offsetof(CPUState, CP0_SRSConf3));
T
ths 已提交
4048
            rn = "SRSConf3";
4049
            break;
T
ths 已提交
4050
        case 5:
4051
            check_insn(env, ctx, ISA_MIPS32R2);
4052
            gen_mfc0_load32(t0, offsetof(CPUState, CP0_SRSConf4));
T
ths 已提交
4053
            rn = "SRSConf4";
4054
            break;
T
ths 已提交
4055 4056
        default:
            goto die;
T
ths 已提交
4057
        }
T
ths 已提交
4058 4059 4060 4061
        break;
    case 7:
        switch (sel) {
        case 0:
4062
            check_insn(env, ctx, ISA_MIPS32R2);
4063
            gen_mfc0_load32(t0, offsetof(CPUState, CP0_HWREna));
T
ths 已提交
4064 4065
            rn = "HWREna";
            break;
T
ths 已提交
4066 4067
        default:
            goto die;
T
ths 已提交
4068
        }
T
ths 已提交
4069 4070 4071 4072
        break;
    case 8:
        switch (sel) {
        case 0:
4073
            tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUState, CP0_BadVAddr));
T
ths 已提交
4074
            rn = "BadVAddr";
T
ths 已提交
4075
            break;
T
ths 已提交
4076 4077
        default:
            goto die;
T
ths 已提交
4078
        }
T
ths 已提交
4079 4080 4081 4082
        break;
    case 9:
        switch (sel) {
        case 0:
P
pbrook 已提交
4083 4084 4085
            /* Mark as an IO operation because we read the time.  */
            if (use_icount)
                gen_io_start();
P
pbrook 已提交
4086
            gen_helper_mfc0_count(t0);
P
pbrook 已提交
4087 4088 4089 4090
            if (use_icount) {
                gen_io_end();
                ctx->bstate = BS_STOP;
            }
T
ths 已提交
4091 4092 4093
            rn = "Count";
            break;
        /* 6,7 are implementation dependent */
T
ths 已提交
4094 4095
        default:
            goto die;
T
ths 已提交
4096
        }
T
ths 已提交
4097 4098 4099 4100
        break;
    case 10:
        switch (sel) {
        case 0:
4101
            tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUState, CP0_EntryHi));
T
ths 已提交
4102 4103
            rn = "EntryHi";
            break;
T
ths 已提交
4104 4105
        default:
            goto die;
T
ths 已提交
4106
        }
T
ths 已提交
4107 4108 4109 4110
        break;
    case 11:
        switch (sel) {
        case 0:
4111
            gen_mfc0_load32(t0, offsetof(CPUState, CP0_Compare));
T
ths 已提交
4112 4113
            rn = "Compare";
            break;
T
ths 已提交
4114
        /* 6,7 are implementation dependent */
T
ths 已提交
4115 4116
        default:
            goto die;
T
ths 已提交
4117
        }
T
ths 已提交
4118 4119 4120 4121
        break;
    case 12:
        switch (sel) {
        case 0:
4122
            gen_mfc0_load32(t0, offsetof(CPUState, CP0_Status));
T
ths 已提交
4123 4124
            rn = "Status";
            break;
T
ths 已提交
4125
        case 1:
4126
            check_insn(env, ctx, ISA_MIPS32R2);
4127
            gen_mfc0_load32(t0, offsetof(CPUState, CP0_IntCtl));
T
ths 已提交
4128 4129
            rn = "IntCtl";
            break;
T
ths 已提交
4130
        case 2:
4131
            check_insn(env, ctx, ISA_MIPS32R2);
4132
            gen_mfc0_load32(t0, offsetof(CPUState, CP0_SRSCtl));
T
ths 已提交
4133 4134
            rn = "SRSCtl";
            break;
T
ths 已提交
4135
        case 3:
4136
            check_insn(env, ctx, ISA_MIPS32R2);
4137
            gen_mfc0_load32(t0, offsetof(CPUState, CP0_SRSMap));
T
ths 已提交
4138 4139
            rn = "SRSMap";
            break;
T
ths 已提交
4140 4141
        default:
            goto die;
T
ths 已提交
4142
        }
T
ths 已提交
4143 4144 4145 4146
        break;
    case 13:
        switch (sel) {
        case 0:
4147
            gen_mfc0_load32(t0, offsetof(CPUState, CP0_Cause));
T
ths 已提交
4148 4149
            rn = "Cause";
            break;
T
ths 已提交
4150 4151
        default:
            goto die;
T
ths 已提交
4152
        }
T
ths 已提交
4153 4154 4155 4156
        break;
    case 14:
        switch (sel) {
        case 0:
4157
            tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUState, CP0_EPC));
T
ths 已提交
4158 4159
            rn = "EPC";
            break;
T
ths 已提交
4160 4161
        default:
            goto die;
T
ths 已提交
4162
        }
T
ths 已提交
4163 4164 4165 4166
        break;
    case 15:
        switch (sel) {
        case 0:
4167
            gen_mfc0_load32(t0, offsetof(CPUState, CP0_PRid));
T
ths 已提交
4168 4169
            rn = "PRid";
            break;
T
ths 已提交
4170
        case 1:
4171
            check_insn(env, ctx, ISA_MIPS32R2);
4172
            gen_mfc0_load32(t0, offsetof(CPUState, CP0_EBase));
T
ths 已提交
4173 4174
            rn = "EBase";
            break;
T
ths 已提交
4175 4176
        default:
            goto die;
T
ths 已提交
4177
        }
T
ths 已提交
4178 4179 4180 4181
        break;
    case 16:
        switch (sel) {
        case 0:
4182
            gen_mfc0_load32(t0, offsetof(CPUState, CP0_Config0));
T
ths 已提交
4183 4184 4185
            rn = "Config";
            break;
        case 1:
4186
            gen_mfc0_load32(t0, offsetof(CPUState, CP0_Config1));
T
ths 已提交
4187 4188 4189
            rn = "Config1";
            break;
        case 2:
4190
            gen_mfc0_load32(t0, offsetof(CPUState, CP0_Config2));
T
ths 已提交
4191 4192 4193
            rn = "Config2";
            break;
        case 3:
4194
            gen_mfc0_load32(t0, offsetof(CPUState, CP0_Config3));
T
ths 已提交
4195 4196 4197
            rn = "Config3";
            break;
       /* 6,7 are implementation dependent */
T
ths 已提交
4198
        case 6:
4199
            gen_mfc0_load32(t0, offsetof(CPUState, CP0_Config6));
T
ths 已提交
4200 4201 4202
            rn = "Config6";
            break;
        case 7:
4203
            gen_mfc0_load32(t0, offsetof(CPUState, CP0_Config7));
T
ths 已提交
4204 4205
            rn = "Config7";
            break;
T
ths 已提交
4206 4207 4208 4209 4210 4211 4212
        default:
            goto die;
        }
        break;
    case 17:
        switch (sel) {
        case 0:
P
pbrook 已提交
4213
            gen_helper_dmfc0_lladdr(t0);
T
ths 已提交
4214 4215
            rn = "LLAddr";
            break;
T
ths 已提交
4216 4217 4218 4219 4220 4221
        default:
            goto die;
        }
        break;
    case 18:
        switch (sel) {
4222
        case 0 ... 7:
P
pbrook 已提交
4223
            gen_helper_1i(dmfc0_watchlo, t0, sel);
T
ths 已提交
4224 4225
            rn = "WatchLo";
            break;
T
ths 已提交
4226 4227 4228 4229 4230 4231
        default:
            goto die;
        }
        break;
    case 19:
        switch (sel) {
4232
        case 0 ... 7:
P
pbrook 已提交
4233
            gen_helper_1i(mfc0_watchhi, t0, sel);
T
ths 已提交
4234 4235
            rn = "WatchHi";
            break;
T
ths 已提交
4236 4237 4238 4239 4240 4241 4242
        default:
            goto die;
        }
        break;
    case 20:
        switch (sel) {
        case 0:
4243
            check_insn(env, ctx, ISA_MIPS3);
4244
            tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUState, CP0_XContext));
T
ths 已提交
4245 4246
            rn = "XContext";
            break;
T
ths 已提交
4247 4248 4249 4250 4251 4252 4253 4254
        default:
            goto die;
        }
        break;
    case 21:
       /* Officially reserved, but sel 0 is used for R1x000 framemask */
        switch (sel) {
        case 0:
4255
            gen_mfc0_load32(t0, offsetof(CPUState, CP0_Framemask));
T
ths 已提交
4256 4257
            rn = "Framemask";
            break;
T
ths 已提交
4258 4259 4260 4261 4262
        default:
            goto die;
        }
        break;
    case 22:
4263
        tcg_gen_movi_tl(t0, 0); /* unimplemented */
T
ths 已提交
4264 4265
        rn = "'Diagnostic"; /* implementation dependent */
        break;
T
ths 已提交
4266 4267 4268
    case 23:
        switch (sel) {
        case 0:
P
pbrook 已提交
4269
            gen_helper_mfc0_debug(t0); /* EJTAG support */
T
ths 已提交
4270 4271
            rn = "Debug";
            break;
T
ths 已提交
4272
        case 1:
P
pbrook 已提交
4273
//            gen_helper_dmfc0_tracecontrol(t0); /* PDtrace support */
T
ths 已提交
4274 4275
            rn = "TraceControl";
//            break;
T
ths 已提交
4276
        case 2:
P
pbrook 已提交
4277
//            gen_helper_dmfc0_tracecontrol2(t0); /* PDtrace support */
T
ths 已提交
4278 4279
            rn = "TraceControl2";
//            break;
T
ths 已提交
4280
        case 3:
P
pbrook 已提交
4281
//            gen_helper_dmfc0_usertracedata(t0); /* PDtrace support */
T
ths 已提交
4282 4283
            rn = "UserTraceData";
//            break;
T
ths 已提交
4284
        case 4:
P
pbrook 已提交
4285
//            gen_helper_dmfc0_tracebpc(t0); /* PDtrace support */
T
ths 已提交
4286 4287
            rn = "TraceBPC";
//            break;
T
ths 已提交
4288 4289 4290 4291 4292 4293 4294
        default:
            goto die;
        }
        break;
    case 24:
        switch (sel) {
        case 0:
T
ths 已提交
4295
            /* EJTAG support */
4296
            tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUState, CP0_DEPC));
T
ths 已提交
4297 4298
            rn = "DEPC";
            break;
T
ths 已提交
4299 4300 4301 4302 4303 4304 4305
        default:
            goto die;
        }
        break;
    case 25:
        switch (sel) {
        case 0:
4306
            gen_mfc0_load32(t0, offsetof(CPUState, CP0_Performance0));
T
ths 已提交
4307
            rn = "Performance0";
T
ths 已提交
4308 4309
            break;
        case 1:
P
pbrook 已提交
4310
//            gen_helper_dmfc0_performance1(t0);
T
ths 已提交
4311 4312
            rn = "Performance1";
//            break;
T
ths 已提交
4313
        case 2:
P
pbrook 已提交
4314
//            gen_helper_dmfc0_performance2(t0);
T
ths 已提交
4315 4316
            rn = "Performance2";
//            break;
T
ths 已提交
4317
        case 3:
P
pbrook 已提交
4318
//            gen_helper_dmfc0_performance3(t0);
T
ths 已提交
4319 4320
            rn = "Performance3";
//            break;
T
ths 已提交
4321
        case 4:
P
pbrook 已提交
4322
//            gen_helper_dmfc0_performance4(t0);
T
ths 已提交
4323 4324
            rn = "Performance4";
//            break;
T
ths 已提交
4325
        case 5:
P
pbrook 已提交
4326
//            gen_helper_dmfc0_performance5(t0);
T
ths 已提交
4327 4328
            rn = "Performance5";
//            break;
T
ths 已提交
4329
        case 6:
P
pbrook 已提交
4330
//            gen_helper_dmfc0_performance6(t0);
T
ths 已提交
4331 4332
            rn = "Performance6";
//            break;
T
ths 已提交
4333
        case 7:
P
pbrook 已提交
4334
//            gen_helper_dmfc0_performance7(t0);
T
ths 已提交
4335 4336
            rn = "Performance7";
//            break;
T
ths 已提交
4337 4338 4339 4340 4341
        default:
            goto die;
        }
        break;
    case 26:
4342 4343 4344
        tcg_gen_movi_tl(t0, 0); /* unimplemented */
        rn = "ECC";
        break;
T
ths 已提交
4345 4346 4347 4348
    case 27:
        switch (sel) {
        /* ignored */
        case 0 ... 3:
4349
            tcg_gen_movi_tl(t0, 0); /* unimplemented */
T
ths 已提交
4350 4351
            rn = "CacheErr";
            break;
T
ths 已提交
4352 4353 4354 4355 4356 4357 4358 4359 4360 4361
        default:
            goto die;
        }
        break;
    case 28:
        switch (sel) {
        case 0:
        case 2:
        case 4:
        case 6:
4362
            gen_mfc0_load32(t0, offsetof(CPUState, CP0_TagLo));
T
ths 已提交
4363 4364 4365 4366 4367 4368
            rn = "TagLo";
            break;
        case 1:
        case 3:
        case 5:
        case 7:
4369
            gen_mfc0_load32(t0, offsetof(CPUState, CP0_DataLo));
T
ths 已提交
4370 4371 4372 4373 4374 4375 4376 4377 4378 4379 4380 4381
            rn = "DataLo";
            break;
        default:
            goto die;
        }
        break;
    case 29:
        switch (sel) {
        case 0:
        case 2:
        case 4:
        case 6:
4382
            gen_mfc0_load32(t0, offsetof(CPUState, CP0_TagHi));
T
ths 已提交
4383 4384 4385 4386 4387 4388
            rn = "TagHi";
            break;
        case 1:
        case 3:
        case 5:
        case 7:
4389
            gen_mfc0_load32(t0, offsetof(CPUState, CP0_DataHi));
T
ths 已提交
4390 4391 4392 4393 4394 4395 4396 4397 4398
            rn = "DataHi";
            break;
        default:
            goto die;
        }
        break;
    case 30:
        switch (sel) {
        case 0:
4399
            tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUState, CP0_ErrorEPC));
T
ths 已提交
4400 4401
            rn = "ErrorEPC";
            break;
T
ths 已提交
4402 4403 4404 4405 4406 4407 4408
        default:
            goto die;
        }
        break;
    case 31:
        switch (sel) {
        case 0:
T
ths 已提交
4409
            /* EJTAG support */
4410
            gen_mfc0_load32(t0, offsetof(CPUState, CP0_DESAVE));
T
ths 已提交
4411 4412
            rn = "DESAVE";
            break;
T
ths 已提交
4413 4414 4415 4416 4417
        default:
            goto die;
        }
        break;
    default:
T
ths 已提交
4418
        goto die;
T
ths 已提交
4419
    }
4420
    LOG_DISAS("dmfc0 %s (reg %d sel %d)\n", rn, reg, sel);
T
ths 已提交
4421 4422 4423
    return;

die:
4424
    LOG_DISAS("dmfc0 %s (reg %d sel %d)\n", rn, reg, sel);
T
ths 已提交
4425 4426 4427
    generate_exception(ctx, EXCP_RI);
}

4428
static void gen_dmtc0 (CPUState *env, DisasContext *ctx, TCGv t0, int reg, int sel)
T
ths 已提交
4429 4430 4431
{
    const char *rn = "invalid";

4432 4433 4434
    if (sel != 0)
        check_insn(env, ctx, ISA_MIPS64);

P
pbrook 已提交
4435 4436 4437
    if (use_icount)
        gen_io_start();

T
ths 已提交
4438 4439 4440 4441
    switch (reg) {
    case 0:
        switch (sel) {
        case 0:
P
pbrook 已提交
4442
            gen_helper_mtc0_index(t0);
T
ths 已提交
4443 4444 4445
            rn = "Index";
            break;
        case 1:
4446
            check_insn(env, ctx, ASE_MT);
P
pbrook 已提交
4447
            gen_helper_mtc0_mvpcontrol(t0);
T
ths 已提交
4448
            rn = "MVPControl";
4449
            break;
T
ths 已提交
4450
        case 2:
4451
            check_insn(env, ctx, ASE_MT);
4452
            /* ignored */
T
ths 已提交
4453
            rn = "MVPConf0";
4454
            break;
T
ths 已提交
4455
        case 3:
4456
            check_insn(env, ctx, ASE_MT);
4457
            /* ignored */
T
ths 已提交
4458
            rn = "MVPConf1";
4459
            break;
T
ths 已提交
4460 4461 4462 4463 4464 4465 4466
        default:
            goto die;
        }
        break;
    case 1:
        switch (sel) {
        case 0:
T
ths 已提交
4467
            /* ignored */
T
ths 已提交
4468
            rn = "Random";
T
ths 已提交
4469
            break;
T
ths 已提交
4470
        case 1:
4471
            check_insn(env, ctx, ASE_MT);
P
pbrook 已提交
4472
            gen_helper_mtc0_vpecontrol(t0);
T
ths 已提交
4473
            rn = "VPEControl";
4474
            break;
T
ths 已提交
4475
        case 2:
4476
            check_insn(env, ctx, ASE_MT);
P
pbrook 已提交
4477
            gen_helper_mtc0_vpeconf0(t0);
T
ths 已提交
4478
            rn = "VPEConf0";
4479
            break;
T
ths 已提交
4480
        case 3:
4481
            check_insn(env, ctx, ASE_MT);
P
pbrook 已提交
4482
            gen_helper_mtc0_vpeconf1(t0);
T
ths 已提交
4483
            rn = "VPEConf1";
4484
            break;
T
ths 已提交
4485
        case 4:
4486
            check_insn(env, ctx, ASE_MT);
P
pbrook 已提交
4487
            gen_helper_mtc0_yqmask(t0);
T
ths 已提交
4488
            rn = "YQMask";
4489
            break;
T
ths 已提交
4490
        case 5:
4491
            check_insn(env, ctx, ASE_MT);
4492
            tcg_gen_st_tl(t0, cpu_env, offsetof(CPUState, CP0_VPESchedule));
T
ths 已提交
4493
            rn = "VPESchedule";
4494
            break;
T
ths 已提交
4495
        case 6:
4496
            check_insn(env, ctx, ASE_MT);
4497
            tcg_gen_st_tl(t0, cpu_env, offsetof(CPUState, CP0_VPEScheFBack));
T
ths 已提交
4498
            rn = "VPEScheFBack";
4499
            break;
T
ths 已提交
4500
        case 7:
4501
            check_insn(env, ctx, ASE_MT);
P
pbrook 已提交
4502
            gen_helper_mtc0_vpeopt(t0);
T
ths 已提交
4503
            rn = "VPEOpt";
4504
            break;
T
ths 已提交
4505 4506 4507 4508 4509 4510 4511
        default:
            goto die;
        }
        break;
    case 2:
        switch (sel) {
        case 0:
P
pbrook 已提交
4512
            gen_helper_mtc0_entrylo0(t0);
T
ths 已提交
4513 4514
            rn = "EntryLo0";
            break;
T
ths 已提交
4515
        case 1:
4516
            check_insn(env, ctx, ASE_MT);
P
pbrook 已提交
4517
            gen_helper_mtc0_tcstatus(t0);
T
ths 已提交
4518
            rn = "TCStatus";
4519
            break;
T
ths 已提交
4520
        case 2:
4521
            check_insn(env, ctx, ASE_MT);
P
pbrook 已提交
4522
            gen_helper_mtc0_tcbind(t0);
T
ths 已提交
4523
            rn = "TCBind";
4524
            break;
T
ths 已提交
4525
        case 3:
4526
            check_insn(env, ctx, ASE_MT);
P
pbrook 已提交
4527
            gen_helper_mtc0_tcrestart(t0);
T
ths 已提交
4528
            rn = "TCRestart";
4529
            break;
T
ths 已提交
4530
        case 4:
4531
            check_insn(env, ctx, ASE_MT);
P
pbrook 已提交
4532
            gen_helper_mtc0_tchalt(t0);
T
ths 已提交
4533
            rn = "TCHalt";
4534
            break;
T
ths 已提交
4535
        case 5:
4536
            check_insn(env, ctx, ASE_MT);
P
pbrook 已提交
4537
            gen_helper_mtc0_tccontext(t0);
T
ths 已提交
4538
            rn = "TCContext";
4539
            break;
T
ths 已提交
4540
        case 6:
4541
            check_insn(env, ctx, ASE_MT);
P
pbrook 已提交
4542
            gen_helper_mtc0_tcschedule(t0);
T
ths 已提交
4543
            rn = "TCSchedule";
4544
            break;
T
ths 已提交
4545
        case 7:
4546
            check_insn(env, ctx, ASE_MT);
P
pbrook 已提交
4547
            gen_helper_mtc0_tcschefback(t0);
T
ths 已提交
4548
            rn = "TCScheFBack";
4549
            break;
T
ths 已提交
4550 4551 4552 4553 4554 4555 4556
        default:
            goto die;
        }
        break;
    case 3:
        switch (sel) {
        case 0:
P
pbrook 已提交
4557
            gen_helper_mtc0_entrylo1(t0);
T
ths 已提交
4558 4559
            rn = "EntryLo1";
            break;
T
ths 已提交
4560 4561
        default:
            goto die;
T
ths 已提交
4562
        }
T
ths 已提交
4563 4564 4565 4566
        break;
    case 4:
        switch (sel) {
        case 0:
P
pbrook 已提交
4567
            gen_helper_mtc0_context(t0);
T
ths 已提交
4568 4569
            rn = "Context";
            break;
T
ths 已提交
4570
        case 1:
P
pbrook 已提交
4571
//           gen_helper_mtc0_contextconfig(t0); /* SmartMIPS ASE */
T
ths 已提交
4572 4573
            rn = "ContextConfig";
//           break;
T
ths 已提交
4574 4575
        default:
            goto die;
T
ths 已提交
4576
        }
T
ths 已提交
4577 4578 4579 4580
        break;
    case 5:
        switch (sel) {
        case 0:
P
pbrook 已提交
4581
            gen_helper_mtc0_pagemask(t0);
T
ths 已提交
4582 4583
            rn = "PageMask";
            break;
T
ths 已提交
4584
        case 1:
4585
            check_insn(env, ctx, ISA_MIPS32R2);
P
pbrook 已提交
4586
            gen_helper_mtc0_pagegrain(t0);
T
ths 已提交
4587 4588
            rn = "PageGrain";
            break;
T
ths 已提交
4589 4590
        default:
            goto die;
T
ths 已提交
4591
        }
T
ths 已提交
4592 4593 4594 4595
        break;
    case 6:
        switch (sel) {
        case 0:
P
pbrook 已提交
4596
            gen_helper_mtc0_wired(t0);
T
ths 已提交
4597 4598
            rn = "Wired";
            break;
T
ths 已提交
4599
        case 1:
4600
            check_insn(env, ctx, ISA_MIPS32R2);
P
pbrook 已提交
4601
            gen_helper_mtc0_srsconf0(t0);
T
ths 已提交
4602
            rn = "SRSConf0";
4603
            break;
T
ths 已提交
4604
        case 2:
4605
            check_insn(env, ctx, ISA_MIPS32R2);
P
pbrook 已提交
4606
            gen_helper_mtc0_srsconf1(t0);
T
ths 已提交
4607
            rn = "SRSConf1";
4608
            break;
T
ths 已提交
4609
        case 3:
4610
            check_insn(env, ctx, ISA_MIPS32R2);
P
pbrook 已提交
4611
            gen_helper_mtc0_srsconf2(t0);
T
ths 已提交
4612
            rn = "SRSConf2";
4613
            break;
T
ths 已提交
4614
        case 4:
4615
            check_insn(env, ctx, ISA_MIPS32R2);
P
pbrook 已提交
4616
            gen_helper_mtc0_srsconf3(t0);
T
ths 已提交
4617
            rn = "SRSConf3";
4618
            break;
T
ths 已提交
4619
        case 5:
4620
            check_insn(env, ctx, ISA_MIPS32R2);
P
pbrook 已提交
4621
            gen_helper_mtc0_srsconf4(t0);
T
ths 已提交
4622
            rn = "SRSConf4";
4623
            break;
T
ths 已提交
4624 4625
        default:
            goto die;
T
ths 已提交
4626
        }
T
ths 已提交
4627 4628 4629 4630
        break;
    case 7:
        switch (sel) {
        case 0:
4631
            check_insn(env, ctx, ISA_MIPS32R2);
P
pbrook 已提交
4632
            gen_helper_mtc0_hwrena(t0);
T
ths 已提交
4633 4634
            rn = "HWREna";
            break;
T
ths 已提交
4635 4636
        default:
            goto die;
T
ths 已提交
4637
        }
T
ths 已提交
4638 4639 4640
        break;
    case 8:
        /* ignored */
T
ths 已提交
4641
        rn = "BadVAddr";
T
ths 已提交
4642 4643 4644 4645
        break;
    case 9:
        switch (sel) {
        case 0:
P
pbrook 已提交
4646
            gen_helper_mtc0_count(t0);
T
ths 已提交
4647 4648
            rn = "Count";
            break;
T
ths 已提交
4649
        /* 6,7 are implementation dependent */
T
ths 已提交
4650 4651
        default:
            goto die;
T
ths 已提交
4652 4653 4654
        }
        /* Stop translation as we may have switched the execution mode */
        ctx->bstate = BS_STOP;
T
ths 已提交
4655 4656 4657 4658
        break;
    case 10:
        switch (sel) {
        case 0:
P
pbrook 已提交
4659
            gen_helper_mtc0_entryhi(t0);
T
ths 已提交
4660 4661
            rn = "EntryHi";
            break;
T
ths 已提交
4662 4663
        default:
            goto die;
T
ths 已提交
4664
        }
T
ths 已提交
4665 4666 4667 4668
        break;
    case 11:
        switch (sel) {
        case 0:
P
pbrook 已提交
4669
            gen_helper_mtc0_compare(t0);
T
ths 已提交
4670 4671
            rn = "Compare";
            break;
T
ths 已提交
4672
        /* 6,7 are implementation dependent */
T
ths 已提交
4673 4674
        default:
            goto die;
T
ths 已提交
4675
        }
4676 4677
        /* Stop translation as we may have switched the execution mode */
        ctx->bstate = BS_STOP;
T
ths 已提交
4678 4679 4680 4681
        break;
    case 12:
        switch (sel) {
        case 0:
P
pbrook 已提交
4682
            gen_helper_mtc0_status(t0);
4683 4684 4685
            /* BS_STOP isn't good enough here, hflags may have changed. */
            gen_save_pc(ctx->pc + 4);
            ctx->bstate = BS_EXCP;
T
ths 已提交
4686 4687
            rn = "Status";
            break;
T
ths 已提交
4688
        case 1:
4689
            check_insn(env, ctx, ISA_MIPS32R2);
P
pbrook 已提交
4690
            gen_helper_mtc0_intctl(t0);
4691 4692
            /* Stop translation as we may have switched the execution mode */
            ctx->bstate = BS_STOP;
T
ths 已提交
4693 4694
            rn = "IntCtl";
            break;
T
ths 已提交
4695
        case 2:
4696
            check_insn(env, ctx, ISA_MIPS32R2);
P
pbrook 已提交
4697
            gen_helper_mtc0_srsctl(t0);
4698 4699
            /* Stop translation as we may have switched the execution mode */
            ctx->bstate = BS_STOP;
T
ths 已提交
4700 4701
            rn = "SRSCtl";
            break;
T
ths 已提交
4702
        case 3:
4703
            check_insn(env, ctx, ISA_MIPS32R2);
4704
            gen_mtc0_store32(t0, offsetof(CPUState, CP0_SRSMap));
4705 4706
            /* Stop translation as we may have switched the execution mode */
            ctx->bstate = BS_STOP;
T
ths 已提交
4707 4708 4709
            rn = "SRSMap";
            break;
        default:
T
ths 已提交
4710
            goto die;
T
ths 已提交
4711
        }
T
ths 已提交
4712 4713 4714 4715
        break;
    case 13:
        switch (sel) {
        case 0:
P
pbrook 已提交
4716
            gen_helper_mtc0_cause(t0);
T
ths 已提交
4717 4718
            rn = "Cause";
            break;
T
ths 已提交
4719 4720
        default:
            goto die;
T
ths 已提交
4721 4722 4723
        }
        /* Stop translation as we may have switched the execution mode */
        ctx->bstate = BS_STOP;
T
ths 已提交
4724 4725 4726 4727
        break;
    case 14:
        switch (sel) {
        case 0:
4728
            tcg_gen_st_tl(t0, cpu_env, offsetof(CPUState, CP0_EPC));
T
ths 已提交
4729 4730
            rn = "EPC";
            break;
T
ths 已提交
4731 4732
        default:
            goto die;
T
ths 已提交
4733
        }
T
ths 已提交
4734 4735 4736 4737
        break;
    case 15:
        switch (sel) {
        case 0:
T
ths 已提交
4738 4739 4740
            /* ignored */
            rn = "PRid";
            break;
T
ths 已提交
4741
        case 1:
4742
            check_insn(env, ctx, ISA_MIPS32R2);
P
pbrook 已提交
4743
            gen_helper_mtc0_ebase(t0);
T
ths 已提交
4744 4745
            rn = "EBase";
            break;
T
ths 已提交
4746 4747
        default:
            goto die;
T
ths 已提交
4748
        }
T
ths 已提交
4749 4750 4751 4752
        break;
    case 16:
        switch (sel) {
        case 0:
P
pbrook 已提交
4753
            gen_helper_mtc0_config0(t0);
T
ths 已提交
4754
            rn = "Config";
T
ths 已提交
4755 4756
            /* Stop translation as we may have switched the execution mode */
            ctx->bstate = BS_STOP;
T
ths 已提交
4757 4758
            break;
        case 1:
T
ths 已提交
4759
            /* ignored */
T
ths 已提交
4760 4761 4762
            rn = "Config1";
            break;
        case 2:
P
pbrook 已提交
4763
            gen_helper_mtc0_config2(t0);
T
ths 已提交
4764
            rn = "Config2";
T
ths 已提交
4765 4766
            /* Stop translation as we may have switched the execution mode */
            ctx->bstate = BS_STOP;
T
ths 已提交
4767 4768
            break;
        case 3:
T
ths 已提交
4769
            /* ignored */
T
ths 已提交
4770 4771 4772 4773 4774 4775 4776 4777 4778 4779 4780
            rn = "Config3";
            break;
        /* 6,7 are implementation dependent */
        default:
            rn = "Invalid config selector";
            goto die;
        }
        break;
    case 17:
        switch (sel) {
        case 0:
T
ths 已提交
4781 4782 4783
            /* ignored */
            rn = "LLAddr";
            break;
T
ths 已提交
4784 4785 4786 4787 4788 4789
        default:
            goto die;
        }
        break;
    case 18:
        switch (sel) {
4790
        case 0 ... 7:
P
pbrook 已提交
4791
            gen_helper_1i(mtc0_watchlo, t0, sel);
T
ths 已提交
4792 4793
            rn = "WatchLo";
            break;
T
ths 已提交
4794 4795 4796 4797 4798 4799
        default:
            goto die;
        }
        break;
    case 19:
        switch (sel) {
4800
        case 0 ... 7:
P
pbrook 已提交
4801
            gen_helper_1i(mtc0_watchhi, t0, sel);
T
ths 已提交
4802 4803
            rn = "WatchHi";
            break;
T
ths 已提交
4804 4805 4806 4807 4808 4809 4810
        default:
            goto die;
        }
        break;
    case 20:
        switch (sel) {
        case 0:
4811
            check_insn(env, ctx, ISA_MIPS3);
P
pbrook 已提交
4812
            gen_helper_mtc0_xcontext(t0);
T
ths 已提交
4813 4814
            rn = "XContext";
            break;
T
ths 已提交
4815 4816 4817 4818 4819 4820 4821 4822
        default:
            goto die;
        }
        break;
    case 21:
       /* Officially reserved, but sel 0 is used for R1x000 framemask */
        switch (sel) {
        case 0:
P
pbrook 已提交
4823
            gen_helper_mtc0_framemask(t0);
T
ths 已提交
4824 4825
            rn = "Framemask";
            break;
T
ths 已提交
4826 4827 4828 4829 4830 4831 4832
        default:
            goto die;
        }
        break;
    case 22:
        /* ignored */
        rn = "Diagnostic"; /* implementation dependent */
T
ths 已提交
4833
        break;
T
ths 已提交
4834 4835 4836
    case 23:
        switch (sel) {
        case 0:
P
pbrook 已提交
4837
            gen_helper_mtc0_debug(t0); /* EJTAG support */
4838 4839 4840
            /* BS_STOP isn't good enough here, hflags may have changed. */
            gen_save_pc(ctx->pc + 4);
            ctx->bstate = BS_EXCP;
T
ths 已提交
4841 4842
            rn = "Debug";
            break;
T
ths 已提交
4843
        case 1:
P
pbrook 已提交
4844
//            gen_helper_mtc0_tracecontrol(t0); /* PDtrace support */
4845 4846
            /* Stop translation as we may have switched the execution mode */
            ctx->bstate = BS_STOP;
T
ths 已提交
4847 4848
            rn = "TraceControl";
//            break;
T
ths 已提交
4849
        case 2:
P
pbrook 已提交
4850
//            gen_helper_mtc0_tracecontrol2(t0); /* PDtrace support */
4851 4852
            /* Stop translation as we may have switched the execution mode */
            ctx->bstate = BS_STOP;
T
ths 已提交
4853 4854
            rn = "TraceControl2";
//            break;
T
ths 已提交
4855
        case 3:
P
pbrook 已提交
4856
//            gen_helper_mtc0_usertracedata(t0); /* PDtrace support */
4857 4858
            /* Stop translation as we may have switched the execution mode */
            ctx->bstate = BS_STOP;
T
ths 已提交
4859 4860
            rn = "UserTraceData";
//            break;
T
ths 已提交
4861
        case 4:
P
pbrook 已提交
4862
//            gen_helper_mtc0_tracebpc(t0); /* PDtrace support */
4863 4864
            /* Stop translation as we may have switched the execution mode */
            ctx->bstate = BS_STOP;
T
ths 已提交
4865 4866
            rn = "TraceBPC";
//            break;
T
ths 已提交
4867 4868 4869 4870 4871 4872 4873
        default:
            goto die;
        }
        break;
    case 24:
        switch (sel) {
        case 0:
4874
            /* EJTAG support */
4875
            tcg_gen_st_tl(t0, cpu_env, offsetof(CPUState, CP0_DEPC));
T
ths 已提交
4876 4877
            rn = "DEPC";
            break;
T
ths 已提交
4878 4879 4880 4881 4882 4883 4884
        default:
            goto die;
        }
        break;
    case 25:
        switch (sel) {
        case 0:
P
pbrook 已提交
4885
            gen_helper_mtc0_performance0(t0);
T
ths 已提交
4886 4887
            rn = "Performance0";
            break;
T
ths 已提交
4888
        case 1:
P
pbrook 已提交
4889
//            gen_helper_mtc0_performance1(t0);
T
ths 已提交
4890 4891
            rn = "Performance1";
//            break;
T
ths 已提交
4892
        case 2:
P
pbrook 已提交
4893
//            gen_helper_mtc0_performance2(t0);
T
ths 已提交
4894 4895
            rn = "Performance2";
//            break;
T
ths 已提交
4896
        case 3:
P
pbrook 已提交
4897
//            gen_helper_mtc0_performance3(t0);
T
ths 已提交
4898 4899
            rn = "Performance3";
//            break;
T
ths 已提交
4900
        case 4:
P
pbrook 已提交
4901
//            gen_helper_mtc0_performance4(t0);
T
ths 已提交
4902 4903
            rn = "Performance4";
//            break;
T
ths 已提交
4904
        case 5:
P
pbrook 已提交
4905
//            gen_helper_mtc0_performance5(t0);
T
ths 已提交
4906 4907
            rn = "Performance5";
//            break;
T
ths 已提交
4908
        case 6:
P
pbrook 已提交
4909
//            gen_helper_mtc0_performance6(t0);
T
ths 已提交
4910 4911
            rn = "Performance6";
//            break;
T
ths 已提交
4912
        case 7:
P
pbrook 已提交
4913
//            gen_helper_mtc0_performance7(t0);
T
ths 已提交
4914 4915
            rn = "Performance7";
//            break;
T
ths 已提交
4916 4917 4918
        default:
            goto die;
        }
T
ths 已提交
4919
        break;
T
ths 已提交
4920
    case 26:
T
ths 已提交
4921
        /* ignored */
T
ths 已提交
4922
        rn = "ECC";
T
ths 已提交
4923
        break;
T
ths 已提交
4924 4925 4926
    case 27:
        switch (sel) {
        case 0 ... 3:
T
ths 已提交
4927 4928 4929
            /* ignored */
            rn = "CacheErr";
            break;
T
ths 已提交
4930 4931 4932
        default:
            goto die;
        }
T
ths 已提交
4933
        break;
T
ths 已提交
4934 4935 4936 4937 4938 4939
    case 28:
        switch (sel) {
        case 0:
        case 2:
        case 4:
        case 6:
P
pbrook 已提交
4940
            gen_helper_mtc0_taglo(t0);
T
ths 已提交
4941 4942 4943 4944 4945 4946
            rn = "TagLo";
            break;
        case 1:
        case 3:
        case 5:
        case 7:
P
pbrook 已提交
4947
            gen_helper_mtc0_datalo(t0);
T
ths 已提交
4948 4949 4950 4951 4952 4953 4954 4955 4956 4957 4958 4959
            rn = "DataLo";
            break;
        default:
            goto die;
        }
        break;
    case 29:
        switch (sel) {
        case 0:
        case 2:
        case 4:
        case 6:
P
pbrook 已提交
4960
            gen_helper_mtc0_taghi(t0);
T
ths 已提交
4961 4962 4963 4964 4965 4966
            rn = "TagHi";
            break;
        case 1:
        case 3:
        case 5:
        case 7:
P
pbrook 已提交
4967
            gen_helper_mtc0_datahi(t0);
T
ths 已提交
4968 4969 4970 4971 4972 4973
            rn = "DataHi";
            break;
        default:
            rn = "invalid sel";
            goto die;
        }
T
ths 已提交
4974
        break;
T
ths 已提交
4975 4976 4977
    case 30:
        switch (sel) {
        case 0:
4978
            tcg_gen_st_tl(t0, cpu_env, offsetof(CPUState, CP0_ErrorEPC));
T
ths 已提交
4979 4980
            rn = "ErrorEPC";
            break;
T
ths 已提交
4981 4982 4983 4984 4985 4986 4987
        default:
            goto die;
        }
        break;
    case 31:
        switch (sel) {
        case 0:
4988
            /* EJTAG support */
4989
            gen_mtc0_store32(t0, offsetof(CPUState, CP0_DESAVE));
T
ths 已提交
4990 4991
            rn = "DESAVE";
            break;
T
ths 已提交
4992 4993 4994
        default:
            goto die;
        }
T
ths 已提交
4995 4996
        /* Stop translation as we may have switched the execution mode */
        ctx->bstate = BS_STOP;
T
ths 已提交
4997 4998
        break;
    default:
T
ths 已提交
4999
        goto die;
T
ths 已提交
5000
    }
5001
    LOG_DISAS("dmtc0 %s (reg %d sel %d)\n", rn, reg, sel);
T
ths 已提交
5002
    /* For simplicity assume that all writes can cause interrupts.  */
P
pbrook 已提交
5003 5004 5005 5006
    if (use_icount) {
        gen_io_end();
        ctx->bstate = BS_STOP;
    }
T
ths 已提交
5007 5008 5009
    return;

die:
5010
    LOG_DISAS("dmtc0 %s (reg %d sel %d)\n", rn, reg, sel);
T
ths 已提交
5011 5012
    generate_exception(ctx, EXCP_RI);
}
5013
#endif /* TARGET_MIPS64 */
T
ths 已提交
5014

5015
static void gen_mftr(CPUState *env, DisasContext *ctx, int rt, int rd,
5016 5017 5018
                     int u, int sel, int h)
{
    int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
P
pbrook 已提交
5019
    TCGv t0 = tcg_temp_local_new();
5020 5021

    if ((env->CP0_VPEConf0 & (1 << CP0VPEC0_MVP)) == 0 &&
5022 5023
        ((env->tcs[other_tc].CP0_TCBind & (0xf << CP0TCBd_CurVPE)) !=
         (env->active_tc.CP0_TCBind & (0xf << CP0TCBd_CurVPE))))
5024
        tcg_gen_movi_tl(t0, -1);
5025 5026
    else if ((env->CP0_VPEControl & (0xff << CP0VPECo_TargTC)) >
             (env->mvp->CP0_MVPConf0 & (0xff << CP0MVPC0_PTC)))
5027
        tcg_gen_movi_tl(t0, -1);
5028 5029 5030 5031 5032
    else if (u == 0) {
        switch (rt) {
        case 2:
            switch (sel) {
            case 1:
P
pbrook 已提交
5033
                gen_helper_mftc0_tcstatus(t0);
5034 5035
                break;
            case 2:
P
pbrook 已提交
5036
                gen_helper_mftc0_tcbind(t0);
5037 5038
                break;
            case 3:
P
pbrook 已提交
5039
                gen_helper_mftc0_tcrestart(t0);
5040 5041
                break;
            case 4:
P
pbrook 已提交
5042
                gen_helper_mftc0_tchalt(t0);
5043 5044
                break;
            case 5:
P
pbrook 已提交
5045
                gen_helper_mftc0_tccontext(t0);
5046 5047
                break;
            case 6:
P
pbrook 已提交
5048
                gen_helper_mftc0_tcschedule(t0);
5049 5050
                break;
            case 7:
P
pbrook 已提交
5051
                gen_helper_mftc0_tcschefback(t0);
5052 5053
                break;
            default:
5054
                gen_mfc0(env, ctx, t0, rt, sel);
5055 5056 5057 5058 5059 5060
                break;
            }
            break;
        case 10:
            switch (sel) {
            case 0:
P
pbrook 已提交
5061
                gen_helper_mftc0_entryhi(t0);
5062 5063
                break;
            default:
5064
                gen_mfc0(env, ctx, t0, rt, sel);
5065 5066 5067 5068 5069
                break;
            }
        case 12:
            switch (sel) {
            case 0:
P
pbrook 已提交
5070
                gen_helper_mftc0_status(t0);
5071 5072
                break;
            default:
5073
                gen_mfc0(env, ctx, t0, rt, sel);
5074 5075 5076 5077 5078
                break;
            }
        case 23:
            switch (sel) {
            case 0:
P
pbrook 已提交
5079
                gen_helper_mftc0_debug(t0);
5080 5081
                break;
            default:
5082
                gen_mfc0(env, ctx, t0, rt, sel);
5083 5084 5085 5086
                break;
            }
            break;
        default:
5087
            gen_mfc0(env, ctx, t0, rt, sel);
5088 5089 5090 5091
        }
    } else switch (sel) {
    /* GPR registers. */
    case 0:
P
pbrook 已提交
5092
        gen_helper_1i(mftgpr, t0, rt);
5093 5094 5095 5096 5097
        break;
    /* Auxiliary CPU registers */
    case 1:
        switch (rt) {
        case 0:
P
pbrook 已提交
5098
            gen_helper_1i(mftlo, t0, 0);
5099 5100
            break;
        case 1:
P
pbrook 已提交
5101
            gen_helper_1i(mfthi, t0, 0);
5102 5103
            break;
        case 2:
P
pbrook 已提交
5104
            gen_helper_1i(mftacx, t0, 0);
5105 5106
            break;
        case 4:
P
pbrook 已提交
5107
            gen_helper_1i(mftlo, t0, 1);
5108 5109
            break;
        case 5:
P
pbrook 已提交
5110
            gen_helper_1i(mfthi, t0, 1);
5111 5112
            break;
        case 6:
P
pbrook 已提交
5113
            gen_helper_1i(mftacx, t0, 1);
5114 5115
            break;
        case 8:
P
pbrook 已提交
5116
            gen_helper_1i(mftlo, t0, 2);
5117 5118
            break;
        case 9:
P
pbrook 已提交
5119
            gen_helper_1i(mfthi, t0, 2);
5120 5121
            break;
        case 10:
P
pbrook 已提交
5122
            gen_helper_1i(mftacx, t0, 2);
5123 5124
            break;
        case 12:
P
pbrook 已提交
5125
            gen_helper_1i(mftlo, t0, 3);
5126 5127
            break;
        case 13:
P
pbrook 已提交
5128
            gen_helper_1i(mfthi, t0, 3);
5129 5130
            break;
        case 14:
P
pbrook 已提交
5131
            gen_helper_1i(mftacx, t0, 3);
5132 5133
            break;
        case 16:
P
pbrook 已提交
5134
            gen_helper_mftdsp(t0);
5135 5136 5137 5138 5139 5140 5141 5142 5143
            break;
        default:
            goto die;
        }
        break;
    /* Floating point (COP1). */
    case 2:
        /* XXX: For now we support only a single FPU context. */
        if (h == 0) {
P
pbrook 已提交
5144
            TCGv_i32 fp0 = tcg_temp_new_i32();
5145 5146 5147

            gen_load_fpr32(fp0, rt);
            tcg_gen_ext_i32_tl(t0, fp0);
P
pbrook 已提交
5148
            tcg_temp_free_i32(fp0);
5149
        } else {
P
pbrook 已提交
5150
            TCGv_i32 fp0 = tcg_temp_new_i32();
5151 5152 5153

            gen_load_fpr32h(fp0, rt);
            tcg_gen_ext_i32_tl(t0, fp0);
P
pbrook 已提交
5154
            tcg_temp_free_i32(fp0);
5155 5156 5157 5158
        }
        break;
    case 3:
        /* XXX: For now we support only a single FPU context. */
P
pbrook 已提交
5159
        gen_helper_1i(cfc1, t0, rt);
5160 5161 5162 5163 5164 5165 5166 5167
        break;
    /* COP2: Not implemented. */
    case 4:
    case 5:
        /* fall through */
    default:
        goto die;
    }
5168
    LOG_DISAS("mftr (reg %d u %d sel %d h %d)\n", rt, u, sel, h);
5169 5170
    gen_store_gpr(t0, rd);
    tcg_temp_free(t0);
5171 5172 5173
    return;

die:
5174
    tcg_temp_free(t0);
5175
    LOG_DISAS("mftr (reg %d u %d sel %d h %d)\n", rt, u, sel, h);
5176 5177 5178
    generate_exception(ctx, EXCP_RI);
}

5179
static void gen_mttr(CPUState *env, DisasContext *ctx, int rd, int rt,
5180 5181 5182
                     int u, int sel, int h)
{
    int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
P
pbrook 已提交
5183
    TCGv t0 = tcg_temp_local_new();
5184

5185
    gen_load_gpr(t0, rt);
5186
    if ((env->CP0_VPEConf0 & (1 << CP0VPEC0_MVP)) == 0 &&
5187 5188
        ((env->tcs[other_tc].CP0_TCBind & (0xf << CP0TCBd_CurVPE)) !=
         (env->active_tc.CP0_TCBind & (0xf << CP0TCBd_CurVPE))))
5189 5190 5191 5192 5193 5194 5195 5196 5197
        /* NOP */ ;
    else if ((env->CP0_VPEControl & (0xff << CP0VPECo_TargTC)) >
             (env->mvp->CP0_MVPConf0 & (0xff << CP0MVPC0_PTC)))
        /* NOP */ ;
    else if (u == 0) {
        switch (rd) {
        case 2:
            switch (sel) {
            case 1:
P
pbrook 已提交
5198
                gen_helper_mttc0_tcstatus(t0);
5199 5200
                break;
            case 2:
P
pbrook 已提交
5201
                gen_helper_mttc0_tcbind(t0);
5202 5203
                break;
            case 3:
P
pbrook 已提交
5204
                gen_helper_mttc0_tcrestart(t0);
5205 5206
                break;
            case 4:
P
pbrook 已提交
5207
                gen_helper_mttc0_tchalt(t0);
5208 5209
                break;
            case 5:
P
pbrook 已提交
5210
                gen_helper_mttc0_tccontext(t0);
5211 5212
                break;
            case 6:
P
pbrook 已提交
5213
                gen_helper_mttc0_tcschedule(t0);
5214 5215
                break;
            case 7:
P
pbrook 已提交
5216
                gen_helper_mttc0_tcschefback(t0);
5217 5218
                break;
            default:
5219
                gen_mtc0(env, ctx, t0, rd, sel);
5220 5221 5222 5223 5224 5225
                break;
            }
            break;
        case 10:
            switch (sel) {
            case 0:
P
pbrook 已提交
5226
                gen_helper_mttc0_entryhi(t0);
5227 5228
                break;
            default:
5229
                gen_mtc0(env, ctx, t0, rd, sel);
5230 5231 5232 5233 5234
                break;
            }
        case 12:
            switch (sel) {
            case 0:
P
pbrook 已提交
5235
                gen_helper_mttc0_status(t0);
5236 5237
                break;
            default:
5238
                gen_mtc0(env, ctx, t0, rd, sel);
5239 5240 5241 5242 5243
                break;
            }
        case 23:
            switch (sel) {
            case 0:
P
pbrook 已提交
5244
                gen_helper_mttc0_debug(t0);
5245 5246
                break;
            default:
5247
                gen_mtc0(env, ctx, t0, rd, sel);
5248 5249 5250 5251
                break;
            }
            break;
        default:
5252
            gen_mtc0(env, ctx, t0, rd, sel);
5253 5254 5255 5256
        }
    } else switch (sel) {
    /* GPR registers. */
    case 0:
P
pbrook 已提交
5257
        gen_helper_1i(mttgpr, t0, rd);
5258 5259 5260 5261 5262
        break;
    /* Auxiliary CPU registers */
    case 1:
        switch (rd) {
        case 0:
P
pbrook 已提交
5263
            gen_helper_1i(mttlo, t0, 0);
5264 5265
            break;
        case 1:
P
pbrook 已提交
5266
            gen_helper_1i(mtthi, t0, 0);
5267 5268
            break;
        case 2:
P
pbrook 已提交
5269
            gen_helper_1i(mttacx, t0, 0);
5270 5271
            break;
        case 4:
P
pbrook 已提交
5272
            gen_helper_1i(mttlo, t0, 1);
5273 5274
            break;
        case 5:
P
pbrook 已提交
5275
            gen_helper_1i(mtthi, t0, 1);
5276 5277
            break;
        case 6:
P
pbrook 已提交
5278
            gen_helper_1i(mttacx, t0, 1);
5279 5280
            break;
        case 8:
P
pbrook 已提交
5281
            gen_helper_1i(mttlo, t0, 2);
5282 5283
            break;
        case 9:
P
pbrook 已提交
5284
            gen_helper_1i(mtthi, t0, 2);
5285 5286
            break;
        case 10:
P
pbrook 已提交
5287
            gen_helper_1i(mttacx, t0, 2);
5288 5289
            break;
        case 12:
P
pbrook 已提交
5290
            gen_helper_1i(mttlo, t0, 3);
5291 5292
            break;
        case 13:
P
pbrook 已提交
5293
            gen_helper_1i(mtthi, t0, 3);
5294 5295
            break;
        case 14:
P
pbrook 已提交
5296
            gen_helper_1i(mttacx, t0, 3);
5297 5298
            break;
        case 16:
P
pbrook 已提交
5299
            gen_helper_mttdsp(t0);
5300 5301 5302 5303 5304 5305 5306 5307 5308
            break;
        default:
            goto die;
        }
        break;
    /* Floating point (COP1). */
    case 2:
        /* XXX: For now we support only a single FPU context. */
        if (h == 0) {
P
pbrook 已提交
5309
            TCGv_i32 fp0 = tcg_temp_new_i32();
5310 5311 5312

            tcg_gen_trunc_tl_i32(fp0, t0);
            gen_store_fpr32(fp0, rd);
P
pbrook 已提交
5313
            tcg_temp_free_i32(fp0);
5314
        } else {
P
pbrook 已提交
5315
            TCGv_i32 fp0 = tcg_temp_new_i32();
5316 5317 5318

            tcg_gen_trunc_tl_i32(fp0, t0);
            gen_store_fpr32h(fp0, rd);
P
pbrook 已提交
5319
            tcg_temp_free_i32(fp0);
5320 5321 5322 5323
        }
        break;
    case 3:
        /* XXX: For now we support only a single FPU context. */
P
pbrook 已提交
5324
        gen_helper_1i(ctc1, t0, rd);
5325 5326 5327 5328 5329 5330 5331 5332
        break;
    /* COP2: Not implemented. */
    case 4:
    case 5:
        /* fall through */
    default:
        goto die;
    }
5333
    LOG_DISAS("mttr (reg %d u %d sel %d h %d)\n", rd, u, sel, h);
5334
    tcg_temp_free(t0);
5335 5336 5337
    return;

die:
5338
    tcg_temp_free(t0);
5339
    LOG_DISAS("mttr (reg %d u %d sel %d h %d)\n", rd, u, sel, h);
5340 5341 5342
    generate_exception(ctx, EXCP_RI);
}

5343
static void gen_cp0 (CPUState *env, DisasContext *ctx, uint32_t opc, int rt, int rd)
B
bellard 已提交
5344
{
T
ths 已提交
5345
    const char *opn = "ldst";
B
bellard 已提交
5346 5347 5348 5349

    switch (opc) {
    case OPC_MFC0:
        if (rt == 0) {
5350
            /* Treat as NOP. */
B
bellard 已提交
5351 5352
            return;
        }
5353
        {
P
pbrook 已提交
5354
            TCGv t0 = tcg_temp_local_new();
5355 5356 5357 5358 5359

            gen_mfc0(env, ctx, t0, rd, ctx->opcode & 0x7);
            gen_store_gpr(t0, rt);
            tcg_temp_free(t0);
        }
B
bellard 已提交
5360 5361 5362
        opn = "mfc0";
        break;
    case OPC_MTC0:
5363
        {
P
pbrook 已提交
5364
            TCGv t0 = tcg_temp_local_new();
5365 5366 5367 5368 5369 5370

            gen_load_gpr(t0, rt);
            save_cpu_state(ctx, 1);
            gen_mtc0(env, ctx, t0, rd, ctx->opcode & 0x7);
            tcg_temp_free(t0);
        }
B
bellard 已提交
5371 5372
        opn = "mtc0";
        break;
5373
#if defined(TARGET_MIPS64)
T
ths 已提交
5374
    case OPC_DMFC0:
5375
        check_insn(env, ctx, ISA_MIPS3);
T
ths 已提交
5376
        if (rt == 0) {
5377
            /* Treat as NOP. */
T
ths 已提交
5378 5379
            return;
        }
5380
        {
P
pbrook 已提交
5381
            TCGv t0 = tcg_temp_local_new();
5382 5383 5384 5385 5386

            gen_dmfc0(env, ctx, t0, rd, ctx->opcode & 0x7);
            gen_store_gpr(t0, rt);
            tcg_temp_free(t0);
        }
T
ths 已提交
5387 5388 5389
        opn = "dmfc0";
        break;
    case OPC_DMTC0:
5390
        check_insn(env, ctx, ISA_MIPS3);
5391
        {
P
pbrook 已提交
5392
            TCGv t0 = tcg_temp_local_new();
5393 5394 5395 5396 5397 5398

            gen_load_gpr(t0, rt);
            save_cpu_state(ctx, 1);
            gen_dmtc0(env, ctx, t0, rd, ctx->opcode & 0x7);
            tcg_temp_free(t0);
        }
T
ths 已提交
5399 5400
        opn = "dmtc0";
        break;
5401
#endif
5402
    case OPC_MFTR:
5403
        check_insn(env, ctx, ASE_MT);
5404 5405 5406 5407
        if (rd == 0) {
            /* Treat as NOP. */
            return;
        }
5408
        gen_mftr(env, ctx, rt, rd, (ctx->opcode >> 5) & 1,
5409 5410 5411 5412
                 ctx->opcode & 0x7, (ctx->opcode >> 4) & 1);
        opn = "mftr";
        break;
    case OPC_MTTR:
5413
        check_insn(env, ctx, ASE_MT);
5414
        gen_mttr(env, ctx, rd, rt, (ctx->opcode >> 5) & 1,
5415 5416 5417
                 ctx->opcode & 0x7, (ctx->opcode >> 4) & 1);
        opn = "mttr";
        break;
B
bellard 已提交
5418 5419
    case OPC_TLBWI:
        opn = "tlbwi";
5420
        if (!env->tlb->helper_tlbwi)
5421
            goto die;
P
pbrook 已提交
5422
        gen_helper_tlbwi();
B
bellard 已提交
5423 5424 5425
        break;
    case OPC_TLBWR:
        opn = "tlbwr";
5426
        if (!env->tlb->helper_tlbwr)
5427
            goto die;
P
pbrook 已提交
5428
        gen_helper_tlbwr();
B
bellard 已提交
5429 5430 5431
        break;
    case OPC_TLBP:
        opn = "tlbp";
5432
        if (!env->tlb->helper_tlbp)
5433
            goto die;
P
pbrook 已提交
5434
        gen_helper_tlbp();
B
bellard 已提交
5435 5436 5437
        break;
    case OPC_TLBR:
        opn = "tlbr";
5438
        if (!env->tlb->helper_tlbr)
5439
            goto die;
P
pbrook 已提交
5440
        gen_helper_tlbr();
B
bellard 已提交
5441 5442 5443
        break;
    case OPC_ERET:
        opn = "eret";
5444
        check_insn(env, ctx, ISA_MIPS2);
5445
        save_cpu_state(ctx, 1);
P
pbrook 已提交
5446
        gen_helper_eret();
B
bellard 已提交
5447 5448 5449 5450
        ctx->bstate = BS_EXCP;
        break;
    case OPC_DERET:
        opn = "deret";
5451
        check_insn(env, ctx, ISA_MIPS32);
B
bellard 已提交
5452
        if (!(ctx->hflags & MIPS_HFLAG_DM)) {
5453
            MIPS_INVAL(opn);
B
bellard 已提交
5454 5455
            generate_exception(ctx, EXCP_RI);
        } else {
5456
            save_cpu_state(ctx, 1);
P
pbrook 已提交
5457
            gen_helper_deret();
B
bellard 已提交
5458 5459 5460
            ctx->bstate = BS_EXCP;
        }
        break;
B
bellard 已提交
5461 5462
    case OPC_WAIT:
        opn = "wait";
5463
        check_insn(env, ctx, ISA_MIPS3 | ISA_MIPS32);
B
bellard 已提交
5464 5465 5466 5467
        /* If we get an exception, we want to restart at next instruction */
        ctx->pc += 4;
        save_cpu_state(ctx, 1);
        ctx->pc -= 4;
P
pbrook 已提交
5468
        gen_helper_wait();
B
bellard 已提交
5469 5470
        ctx->bstate = BS_EXCP;
        break;
B
bellard 已提交
5471
    default:
5472
 die:
5473
        MIPS_INVAL(opn);
B
bellard 已提交
5474 5475 5476 5477 5478
        generate_exception(ctx, EXCP_RI);
        return;
    }
    MIPS_DEBUG("%s %s %d", opn, regnames[rt], rd);
}
5479
#endif /* !CONFIG_USER_ONLY */
B
bellard 已提交
5480

B
bellard 已提交
5481
/* CP1 Branches (before delay slot) */
5482
static void gen_compute_branch1 (CPUState *env, DisasContext *ctx, uint32_t op,
5483
                                 int32_t cc, int32_t offset)
B
bellard 已提交
5484 5485
{
    target_ulong btarget;
5486
    const char *opn = "cp1 cond branch";
P
pbrook 已提交
5487
    TCGv_i32 t0 = tcg_temp_new_i32();
B
bellard 已提交
5488

5489 5490 5491
    if (cc != 0)
        check_insn(env, ctx, ISA_MIPS4 | ISA_MIPS32);

B
bellard 已提交
5492 5493
    btarget = ctx->pc + 4 + offset;

5494 5495
    switch (op) {
    case OPC_BC1F:
5496 5497 5498 5499
        tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
        tcg_gen_not_i32(t0, t0);
        tcg_gen_andi_i32(t0, t0, 1);
        tcg_gen_extu_i32_tl(bcond, t0);
5500
        opn = "bc1f";
B
bellard 已提交
5501
        goto not_likely;
5502
    case OPC_BC1FL:
5503 5504 5505 5506
        tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
        tcg_gen_not_i32(t0, t0);
        tcg_gen_andi_i32(t0, t0, 1);
        tcg_gen_extu_i32_tl(bcond, t0);
5507
        opn = "bc1fl";
B
bellard 已提交
5508
        goto likely;
5509
    case OPC_BC1T:
5510 5511 5512
        tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
        tcg_gen_andi_i32(t0, t0, 1);
        tcg_gen_extu_i32_tl(bcond, t0);
5513
        opn = "bc1t";
5514
        goto not_likely;
5515
    case OPC_BC1TL:
5516 5517 5518
        tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
        tcg_gen_andi_i32(t0, t0, 1);
        tcg_gen_extu_i32_tl(bcond, t0);
5519
        opn = "bc1tl";
B
bellard 已提交
5520 5521 5522
    likely:
        ctx->hflags |= MIPS_HFLAG_BL;
        break;
5523
    case OPC_BC1FANY2:
5524
        {
5525 5526 5527 5528 5529 5530 5531 5532
            TCGv_i32 t1 = tcg_temp_new_i32();
            tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
            tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+1));
            tcg_gen_or_i32(t0, t0, t1);
            tcg_temp_free_i32(t1);
            tcg_gen_not_i32(t0, t0);
            tcg_gen_andi_i32(t0, t0, 1);
            tcg_gen_extu_i32_tl(bcond, t0);
5533
        }
5534
        opn = "bc1any2f";
5535 5536
        goto not_likely;
    case OPC_BC1TANY2:
5537
        {
5538 5539 5540 5541 5542 5543 5544
            TCGv_i32 t1 = tcg_temp_new_i32();
            tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
            tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+1));
            tcg_gen_or_i32(t0, t0, t1);
            tcg_temp_free_i32(t1);
            tcg_gen_andi_i32(t0, t0, 1);
            tcg_gen_extu_i32_tl(bcond, t0);
5545
        }
5546
        opn = "bc1any2t";
5547 5548
        goto not_likely;
    case OPC_BC1FANY4:
5549
        {
5550 5551 5552 5553 5554 5555 5556 5557 5558 5559 5560 5561
            TCGv_i32 t1 = tcg_temp_new_i32();
            tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
            tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+1));
            tcg_gen_or_i32(t0, t0, t1);
            tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+2));
            tcg_gen_or_i32(t0, t0, t1);
            tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+3));
            tcg_gen_or_i32(t0, t0, t1);
            tcg_temp_free_i32(t1);
            tcg_gen_not_i32(t0, t0);
            tcg_gen_andi_i32(t0, t0, 1);
            tcg_gen_extu_i32_tl(bcond, t0);
5562
        }
5563
        opn = "bc1any4f";
5564 5565
        goto not_likely;
    case OPC_BC1TANY4:
5566
        {
5567 5568 5569 5570 5571 5572 5573 5574 5575 5576 5577
            TCGv_i32 t1 = tcg_temp_new_i32();
            tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
            tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+1));
            tcg_gen_or_i32(t0, t0, t1);
            tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+2));
            tcg_gen_or_i32(t0, t0, t1);
            tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+3));
            tcg_gen_or_i32(t0, t0, t1);
            tcg_temp_free_i32(t1);
            tcg_gen_andi_i32(t0, t0, 1);
            tcg_gen_extu_i32_tl(bcond, t0);
5578
        }
5579
        opn = "bc1any4t";
5580 5581 5582 5583
    not_likely:
        ctx->hflags |= MIPS_HFLAG_BC;
        break;
    default:
5584
        MIPS_INVAL(opn);
5585
        generate_exception (ctx, EXCP_RI);
5586
        goto out;
B
bellard 已提交
5587
    }
5588
    MIPS_DEBUG("%s: cond %02x target " TARGET_FMT_lx, opn,
B
bellard 已提交
5589 5590
               ctx->hflags, btarget);
    ctx->btarget = btarget;
5591 5592

 out:
P
pbrook 已提交
5593
    tcg_temp_free_i32(t0);
B
bellard 已提交
5594 5595
}

B
bellard 已提交
5596
/* Coprocessor 1 (FPU) */
5597 5598 5599

#define FOP(func, fmt) (((fmt) << 21) | (func))

5600
static void gen_cp1 (DisasContext *ctx, uint32_t opc, int rt, int fs)
B
bellard 已提交
5601
{
5602
    const char *opn = "cp1 move";
P
pbrook 已提交
5603
    TCGv t0 = tcg_temp_local_new();
B
bellard 已提交
5604 5605 5606

    switch (opc) {
    case OPC_MFC1:
5607
        {
P
pbrook 已提交
5608
            TCGv_i32 fp0 = tcg_temp_new_i32();
5609 5610 5611

            gen_load_fpr32(fp0, fs);
            tcg_gen_ext_i32_tl(t0, fp0);
P
pbrook 已提交
5612
            tcg_temp_free_i32(fp0);
A
aurel32 已提交
5613
        }
5614
        gen_store_gpr(t0, rt);
B
bellard 已提交
5615 5616 5617
        opn = "mfc1";
        break;
    case OPC_MTC1:
5618
        gen_load_gpr(t0, rt);
5619
        {
P
pbrook 已提交
5620
            TCGv_i32 fp0 = tcg_temp_new_i32();
5621 5622 5623

            tcg_gen_trunc_tl_i32(fp0, t0);
            gen_store_fpr32(fp0, fs);
P
pbrook 已提交
5624
            tcg_temp_free_i32(fp0);
A
aurel32 已提交
5625
        }
B
bellard 已提交
5626 5627 5628
        opn = "mtc1";
        break;
    case OPC_CFC1:
P
pbrook 已提交
5629
        gen_helper_1i(cfc1, t0, fs);
5630
        gen_store_gpr(t0, rt);
B
bellard 已提交
5631 5632 5633
        opn = "cfc1";
        break;
    case OPC_CTC1:
5634
        gen_load_gpr(t0, rt);
P
pbrook 已提交
5635
        gen_helper_1i(ctc1, t0, fs);
B
bellard 已提交
5636 5637
        opn = "ctc1";
        break;
T
ths 已提交
5638
    case OPC_DMFC1:
5639
        {
P
pbrook 已提交
5640
            TCGv_i64 fp0 = tcg_temp_new_i64();
5641 5642

            gen_load_fpr64(ctx, fp0, fs);
P
pbrook 已提交
5643 5644
            tcg_gen_trunc_i64_tl(t0, fp0);
            tcg_temp_free_i64(fp0);
A
aurel32 已提交
5645
        }
5646
        gen_store_gpr(t0, rt);
5647 5648
        opn = "dmfc1";
        break;
T
ths 已提交
5649
    case OPC_DMTC1:
5650
        gen_load_gpr(t0, rt);
5651
        {
P
pbrook 已提交
5652
            TCGv_i64 fp0 = tcg_temp_new_i64();
5653

P
pbrook 已提交
5654
            tcg_gen_extu_tl_i64(fp0, t0);
5655
            gen_store_fpr64(ctx, fp0, fs);
P
pbrook 已提交
5656
            tcg_temp_free_i64(fp0);
A
aurel32 已提交
5657
        }
5658 5659 5660
        opn = "dmtc1";
        break;
    case OPC_MFHC1:
5661
        {
P
pbrook 已提交
5662
            TCGv_i32 fp0 = tcg_temp_new_i32();
5663 5664 5665

            gen_load_fpr32h(fp0, fs);
            tcg_gen_ext_i32_tl(t0, fp0);
P
pbrook 已提交
5666
            tcg_temp_free_i32(fp0);
A
aurel32 已提交
5667
        }
5668
        gen_store_gpr(t0, rt);
5669 5670 5671
        opn = "mfhc1";
        break;
    case OPC_MTHC1:
5672
        gen_load_gpr(t0, rt);
5673
        {
P
pbrook 已提交
5674
            TCGv_i32 fp0 = tcg_temp_new_i32();
5675 5676 5677

            tcg_gen_trunc_tl_i32(fp0, t0);
            gen_store_fpr32h(fp0, fs);
P
pbrook 已提交
5678
            tcg_temp_free_i32(fp0);
A
aurel32 已提交
5679
        }
5680 5681
        opn = "mthc1";
        break;
B
bellard 已提交
5682
    default:
5683
        MIPS_INVAL(opn);
5684
        generate_exception (ctx, EXCP_RI);
5685
        goto out;
B
bellard 已提交
5686 5687
    }
    MIPS_DEBUG("%s %s %s", opn, regnames[rt], fregnames[fs]);
5688 5689 5690

 out:
    tcg_temp_free(t0);
B
bellard 已提交
5691 5692
}

5693 5694
static void gen_movci (DisasContext *ctx, int rd, int rs, int cc, int tf)
{
A
aurel32 已提交
5695
    int l1;
T
ths 已提交
5696
    TCGCond cond;
A
aurel32 已提交
5697 5698 5699 5700 5701 5702
    TCGv_i32 t0;

    if (rd == 0) {
        /* Treat as NOP. */
        return;
    }
B
bellard 已提交
5703

T
ths 已提交
5704 5705
    if (tf)
        cond = TCG_COND_EQ;
5706 5707 5708
    else
        cond = TCG_COND_NE;

A
aurel32 已提交
5709 5710 5711 5712 5713 5714 5715 5716 5717
    l1 = gen_new_label();
    t0 = tcg_temp_new_i32();
    tcg_gen_andi_i32(t0, fpu_fcr31, get_fp_bit(cc));
    tcg_gen_brcondi_i32(cond, t0, 0, l1);
    if (rs == 0) {
        tcg_gen_movi_tl(cpu_gpr[rd], 0);
    } else {
        tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
    }
T
ths 已提交
5718
    gen_set_label(l1);
A
aurel32 已提交
5719
    tcg_temp_free_i32(t0);
5720 5721
}

5722
static inline void gen_movcf_s (int fs, int fd, int cc, int tf)
5723 5724
{
    int cond;
A
aurel32 已提交
5725
    TCGv_i32 t0 = tcg_temp_new_i32();
5726 5727 5728 5729 5730 5731 5732
    int l1 = gen_new_label();

    if (tf)
        cond = TCG_COND_EQ;
    else
        cond = TCG_COND_NE;

A
aurel32 已提交
5733 5734 5735 5736
    tcg_gen_andi_i32(t0, fpu_fcr31, get_fp_bit(cc));
    tcg_gen_brcondi_i32(cond, t0, 0, l1);
    gen_load_fpr32(t0, fs);
    gen_store_fpr32(t0, fd);
5737
    gen_set_label(l1);
A
aurel32 已提交
5738
    tcg_temp_free_i32(t0);
5739
}
5740

5741
static inline void gen_movcf_d (DisasContext *ctx, int fs, int fd, int cc, int tf)
5742 5743
{
    int cond;
A
aurel32 已提交
5744 5745
    TCGv_i32 t0 = tcg_temp_new_i32();
    TCGv_i64 fp0;
5746 5747 5748 5749 5750 5751 5752
    int l1 = gen_new_label();

    if (tf)
        cond = TCG_COND_EQ;
    else
        cond = TCG_COND_NE;

A
aurel32 已提交
5753 5754 5755
    tcg_gen_andi_i32(t0, fpu_fcr31, get_fp_bit(cc));
    tcg_gen_brcondi_i32(cond, t0, 0, l1);
    fp0 = tcg_temp_local_new_i64();
A
aurel32 已提交
5756 5757
    gen_load_fpr64(ctx, fp0, fs);
    gen_store_fpr64(ctx, fp0, fd);
P
pbrook 已提交
5758
    tcg_temp_free_i64(fp0);
A
aurel32 已提交
5759 5760
    gen_set_label(l1);
    tcg_temp_free_i32(t0);
5761 5762
}

5763
static inline void gen_movcf_ps (int fs, int fd, int cc, int tf)
5764 5765
{
    int cond;
A
aurel32 已提交
5766
    TCGv_i32 t0 = tcg_temp_new_i32();
5767 5768 5769 5770 5771 5772 5773 5774
    int l1 = gen_new_label();
    int l2 = gen_new_label();

    if (tf)
        cond = TCG_COND_EQ;
    else
        cond = TCG_COND_NE;

A
aurel32 已提交
5775 5776 5777 5778
    tcg_gen_andi_i32(t0, fpu_fcr31, get_fp_bit(cc));
    tcg_gen_brcondi_i32(cond, t0, 0, l1);
    gen_load_fpr32(t0, fs);
    gen_store_fpr32(t0, fd);
5779
    gen_set_label(l1);
A
aurel32 已提交
5780

A
aurel32 已提交
5781 5782 5783 5784
    tcg_gen_andi_i32(t0, fpu_fcr31, get_fp_bit(cc+1));
    tcg_gen_brcondi_i32(cond, t0, 0, l2);
    gen_load_fpr32h(t0, fs);
    gen_store_fpr32h(t0, fd);
5785
    gen_set_label(l2);
A
aurel32 已提交
5786

A
aurel32 已提交
5787
    tcg_temp_free_i32(t0);
5788 5789
}

B
bellard 已提交
5790

5791 5792
static void gen_farith (DisasContext *ctx, uint32_t op1,
                        int ft, int fs, int fd, int cc)
B
bellard 已提交
5793
{
5794
    const char *opn = "farith";
B
bellard 已提交
5795 5796 5797 5798 5799 5800 5801 5802 5803 5804 5805 5806 5807 5808 5809 5810 5811 5812
    const char *condnames[] = {
            "c.f",
            "c.un",
            "c.eq",
            "c.ueq",
            "c.olt",
            "c.ult",
            "c.ole",
            "c.ule",
            "c.sf",
            "c.ngle",
            "c.seq",
            "c.ngl",
            "c.lt",
            "c.nge",
            "c.le",
            "c.ngt",
    };
5813 5814 5815 5816 5817 5818 5819 5820 5821 5822 5823 5824 5825 5826 5827 5828 5829 5830 5831
    const char *condnames_abs[] = {
            "cabs.f",
            "cabs.un",
            "cabs.eq",
            "cabs.ueq",
            "cabs.olt",
            "cabs.ult",
            "cabs.ole",
            "cabs.ule",
            "cabs.sf",
            "cabs.ngle",
            "cabs.seq",
            "cabs.ngl",
            "cabs.lt",
            "cabs.nge",
            "cabs.le",
            "cabs.ngt",
    };
    enum { BINOP, CMPOP, OTHEROP } optype = OTHEROP;
5832 5833
    uint32_t func = ctx->opcode & 0x3f;

B
bellard 已提交
5834
    switch (ctx->opcode & FOP(0x3f, 0x1f)) {
5835
    case FOP(0, 16):
5836
        {
P
pbrook 已提交
5837 5838
            TCGv_i32 fp0 = tcg_temp_new_i32();
            TCGv_i32 fp1 = tcg_temp_new_i32();
5839 5840 5841

            gen_load_fpr32(fp0, fs);
            gen_load_fpr32(fp1, ft);
P
pbrook 已提交
5842 5843
            gen_helper_float_add_s(fp0, fp0, fp1);
            tcg_temp_free_i32(fp1);
5844
            gen_store_fpr32(fp0, fd);
P
pbrook 已提交
5845
            tcg_temp_free_i32(fp0);
5846
        }
5847
        opn = "add.s";
5848
        optype = BINOP;
5849 5850
        break;
    case FOP(1, 16):
5851
        {
P
pbrook 已提交
5852 5853
            TCGv_i32 fp0 = tcg_temp_new_i32();
            TCGv_i32 fp1 = tcg_temp_new_i32();
5854 5855 5856

            gen_load_fpr32(fp0, fs);
            gen_load_fpr32(fp1, ft);
P
pbrook 已提交
5857 5858
            gen_helper_float_sub_s(fp0, fp0, fp1);
            tcg_temp_free_i32(fp1);
5859
            gen_store_fpr32(fp0, fd);
P
pbrook 已提交
5860
            tcg_temp_free_i32(fp0);
5861
        }
5862
        opn = "sub.s";
5863
        optype = BINOP;
5864 5865
        break;
    case FOP(2, 16):
5866
        {
P
pbrook 已提交
5867 5868
            TCGv_i32 fp0 = tcg_temp_new_i32();
            TCGv_i32 fp1 = tcg_temp_new_i32();
5869 5870 5871

            gen_load_fpr32(fp0, fs);
            gen_load_fpr32(fp1, ft);
P
pbrook 已提交
5872 5873
            gen_helper_float_mul_s(fp0, fp0, fp1);
            tcg_temp_free_i32(fp1);
5874
            gen_store_fpr32(fp0, fd);
P
pbrook 已提交
5875
            tcg_temp_free_i32(fp0);
5876
        }
5877
        opn = "mul.s";
5878
        optype = BINOP;
5879 5880
        break;
    case FOP(3, 16):
5881
        {
P
pbrook 已提交
5882 5883
            TCGv_i32 fp0 = tcg_temp_new_i32();
            TCGv_i32 fp1 = tcg_temp_new_i32();
5884 5885 5886

            gen_load_fpr32(fp0, fs);
            gen_load_fpr32(fp1, ft);
P
pbrook 已提交
5887 5888
            gen_helper_float_div_s(fp0, fp0, fp1);
            tcg_temp_free_i32(fp1);
5889
            gen_store_fpr32(fp0, fd);
P
pbrook 已提交
5890
            tcg_temp_free_i32(fp0);
5891
        }
5892
        opn = "div.s";
5893
        optype = BINOP;
5894 5895
        break;
    case FOP(4, 16):
5896
        {
P
pbrook 已提交
5897
            TCGv_i32 fp0 = tcg_temp_new_i32();
5898 5899

            gen_load_fpr32(fp0, fs);
P
pbrook 已提交
5900
            gen_helper_float_sqrt_s(fp0, fp0);
5901
            gen_store_fpr32(fp0, fd);
P
pbrook 已提交
5902
            tcg_temp_free_i32(fp0);
5903
        }
5904 5905 5906
        opn = "sqrt.s";
        break;
    case FOP(5, 16):
5907
        {
P
pbrook 已提交
5908
            TCGv_i32 fp0 = tcg_temp_new_i32();
5909 5910

            gen_load_fpr32(fp0, fs);
P
pbrook 已提交
5911
            gen_helper_float_abs_s(fp0, fp0);
5912
            gen_store_fpr32(fp0, fd);
P
pbrook 已提交
5913
            tcg_temp_free_i32(fp0);
5914
        }
5915 5916 5917
        opn = "abs.s";
        break;
    case FOP(6, 16):
5918
        {
P
pbrook 已提交
5919
            TCGv_i32 fp0 = tcg_temp_new_i32();
5920 5921 5922

            gen_load_fpr32(fp0, fs);
            gen_store_fpr32(fp0, fd);
P
pbrook 已提交
5923
            tcg_temp_free_i32(fp0);
5924
        }
5925 5926 5927
        opn = "mov.s";
        break;
    case FOP(7, 16):
5928
        {
P
pbrook 已提交
5929
            TCGv_i32 fp0 = tcg_temp_new_i32();
5930 5931

            gen_load_fpr32(fp0, fs);
P
pbrook 已提交
5932
            gen_helper_float_chs_s(fp0, fp0);
5933
            gen_store_fpr32(fp0, fd);
P
pbrook 已提交
5934
            tcg_temp_free_i32(fp0);
5935
        }
5936 5937 5938
        opn = "neg.s";
        break;
    case FOP(8, 16):
5939
        check_cp1_64bitmode(ctx);
5940
        {
P
pbrook 已提交
5941 5942
            TCGv_i32 fp32 = tcg_temp_new_i32();
            TCGv_i64 fp64 = tcg_temp_new_i64();
5943 5944

            gen_load_fpr32(fp32, fs);
P
pbrook 已提交
5945 5946
            gen_helper_float_roundl_s(fp64, fp32);
            tcg_temp_free_i32(fp32);
5947
            gen_store_fpr64(ctx, fp64, fd);
P
pbrook 已提交
5948
            tcg_temp_free_i64(fp64);
5949
        }
5950 5951 5952
        opn = "round.l.s";
        break;
    case FOP(9, 16):
5953
        check_cp1_64bitmode(ctx);
5954
        {
P
pbrook 已提交
5955 5956
            TCGv_i32 fp32 = tcg_temp_new_i32();
            TCGv_i64 fp64 = tcg_temp_new_i64();
5957 5958

            gen_load_fpr32(fp32, fs);
P
pbrook 已提交
5959 5960
            gen_helper_float_truncl_s(fp64, fp32);
            tcg_temp_free_i32(fp32);
5961
            gen_store_fpr64(ctx, fp64, fd);
P
pbrook 已提交
5962
            tcg_temp_free_i64(fp64);
5963
        }
5964 5965 5966
        opn = "trunc.l.s";
        break;
    case FOP(10, 16):
5967
        check_cp1_64bitmode(ctx);
5968
        {
P
pbrook 已提交
5969 5970
            TCGv_i32 fp32 = tcg_temp_new_i32();
            TCGv_i64 fp64 = tcg_temp_new_i64();
5971 5972

            gen_load_fpr32(fp32, fs);
P
pbrook 已提交
5973 5974
            gen_helper_float_ceill_s(fp64, fp32);
            tcg_temp_free_i32(fp32);
5975
            gen_store_fpr64(ctx, fp64, fd);
P
pbrook 已提交
5976
            tcg_temp_free_i64(fp64);
5977
        }
5978 5979 5980
        opn = "ceil.l.s";
        break;
    case FOP(11, 16):
5981
        check_cp1_64bitmode(ctx);
5982
        {
P
pbrook 已提交
5983 5984
            TCGv_i32 fp32 = tcg_temp_new_i32();
            TCGv_i64 fp64 = tcg_temp_new_i64();
5985 5986

            gen_load_fpr32(fp32, fs);
P
pbrook 已提交
5987 5988
            gen_helper_float_floorl_s(fp64, fp32);
            tcg_temp_free_i32(fp32);
5989
            gen_store_fpr64(ctx, fp64, fd);
P
pbrook 已提交
5990
            tcg_temp_free_i64(fp64);
5991
        }
5992 5993 5994
        opn = "floor.l.s";
        break;
    case FOP(12, 16):
5995
        {
P
pbrook 已提交
5996
            TCGv_i32 fp0 = tcg_temp_new_i32();
5997 5998

            gen_load_fpr32(fp0, fs);
P
pbrook 已提交
5999
            gen_helper_float_roundw_s(fp0, fp0);
6000
            gen_store_fpr32(fp0, fd);
P
pbrook 已提交
6001
            tcg_temp_free_i32(fp0);
6002
        }
6003 6004 6005
        opn = "round.w.s";
        break;
    case FOP(13, 16):
6006
        {
P
pbrook 已提交
6007
            TCGv_i32 fp0 = tcg_temp_new_i32();
6008 6009

            gen_load_fpr32(fp0, fs);
P
pbrook 已提交
6010
            gen_helper_float_truncw_s(fp0, fp0);
6011
            gen_store_fpr32(fp0, fd);
P
pbrook 已提交
6012
            tcg_temp_free_i32(fp0);
6013
        }
6014 6015 6016
        opn = "trunc.w.s";
        break;
    case FOP(14, 16):
6017
        {
P
pbrook 已提交
6018
            TCGv_i32 fp0 = tcg_temp_new_i32();
6019 6020

            gen_load_fpr32(fp0, fs);
P
pbrook 已提交
6021
            gen_helper_float_ceilw_s(fp0, fp0);
6022
            gen_store_fpr32(fp0, fd);
P
pbrook 已提交
6023
            tcg_temp_free_i32(fp0);
6024
        }
6025 6026 6027
        opn = "ceil.w.s";
        break;
    case FOP(15, 16):
6028
        {
P
pbrook 已提交
6029
            TCGv_i32 fp0 = tcg_temp_new_i32();
6030 6031

            gen_load_fpr32(fp0, fs);
P
pbrook 已提交
6032
            gen_helper_float_floorw_s(fp0, fp0);
6033
            gen_store_fpr32(fp0, fd);
P
pbrook 已提交
6034
            tcg_temp_free_i32(fp0);
6035
        }
6036 6037 6038
        opn = "floor.w.s";
        break;
    case FOP(17, 16):
6039
        gen_movcf_s(fs, fd, (ft >> 2) & 0x7, ft & 0x1);
6040 6041 6042
        opn = "movcf.s";
        break;
    case FOP(18, 16):
6043 6044
        {
            int l1 = gen_new_label();
P
pbrook 已提交
6045 6046
            TCGv t0 = tcg_temp_new();
            TCGv_i32 fp0 = tcg_temp_local_new_i32();
6047

6048 6049
            gen_load_gpr(t0, ft);
            tcg_gen_brcondi_tl(TCG_COND_NE, t0, 0, l1);
6050 6051
            gen_load_fpr32(fp0, fs);
            gen_store_fpr32(fp0, fd);
P
pbrook 已提交
6052
            tcg_temp_free_i32(fp0);
6053
            gen_set_label(l1);
A
aurel32 已提交
6054
            tcg_temp_free(t0);
6055
        }
6056 6057 6058
        opn = "movz.s";
        break;
    case FOP(19, 16):
6059 6060
        {
            int l1 = gen_new_label();
P
pbrook 已提交
6061 6062
            TCGv t0 = tcg_temp_new();
            TCGv_i32 fp0 = tcg_temp_local_new_i32();
6063

6064 6065
            gen_load_gpr(t0, ft);
            tcg_gen_brcondi_tl(TCG_COND_EQ, t0, 0, l1);
6066 6067
            gen_load_fpr32(fp0, fs);
            gen_store_fpr32(fp0, fd);
P
pbrook 已提交
6068
            tcg_temp_free_i32(fp0);
6069
            gen_set_label(l1);
A
aurel32 已提交
6070
            tcg_temp_free(t0);
6071
        }
6072 6073
        opn = "movn.s";
        break;
T
ths 已提交
6074
    case FOP(21, 16):
6075
        check_cop1x(ctx);
6076
        {
P
pbrook 已提交
6077
            TCGv_i32 fp0 = tcg_temp_new_i32();
6078 6079

            gen_load_fpr32(fp0, fs);
P
pbrook 已提交
6080
            gen_helper_float_recip_s(fp0, fp0);
6081
            gen_store_fpr32(fp0, fd);
P
pbrook 已提交
6082
            tcg_temp_free_i32(fp0);
6083
        }
T
ths 已提交
6084 6085 6086
        opn = "recip.s";
        break;
    case FOP(22, 16):
6087
        check_cop1x(ctx);
6088
        {
P
pbrook 已提交
6089
            TCGv_i32 fp0 = tcg_temp_new_i32();
6090 6091

            gen_load_fpr32(fp0, fs);
P
pbrook 已提交
6092
            gen_helper_float_rsqrt_s(fp0, fp0);
6093
            gen_store_fpr32(fp0, fd);
P
pbrook 已提交
6094
            tcg_temp_free_i32(fp0);
6095
        }
T
ths 已提交
6096 6097 6098
        opn = "rsqrt.s";
        break;
    case FOP(28, 16):
6099
        check_cp1_64bitmode(ctx);
6100
        {
P
pbrook 已提交
6101 6102
            TCGv_i32 fp0 = tcg_temp_new_i32();
            TCGv_i32 fp1 = tcg_temp_new_i32();
6103 6104 6105

            gen_load_fpr32(fp0, fs);
            gen_load_fpr32(fp1, fd);
P
pbrook 已提交
6106 6107
            gen_helper_float_recip2_s(fp0, fp0, fp1);
            tcg_temp_free_i32(fp1);
6108
            gen_store_fpr32(fp0, fd);
P
pbrook 已提交
6109
            tcg_temp_free_i32(fp0);
6110
        }
T
ths 已提交
6111 6112 6113
        opn = "recip2.s";
        break;
    case FOP(29, 16):
6114
        check_cp1_64bitmode(ctx);
6115
        {
P
pbrook 已提交
6116
            TCGv_i32 fp0 = tcg_temp_new_i32();
6117 6118

            gen_load_fpr32(fp0, fs);
P
pbrook 已提交
6119
            gen_helper_float_recip1_s(fp0, fp0);
6120
            gen_store_fpr32(fp0, fd);
P
pbrook 已提交
6121
            tcg_temp_free_i32(fp0);
6122
        }
T
ths 已提交
6123 6124 6125
        opn = "recip1.s";
        break;
    case FOP(30, 16):
6126
        check_cp1_64bitmode(ctx);
6127
        {
P
pbrook 已提交
6128
            TCGv_i32 fp0 = tcg_temp_new_i32();
6129 6130

            gen_load_fpr32(fp0, fs);
P
pbrook 已提交
6131
            gen_helper_float_rsqrt1_s(fp0, fp0);
6132
            gen_store_fpr32(fp0, fd);
P
pbrook 已提交
6133
            tcg_temp_free_i32(fp0);
6134
        }
T
ths 已提交
6135 6136 6137
        opn = "rsqrt1.s";
        break;
    case FOP(31, 16):
6138
        check_cp1_64bitmode(ctx);
6139
        {
P
pbrook 已提交
6140 6141
            TCGv_i32 fp0 = tcg_temp_new_i32();
            TCGv_i32 fp1 = tcg_temp_new_i32();
6142 6143 6144

            gen_load_fpr32(fp0, fs);
            gen_load_fpr32(fp1, ft);
P
pbrook 已提交
6145 6146
            gen_helper_float_rsqrt2_s(fp0, fp0, fp1);
            tcg_temp_free_i32(fp1);
6147
            gen_store_fpr32(fp0, fd);
P
pbrook 已提交
6148
            tcg_temp_free_i32(fp0);
6149
        }
T
ths 已提交
6150 6151
        opn = "rsqrt2.s";
        break;
6152
    case FOP(33, 16):
6153
        check_cp1_registers(ctx, fd);
6154
        {
P
pbrook 已提交
6155 6156
            TCGv_i32 fp32 = tcg_temp_new_i32();
            TCGv_i64 fp64 = tcg_temp_new_i64();
6157 6158

            gen_load_fpr32(fp32, fs);
P
pbrook 已提交
6159 6160
            gen_helper_float_cvtd_s(fp64, fp32);
            tcg_temp_free_i32(fp32);
6161
            gen_store_fpr64(ctx, fp64, fd);
P
pbrook 已提交
6162
            tcg_temp_free_i64(fp64);
6163
        }
6164 6165 6166
        opn = "cvt.d.s";
        break;
    case FOP(36, 16):
6167
        {
P
pbrook 已提交
6168
            TCGv_i32 fp0 = tcg_temp_new_i32();
6169 6170

            gen_load_fpr32(fp0, fs);
P
pbrook 已提交
6171
            gen_helper_float_cvtw_s(fp0, fp0);
6172
            gen_store_fpr32(fp0, fd);
P
pbrook 已提交
6173
            tcg_temp_free_i32(fp0);
6174
        }
6175 6176 6177
        opn = "cvt.w.s";
        break;
    case FOP(37, 16):
6178
        check_cp1_64bitmode(ctx);
6179
        {
P
pbrook 已提交
6180 6181
            TCGv_i32 fp32 = tcg_temp_new_i32();
            TCGv_i64 fp64 = tcg_temp_new_i64();
6182 6183

            gen_load_fpr32(fp32, fs);
P
pbrook 已提交
6184 6185
            gen_helper_float_cvtl_s(fp64, fp32);
            tcg_temp_free_i32(fp32);
6186
            gen_store_fpr64(ctx, fp64, fd);
P
pbrook 已提交
6187
            tcg_temp_free_i64(fp64);
6188
        }
6189 6190 6191
        opn = "cvt.l.s";
        break;
    case FOP(38, 16):
6192
        check_cp1_64bitmode(ctx);
6193
        {
P
pbrook 已提交
6194 6195 6196
            TCGv_i64 fp64 = tcg_temp_new_i64();
            TCGv_i32 fp32_0 = tcg_temp_new_i32();
            TCGv_i32 fp32_1 = tcg_temp_new_i32();
6197 6198 6199

            gen_load_fpr32(fp32_0, fs);
            gen_load_fpr32(fp32_1, ft);
P
pbrook 已提交
6200
            tcg_gen_concat_i32_i64(fp64, fp32_0, fp32_1);
P
pbrook 已提交
6201 6202
            tcg_temp_free_i32(fp32_1);
            tcg_temp_free_i32(fp32_0);
P
pbrook 已提交
6203
            gen_store_fpr64(ctx, fp64, fd);
P
pbrook 已提交
6204
            tcg_temp_free_i64(fp64);
6205
        }
6206 6207 6208 6209 6210 6211 6212 6213 6214 6215 6216 6217 6218 6219 6220 6221 6222 6223
        opn = "cvt.ps.s";
        break;
    case FOP(48, 16):
    case FOP(49, 16):
    case FOP(50, 16):
    case FOP(51, 16):
    case FOP(52, 16):
    case FOP(53, 16):
    case FOP(54, 16):
    case FOP(55, 16):
    case FOP(56, 16):
    case FOP(57, 16):
    case FOP(58, 16):
    case FOP(59, 16):
    case FOP(60, 16):
    case FOP(61, 16):
    case FOP(62, 16):
    case FOP(63, 16):
6224
        {
P
pbrook 已提交
6225 6226
            TCGv_i32 fp0 = tcg_temp_new_i32();
            TCGv_i32 fp1 = tcg_temp_new_i32();
6227 6228 6229 6230 6231 6232 6233 6234 6235 6236 6237

            gen_load_fpr32(fp0, fs);
            gen_load_fpr32(fp1, ft);
            if (ctx->opcode & (1 << 6)) {
                check_cop1x(ctx);
                gen_cmpabs_s(func-48, fp0, fp1, cc);
                opn = condnames_abs[func-48];
            } else {
                gen_cmp_s(func-48, fp0, fp1, cc);
                opn = condnames[func-48];
            }
P
pbrook 已提交
6238 6239
            tcg_temp_free_i32(fp0);
            tcg_temp_free_i32(fp1);
6240
        }
6241
        break;
B
bellard 已提交
6242
    case FOP(0, 17):
6243
        check_cp1_registers(ctx, fs | ft | fd);
6244
        {
P
pbrook 已提交
6245 6246
            TCGv_i64 fp0 = tcg_temp_new_i64();
            TCGv_i64 fp1 = tcg_temp_new_i64();
6247 6248 6249

            gen_load_fpr64(ctx, fp0, fs);
            gen_load_fpr64(ctx, fp1, ft);
P
pbrook 已提交
6250 6251
            gen_helper_float_add_d(fp0, fp0, fp1);
            tcg_temp_free_i64(fp1);
6252
            gen_store_fpr64(ctx, fp0, fd);
P
pbrook 已提交
6253
            tcg_temp_free_i64(fp0);
6254
        }
B
bellard 已提交
6255
        opn = "add.d";
6256
        optype = BINOP;
B
bellard 已提交
6257 6258
        break;
    case FOP(1, 17):
6259
        check_cp1_registers(ctx, fs | ft | fd);
6260
        {
P
pbrook 已提交
6261 6262
            TCGv_i64 fp0 = tcg_temp_new_i64();
            TCGv_i64 fp1 = tcg_temp_new_i64();
6263 6264 6265

            gen_load_fpr64(ctx, fp0, fs);
            gen_load_fpr64(ctx, fp1, ft);
P
pbrook 已提交
6266 6267
            gen_helper_float_sub_d(fp0, fp0, fp1);
            tcg_temp_free_i64(fp1);
6268
            gen_store_fpr64(ctx, fp0, fd);
P
pbrook 已提交
6269
            tcg_temp_free_i64(fp0);
6270
        }
B
bellard 已提交
6271
        opn = "sub.d";
6272
        optype = BINOP;
B
bellard 已提交
6273 6274
        break;
    case FOP(2, 17):
6275
        check_cp1_registers(ctx, fs | ft | fd);
6276
        {
P
pbrook 已提交
6277 6278
            TCGv_i64 fp0 = tcg_temp_new_i64();
            TCGv_i64 fp1 = tcg_temp_new_i64();
6279 6280 6281

            gen_load_fpr64(ctx, fp0, fs);
            gen_load_fpr64(ctx, fp1, ft);
P
pbrook 已提交
6282 6283
            gen_helper_float_mul_d(fp0, fp0, fp1);
            tcg_temp_free_i64(fp1);
6284
            gen_store_fpr64(ctx, fp0, fd);
P
pbrook 已提交
6285
            tcg_temp_free_i64(fp0);
6286
        }
B
bellard 已提交
6287
        opn = "mul.d";
6288
        optype = BINOP;
B
bellard 已提交
6289 6290
        break;
    case FOP(3, 17):
6291
        check_cp1_registers(ctx, fs | ft | fd);
6292
        {
P
pbrook 已提交
6293 6294
            TCGv_i64 fp0 = tcg_temp_new_i64();
            TCGv_i64 fp1 = tcg_temp_new_i64();
6295 6296 6297

            gen_load_fpr64(ctx, fp0, fs);
            gen_load_fpr64(ctx, fp1, ft);
P
pbrook 已提交
6298 6299
            gen_helper_float_div_d(fp0, fp0, fp1);
            tcg_temp_free_i64(fp1);
6300
            gen_store_fpr64(ctx, fp0, fd);
P
pbrook 已提交
6301
            tcg_temp_free_i64(fp0);
6302
        }
B
bellard 已提交
6303
        opn = "div.d";
6304
        optype = BINOP;
B
bellard 已提交
6305 6306
        break;
    case FOP(4, 17):
6307
        check_cp1_registers(ctx, fs | fd);
6308
        {
P
pbrook 已提交
6309
            TCGv_i64 fp0 = tcg_temp_new_i64();
6310 6311

            gen_load_fpr64(ctx, fp0, fs);
P
pbrook 已提交
6312
            gen_helper_float_sqrt_d(fp0, fp0);
6313
            gen_store_fpr64(ctx, fp0, fd);
P
pbrook 已提交
6314
            tcg_temp_free_i64(fp0);
6315
        }
B
bellard 已提交
6316 6317 6318
        opn = "sqrt.d";
        break;
    case FOP(5, 17):
6319
        check_cp1_registers(ctx, fs | fd);
6320
        {
P
pbrook 已提交
6321
            TCGv_i64 fp0 = tcg_temp_new_i64();
6322 6323

            gen_load_fpr64(ctx, fp0, fs);
P
pbrook 已提交
6324
            gen_helper_float_abs_d(fp0, fp0);
6325
            gen_store_fpr64(ctx, fp0, fd);
P
pbrook 已提交
6326
            tcg_temp_free_i64(fp0);
6327
        }
B
bellard 已提交
6328 6329 6330
        opn = "abs.d";
        break;
    case FOP(6, 17):
6331
        check_cp1_registers(ctx, fs | fd);
6332
        {
P
pbrook 已提交
6333
            TCGv_i64 fp0 = tcg_temp_new_i64();
6334 6335 6336

            gen_load_fpr64(ctx, fp0, fs);
            gen_store_fpr64(ctx, fp0, fd);
P
pbrook 已提交
6337
            tcg_temp_free_i64(fp0);
6338
        }
B
bellard 已提交
6339 6340 6341
        opn = "mov.d";
        break;
    case FOP(7, 17):
6342
        check_cp1_registers(ctx, fs | fd);
6343
        {
P
pbrook 已提交
6344
            TCGv_i64 fp0 = tcg_temp_new_i64();
6345 6346

            gen_load_fpr64(ctx, fp0, fs);
P
pbrook 已提交
6347
            gen_helper_float_chs_d(fp0, fp0);
6348
            gen_store_fpr64(ctx, fp0, fd);
P
pbrook 已提交
6349
            tcg_temp_free_i64(fp0);
6350
        }
B
bellard 已提交
6351 6352
        opn = "neg.d";
        break;
6353
    case FOP(8, 17):
6354
        check_cp1_64bitmode(ctx);
6355
        {
P
pbrook 已提交
6356
            TCGv_i64 fp0 = tcg_temp_new_i64();
6357 6358

            gen_load_fpr64(ctx, fp0, fs);
P
pbrook 已提交
6359
            gen_helper_float_roundl_d(fp0, fp0);
6360
            gen_store_fpr64(ctx, fp0, fd);
P
pbrook 已提交
6361
            tcg_temp_free_i64(fp0);
6362
        }
6363 6364 6365
        opn = "round.l.d";
        break;
    case FOP(9, 17):
6366
        check_cp1_64bitmode(ctx);
6367
        {
P
pbrook 已提交
6368
            TCGv_i64 fp0 = tcg_temp_new_i64();
6369 6370

            gen_load_fpr64(ctx, fp0, fs);
P
pbrook 已提交
6371
            gen_helper_float_truncl_d(fp0, fp0);
6372
            gen_store_fpr64(ctx, fp0, fd);
P
pbrook 已提交
6373
            tcg_temp_free_i64(fp0);
6374
        }
6375 6376 6377
        opn = "trunc.l.d";
        break;
    case FOP(10, 17):
6378
        check_cp1_64bitmode(ctx);
6379
        {
P
pbrook 已提交
6380
            TCGv_i64 fp0 = tcg_temp_new_i64();
6381 6382

            gen_load_fpr64(ctx, fp0, fs);
P
pbrook 已提交
6383
            gen_helper_float_ceill_d(fp0, fp0);
6384
            gen_store_fpr64(ctx, fp0, fd);
P
pbrook 已提交
6385
            tcg_temp_free_i64(fp0);
6386
        }
6387 6388 6389
        opn = "ceil.l.d";
        break;
    case FOP(11, 17):
6390
        check_cp1_64bitmode(ctx);
6391
        {
P
pbrook 已提交
6392
            TCGv_i64 fp0 = tcg_temp_new_i64();
6393 6394

            gen_load_fpr64(ctx, fp0, fs);
P
pbrook 已提交
6395
            gen_helper_float_floorl_d(fp0, fp0);
6396
            gen_store_fpr64(ctx, fp0, fd);
P
pbrook 已提交
6397
            tcg_temp_free_i64(fp0);
6398
        }
6399 6400
        opn = "floor.l.d";
        break;
B
bellard 已提交
6401
    case FOP(12, 17):
6402
        check_cp1_registers(ctx, fs);
6403
        {
P
pbrook 已提交
6404 6405
            TCGv_i32 fp32 = tcg_temp_new_i32();
            TCGv_i64 fp64 = tcg_temp_new_i64();
6406 6407

            gen_load_fpr64(ctx, fp64, fs);
P
pbrook 已提交
6408 6409
            gen_helper_float_roundw_d(fp32, fp64);
            tcg_temp_free_i64(fp64);
6410
            gen_store_fpr32(fp32, fd);
P
pbrook 已提交
6411
            tcg_temp_free_i32(fp32);
6412
        }
B
bellard 已提交
6413 6414 6415
        opn = "round.w.d";
        break;
    case FOP(13, 17):
6416
        check_cp1_registers(ctx, fs);
6417
        {
P
pbrook 已提交
6418 6419
            TCGv_i32 fp32 = tcg_temp_new_i32();
            TCGv_i64 fp64 = tcg_temp_new_i64();
6420 6421

            gen_load_fpr64(ctx, fp64, fs);
P
pbrook 已提交
6422 6423
            gen_helper_float_truncw_d(fp32, fp64);
            tcg_temp_free_i64(fp64);
6424
            gen_store_fpr32(fp32, fd);
P
pbrook 已提交
6425
            tcg_temp_free_i32(fp32);
6426
        }
B
bellard 已提交
6427 6428 6429
        opn = "trunc.w.d";
        break;
    case FOP(14, 17):
6430
        check_cp1_registers(ctx, fs);
6431
        {
P
pbrook 已提交
6432 6433
            TCGv_i32 fp32 = tcg_temp_new_i32();
            TCGv_i64 fp64 = tcg_temp_new_i64();
6434 6435

            gen_load_fpr64(ctx, fp64, fs);
P
pbrook 已提交
6436 6437
            gen_helper_float_ceilw_d(fp32, fp64);
            tcg_temp_free_i64(fp64);
6438
            gen_store_fpr32(fp32, fd);
P
pbrook 已提交
6439
            tcg_temp_free_i32(fp32);
6440
        }
B
bellard 已提交
6441 6442 6443
        opn = "ceil.w.d";
        break;
    case FOP(15, 17):
6444
        check_cp1_registers(ctx, fs);
6445
        {
P
pbrook 已提交
6446 6447
            TCGv_i32 fp32 = tcg_temp_new_i32();
            TCGv_i64 fp64 = tcg_temp_new_i64();
6448 6449

            gen_load_fpr64(ctx, fp64, fs);
P
pbrook 已提交
6450 6451
            gen_helper_float_floorw_d(fp32, fp64);
            tcg_temp_free_i64(fp64);
6452
            gen_store_fpr32(fp32, fd);
P
pbrook 已提交
6453
            tcg_temp_free_i32(fp32);
6454
        }
6455
        opn = "floor.w.d";
B
bellard 已提交
6456
        break;
6457
    case FOP(17, 17):
6458
        gen_movcf_d(ctx, fs, fd, (ft >> 2) & 0x7, ft & 0x1);
6459
        opn = "movcf.d";
6460
        break;
6461
    case FOP(18, 17):
6462 6463
        {
            int l1 = gen_new_label();
P
pbrook 已提交
6464 6465
            TCGv t0 = tcg_temp_new();
            TCGv_i64 fp0 = tcg_temp_local_new_i64();
6466

6467 6468
            gen_load_gpr(t0, ft);
            tcg_gen_brcondi_tl(TCG_COND_NE, t0, 0, l1);
6469 6470
            gen_load_fpr64(ctx, fp0, fs);
            gen_store_fpr64(ctx, fp0, fd);
P
pbrook 已提交
6471
            tcg_temp_free_i64(fp0);
6472
            gen_set_label(l1);
A
aurel32 已提交
6473
            tcg_temp_free(t0);
6474
        }
6475 6476 6477
        opn = "movz.d";
        break;
    case FOP(19, 17):
6478 6479
        {
            int l1 = gen_new_label();
P
pbrook 已提交
6480 6481
            TCGv t0 = tcg_temp_new();
            TCGv_i64 fp0 = tcg_temp_local_new_i64();
6482

6483 6484
            gen_load_gpr(t0, ft);
            tcg_gen_brcondi_tl(TCG_COND_EQ, t0, 0, l1);
6485 6486
            gen_load_fpr64(ctx, fp0, fs);
            gen_store_fpr64(ctx, fp0, fd);
P
pbrook 已提交
6487
            tcg_temp_free_i64(fp0);
6488
            gen_set_label(l1);
A
aurel32 已提交
6489
            tcg_temp_free(t0);
6490
        }
6491
        opn = "movn.d";
B
bellard 已提交
6492
        break;
T
ths 已提交
6493
    case FOP(21, 17):
6494
        check_cp1_64bitmode(ctx);
6495
        {
P
pbrook 已提交
6496
            TCGv_i64 fp0 = tcg_temp_new_i64();
6497 6498

            gen_load_fpr64(ctx, fp0, fs);
P
pbrook 已提交
6499
            gen_helper_float_recip_d(fp0, fp0);
6500
            gen_store_fpr64(ctx, fp0, fd);
P
pbrook 已提交
6501
            tcg_temp_free_i64(fp0);
6502
        }
T
ths 已提交
6503 6504 6505
        opn = "recip.d";
        break;
    case FOP(22, 17):
6506
        check_cp1_64bitmode(ctx);
6507
        {
P
pbrook 已提交
6508
            TCGv_i64 fp0 = tcg_temp_new_i64();
6509 6510

            gen_load_fpr64(ctx, fp0, fs);
P
pbrook 已提交
6511
            gen_helper_float_rsqrt_d(fp0, fp0);
6512
            gen_store_fpr64(ctx, fp0, fd);
P
pbrook 已提交
6513
            tcg_temp_free_i64(fp0);
6514
        }
T
ths 已提交
6515 6516 6517
        opn = "rsqrt.d";
        break;
    case FOP(28, 17):
6518
        check_cp1_64bitmode(ctx);
6519
        {
P
pbrook 已提交
6520 6521
            TCGv_i64 fp0 = tcg_temp_new_i64();
            TCGv_i64 fp1 = tcg_temp_new_i64();
6522 6523 6524

            gen_load_fpr64(ctx, fp0, fs);
            gen_load_fpr64(ctx, fp1, ft);
P
pbrook 已提交
6525 6526
            gen_helper_float_recip2_d(fp0, fp0, fp1);
            tcg_temp_free_i64(fp1);
6527
            gen_store_fpr64(ctx, fp0, fd);
P
pbrook 已提交
6528
            tcg_temp_free_i64(fp0);
6529
        }
T
ths 已提交
6530 6531 6532
        opn = "recip2.d";
        break;
    case FOP(29, 17):
6533
        check_cp1_64bitmode(ctx);
6534
        {
P
pbrook 已提交
6535
            TCGv_i64 fp0 = tcg_temp_new_i64();
6536 6537

            gen_load_fpr64(ctx, fp0, fs);
P
pbrook 已提交
6538
            gen_helper_float_recip1_d(fp0, fp0);
6539
            gen_store_fpr64(ctx, fp0, fd);
P
pbrook 已提交
6540
            tcg_temp_free_i64(fp0);
6541
        }
T
ths 已提交
6542 6543 6544
        opn = "recip1.d";
        break;
    case FOP(30, 17):
6545
        check_cp1_64bitmode(ctx);
6546
        {
P
pbrook 已提交
6547
            TCGv_i64 fp0 = tcg_temp_new_i64();
6548 6549

            gen_load_fpr64(ctx, fp0, fs);
P
pbrook 已提交
6550
            gen_helper_float_rsqrt1_d(fp0, fp0);
6551
            gen_store_fpr64(ctx, fp0, fd);
P
pbrook 已提交
6552
            tcg_temp_free_i64(fp0);
6553
        }
T
ths 已提交
6554 6555 6556
        opn = "rsqrt1.d";
        break;
    case FOP(31, 17):
6557
        check_cp1_64bitmode(ctx);
6558
        {
P
pbrook 已提交
6559 6560
            TCGv_i64 fp0 = tcg_temp_new_i64();
            TCGv_i64 fp1 = tcg_temp_new_i64();
6561 6562 6563

            gen_load_fpr64(ctx, fp0, fs);
            gen_load_fpr64(ctx, fp1, ft);
P
pbrook 已提交
6564 6565
            gen_helper_float_rsqrt2_d(fp0, fp0, fp1);
            tcg_temp_free_i64(fp1);
6566
            gen_store_fpr64(ctx, fp0, fd);
P
pbrook 已提交
6567
            tcg_temp_free_i64(fp0);
6568
        }
T
ths 已提交
6569 6570
        opn = "rsqrt2.d";
        break;
B
bellard 已提交
6571 6572 6573 6574 6575 6576 6577 6578 6579 6580 6581 6582 6583 6584 6585 6586
    case FOP(48, 17):
    case FOP(49, 17):
    case FOP(50, 17):
    case FOP(51, 17):
    case FOP(52, 17):
    case FOP(53, 17):
    case FOP(54, 17):
    case FOP(55, 17):
    case FOP(56, 17):
    case FOP(57, 17):
    case FOP(58, 17):
    case FOP(59, 17):
    case FOP(60, 17):
    case FOP(61, 17):
    case FOP(62, 17):
    case FOP(63, 17):
6587
        {
P
pbrook 已提交
6588 6589
            TCGv_i64 fp0 = tcg_temp_new_i64();
            TCGv_i64 fp1 = tcg_temp_new_i64();
6590 6591 6592 6593 6594 6595 6596 6597 6598 6599 6600 6601 6602

            gen_load_fpr64(ctx, fp0, fs);
            gen_load_fpr64(ctx, fp1, ft);
            if (ctx->opcode & (1 << 6)) {
                check_cop1x(ctx);
                check_cp1_registers(ctx, fs | ft);
                gen_cmpabs_d(func-48, fp0, fp1, cc);
                opn = condnames_abs[func-48];
            } else {
                check_cp1_registers(ctx, fs | ft);
                gen_cmp_d(func-48, fp0, fp1, cc);
                opn = condnames[func-48];
            }
P
pbrook 已提交
6603 6604
            tcg_temp_free_i64(fp0);
            tcg_temp_free_i64(fp1);
6605
        }
B
bellard 已提交
6606
        break;
6607
    case FOP(32, 17):
6608
        check_cp1_registers(ctx, fs);
6609
        {
P
pbrook 已提交
6610 6611
            TCGv_i32 fp32 = tcg_temp_new_i32();
            TCGv_i64 fp64 = tcg_temp_new_i64();
6612 6613

            gen_load_fpr64(ctx, fp64, fs);
P
pbrook 已提交
6614 6615
            gen_helper_float_cvts_d(fp32, fp64);
            tcg_temp_free_i64(fp64);
6616
            gen_store_fpr32(fp32, fd);
P
pbrook 已提交
6617
            tcg_temp_free_i32(fp32);
6618
        }
6619 6620 6621
        opn = "cvt.s.d";
        break;
    case FOP(36, 17):
6622
        check_cp1_registers(ctx, fs);
6623
        {
P
pbrook 已提交
6624 6625
            TCGv_i32 fp32 = tcg_temp_new_i32();
            TCGv_i64 fp64 = tcg_temp_new_i64();
6626 6627

            gen_load_fpr64(ctx, fp64, fs);
P
pbrook 已提交
6628 6629
            gen_helper_float_cvtw_d(fp32, fp64);
            tcg_temp_free_i64(fp64);
6630
            gen_store_fpr32(fp32, fd);
P
pbrook 已提交
6631
            tcg_temp_free_i32(fp32);
6632
        }
6633 6634 6635
        opn = "cvt.w.d";
        break;
    case FOP(37, 17):
6636
        check_cp1_64bitmode(ctx);
6637
        {
P
pbrook 已提交
6638
            TCGv_i64 fp0 = tcg_temp_new_i64();
6639 6640

            gen_load_fpr64(ctx, fp0, fs);
P
pbrook 已提交
6641
            gen_helper_float_cvtl_d(fp0, fp0);
6642
            gen_store_fpr64(ctx, fp0, fd);
P
pbrook 已提交
6643
            tcg_temp_free_i64(fp0);
6644
        }
6645 6646 6647
        opn = "cvt.l.d";
        break;
    case FOP(32, 20):
6648
        {
P
pbrook 已提交
6649
            TCGv_i32 fp0 = tcg_temp_new_i32();
6650 6651

            gen_load_fpr32(fp0, fs);
P
pbrook 已提交
6652
            gen_helper_float_cvts_w(fp0, fp0);
6653
            gen_store_fpr32(fp0, fd);
P
pbrook 已提交
6654
            tcg_temp_free_i32(fp0);
6655
        }
6656
        opn = "cvt.s.w";
B
bellard 已提交
6657
        break;
6658
    case FOP(33, 20):
6659
        check_cp1_registers(ctx, fd);
6660
        {
P
pbrook 已提交
6661 6662
            TCGv_i32 fp32 = tcg_temp_new_i32();
            TCGv_i64 fp64 = tcg_temp_new_i64();
6663 6664

            gen_load_fpr32(fp32, fs);
P
pbrook 已提交
6665 6666
            gen_helper_float_cvtd_w(fp64, fp32);
            tcg_temp_free_i32(fp32);
6667
            gen_store_fpr64(ctx, fp64, fd);
P
pbrook 已提交
6668
            tcg_temp_free_i64(fp64);
6669
        }
6670 6671 6672
        opn = "cvt.d.w";
        break;
    case FOP(32, 21):
6673
        check_cp1_64bitmode(ctx);
6674
        {
P
pbrook 已提交
6675 6676
            TCGv_i32 fp32 = tcg_temp_new_i32();
            TCGv_i64 fp64 = tcg_temp_new_i64();
6677 6678

            gen_load_fpr64(ctx, fp64, fs);
P
pbrook 已提交
6679 6680
            gen_helper_float_cvts_l(fp32, fp64);
            tcg_temp_free_i64(fp64);
6681
            gen_store_fpr32(fp32, fd);
P
pbrook 已提交
6682
            tcg_temp_free_i32(fp32);
6683
        }
6684 6685 6686
        opn = "cvt.s.l";
        break;
    case FOP(33, 21):
6687
        check_cp1_64bitmode(ctx);
6688
        {
P
pbrook 已提交
6689
            TCGv_i64 fp0 = tcg_temp_new_i64();
6690 6691

            gen_load_fpr64(ctx, fp0, fs);
P
pbrook 已提交
6692
            gen_helper_float_cvtd_l(fp0, fp0);
6693
            gen_store_fpr64(ctx, fp0, fd);
P
pbrook 已提交
6694
            tcg_temp_free_i64(fp0);
6695
        }
6696 6697 6698
        opn = "cvt.d.l";
        break;
    case FOP(38, 20):
6699
        check_cp1_64bitmode(ctx);
6700
        {
P
pbrook 已提交
6701
            TCGv_i64 fp0 = tcg_temp_new_i64();
6702 6703

            gen_load_fpr64(ctx, fp0, fs);
P
pbrook 已提交
6704
            gen_helper_float_cvtps_pw(fp0, fp0);
6705
            gen_store_fpr64(ctx, fp0, fd);
P
pbrook 已提交
6706
            tcg_temp_free_i64(fp0);
6707
        }
6708 6709 6710
        opn = "cvt.ps.pw";
        break;
    case FOP(0, 22):
6711
        check_cp1_64bitmode(ctx);
6712
        {
P
pbrook 已提交
6713 6714
            TCGv_i64 fp0 = tcg_temp_new_i64();
            TCGv_i64 fp1 = tcg_temp_new_i64();
6715 6716 6717

            gen_load_fpr64(ctx, fp0, fs);
            gen_load_fpr64(ctx, fp1, ft);
P
pbrook 已提交
6718 6719
            gen_helper_float_add_ps(fp0, fp0, fp1);
            tcg_temp_free_i64(fp1);
6720
            gen_store_fpr64(ctx, fp0, fd);
P
pbrook 已提交
6721
            tcg_temp_free_i64(fp0);
6722
        }
6723
        opn = "add.ps";
B
bellard 已提交
6724
        break;
6725
    case FOP(1, 22):
6726
        check_cp1_64bitmode(ctx);
6727
        {
P
pbrook 已提交
6728 6729
            TCGv_i64 fp0 = tcg_temp_new_i64();
            TCGv_i64 fp1 = tcg_temp_new_i64();
6730 6731 6732

            gen_load_fpr64(ctx, fp0, fs);
            gen_load_fpr64(ctx, fp1, ft);
P
pbrook 已提交
6733 6734
            gen_helper_float_sub_ps(fp0, fp0, fp1);
            tcg_temp_free_i64(fp1);
6735
            gen_store_fpr64(ctx, fp0, fd);
P
pbrook 已提交
6736
            tcg_temp_free_i64(fp0);
6737
        }
6738
        opn = "sub.ps";
B
bellard 已提交
6739
        break;
6740
    case FOP(2, 22):
6741
        check_cp1_64bitmode(ctx);
6742
        {
P
pbrook 已提交
6743 6744
            TCGv_i64 fp0 = tcg_temp_new_i64();
            TCGv_i64 fp1 = tcg_temp_new_i64();
6745 6746 6747

            gen_load_fpr64(ctx, fp0, fs);
            gen_load_fpr64(ctx, fp1, ft);
P
pbrook 已提交
6748 6749
            gen_helper_float_mul_ps(fp0, fp0, fp1);
            tcg_temp_free_i64(fp1);
6750
            gen_store_fpr64(ctx, fp0, fd);
P
pbrook 已提交
6751
            tcg_temp_free_i64(fp0);
6752
        }
6753
        opn = "mul.ps";
B
bellard 已提交
6754
        break;
6755
    case FOP(5, 22):
6756
        check_cp1_64bitmode(ctx);
6757
        {
P
pbrook 已提交
6758
            TCGv_i64 fp0 = tcg_temp_new_i64();
6759 6760

            gen_load_fpr64(ctx, fp0, fs);
P
pbrook 已提交
6761
            gen_helper_float_abs_ps(fp0, fp0);
6762
            gen_store_fpr64(ctx, fp0, fd);
P
pbrook 已提交
6763
            tcg_temp_free_i64(fp0);
6764
        }
6765
        opn = "abs.ps";
B
bellard 已提交
6766
        break;
6767
    case FOP(6, 22):
6768
        check_cp1_64bitmode(ctx);
6769
        {
P
pbrook 已提交
6770
            TCGv_i64 fp0 = tcg_temp_new_i64();
6771 6772 6773

            gen_load_fpr64(ctx, fp0, fs);
            gen_store_fpr64(ctx, fp0, fd);
P
pbrook 已提交
6774
            tcg_temp_free_i64(fp0);
6775
        }
6776
        opn = "mov.ps";
B
bellard 已提交
6777
        break;
6778
    case FOP(7, 22):
6779
        check_cp1_64bitmode(ctx);
6780
        {
P
pbrook 已提交
6781
            TCGv_i64 fp0 = tcg_temp_new_i64();
6782 6783

            gen_load_fpr64(ctx, fp0, fs);
P
pbrook 已提交
6784
            gen_helper_float_chs_ps(fp0, fp0);
6785
            gen_store_fpr64(ctx, fp0, fd);
P
pbrook 已提交
6786
            tcg_temp_free_i64(fp0);
6787
        }
6788
        opn = "neg.ps";
B
bellard 已提交
6789
        break;
6790
    case FOP(17, 22):
6791
        check_cp1_64bitmode(ctx);
6792
        gen_movcf_ps(fs, fd, (ft >> 2) & 0x7, ft & 0x1);
6793
        opn = "movcf.ps";
B
bellard 已提交
6794
        break;
6795
    case FOP(18, 22):
6796
        check_cp1_64bitmode(ctx);
6797 6798
        {
            int l1 = gen_new_label();
P
pbrook 已提交
6799 6800 6801
            TCGv t0 = tcg_temp_new();
            TCGv_i32 fp0 = tcg_temp_local_new_i32();
            TCGv_i32 fph0 = tcg_temp_local_new_i32();
6802

6803 6804
            gen_load_gpr(t0, ft);
            tcg_gen_brcondi_tl(TCG_COND_NE, t0, 0, l1);
6805 6806 6807 6808
            gen_load_fpr32(fp0, fs);
            gen_load_fpr32h(fph0, fs);
            gen_store_fpr32(fp0, fd);
            gen_store_fpr32h(fph0, fd);
P
pbrook 已提交
6809 6810
            tcg_temp_free_i32(fp0);
            tcg_temp_free_i32(fph0);
6811
            gen_set_label(l1);
A
aurel32 已提交
6812
            tcg_temp_free(t0);
6813
        }
6814
        opn = "movz.ps";
B
bellard 已提交
6815
        break;
6816
    case FOP(19, 22):
6817
        check_cp1_64bitmode(ctx);
6818 6819
        {
            int l1 = gen_new_label();
P
pbrook 已提交
6820 6821 6822
            TCGv t0 = tcg_temp_new();
            TCGv_i32 fp0 = tcg_temp_local_new_i32();
            TCGv_i32 fph0 = tcg_temp_local_new_i32();
6823

6824 6825
            gen_load_gpr(t0, ft);
            tcg_gen_brcondi_tl(TCG_COND_EQ, t0, 0, l1);
6826 6827 6828 6829
            gen_load_fpr32(fp0, fs);
            gen_load_fpr32h(fph0, fs);
            gen_store_fpr32(fp0, fd);
            gen_store_fpr32h(fph0, fd);
P
pbrook 已提交
6830 6831
            tcg_temp_free_i32(fp0);
            tcg_temp_free_i32(fph0);
6832
            gen_set_label(l1);
A
aurel32 已提交
6833
            tcg_temp_free(t0);
6834
        }
6835
        opn = "movn.ps";
B
bellard 已提交
6836
        break;
6837
    case FOP(24, 22):
6838
        check_cp1_64bitmode(ctx);
6839
        {
P
pbrook 已提交
6840 6841
            TCGv_i64 fp0 = tcg_temp_new_i64();
            TCGv_i64 fp1 = tcg_temp_new_i64();
6842 6843 6844

            gen_load_fpr64(ctx, fp0, ft);
            gen_load_fpr64(ctx, fp1, fs);
P
pbrook 已提交
6845 6846
            gen_helper_float_addr_ps(fp0, fp0, fp1);
            tcg_temp_free_i64(fp1);
6847
            gen_store_fpr64(ctx, fp0, fd);
P
pbrook 已提交
6848
            tcg_temp_free_i64(fp0);
6849
        }
6850 6851
        opn = "addr.ps";
        break;
T
ths 已提交
6852
    case FOP(26, 22):
6853
        check_cp1_64bitmode(ctx);
6854
        {
P
pbrook 已提交
6855 6856
            TCGv_i64 fp0 = tcg_temp_new_i64();
            TCGv_i64 fp1 = tcg_temp_new_i64();
6857 6858 6859

            gen_load_fpr64(ctx, fp0, ft);
            gen_load_fpr64(ctx, fp1, fs);
P
pbrook 已提交
6860 6861
            gen_helper_float_mulr_ps(fp0, fp0, fp1);
            tcg_temp_free_i64(fp1);
6862
            gen_store_fpr64(ctx, fp0, fd);
P
pbrook 已提交
6863
            tcg_temp_free_i64(fp0);
6864
        }
T
ths 已提交
6865 6866 6867
        opn = "mulr.ps";
        break;
    case FOP(28, 22):
6868
        check_cp1_64bitmode(ctx);
6869
        {
P
pbrook 已提交
6870 6871
            TCGv_i64 fp0 = tcg_temp_new_i64();
            TCGv_i64 fp1 = tcg_temp_new_i64();
6872 6873 6874

            gen_load_fpr64(ctx, fp0, fs);
            gen_load_fpr64(ctx, fp1, fd);
P
pbrook 已提交
6875 6876
            gen_helper_float_recip2_ps(fp0, fp0, fp1);
            tcg_temp_free_i64(fp1);
6877
            gen_store_fpr64(ctx, fp0, fd);
P
pbrook 已提交
6878
            tcg_temp_free_i64(fp0);
6879
        }
T
ths 已提交
6880 6881 6882
        opn = "recip2.ps";
        break;
    case FOP(29, 22):
6883
        check_cp1_64bitmode(ctx);
6884
        {
P
pbrook 已提交
6885
            TCGv_i64 fp0 = tcg_temp_new_i64();
6886 6887

            gen_load_fpr64(ctx, fp0, fs);
P
pbrook 已提交
6888
            gen_helper_float_recip1_ps(fp0, fp0);
6889
            gen_store_fpr64(ctx, fp0, fd);
P
pbrook 已提交
6890
            tcg_temp_free_i64(fp0);
6891
        }
T
ths 已提交
6892 6893 6894
        opn = "recip1.ps";
        break;
    case FOP(30, 22):
6895
        check_cp1_64bitmode(ctx);
6896
        {
P
pbrook 已提交
6897
            TCGv_i64 fp0 = tcg_temp_new_i64();
6898 6899

            gen_load_fpr64(ctx, fp0, fs);
P
pbrook 已提交
6900
            gen_helper_float_rsqrt1_ps(fp0, fp0);
6901
            gen_store_fpr64(ctx, fp0, fd);
P
pbrook 已提交
6902
            tcg_temp_free_i64(fp0);
6903
        }
T
ths 已提交
6904 6905 6906
        opn = "rsqrt1.ps";
        break;
    case FOP(31, 22):
6907
        check_cp1_64bitmode(ctx);
6908
        {
P
pbrook 已提交
6909 6910
            TCGv_i64 fp0 = tcg_temp_new_i64();
            TCGv_i64 fp1 = tcg_temp_new_i64();
6911 6912 6913

            gen_load_fpr64(ctx, fp0, fs);
            gen_load_fpr64(ctx, fp1, ft);
P
pbrook 已提交
6914 6915
            gen_helper_float_rsqrt2_ps(fp0, fp0, fp1);
            tcg_temp_free_i64(fp1);
6916
            gen_store_fpr64(ctx, fp0, fd);
P
pbrook 已提交
6917
            tcg_temp_free_i64(fp0);
6918
        }
T
ths 已提交
6919 6920
        opn = "rsqrt2.ps";
        break;
6921
    case FOP(32, 22):
6922
        check_cp1_64bitmode(ctx);
6923
        {
P
pbrook 已提交
6924
            TCGv_i32 fp0 = tcg_temp_new_i32();
6925 6926

            gen_load_fpr32h(fp0, fs);
P
pbrook 已提交
6927
            gen_helper_float_cvts_pu(fp0, fp0);
6928
            gen_store_fpr32(fp0, fd);
P
pbrook 已提交
6929
            tcg_temp_free_i32(fp0);
6930
        }
6931
        opn = "cvt.s.pu";
6932
        break;
6933
    case FOP(36, 22):
6934
        check_cp1_64bitmode(ctx);
6935
        {
P
pbrook 已提交
6936
            TCGv_i64 fp0 = tcg_temp_new_i64();
6937 6938

            gen_load_fpr64(ctx, fp0, fs);
P
pbrook 已提交
6939
            gen_helper_float_cvtpw_ps(fp0, fp0);
6940
            gen_store_fpr64(ctx, fp0, fd);
P
pbrook 已提交
6941
            tcg_temp_free_i64(fp0);
6942
        }
6943
        opn = "cvt.pw.ps";
B
bellard 已提交
6944
        break;
6945
    case FOP(40, 22):
6946
        check_cp1_64bitmode(ctx);
6947
        {
P
pbrook 已提交
6948
            TCGv_i32 fp0 = tcg_temp_new_i32();
6949 6950

            gen_load_fpr32(fp0, fs);
P
pbrook 已提交
6951
            gen_helper_float_cvts_pl(fp0, fp0);
6952
            gen_store_fpr32(fp0, fd);
P
pbrook 已提交
6953
            tcg_temp_free_i32(fp0);
6954
        }
6955
        opn = "cvt.s.pl";
B
bellard 已提交
6956
        break;
6957
    case FOP(44, 22):
6958
        check_cp1_64bitmode(ctx);
6959
        {
P
pbrook 已提交
6960 6961
            TCGv_i32 fp0 = tcg_temp_new_i32();
            TCGv_i32 fp1 = tcg_temp_new_i32();
6962 6963 6964 6965 6966

            gen_load_fpr32(fp0, fs);
            gen_load_fpr32(fp1, ft);
            gen_store_fpr32h(fp0, fd);
            gen_store_fpr32(fp1, fd);
P
pbrook 已提交
6967 6968
            tcg_temp_free_i32(fp0);
            tcg_temp_free_i32(fp1);
6969
        }
6970
        opn = "pll.ps";
B
bellard 已提交
6971
        break;
6972
    case FOP(45, 22):
6973
        check_cp1_64bitmode(ctx);
6974
        {
P
pbrook 已提交
6975 6976
            TCGv_i32 fp0 = tcg_temp_new_i32();
            TCGv_i32 fp1 = tcg_temp_new_i32();
6977 6978 6979 6980 6981

            gen_load_fpr32(fp0, fs);
            gen_load_fpr32h(fp1, ft);
            gen_store_fpr32(fp1, fd);
            gen_store_fpr32h(fp0, fd);
P
pbrook 已提交
6982 6983
            tcg_temp_free_i32(fp0);
            tcg_temp_free_i32(fp1);
6984
        }
6985 6986 6987
        opn = "plu.ps";
        break;
    case FOP(46, 22):
6988
        check_cp1_64bitmode(ctx);
6989
        {
P
pbrook 已提交
6990 6991
            TCGv_i32 fp0 = tcg_temp_new_i32();
            TCGv_i32 fp1 = tcg_temp_new_i32();
6992 6993 6994 6995 6996

            gen_load_fpr32h(fp0, fs);
            gen_load_fpr32(fp1, ft);
            gen_store_fpr32(fp1, fd);
            gen_store_fpr32h(fp0, fd);
P
pbrook 已提交
6997 6998
            tcg_temp_free_i32(fp0);
            tcg_temp_free_i32(fp1);
6999
        }
7000 7001 7002
        opn = "pul.ps";
        break;
    case FOP(47, 22):
7003
        check_cp1_64bitmode(ctx);
7004
        {
P
pbrook 已提交
7005 7006
            TCGv_i32 fp0 = tcg_temp_new_i32();
            TCGv_i32 fp1 = tcg_temp_new_i32();
7007 7008 7009 7010 7011

            gen_load_fpr32h(fp0, fs);
            gen_load_fpr32h(fp1, ft);
            gen_store_fpr32(fp1, fd);
            gen_store_fpr32h(fp0, fd);
P
pbrook 已提交
7012 7013
            tcg_temp_free_i32(fp0);
            tcg_temp_free_i32(fp1);
7014
        }
7015 7016 7017 7018 7019 7020 7021 7022 7023 7024 7025 7026 7027 7028 7029 7030 7031 7032
        opn = "puu.ps";
        break;
    case FOP(48, 22):
    case FOP(49, 22):
    case FOP(50, 22):
    case FOP(51, 22):
    case FOP(52, 22):
    case FOP(53, 22):
    case FOP(54, 22):
    case FOP(55, 22):
    case FOP(56, 22):
    case FOP(57, 22):
    case FOP(58, 22):
    case FOP(59, 22):
    case FOP(60, 22):
    case FOP(61, 22):
    case FOP(62, 22):
    case FOP(63, 22):
7033
        check_cp1_64bitmode(ctx);
7034
        {
P
pbrook 已提交
7035 7036
            TCGv_i64 fp0 = tcg_temp_new_i64();
            TCGv_i64 fp1 = tcg_temp_new_i64();
7037 7038 7039 7040 7041 7042 7043 7044 7045 7046

            gen_load_fpr64(ctx, fp0, fs);
            gen_load_fpr64(ctx, fp1, ft);
            if (ctx->opcode & (1 << 6)) {
                gen_cmpabs_ps(func-48, fp0, fp1, cc);
                opn = condnames_abs[func-48];
            } else {
                gen_cmp_ps(func-48, fp0, fp1, cc);
                opn = condnames[func-48];
            }
P
pbrook 已提交
7047 7048
            tcg_temp_free_i64(fp0);
            tcg_temp_free_i64(fp1);
7049
        }
B
bellard 已提交
7050
        break;
7051
    default:
7052
        MIPS_INVAL(opn);
7053
        generate_exception (ctx, EXCP_RI);
B
bellard 已提交
7054 7055
        return;
    }
7056 7057
    switch (optype) {
    case BINOP:
B
bellard 已提交
7058
        MIPS_DEBUG("%s %s, %s, %s", opn, fregnames[fd], fregnames[fs], fregnames[ft]);
7059 7060 7061 7062 7063
        break;
    case CMPOP:
        MIPS_DEBUG("%s %s,%s", opn, fregnames[fs], fregnames[ft]);
        break;
    default:
B
bellard 已提交
7064
        MIPS_DEBUG("%s %s,%s", opn, fregnames[fd], fregnames[fs]);
7065 7066
        break;
    }
B
bellard 已提交
7067
}
B
bellard 已提交
7068

7069
/* Coprocessor 3 (FPU) */
7070 7071
static void gen_flt3_ldst (DisasContext *ctx, uint32_t opc,
                           int fd, int fs, int base, int index)
7072
{
7073
    const char *opn = "extended float load/store";
T
ths 已提交
7074
    int store = 0;
P
pbrook 已提交
7075 7076
    TCGv t0 = tcg_temp_local_new();
    TCGv t1 = tcg_temp_local_new();
7077

T
ths 已提交
7078
    if (base == 0) {
7079
        gen_load_gpr(t0, index);
T
ths 已提交
7080
    } else if (index == 0) {
7081
        gen_load_gpr(t0, base);
T
ths 已提交
7082
    } else {
7083 7084
        gen_load_gpr(t0, index);
        gen_op_addr_add(ctx, t0, cpu_gpr[base]);
T
ths 已提交
7085
    }
7086
    /* Don't do NOP if destination is zero: we must perform the actual
7087
       memory access. */
7088 7089
    switch (opc) {
    case OPC_LWXC1:
7090
        check_cop1x(ctx);
7091
        {
P
pbrook 已提交
7092
            TCGv_i32 fp0 = tcg_temp_new_i32();
7093

P
pbrook 已提交
7094 7095
            tcg_gen_qemu_ld32s(t1, t0, ctx->mem_idx);
            tcg_gen_trunc_tl_i32(fp0, t1);
7096
            gen_store_fpr32(fp0, fd);
P
pbrook 已提交
7097
            tcg_temp_free_i32(fp0);
7098
        }
7099 7100 7101
        opn = "lwxc1";
        break;
    case OPC_LDXC1:
7102 7103
        check_cop1x(ctx);
        check_cp1_registers(ctx, fd);
7104
        {
P
pbrook 已提交
7105
            TCGv_i64 fp0 = tcg_temp_new_i64();
7106 7107 7108

            tcg_gen_qemu_ld64(fp0, t0, ctx->mem_idx);
            gen_store_fpr64(ctx, fp0, fd);
P
pbrook 已提交
7109
            tcg_temp_free_i64(fp0);
7110
        }
7111 7112 7113
        opn = "ldxc1";
        break;
    case OPC_LUXC1:
7114
        check_cp1_64bitmode(ctx);
7115
        tcg_gen_andi_tl(t0, t0, ~0x7);
7116
        {
P
pbrook 已提交
7117
            TCGv_i64 fp0 = tcg_temp_new_i64();
7118 7119 7120

            tcg_gen_qemu_ld64(fp0, t0, ctx->mem_idx);
            gen_store_fpr64(ctx, fp0, fd);
P
pbrook 已提交
7121
            tcg_temp_free_i64(fp0);
7122
        }
7123 7124 7125
        opn = "luxc1";
        break;
    case OPC_SWXC1:
7126
        check_cop1x(ctx);
7127
        {
P
pbrook 已提交
7128
            TCGv_i32 fp0 = tcg_temp_new_i32();
7129 7130

            gen_load_fpr32(fp0, fs);
P
pbrook 已提交
7131 7132 7133
            tcg_gen_extu_i32_tl(t1, fp0);
            tcg_gen_qemu_st32(t1, t0, ctx->mem_idx);
            tcg_temp_free_i32(fp0);
7134
        }
7135
        opn = "swxc1";
T
ths 已提交
7136
        store = 1;
7137 7138
        break;
    case OPC_SDXC1:
7139 7140
        check_cop1x(ctx);
        check_cp1_registers(ctx, fs);
7141
        {
P
pbrook 已提交
7142
            TCGv_i64 fp0 = tcg_temp_new_i64();
7143 7144 7145

            gen_load_fpr64(ctx, fp0, fs);
            tcg_gen_qemu_st64(fp0, t0, ctx->mem_idx);
P
pbrook 已提交
7146
            tcg_temp_free_i64(fp0);
7147
        }
7148
        opn = "sdxc1";
T
ths 已提交
7149
        store = 1;
7150 7151
        break;
    case OPC_SUXC1:
7152
        check_cp1_64bitmode(ctx);
7153
        tcg_gen_andi_tl(t0, t0, ~0x7);
7154
        {
P
pbrook 已提交
7155
            TCGv_i64 fp0 = tcg_temp_new_i64();
7156 7157 7158

            gen_load_fpr64(ctx, fp0, fs);
            tcg_gen_qemu_st64(fp0, t0, ctx->mem_idx);
P
pbrook 已提交
7159
            tcg_temp_free_i64(fp0);
7160
        }
7161
        opn = "suxc1";
T
ths 已提交
7162
        store = 1;
7163 7164
        break;
    default:
7165
        MIPS_INVAL(opn);
7166
        generate_exception(ctx, EXCP_RI);
7167 7168
        tcg_temp_free(t0);
        tcg_temp_free(t1);
7169 7170
        return;
    }
7171 7172
    tcg_temp_free(t0);
    tcg_temp_free(t1);
T
ths 已提交
7173 7174
    MIPS_DEBUG("%s %s, %s(%s)", opn, fregnames[store ? fs : fd],
               regnames[index], regnames[base]);
7175 7176
}

7177 7178
static void gen_flt3_arith (DisasContext *ctx, uint32_t opc,
                            int fd, int fr, int fs, int ft)
7179
{
7180
    const char *opn = "flt3_arith";
7181 7182 7183

    switch (opc) {
    case OPC_ALNV_PS:
7184
        check_cp1_64bitmode(ctx);
7185
        {
P
pbrook 已提交
7186 7187 7188 7189 7190
            TCGv t0 = tcg_temp_local_new();
            TCGv_i32 fp0 = tcg_temp_local_new_i32();
            TCGv_i32 fph0 = tcg_temp_local_new_i32();
            TCGv_i32 fp1 = tcg_temp_local_new_i32();
            TCGv_i32 fph1 = tcg_temp_local_new_i32();
7191 7192 7193
            int l1 = gen_new_label();
            int l2 = gen_new_label();

7194 7195
            gen_load_gpr(t0, fr);
            tcg_gen_andi_tl(t0, t0, 0x7);
7196 7197 7198 7199
            gen_load_fpr32(fp0, fs);
            gen_load_fpr32h(fph0, fs);
            gen_load_fpr32(fp1, ft);
            gen_load_fpr32h(fph1, ft);
7200 7201

            tcg_gen_brcondi_tl(TCG_COND_NE, t0, 0, l1);
7202 7203
            gen_store_fpr32(fp0, fd);
            gen_store_fpr32h(fph0, fd);
7204 7205
            tcg_gen_br(l2);
            gen_set_label(l1);
7206 7207
            tcg_gen_brcondi_tl(TCG_COND_NE, t0, 4, l2);
            tcg_temp_free(t0);
7208
#ifdef TARGET_WORDS_BIGENDIAN
7209 7210
            gen_store_fpr32(fph1, fd);
            gen_store_fpr32h(fp0, fd);
7211
#else
7212 7213
            gen_store_fpr32(fph0, fd);
            gen_store_fpr32h(fp1, fd);
7214 7215
#endif
            gen_set_label(l2);
P
pbrook 已提交
7216 7217 7218 7219
            tcg_temp_free_i32(fp0);
            tcg_temp_free_i32(fph0);
            tcg_temp_free_i32(fp1);
            tcg_temp_free_i32(fph1);
7220
        }
7221 7222 7223
        opn = "alnv.ps";
        break;
    case OPC_MADD_S:
7224
        check_cop1x(ctx);
7225
        {
P
pbrook 已提交
7226 7227 7228
            TCGv_i32 fp0 = tcg_temp_new_i32();
            TCGv_i32 fp1 = tcg_temp_new_i32();
            TCGv_i32 fp2 = tcg_temp_new_i32();
7229 7230 7231 7232

            gen_load_fpr32(fp0, fs);
            gen_load_fpr32(fp1, ft);
            gen_load_fpr32(fp2, fr);
P
pbrook 已提交
7233 7234 7235
            gen_helper_float_muladd_s(fp2, fp0, fp1, fp2);
            tcg_temp_free_i32(fp0);
            tcg_temp_free_i32(fp1);
7236
            gen_store_fpr32(fp2, fd);
P
pbrook 已提交
7237
            tcg_temp_free_i32(fp2);
7238
        }
7239 7240 7241
        opn = "madd.s";
        break;
    case OPC_MADD_D:
7242 7243
        check_cop1x(ctx);
        check_cp1_registers(ctx, fd | fs | ft | fr);
7244
        {
P
pbrook 已提交
7245 7246 7247
            TCGv_i64 fp0 = tcg_temp_new_i64();
            TCGv_i64 fp1 = tcg_temp_new_i64();
            TCGv_i64 fp2 = tcg_temp_new_i64();
7248 7249 7250 7251

            gen_load_fpr64(ctx, fp0, fs);
            gen_load_fpr64(ctx, fp1, ft);
            gen_load_fpr64(ctx, fp2, fr);
P
pbrook 已提交
7252 7253 7254
            gen_helper_float_muladd_d(fp2, fp0, fp1, fp2);
            tcg_temp_free_i64(fp0);
            tcg_temp_free_i64(fp1);
7255
            gen_store_fpr64(ctx, fp2, fd);
P
pbrook 已提交
7256
            tcg_temp_free_i64(fp2);
7257
        }
7258 7259 7260
        opn = "madd.d";
        break;
    case OPC_MADD_PS:
7261
        check_cp1_64bitmode(ctx);
7262
        {
P
pbrook 已提交
7263 7264 7265
            TCGv_i64 fp0 = tcg_temp_new_i64();
            TCGv_i64 fp1 = tcg_temp_new_i64();
            TCGv_i64 fp2 = tcg_temp_new_i64();
7266 7267 7268 7269

            gen_load_fpr64(ctx, fp0, fs);
            gen_load_fpr64(ctx, fp1, ft);
            gen_load_fpr64(ctx, fp2, fr);
P
pbrook 已提交
7270 7271 7272
            gen_helper_float_muladd_ps(fp2, fp0, fp1, fp2);
            tcg_temp_free_i64(fp0);
            tcg_temp_free_i64(fp1);
7273
            gen_store_fpr64(ctx, fp2, fd);
P
pbrook 已提交
7274
            tcg_temp_free_i64(fp2);
7275
        }
7276 7277 7278
        opn = "madd.ps";
        break;
    case OPC_MSUB_S:
7279
        check_cop1x(ctx);
7280
        {
P
pbrook 已提交
7281 7282 7283
            TCGv_i32 fp0 = tcg_temp_new_i32();
            TCGv_i32 fp1 = tcg_temp_new_i32();
            TCGv_i32 fp2 = tcg_temp_new_i32();
7284 7285 7286 7287

            gen_load_fpr32(fp0, fs);
            gen_load_fpr32(fp1, ft);
            gen_load_fpr32(fp2, fr);
P
pbrook 已提交
7288 7289 7290
            gen_helper_float_mulsub_s(fp2, fp0, fp1, fp2);
            tcg_temp_free_i32(fp0);
            tcg_temp_free_i32(fp1);
7291
            gen_store_fpr32(fp2, fd);
P
pbrook 已提交
7292
            tcg_temp_free_i32(fp2);
7293
        }
7294 7295 7296
        opn = "msub.s";
        break;
    case OPC_MSUB_D:
7297 7298
        check_cop1x(ctx);
        check_cp1_registers(ctx, fd | fs | ft | fr);
7299
        {
P
pbrook 已提交
7300 7301 7302
            TCGv_i64 fp0 = tcg_temp_new_i64();
            TCGv_i64 fp1 = tcg_temp_new_i64();
            TCGv_i64 fp2 = tcg_temp_new_i64();
7303 7304 7305 7306

            gen_load_fpr64(ctx, fp0, fs);
            gen_load_fpr64(ctx, fp1, ft);
            gen_load_fpr64(ctx, fp2, fr);
P
pbrook 已提交
7307 7308 7309
            gen_helper_float_mulsub_d(fp2, fp0, fp1, fp2);
            tcg_temp_free_i64(fp0);
            tcg_temp_free_i64(fp1);
7310
            gen_store_fpr64(ctx, fp2, fd);
P
pbrook 已提交
7311
            tcg_temp_free_i64(fp2);
7312
        }
7313 7314 7315
        opn = "msub.d";
        break;
    case OPC_MSUB_PS:
7316
        check_cp1_64bitmode(ctx);
7317
        {
P
pbrook 已提交
7318 7319 7320
            TCGv_i64 fp0 = tcg_temp_new_i64();
            TCGv_i64 fp1 = tcg_temp_new_i64();
            TCGv_i64 fp2 = tcg_temp_new_i64();
7321 7322 7323 7324

            gen_load_fpr64(ctx, fp0, fs);
            gen_load_fpr64(ctx, fp1, ft);
            gen_load_fpr64(ctx, fp2, fr);
P
pbrook 已提交
7325 7326 7327
            gen_helper_float_mulsub_ps(fp2, fp0, fp1, fp2);
            tcg_temp_free_i64(fp0);
            tcg_temp_free_i64(fp1);
7328
            gen_store_fpr64(ctx, fp2, fd);
P
pbrook 已提交
7329
            tcg_temp_free_i64(fp2);
7330
        }
7331 7332 7333
        opn = "msub.ps";
        break;
    case OPC_NMADD_S:
7334
        check_cop1x(ctx);
7335
        {
P
pbrook 已提交
7336 7337 7338
            TCGv_i32 fp0 = tcg_temp_new_i32();
            TCGv_i32 fp1 = tcg_temp_new_i32();
            TCGv_i32 fp2 = tcg_temp_new_i32();
7339 7340 7341 7342

            gen_load_fpr32(fp0, fs);
            gen_load_fpr32(fp1, ft);
            gen_load_fpr32(fp2, fr);
P
pbrook 已提交
7343 7344 7345
            gen_helper_float_nmuladd_s(fp2, fp0, fp1, fp2);
            tcg_temp_free_i32(fp0);
            tcg_temp_free_i32(fp1);
7346
            gen_store_fpr32(fp2, fd);
P
pbrook 已提交
7347
            tcg_temp_free_i32(fp2);
7348
        }
7349 7350 7351
        opn = "nmadd.s";
        break;
    case OPC_NMADD_D:
7352 7353
        check_cop1x(ctx);
        check_cp1_registers(ctx, fd | fs | ft | fr);
7354
        {
P
pbrook 已提交
7355 7356 7357
            TCGv_i64 fp0 = tcg_temp_new_i64();
            TCGv_i64 fp1 = tcg_temp_new_i64();
            TCGv_i64 fp2 = tcg_temp_new_i64();
7358 7359 7360 7361

            gen_load_fpr64(ctx, fp0, fs);
            gen_load_fpr64(ctx, fp1, ft);
            gen_load_fpr64(ctx, fp2, fr);
P
pbrook 已提交
7362 7363 7364
            gen_helper_float_nmuladd_d(fp2, fp0, fp1, fp2);
            tcg_temp_free_i64(fp0);
            tcg_temp_free_i64(fp1);
7365
            gen_store_fpr64(ctx, fp2, fd);
P
pbrook 已提交
7366
            tcg_temp_free_i64(fp2);
7367
        }
7368 7369 7370
        opn = "nmadd.d";
        break;
    case OPC_NMADD_PS:
7371
        check_cp1_64bitmode(ctx);
7372
        {
P
pbrook 已提交
7373 7374 7375
            TCGv_i64 fp0 = tcg_temp_new_i64();
            TCGv_i64 fp1 = tcg_temp_new_i64();
            TCGv_i64 fp2 = tcg_temp_new_i64();
7376 7377 7378 7379

            gen_load_fpr64(ctx, fp0, fs);
            gen_load_fpr64(ctx, fp1, ft);
            gen_load_fpr64(ctx, fp2, fr);
P
pbrook 已提交
7380 7381 7382
            gen_helper_float_nmuladd_ps(fp2, fp0, fp1, fp2);
            tcg_temp_free_i64(fp0);
            tcg_temp_free_i64(fp1);
7383
            gen_store_fpr64(ctx, fp2, fd);
P
pbrook 已提交
7384
            tcg_temp_free_i64(fp2);
7385
        }
7386 7387 7388
        opn = "nmadd.ps";
        break;
    case OPC_NMSUB_S:
7389
        check_cop1x(ctx);
7390
        {
P
pbrook 已提交
7391 7392 7393
            TCGv_i32 fp0 = tcg_temp_new_i32();
            TCGv_i32 fp1 = tcg_temp_new_i32();
            TCGv_i32 fp2 = tcg_temp_new_i32();
7394 7395 7396 7397

            gen_load_fpr32(fp0, fs);
            gen_load_fpr32(fp1, ft);
            gen_load_fpr32(fp2, fr);
P
pbrook 已提交
7398 7399 7400
            gen_helper_float_nmulsub_s(fp2, fp0, fp1, fp2);
            tcg_temp_free_i32(fp0);
            tcg_temp_free_i32(fp1);
7401
            gen_store_fpr32(fp2, fd);
P
pbrook 已提交
7402
            tcg_temp_free_i32(fp2);
7403
        }
7404 7405 7406
        opn = "nmsub.s";
        break;
    case OPC_NMSUB_D:
7407 7408
        check_cop1x(ctx);
        check_cp1_registers(ctx, fd | fs | ft | fr);
7409
        {
P
pbrook 已提交
7410 7411 7412
            TCGv_i64 fp0 = tcg_temp_new_i64();
            TCGv_i64 fp1 = tcg_temp_new_i64();
            TCGv_i64 fp2 = tcg_temp_new_i64();
7413 7414 7415 7416

            gen_load_fpr64(ctx, fp0, fs);
            gen_load_fpr64(ctx, fp1, ft);
            gen_load_fpr64(ctx, fp2, fr);
P
pbrook 已提交
7417 7418 7419
            gen_helper_float_nmulsub_d(fp2, fp0, fp1, fp2);
            tcg_temp_free_i64(fp0);
            tcg_temp_free_i64(fp1);
7420
            gen_store_fpr64(ctx, fp2, fd);
P
pbrook 已提交
7421
            tcg_temp_free_i64(fp2);
7422
        }
7423 7424 7425
        opn = "nmsub.d";
        break;
    case OPC_NMSUB_PS:
7426
        check_cp1_64bitmode(ctx);
7427
        {
P
pbrook 已提交
7428 7429 7430
            TCGv_i64 fp0 = tcg_temp_new_i64();
            TCGv_i64 fp1 = tcg_temp_new_i64();
            TCGv_i64 fp2 = tcg_temp_new_i64();
7431 7432 7433 7434

            gen_load_fpr64(ctx, fp0, fs);
            gen_load_fpr64(ctx, fp1, ft);
            gen_load_fpr64(ctx, fp2, fr);
P
pbrook 已提交
7435 7436 7437
            gen_helper_float_nmulsub_ps(fp2, fp0, fp1, fp2);
            tcg_temp_free_i64(fp0);
            tcg_temp_free_i64(fp1);
7438
            gen_store_fpr64(ctx, fp2, fd);
P
pbrook 已提交
7439
            tcg_temp_free_i64(fp2);
7440
        }
7441 7442
        opn = "nmsub.ps";
        break;
7443 7444
    default:
        MIPS_INVAL(opn);
7445 7446 7447 7448 7449
        generate_exception (ctx, EXCP_RI);
        return;
    }
    MIPS_DEBUG("%s %s, %s, %s, %s", opn, fregnames[fd], fregnames[fr],
               fregnames[fs], fregnames[ft]);
7450 7451 7452
}

/* ISA extensions (ASEs) */
B
bellard 已提交
7453 7454 7455
/* MIPS16 extension to MIPS32 */
/* SmartMIPS extension to MIPS32 */

7456
#if defined(TARGET_MIPS64)
B
bellard 已提交
7457 7458 7459 7460 7461

/* MDMX extension to MIPS64 */

#endif

7462
static void decode_opc (CPUState *env, DisasContext *ctx)
B
bellard 已提交
7463 7464 7465
{
    int32_t offset;
    int rs, rt, rd, sa;
7466
    uint32_t op, op1, op2;
B
bellard 已提交
7467 7468
    int16_t imm;

7469 7470
    /* make sure instructions are on a word boundary */
    if (ctx->pc & 0x3) {
7471
        env->CP0_BadVAddr = ctx->pc;
7472 7473 7474 7475
        generate_exception(ctx, EXCP_AdEL);
        return;
    }

7476
    /* Handle blikely not taken case */
B
bellard 已提交
7477
    if ((ctx->hflags & MIPS_HFLAG_BMASK) == MIPS_HFLAG_BL) {
7478 7479
        int l1 = gen_new_label();

T
ths 已提交
7480
        MIPS_DEBUG("blikely condition (" TARGET_FMT_lx ")", ctx->pc + 4);
7481
        tcg_gen_brcondi_tl(TCG_COND_NE, bcond, 0, l1);
7482
        tcg_gen_movi_i32(hflags, ctx->hflags & ~MIPS_HFLAG_BMASK);
7483 7484
        gen_goto_tb(ctx, 1, ctx->pc + 4);
        gen_set_label(l1);
B
bellard 已提交
7485
    }
7486 7487 7488 7489 7490
    op = MASK_OP_MAJOR(ctx->opcode);
    rs = (ctx->opcode >> 21) & 0x1f;
    rt = (ctx->opcode >> 16) & 0x1f;
    rd = (ctx->opcode >> 11) & 0x1f;
    sa = (ctx->opcode >> 6) & 0x1f;
B
bellard 已提交
7491 7492
    imm = (int16_t)ctx->opcode;
    switch (op) {
7493 7494
    case OPC_SPECIAL:
        op1 = MASK_SPECIAL(ctx->opcode);
B
bellard 已提交
7495
        switch (op1) {
7496 7497
        case OPC_SLL:          /* Arithmetic with immediate */
        case OPC_SRL ... OPC_SRA:
7498
            gen_arith_imm(env, ctx, op1, rd, rt, sa);
7499
            break;
7500 7501
        case OPC_MOVZ ... OPC_MOVN:
            check_insn(env, ctx, ISA_MIPS4 | ISA_MIPS32);
7502 7503 7504 7505
        case OPC_SLLV:         /* Arithmetic */
        case OPC_SRLV ... OPC_SRAV:
        case OPC_ADD ... OPC_NOR:
        case OPC_SLT ... OPC_SLTU:
7506
            gen_arith(env, ctx, op1, rd, rs, rt);
7507 7508
            break;
        case OPC_MULT ... OPC_DIVU:
7509 7510 7511 7512 7513 7514
            if (sa) {
                check_insn(env, ctx, INSN_VR54XX);
                op1 = MASK_MUL_VR54XX(ctx->opcode);
                gen_mul_vr54xx(ctx, op1, rd, rs, rt);
            } else
                gen_muldiv(ctx, op1, rs, rt);
7515 7516 7517
            break;
        case OPC_JR ... OPC_JALR:
            gen_compute_branch(ctx, op1, rs, rd, sa);
B
bellard 已提交
7518
            return;
7519 7520 7521
        case OPC_TGE ... OPC_TEQ: /* Traps */
        case OPC_TNE:
            gen_trap(ctx, op1, rs, rt, -1);
B
bellard 已提交
7522
            break;
7523 7524 7525
        case OPC_MFHI:          /* Move from HI/LO */
        case OPC_MFLO:
            gen_HILO(ctx, op1, rd);
B
bellard 已提交
7526
            break;
7527 7528 7529
        case OPC_MTHI:
        case OPC_MTLO:          /* Move to HI/LO */
            gen_HILO(ctx, op1, rs);
B
bellard 已提交
7530
            break;
7531 7532 7533 7534 7535
        case OPC_PMON:          /* Pmon entry point, also R4010 selsl */
#ifdef MIPS_STRICT_STANDARD
            MIPS_INVAL("PMON / selsl");
            generate_exception(ctx, EXCP_RI);
#else
P
pbrook 已提交
7536
            gen_helper_0i(pmon, sa);
7537
#endif
7538 7539
            break;
        case OPC_SYSCALL:
B
bellard 已提交
7540 7541
            generate_exception(ctx, EXCP_SYSCALL);
            break;
7542
        case OPC_BREAK:
B
bellard 已提交
7543 7544
            generate_exception(ctx, EXCP_BREAK);
            break;
7545 7546 7547 7548 7549
        case OPC_SPIM:
#ifdef MIPS_STRICT_STANDARD
            MIPS_INVAL("SPIM");
            generate_exception(ctx, EXCP_RI);
#else
7550 7551 7552
           /* Implemented as RI exception for now. */
            MIPS_INVAL("spim (unofficial)");
            generate_exception(ctx, EXCP_RI);
7553
#endif
B
bellard 已提交
7554
            break;
7555
        case OPC_SYNC:
7556
            /* Treat as NOP. */
B
bellard 已提交
7557
            break;
B
bellard 已提交
7558

7559
        case OPC_MOVCI:
7560
            check_insn(env, ctx, ISA_MIPS4 | ISA_MIPS32);
7561
            if (env->CP0_Config1 & (1 << CP0C1_FP)) {
7562
                save_cpu_state(ctx, 1);
7563
                check_cp1_enabled(ctx);
7564 7565 7566
                gen_movci(ctx, rd, rs, (ctx->opcode >> 18) & 0x7,
                          (ctx->opcode >> 16) & 1);
            } else {
7567
                generate_exception_err(ctx, EXCP_CpU, 1);
7568
            }
B
bellard 已提交
7569 7570
            break;

7571
#if defined(TARGET_MIPS64)
7572 7573 7574 7575 7576
       /* MIPS64 specific opcodes */
        case OPC_DSLL:
        case OPC_DSRL ... OPC_DSRA:
        case OPC_DSLL32:
        case OPC_DSRL32 ... OPC_DSRA32:
7577 7578 7579
            check_insn(env, ctx, ISA_MIPS3);
            check_mips_64(ctx);
            gen_arith_imm(env, ctx, op1, rd, rt, sa);
7580 7581 7582 7583
            break;
        case OPC_DSLLV:
        case OPC_DSRLV ... OPC_DSRAV:
        case OPC_DADD ... OPC_DSUBU:
7584 7585 7586
            check_insn(env, ctx, ISA_MIPS3);
            check_mips_64(ctx);
            gen_arith(env, ctx, op1, rd, rs, rt);
7587 7588
            break;
        case OPC_DMULT ... OPC_DDIVU:
7589 7590
            check_insn(env, ctx, ISA_MIPS3);
            check_mips_64(ctx);
7591 7592
            gen_muldiv(ctx, op1, rs, rt);
            break;
B
bellard 已提交
7593 7594 7595 7596 7597 7598 7599
#endif
        default:            /* Invalid */
            MIPS_INVAL("special");
            generate_exception(ctx, EXCP_RI);
            break;
        }
        break;
7600 7601
    case OPC_SPECIAL2:
        op1 = MASK_SPECIAL2(ctx->opcode);
B
bellard 已提交
7602
        switch (op1) {
7603 7604
        case OPC_MADD ... OPC_MADDU: /* Multiply and add/sub */
        case OPC_MSUB ... OPC_MSUBU:
7605
            check_insn(env, ctx, ISA_MIPS32);
7606
            gen_muldiv(ctx, op1, rs, rt);
B
bellard 已提交
7607
            break;
7608
        case OPC_MUL:
7609
            gen_arith(env, ctx, op1, rd, rs, rt);
B
bellard 已提交
7610
            break;
A
aurel32 已提交
7611 7612
        case OPC_CLO:
        case OPC_CLZ:
7613
            check_insn(env, ctx, ISA_MIPS32);
7614
            gen_cl(ctx, op1, rd, rs);
B
bellard 已提交
7615
            break;
7616
        case OPC_SDBBP:
B
bellard 已提交
7617 7618 7619
            /* XXX: not clear which exception should be raised
             *      when in debug mode...
             */
7620
            check_insn(env, ctx, ISA_MIPS32);
B
bellard 已提交
7621 7622 7623 7624 7625
            if (!(ctx->hflags & MIPS_HFLAG_DM)) {
                generate_exception(ctx, EXCP_DBp);
            } else {
                generate_exception(ctx, EXCP_DBp);
            }
7626
            /* Treat as NOP. */
B
bellard 已提交
7627
            break;
7628
#if defined(TARGET_MIPS64)
A
aurel32 已提交
7629 7630
        case OPC_DCLO:
        case OPC_DCLZ:
7631 7632
            check_insn(env, ctx, ISA_MIPS64);
            check_mips_64(ctx);
7633 7634 7635
            gen_cl(ctx, op1, rd, rs);
            break;
#endif
B
bellard 已提交
7636 7637 7638 7639 7640 7641
        default:            /* Invalid */
            MIPS_INVAL("special2");
            generate_exception(ctx, EXCP_RI);
            break;
        }
        break;
7642
    case OPC_SPECIAL3:
7643 7644 7645 7646 7647 7648 7649 7650 7651 7652
        op1 = MASK_SPECIAL3(ctx->opcode);
        switch (op1) {
        case OPC_EXT:
        case OPC_INS:
            check_insn(env, ctx, ISA_MIPS32R2);
            gen_bitops(ctx, op1, rt, rs, sa, rd);
            break;
        case OPC_BSHFL:
            check_insn(env, ctx, ISA_MIPS32R2);
            op2 = MASK_BSHFL(ctx->opcode);
7653
            gen_bshfl(ctx, op2, rt, rd);
7654
            break;
7655
        case OPC_RDHWR:
7656
            check_insn(env, ctx, ISA_MIPS32R2);
7657
            {
P
pbrook 已提交
7658
                TCGv t0 = tcg_temp_local_new();
7659 7660 7661 7662

                switch (rd) {
                case 0:
                    save_cpu_state(ctx, 1);
P
pbrook 已提交
7663
                    gen_helper_rdhwr_cpunum(t0);
7664 7665 7666
                    break;
                case 1:
                    save_cpu_state(ctx, 1);
P
pbrook 已提交
7667
                    gen_helper_rdhwr_synci_step(t0);
7668 7669 7670
                    break;
                case 2:
                    save_cpu_state(ctx, 1);
P
pbrook 已提交
7671
                    gen_helper_rdhwr_cc(t0);
7672 7673 7674
                    break;
                case 3:
                    save_cpu_state(ctx, 1);
P
pbrook 已提交
7675
                    gen_helper_rdhwr_ccres(t0);
7676 7677
                    break;
                case 29:
7678 7679 7680 7681 7682 7683 7684
#if defined(CONFIG_USER_ONLY)
                    tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUState, tls_value));
                    break;
#else
                    /* XXX: Some CPUs implement this in hardware.
                       Not supported yet. */
#endif
7685 7686 7687 7688 7689 7690 7691
                default:            /* Invalid */
                    MIPS_INVAL("rdhwr");
                    generate_exception(ctx, EXCP_RI);
                    break;
                }
                gen_store_gpr(t0, rt);
                tcg_temp_free(t0);
7692 7693
            }
            break;
7694
        case OPC_FORK:
7695
            check_insn(env, ctx, ASE_MT);
7696
            {
P
pbrook 已提交
7697 7698
                TCGv t0 = tcg_temp_local_new();
                TCGv t1 = tcg_temp_local_new();
7699 7700 7701

                gen_load_gpr(t0, rt);
                gen_load_gpr(t1, rs);
P
pbrook 已提交
7702
                gen_helper_fork(t0, t1);
7703 7704 7705
                tcg_temp_free(t0);
                tcg_temp_free(t1);
            }
7706 7707
            break;
        case OPC_YIELD:
7708
            check_insn(env, ctx, ASE_MT);
7709
            {
P
pbrook 已提交
7710
                TCGv t0 = tcg_temp_local_new();
7711 7712

                gen_load_gpr(t0, rs);
P
pbrook 已提交
7713
                gen_helper_yield(t0, t0);
7714 7715 7716
                gen_store_gpr(t0, rd);
                tcg_temp_free(t0);
            }
7717
            break;
7718
#if defined(TARGET_MIPS64)
7719 7720
        case OPC_DEXTM ... OPC_DEXT:
        case OPC_DINSM ... OPC_DINS:
7721 7722
            check_insn(env, ctx, ISA_MIPS64R2);
            check_mips_64(ctx);
7723
            gen_bitops(ctx, op1, rt, rs, sa, rd);
7724
            break;
7725
        case OPC_DBSHFL:
7726 7727
            check_insn(env, ctx, ISA_MIPS64R2);
            check_mips_64(ctx);
7728
            op2 = MASK_DBSHFL(ctx->opcode);
7729
            gen_bshfl(ctx, op2, rt, rd);
T
ths 已提交
7730
            break;
7731 7732 7733 7734 7735 7736 7737 7738 7739 7740 7741 7742 7743
#endif
        default:            /* Invalid */
            MIPS_INVAL("special3");
            generate_exception(ctx, EXCP_RI);
            break;
        }
        break;
    case OPC_REGIMM:
        op1 = MASK_REGIMM(ctx->opcode);
        switch (op1) {
        case OPC_BLTZ ... OPC_BGEZL: /* REGIMM branches */
        case OPC_BLTZAL ... OPC_BGEZALL:
            gen_compute_branch(ctx, op1, rs, -1, imm << 2);
B
bellard 已提交
7744
            return;
7745 7746 7747 7748 7749
        case OPC_TGEI ... OPC_TEQI: /* REGIMM traps */
        case OPC_TNEI:
            gen_trap(ctx, op1, rs, -1, imm);
            break;
        case OPC_SYNCI:
7750
            check_insn(env, ctx, ISA_MIPS32R2);
7751
            /* Treat as NOP. */
B
bellard 已提交
7752 7753
            break;
        default:            /* Invalid */
7754
            MIPS_INVAL("regimm");
B
bellard 已提交
7755 7756 7757 7758
            generate_exception(ctx, EXCP_RI);
            break;
        }
        break;
7759
    case OPC_CP0:
7760
        check_cp0_enabled(ctx);
7761
        op1 = MASK_CP0(ctx->opcode);
B
bellard 已提交
7762
        switch (op1) {
7763 7764
        case OPC_MFC0:
        case OPC_MTC0:
7765 7766
        case OPC_MFTR:
        case OPC_MTTR:
7767
#if defined(TARGET_MIPS64)
7768 7769 7770
        case OPC_DMFC0:
        case OPC_DMTC0:
#endif
7771
#ifndef CONFIG_USER_ONLY
7772
            gen_cp0(env, ctx, op1, rt, rd);
T
ths 已提交
7773
#endif /* !CONFIG_USER_ONLY */
7774 7775
            break;
        case OPC_C0_FIRST ... OPC_C0_LAST:
7776
#ifndef CONFIG_USER_ONLY
7777
            gen_cp0(env, ctx, MASK_C0(ctx->opcode), rt, rd);
T
ths 已提交
7778
#endif /* !CONFIG_USER_ONLY */
7779 7780
            break;
        case OPC_MFMC0:
7781
#ifndef CONFIG_USER_ONLY
7782
            {
P
pbrook 已提交
7783
                TCGv t0 = tcg_temp_local_new();
7784

T
ths 已提交
7785
                op2 = MASK_MFMC0(ctx->opcode);
7786 7787 7788
                switch (op2) {
                case OPC_DMT:
                    check_insn(env, ctx, ASE_MT);
P
pbrook 已提交
7789
                    gen_helper_dmt(t0, t0);
7790 7791 7792
                    break;
                case OPC_EMT:
                    check_insn(env, ctx, ASE_MT);
P
pbrook 已提交
7793
                    gen_helper_emt(t0, t0);
7794
                    break;
7795 7796
                case OPC_DVPE:
                    check_insn(env, ctx, ASE_MT);
P
pbrook 已提交
7797
                    gen_helper_dvpe(t0, t0);
7798 7799 7800
                    break;
                case OPC_EVPE:
                    check_insn(env, ctx, ASE_MT);
P
pbrook 已提交
7801
                    gen_helper_evpe(t0, t0);
7802 7803 7804 7805
                    break;
                case OPC_DI:
                    check_insn(env, ctx, ISA_MIPS32R2);
                    save_cpu_state(ctx, 1);
P
pbrook 已提交
7806
                    gen_helper_di(t0);
7807 7808 7809 7810 7811 7812
                    /* Stop translation as we may have switched the execution mode */
                    ctx->bstate = BS_STOP;
                    break;
                case OPC_EI:
                    check_insn(env, ctx, ISA_MIPS32R2);
                    save_cpu_state(ctx, 1);
P
pbrook 已提交
7813
                    gen_helper_ei(t0);
7814 7815 7816 7817 7818 7819 7820 7821 7822 7823
                    /* Stop translation as we may have switched the execution mode */
                    ctx->bstate = BS_STOP;
                    break;
                default:            /* Invalid */
                    MIPS_INVAL("mfmc0");
                    generate_exception(ctx, EXCP_RI);
                    break;
                }
                gen_store_gpr(t0, rt);
                tcg_temp_free(t0);
7824
            }
T
ths 已提交
7825
#endif /* !CONFIG_USER_ONLY */
B
bellard 已提交
7826
            break;
7827
        case OPC_RDPGPR:
7828
            check_insn(env, ctx, ISA_MIPS32R2);
7829
            gen_load_srsgpr(rt, rd);
7830
            break;
7831
        case OPC_WRPGPR:
7832
            check_insn(env, ctx, ISA_MIPS32R2);
7833
            gen_store_srsgpr(rt, rd);
7834
            break;
B
bellard 已提交
7835
        default:
7836
            MIPS_INVAL("cp0");
7837
            generate_exception(ctx, EXCP_RI);
B
bellard 已提交
7838 7839 7840
            break;
        }
        break;
7841
    case OPC_ADDI ... OPC_LUI: /* Arithmetic with immediate opcode */
7842
         gen_arith_imm(env, ctx, op, rt, rs, imm);
7843 7844 7845 7846 7847 7848 7849 7850 7851 7852 7853 7854 7855 7856 7857 7858 7859
         break;
    case OPC_J ... OPC_JAL: /* Jump */
         offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2;
         gen_compute_branch(ctx, op, rs, rt, offset);
         return;
    case OPC_BEQ ... OPC_BGTZ: /* Branch */
    case OPC_BEQL ... OPC_BGTZL:
         gen_compute_branch(ctx, op, rs, rt, imm << 2);
         return;
    case OPC_LB ... OPC_LWR: /* Load and stores */
    case OPC_SB ... OPC_SW:
    case OPC_SWR:
    case OPC_LL:
    case OPC_SC:
         gen_ldst(ctx, op, rt, rs, imm);
         break;
    case OPC_CACHE:
7860
        check_insn(env, ctx, ISA_MIPS3 | ISA_MIPS32);
7861
        /* Treat as NOP. */
7862
        break;
7863
    case OPC_PREF:
7864
        check_insn(env, ctx, ISA_MIPS4 | ISA_MIPS32);
7865
        /* Treat as NOP. */
B
bellard 已提交
7866
        break;
B
bellard 已提交
7867

7868
    /* Floating point (COP1). */
7869 7870 7871 7872
    case OPC_LWC1:
    case OPC_LDC1:
    case OPC_SWC1:
    case OPC_SDC1:
7873 7874
        if (env->CP0_Config1 & (1 << CP0C1_FP)) {
            save_cpu_state(ctx, 1);
7875
            check_cp1_enabled(ctx);
7876 7877 7878 7879
            gen_flt_ldst(ctx, op, rt, rs, imm);
        } else {
            generate_exception_err(ctx, EXCP_CpU, 1);
        }
B
bellard 已提交
7880 7881
        break;

7882
    case OPC_CP1:
7883 7884
        if (env->CP0_Config1 & (1 << CP0C1_FP)) {
            save_cpu_state(ctx, 1);
7885
            check_cp1_enabled(ctx);
7886 7887
            op1 = MASK_CP1(ctx->opcode);
            switch (op1) {
7888 7889
            case OPC_MFHC1:
            case OPC_MTHC1:
7890
                check_insn(env, ctx, ISA_MIPS32R2);
7891 7892 7893 7894
            case OPC_MFC1:
            case OPC_CFC1:
            case OPC_MTC1:
            case OPC_CTC1:
7895 7896
                gen_cp1(ctx, op1, rt, rd);
                break;
7897
#if defined(TARGET_MIPS64)
7898 7899
            case OPC_DMFC1:
            case OPC_DMTC1:
7900
                check_insn(env, ctx, ISA_MIPS3);
7901 7902
                gen_cp1(ctx, op1, rt, rd);
                break;
7903
#endif
7904 7905
            case OPC_BC1ANY2:
            case OPC_BC1ANY4:
7906
                check_cop1x(ctx);
7907
                check_insn(env, ctx, ASE_MIPS3D);
7908 7909
                /* fall through */
            case OPC_BC1:
7910
                gen_compute_branch1(env, ctx, MASK_BC1(ctx->opcode),
7911
                                    (rt >> 2) & 0x7, imm << 2);
7912 7913 7914 7915 7916
                return;
            case OPC_S_FMT:
            case OPC_D_FMT:
            case OPC_W_FMT:
            case OPC_L_FMT:
7917 7918 7919
            case OPC_PS_FMT:
                gen_farith(ctx, MASK_CP1_FUNC(ctx->opcode), rt, rd, sa,
                           (imm >> 8) & 0x7);
7920 7921
                break;
            default:
7922
                MIPS_INVAL("cp1");
7923
                generate_exception (ctx, EXCP_RI);
7924 7925 7926 7927
                break;
            }
        } else {
            generate_exception_err(ctx, EXCP_CpU, 1);
B
bellard 已提交
7928
        }
B
bellard 已提交
7929 7930 7931
        break;

    /* COP2.  */
7932 7933 7934 7935 7936 7937
    case OPC_LWC2:
    case OPC_LDC2:
    case OPC_SWC2:
    case OPC_SDC2:
    case OPC_CP2:
        /* COP2: Not implemented. */
B
bellard 已提交
7938 7939 7940
        generate_exception_err(ctx, EXCP_CpU, 2);
        break;

7941
    case OPC_CP3:
7942
        if (env->CP0_Config1 & (1 << CP0C1_FP)) {
7943
            save_cpu_state(ctx, 1);
7944
            check_cp1_enabled(ctx);
7945 7946
            op1 = MASK_CP3(ctx->opcode);
            switch (op1) {
7947 7948 7949 7950 7951 7952
            case OPC_LWXC1:
            case OPC_LDXC1:
            case OPC_LUXC1:
            case OPC_SWXC1:
            case OPC_SDXC1:
            case OPC_SUXC1:
T
ths 已提交
7953
                gen_flt3_ldst(ctx, op1, sa, rd, rs, rt);
7954
                break;
T
ths 已提交
7955
            case OPC_PREFX:
7956
                /* Treat as NOP. */
T
ths 已提交
7957
                break;
7958 7959 7960 7961 7962 7963 7964 7965 7966 7967 7968 7969 7970 7971 7972
            case OPC_ALNV_PS:
            case OPC_MADD_S:
            case OPC_MADD_D:
            case OPC_MADD_PS:
            case OPC_MSUB_S:
            case OPC_MSUB_D:
            case OPC_MSUB_PS:
            case OPC_NMADD_S:
            case OPC_NMADD_D:
            case OPC_NMADD_PS:
            case OPC_NMSUB_S:
            case OPC_NMSUB_D:
            case OPC_NMSUB_PS:
                gen_flt3_arith(ctx, op1, sa, rs, rd, rt);
                break;
7973
            default:
7974
                MIPS_INVAL("cp3");
7975
                generate_exception (ctx, EXCP_RI);
7976 7977 7978
                break;
            }
        } else {
7979
            generate_exception_err(ctx, EXCP_CpU, 1);
7980
        }
B
bellard 已提交
7981 7982
        break;

7983
#if defined(TARGET_MIPS64)
7984 7985 7986 7987 7988 7989 7990 7991
    /* MIPS64 opcodes */
    case OPC_LWU:
    case OPC_LDL ... OPC_LDR:
    case OPC_SDL ... OPC_SDR:
    case OPC_LLD:
    case OPC_LD:
    case OPC_SCD:
    case OPC_SD:
7992 7993
        check_insn(env, ctx, ISA_MIPS3);
        check_mips_64(ctx);
7994 7995 7996
        gen_ldst(ctx, op, rt, rs, imm);
        break;
    case OPC_DADDI ... OPC_DADDIU:
7997 7998 7999
        check_insn(env, ctx, ISA_MIPS3);
        check_mips_64(ctx);
        gen_arith_imm(env, ctx, op, rt, rs, imm);
8000
        break;
B
bellard 已提交
8001
#endif
8002
    case OPC_JALX:
8003
        check_insn(env, ctx, ASE_MIPS16);
8004 8005
        /* MIPS16: Not implemented. */
    case OPC_MDMX:
8006
        check_insn(env, ctx, ASE_MDMX);
8007
        /* MDMX: Not implemented. */
B
bellard 已提交
8008
    default:            /* Invalid */
8009
        MIPS_INVAL("major opcode");
B
bellard 已提交
8010 8011 8012
        generate_exception(ctx, EXCP_RI);
        break;
    }
B
bellard 已提交
8013
    if (ctx->hflags & MIPS_HFLAG_BMASK) {
T
ths 已提交
8014
        int hflags = ctx->hflags & MIPS_HFLAG_BMASK;
B
bellard 已提交
8015
        /* Branches completion */
B
bellard 已提交
8016
        ctx->hflags &= ~MIPS_HFLAG_BMASK;
B
bellard 已提交
8017 8018
        ctx->bstate = BS_BRANCH;
        save_cpu_state(ctx, 0);
P
pbrook 已提交
8019
        /* FIXME: Need to clear can_do_io.  */
8020
        switch (hflags) {
B
bellard 已提交
8021 8022 8023
        case MIPS_HFLAG_B:
            /* unconditional branch */
            MIPS_DEBUG("unconditional branch");
8024
            gen_goto_tb(ctx, 0, ctx->btarget);
B
bellard 已提交
8025 8026 8027 8028
            break;
        case MIPS_HFLAG_BL:
            /* blikely taken case */
            MIPS_DEBUG("blikely branch taken");
8029
            gen_goto_tb(ctx, 0, ctx->btarget);
B
bellard 已提交
8030 8031 8032 8033
            break;
        case MIPS_HFLAG_BC:
            /* Conditional branch */
            MIPS_DEBUG("conditional branch");
B
bellard 已提交
8034
            {
8035 8036
                int l1 = gen_new_label();

8037
                tcg_gen_brcondi_tl(TCG_COND_NE, bcond, 0, l1);
8038 8039 8040
                gen_goto_tb(ctx, 1, ctx->pc + 4);
                gen_set_label(l1);
                gen_goto_tb(ctx, 0, ctx->btarget);
B
bellard 已提交
8041
            }
B
bellard 已提交
8042 8043 8044 8045
            break;
        case MIPS_HFLAG_BR:
            /* unconditional branch to register */
            MIPS_DEBUG("branch to register");
8046
            tcg_gen_mov_tl(cpu_PC, btarget);
B
bellard 已提交
8047
            tcg_gen_exit_tb(0);
B
bellard 已提交
8048 8049 8050 8051 8052 8053 8054 8055
            break;
        default:
            MIPS_DEBUG("unknown branch");
            break;
        }
    }
}

8056
static inline void
8057 8058
gen_intermediate_code_internal (CPUState *env, TranslationBlock *tb,
                                int search_pc)
B
bellard 已提交
8059
{
T
ths 已提交
8060
    DisasContext ctx;
B
bellard 已提交
8061 8062
    target_ulong pc_start;
    uint16_t *gen_opc_end;
8063
    CPUBreakpoint *bp;
B
bellard 已提交
8064
    int j, lj = -1;
P
pbrook 已提交
8065 8066
    int num_insns;
    int max_insns;
B
bellard 已提交
8067

8068 8069
    if (search_pc)
        qemu_log("search pc %d\n", search_pc);
B
bellard 已提交
8070

B
bellard 已提交
8071
    pc_start = tb->pc;
T
ths 已提交
8072 8073
    /* Leave some spare opc slots for branch handling. */
    gen_opc_end = gen_opc_buf + OPC_MAX_SIZE - 16;
B
bellard 已提交
8074
    ctx.pc = pc_start;
B
bellard 已提交
8075
    ctx.saved_pc = -1;
B
bellard 已提交
8076 8077
    ctx.tb = tb;
    ctx.bstate = BS_NONE;
B
bellard 已提交
8078
    /* Restore delay slot state from the tb context.  */
8079
    ctx.hflags = (uint32_t)tb->flags; /* FIXME: maybe use 64 bits here? */
8080
    restore_cpu_state(env, &ctx);
8081
#ifdef CONFIG_USER_ONLY
T
ths 已提交
8082
        ctx.mem_idx = MIPS_HFLAG_UM;
8083
#else
T
ths 已提交
8084
        ctx.mem_idx = ctx.hflags & MIPS_HFLAG_KSU;
8085
#endif
P
pbrook 已提交
8086 8087 8088 8089
    num_insns = 0;
    max_insns = tb->cflags & CF_COUNT_MASK;
    if (max_insns == 0)
        max_insns = CF_COUNT_MASK;
B
bellard 已提交
8090
#ifdef DEBUG_DISAS
8091 8092 8093
    qemu_log_mask(CPU_LOG_TB_CPU, "------------------------------------------------\n");
    /* FIXME: This may print out stale hflags from env... */
    log_cpu_state_mask(CPU_LOG_TB_CPU, env, 0);
B
bellard 已提交
8094
#endif
8095
    LOG_DISAS("\ntb %p idx %d hflags %04x\n", tb, ctx.mem_idx, ctx.hflags);
P
pbrook 已提交
8096
    gen_icount_start();
T
ths 已提交
8097
    while (ctx.bstate == BS_NONE) {
8098 8099
        if (unlikely(!TAILQ_EMPTY(&env->breakpoints))) {
            TAILQ_FOREACH(bp, &env->breakpoints, entry) {
8100
                if (bp->pc == ctx.pc) {
T
ths 已提交
8101
                    save_cpu_state(&ctx, 1);
B
bellard 已提交
8102
                    ctx.bstate = BS_BRANCH;
P
pbrook 已提交
8103
                    gen_helper_0i(raise_exception, EXCP_DEBUG);
8104 8105 8106
                    /* Include the breakpoint location or the tb won't
                     * be flushed when it must be.  */
                    ctx.pc += 4;
B
bellard 已提交
8107 8108 8109 8110 8111
                    goto done_generating;
                }
            }
        }

B
bellard 已提交
8112 8113 8114 8115 8116 8117 8118
        if (search_pc) {
            j = gen_opc_ptr - gen_opc_buf;
            if (lj < j) {
                lj++;
                while (lj < j)
                    gen_opc_instr_start[lj++] = 0;
            }
B
bellard 已提交
8119 8120 8121
            gen_opc_pc[lj] = ctx.pc;
            gen_opc_hflags[lj] = ctx.hflags & MIPS_HFLAG_BMASK;
            gen_opc_instr_start[lj] = 1;
P
pbrook 已提交
8122
            gen_opc_icount[lj] = num_insns;
B
bellard 已提交
8123
        }
P
pbrook 已提交
8124 8125
        if (num_insns + 1 == max_insns && (tb->cflags & CF_LAST_IO))
            gen_io_start();
B
bellard 已提交
8126
        ctx.opcode = ldl_code(ctx.pc);
8127
        decode_opc(env, &ctx);
B
bellard 已提交
8128
        ctx.pc += 4;
P
pbrook 已提交
8129
        num_insns++;
B
bellard 已提交
8130 8131 8132 8133

        if (env->singlestep_enabled)
            break;

B
bellard 已提交
8134 8135
        if ((ctx.pc & (TARGET_PAGE_SIZE - 1)) == 0)
            break;
B
bellard 已提交
8136

T
ths 已提交
8137 8138 8139
        if (gen_opc_ptr >= gen_opc_end)
            break;

P
pbrook 已提交
8140 8141
        if (num_insns >= max_insns)
            break;
8142 8143 8144

        if (singlestep)
            break;
B
bellard 已提交
8145
    }
P
pbrook 已提交
8146 8147
    if (tb->cflags & CF_LAST_IO)
        gen_io_end();
B
bellard 已提交
8148
    if (env->singlestep_enabled) {
T
ths 已提交
8149
        save_cpu_state(&ctx, ctx.bstate == BS_NONE);
P
pbrook 已提交
8150
        gen_helper_0i(raise_exception, EXCP_DEBUG);
T
ths 已提交
8151
    } else {
A
aurel32 已提交
8152
        switch (ctx.bstate) {
T
ths 已提交
8153
        case BS_STOP:
P
pbrook 已提交
8154
            gen_helper_interrupt_restart();
8155 8156
            gen_goto_tb(&ctx, 0, ctx.pc);
            break;
T
ths 已提交
8157
        case BS_NONE:
T
ths 已提交
8158
            save_cpu_state(&ctx, 0);
T
ths 已提交
8159 8160
            gen_goto_tb(&ctx, 0, ctx.pc);
            break;
8161
        case BS_EXCP:
P
pbrook 已提交
8162
            gen_helper_interrupt_restart();
B
bellard 已提交
8163
            tcg_gen_exit_tb(0);
T
ths 已提交
8164
            break;
8165 8166 8167
        case BS_BRANCH:
        default:
            break;
A
aurel32 已提交
8168
        }
B
bellard 已提交
8169
    }
B
bellard 已提交
8170
done_generating:
P
pbrook 已提交
8171
    gen_icount_end(tb, num_insns);
B
bellard 已提交
8172 8173 8174 8175 8176 8177 8178 8179
    *gen_opc_ptr = INDEX_op_end;
    if (search_pc) {
        j = gen_opc_ptr - gen_opc_buf;
        lj++;
        while (lj <= j)
            gen_opc_instr_start[lj++] = 0;
    } else {
        tb->size = ctx.pc - pc_start;
P
pbrook 已提交
8180
        tb->icount = num_insns;
B
bellard 已提交
8181 8182
    }
#ifdef DEBUG_DISAS
8183
    LOG_DISAS("\n");
8184
    if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) {
8185 8186 8187
        qemu_log("IN: %s\n", lookup_symbol(pc_start));
        log_target_disas(pc_start, ctx.pc - pc_start, 0);
        qemu_log("\n");
B
bellard 已提交
8188
    }
8189
    qemu_log_mask(CPU_LOG_TB_CPU, "---------------- %d %08x\n", ctx.bstate, ctx.hflags);
B
bellard 已提交
8190 8191 8192
#endif
}

8193
void gen_intermediate_code (CPUState *env, struct TranslationBlock *tb)
B
bellard 已提交
8194
{
8195
    gen_intermediate_code_internal(env, tb, 0);
B
bellard 已提交
8196 8197
}

8198
void gen_intermediate_code_pc (CPUState *env, struct TranslationBlock *tb)
B
bellard 已提交
8199
{
8200
    gen_intermediate_code_internal(env, tb, 1);
B
bellard 已提交
8201 8202
}

8203 8204 8205
static void fpu_dump_state(CPUState *env, FILE *f,
                           int (*fpu_fprintf)(FILE *f, const char *fmt, ...),
                           int flags)
B
bellard 已提交
8206 8207
{
    int i;
8208
    int is_fpu64 = !!(env->hflags & MIPS_HFLAG_F64);
8209 8210 8211 8212 8213 8214 8215 8216 8217 8218 8219 8220 8221 8222 8223

#define printfpr(fp)                                                        \
    do {                                                                    \
        if (is_fpu64)                                                       \
            fpu_fprintf(f, "w:%08x d:%016lx fd:%13g fs:%13g psu: %13g\n",   \
                        (fp)->w[FP_ENDIAN_IDX], (fp)->d, (fp)->fd,          \
                        (fp)->fs[FP_ENDIAN_IDX], (fp)->fs[!FP_ENDIAN_IDX]); \
        else {                                                              \
            fpr_t tmp;                                                      \
            tmp.w[FP_ENDIAN_IDX] = (fp)->w[FP_ENDIAN_IDX];                  \
            tmp.w[!FP_ENDIAN_IDX] = ((fp) + 1)->w[FP_ENDIAN_IDX];           \
            fpu_fprintf(f, "w:%08x d:%016lx fd:%13g fs:%13g psu:%13g\n",    \
                        tmp.w[FP_ENDIAN_IDX], tmp.d, tmp.fd,                \
                        tmp.fs[FP_ENDIAN_IDX], tmp.fs[!FP_ENDIAN_IDX]);     \
        }                                                                   \
B
bellard 已提交
8224 8225
    } while(0)

8226 8227

    fpu_fprintf(f, "CP1 FCR0 0x%08x  FCR31 0x%08x  SR.FR %d  fp_status 0x%08x(0x%02x)\n",
8228 8229
                env->active_fpu.fcr0, env->active_fpu.fcr31, is_fpu64, env->active_fpu.fp_status,
                get_float_exception_flags(&env->active_fpu.fp_status));
8230 8231
    for (i = 0; i < 32; (is_fpu64) ? i++ : (i += 2)) {
        fpu_fprintf(f, "%3s: ", fregnames[i]);
8232
        printfpr(&env->active_fpu.fpr[i]);
B
bellard 已提交
8233 8234 8235 8236 8237
    }

#undef printfpr
}

8238
#if defined(TARGET_MIPS64) && defined(MIPS_DEBUG_SIGN_EXTENSIONS)
8239
/* Debug help: The architecture requires 32bit code to maintain proper
T
ths 已提交
8240
   sign-extended values on 64bit machines.  */
8241 8242 8243

#define SIGN_EXT_P(val) ((((val) & ~0x7fffffff) == 0) || (((val) & ~0x7fffffff) == ~0x7fffffff))

8244 8245 8246 8247
static void
cpu_mips_check_sign_extensions (CPUState *env, FILE *f,
                                int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
                                int flags)
8248 8249 8250
{
    int i;

8251 8252 8253 8254 8255 8256
    if (!SIGN_EXT_P(env->active_tc.PC))
        cpu_fprintf(f, "BROKEN: pc=0x" TARGET_FMT_lx "\n", env->active_tc.PC);
    if (!SIGN_EXT_P(env->active_tc.HI[0]))
        cpu_fprintf(f, "BROKEN: HI=0x" TARGET_FMT_lx "\n", env->active_tc.HI[0]);
    if (!SIGN_EXT_P(env->active_tc.LO[0]))
        cpu_fprintf(f, "BROKEN: LO=0x" TARGET_FMT_lx "\n", env->active_tc.LO[0]);
8257
    if (!SIGN_EXT_P(env->btarget))
T
ths 已提交
8258
        cpu_fprintf(f, "BROKEN: btarget=0x" TARGET_FMT_lx "\n", env->btarget);
8259 8260

    for (i = 0; i < 32; i++) {
8261 8262
        if (!SIGN_EXT_P(env->active_tc.gpr[i]))
            cpu_fprintf(f, "BROKEN: %s=0x" TARGET_FMT_lx "\n", regnames[i], env->active_tc.gpr[i]);
8263 8264 8265
    }

    if (!SIGN_EXT_P(env->CP0_EPC))
T
ths 已提交
8266
        cpu_fprintf(f, "BROKEN: EPC=0x" TARGET_FMT_lx "\n", env->CP0_EPC);
8267
    if (!SIGN_EXT_P(env->CP0_LLAddr))
T
ths 已提交
8268
        cpu_fprintf(f, "BROKEN: LLAddr=0x" TARGET_FMT_lx "\n", env->CP0_LLAddr);
8269 8270 8271
}
#endif

8272
void cpu_dump_state (CPUState *env, FILE *f,
B
bellard 已提交
8273 8274 8275 8276
                     int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
                     int flags)
{
    int i;
8277

T
ths 已提交
8278
    cpu_fprintf(f, "pc=0x" TARGET_FMT_lx " HI=0x" TARGET_FMT_lx " LO=0x" TARGET_FMT_lx " ds %04x " TARGET_FMT_lx " %d\n",
8279 8280
                env->active_tc.PC, env->active_tc.HI[0], env->active_tc.LO[0],
                env->hflags, env->btarget, env->bcond);
B
bellard 已提交
8281 8282 8283
    for (i = 0; i < 32; i++) {
        if ((i & 3) == 0)
            cpu_fprintf(f, "GPR%02d:", i);
8284
        cpu_fprintf(f, " %s " TARGET_FMT_lx, regnames[i], env->active_tc.gpr[i]);
B
bellard 已提交
8285 8286 8287
        if ((i & 3) == 3)
            cpu_fprintf(f, "\n");
    }
8288

T
ths 已提交
8289
    cpu_fprintf(f, "CP0 Status  0x%08x Cause   0x%08x EPC    0x" TARGET_FMT_lx "\n",
8290
                env->CP0_Status, env->CP0_Cause, env->CP0_EPC);
T
ths 已提交
8291
    cpu_fprintf(f, "    Config0 0x%08x Config1 0x%08x LLAddr 0x" TARGET_FMT_lx "\n",
B
bellard 已提交
8292
                env->CP0_Config0, env->CP0_Config1, env->CP0_LLAddr);
8293
    if (env->hflags & MIPS_HFLAG_FPU)
8294
        fpu_dump_state(env, f, cpu_fprintf, flags);
8295
#if defined(TARGET_MIPS64) && defined(MIPS_DEBUG_SIGN_EXTENSIONS)
8296 8297
    cpu_mips_check_sign_extensions(env, f, cpu_fprintf, flags);
#endif
B
bellard 已提交
8298 8299
}

8300 8301
static void mips_tcg_init(void)
{
8302
    int i;
8303 8304 8305 8306
    static int inited;

    /* Initialize various static tables. */
    if (inited)
A
aurel32 已提交
8307
        return;
8308

P
pbrook 已提交
8309
    cpu_env = tcg_global_reg_new_ptr(TCG_AREG0, "env");
8310
    for (i = 0; i < 32; i++)
P
pbrook 已提交
8311
        cpu_gpr[i] = tcg_global_mem_new(TCG_AREG0,
8312 8313
                                        offsetof(CPUState, active_tc.gpr[i]),
                                        regnames[i]);
P
pbrook 已提交
8314
    cpu_PC = tcg_global_mem_new(TCG_AREG0,
8315 8316
                                offsetof(CPUState, active_tc.PC), "PC");
    for (i = 0; i < MIPS_DSP_ACC; i++) {
P
pbrook 已提交
8317
        cpu_HI[i] = tcg_global_mem_new(TCG_AREG0,
8318 8319
                                       offsetof(CPUState, active_tc.HI[i]),
                                       regnames_HI[i]);
P
pbrook 已提交
8320
        cpu_LO[i] = tcg_global_mem_new(TCG_AREG0,
8321 8322
                                       offsetof(CPUState, active_tc.LO[i]),
                                       regnames_LO[i]);
P
pbrook 已提交
8323
        cpu_ACX[i] = tcg_global_mem_new(TCG_AREG0,
8324 8325 8326
                                        offsetof(CPUState, active_tc.ACX[i]),
                                        regnames_ACX[i]);
    }
P
pbrook 已提交
8327
    cpu_dspctrl = tcg_global_mem_new(TCG_AREG0,
8328 8329
                                     offsetof(CPUState, active_tc.DSPControl),
                                     "DSPControl");
8330 8331
    bcond = tcg_global_mem_new(TCG_AREG0,
                               offsetof(CPUState, bcond), "bcond");
P
pbrook 已提交
8332
    btarget = tcg_global_mem_new(TCG_AREG0,
T
ths 已提交
8333
                                 offsetof(CPUState, btarget), "btarget");
8334 8335 8336
    hflags = tcg_global_mem_new_i32(TCG_AREG0,
                                    offsetof(CPUState, hflags), "hflags");

P
pbrook 已提交
8337 8338 8339 8340 8341 8342
    fpu_fcr0 = tcg_global_mem_new_i32(TCG_AREG0,
                                      offsetof(CPUState, active_fpu.fcr0),
                                      "fcr0");
    fpu_fcr31 = tcg_global_mem_new_i32(TCG_AREG0,
                                       offsetof(CPUState, active_fpu.fcr31),
                                       "fcr31");
8343

T
ths 已提交
8344
    /* register helpers */
P
pbrook 已提交
8345
#define GEN_HELPER 2
T
ths 已提交
8346 8347
#include "helper.h"

8348 8349 8350
    inited = 1;
}

B
bellard 已提交
8351 8352 8353
#include "translate_init.c"

CPUMIPSState *cpu_mips_init (const char *cpu_model)
B
bellard 已提交
8354 8355
{
    CPUMIPSState *env;
B
bellard 已提交
8356
    const mips_def_t *def;
B
bellard 已提交
8357

B
bellard 已提交
8358 8359 8360
    def = cpu_mips_find_by_name(cpu_model);
    if (!def)
        return NULL;
B
bellard 已提交
8361
    env = qemu_mallocz(sizeof(CPUMIPSState));
B
bellard 已提交
8362 8363
    env->cpu_model = def;

B
bellard 已提交
8364
    cpu_exec_init(env);
8365
    env->cpu_model_str = cpu_model;
8366
    mips_tcg_init();
8367 8368 8369 8370 8371 8372
    cpu_reset(env);
    return env;
}

void cpu_reset (CPUMIPSState *env)
{
A
aliguori 已提交
8373 8374 8375 8376 8377
    if (qemu_loglevel_mask(CPU_LOG_RESET)) {
        qemu_log("CPU Reset (CPU %d)\n", env->cpu_index);
        log_cpu_state(env, 0);
    }

8378 8379
    memset(env, 0, offsetof(CPUMIPSState, breakpoints));

B
bellard 已提交
8380
    tlb_flush(env, 1);
8381

B
bellard 已提交
8382
    /* Minimal init */
T
ths 已提交
8383
#if defined(CONFIG_USER_ONLY)
8384 8385 8386 8387 8388 8389
    env->hflags = MIPS_HFLAG_UM;
#else
    if (env->hflags & MIPS_HFLAG_BMASK) {
        /* If the exception was raised from a delay slot,
           come back to the jump.  */
        env->CP0_ErrorEPC = env->active_tc.PC - 4;
8390
    } else {
8391 8392 8393 8394 8395 8396 8397 8398 8399 8400 8401 8402 8403 8404 8405 8406
        env->CP0_ErrorEPC = env->active_tc.PC;
    }
    env->active_tc.PC = (int32_t)0xBFC00000;
    env->CP0_Wired = 0;
    /* SMP not implemented */
    env->CP0_EBase = 0x80000000;
    env->CP0_Status = (1 << CP0St_BEV) | (1 << CP0St_ERL);
    /* vectored interrupts not implemented, timer on int 7,
       no performance counters. */
    env->CP0_IntCtl = 0xe0000000;
    {
        int i;

        for (i = 0; i < 7; i++) {
            env->CP0_WatchLo[i] = 0;
            env->CP0_WatchHi[i] = 0x80000000;
8407
        }
8408 8409
        env->CP0_WatchLo[7] = 0;
        env->CP0_WatchHi[7] = 0;
8410
    }
8411 8412 8413 8414
    /* Count register increments in debug mode, EJTAG version 1 */
    env->CP0_Debug = (1 << CP0DB_CNT) | (0x1 << CP0DB_VER);
    env->hflags = MIPS_HFLAG_CP0;
#endif
B
bellard 已提交
8415
    env->exception_index = EXCP_NONE;
B
bellard 已提交
8416
    cpu_mips_register(env, env->cpu_model);
B
bellard 已提交
8417
}
A
aurel32 已提交
8418 8419 8420 8421

void gen_pc_load(CPUState *env, TranslationBlock *tb,
                unsigned long searched_pc, int pc_pos, void *puc)
{
8422
    env->active_tc.PC = gen_opc_pc[pc_pos];
A
aurel32 已提交
8423 8424 8425
    env->hflags &= ~MIPS_HFLAG_BMASK;
    env->hflags |= gen_opc_hflags[pc_pos];
}