translate.c 224.6 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 20 21 22 23 24 25 26 27 28 29 30 31
 *
 * 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
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */

#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"
32
#include "helper.h"
B
bellard 已提交
33
#include "tcg-op.h"
34
#include "qemu-common.h"
B
bellard 已提交
35

36
//#define MIPS_DEBUG_DISAS
37
//#define MIPS_DEBUG_SIGN_EXTENSIONS
B
bellard 已提交
38 39
//#define MIPS_SINGLE_STEP

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

enum {
    /* indirect opcode tables */
45 46 47 48 49 50 51 52
    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),
53
    /* arithmetic with immediate */
54 55 56 57 58 59 60 61 62 63
    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),
64
    /* Jump and branches */
65 66 67 68 69 70 71 72 73 74 75
    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 */
76
    /* Load and stores */
77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99
    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),
100
    /* Floating point load/store */
101 102 103 104 105 106 107 108 109 110
    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),
111
    /* Cache and prefetch */
112 113 114 115
    OPC_CACHE    = (0x2F << 26),
    OPC_PREF     = (0x33 << 26),
    /* Reserved major opcode */
    OPC_MAJOR3B_RESERVED = (0x3B << 26),
116 117 118
};

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

121 122
enum {
    /* Shifts */
123
    OPC_SLL      = 0x00 | OPC_SPECIAL,
124 125
    /* NOP is SLL r0, r0, 0   */
    /* SSNOP is SLL r0, r0, 1 */
126 127 128 129
    /* EHB is SLL r0, r0, 3 */
    OPC_SRL      = 0x02 | OPC_SPECIAL, /* also ROTR */
    OPC_SRA      = 0x03 | OPC_SPECIAL,
    OPC_SLLV     = 0x04 | OPC_SPECIAL,
130
    OPC_SRLV     = 0x06 | OPC_SPECIAL, /* also ROTRV */
131 132 133 134 135 136 137 138 139 140
    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,
141
    /* Multiplication / division */
142 143 144 145 146 147 148 149
    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,
150
    /* 2 registers arithmetic / logic */
151 152 153 154 155 156 157 158 159 160 161 162 163 164
    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,
165
    /* Jumps */
166 167
    OPC_JR       = 0x08 | OPC_SPECIAL, /* Also JR.HB */
    OPC_JALR     = 0x09 | OPC_SPECIAL, /* Also JALR.HB */
168
    /* Traps */
169 170 171 172 173 174
    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,
175
    /* HI / LO registers load & stores */
176 177 178 179
    OPC_MFHI     = 0x10 | OPC_SPECIAL,
    OPC_MTHI     = 0x11 | OPC_SPECIAL,
    OPC_MFLO     = 0x12 | OPC_SPECIAL,
    OPC_MTLO     = 0x13 | OPC_SPECIAL,
180
    /* Conditional moves */
181 182
    OPC_MOVZ     = 0x0A | OPC_SPECIAL,
    OPC_MOVN     = 0x0B | OPC_SPECIAL,
183

184
    OPC_MOVCI    = 0x01 | OPC_SPECIAL,
185 186

    /* Special */
187 188 189 190 191 192 193 194 195 196 197 198 199 200 201
    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,
};

202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221
/* 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,
};

222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240
/* 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,
241 242
};

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

246
enum {
247 248 249 250 251 252
    /* 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,
253
    /* Misc */
254 255 256 257
    OPC_CLZ      = 0x20 | OPC_SPECIAL2,
    OPC_CLO      = 0x21 | OPC_SPECIAL2,
    OPC_DCLZ     = 0x24 | OPC_SPECIAL2,
    OPC_DCLO     = 0x25 | OPC_SPECIAL2,
258
    /* Special */
259 260 261 262 263 264 265 266 267 268 269 270 271 272 273
    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,
274 275
    OPC_FORK     = 0x08 | OPC_SPECIAL3,
    OPC_YIELD    = 0x09 | OPC_SPECIAL3,
276 277 278
    OPC_BSHFL    = 0x20 | OPC_SPECIAL3,
    OPC_DBSHFL   = 0x24 | OPC_SPECIAL3,
    OPC_RDHWR    = 0x3B | OPC_SPECIAL3,
279 280
};

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

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

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

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

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

B
bellard 已提交
301
enum {
302 303 304 305
    OPC_MFC0     = (0x00 << 21) | OPC_CP0,
    OPC_DMFC0    = (0x01 << 21) | OPC_CP0,
    OPC_MTC0     = (0x04 << 21) | OPC_CP0,
    OPC_DMTC0    = (0x05 << 21) | OPC_CP0,
306
    OPC_MFTR     = (0x08 << 21) | OPC_CP0,
307 308
    OPC_RDPGPR   = (0x0A << 21) | OPC_CP0,
    OPC_MFMC0    = (0x0B << 21) | OPC_CP0,
309
    OPC_MTTR     = (0x0C << 21) | OPC_CP0,
310 311 312 313
    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 已提交
314
};
315 316

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

enum {
320 321 322 323
    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,
324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348
    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,
349
    OPC_MFHC1    = (0x03 << 21) | OPC_CP1,
350 351 352
    OPC_MTC1     = (0x04 << 21) | OPC_CP1,
    OPC_DMTC1    = (0x05 << 21) | OPC_CP1,
    OPC_CTC1     = (0x06 << 21) | OPC_CP1,
353
    OPC_MTHC1    = (0x07 << 21) | OPC_CP1,
354
    OPC_BC1      = (0x08 << 21) | OPC_CP1, /* bc */
355 356
    OPC_BC1ANY2  = (0x09 << 21) | OPC_CP1,
    OPC_BC1ANY4  = (0x0A << 21) | OPC_CP1,
357 358 359 360 361 362
    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 */
363
    OPC_PS_FMT   = (0x16 << 21) | OPC_CP1, /* 22: fmt=paired single fp */
364 365
};

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

369 370 371 372 373 374 375
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,
};

376 377 378 379 380 381 382 383 384
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,
};
385 386

#define MASK_CP2(op)       MASK_OP_MAJOR(op) | (op & (0x1F << 21))
T
ths 已提交
387 388 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

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,
418
    OPC_NMADD_D = 0x31 | OPC_CP3,
T
ths 已提交
419 420 421 422 423 424
    OPC_NMADD_PS= 0x36 | OPC_CP3,
    OPC_NMSUB_S = 0x38 | OPC_CP3,
    OPC_NMSUB_D = 0x39 | OPC_CP3,
    OPC_NMSUB_PS= 0x3E | OPC_CP3,
};

425
/* global register indices */
T
ths 已提交
426 427 428 429
static TCGv cpu_env, current_tc_gprs, current_tc_hi, current_fpu, cpu_T[2];

/* FPU TNs, global for now. */
static TCGv fpu32_T[3], fpu64_T[3], fpu32h_T[3];
B
bellard 已提交
430

T
ths 已提交
431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448
static inline void tcg_gen_helper_0_1i(void *func, TCGv arg)
{
    TCGv t = tcg_const_i32(arg);

    tcg_gen_helper_0_1(func, t);
    tcg_temp_free(t);
}

static inline void tcg_gen_helper_0_2ii(void *func, TCGv arg1, TCGv arg2)
{
    TCGv t1 = tcg_const_i32(arg1);
    TCGv t2 = tcg_const_i32(arg2);

    tcg_gen_helper_0_2(func, t1, t2);
    tcg_temp_free(t1);
    tcg_temp_free(t2);
}

449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470
typedef struct DisasContext {
    struct TranslationBlock *tb;
    target_ulong pc, saved_pc;
    uint32_t opcode;
    uint32_t fp_status;
    /* 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
                      * exception condition
                      */
    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 已提交
471 472 473 474 475
    { "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", };

476 477 478 479 480
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 已提交
481

482 483 484 485 486 487 488 489 490 491 492
#ifdef MIPS_DEBUG_DISAS
#define MIPS_DEBUG(fmt, args...)                                              \
do {                                                                          \
    if (loglevel & CPU_LOG_TB_IN_ASM) {                                       \
        fprintf(logfile, TARGET_FMT_lx ": %08x " fmt "\n",                    \
                ctx->pc, ctx->opcode , ##args);                               \
    }                                                                         \
} while (0)
#else
#define MIPS_DEBUG(fmt, args...) do { } while(0)
#endif
T
ths 已提交
493

494 495 496 497 498
#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)
499

500 501
/* General purpose registers moves. */
static inline void gen_load_gpr (TCGv t, int reg)
502
{
503 504 505 506
    if (reg == 0)
        tcg_gen_movi_tl(t, 0);
    else
        tcg_gen_ld_tl(t, current_tc_gprs, sizeof(target_ulong) * reg);
507 508
}

509
static inline void gen_store_gpr (TCGv t, int reg)
510
{
511 512
    if (reg != 0)
        tcg_gen_st_tl(t, current_tc_gprs, sizeof(target_ulong) * reg);
513 514
}

515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541
/* Moves to/from HI and LO registers.  */
static inline void gen_load_LO (TCGv t, int reg)
{
    tcg_gen_ld_tl(t, current_tc_hi,
                  offsetof(CPUState, LO)
                  - offsetof(CPUState, HI)
                  + sizeof(target_ulong) * reg);
}

static inline void gen_store_LO (TCGv t, int reg)
{
    tcg_gen_st_tl(t, current_tc_hi,
                  offsetof(CPUState, LO)
                  - offsetof(CPUState, HI)
                  + sizeof(target_ulong) * reg);
}

static inline void gen_load_HI (TCGv t, int reg)
{
    tcg_gen_ld_tl(t, current_tc_hi, sizeof(target_ulong) * reg);
}

static inline void gen_store_HI (TCGv t, int reg)
{
    tcg_gen_st_tl(t, current_tc_hi, sizeof(target_ulong) * reg);
}

542 543
/* Moves to/from shadow registers. */
static inline void gen_load_srsgpr (TCGv t, int reg)
544
{
545 546 547
    if (reg == 0)
        tcg_gen_movi_tl(t, 0);
    else {
548
        TCGv r_tmp = tcg_temp_new(TCG_TYPE_I32);
549

550 551 552 553 554
        tcg_gen_ld_i32(r_tmp, cpu_env, offsetof(CPUState, CP0_SRSCtl));
        tcg_gen_shri_i32(r_tmp, r_tmp, CP0SRSCtl_PSS);
        tcg_gen_andi_i32(r_tmp, r_tmp, 0xf);
        tcg_gen_muli_i32(r_tmp, r_tmp, sizeof(target_ulong) * 32);
        tcg_gen_add_i32(r_tmp, cpu_env, r_tmp);
555

556
        tcg_gen_ld_tl(t, r_tmp, sizeof(target_ulong) * reg);
557
        tcg_temp_free(r_tmp);
558
    }
559 560
}

561
static inline void gen_store_srsgpr (TCGv t, int reg)
562
{
563
    if (reg != 0) {
564
        TCGv r_tmp = tcg_temp_new(TCG_TYPE_I32);
565

566 567 568 569 570
        tcg_gen_ld_i32(r_tmp, cpu_env, offsetof(CPUState, CP0_SRSCtl));
        tcg_gen_shri_i32(r_tmp, r_tmp, CP0SRSCtl_PSS);
        tcg_gen_andi_i32(r_tmp, r_tmp, 0xf);
        tcg_gen_muli_i32(r_tmp, r_tmp, sizeof(target_ulong) * 32);
        tcg_gen_add_i32(r_tmp, cpu_env, r_tmp);
571

572
        tcg_gen_st_tl(t, r_tmp, sizeof(target_ulong) * reg);
573
        tcg_temp_free(r_tmp);
574
    }
575 576 577
}

/* Floating point register moves. */
T
ths 已提交
578 579 580
static inline void gen_load_fpr32 (TCGv t, int reg)
{
    tcg_gen_ld_i32(t, current_fpu, 8 * reg + 4 * FP_ENDIAN_IDX);
B
bellard 已提交
581 582
}

T
ths 已提交
583 584 585 586
static inline void gen_store_fpr32 (TCGv t, int reg)
{
    tcg_gen_st_i32(t, current_fpu, 8 * reg + 4 * FP_ENDIAN_IDX);
}
B
bellard 已提交
587

T
ths 已提交
588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605
static inline void gen_load_fpr64 (DisasContext *ctx, TCGv t, int reg)
{
    if (ctx->hflags & MIPS_HFLAG_F64) {
        tcg_gen_ld_i64(t, current_fpu, 8 * reg);
    } else {
        TCGv r_tmp1 = tcg_temp_new(TCG_TYPE_I32);
        TCGv r_tmp2 = tcg_temp_new(TCG_TYPE_I64);

        tcg_gen_ld_i32(r_tmp1, current_fpu, 8 * (reg | 1) + 4 * FP_ENDIAN_IDX);
        tcg_gen_extu_i32_i64(t, r_tmp1);
        tcg_gen_shli_i64(t, t, 32);
        tcg_gen_ld_i32(r_tmp1, current_fpu, 8 * (reg & ~1) + 4 * FP_ENDIAN_IDX);
        tcg_gen_extu_i32_i64(r_tmp2, r_tmp1);
        tcg_gen_or_i64(t, t, r_tmp2);
        tcg_temp_free(r_tmp1);
        tcg_temp_free(r_tmp2);
    }
}
B
bellard 已提交
606

T
ths 已提交
607 608 609 610 611 612
static inline void gen_store_fpr64 (DisasContext *ctx, TCGv t, int reg)
{
    if (ctx->hflags & MIPS_HFLAG_F64) {
        tcg_gen_st_i64(t, current_fpu, 8 * reg);
    } else {
        TCGv r_tmp = tcg_temp_new(TCG_TYPE_I32);
613

T
ths 已提交
614 615 616 617 618 619 620 621
        tcg_gen_trunc_i64_i32(r_tmp, t);
        tcg_gen_st_i32(r_tmp, current_fpu, 8 * (reg & ~1) + 4 * FP_ENDIAN_IDX);
        tcg_gen_shri_i64(t, t, 32);
        tcg_gen_trunc_i64_i32(r_tmp, t);
        tcg_gen_st_i32(r_tmp, current_fpu, 8 * (reg | 1) + 4 * FP_ENDIAN_IDX);
        tcg_temp_free(r_tmp);
    }
}
B
bellard 已提交
622

T
ths 已提交
623 624 625 626
static inline void gen_load_fpr32h (TCGv t, int reg)
{
    tcg_gen_ld_i32(t, current_fpu, 8 * reg + 4 * !FP_ENDIAN_IDX);
}
627

T
ths 已提交
628 629 630 631
static inline void gen_store_fpr32h (TCGv t, int reg)
{
    tcg_gen_st_i32(t, current_fpu, 8 * reg + 4 * !FP_ENDIAN_IDX);
}
632

633
#define FOP_CONDS(type, fmt)                                            \
634
static GenOpFunc1 * gen_op_cmp ## type ## _ ## fmt ## _table[16] = {    \
635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650
    gen_op_cmp ## type ## _ ## fmt ## _f,                               \
    gen_op_cmp ## type ## _ ## fmt ## _un,                              \
    gen_op_cmp ## type ## _ ## fmt ## _eq,                              \
    gen_op_cmp ## type ## _ ## fmt ## _ueq,                             \
    gen_op_cmp ## type ## _ ## fmt ## _olt,                             \
    gen_op_cmp ## type ## _ ## fmt ## _ult,                             \
    gen_op_cmp ## type ## _ ## fmt ## _ole,                             \
    gen_op_cmp ## type ## _ ## fmt ## _ule,                             \
    gen_op_cmp ## type ## _ ## fmt ## _sf,                              \
    gen_op_cmp ## type ## _ ## fmt ## _ngle,                            \
    gen_op_cmp ## type ## _ ## fmt ## _seq,                             \
    gen_op_cmp ## type ## _ ## fmt ## _ngl,                             \
    gen_op_cmp ## type ## _ ## fmt ## _lt,                              \
    gen_op_cmp ## type ## _ ## fmt ## _nge,                             \
    gen_op_cmp ## type ## _ ## fmt ## _le,                              \
    gen_op_cmp ## type ## _ ## fmt ## _ngt,                             \
B
bellard 已提交
651
};                                                                      \
652
static always_inline void gen_cmp ## type ## _ ## fmt(int n, long cc)   \
B
bellard 已提交
653
{                                                                       \
654
    gen_op_cmp ## type ## _ ## fmt ## _table[n](cc);                    \
B
bellard 已提交
655 656
}

657 658 659 660 661 662
FOP_CONDS(, d)
FOP_CONDS(abs, d)
FOP_CONDS(, s)
FOP_CONDS(abs, s)
FOP_CONDS(, ps)
FOP_CONDS(abs, ps)
B
bellard 已提交
663

664 665 666 667 668 669 670 671
/* Tests */
#define OP_COND(name, cond)                                   \
void glue(gen_op_, name) (void)                               \
{                                                             \
    int l1 = gen_new_label();                                 \
    int l2 = gen_new_label();                                 \
                                                              \
    tcg_gen_brcond_tl(cond, cpu_T[0], cpu_T[1], l1);          \
672
    tcg_gen_movi_tl(cpu_T[0], 0);                             \
673 674
    tcg_gen_br(l2);                                           \
    gen_set_label(l1);                                        \
675
    tcg_gen_movi_tl(cpu_T[0], 1);                             \
676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691
    gen_set_label(l2);                                        \
}
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

#define OP_CONDI(name, cond)                                  \
void glue(gen_op_, name) (target_ulong val)                   \
{                                                             \
    int l1 = gen_new_label();                                 \
    int l2 = gen_new_label();                                 \
                                                              \
P
pbrook 已提交
692
    tcg_gen_brcondi_tl(cond, cpu_T[0], val, l1);              \
693
    tcg_gen_movi_tl(cpu_T[0], 0);                             \
694 695
    tcg_gen_br(l2);                                           \
    gen_set_label(l1);                                        \
696
    tcg_gen_movi_tl(cpu_T[0], 1);                             \
697 698 699 700 701 702 703 704 705 706 707 708
    gen_set_label(l2);                                        \
}
OP_CONDI(lti, TCG_COND_LT);
OP_CONDI(ltiu, TCG_COND_LTU);
#undef OP_CONDI

#define OP_CONDZ(name, cond)                                  \
void glue(gen_op_, name) (void)                               \
{                                                             \
    int l1 = gen_new_label();                                 \
    int l2 = gen_new_label();                                 \
                                                              \
P
pbrook 已提交
709
    tcg_gen_brcondi_tl(cond, cpu_T[0], 0, l1);                \
710
    tcg_gen_movi_tl(cpu_T[0], 0);                             \
711 712
    tcg_gen_br(l2);                                           \
    gen_set_label(l1);                                        \
713
    tcg_gen_movi_tl(cpu_T[0], 1);                             \
714 715 716 717 718 719 720 721
    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

722 723 724
static inline void gen_save_pc(target_ulong pc)
{
    TCGv r_tmp = tcg_temp_new(TCG_TYPE_TL);
725
    TCGv r_tc_off = tcg_temp_new(TCG_TYPE_I32);
726
    TCGv r_tc_off_ptr = tcg_temp_new(TCG_TYPE_PTR);
727 728 729 730 731
    TCGv r_ptr = tcg_temp_new(TCG_TYPE_PTR);

    tcg_gen_movi_tl(r_tmp, pc);
    tcg_gen_ld_i32(r_tc_off, cpu_env, offsetof(CPUState, current_tc));
    tcg_gen_muli_i32(r_tc_off, r_tc_off, sizeof(target_ulong));
732 733
    tcg_gen_ext_i32_ptr(r_tc_off_ptr, r_tc_off);
    tcg_gen_add_ptr(r_ptr, cpu_env, r_tc_off_ptr);
734
    tcg_gen_st_tl(r_tmp, r_ptr, offsetof(CPUState, PC));
735
    tcg_temp_free(r_tc_off);
T
ths 已提交
736
    tcg_temp_free(r_tc_off_ptr);
737 738
    tcg_temp_free(r_ptr);
    tcg_temp_free(r_tmp);
739
}
740

741 742 743
static inline void gen_breg_pc(void)
{
    TCGv r_tmp = tcg_temp_new(TCG_TYPE_TL);
744
    TCGv r_tc_off = tcg_temp_new(TCG_TYPE_I32);
745
    TCGv r_tc_off_ptr = tcg_temp_new(TCG_TYPE_PTR);
746 747 748 749 750
    TCGv r_ptr = tcg_temp_new(TCG_TYPE_PTR);

    tcg_gen_ld_tl(r_tmp, cpu_env, offsetof(CPUState, btarget));
    tcg_gen_ld_i32(r_tc_off, cpu_env, offsetof(CPUState, current_tc));
    tcg_gen_muli_i32(r_tc_off, r_tc_off, sizeof(target_ulong));
751 752
    tcg_gen_ext_i32_ptr(r_tc_off_ptr, r_tc_off);
    tcg_gen_add_ptr(r_ptr, cpu_env, r_tc_off_ptr);
753
    tcg_gen_st_tl(r_tmp, r_ptr, offsetof(CPUState, PC));
754
    tcg_temp_free(r_tc_off);
T
ths 已提交
755
    tcg_temp_free(r_tc_off_ptr);
756 757
    tcg_temp_free(r_ptr);
    tcg_temp_free(r_tmp);
758
}
B
bellard 已提交
759

760
static inline void gen_save_btarget(target_ulong btarget)
761
{
762 763 764 765
    TCGv r_tmp = tcg_temp_new(TCG_TYPE_TL);

    tcg_gen_movi_tl(r_tmp, btarget);
    tcg_gen_st_tl(r_tmp, cpu_env, offsetof(CPUState, btarget));
T
ths 已提交
766
    tcg_temp_free(r_tmp);
767 768
}

769
static always_inline void gen_save_breg_target(int reg)
770
{
771 772 773 774
    TCGv r_tmp = tcg_temp_new(TCG_TYPE_TL);

    gen_load_gpr(r_tmp, reg);
    tcg_gen_st_tl(r_tmp, cpu_env, offsetof(CPUState, btarget));
T
ths 已提交
775
    tcg_temp_free(r_tmp);
776 777
}

778
static always_inline void save_cpu_state (DisasContext *ctx, int do_save_pc)
B
bellard 已提交
779 780 781 782 783 784 785 786
{
#if defined MIPS_DEBUG_DISAS
    if (loglevel & CPU_LOG_TB_IN_ASM) {
            fprintf(logfile, "hflags %08x saved %08x\n",
                    ctx->hflags, ctx->saved_hflags);
    }
#endif
    if (do_save_pc && ctx->pc != ctx->saved_pc) {
787
        gen_save_pc(ctx->pc);
B
bellard 已提交
788 789 790 791 792
        ctx->saved_pc = ctx->pc;
    }
    if (ctx->hflags != ctx->saved_hflags) {
        gen_op_save_state(ctx->hflags);
        ctx->saved_hflags = ctx->hflags;
793 794 795 796 797 798
        switch (ctx->hflags & MIPS_HFLAG_BMASK) {
        case MIPS_HFLAG_BR:
            break;
        case MIPS_HFLAG_BC:
        case MIPS_HFLAG_BL:
        case MIPS_HFLAG_B:
799
            gen_save_btarget(ctx->btarget);
800
            break;
B
bellard 已提交
801 802 803 804
        }
    }
}

805
static always_inline void restore_cpu_state (CPUState *env, DisasContext *ctx)
806
{
807 808 809 810 811 812
    ctx->saved_hflags = ctx->hflags;
    switch (ctx->hflags & MIPS_HFLAG_BMASK) {
    case MIPS_HFLAG_BR:
        break;
    case MIPS_HFLAG_BC:
    case MIPS_HFLAG_BL:
813
    case MIPS_HFLAG_B:
814 815
        ctx->btarget = env->btarget;
        break;
816 817 818
    }
}

819
static always_inline void
820
generate_exception_err (DisasContext *ctx, int excp, int err)
821 822
{
    save_cpu_state(ctx, 1);
T
ths 已提交
823
    tcg_gen_helper_0_2ii(do_raise_exception_err, excp, err);
824
    tcg_gen_helper_0_0(do_interrupt_restart);
825 826 827 828
    tcg_gen_exit_tb(0);
}

static always_inline void
829
generate_exception (DisasContext *ctx, int excp)
830
{
B
bellard 已提交
831
    save_cpu_state(ctx, 1);
T
ths 已提交
832
    tcg_gen_helper_0_1i(do_raise_exception, excp);
833 834
    tcg_gen_helper_0_0(do_interrupt_restart);
    tcg_gen_exit_tb(0);
B
bellard 已提交
835 836
}

837 838
/* Addresses computation */
static inline void gen_op_addr_add (void)
B
bellard 已提交
839
{
840 841 842 843 844 845 846 847
    tcg_gen_add_tl(cpu_T[0], cpu_T[0], cpu_T[1]);

#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. */
    {
        int l1 = gen_new_label();
T
ths 已提交
848 849 850 851 852 853 854 855 856
        TCGv r_tmp = tcg_temp_local_new(TCG_TYPE_I32);

        tcg_gen_ld_i32(r_tmp, cpu_env, offsetof(CPUState, hflags));
        tcg_gen_andi_i32(r_tmp, r_tmp, MIPS_HFLAG_KSU);
        tcg_gen_brcondi_i32(TCG_COND_NE, r_tmp, MIPS_HFLAG_UM, l1);
        tcg_gen_ld_i32(r_tmp, cpu_env, offsetof(CPUState, CP0_Status));
        tcg_gen_andi_i32(r_tmp, r_tmp, (1 << CP0St_UX));
        tcg_gen_brcondi_i32(TCG_COND_NE, r_tmp, 0, l1);
        tcg_temp_free(r_tmp);
857 858 859 860
        tcg_gen_ext32s_i64(cpu_T[0], cpu_T[0]);
        gen_set_label(l1);
    }
#endif
B
bellard 已提交
861 862
}

863
static always_inline void check_cp0_enabled(DisasContext *ctx)
864
{
865
    if (unlikely(!(ctx->hflags & MIPS_HFLAG_CP0)))
866 867 868
        generate_exception_err(ctx, EXCP_CpU, 1);
}

869
static always_inline void check_cp1_enabled(DisasContext *ctx)
870
{
871
    if (unlikely(!(ctx->hflags & MIPS_HFLAG_FPU)))
872 873 874
        generate_exception_err(ctx, EXCP_CpU, 1);
}

875 876 877 878 879 880 881 882 883 884 885 886 887
/* Verify that the processor is running with COP1X instructions enabled.
   This is associated with the nabla symbol in the MIPS32 and MIPS64
   opcode tables.  */

static always_inline void check_cop1x(DisasContext *ctx)
{
    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.  */

888
static always_inline void check_cp1_64bitmode(DisasContext *ctx)
889
{
890
    if (unlikely(~ctx->hflags & (MIPS_HFLAG_F64 | MIPS_HFLAG_COP1X)))
891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906
        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);
 */
void check_cp1_registers(DisasContext *ctx, int regs)
{
907
    if (unlikely(!(ctx->hflags & MIPS_HFLAG_F64) && (regs & 1)))
908 909 910
        generate_exception(ctx, EXCP_RI);
}

911
/* This code generates a "reserved instruction" exception if the
912
   CPU does not support the instruction set corresponding to flags. */
913
static always_inline void check_insn(CPUState *env, DisasContext *ctx, int flags)
914
{
915
    if (unlikely(!(env->insn_flags & flags)))
916 917 918
        generate_exception(ctx, EXCP_RI);
}

919 920
/* This code generates a "reserved instruction" exception if 64-bit
   instructions are not enabled. */
921
static always_inline void check_mips_64(DisasContext *ctx)
922
{
923
    if (unlikely(!(ctx->hflags & MIPS_HFLAG_64)))
924 925 926
        generate_exception(ctx, EXCP_RI);
}

T
ths 已提交
927
/* load/store instructions. */
B
bellard 已提交
928 929 930 931 932 933 934 935 936
#if defined(CONFIG_USER_ONLY)
#define op_ldst(name)        gen_op_##name##_raw()
#define OP_LD_TABLE(width)
#define OP_ST_TABLE(width)
#else
#define op_ldst(name)        (*gen_op_##name[ctx->mem_idx])()
#define OP_LD_TABLE(width)                                                    \
static GenOpFunc *gen_op_l##width[] = {                                       \
    &gen_op_l##width##_kernel,                                                \
T
ths 已提交
937 938
    &gen_op_l##width##_super,                                                 \
    &gen_op_l##width##_user,                                                  \
B
bellard 已提交
939 940 941 942
}
#define OP_ST_TABLE(width)                                                    \
static GenOpFunc *gen_op_s##width[] = {                                       \
    &gen_op_s##width##_kernel,                                                \
T
ths 已提交
943 944
    &gen_op_s##width##_super,                                                 \
    &gen_op_s##width##_user,                                                  \
B
bellard 已提交
945 946 947
}
#endif

948
#if defined(TARGET_MIPS64)
B
bellard 已提交
949 950 951 952 953 954 955 956 957
OP_LD_TABLE(dl);
OP_LD_TABLE(dr);
OP_ST_TABLE(dl);
OP_ST_TABLE(dr);
#endif
OP_LD_TABLE(wl);
OP_LD_TABLE(wr);
OP_ST_TABLE(wl);
OP_ST_TABLE(wr);
958 959
OP_LD_TABLE(uxc1);
OP_ST_TABLE(uxc1);
B
bellard 已提交
960

961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005
#define OP_LD(insn,fname)                                        \
void inline op_ldst_##insn(DisasContext *ctx)                    \
{                                                                \
    tcg_gen_qemu_##fname(cpu_T[0], cpu_T[0], ctx->mem_idx);      \
}
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)                                        \
void inline op_ldst_##insn(DisasContext *ctx)                    \
{                                                                \
    tcg_gen_qemu_##fname(cpu_T[1], cpu_T[0], ctx->mem_idx);      \
}
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)                                        \
void inline op_ldst_##insn(DisasContext *ctx)                           \
{                                                                       \
    tcg_gen_mov_tl(cpu_T[1], cpu_T[0]);                                 \
    tcg_gen_qemu_##fname(cpu_T[0], cpu_T[0], ctx->mem_idx);             \
    tcg_gen_st_tl(cpu_T[1], cpu_env, offsetof(CPUState, CP0_LLAddr));   \
}
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)                                 \
void inline op_ldst_##insn(DisasContext *ctx)                           \
{                                                                       \
T
ths 已提交
1006
    TCGv r_tmp = tcg_temp_local_new(TCG_TYPE_TL);                       \
1007 1008 1009 1010 1011
    int l1 = gen_new_label();                                           \
    int l2 = gen_new_label();                                           \
    int l3 = gen_new_label();                                           \
                                                                        \
    tcg_gen_andi_tl(r_tmp, cpu_T[0], almask);                           \
P
pbrook 已提交
1012
    tcg_gen_brcondi_tl(TCG_COND_EQ, r_tmp, 0, l1);                      \
1013
    tcg_gen_st_tl(cpu_T[0], cpu_env, offsetof(CPUState, CP0_BadVAddr)); \
T
ths 已提交
1014
    generate_exception(ctx, EXCP_AdES);                                 \
1015 1016 1017
    gen_set_label(l1);                                                  \
    tcg_gen_ld_tl(r_tmp, cpu_env, offsetof(CPUState, CP0_LLAddr));      \
    tcg_gen_brcond_tl(TCG_COND_NE, cpu_T[0], r_tmp, l2);                \
T
ths 已提交
1018
    tcg_temp_free(r_tmp);                                               \
1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031
    tcg_gen_qemu_##fname(cpu_T[1], cpu_T[0], ctx->mem_idx);             \
    tcg_gen_movi_tl(cpu_T[0], 1);                                       \
    tcg_gen_br(l3);                                                     \
    gen_set_label(l2);                                                  \
    tcg_gen_movi_tl(cpu_T[0], 0);                                       \
    gen_set_label(l3);                                                  \
}
OP_ST_ATOMIC(sc,st32,0x3);
#if defined(TARGET_MIPS64)
OP_ST_ATOMIC(scd,st64,0x7);
#endif
#undef OP_ST_ATOMIC

B
bellard 已提交
1032
/* Load and store */
1033
static void gen_ldst (DisasContext *ctx, uint32_t opc, int rt,
B
bellard 已提交
1034 1035
                      int base, int16_t offset)
{
1036
    const char *opn = "ldst";
B
bellard 已提交
1037 1038

    if (base == 0) {
1039
        tcg_gen_movi_tl(cpu_T[0], offset);
B
bellard 已提交
1040
    } else if (offset == 0) {
1041
        gen_load_gpr(cpu_T[0], base);
B
bellard 已提交
1042
    } else {
1043 1044
        gen_load_gpr(cpu_T[0], base);
        tcg_gen_movi_tl(cpu_T[1], offset);
1045
        gen_op_addr_add();
B
bellard 已提交
1046 1047
    }
    /* Don't do NOP if destination is zero: we must perform the actual
1048
       memory access. */
B
bellard 已提交
1049
    switch (opc) {
1050
#if defined(TARGET_MIPS64)
1051
    case OPC_LWU:
1052
        op_ldst_lwu(ctx);
1053
        gen_store_gpr(cpu_T[0], rt);
1054 1055
        opn = "lwu";
        break;
B
bellard 已提交
1056
    case OPC_LD:
1057
        op_ldst_ld(ctx);
1058
        gen_store_gpr(cpu_T[0], rt);
B
bellard 已提交
1059 1060
        opn = "ld";
        break;
1061
    case OPC_LLD:
1062
        op_ldst_lld(ctx);
1063
        gen_store_gpr(cpu_T[0], rt);
1064 1065
        opn = "lld";
        break;
B
bellard 已提交
1066
    case OPC_SD:
1067
        gen_load_gpr(cpu_T[1], rt);
1068
        op_ldst_sd(ctx);
B
bellard 已提交
1069 1070
        opn = "sd";
        break;
1071
    case OPC_SCD:
T
ths 已提交
1072
        save_cpu_state(ctx, 1);
1073
        gen_load_gpr(cpu_T[1], rt);
1074
        op_ldst_scd(ctx);
1075
        gen_store_gpr(cpu_T[0], rt);
1076 1077
        opn = "scd";
        break;
B
bellard 已提交
1078
    case OPC_LDL:
1079
        gen_load_gpr(cpu_T[1], rt);
B
bellard 已提交
1080
        op_ldst(ldl);
1081
        gen_store_gpr(cpu_T[1], rt);
B
bellard 已提交
1082 1083 1084
        opn = "ldl";
        break;
    case OPC_SDL:
1085
        gen_load_gpr(cpu_T[1], rt);
B
bellard 已提交
1086 1087 1088 1089
        op_ldst(sdl);
        opn = "sdl";
        break;
    case OPC_LDR:
1090
        gen_load_gpr(cpu_T[1], rt);
B
bellard 已提交
1091
        op_ldst(ldr);
1092
        gen_store_gpr(cpu_T[1], rt);
B
bellard 已提交
1093 1094 1095
        opn = "ldr";
        break;
    case OPC_SDR:
1096
        gen_load_gpr(cpu_T[1], rt);
B
bellard 已提交
1097 1098 1099 1100 1101
        op_ldst(sdr);
        opn = "sdr";
        break;
#endif
    case OPC_LW:
1102
        op_ldst_lw(ctx);
1103
        gen_store_gpr(cpu_T[0], rt);
B
bellard 已提交
1104 1105 1106
        opn = "lw";
        break;
    case OPC_SW:
1107
        gen_load_gpr(cpu_T[1], rt);
1108
        op_ldst_sw(ctx);
B
bellard 已提交
1109 1110 1111
        opn = "sw";
        break;
    case OPC_LH:
1112
        op_ldst_lh(ctx);
1113
        gen_store_gpr(cpu_T[0], rt);
B
bellard 已提交
1114 1115 1116
        opn = "lh";
        break;
    case OPC_SH:
1117
        gen_load_gpr(cpu_T[1], rt);
1118
        op_ldst_sh(ctx);
B
bellard 已提交
1119 1120 1121
        opn = "sh";
        break;
    case OPC_LHU:
1122
        op_ldst_lhu(ctx);
1123
        gen_store_gpr(cpu_T[0], rt);
B
bellard 已提交
1124 1125 1126
        opn = "lhu";
        break;
    case OPC_LB:
1127
        op_ldst_lb(ctx);
1128
        gen_store_gpr(cpu_T[0], rt);
B
bellard 已提交
1129 1130 1131
        opn = "lb";
        break;
    case OPC_SB:
1132
        gen_load_gpr(cpu_T[1], rt);
1133
        op_ldst_sb(ctx);
B
bellard 已提交
1134 1135 1136
        opn = "sb";
        break;
    case OPC_LBU:
1137
        op_ldst_lbu(ctx);
1138
        gen_store_gpr(cpu_T[0], rt);
B
bellard 已提交
1139 1140 1141
        opn = "lbu";
        break;
    case OPC_LWL:
1142
	gen_load_gpr(cpu_T[1], rt);
B
bellard 已提交
1143
        op_ldst(lwl);
1144
        gen_store_gpr(cpu_T[1], rt);
B
bellard 已提交
1145 1146 1147
        opn = "lwl";
        break;
    case OPC_SWL:
1148
        gen_load_gpr(cpu_T[1], rt);
B
bellard 已提交
1149 1150 1151 1152
        op_ldst(swl);
        opn = "swr";
        break;
    case OPC_LWR:
1153
	gen_load_gpr(cpu_T[1], rt);
B
bellard 已提交
1154
        op_ldst(lwr);
1155
        gen_store_gpr(cpu_T[1], rt);
B
bellard 已提交
1156 1157 1158
        opn = "lwr";
        break;
    case OPC_SWR:
1159
        gen_load_gpr(cpu_T[1], rt);
B
bellard 已提交
1160 1161 1162 1163
        op_ldst(swr);
        opn = "swr";
        break;
    case OPC_LL:
1164
        op_ldst_ll(ctx);
1165
        gen_store_gpr(cpu_T[0], rt);
B
bellard 已提交
1166 1167 1168
        opn = "ll";
        break;
    case OPC_SC:
T
ths 已提交
1169
        save_cpu_state(ctx, 1);
1170
        gen_load_gpr(cpu_T[1], rt);
1171
        op_ldst_sc(ctx);
1172
        gen_store_gpr(cpu_T[0], rt);
B
bellard 已提交
1173 1174 1175
        opn = "sc";
        break;
    default:
1176
        MIPS_INVAL(opn);
B
bellard 已提交
1177 1178 1179 1180 1181 1182
        generate_exception(ctx, EXCP_RI);
        return;
    }
    MIPS_DEBUG("%s %s, %d(%s)", opn, regnames[rt], offset, regnames[base]);
}

B
bellard 已提交
1183
/* Load and store */
1184
static void gen_flt_ldst (DisasContext *ctx, uint32_t opc, int ft,
B
bellard 已提交
1185 1186
                      int base, int16_t offset)
{
1187
    const char *opn = "flt_ldst";
B
bellard 已提交
1188 1189

    if (base == 0) {
1190
        tcg_gen_movi_tl(cpu_T[0], offset);
B
bellard 已提交
1191
    } else if (offset == 0) {
1192
        gen_load_gpr(cpu_T[0], base);
B
bellard 已提交
1193
    } else {
1194 1195
        gen_load_gpr(cpu_T[0], base);
        tcg_gen_movi_tl(cpu_T[1], offset);
1196
        gen_op_addr_add();
B
bellard 已提交
1197 1198
    }
    /* Don't do NOP if destination is zero: we must perform the actual
1199
       memory access. */
B
bellard 已提交
1200 1201
    switch (opc) {
    case OPC_LWC1:
T
ths 已提交
1202 1203
        tcg_gen_qemu_ld32s(fpu32_T[0], cpu_T[0], ctx->mem_idx);
        gen_store_fpr32(fpu32_T[0], ft);
B
bellard 已提交
1204 1205 1206
        opn = "lwc1";
        break;
    case OPC_SWC1:
T
ths 已提交
1207 1208
        gen_load_fpr32(fpu32_T[0], ft);
        tcg_gen_qemu_st32(fpu32_T[0], cpu_T[0], ctx->mem_idx);
B
bellard 已提交
1209 1210 1211
        opn = "swc1";
        break;
    case OPC_LDC1:
T
ths 已提交
1212 1213
        tcg_gen_qemu_ld64(fpu64_T[0], cpu_T[0], ctx->mem_idx);
        gen_store_fpr64(ctx, fpu64_T[0], ft);
B
bellard 已提交
1214 1215 1216
        opn = "ldc1";
        break;
    case OPC_SDC1:
T
ths 已提交
1217 1218
        gen_load_fpr64(ctx, fpu64_T[0], ft);
        tcg_gen_qemu_st64(fpu64_T[0], cpu_T[0], ctx->mem_idx);
B
bellard 已提交
1219 1220 1221
        opn = "sdc1";
        break;
    default:
1222
        MIPS_INVAL(opn);
1223
        generate_exception(ctx, EXCP_RI);
B
bellard 已提交
1224 1225 1226 1227 1228
        return;
    }
    MIPS_DEBUG("%s %s, %d(%s)", opn, fregnames[ft], offset, regnames[base]);
}

B
bellard 已提交
1229
/* Arithmetic with immediate operand */
1230 1231
static void gen_arith_imm (CPUState *env, DisasContext *ctx, uint32_t opc,
                           int rt, int rs, int16_t imm)
B
bellard 已提交
1232
{
1233
    target_ulong uimm;
1234
    const char *opn = "imm arith";
B
bellard 已提交
1235

1236
    if (rt == 0 && opc != OPC_ADDI && opc != OPC_DADDI) {
1237 1238
        /* If no destination, treat it as a NOP.
           For addi, we must generate the overflow exception when needed. */
B
bellard 已提交
1239 1240 1241
        MIPS_DEBUG("NOP");
        return;
    }
1242 1243 1244 1245
    uimm = (uint16_t)imm;
    switch (opc) {
    case OPC_ADDI:
    case OPC_ADDIU:
1246
#if defined(TARGET_MIPS64)
1247 1248 1249 1250 1251
    case OPC_DADDI:
    case OPC_DADDIU:
#endif
    case OPC_SLTI:
    case OPC_SLTIU:
1252
        uimm = (target_long)imm; /* Sign extend to 32/64 bits */
1253
        tcg_gen_movi_tl(cpu_T[1], uimm);
1254 1255 1256 1257
        /* Fall through. */
    case OPC_ANDI:
    case OPC_ORI:
    case OPC_XORI:
1258
        gen_load_gpr(cpu_T[0], rs);
1259 1260
        break;
    case OPC_LUI:
1261
        tcg_gen_movi_tl(cpu_T[0], imm << 16);
1262 1263 1264 1265
        break;
    case OPC_SLL:
    case OPC_SRA:
    case OPC_SRL:
1266
#if defined(TARGET_MIPS64)
1267 1268 1269 1270 1271 1272 1273 1274
    case OPC_DSLL:
    case OPC_DSRA:
    case OPC_DSRL:
    case OPC_DSLL32:
    case OPC_DSRA32:
    case OPC_DSRL32:
#endif
        uimm &= 0x1f;
1275
        gen_load_gpr(cpu_T[0], rs);
1276
        break;
B
bellard 已提交
1277 1278 1279
    }
    switch (opc) {
    case OPC_ADDI:
1280
        {
T
ths 已提交
1281
            TCGv r_tmp1 = tcg_temp_local_new(TCG_TYPE_TL);
1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292
            TCGv r_tmp2 = tcg_temp_new(TCG_TYPE_TL);
            int l1 = gen_new_label();

            save_cpu_state(ctx, 1);
            tcg_gen_ext32s_tl(r_tmp1, cpu_T[0]);
            tcg_gen_addi_tl(cpu_T[0], r_tmp1, uimm);

            tcg_gen_xori_tl(r_tmp1, r_tmp1, uimm);
            tcg_gen_xori_tl(r_tmp1, r_tmp1, -1);
            tcg_gen_xori_tl(r_tmp2, cpu_T[0], uimm);
            tcg_gen_and_tl(r_tmp1, r_tmp1, r_tmp2);
T
ths 已提交
1293
            tcg_temp_free(r_tmp2);
1294
            tcg_gen_shri_tl(r_tmp1, r_tmp1, 31);
P
pbrook 已提交
1295
            tcg_gen_brcondi_tl(TCG_COND_EQ, r_tmp1, 0, l1);
T
ths 已提交
1296
            tcg_temp_free(r_tmp1);
1297 1298 1299 1300 1301 1302
            /* operands of same sign, result different sign */
            generate_exception(ctx, EXCP_OVERFLOW);
            gen_set_label(l1);

            tcg_gen_ext32s_tl(cpu_T[0], cpu_T[0]);
        }
B
bellard 已提交
1303 1304 1305
        opn = "addi";
        break;
    case OPC_ADDIU:
1306 1307 1308
        tcg_gen_ext32s_tl(cpu_T[0], cpu_T[0]);
        tcg_gen_addi_tl(cpu_T[0], cpu_T[0], uimm);
        tcg_gen_ext32s_tl(cpu_T[0], cpu_T[0]);
B
bellard 已提交
1309 1310
        opn = "addiu";
        break;
1311
#if defined(TARGET_MIPS64)
1312
    case OPC_DADDI:
1313
        {
T
ths 已提交
1314
            TCGv r_tmp1 = tcg_temp_local_new(TCG_TYPE_TL);
1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325
            TCGv r_tmp2 = tcg_temp_new(TCG_TYPE_TL);
            int l1 = gen_new_label();

            save_cpu_state(ctx, 1);
            tcg_gen_mov_tl(r_tmp1, cpu_T[0]);
            tcg_gen_addi_tl(cpu_T[0], cpu_T[0], uimm);

            tcg_gen_xori_tl(r_tmp1, r_tmp1, uimm);
            tcg_gen_xori_tl(r_tmp1, r_tmp1, -1);
            tcg_gen_xori_tl(r_tmp2, cpu_T[0], uimm);
            tcg_gen_and_tl(r_tmp1, r_tmp1, r_tmp2);
T
ths 已提交
1326
            tcg_temp_free(r_tmp2);
1327
            tcg_gen_shri_tl(r_tmp1, r_tmp1, 63);
P
pbrook 已提交
1328
            tcg_gen_brcondi_tl(TCG_COND_EQ, r_tmp1, 0, l1);
T
ths 已提交
1329
            tcg_temp_free(r_tmp1);
1330 1331 1332 1333
            /* operands of same sign, result different sign */
            generate_exception(ctx, EXCP_OVERFLOW);
            gen_set_label(l1);
        }
1334 1335 1336
        opn = "daddi";
        break;
    case OPC_DADDIU:
1337
        tcg_gen_addi_tl(cpu_T[0], cpu_T[0], uimm);
1338 1339 1340
        opn = "daddiu";
        break;
#endif
B
bellard 已提交
1341
    case OPC_SLTI:
1342
        gen_op_lti(uimm);
B
bellard 已提交
1343 1344 1345
        opn = "slti";
        break;
    case OPC_SLTIU:
1346
        gen_op_ltiu(uimm);
B
bellard 已提交
1347 1348 1349
        opn = "sltiu";
        break;
    case OPC_ANDI:
1350
        tcg_gen_andi_tl(cpu_T[0], cpu_T[0], uimm);
B
bellard 已提交
1351 1352 1353
        opn = "andi";
        break;
    case OPC_ORI:
1354
        tcg_gen_ori_tl(cpu_T[0], cpu_T[0], uimm);
B
bellard 已提交
1355 1356 1357
        opn = "ori";
        break;
    case OPC_XORI:
1358
        tcg_gen_xori_tl(cpu_T[0], cpu_T[0], uimm);
B
bellard 已提交
1359 1360 1361 1362 1363 1364
        opn = "xori";
        break;
    case OPC_LUI:
        opn = "lui";
        break;
    case OPC_SLL:
1365 1366 1367
        tcg_gen_ext32u_tl(cpu_T[0], cpu_T[0]);
        tcg_gen_shli_tl(cpu_T[0], cpu_T[0], uimm);
        tcg_gen_ext32s_tl(cpu_T[0], cpu_T[0]);
B
bellard 已提交
1368 1369 1370
        opn = "sll";
        break;
    case OPC_SRA:
1371 1372 1373
        tcg_gen_ext32s_tl(cpu_T[0], cpu_T[0]);
        tcg_gen_sari_tl(cpu_T[0], cpu_T[0], uimm);
        tcg_gen_ext32s_tl(cpu_T[0], cpu_T[0]);
B
bellard 已提交
1374 1375 1376
        opn = "sra";
        break;
    case OPC_SRL:
1377 1378
        switch ((ctx->opcode >> 21) & 0x1f) {
        case 0:
1379 1380 1381
            tcg_gen_ext32u_tl(cpu_T[0], cpu_T[0]);
            tcg_gen_shri_tl(cpu_T[0], cpu_T[0], uimm);
            tcg_gen_ext32s_tl(cpu_T[0], cpu_T[0]);
1382
            opn = "srl";
1383 1384
            break;
        case 1:
1385 1386
            /* rotr is decoded as srl on non-R2 CPUs */
            if (env->insn_flags & ISA_MIPS32R2) {
1387
                if (uimm != 0) {
1388 1389
                    TCGv r_tmp1 = tcg_temp_new(TCG_TYPE_I32);
                    TCGv r_tmp2 = tcg_temp_new(TCG_TYPE_I32);
1390 1391 1392 1393 1394 1395 1396

                    tcg_gen_trunc_tl_i32(r_tmp1, cpu_T[0]);
                    tcg_gen_movi_i32(r_tmp2, 0x20);
                    tcg_gen_subi_i32(r_tmp2, r_tmp2, uimm);
                    tcg_gen_shl_i32(r_tmp2, r_tmp1, r_tmp2);
                    tcg_gen_shri_i32(r_tmp1, r_tmp1, uimm);
                    tcg_gen_or_i32(r_tmp1, r_tmp1, r_tmp2);
T
ths 已提交
1397
                    tcg_gen_ext_i32_tl(cpu_T[0], r_tmp1);
1398 1399
                    tcg_temp_free(r_tmp1);
                    tcg_temp_free(r_tmp2);
1400
                }
1401 1402
                opn = "rotr";
            } else {
1403 1404 1405
                tcg_gen_ext32u_tl(cpu_T[0], cpu_T[0]);
                tcg_gen_shri_tl(cpu_T[0], cpu_T[0], uimm);
                tcg_gen_ext32s_tl(cpu_T[0], cpu_T[0]);
1406 1407
                opn = "srl";
            }
1408 1409 1410 1411 1412 1413
            break;
        default:
            MIPS_INVAL("invalid srl flag");
            generate_exception(ctx, EXCP_RI);
            break;
        }
1414
        break;
1415
#if defined(TARGET_MIPS64)
1416
    case OPC_DSLL:
1417
        tcg_gen_shli_tl(cpu_T[0], cpu_T[0], uimm);
1418 1419 1420
        opn = "dsll";
        break;
    case OPC_DSRA:
1421
        tcg_gen_sari_tl(cpu_T[0], cpu_T[0], uimm);
1422 1423 1424
        opn = "dsra";
        break;
    case OPC_DSRL:
1425 1426
        switch ((ctx->opcode >> 21) & 0x1f) {
        case 0:
1427
            tcg_gen_shri_tl(cpu_T[0], cpu_T[0], uimm);
1428
            opn = "dsrl";
1429 1430
            break;
        case 1:
1431 1432
            /* drotr is decoded as dsrl on non-R2 CPUs */
            if (env->insn_flags & ISA_MIPS32R2) {
1433 1434 1435 1436 1437 1438 1439 1440
                if (uimm != 0) {
                    TCGv r_tmp1 = tcg_temp_new(TCG_TYPE_TL);

                    tcg_gen_movi_tl(r_tmp1, 0x40);
                    tcg_gen_subi_tl(r_tmp1, r_tmp1, uimm);
                    tcg_gen_shl_tl(r_tmp1, cpu_T[0], r_tmp1);
                    tcg_gen_shri_tl(cpu_T[0], cpu_T[0], uimm);
                    tcg_gen_or_tl(cpu_T[0], cpu_T[0], r_tmp1);
T
ths 已提交
1441
                    tcg_temp_free(r_tmp1);
1442
                }
1443 1444
                opn = "drotr";
            } else {
1445
                tcg_gen_shri_tl(cpu_T[0], cpu_T[0], uimm);
1446 1447
                opn = "dsrl";
            }
1448 1449 1450 1451 1452 1453
            break;
        default:
            MIPS_INVAL("invalid dsrl flag");
            generate_exception(ctx, EXCP_RI);
            break;
        }
1454 1455
        break;
    case OPC_DSLL32:
1456
        tcg_gen_shli_tl(cpu_T[0], cpu_T[0], uimm + 32);
1457 1458 1459
        opn = "dsll32";
        break;
    case OPC_DSRA32:
1460
        tcg_gen_sari_tl(cpu_T[0], cpu_T[0], uimm + 32);
1461 1462 1463
        opn = "dsra32";
        break;
    case OPC_DSRL32:
1464 1465
        switch ((ctx->opcode >> 21) & 0x1f) {
        case 0:
1466
            tcg_gen_shri_tl(cpu_T[0], cpu_T[0], uimm + 32);
1467
            opn = "dsrl32";
1468 1469
            break;
        case 1:
1470 1471
            /* drotr32 is decoded as dsrl32 on non-R2 CPUs */
            if (env->insn_flags & ISA_MIPS32R2) {
1472 1473 1474 1475 1476 1477 1478 1479 1480 1481
                TCGv r_tmp1 = tcg_temp_new(TCG_TYPE_TL);
                TCGv r_tmp2 = tcg_temp_new(TCG_TYPE_TL);

                tcg_gen_movi_tl(r_tmp1, 0x40);
                tcg_gen_movi_tl(r_tmp2, 32);
                tcg_gen_addi_tl(r_tmp2, r_tmp2, uimm);
                tcg_gen_sub_tl(r_tmp1, r_tmp1, r_tmp2);
                tcg_gen_shl_tl(r_tmp1, cpu_T[0], r_tmp1);
                tcg_gen_shr_tl(cpu_T[0], cpu_T[0], r_tmp2);
                tcg_gen_or_tl(cpu_T[0], cpu_T[0], r_tmp1);
T
ths 已提交
1482 1483
                tcg_temp_free(r_tmp1);
                tcg_temp_free(r_tmp2);
1484 1485
                opn = "drotr32";
            } else {
1486
                tcg_gen_shri_tl(cpu_T[0], cpu_T[0], uimm + 32);
1487 1488
                opn = "dsrl32";
            }
1489 1490 1491 1492 1493 1494
            break;
        default:
            MIPS_INVAL("invalid dsrl32 flag");
            generate_exception(ctx, EXCP_RI);
            break;
        }
B
bellard 已提交
1495
        break;
1496
#endif
B
bellard 已提交
1497
    default:
1498
        MIPS_INVAL(opn);
B
bellard 已提交
1499 1500 1501
        generate_exception(ctx, EXCP_RI);
        return;
    }
1502
    gen_store_gpr(cpu_T[0], rt);
T
ths 已提交
1503
    MIPS_DEBUG("%s %s, %s, " TARGET_FMT_lx, opn, regnames[rt], regnames[rs], uimm);
B
bellard 已提交
1504 1505 1506
}

/* Arithmetic */
1507
static void gen_arith (CPUState *env, DisasContext *ctx, uint32_t opc,
B
bellard 已提交
1508 1509
                       int rd, int rs, int rt)
{
1510
    const char *opn = "arith";
B
bellard 已提交
1511

1512 1513
    if (rd == 0 && opc != OPC_ADD && opc != OPC_SUB
       && opc != OPC_DADD && opc != OPC_DSUB) {
1514 1515
        /* If no destination, treat it as a NOP.
           For add & sub, we must generate the overflow exception when needed. */
B
bellard 已提交
1516 1517 1518
        MIPS_DEBUG("NOP");
        return;
    }
1519
    gen_load_gpr(cpu_T[0], rs);
T
ths 已提交
1520 1521 1522
    /* Specialcase the conventional move operation. */
    if (rt == 0 && (opc == OPC_ADDU || opc == OPC_DADDU
                    || opc == OPC_SUBU || opc == OPC_DSUBU)) {
1523
        gen_store_gpr(cpu_T[0], rd);
T
ths 已提交
1524 1525
        return;
    }
1526
    gen_load_gpr(cpu_T[1], rt);
B
bellard 已提交
1527 1528
    switch (opc) {
    case OPC_ADD:
1529
        {
T
ths 已提交
1530
            TCGv r_tmp1 = tcg_temp_local_new(TCG_TYPE_TL);
1531 1532 1533 1534 1535 1536 1537 1538 1539 1540 1541 1542
            TCGv r_tmp2 = tcg_temp_new(TCG_TYPE_TL);
            int l1 = gen_new_label();

            save_cpu_state(ctx, 1);
            tcg_gen_ext32s_tl(r_tmp1, cpu_T[0]);
            tcg_gen_ext32s_tl(r_tmp2, cpu_T[1]);
            tcg_gen_add_tl(cpu_T[0], r_tmp1, r_tmp2);

            tcg_gen_xor_tl(r_tmp1, r_tmp1, cpu_T[1]);
            tcg_gen_xori_tl(r_tmp1, r_tmp1, -1);
            tcg_gen_xor_tl(r_tmp2, cpu_T[0], cpu_T[1]);
            tcg_gen_and_tl(r_tmp1, r_tmp1, r_tmp2);
T
ths 已提交
1543
            tcg_temp_free(r_tmp2);
1544
            tcg_gen_shri_tl(r_tmp1, r_tmp1, 31);
P
pbrook 已提交
1545
            tcg_gen_brcondi_tl(TCG_COND_EQ, r_tmp1, 0, l1);
T
ths 已提交
1546
            tcg_temp_free(r_tmp1);
1547 1548 1549 1550 1551 1552
            /* operands of same sign, result different sign */
            generate_exception(ctx, EXCP_OVERFLOW);
            gen_set_label(l1);

            tcg_gen_ext32s_tl(cpu_T[0], cpu_T[0]);
        }
B
bellard 已提交
1553 1554 1555
        opn = "add";
        break;
    case OPC_ADDU:
1556 1557 1558 1559
        tcg_gen_ext32s_tl(cpu_T[0], cpu_T[0]);
        tcg_gen_ext32s_tl(cpu_T[1], cpu_T[1]);
        tcg_gen_add_tl(cpu_T[0], cpu_T[0], cpu_T[1]);
        tcg_gen_ext32s_tl(cpu_T[0], cpu_T[0]);
B
bellard 已提交
1560 1561 1562
        opn = "addu";
        break;
    case OPC_SUB:
1563
        {
T
ths 已提交
1564
            TCGv r_tmp1 = tcg_temp_local_new(TCG_TYPE_TL);
1565 1566 1567 1568 1569 1570 1571 1572 1573 1574 1575
            TCGv r_tmp2 = tcg_temp_new(TCG_TYPE_TL);
            int l1 = gen_new_label();

            save_cpu_state(ctx, 1);
            tcg_gen_ext32s_tl(r_tmp1, cpu_T[0]);
            tcg_gen_ext32s_tl(r_tmp2, cpu_T[1]);
            tcg_gen_sub_tl(cpu_T[0], r_tmp1, r_tmp2);

            tcg_gen_xor_tl(r_tmp2, r_tmp1, cpu_T[1]);
            tcg_gen_xor_tl(r_tmp1, r_tmp1, cpu_T[0]);
            tcg_gen_and_tl(r_tmp1, r_tmp1, r_tmp2);
T
ths 已提交
1576
            tcg_temp_free(r_tmp2);
1577
            tcg_gen_shri_tl(r_tmp1, r_tmp1, 31);
P
pbrook 已提交
1578
            tcg_gen_brcondi_tl(TCG_COND_EQ, r_tmp1, 0, l1);
T
ths 已提交
1579
            tcg_temp_free(r_tmp1);
1580 1581 1582 1583 1584 1585
            /* operands of different sign, first operand and result different sign */
            generate_exception(ctx, EXCP_OVERFLOW);
            gen_set_label(l1);

            tcg_gen_ext32s_tl(cpu_T[0], cpu_T[0]);
        }
B
bellard 已提交
1586 1587 1588
        opn = "sub";
        break;
    case OPC_SUBU:
1589 1590 1591 1592
        tcg_gen_ext32s_tl(cpu_T[0], cpu_T[0]);
        tcg_gen_ext32s_tl(cpu_T[1], cpu_T[1]);
        tcg_gen_sub_tl(cpu_T[0], cpu_T[0], cpu_T[1]);
        tcg_gen_ext32s_tl(cpu_T[0], cpu_T[0]);
B
bellard 已提交
1593 1594
        opn = "subu";
        break;
1595
#if defined(TARGET_MIPS64)
1596
    case OPC_DADD:
1597
        {
T
ths 已提交
1598
            TCGv r_tmp1 = tcg_temp_local_new(TCG_TYPE_TL);
1599 1600 1601 1602 1603 1604 1605 1606 1607 1608 1609
            TCGv r_tmp2 = tcg_temp_new(TCG_TYPE_TL);
            int l1 = gen_new_label();

            save_cpu_state(ctx, 1);
            tcg_gen_mov_tl(r_tmp1, cpu_T[0]);
            tcg_gen_add_tl(cpu_T[0], cpu_T[0], cpu_T[1]);

            tcg_gen_xor_tl(r_tmp1, r_tmp1, cpu_T[1]);
            tcg_gen_xori_tl(r_tmp1, r_tmp1, -1);
            tcg_gen_xor_tl(r_tmp2, cpu_T[0], cpu_T[1]);
            tcg_gen_and_tl(r_tmp1, r_tmp1, r_tmp2);
T
ths 已提交
1610
            tcg_temp_free(r_tmp2);
1611
            tcg_gen_shri_tl(r_tmp1, r_tmp1, 63);
P
pbrook 已提交
1612
            tcg_gen_brcondi_tl(TCG_COND_EQ, r_tmp1, 0, l1);
T
ths 已提交
1613
            tcg_temp_free(r_tmp1);
1614 1615 1616 1617
            /* operands of same sign, result different sign */
            generate_exception(ctx, EXCP_OVERFLOW);
            gen_set_label(l1);
        }
1618 1619 1620
        opn = "dadd";
        break;
    case OPC_DADDU:
1621
        tcg_gen_add_tl(cpu_T[0], cpu_T[0], cpu_T[1]);
1622 1623 1624
        opn = "daddu";
        break;
    case OPC_DSUB:
1625
        {
T
ths 已提交
1626
            TCGv r_tmp1 = tcg_temp_local_new(TCG_TYPE_TL);
1627 1628 1629 1630 1631 1632 1633 1634 1635 1636
            TCGv r_tmp2 = tcg_temp_new(TCG_TYPE_TL);
            int l1 = gen_new_label();

            save_cpu_state(ctx, 1);
            tcg_gen_mov_tl(r_tmp1, cpu_T[0]);
            tcg_gen_sub_tl(cpu_T[0], cpu_T[0], cpu_T[1]);

            tcg_gen_xor_tl(r_tmp2, r_tmp1, cpu_T[1]);
            tcg_gen_xor_tl(r_tmp1, r_tmp1, cpu_T[0]);
            tcg_gen_and_tl(r_tmp1, r_tmp1, r_tmp2);
T
ths 已提交
1637
            tcg_temp_free(r_tmp2);
1638
            tcg_gen_shri_tl(r_tmp1, r_tmp1, 63);
P
pbrook 已提交
1639
            tcg_gen_brcondi_tl(TCG_COND_EQ, r_tmp1, 0, l1);
T
ths 已提交
1640
            tcg_temp_free(r_tmp1);
1641 1642 1643 1644
            /* operands of different sign, first operand and result different sign */
            generate_exception(ctx, EXCP_OVERFLOW);
            gen_set_label(l1);
        }
1645 1646 1647
        opn = "dsub";
        break;
    case OPC_DSUBU:
1648
        tcg_gen_sub_tl(cpu_T[0], cpu_T[0], cpu_T[1]);
1649 1650 1651
        opn = "dsubu";
        break;
#endif
B
bellard 已提交
1652 1653 1654 1655 1656 1657 1658 1659 1660
    case OPC_SLT:
        gen_op_lt();
        opn = "slt";
        break;
    case OPC_SLTU:
        gen_op_ltu();
        opn = "sltu";
        break;
    case OPC_AND:
1661
        tcg_gen_and_tl(cpu_T[0], cpu_T[0], cpu_T[1]);
B
bellard 已提交
1662 1663 1664
        opn = "and";
        break;
    case OPC_NOR:
1665 1666
        tcg_gen_or_tl(cpu_T[0], cpu_T[0], cpu_T[1]);
        tcg_gen_not_tl(cpu_T[0], cpu_T[0]);
B
bellard 已提交
1667 1668 1669
        opn = "nor";
        break;
    case OPC_OR:
1670
        tcg_gen_or_tl(cpu_T[0], cpu_T[0], cpu_T[1]);
B
bellard 已提交
1671 1672 1673
        opn = "or";
        break;
    case OPC_XOR:
1674
        tcg_gen_xor_tl(cpu_T[0], cpu_T[0], cpu_T[1]);
B
bellard 已提交
1675 1676 1677
        opn = "xor";
        break;
    case OPC_MUL:
1678 1679 1680 1681
        tcg_gen_ext32s_tl(cpu_T[0], cpu_T[0]);
        tcg_gen_ext32s_tl(cpu_T[1], cpu_T[1]);
        tcg_gen_mul_tl(cpu_T[0], cpu_T[0], cpu_T[1]);
        tcg_gen_ext32s_tl(cpu_T[0], cpu_T[0]);
B
bellard 已提交
1682 1683 1684
        opn = "mul";
        break;
    case OPC_MOVN:
T
ths 已提交
1685 1686 1687
        {
            int l1 = gen_new_label();

P
pbrook 已提交
1688
            tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_T[1], 0, l1);
1689
            gen_store_gpr(cpu_T[0], rd);
T
ths 已提交
1690 1691
            gen_set_label(l1);
        }
B
bellard 已提交
1692 1693 1694
        opn = "movn";
        goto print;
    case OPC_MOVZ:
T
ths 已提交
1695 1696 1697
        {
            int l1 = gen_new_label();

P
pbrook 已提交
1698
            tcg_gen_brcondi_tl(TCG_COND_NE, cpu_T[1], 0, l1);
1699
            gen_store_gpr(cpu_T[0], rd);
T
ths 已提交
1700 1701
            gen_set_label(l1);
        }
B
bellard 已提交
1702 1703 1704
        opn = "movz";
        goto print;
    case OPC_SLLV:
1705 1706 1707 1708 1709
        tcg_gen_ext32u_tl(cpu_T[0], cpu_T[0]);
        tcg_gen_ext32u_tl(cpu_T[1], cpu_T[1]);
        tcg_gen_andi_tl(cpu_T[0], cpu_T[0], 0x1f);
        tcg_gen_shl_tl(cpu_T[0], cpu_T[1], cpu_T[0]);
        tcg_gen_ext32s_tl(cpu_T[0], cpu_T[0]);
B
bellard 已提交
1710 1711 1712
        opn = "sllv";
        break;
    case OPC_SRAV:
1713 1714 1715 1716
        tcg_gen_ext32s_tl(cpu_T[1], cpu_T[1]);
        tcg_gen_andi_tl(cpu_T[0], cpu_T[0], 0x1f);
        tcg_gen_sar_tl(cpu_T[0], cpu_T[1], cpu_T[0]);
        tcg_gen_ext32s_tl(cpu_T[0], cpu_T[0]);
B
bellard 已提交
1717 1718 1719
        opn = "srav";
        break;
    case OPC_SRLV:
1720 1721
        switch ((ctx->opcode >> 6) & 0x1f) {
        case 0:
1722 1723 1724 1725
            tcg_gen_ext32u_tl(cpu_T[1], cpu_T[1]);
            tcg_gen_andi_tl(cpu_T[0], cpu_T[0], 0x1f);
            tcg_gen_shr_tl(cpu_T[0], cpu_T[1], cpu_T[0]);
            tcg_gen_ext32s_tl(cpu_T[0], cpu_T[0]);
1726
            opn = "srlv";
1727 1728
            break;
        case 1:
1729 1730
            /* rotrv is decoded as srlv on non-R2 CPUs */
            if (env->insn_flags & ISA_MIPS32R2) {
1731 1732 1733 1734
                int l1 = gen_new_label();
                int l2 = gen_new_label();

                tcg_gen_andi_tl(cpu_T[0], cpu_T[0], 0x1f);
P
pbrook 已提交
1735
                tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_T[0], 0, l1);
1736
                {
1737 1738 1739
                    TCGv r_tmp1 = tcg_temp_new(TCG_TYPE_I32);
                    TCGv r_tmp2 = tcg_temp_new(TCG_TYPE_I32);
                    TCGv r_tmp3 = tcg_temp_new(TCG_TYPE_I32);
1740 1741 1742 1743 1744 1745 1746 1747

                    tcg_gen_trunc_tl_i32(r_tmp1, cpu_T[0]);
                    tcg_gen_trunc_tl_i32(r_tmp2, cpu_T[1]);
                    tcg_gen_movi_i32(r_tmp3, 0x20);
                    tcg_gen_sub_i32(r_tmp3, r_tmp3, r_tmp1);
                    tcg_gen_shl_i32(r_tmp3, r_tmp2, r_tmp3);
                    tcg_gen_shr_i32(r_tmp1, r_tmp2, r_tmp1);
                    tcg_gen_or_i32(r_tmp1, r_tmp1, r_tmp3);
T
ths 已提交
1748
                    tcg_gen_ext_i32_tl(cpu_T[0], r_tmp1);
1749 1750 1751
                    tcg_temp_free(r_tmp1);
                    tcg_temp_free(r_tmp2);
                    tcg_temp_free(r_tmp3);
1752 1753 1754 1755 1756
                    tcg_gen_br(l2);
                }
                gen_set_label(l1);
                tcg_gen_mov_tl(cpu_T[0], cpu_T[1]);
                gen_set_label(l2);
1757 1758
                opn = "rotrv";
            } else {
1759 1760 1761 1762
                tcg_gen_ext32u_tl(cpu_T[1], cpu_T[1]);
                tcg_gen_andi_tl(cpu_T[0], cpu_T[0], 0x1f);
                tcg_gen_shr_tl(cpu_T[0], cpu_T[1], cpu_T[0]);
                tcg_gen_ext32s_tl(cpu_T[0], cpu_T[0]);
1763 1764
                opn = "srlv";
            }
1765 1766 1767 1768 1769 1770
            break;
        default:
            MIPS_INVAL("invalid srlv flag");
            generate_exception(ctx, EXCP_RI);
            break;
        }
1771
        break;
1772
#if defined(TARGET_MIPS64)
1773
    case OPC_DSLLV:
1774 1775
        tcg_gen_andi_tl(cpu_T[0], cpu_T[0], 0x3f);
        tcg_gen_shl_tl(cpu_T[0], cpu_T[1], cpu_T[0]);
1776 1777 1778
        opn = "dsllv";
        break;
    case OPC_DSRAV:
1779 1780
        tcg_gen_andi_tl(cpu_T[0], cpu_T[0], 0x3f);
        tcg_gen_sar_tl(cpu_T[0], cpu_T[1], cpu_T[0]);
1781 1782 1783
        opn = "dsrav";
        break;
    case OPC_DSRLV:
1784 1785
        switch ((ctx->opcode >> 6) & 0x1f) {
        case 0:
1786 1787
            tcg_gen_andi_tl(cpu_T[0], cpu_T[0], 0x3f);
            tcg_gen_shr_tl(cpu_T[0], cpu_T[1], cpu_T[0]);
1788
            opn = "dsrlv";
1789 1790
            break;
        case 1:
1791 1792
            /* drotrv is decoded as dsrlv on non-R2 CPUs */
            if (env->insn_flags & ISA_MIPS32R2) {
1793 1794 1795 1796
                int l1 = gen_new_label();
                int l2 = gen_new_label();

                tcg_gen_andi_tl(cpu_T[0], cpu_T[0], 0x3f);
P
pbrook 已提交
1797
                tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_T[0], 0, l1);
1798 1799 1800 1801 1802 1803 1804 1805
                {
                    TCGv r_tmp1 = tcg_temp_new(TCG_TYPE_TL);

                    tcg_gen_movi_tl(r_tmp1, 0x40);
                    tcg_gen_sub_tl(r_tmp1, r_tmp1, cpu_T[0]);
                    tcg_gen_shl_tl(r_tmp1, cpu_T[1], r_tmp1);
                    tcg_gen_shr_tl(cpu_T[0], cpu_T[1], cpu_T[0]);
                    tcg_gen_or_tl(cpu_T[0], cpu_T[0], r_tmp1);
T
ths 已提交
1806
                    tcg_temp_free(r_tmp1);
1807 1808 1809 1810 1811
                    tcg_gen_br(l2);
                }
                gen_set_label(l1);
                tcg_gen_mov_tl(cpu_T[0], cpu_T[1]);
                gen_set_label(l2);
1812 1813
                opn = "drotrv";
            } else {
1814 1815
                tcg_gen_andi_tl(cpu_T[0], cpu_T[0], 0x3f);
                tcg_gen_shr_tl(cpu_T[0], cpu_T[1], cpu_T[0]);
1816 1817
                opn = "dsrlv";
            }
1818 1819 1820 1821 1822 1823
            break;
        default:
            MIPS_INVAL("invalid dsrlv flag");
            generate_exception(ctx, EXCP_RI);
            break;
        }
B
bellard 已提交
1824
        break;
1825
#endif
B
bellard 已提交
1826
    default:
1827
        MIPS_INVAL(opn);
B
bellard 已提交
1828 1829 1830
        generate_exception(ctx, EXCP_RI);
        return;
    }
1831
    gen_store_gpr(cpu_T[0], rd);
B
bellard 已提交
1832 1833 1834 1835 1836
 print:
    MIPS_DEBUG("%s %s, %s, %s", opn, regnames[rd], regnames[rs], regnames[rt]);
}

/* Arithmetic on HI/LO registers */
1837
static void gen_HILO (DisasContext *ctx, uint32_t opc, int reg)
B
bellard 已提交
1838
{
1839
    const char *opn = "hilo";
B
bellard 已提交
1840 1841

    if (reg == 0 && (opc == OPC_MFHI || opc == OPC_MFLO)) {
1842
        /* Treat as NOP. */
B
bellard 已提交
1843 1844 1845 1846 1847
        MIPS_DEBUG("NOP");
        return;
    }
    switch (opc) {
    case OPC_MFHI:
1848
        gen_load_HI(cpu_T[0], 0);
1849
        gen_store_gpr(cpu_T[0], reg);
B
bellard 已提交
1850 1851 1852
        opn = "mfhi";
        break;
    case OPC_MFLO:
1853
        gen_load_LO(cpu_T[0], 0);
1854
        gen_store_gpr(cpu_T[0], reg);
B
bellard 已提交
1855 1856 1857
        opn = "mflo";
        break;
    case OPC_MTHI:
1858
        gen_load_gpr(cpu_T[0], reg);
1859
        gen_store_HI(cpu_T[0], 0);
B
bellard 已提交
1860 1861 1862
        opn = "mthi";
        break;
    case OPC_MTLO:
1863
        gen_load_gpr(cpu_T[0], reg);
1864
        gen_store_LO(cpu_T[0], 0);
B
bellard 已提交
1865 1866 1867
        opn = "mtlo";
        break;
    default:
1868
        MIPS_INVAL(opn);
B
bellard 已提交
1869 1870 1871 1872 1873 1874
        generate_exception(ctx, EXCP_RI);
        return;
    }
    MIPS_DEBUG("%s %s", opn, regnames[reg]);
}

1875
static void gen_muldiv (DisasContext *ctx, uint32_t opc,
B
bellard 已提交
1876 1877
                        int rs, int rt)
{
1878
    const char *opn = "mul/div";
B
bellard 已提交
1879

1880 1881
    gen_load_gpr(cpu_T[0], rs);
    gen_load_gpr(cpu_T[1], rt);
B
bellard 已提交
1882 1883
    switch (opc) {
    case OPC_DIV:
1884 1885 1886
        {
            int l1 = gen_new_label();

1887 1888
            tcg_gen_ext32s_tl(cpu_T[0], cpu_T[0]);
            tcg_gen_ext32s_tl(cpu_T[1], cpu_T[1]);
P
pbrook 已提交
1889
            tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_T[1], 0, l1);
1890
            {
1891 1892
                TCGv r_tmp1 = tcg_temp_new(TCG_TYPE_I64);
                TCGv r_tmp2 = tcg_temp_new(TCG_TYPE_I64);
T
ths 已提交
1893 1894 1895 1896 1897 1898 1899 1900
                TCGv r_tmp3 = tcg_temp_new(TCG_TYPE_I64);

                tcg_gen_ext_tl_i64(r_tmp1, cpu_T[0]);
                tcg_gen_ext_tl_i64(r_tmp2, cpu_T[1]);
                tcg_gen_div_i64(r_tmp3, r_tmp1, r_tmp2);
                tcg_gen_rem_i64(r_tmp2, r_tmp1, r_tmp2);
                tcg_gen_trunc_i64_tl(cpu_T[0], r_tmp3);
                tcg_gen_trunc_i64_tl(cpu_T[1], r_tmp2);
T
ths 已提交
1901 1902 1903
                tcg_temp_free(r_tmp1);
                tcg_temp_free(r_tmp2);
                tcg_temp_free(r_tmp3);
1904 1905
                tcg_gen_ext32s_tl(cpu_T[0], cpu_T[0]);
                tcg_gen_ext32s_tl(cpu_T[1], cpu_T[1]);
T
ths 已提交
1906 1907
                gen_store_LO(cpu_T[0], 0);
                gen_store_HI(cpu_T[1], 0);
1908 1909 1910
            }
            gen_set_label(l1);
        }
B
bellard 已提交
1911 1912 1913
        opn = "div";
        break;
    case OPC_DIVU:
1914 1915 1916
        {
            int l1 = gen_new_label();

1917
            tcg_gen_ext32s_tl(cpu_T[1], cpu_T[1]);
P
pbrook 已提交
1918
            tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_T[1], 0, l1);
1919
            {
1920 1921 1922
                TCGv r_tmp1 = tcg_temp_new(TCG_TYPE_I32);
                TCGv r_tmp2 = tcg_temp_new(TCG_TYPE_I32);
                TCGv r_tmp3 = tcg_temp_new(TCG_TYPE_I32);
1923

1924 1925
                tcg_gen_trunc_tl_i32(r_tmp1, cpu_T[0]);
                tcg_gen_trunc_tl_i32(r_tmp2, cpu_T[1]);
1926 1927
                tcg_gen_divu_i32(r_tmp3, r_tmp1, r_tmp2);
                tcg_gen_remu_i32(r_tmp1, r_tmp1, r_tmp2);
1928 1929
                tcg_gen_ext_i32_tl(cpu_T[0], r_tmp3);
                tcg_gen_ext_i32_tl(cpu_T[1], r_tmp1);
1930 1931 1932
                tcg_temp_free(r_tmp1);
                tcg_temp_free(r_tmp2);
                tcg_temp_free(r_tmp3);
1933 1934
                gen_store_LO(cpu_T[0], 0);
                gen_store_HI(cpu_T[1], 0);
1935 1936 1937
            }
            gen_set_label(l1);
        }
B
bellard 已提交
1938 1939 1940 1941 1942 1943 1944 1945 1946 1947
        opn = "divu";
        break;
    case OPC_MULT:
        gen_op_mult();
        opn = "mult";
        break;
    case OPC_MULTU:
        gen_op_multu();
        opn = "multu";
        break;
1948
#if defined(TARGET_MIPS64)
1949
    case OPC_DDIV:
1950 1951 1952
        {
            int l1 = gen_new_label();

P
pbrook 已提交
1953
            tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_T[1], 0, l1);
1954 1955 1956
            {
                int l2 = gen_new_label();

1957 1958
                tcg_gen_brcondi_tl(TCG_COND_NE, cpu_T[0], -1LL << 63, l2);
                tcg_gen_brcondi_tl(TCG_COND_NE, cpu_T[1], -1LL, l2);
1959 1960 1961 1962 1963 1964
                {
                    tcg_gen_movi_tl(cpu_T[1], 0);
                    gen_store_LO(cpu_T[0], 0);
                    gen_store_HI(cpu_T[1], 0);
                    tcg_gen_br(l1);
                }
1965
                gen_set_label(l2);
1966 1967 1968
                {
                    TCGv r_tmp1 = tcg_temp_new(TCG_TYPE_I64);
                    TCGv r_tmp2 = tcg_temp_new(TCG_TYPE_I64);
1969

1970 1971 1972 1973
                    tcg_gen_div_i64(r_tmp1, cpu_T[0], cpu_T[1]);
                    tcg_gen_rem_i64(r_tmp2, cpu_T[0], cpu_T[1]);
                    gen_store_LO(r_tmp1, 0);
                    gen_store_HI(r_tmp2, 0);
T
ths 已提交
1974 1975
                    tcg_temp_free(r_tmp1);
                    tcg_temp_free(r_tmp2);
1976
                }
1977 1978 1979
            }
            gen_set_label(l1);
        }
1980 1981 1982
        opn = "ddiv";
        break;
    case OPC_DDIVU:
1983 1984 1985
        {
            int l1 = gen_new_label();

P
pbrook 已提交
1986
            tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_T[1], 0, l1);
1987 1988 1989 1990 1991 1992
            {
                TCGv r_tmp1 = tcg_temp_new(TCG_TYPE_I64);
                TCGv r_tmp2 = tcg_temp_new(TCG_TYPE_I64);

                tcg_gen_divu_i64(r_tmp1, cpu_T[0], cpu_T[1]);
                tcg_gen_remu_i64(r_tmp2, cpu_T[0], cpu_T[1]);
T
ths 已提交
1993 1994
                tcg_temp_free(r_tmp1);
                tcg_temp_free(r_tmp2);
1995 1996
                gen_store_LO(r_tmp1, 0);
                gen_store_HI(r_tmp2, 0);
1997 1998 1999
            }
            gen_set_label(l1);
        }
2000 2001 2002 2003 2004 2005 2006 2007 2008 2009 2010
        opn = "ddivu";
        break;
    case OPC_DMULT:
        gen_op_dmult();
        opn = "dmult";
        break;
    case OPC_DMULTU:
        gen_op_dmultu();
        opn = "dmultu";
        break;
#endif
B
bellard 已提交
2011 2012 2013 2014 2015 2016 2017 2018 2019 2020 2021 2022 2023 2024 2025 2026 2027
    case OPC_MADD:
        gen_op_madd();
        opn = "madd";
        break;
    case OPC_MADDU:
        gen_op_maddu();
        opn = "maddu";
        break;
    case OPC_MSUB:
        gen_op_msub();
        opn = "msub";
        break;
    case OPC_MSUBU:
        gen_op_msubu();
        opn = "msubu";
        break;
    default:
2028
        MIPS_INVAL(opn);
B
bellard 已提交
2029 2030 2031 2032 2033 2034
        generate_exception(ctx, EXCP_RI);
        return;
    }
    MIPS_DEBUG("%s %s %s", opn, regnames[rs], regnames[rt]);
}

2035 2036 2037 2038 2039
static void gen_mul_vr54xx (DisasContext *ctx, uint32_t opc,
                            int rd, int rs, int rt)
{
    const char *opn = "mul vr54xx";

2040 2041
    gen_load_gpr(cpu_T[0], rs);
    gen_load_gpr(cpu_T[1], rt);
2042 2043 2044 2045 2046 2047 2048 2049 2050 2051 2052 2053 2054 2055 2056 2057 2058 2059 2060 2061 2062 2063 2064 2065 2066 2067 2068 2069 2070 2071 2072 2073 2074 2075 2076 2077 2078 2079 2080 2081 2082 2083 2084 2085 2086 2087 2088 2089 2090 2091 2092 2093 2094 2095 2096 2097 2098 2099 2100 2101 2102 2103 2104

    switch (opc) {
    case OPC_VR54XX_MULS:
        gen_op_muls();
        opn = "muls";
	break;
    case OPC_VR54XX_MULSU:
        gen_op_mulsu();
        opn = "mulsu";
	break;
    case OPC_VR54XX_MACC:
        gen_op_macc();
        opn = "macc";
	break;
    case OPC_VR54XX_MACCU:
        gen_op_maccu();
        opn = "maccu";
	break;
    case OPC_VR54XX_MSAC:
        gen_op_msac();
        opn = "msac";
	break;
    case OPC_VR54XX_MSACU:
        gen_op_msacu();
        opn = "msacu";
	break;
    case OPC_VR54XX_MULHI:
        gen_op_mulhi();
        opn = "mulhi";
	break;
    case OPC_VR54XX_MULHIU:
        gen_op_mulhiu();
        opn = "mulhiu";
	break;
    case OPC_VR54XX_MULSHI:
        gen_op_mulshi();
        opn = "mulshi";
	break;
    case OPC_VR54XX_MULSHIU:
        gen_op_mulshiu();
        opn = "mulshiu";
	break;
    case OPC_VR54XX_MACCHI:
        gen_op_macchi();
        opn = "macchi";
	break;
    case OPC_VR54XX_MACCHIU:
        gen_op_macchiu();
        opn = "macchiu";
	break;
    case OPC_VR54XX_MSACHI:
        gen_op_msachi();
        opn = "msachi";
	break;
    case OPC_VR54XX_MSACHIU:
        gen_op_msachiu();
        opn = "msachiu";
	break;
    default:
        MIPS_INVAL("mul vr54xx");
        generate_exception(ctx, EXCP_RI);
        return;
    }
2105
    gen_store_gpr(cpu_T[0], rd);
2106 2107 2108
    MIPS_DEBUG("%s %s, %s, %s", opn, regnames[rd], regnames[rs], regnames[rt]);
}

2109
static void gen_cl (DisasContext *ctx, uint32_t opc,
B
bellard 已提交
2110 2111
                    int rd, int rs)
{
2112
    const char *opn = "CLx";
B
bellard 已提交
2113
    if (rd == 0) {
2114
        /* Treat as NOP. */
B
bellard 已提交
2115 2116 2117
        MIPS_DEBUG("NOP");
        return;
    }
2118
    gen_load_gpr(cpu_T[0], rs);
B
bellard 已提交
2119 2120
    switch (opc) {
    case OPC_CLO:
2121
        tcg_gen_helper_0_0(do_clo);
B
bellard 已提交
2122 2123 2124
        opn = "clo";
        break;
    case OPC_CLZ:
2125
        tcg_gen_helper_0_0(do_clz);
B
bellard 已提交
2126 2127
        opn = "clz";
        break;
2128
#if defined(TARGET_MIPS64)
2129
    case OPC_DCLO:
2130
        tcg_gen_helper_0_0(do_dclo);
2131 2132 2133
        opn = "dclo";
        break;
    case OPC_DCLZ:
2134
        tcg_gen_helper_0_0(do_dclz);
2135 2136 2137
        opn = "dclz";
        break;
#endif
B
bellard 已提交
2138
    default:
2139
        MIPS_INVAL(opn);
B
bellard 已提交
2140 2141 2142
        generate_exception(ctx, EXCP_RI);
        return;
    }
2143
    gen_store_gpr(cpu_T[0], rd);
B
bellard 已提交
2144 2145 2146 2147
    MIPS_DEBUG("%s %s, %s", opn, regnames[rd], regnames[rs]);
}

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

    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) {
2164 2165
            gen_load_gpr(cpu_T[0], rs);
            gen_load_gpr(cpu_T[1], rt);
B
bellard 已提交
2166 2167
            cond = 1;
        }
2168
        break;
B
bellard 已提交
2169 2170 2171 2172 2173 2174 2175 2176
    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) {
2177 2178
            gen_load_gpr(cpu_T[0], rs);
            tcg_gen_movi_tl(cpu_T[1], (int32_t)imm);
B
bellard 已提交
2179 2180 2181 2182 2183 2184 2185 2186 2187 2188 2189 2190 2191
            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 */
2192
            tcg_gen_movi_tl(cpu_T[0], 1);
B
bellard 已提交
2193 2194 2195 2196 2197 2198 2199
            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           */
2200
            /* Never trap: treat as NOP. */
B
bellard 已提交
2201 2202
            return;
        default:
2203
            MIPS_INVAL("trap");
B
bellard 已提交
2204 2205 2206 2207 2208 2209 2210 2211 2212 2213 2214 2215 2216 2217 2218 2219 2220 2221 2222 2223 2224 2225 2226 2227 2228 2229 2230 2231 2232 2233
            generate_exception(ctx, EXCP_RI);
            return;
        }
    } else {
        switch (opc) {
        case OPC_TEQ:
        case OPC_TEQI:
            gen_op_eq();
            break;
        case OPC_TGE:
        case OPC_TGEI:
            gen_op_ge();
            break;
        case OPC_TGEU:
        case OPC_TGEIU:
            gen_op_geu();
            break;
        case OPC_TLT:
        case OPC_TLTI:
            gen_op_lt();
            break;
        case OPC_TLTU:
        case OPC_TLTIU:
            gen_op_ltu();
            break;
        case OPC_TNE:
        case OPC_TNEI:
            gen_op_ne();
            break;
        default:
2234
            MIPS_INVAL("trap");
B
bellard 已提交
2235 2236 2237 2238 2239 2240 2241 2242 2243
            generate_exception(ctx, EXCP_RI);
            return;
        }
    }
    save_cpu_state(ctx, 1);
    gen_op_trap();
    ctx->bstate = BS_STOP;
}

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

B
bellard 已提交
2258
/* Branches (before delay slot) */
2259
static void gen_compute_branch (DisasContext *ctx, uint32_t opc,
B
bellard 已提交
2260 2261
                                int rs, int rt, int32_t offset)
{
2262 2263 2264 2265 2266
    target_ulong btarget = -1;
    int blink = 0;
    int bcond = 0;

    if (ctx->hflags & MIPS_HFLAG_BMASK) {
2267
#ifdef MIPS_DEBUG_DISAS
2268 2269
        if (loglevel & CPU_LOG_TB_IN_ASM) {
            fprintf(logfile,
2270
                    "Branch in delay slot at PC 0x" TARGET_FMT_lx "\n",
2271
                    ctx->pc);
2272
	}
2273
#endif
2274 2275 2276
        generate_exception(ctx, EXCP_RI);
        return;
    }
B
bellard 已提交
2277 2278 2279 2280 2281 2282 2283 2284 2285

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

B
bellard 已提交
2490 2491
    ctx->btarget = btarget;
    if (blink > 0) {
2492 2493
        tcg_gen_movi_tl(cpu_T[0], ctx->pc + 8);
        gen_store_gpr(cpu_T[0], blink);
B
bellard 已提交
2494 2495 2496
    }
}

2497 2498 2499 2500
/* special3 bitfield operations */
static void gen_bitops (DisasContext *ctx, uint32_t opc, int rt,
                       int rs, int lsb, int msb)
{
2501
    gen_load_gpr(cpu_T[1], rs);
2502 2503 2504 2505 2506 2507
    switch (opc) {
    case OPC_EXT:
        if (lsb + msb > 31)
            goto fail;
        gen_op_ext(lsb, msb + 1);
        break;
T
ths 已提交
2508
#if defined(TARGET_MIPS64)
2509 2510 2511
    case OPC_DEXTM:
        if (lsb + msb > 63)
            goto fail;
T
ths 已提交
2512
        gen_op_dext(lsb, msb + 1 + 32);
2513 2514 2515 2516
        break;
    case OPC_DEXTU:
        if (lsb + msb > 63)
            goto fail;
T
ths 已提交
2517
        gen_op_dext(lsb + 32, msb + 1);
2518 2519
        break;
    case OPC_DEXT:
T
ths 已提交
2520 2521 2522
        if (lsb + msb > 63)
            goto fail;
        gen_op_dext(lsb, msb + 1);
2523
        break;
T
ths 已提交
2524
#endif
2525 2526 2527
    case OPC_INS:
        if (lsb > msb)
            goto fail;
2528
        gen_load_gpr(cpu_T[0], rt);
2529 2530
        gen_op_ins(lsb, msb - lsb + 1);
        break;
T
ths 已提交
2531
#if defined(TARGET_MIPS64)
2532 2533 2534
    case OPC_DINSM:
        if (lsb > msb)
            goto fail;
2535
        gen_load_gpr(cpu_T[0], rt);
T
ths 已提交
2536
        gen_op_dins(lsb, msb - lsb + 1 + 32);
2537 2538 2539 2540
        break;
    case OPC_DINSU:
        if (lsb > msb)
            goto fail;
2541
        gen_load_gpr(cpu_T[0], rt);
T
ths 已提交
2542
        gen_op_dins(lsb + 32, msb - lsb + 1);
2543 2544 2545 2546
        break;
    case OPC_DINS:
        if (lsb > msb)
            goto fail;
2547
        gen_load_gpr(cpu_T[0], rt);
T
ths 已提交
2548
        gen_op_dins(lsb, msb - lsb + 1);
2549
        break;
T
ths 已提交
2550
#endif
2551 2552 2553 2554 2555 2556
    default:
fail:
        MIPS_INVAL("bitops");
        generate_exception(ctx, EXCP_RI);
        return;
    }
2557
    gen_store_gpr(cpu_T[0], rt);
2558 2559
}

B
bellard 已提交
2560
/* CP0 (MMU and control) */
2561
#ifndef CONFIG_USER_ONLY
T
ths 已提交
2562 2563 2564 2565 2566 2567 2568 2569 2570 2571 2572
static inline void gen_mfc0_load32 (TCGv t, target_ulong off)
{
    TCGv r_tmp = tcg_temp_new(TCG_TYPE_I32);

    tcg_gen_ld_i32(r_tmp, cpu_env, off);
    tcg_gen_ext_i32_tl(t, r_tmp);
    tcg_temp_free(r_tmp);
}

static inline void gen_mfc0_load64 (TCGv t, target_ulong off)
{
T
ths 已提交
2573 2574
    tcg_gen_ld_tl(t, cpu_env, off);
    tcg_gen_ext32s_tl(t, t);
T
ths 已提交
2575 2576
}

2577 2578 2579 2580 2581 2582 2583 2584 2585 2586 2587
static inline void gen_mtc0_store32 (TCGv t, target_ulong off)
{
    TCGv r_tmp = tcg_temp_new(TCG_TYPE_I32);

    tcg_gen_trunc_tl_i32(r_tmp, t);
    tcg_gen_st_i32(r_tmp, cpu_env, off);
    tcg_temp_free(r_tmp);
}

static inline void gen_mtc0_store64 (TCGv t, target_ulong off)
{
T
ths 已提交
2588 2589
    tcg_gen_ext32s_tl(t, t);
    tcg_gen_st_tl(t, cpu_env, off);
2590 2591
}

2592
static void gen_mfc0 (CPUState *env, DisasContext *ctx, int reg, int sel)
2593
{
2594
    const char *rn = "invalid";
2595

2596 2597 2598
    if (sel != 0)
        check_insn(env, ctx, ISA_MIPS32);

2599 2600
    switch (reg) {
    case 0:
2601 2602
        switch (sel) {
        case 0:
T
ths 已提交
2603
            gen_mfc0_load32(cpu_T[0], offsetof(CPUState, CP0_Index));
2604 2605 2606
            rn = "Index";
            break;
        case 1:
2607
            check_insn(env, ctx, ASE_MT);
2608
            tcg_gen_helper_0_0(do_mfc0_mvpcontrol);
2609
            rn = "MVPControl";
2610
            break;
2611
        case 2:
2612
            check_insn(env, ctx, ASE_MT);
2613
            tcg_gen_helper_0_0(do_mfc0_mvpconf0);
2614
            rn = "MVPConf0";
2615
            break;
2616
        case 3:
2617
            check_insn(env, ctx, ASE_MT);
2618
            tcg_gen_helper_0_0(do_mfc0_mvpconf1);
2619
            rn = "MVPConf1";
2620
            break;
2621 2622 2623
        default:
            goto die;
        }
2624 2625
        break;
    case 1:
2626 2627
        switch (sel) {
        case 0:
2628
            tcg_gen_helper_0_0(do_mfc0_random);
2629
            rn = "Random";
T
ths 已提交
2630
            break;
2631
        case 1:
2632
            check_insn(env, ctx, ASE_MT);
T
ths 已提交
2633
            gen_mfc0_load32(cpu_T[0], offsetof(CPUState, CP0_VPEControl));
2634
            rn = "VPEControl";
2635
            break;
2636
        case 2:
2637
            check_insn(env, ctx, ASE_MT);
T
ths 已提交
2638
            gen_mfc0_load32(cpu_T[0], offsetof(CPUState, CP0_VPEConf0));
2639
            rn = "VPEConf0";
2640
            break;
2641
        case 3:
2642
            check_insn(env, ctx, ASE_MT);
T
ths 已提交
2643
            gen_mfc0_load32(cpu_T[0], offsetof(CPUState, CP0_VPEConf1));
2644
            rn = "VPEConf1";
2645
            break;
2646
        case 4:
2647
            check_insn(env, ctx, ASE_MT);
T
ths 已提交
2648
            gen_mfc0_load64(cpu_T[0], offsetof(CPUState, CP0_YQMask));
2649
            rn = "YQMask";
2650
            break;
2651
        case 5:
2652
            check_insn(env, ctx, ASE_MT);
T
ths 已提交
2653
            gen_mfc0_load64(cpu_T[0], offsetof(CPUState, CP0_VPESchedule));
2654
            rn = "VPESchedule";
2655
            break;
2656
        case 6:
2657
            check_insn(env, ctx, ASE_MT);
T
ths 已提交
2658
            gen_mfc0_load64(cpu_T[0], offsetof(CPUState, CP0_VPEScheFBack));
2659
            rn = "VPEScheFBack";
2660
            break;
2661
        case 7:
2662
            check_insn(env, ctx, ASE_MT);
T
ths 已提交
2663
            gen_mfc0_load32(cpu_T[0], offsetof(CPUState, CP0_VPEOpt));
2664
            rn = "VPEOpt";
2665
            break;
2666 2667 2668
        default:
            goto die;
        }
2669 2670
        break;
    case 2:
2671 2672
        switch (sel) {
        case 0:
T
ths 已提交
2673 2674
            tcg_gen_ld_tl(cpu_T[0], cpu_env, offsetof(CPUState, CP0_EntryLo0));
            tcg_gen_ext32s_tl(cpu_T[0], cpu_T[0]);
T
ths 已提交
2675 2676
            rn = "EntryLo0";
            break;
2677
        case 1:
2678
            check_insn(env, ctx, ASE_MT);
2679
            tcg_gen_helper_0_0(do_mfc0_tcstatus);
T
ths 已提交
2680
            rn = "TCStatus";
2681
            break;
2682
        case 2:
2683
            check_insn(env, ctx, ASE_MT);
2684
            tcg_gen_helper_0_0(do_mfc0_tcbind);
T
ths 已提交
2685
            rn = "TCBind";
2686
            break;
2687
        case 3:
2688
            check_insn(env, ctx, ASE_MT);
2689
            tcg_gen_helper_0_0(do_mfc0_tcrestart);
T
ths 已提交
2690
            rn = "TCRestart";
2691
            break;
2692
        case 4:
2693
            check_insn(env, ctx, ASE_MT);
2694
            tcg_gen_helper_0_0(do_mfc0_tchalt);
T
ths 已提交
2695
            rn = "TCHalt";
2696
            break;
2697
        case 5:
2698
            check_insn(env, ctx, ASE_MT);
2699
            tcg_gen_helper_0_0(do_mfc0_tccontext);
T
ths 已提交
2700
            rn = "TCContext";
2701
            break;
2702
        case 6:
2703
            check_insn(env, ctx, ASE_MT);
2704
            tcg_gen_helper_0_0(do_mfc0_tcschedule);
T
ths 已提交
2705
            rn = "TCSchedule";
2706
            break;
2707
        case 7:
2708
            check_insn(env, ctx, ASE_MT);
2709
            tcg_gen_helper_0_0(do_mfc0_tcschefback);
T
ths 已提交
2710
            rn = "TCScheFBack";
2711
            break;
2712 2713 2714
        default:
            goto die;
        }
2715 2716
        break;
    case 3:
2717 2718
        switch (sel) {
        case 0:
T
ths 已提交
2719 2720
            tcg_gen_ld_tl(cpu_T[0], cpu_env, offsetof(CPUState, CP0_EntryLo1));
            tcg_gen_ext32s_tl(cpu_T[0], cpu_T[0]);
T
ths 已提交
2721 2722
            rn = "EntryLo1";
            break;
2723 2724
        default:
            goto die;
2725
        }
2726 2727
        break;
    case 4:
2728 2729
        switch (sel) {
        case 0:
T
ths 已提交
2730 2731
            tcg_gen_ld_tl(cpu_T[0], cpu_env, offsetof(CPUState, CP0_Context));
            tcg_gen_ext32s_tl(cpu_T[0], cpu_T[0]);
T
ths 已提交
2732 2733
            rn = "Context";
            break;
2734
        case 1:
2735
//            tcg_gen_helper_0_0(do_mfc0_contextconfig); /* SmartMIPS ASE */
T
ths 已提交
2736 2737
            rn = "ContextConfig";
//            break;
2738 2739
        default:
            goto die;
2740
        }
2741 2742
        break;
    case 5:
2743 2744
        switch (sel) {
        case 0:
T
ths 已提交
2745
            gen_mfc0_load32(cpu_T[0], offsetof(CPUState, CP0_PageMask));
T
ths 已提交
2746 2747
            rn = "PageMask";
            break;
2748
        case 1:
2749
            check_insn(env, ctx, ISA_MIPS32R2);
T
ths 已提交
2750
            gen_mfc0_load32(cpu_T[0], offsetof(CPUState, CP0_PageGrain));
T
ths 已提交
2751 2752
            rn = "PageGrain";
            break;
2753 2754
        default:
            goto die;
2755
        }
2756 2757
        break;
    case 6:
2758 2759
        switch (sel) {
        case 0:
T
ths 已提交
2760
            gen_mfc0_load32(cpu_T[0], offsetof(CPUState, CP0_Wired));
T
ths 已提交
2761 2762
            rn = "Wired";
            break;
2763
        case 1:
2764
            check_insn(env, ctx, ISA_MIPS32R2);
T
ths 已提交
2765
            gen_mfc0_load32(cpu_T[0], offsetof(CPUState, CP0_SRSConf0));
T
ths 已提交
2766
            rn = "SRSConf0";
2767
            break;
2768
        case 2:
2769
            check_insn(env, ctx, ISA_MIPS32R2);
T
ths 已提交
2770
            gen_mfc0_load32(cpu_T[0], offsetof(CPUState, CP0_SRSConf1));
T
ths 已提交
2771
            rn = "SRSConf1";
2772
            break;
2773
        case 3:
2774
            check_insn(env, ctx, ISA_MIPS32R2);
T
ths 已提交
2775
            gen_mfc0_load32(cpu_T[0], offsetof(CPUState, CP0_SRSConf2));
T
ths 已提交
2776
            rn = "SRSConf2";
2777
            break;
2778
        case 4:
2779
            check_insn(env, ctx, ISA_MIPS32R2);
T
ths 已提交
2780
            gen_mfc0_load32(cpu_T[0], offsetof(CPUState, CP0_SRSConf3));
T
ths 已提交
2781
            rn = "SRSConf3";
2782
            break;
2783
        case 5:
2784
            check_insn(env, ctx, ISA_MIPS32R2);
T
ths 已提交
2785
            gen_mfc0_load32(cpu_T[0], offsetof(CPUState, CP0_SRSConf4));
T
ths 已提交
2786
            rn = "SRSConf4";
2787
            break;
2788 2789
        default:
            goto die;
2790
        }
2791
        break;
2792
    case 7:
2793 2794
        switch (sel) {
        case 0:
2795
            check_insn(env, ctx, ISA_MIPS32R2);
T
ths 已提交
2796
            gen_mfc0_load32(cpu_T[0], offsetof(CPUState, CP0_HWREna));
T
ths 已提交
2797 2798
            rn = "HWREna";
            break;
2799 2800
        default:
            goto die;
2801
        }
2802
        break;
2803
    case 8:
2804 2805
        switch (sel) {
        case 0:
T
ths 已提交
2806 2807 2808
            tcg_gen_ld_tl(cpu_T[0], cpu_env, offsetof(CPUState, CP0_BadVAddr));
            tcg_gen_ext32s_tl(cpu_T[0], cpu_T[0]);
            rn = "BadVAddr";
T
ths 已提交
2809
            break;
2810 2811 2812
        default:
            goto die;
       }
2813 2814
        break;
    case 9:
2815 2816
        switch (sel) {
        case 0:
2817
            tcg_gen_helper_0_0(do_mfc0_count);
T
ths 已提交
2818 2819 2820
            rn = "Count";
            break;
        /* 6,7 are implementation dependent */
2821 2822
        default:
            goto die;
T
ths 已提交
2823
        }
2824 2825
        break;
    case 10:
2826 2827
        switch (sel) {
        case 0:
T
ths 已提交
2828 2829
            tcg_gen_ld_tl(cpu_T[0], cpu_env, offsetof(CPUState, CP0_EntryHi));
            tcg_gen_ext32s_tl(cpu_T[0], cpu_T[0]);
T
ths 已提交
2830 2831
            rn = "EntryHi";
            break;
2832 2833
        default:
            goto die;
2834
        }
2835 2836
        break;
    case 11:
2837 2838
        switch (sel) {
        case 0:
T
ths 已提交
2839
            gen_mfc0_load32(cpu_T[0], offsetof(CPUState, CP0_Compare));
T
ths 已提交
2840 2841 2842
            rn = "Compare";
            break;
        /* 6,7 are implementation dependent */
2843 2844
        default:
            goto die;
T
ths 已提交
2845
        }
2846 2847
        break;
    case 12:
2848 2849
        switch (sel) {
        case 0:
T
ths 已提交
2850
            gen_mfc0_load32(cpu_T[0], offsetof(CPUState, CP0_Status));
T
ths 已提交
2851 2852
            rn = "Status";
            break;
2853
        case 1:
2854
            check_insn(env, ctx, ISA_MIPS32R2);
T
ths 已提交
2855
            gen_mfc0_load32(cpu_T[0], offsetof(CPUState, CP0_IntCtl));
T
ths 已提交
2856 2857
            rn = "IntCtl";
            break;
2858
        case 2:
2859
            check_insn(env, ctx, ISA_MIPS32R2);
T
ths 已提交
2860
            gen_mfc0_load32(cpu_T[0], offsetof(CPUState, CP0_SRSCtl));
T
ths 已提交
2861 2862
            rn = "SRSCtl";
            break;
2863
        case 3:
2864
            check_insn(env, ctx, ISA_MIPS32R2);
T
ths 已提交
2865
            gen_mfc0_load32(cpu_T[0], offsetof(CPUState, CP0_SRSMap));
T
ths 已提交
2866
            rn = "SRSMap";
2867
            break;
2868 2869 2870
        default:
            goto die;
       }
2871 2872
        break;
    case 13:
2873 2874
        switch (sel) {
        case 0:
T
ths 已提交
2875
            gen_mfc0_load32(cpu_T[0], offsetof(CPUState, CP0_Cause));
T
ths 已提交
2876 2877
            rn = "Cause";
            break;
2878 2879 2880
        default:
            goto die;
       }
2881 2882
        break;
    case 14:
2883 2884
        switch (sel) {
        case 0:
T
ths 已提交
2885 2886
            tcg_gen_ld_tl(cpu_T[0], cpu_env, offsetof(CPUState, CP0_EPC));
            tcg_gen_ext32s_tl(cpu_T[0], cpu_T[0]);
T
ths 已提交
2887 2888
            rn = "EPC";
            break;
2889 2890
        default:
            goto die;
2891
        }
2892 2893
        break;
    case 15:
2894 2895
        switch (sel) {
        case 0:
T
ths 已提交
2896
            gen_mfc0_load32(cpu_T[0], offsetof(CPUState, CP0_PRid));
T
ths 已提交
2897 2898
            rn = "PRid";
            break;
2899
        case 1:
2900
            check_insn(env, ctx, ISA_MIPS32R2);
T
ths 已提交
2901
            gen_mfc0_load32(cpu_T[0], offsetof(CPUState, CP0_EBase));
T
ths 已提交
2902 2903
            rn = "EBase";
            break;
2904 2905 2906
        default:
            goto die;
       }
2907 2908 2909 2910
        break;
    case 16:
        switch (sel) {
        case 0:
T
ths 已提交
2911
            gen_mfc0_load32(cpu_T[0], offsetof(CPUState, CP0_Config0));
2912 2913 2914
            rn = "Config";
            break;
        case 1:
T
ths 已提交
2915
            gen_mfc0_load32(cpu_T[0], offsetof(CPUState, CP0_Config1));
2916 2917
            rn = "Config1";
            break;
2918
        case 2:
T
ths 已提交
2919
            gen_mfc0_load32(cpu_T[0], offsetof(CPUState, CP0_Config2));
2920 2921 2922
            rn = "Config2";
            break;
        case 3:
T
ths 已提交
2923
            gen_mfc0_load32(cpu_T[0], offsetof(CPUState, CP0_Config3));
2924 2925
            rn = "Config3";
            break;
2926 2927 2928
        /* 4,5 are reserved */
        /* 6,7 are implementation dependent */
        case 6:
T
ths 已提交
2929
            gen_mfc0_load32(cpu_T[0], offsetof(CPUState, CP0_Config6));
2930 2931 2932
            rn = "Config6";
            break;
        case 7:
T
ths 已提交
2933
            gen_mfc0_load32(cpu_T[0], offsetof(CPUState, CP0_Config7));
2934 2935
            rn = "Config7";
            break;
2936 2937 2938 2939 2940
        default:
            goto die;
        }
        break;
    case 17:
2941 2942
        switch (sel) {
        case 0:
2943
            tcg_gen_helper_0_0(do_mfc0_lladdr);
T
ths 已提交
2944 2945
            rn = "LLAddr";
            break;
2946 2947 2948
        default:
            goto die;
        }
2949 2950
        break;
    case 18:
2951
        switch (sel) {
2952
        case 0 ... 7:
2953
            tcg_gen_helper_0_1i(do_mfc0_watchlo, sel);
T
ths 已提交
2954 2955
            rn = "WatchLo";
            break;
2956 2957 2958
        default:
            goto die;
        }
2959 2960
        break;
    case 19:
2961
        switch (sel) {
2962
        case 0 ...7:
2963
            tcg_gen_helper_0_1i(do_mfc0_watchhi, sel);
T
ths 已提交
2964 2965
            rn = "WatchHi";
            break;
2966 2967 2968
        default:
            goto die;
        }
2969
        break;
2970
    case 20:
2971 2972
        switch (sel) {
        case 0:
2973
#if defined(TARGET_MIPS64)
2974
            check_insn(env, ctx, ISA_MIPS3);
T
ths 已提交
2975 2976
            tcg_gen_ld_tl(cpu_T[0], cpu_env, offsetof(CPUState, CP0_XContext));
            tcg_gen_ext32s_tl(cpu_T[0], cpu_T[0]);
T
ths 已提交
2977 2978
            rn = "XContext";
            break;
T
ths 已提交
2979
#endif
2980 2981 2982
        default:
            goto die;
        }
2983 2984
        break;
    case 21:
2985 2986 2987
       /* Officially reserved, but sel 0 is used for R1x000 framemask */
        switch (sel) {
        case 0:
T
ths 已提交
2988
            gen_mfc0_load32(cpu_T[0], offsetof(CPUState, CP0_Framemask));
T
ths 已提交
2989 2990
            rn = "Framemask";
            break;
2991 2992 2993
        default:
            goto die;
        }
2994 2995
        break;
    case 22:
T
ths 已提交
2996 2997 2998
        /* ignored */
        rn = "'Diagnostic"; /* implementation dependent */
        break;
2999
    case 23:
3000 3001
        switch (sel) {
        case 0:
3002
            tcg_gen_helper_0_0(do_mfc0_debug); /* EJTAG support */
T
ths 已提交
3003 3004
            rn = "Debug";
            break;
3005
        case 1:
3006
//            tcg_gen_helper_0_0(do_mfc0_tracecontrol); /* PDtrace support */
T
ths 已提交
3007 3008
            rn = "TraceControl";
//            break;
3009
        case 2:
3010
//            tcg_gen_helper_0_0(do_mfc0_tracecontrol2); /* PDtrace support */
T
ths 已提交
3011 3012
            rn = "TraceControl2";
//            break;
3013
        case 3:
3014
//            tcg_gen_helper_0_0(do_mfc0_usertracedata); /* PDtrace support */
T
ths 已提交
3015 3016
            rn = "UserTraceData";
//            break;
3017
        case 4:
3018
//            tcg_gen_helper_0_0(do_mfc0_debug); /* PDtrace support */
T
ths 已提交
3019 3020
            rn = "TraceBPC";
//            break;
3021 3022 3023
        default:
            goto die;
        }
3024 3025
        break;
    case 24:
3026 3027
        switch (sel) {
        case 0:
T
ths 已提交
3028 3029 3030
            /* EJTAG support */
            tcg_gen_ld_tl(cpu_T[0], cpu_env, offsetof(CPUState, CP0_DEPC));
            tcg_gen_ext32s_tl(cpu_T[0], cpu_T[0]);
T
ths 已提交
3031 3032
            rn = "DEPC";
            break;
3033 3034 3035
        default:
            goto die;
        }
3036
        break;
3037
    case 25:
3038 3039
        switch (sel) {
        case 0:
T
ths 已提交
3040
            gen_mfc0_load32(cpu_T[0], offsetof(CPUState, CP0_Performance0));
T
ths 已提交
3041
            rn = "Performance0";
3042 3043
            break;
        case 1:
3044
//            tcg_gen_helper_0_0(do_mfc0_performance1);
T
ths 已提交
3045 3046
            rn = "Performance1";
//            break;
3047
        case 2:
3048
//            tcg_gen_helper_0_0(do_mfc0_performance2);
T
ths 已提交
3049 3050
            rn = "Performance2";
//            break;
3051
        case 3:
3052
//            tcg_gen_helper_0_0(do_mfc0_performance3);
T
ths 已提交
3053 3054
            rn = "Performance3";
//            break;
3055
        case 4:
3056
//            tcg_gen_helper_0_0(do_mfc0_performance4);
T
ths 已提交
3057 3058
            rn = "Performance4";
//            break;
3059
        case 5:
3060
//            tcg_gen_helper_0_0(do_mfc0_performance5);
T
ths 已提交
3061 3062
            rn = "Performance5";
//            break;
3063
        case 6:
3064
//            tcg_gen_helper_0_0(do_mfc0_performance6);
T
ths 已提交
3065 3066
            rn = "Performance6";
//            break;
3067
        case 7:
3068
//            tcg_gen_helper_0_0(do_mfc0_performance7);
T
ths 已提交
3069 3070
            rn = "Performance7";
//            break;
3071 3072 3073
        default:
            goto die;
        }
3074 3075
        break;
    case 26:
3076 3077
       rn = "ECC";
       break;
3078
    case 27:
3079 3080 3081
        switch (sel) {
        /* ignored */
        case 0 ... 3:
T
ths 已提交
3082 3083
            rn = "CacheErr";
            break;
3084 3085 3086
        default:
            goto die;
        }
3087
        break;
3088 3089 3090
    case 28:
        switch (sel) {
        case 0:
3091 3092 3093
        case 2:
        case 4:
        case 6:
T
ths 已提交
3094
            gen_mfc0_load32(cpu_T[0], offsetof(CPUState, CP0_TagLo));
3095 3096 3097
            rn = "TagLo";
            break;
        case 1:
3098 3099 3100
        case 3:
        case 5:
        case 7:
T
ths 已提交
3101
            gen_mfc0_load32(cpu_T[0], offsetof(CPUState, CP0_DataLo));
3102 3103 3104 3105 3106 3107
            rn = "DataLo";
            break;
        default:
            goto die;
        }
        break;
3108
    case 29:
3109 3110 3111 3112 3113
        switch (sel) {
        case 0:
        case 2:
        case 4:
        case 6:
T
ths 已提交
3114
            gen_mfc0_load32(cpu_T[0], offsetof(CPUState, CP0_TagHi));
3115 3116 3117 3118 3119 3120
            rn = "TagHi";
            break;
        case 1:
        case 3:
        case 5:
        case 7:
T
ths 已提交
3121
            gen_mfc0_load32(cpu_T[0], offsetof(CPUState, CP0_DataHi));
3122 3123 3124 3125 3126
            rn = "DataHi";
            break;
        default:
            goto die;
        }
3127
        break;
3128
    case 30:
3129 3130
        switch (sel) {
        case 0:
T
ths 已提交
3131 3132
            tcg_gen_ld_tl(cpu_T[0], cpu_env, offsetof(CPUState, CP0_ErrorEPC));
            tcg_gen_ext32s_tl(cpu_T[0], cpu_T[0]);
T
ths 已提交
3133 3134
            rn = "ErrorEPC";
            break;
3135 3136 3137
        default:
            goto die;
        }
3138 3139
        break;
    case 31:
3140 3141
        switch (sel) {
        case 0:
T
ths 已提交
3142
            /* EJTAG support */
T
ths 已提交
3143
            gen_mfc0_load32(cpu_T[0], offsetof(CPUState, CP0_DESAVE));
T
ths 已提交
3144 3145
            rn = "DESAVE";
            break;
3146 3147 3148
        default:
            goto die;
        }
3149 3150 3151 3152 3153 3154
        break;
    default:
       goto die;
    }
#if defined MIPS_DEBUG_DISAS
    if (loglevel & CPU_LOG_TB_IN_ASM) {
3155 3156
        fprintf(logfile, "mfc0 %s (reg %d sel %d)\n",
                rn, reg, sel);
3157 3158 3159 3160 3161 3162 3163
    }
#endif
    return;

die:
#if defined MIPS_DEBUG_DISAS
    if (loglevel & CPU_LOG_TB_IN_ASM) {
3164 3165
        fprintf(logfile, "mfc0 %s (reg %d sel %d)\n",
                rn, reg, sel);
3166 3167 3168 3169 3170
    }
#endif
    generate_exception(ctx, EXCP_RI);
}

3171
static void gen_mtc0 (CPUState *env, DisasContext *ctx, int reg, int sel)
3172
{
3173 3174
    const char *rn = "invalid";

3175 3176 3177
    if (sel != 0)
        check_insn(env, ctx, ISA_MIPS32);

3178 3179
    switch (reg) {
    case 0:
3180 3181
        switch (sel) {
        case 0:
3182
            tcg_gen_helper_0_0(do_mtc0_index);
3183 3184 3185
            rn = "Index";
            break;
        case 1:
3186
            check_insn(env, ctx, ASE_MT);
3187
            tcg_gen_helper_0_0(do_mtc0_mvpcontrol);
3188
            rn = "MVPControl";
3189
            break;
3190
        case 2:
3191
            check_insn(env, ctx, ASE_MT);
3192
            /* ignored */
3193
            rn = "MVPConf0";
3194
            break;
3195
        case 3:
3196
            check_insn(env, ctx, ASE_MT);
3197
            /* ignored */
3198
            rn = "MVPConf1";
3199
            break;
3200 3201 3202
        default:
            goto die;
        }
3203 3204
        break;
    case 1:
3205 3206
        switch (sel) {
        case 0:
T
ths 已提交
3207
            /* ignored */
3208
            rn = "Random";
T
ths 已提交
3209
            break;
3210
        case 1:
3211
            check_insn(env, ctx, ASE_MT);
3212
            tcg_gen_helper_0_0(do_mtc0_vpecontrol);
3213
            rn = "VPEControl";
3214
            break;
3215
        case 2:
3216
            check_insn(env, ctx, ASE_MT);
3217
            tcg_gen_helper_0_0(do_mtc0_vpeconf0);
3218
            rn = "VPEConf0";
3219
            break;
3220
        case 3:
3221
            check_insn(env, ctx, ASE_MT);
3222
            tcg_gen_helper_0_0(do_mtc0_vpeconf1);
3223
            rn = "VPEConf1";
3224
            break;
3225
        case 4:
3226
            check_insn(env, ctx, ASE_MT);
3227
            tcg_gen_helper_0_0(do_mtc0_yqmask);
3228
            rn = "YQMask";
3229
            break;
3230
        case 5:
3231
            check_insn(env, ctx, ASE_MT);
3232
            gen_mtc0_store64(cpu_T[0], offsetof(CPUState, CP0_VPESchedule));
3233
            rn = "VPESchedule";
3234
            break;
3235
        case 6:
3236
            check_insn(env, ctx, ASE_MT);
3237
            gen_mtc0_store64(cpu_T[0], offsetof(CPUState, CP0_VPEScheFBack));
3238
            rn = "VPEScheFBack";
3239
            break;
3240
        case 7:
3241
            check_insn(env, ctx, ASE_MT);
3242
            tcg_gen_helper_0_0(do_mtc0_vpeopt);
3243
            rn = "VPEOpt";
3244
            break;
3245 3246 3247
        default:
            goto die;
        }
3248 3249
        break;
    case 2:
3250 3251
        switch (sel) {
        case 0:
3252
            tcg_gen_helper_0_0(do_mtc0_entrylo0);
T
ths 已提交
3253 3254
            rn = "EntryLo0";
            break;
3255
        case 1:
3256
            check_insn(env, ctx, ASE_MT);
3257
            tcg_gen_helper_0_0(do_mtc0_tcstatus);
T
ths 已提交
3258
            rn = "TCStatus";
3259
            break;
3260
        case 2:
3261
            check_insn(env, ctx, ASE_MT);
3262
            tcg_gen_helper_0_0(do_mtc0_tcbind);
T
ths 已提交
3263
            rn = "TCBind";
3264
            break;
3265
        case 3:
3266
            check_insn(env, ctx, ASE_MT);
3267
            tcg_gen_helper_0_0(do_mtc0_tcrestart);
T
ths 已提交
3268
            rn = "TCRestart";
3269
            break;
3270
        case 4:
3271
            check_insn(env, ctx, ASE_MT);
3272
            tcg_gen_helper_0_0(do_mtc0_tchalt);
T
ths 已提交
3273
            rn = "TCHalt";
3274
            break;
3275
        case 5:
3276
            check_insn(env, ctx, ASE_MT);
3277
            tcg_gen_helper_0_0(do_mtc0_tccontext);
T
ths 已提交
3278
            rn = "TCContext";
3279
            break;
3280
        case 6:
3281
            check_insn(env, ctx, ASE_MT);
3282
            tcg_gen_helper_0_0(do_mtc0_tcschedule);
T
ths 已提交
3283
            rn = "TCSchedule";
3284
            break;
3285
        case 7:
3286
            check_insn(env, ctx, ASE_MT);
3287
            tcg_gen_helper_0_0(do_mtc0_tcschefback);
T
ths 已提交
3288
            rn = "TCScheFBack";
3289
            break;
3290 3291 3292
        default:
            goto die;
        }
3293 3294
        break;
    case 3:
3295 3296
        switch (sel) {
        case 0:
3297
            tcg_gen_helper_0_0(do_mtc0_entrylo1);
T
ths 已提交
3298 3299
            rn = "EntryLo1";
            break;
3300 3301
        default:
            goto die;
T
ths 已提交
3302
        }
3303 3304
        break;
    case 4:
3305 3306
        switch (sel) {
        case 0:
3307
            tcg_gen_helper_0_0(do_mtc0_context);
T
ths 已提交
3308 3309
            rn = "Context";
            break;
3310
        case 1:
3311
//            tcg_gen_helper_0_0(do_mtc0_contextconfig); /* SmartMIPS ASE */
T
ths 已提交
3312 3313
            rn = "ContextConfig";
//            break;
3314 3315
        default:
            goto die;
T
ths 已提交
3316
        }
3317 3318
        break;
    case 5:
3319 3320
        switch (sel) {
        case 0:
3321
            tcg_gen_helper_0_0(do_mtc0_pagemask);
T
ths 已提交
3322 3323
            rn = "PageMask";
            break;
3324
        case 1:
3325
            check_insn(env, ctx, ISA_MIPS32R2);
3326
            tcg_gen_helper_0_0(do_mtc0_pagegrain);
T
ths 已提交
3327 3328
            rn = "PageGrain";
            break;
3329 3330
        default:
            goto die;
T
ths 已提交
3331
        }
3332 3333
        break;
    case 6:
3334 3335
        switch (sel) {
        case 0:
3336
            tcg_gen_helper_0_0(do_mtc0_wired);
T
ths 已提交
3337 3338
            rn = "Wired";
            break;
3339
        case 1:
3340
            check_insn(env, ctx, ISA_MIPS32R2);
3341
            tcg_gen_helper_0_0(do_mtc0_srsconf0);
T
ths 已提交
3342
            rn = "SRSConf0";
3343
            break;
3344
        case 2:
3345
            check_insn(env, ctx, ISA_MIPS32R2);
3346
            tcg_gen_helper_0_0(do_mtc0_srsconf1);
T
ths 已提交
3347
            rn = "SRSConf1";
3348
            break;
3349
        case 3:
3350
            check_insn(env, ctx, ISA_MIPS32R2);
3351
            tcg_gen_helper_0_0(do_mtc0_srsconf2);
T
ths 已提交
3352
            rn = "SRSConf2";
3353
            break;
3354
        case 4:
3355
            check_insn(env, ctx, ISA_MIPS32R2);
3356
            tcg_gen_helper_0_0(do_mtc0_srsconf3);
T
ths 已提交
3357
            rn = "SRSConf3";
3358
            break;
3359
        case 5:
3360
            check_insn(env, ctx, ISA_MIPS32R2);
3361
            tcg_gen_helper_0_0(do_mtc0_srsconf4);
T
ths 已提交
3362
            rn = "SRSConf4";
3363
            break;
3364 3365
        default:
            goto die;
T
ths 已提交
3366
        }
3367 3368
        break;
    case 7:
3369 3370
        switch (sel) {
        case 0:
3371
            check_insn(env, ctx, ISA_MIPS32R2);
3372
            tcg_gen_helper_0_0(do_mtc0_hwrena);
T
ths 已提交
3373 3374
            rn = "HWREna";
            break;
3375 3376
        default:
            goto die;
T
ths 已提交
3377
        }
3378 3379
        break;
    case 8:
3380
        /* ignored */
T
ths 已提交
3381
        rn = "BadVAddr";
3382 3383
        break;
    case 9:
3384 3385
        switch (sel) {
        case 0:
3386
            tcg_gen_helper_0_0(do_mtc0_count);
T
ths 已提交
3387 3388
            rn = "Count";
            break;
T
ths 已提交
3389
        /* 6,7 are implementation dependent */
3390 3391
        default:
            goto die;
T
ths 已提交
3392 3393 3394
        }
        /* Stop translation as we may have switched the execution mode */
        ctx->bstate = BS_STOP;
3395 3396
        break;
    case 10:
3397 3398
        switch (sel) {
        case 0:
3399
            tcg_gen_helper_0_0(do_mtc0_entryhi);
T
ths 已提交
3400 3401
            rn = "EntryHi";
            break;
3402 3403
        default:
            goto die;
T
ths 已提交
3404
        }
3405 3406
        break;
    case 11:
3407 3408
        switch (sel) {
        case 0:
3409
            tcg_gen_helper_0_0(do_mtc0_compare);
T
ths 已提交
3410 3411 3412
            rn = "Compare";
            break;
        /* 6,7 are implementation dependent */
3413 3414
        default:
            goto die;
T
ths 已提交
3415
        }
A
aurel32 已提交
3416 3417
        /* Stop translation as we may have switched the execution mode */
        ctx->bstate = BS_STOP;
3418 3419
        break;
    case 12:
3420 3421
        switch (sel) {
        case 0:
3422
            tcg_gen_helper_0_0(do_mtc0_status);
3423 3424 3425
            /* BS_STOP isn't good enough here, hflags may have changed. */
            gen_save_pc(ctx->pc + 4);
            ctx->bstate = BS_EXCP;
T
ths 已提交
3426 3427
            rn = "Status";
            break;
3428
        case 1:
3429
            check_insn(env, ctx, ISA_MIPS32R2);
3430
            tcg_gen_helper_0_0(do_mtc0_intctl);
3431 3432
            /* Stop translation as we may have switched the execution mode */
            ctx->bstate = BS_STOP;
T
ths 已提交
3433 3434
            rn = "IntCtl";
            break;
3435
        case 2:
3436
            check_insn(env, ctx, ISA_MIPS32R2);
3437
            tcg_gen_helper_0_0(do_mtc0_srsctl);
3438 3439
            /* Stop translation as we may have switched the execution mode */
            ctx->bstate = BS_STOP;
T
ths 已提交
3440 3441
            rn = "SRSCtl";
            break;
3442
        case 3:
3443
            check_insn(env, ctx, ISA_MIPS32R2);
3444
            gen_mtc0_store32(cpu_T[0], offsetof(CPUState, CP0_SRSMap));
3445 3446
            /* Stop translation as we may have switched the execution mode */
            ctx->bstate = BS_STOP;
T
ths 已提交
3447
            rn = "SRSMap";
3448
            break;
3449 3450
        default:
            goto die;
T
ths 已提交
3451
        }
3452 3453
        break;
    case 13:
3454 3455
        switch (sel) {
        case 0:
3456
            tcg_gen_helper_0_0(do_mtc0_cause);
T
ths 已提交
3457 3458
            rn = "Cause";
            break;
3459 3460
        default:
            goto die;
T
ths 已提交
3461 3462 3463
        }
        /* Stop translation as we may have switched the execution mode */
        ctx->bstate = BS_STOP;
3464 3465
        break;
    case 14:
3466 3467
        switch (sel) {
        case 0:
3468
            gen_mtc0_store64(cpu_T[0], offsetof(CPUState, CP0_EPC));
T
ths 已提交
3469 3470
            rn = "EPC";
            break;
3471 3472
        default:
            goto die;
T
ths 已提交
3473
        }
3474 3475
        break;
    case 15:
3476 3477
        switch (sel) {
        case 0:
T
ths 已提交
3478 3479 3480
            /* ignored */
            rn = "PRid";
            break;
3481
        case 1:
3482
            check_insn(env, ctx, ISA_MIPS32R2);
3483
            tcg_gen_helper_0_0(do_mtc0_ebase);
T
ths 已提交
3484 3485
            rn = "EBase";
            break;
3486 3487
        default:
            goto die;
3488
        }
3489 3490 3491 3492
        break;
    case 16:
        switch (sel) {
        case 0:
3493
            tcg_gen_helper_0_0(do_mtc0_config0);
3494
            rn = "Config";
T
ths 已提交
3495 3496
            /* Stop translation as we may have switched the execution mode */
            ctx->bstate = BS_STOP;
3497 3498
            break;
        case 1:
3499
            /* ignored, read only */
3500 3501 3502
            rn = "Config1";
            break;
        case 2:
3503
            tcg_gen_helper_0_0(do_mtc0_config2);
3504
            rn = "Config2";
T
ths 已提交
3505 3506
            /* Stop translation as we may have switched the execution mode */
            ctx->bstate = BS_STOP;
3507
            break;
3508
        case 3:
3509
            /* ignored, read only */
3510 3511
            rn = "Config3";
            break;
3512 3513 3514 3515 3516 3517 3518 3519 3520 3521
        /* 4,5 are reserved */
        /* 6,7 are implementation dependent */
        case 6:
            /* ignored */
            rn = "Config6";
            break;
        case 7:
            /* ignored */
            rn = "Config7";
            break;
3522 3523 3524 3525 3526 3527
        default:
            rn = "Invalid config selector";
            goto die;
        }
        break;
    case 17:
3528 3529
        switch (sel) {
        case 0:
T
ths 已提交
3530 3531 3532
            /* ignored */
            rn = "LLAddr";
            break;
3533 3534 3535
        default:
            goto die;
        }
3536 3537
        break;
    case 18:
3538
        switch (sel) {
3539
        case 0 ... 7:
3540
            tcg_gen_helper_0_1i(do_mtc0_watchlo, sel);
T
ths 已提交
3541 3542
            rn = "WatchLo";
            break;
3543 3544 3545
        default:
            goto die;
        }
3546 3547
        break;
    case 19:
3548
        switch (sel) {
3549
        case 0 ... 7:
3550
            tcg_gen_helper_0_1i(do_mtc0_watchhi, sel);
T
ths 已提交
3551 3552
            rn = "WatchHi";
            break;
3553 3554 3555
        default:
            goto die;
        }
3556 3557
        break;
    case 20:
3558 3559
        switch (sel) {
        case 0:
3560
#if defined(TARGET_MIPS64)
3561
            check_insn(env, ctx, ISA_MIPS3);
3562
            tcg_gen_helper_0_0(do_mtc0_xcontext);
T
ths 已提交
3563 3564
            rn = "XContext";
            break;
T
ths 已提交
3565
#endif
3566 3567 3568
        default:
            goto die;
        }
3569 3570
        break;
    case 21:
3571 3572 3573
       /* Officially reserved, but sel 0 is used for R1x000 framemask */
        switch (sel) {
        case 0:
3574
            tcg_gen_helper_0_0(do_mtc0_framemask);
T
ths 已提交
3575 3576
            rn = "Framemask";
            break;
3577 3578 3579 3580
        default:
            goto die;
        }
        break;
3581
    case 22:
3582 3583
        /* ignored */
        rn = "Diagnostic"; /* implementation dependent */
T
ths 已提交
3584
        break;
3585
    case 23:
3586 3587
        switch (sel) {
        case 0:
3588
            tcg_gen_helper_0_0(do_mtc0_debug); /* EJTAG support */
3589 3590 3591
            /* BS_STOP isn't good enough here, hflags may have changed. */
            gen_save_pc(ctx->pc + 4);
            ctx->bstate = BS_EXCP;
T
ths 已提交
3592 3593
            rn = "Debug";
            break;
3594
        case 1:
3595
//            tcg_gen_helper_0_0(do_mtc0_tracecontrol); /* PDtrace support */
T
ths 已提交
3596
            rn = "TraceControl";
3597 3598
            /* Stop translation as we may have switched the execution mode */
            ctx->bstate = BS_STOP;
T
ths 已提交
3599
//            break;
3600
        case 2:
3601
//            tcg_gen_helper_0_0(do_mtc0_tracecontrol2); /* PDtrace support */
T
ths 已提交
3602
            rn = "TraceControl2";
3603 3604
            /* Stop translation as we may have switched the execution mode */
            ctx->bstate = BS_STOP;
T
ths 已提交
3605
//            break;
3606
        case 3:
3607 3608
            /* Stop translation as we may have switched the execution mode */
            ctx->bstate = BS_STOP;
3609
//            tcg_gen_helper_0_0(do_mtc0_usertracedata); /* PDtrace support */
T
ths 已提交
3610
            rn = "UserTraceData";
3611 3612
            /* Stop translation as we may have switched the execution mode */
            ctx->bstate = BS_STOP;
T
ths 已提交
3613
//            break;
3614
        case 4:
3615
//            tcg_gen_helper_0_0(do_mtc0_debug); /* PDtrace support */
3616 3617
            /* Stop translation as we may have switched the execution mode */
            ctx->bstate = BS_STOP;
T
ths 已提交
3618 3619
            rn = "TraceBPC";
//            break;
3620 3621 3622
        default:
            goto die;
        }
3623 3624
        break;
    case 24:
3625 3626
        switch (sel) {
        case 0:
3627 3628
            /* EJTAG support */
            gen_mtc0_store64(cpu_T[0], offsetof(CPUState, CP0_DEPC));
T
ths 已提交
3629 3630
            rn = "DEPC";
            break;
3631 3632 3633
        default:
            goto die;
        }
3634 3635
        break;
    case 25:
3636 3637
        switch (sel) {
        case 0:
3638
            tcg_gen_helper_0_0(do_mtc0_performance0);
T
ths 已提交
3639 3640
            rn = "Performance0";
            break;
3641
        case 1:
3642
//            tcg_gen_helper_0_0(do_mtc0_performance1);
T
ths 已提交
3643 3644
            rn = "Performance1";
//            break;
3645
        case 2:
3646
//            tcg_gen_helper_0_0(do_mtc0_performance2);
T
ths 已提交
3647 3648
            rn = "Performance2";
//            break;
3649
        case 3:
3650
//            tcg_gen_helper_0_0(do_mtc0_performance3);
T
ths 已提交
3651 3652
            rn = "Performance3";
//            break;
3653
        case 4:
3654
//            tcg_gen_helper_0_0(do_mtc0_performance4);
T
ths 已提交
3655 3656
            rn = "Performance4";
//            break;
3657
        case 5:
3658
//            tcg_gen_helper_0_0(do_mtc0_performance5);
T
ths 已提交
3659 3660
            rn = "Performance5";
//            break;
3661
        case 6:
3662
//            tcg_gen_helper_0_0(do_mtc0_performance6);
T
ths 已提交
3663 3664
            rn = "Performance6";
//            break;
3665
        case 7:
3666
//            tcg_gen_helper_0_0(do_mtc0_performance7);
T
ths 已提交
3667 3668
            rn = "Performance7";
//            break;
3669 3670 3671
        default:
            goto die;
        }
3672 3673
       break;
    case 26:
T
ths 已提交
3674
        /* ignored */
3675
        rn = "ECC";
T
ths 已提交
3676
        break;
3677
    case 27:
3678 3679
        switch (sel) {
        case 0 ... 3:
T
ths 已提交
3680 3681 3682
            /* ignored */
            rn = "CacheErr";
            break;
3683 3684 3685
        default:
            goto die;
        }
3686 3687 3688 3689
       break;
    case 28:
        switch (sel) {
        case 0:
3690 3691 3692
        case 2:
        case 4:
        case 6:
3693
            tcg_gen_helper_0_0(do_mtc0_taglo);
3694 3695
            rn = "TagLo";
            break;
3696 3697 3698 3699
        case 1:
        case 3:
        case 5:
        case 7:
3700
            tcg_gen_helper_0_0(do_mtc0_datalo);
3701 3702
            rn = "DataLo";
            break;
3703 3704 3705 3706 3707
        default:
            goto die;
        }
        break;
    case 29:
3708 3709 3710 3711 3712
        switch (sel) {
        case 0:
        case 2:
        case 4:
        case 6:
3713
            tcg_gen_helper_0_0(do_mtc0_taghi);
3714 3715 3716 3717 3718 3719
            rn = "TagHi";
            break;
        case 1:
        case 3:
        case 5:
        case 7:
3720
            tcg_gen_helper_0_0(do_mtc0_datahi);
3721 3722 3723 3724 3725 3726
            rn = "DataHi";
            break;
        default:
            rn = "invalid sel";
            goto die;
        }
3727 3728
       break;
    case 30:
3729 3730
        switch (sel) {
        case 0:
3731
            gen_mtc0_store64(cpu_T[0], offsetof(CPUState, CP0_ErrorEPC));
T
ths 已提交
3732 3733
            rn = "ErrorEPC";
            break;
3734 3735 3736
        default:
            goto die;
        }
3737 3738
        break;
    case 31:
3739 3740
        switch (sel) {
        case 0:
3741 3742
            /* EJTAG support */
            gen_mtc0_store32(cpu_T[0], offsetof(CPUState, CP0_DESAVE));
T
ths 已提交
3743 3744
            rn = "DESAVE";
            break;
3745 3746 3747
        default:
            goto die;
        }
T
ths 已提交
3748 3749
        /* Stop translation as we may have switched the execution mode */
        ctx->bstate = BS_STOP;
3750 3751 3752 3753 3754 3755
        break;
    default:
       goto die;
    }
#if defined MIPS_DEBUG_DISAS
    if (loglevel & CPU_LOG_TB_IN_ASM) {
3756 3757
        fprintf(logfile, "mtc0 %s (reg %d sel %d)\n",
                rn, reg, sel);
3758 3759 3760 3761 3762 3763 3764
    }
#endif
    return;

die:
#if defined MIPS_DEBUG_DISAS
    if (loglevel & CPU_LOG_TB_IN_ASM) {
3765 3766
        fprintf(logfile, "mtc0 %s (reg %d sel %d)\n",
                rn, reg, sel);
3767 3768 3769 3770 3771
    }
#endif
    generate_exception(ctx, EXCP_RI);
}

3772
#if defined(TARGET_MIPS64)
3773
static void gen_dmfc0 (CPUState *env, DisasContext *ctx, int reg, int sel)
T
ths 已提交
3774 3775 3776
{
    const char *rn = "invalid";

3777 3778 3779
    if (sel != 0)
        check_insn(env, ctx, ISA_MIPS64);

T
ths 已提交
3780 3781 3782 3783
    switch (reg) {
    case 0:
        switch (sel) {
        case 0:
T
ths 已提交
3784
            gen_mfc0_load32(cpu_T[0], offsetof(CPUState, CP0_Index));
T
ths 已提交
3785 3786 3787
            rn = "Index";
            break;
        case 1:
3788
            check_insn(env, ctx, ASE_MT);
3789
            tcg_gen_helper_0_0(do_mfc0_mvpcontrol);
T
ths 已提交
3790
            rn = "MVPControl";
3791
            break;
T
ths 已提交
3792
        case 2:
3793
            check_insn(env, ctx, ASE_MT);
3794
            tcg_gen_helper_0_0(do_mfc0_mvpconf0);
T
ths 已提交
3795
            rn = "MVPConf0";
3796
            break;
T
ths 已提交
3797
        case 3:
3798
            check_insn(env, ctx, ASE_MT);
3799
            tcg_gen_helper_0_0(do_mfc0_mvpconf1);
T
ths 已提交
3800
            rn = "MVPConf1";
3801
            break;
T
ths 已提交
3802 3803 3804 3805 3806 3807 3808
        default:
            goto die;
        }
        break;
    case 1:
        switch (sel) {
        case 0:
3809
            tcg_gen_helper_0_0(do_mfc0_random);
T
ths 已提交
3810
            rn = "Random";
T
ths 已提交
3811
            break;
T
ths 已提交
3812
        case 1:
3813
            check_insn(env, ctx, ASE_MT);
T
ths 已提交
3814
            gen_mfc0_load32(cpu_T[0], offsetof(CPUState, CP0_VPEControl));
T
ths 已提交
3815
            rn = "VPEControl";
3816
            break;
T
ths 已提交
3817
        case 2:
3818
            check_insn(env, ctx, ASE_MT);
T
ths 已提交
3819
            gen_mfc0_load32(cpu_T[0], offsetof(CPUState, CP0_VPEConf0));
T
ths 已提交
3820
            rn = "VPEConf0";
3821
            break;
T
ths 已提交
3822
        case 3:
3823
            check_insn(env, ctx, ASE_MT);
T
ths 已提交
3824
            gen_mfc0_load32(cpu_T[0], offsetof(CPUState, CP0_VPEConf1));
T
ths 已提交
3825
            rn = "VPEConf1";
3826
            break;
T
ths 已提交
3827
        case 4:
3828
            check_insn(env, ctx, ASE_MT);
T
ths 已提交
3829
            tcg_gen_ld_tl(cpu_T[0], cpu_env, offsetof(CPUState, CP0_YQMask));
T
ths 已提交
3830
            rn = "YQMask";
3831
            break;
T
ths 已提交
3832
        case 5:
3833
            check_insn(env, ctx, ASE_MT);
T
ths 已提交
3834
            tcg_gen_ld_tl(cpu_T[0], cpu_env, offsetof(CPUState, CP0_VPESchedule));
T
ths 已提交
3835
            rn = "VPESchedule";
3836
            break;
T
ths 已提交
3837
        case 6:
3838
            check_insn(env, ctx, ASE_MT);
T
ths 已提交
3839
            tcg_gen_ld_tl(cpu_T[0], cpu_env, offsetof(CPUState, CP0_VPEScheFBack));
T
ths 已提交
3840
            rn = "VPEScheFBack";
3841
            break;
T
ths 已提交
3842
        case 7:
3843
            check_insn(env, ctx, ASE_MT);
T
ths 已提交
3844
            gen_mfc0_load32(cpu_T[0], offsetof(CPUState, CP0_VPEOpt));
T
ths 已提交
3845
            rn = "VPEOpt";
3846
            break;
T
ths 已提交
3847 3848 3849 3850 3851 3852 3853
        default:
            goto die;
        }
        break;
    case 2:
        switch (sel) {
        case 0:
T
ths 已提交
3854
            tcg_gen_ld_tl(cpu_T[0], cpu_env, offsetof(CPUState, CP0_EntryLo0));
T
ths 已提交
3855 3856
            rn = "EntryLo0";
            break;
T
ths 已提交
3857
        case 1:
3858
            check_insn(env, ctx, ASE_MT);
3859
            tcg_gen_helper_0_0(do_mfc0_tcstatus);
T
ths 已提交
3860
            rn = "TCStatus";
3861
            break;
T
ths 已提交
3862
        case 2:
3863
            check_insn(env, ctx, ASE_MT);
3864
            tcg_gen_helper_0_0(do_mfc0_tcbind);
T
ths 已提交
3865
            rn = "TCBind";
3866
            break;
T
ths 已提交
3867
        case 3:
3868
            check_insn(env, ctx, ASE_MT);
3869
            tcg_gen_helper_0_0(do_dmfc0_tcrestart);
T
ths 已提交
3870
            rn = "TCRestart";
3871
            break;
T
ths 已提交
3872
        case 4:
3873
            check_insn(env, ctx, ASE_MT);
3874
            tcg_gen_helper_0_0(do_dmfc0_tchalt);
T
ths 已提交
3875
            rn = "TCHalt";
3876
            break;
T
ths 已提交
3877
        case 5:
3878
            check_insn(env, ctx, ASE_MT);
3879
            tcg_gen_helper_0_0(do_dmfc0_tccontext);
T
ths 已提交
3880
            rn = "TCContext";
3881
            break;
T
ths 已提交
3882
        case 6:
3883
            check_insn(env, ctx, ASE_MT);
3884
            tcg_gen_helper_0_0(do_dmfc0_tcschedule);
T
ths 已提交
3885
            rn = "TCSchedule";
3886
            break;
T
ths 已提交
3887
        case 7:
3888
            check_insn(env, ctx, ASE_MT);
3889
            tcg_gen_helper_0_0(do_dmfc0_tcschefback);
T
ths 已提交
3890
            rn = "TCScheFBack";
3891
            break;
T
ths 已提交
3892 3893 3894 3895 3896 3897 3898
        default:
            goto die;
        }
        break;
    case 3:
        switch (sel) {
        case 0:
T
ths 已提交
3899
            tcg_gen_ld_tl(cpu_T[0], cpu_env, offsetof(CPUState, CP0_EntryLo1));
T
ths 已提交
3900 3901
            rn = "EntryLo1";
            break;
T
ths 已提交
3902 3903
        default:
            goto die;
3904
        }
T
ths 已提交
3905 3906 3907 3908
        break;
    case 4:
        switch (sel) {
        case 0:
T
ths 已提交
3909
            tcg_gen_ld_tl(cpu_T[0], cpu_env, offsetof(CPUState, CP0_Context));
T
ths 已提交
3910 3911
            rn = "Context";
            break;
T
ths 已提交
3912
        case 1:
3913
//            tcg_gen_helper_0_0(do_dmfc0_contextconfig); /* SmartMIPS ASE */
T
ths 已提交
3914 3915
            rn = "ContextConfig";
//            break;
T
ths 已提交
3916 3917
        default:
            goto die;
T
ths 已提交
3918
        }
T
ths 已提交
3919 3920 3921 3922
        break;
    case 5:
        switch (sel) {
        case 0:
T
ths 已提交
3923
            gen_mfc0_load32(cpu_T[0], offsetof(CPUState, CP0_PageMask));
T
ths 已提交
3924 3925
            rn = "PageMask";
            break;
T
ths 已提交
3926
        case 1:
3927
            check_insn(env, ctx, ISA_MIPS32R2);
T
ths 已提交
3928
            gen_mfc0_load32(cpu_T[0], offsetof(CPUState, CP0_PageGrain));
T
ths 已提交
3929 3930
            rn = "PageGrain";
            break;
T
ths 已提交
3931 3932
        default:
            goto die;
T
ths 已提交
3933
        }
T
ths 已提交
3934 3935 3936 3937
        break;
    case 6:
        switch (sel) {
        case 0:
T
ths 已提交
3938
            gen_mfc0_load32(cpu_T[0], offsetof(CPUState, CP0_Wired));
T
ths 已提交
3939 3940
            rn = "Wired";
            break;
T
ths 已提交
3941
        case 1:
3942
            check_insn(env, ctx, ISA_MIPS32R2);
T
ths 已提交
3943
            gen_mfc0_load32(cpu_T[0], offsetof(CPUState, CP0_SRSConf0));
T
ths 已提交
3944
            rn = "SRSConf0";
3945
            break;
T
ths 已提交
3946
        case 2:
3947
            check_insn(env, ctx, ISA_MIPS32R2);
T
ths 已提交
3948
            gen_mfc0_load32(cpu_T[0], offsetof(CPUState, CP0_SRSConf1));
T
ths 已提交
3949
            rn = "SRSConf1";
3950
            break;
T
ths 已提交
3951
        case 3:
3952
            check_insn(env, ctx, ISA_MIPS32R2);
T
ths 已提交
3953
            gen_mfc0_load32(cpu_T[0], offsetof(CPUState, CP0_SRSConf2));
T
ths 已提交
3954
            rn = "SRSConf2";
3955
            break;
T
ths 已提交
3956
        case 4:
3957
            check_insn(env, ctx, ISA_MIPS32R2);
T
ths 已提交
3958
            gen_mfc0_load32(cpu_T[0], offsetof(CPUState, CP0_SRSConf3));
T
ths 已提交
3959
            rn = "SRSConf3";
3960
            break;
T
ths 已提交
3961
        case 5:
3962
            check_insn(env, ctx, ISA_MIPS32R2);
T
ths 已提交
3963
            gen_mfc0_load32(cpu_T[0], offsetof(CPUState, CP0_SRSConf4));
T
ths 已提交
3964
            rn = "SRSConf4";
3965
            break;
T
ths 已提交
3966 3967
        default:
            goto die;
T
ths 已提交
3968
        }
T
ths 已提交
3969 3970 3971 3972
        break;
    case 7:
        switch (sel) {
        case 0:
3973
            check_insn(env, ctx, ISA_MIPS32R2);
T
ths 已提交
3974
            gen_mfc0_load32(cpu_T[0], offsetof(CPUState, CP0_HWREna));
T
ths 已提交
3975 3976
            rn = "HWREna";
            break;
T
ths 已提交
3977 3978
        default:
            goto die;
T
ths 已提交
3979
        }
T
ths 已提交
3980 3981 3982 3983
        break;
    case 8:
        switch (sel) {
        case 0:
T
ths 已提交
3984 3985
            tcg_gen_ld_tl(cpu_T[0], cpu_env, offsetof(CPUState, CP0_BadVAddr));
            rn = "BadVAddr";
T
ths 已提交
3986
            break;
T
ths 已提交
3987 3988
        default:
            goto die;
T
ths 已提交
3989
        }
T
ths 已提交
3990 3991 3992 3993
        break;
    case 9:
        switch (sel) {
        case 0:
3994
            tcg_gen_helper_0_0(do_mfc0_count);
T
ths 已提交
3995 3996 3997
            rn = "Count";
            break;
        /* 6,7 are implementation dependent */
T
ths 已提交
3998 3999
        default:
            goto die;
T
ths 已提交
4000
        }
T
ths 已提交
4001 4002 4003 4004
        break;
    case 10:
        switch (sel) {
        case 0:
T
ths 已提交
4005
            tcg_gen_ld_tl(cpu_T[0], cpu_env, offsetof(CPUState, CP0_EntryHi));
T
ths 已提交
4006 4007
            rn = "EntryHi";
            break;
T
ths 已提交
4008 4009
        default:
            goto die;
T
ths 已提交
4010
        }
T
ths 已提交
4011 4012 4013 4014
        break;
    case 11:
        switch (sel) {
        case 0:
T
ths 已提交
4015
            gen_mfc0_load32(cpu_T[0], offsetof(CPUState, CP0_Compare));
T
ths 已提交
4016 4017
            rn = "Compare";
            break;
T
ths 已提交
4018
        /* 6,7 are implementation dependent */
T
ths 已提交
4019 4020
        default:
            goto die;
T
ths 已提交
4021
        }
T
ths 已提交
4022 4023 4024 4025
        break;
    case 12:
        switch (sel) {
        case 0:
T
ths 已提交
4026
            gen_mfc0_load32(cpu_T[0], offsetof(CPUState, CP0_Status));
T
ths 已提交
4027 4028
            rn = "Status";
            break;
T
ths 已提交
4029
        case 1:
4030
            check_insn(env, ctx, ISA_MIPS32R2);
T
ths 已提交
4031
            gen_mfc0_load32(cpu_T[0], offsetof(CPUState, CP0_IntCtl));
T
ths 已提交
4032 4033
            rn = "IntCtl";
            break;
T
ths 已提交
4034
        case 2:
4035
            check_insn(env, ctx, ISA_MIPS32R2);
T
ths 已提交
4036
            gen_mfc0_load32(cpu_T[0], offsetof(CPUState, CP0_SRSCtl));
T
ths 已提交
4037 4038
            rn = "SRSCtl";
            break;
T
ths 已提交
4039
        case 3:
4040
            check_insn(env, ctx, ISA_MIPS32R2);
T
ths 已提交
4041
            gen_mfc0_load32(cpu_T[0], offsetof(CPUState, CP0_SRSMap));
T
ths 已提交
4042 4043
            rn = "SRSMap";
            break;
T
ths 已提交
4044 4045
        default:
            goto die;
T
ths 已提交
4046
        }
T
ths 已提交
4047 4048 4049 4050
        break;
    case 13:
        switch (sel) {
        case 0:
T
ths 已提交
4051
            gen_mfc0_load32(cpu_T[0], offsetof(CPUState, CP0_Cause));
T
ths 已提交
4052 4053
            rn = "Cause";
            break;
T
ths 已提交
4054 4055
        default:
            goto die;
T
ths 已提交
4056
        }
T
ths 已提交
4057 4058 4059 4060
        break;
    case 14:
        switch (sel) {
        case 0:
T
ths 已提交
4061
            tcg_gen_ld_tl(cpu_T[0], cpu_env, offsetof(CPUState, CP0_EPC));
T
ths 已提交
4062 4063
            rn = "EPC";
            break;
T
ths 已提交
4064 4065
        default:
            goto die;
T
ths 已提交
4066
        }
T
ths 已提交
4067 4068 4069 4070
        break;
    case 15:
        switch (sel) {
        case 0:
T
ths 已提交
4071
            gen_mfc0_load32(cpu_T[0], offsetof(CPUState, CP0_PRid));
T
ths 已提交
4072 4073
            rn = "PRid";
            break;
T
ths 已提交
4074
        case 1:
4075
            check_insn(env, ctx, ISA_MIPS32R2);
T
ths 已提交
4076
            gen_mfc0_load32(cpu_T[0], offsetof(CPUState, CP0_EBase));
T
ths 已提交
4077 4078
            rn = "EBase";
            break;
T
ths 已提交
4079 4080
        default:
            goto die;
T
ths 已提交
4081
        }
T
ths 已提交
4082 4083 4084 4085
        break;
    case 16:
        switch (sel) {
        case 0:
T
ths 已提交
4086
            gen_mfc0_load32(cpu_T[0], offsetof(CPUState, CP0_Config0));
T
ths 已提交
4087 4088 4089
            rn = "Config";
            break;
        case 1:
T
ths 已提交
4090
            gen_mfc0_load32(cpu_T[0], offsetof(CPUState, CP0_Config1));
T
ths 已提交
4091 4092 4093
            rn = "Config1";
            break;
        case 2:
T
ths 已提交
4094
            gen_mfc0_load32(cpu_T[0], offsetof(CPUState, CP0_Config2));
T
ths 已提交
4095 4096 4097
            rn = "Config2";
            break;
        case 3:
T
ths 已提交
4098
            gen_mfc0_load32(cpu_T[0], offsetof(CPUState, CP0_Config3));
T
ths 已提交
4099 4100 4101
            rn = "Config3";
            break;
       /* 6,7 are implementation dependent */
T
ths 已提交
4102
        case 6:
T
ths 已提交
4103
            gen_mfc0_load32(cpu_T[0], offsetof(CPUState, CP0_Config6));
T
ths 已提交
4104 4105 4106
            rn = "Config6";
            break;
        case 7:
T
ths 已提交
4107
            gen_mfc0_load32(cpu_T[0], offsetof(CPUState, CP0_Config7));
T
ths 已提交
4108 4109
            rn = "Config7";
            break;
T
ths 已提交
4110 4111 4112 4113 4114 4115 4116
        default:
            goto die;
        }
        break;
    case 17:
        switch (sel) {
        case 0:
4117
            tcg_gen_helper_0_0(do_dmfc0_lladdr);
T
ths 已提交
4118 4119
            rn = "LLAddr";
            break;
T
ths 已提交
4120 4121 4122 4123 4124 4125
        default:
            goto die;
        }
        break;
    case 18:
        switch (sel) {
4126
        case 0 ... 7:
4127
            tcg_gen_helper_0_1i(do_dmfc0_watchlo, sel);
T
ths 已提交
4128 4129
            rn = "WatchLo";
            break;
T
ths 已提交
4130 4131 4132 4133 4134 4135
        default:
            goto die;
        }
        break;
    case 19:
        switch (sel) {
4136
        case 0 ... 7:
4137
            tcg_gen_helper_0_1i(do_mfc0_watchhi, sel);
T
ths 已提交
4138 4139
            rn = "WatchHi";
            break;
T
ths 已提交
4140 4141 4142 4143 4144 4145 4146
        default:
            goto die;
        }
        break;
    case 20:
        switch (sel) {
        case 0:
4147
            check_insn(env, ctx, ISA_MIPS3);
T
ths 已提交
4148
            tcg_gen_ld_tl(cpu_T[0], cpu_env, offsetof(CPUState, CP0_XContext));
T
ths 已提交
4149 4150
            rn = "XContext";
            break;
T
ths 已提交
4151 4152 4153 4154 4155 4156 4157 4158
        default:
            goto die;
        }
        break;
    case 21:
       /* Officially reserved, but sel 0 is used for R1x000 framemask */
        switch (sel) {
        case 0:
T
ths 已提交
4159
            gen_mfc0_load32(cpu_T[0], offsetof(CPUState, CP0_Framemask));
T
ths 已提交
4160 4161
            rn = "Framemask";
            break;
T
ths 已提交
4162 4163 4164 4165 4166
        default:
            goto die;
        }
        break;
    case 22:
T
ths 已提交
4167 4168 4169
        /* ignored */
        rn = "'Diagnostic"; /* implementation dependent */
        break;
T
ths 已提交
4170 4171 4172
    case 23:
        switch (sel) {
        case 0:
4173
            tcg_gen_helper_0_0(do_mfc0_debug); /* EJTAG support */
T
ths 已提交
4174 4175
            rn = "Debug";
            break;
T
ths 已提交
4176
        case 1:
4177
//            tcg_gen_helper_0_0(do_dmfc0_tracecontrol); /* PDtrace support */
T
ths 已提交
4178 4179
            rn = "TraceControl";
//            break;
T
ths 已提交
4180
        case 2:
4181
//            tcg_gen_helper_0_0(do_dmfc0_tracecontrol2); /* PDtrace support */
T
ths 已提交
4182 4183
            rn = "TraceControl2";
//            break;
T
ths 已提交
4184
        case 3:
4185
//            tcg_gen_helper_0_0(do_dmfc0_usertracedata); /* PDtrace support */
T
ths 已提交
4186 4187
            rn = "UserTraceData";
//            break;
T
ths 已提交
4188
        case 4:
4189
//            tcg_gen_helper_0_0(do_dmfc0_debug); /* PDtrace support */
T
ths 已提交
4190 4191
            rn = "TraceBPC";
//            break;
T
ths 已提交
4192 4193 4194 4195 4196 4197 4198
        default:
            goto die;
        }
        break;
    case 24:
        switch (sel) {
        case 0:
T
ths 已提交
4199 4200
            /* EJTAG support */
            tcg_gen_ld_tl(cpu_T[0], cpu_env, offsetof(CPUState, CP0_DEPC));
T
ths 已提交
4201 4202
            rn = "DEPC";
            break;
T
ths 已提交
4203 4204 4205 4206 4207 4208 4209
        default:
            goto die;
        }
        break;
    case 25:
        switch (sel) {
        case 0:
T
ths 已提交
4210
            gen_mfc0_load32(cpu_T[0], offsetof(CPUState, CP0_Performance0));
T
ths 已提交
4211
            rn = "Performance0";
T
ths 已提交
4212 4213
            break;
        case 1:
4214
//            tcg_gen_helper_0_0(do_dmfc0_performance1);
T
ths 已提交
4215 4216
            rn = "Performance1";
//            break;
T
ths 已提交
4217
        case 2:
4218
//            tcg_gen_helper_0_0(do_dmfc0_performance2);
T
ths 已提交
4219 4220
            rn = "Performance2";
//            break;
T
ths 已提交
4221
        case 3:
4222
//            tcg_gen_helper_0_0(do_dmfc0_performance3);
T
ths 已提交
4223 4224
            rn = "Performance3";
//            break;
T
ths 已提交
4225
        case 4:
4226
//            tcg_gen_helper_0_0(do_dmfc0_performance4);
T
ths 已提交
4227 4228
            rn = "Performance4";
//            break;
T
ths 已提交
4229
        case 5:
4230
//            tcg_gen_helper_0_0(do_dmfc0_performance5);
T
ths 已提交
4231 4232
            rn = "Performance5";
//            break;
T
ths 已提交
4233
        case 6:
4234
//            tcg_gen_helper_0_0(do_dmfc0_performance6);
T
ths 已提交
4235 4236
            rn = "Performance6";
//            break;
T
ths 已提交
4237
        case 7:
4238
//            tcg_gen_helper_0_0(do_dmfc0_performance7);
T
ths 已提交
4239 4240
            rn = "Performance7";
//            break;
T
ths 已提交
4241 4242 4243 4244 4245 4246 4247 4248 4249 4250 4251
        default:
            goto die;
        }
        break;
    case 26:
       rn = "ECC";
       break;
    case 27:
        switch (sel) {
        /* ignored */
        case 0 ... 3:
T
ths 已提交
4252 4253
            rn = "CacheErr";
            break;
T
ths 已提交
4254 4255 4256 4257 4258 4259 4260 4261 4262 4263
        default:
            goto die;
        }
        break;
    case 28:
        switch (sel) {
        case 0:
        case 2:
        case 4:
        case 6:
T
ths 已提交
4264
            gen_mfc0_load32(cpu_T[0], offsetof(CPUState, CP0_TagLo));
T
ths 已提交
4265 4266 4267 4268 4269 4270
            rn = "TagLo";
            break;
        case 1:
        case 3:
        case 5:
        case 7:
T
ths 已提交
4271
            gen_mfc0_load32(cpu_T[0], offsetof(CPUState, CP0_DataLo));
T
ths 已提交
4272 4273 4274 4275 4276 4277 4278 4279 4280 4281 4282 4283
            rn = "DataLo";
            break;
        default:
            goto die;
        }
        break;
    case 29:
        switch (sel) {
        case 0:
        case 2:
        case 4:
        case 6:
T
ths 已提交
4284
            gen_mfc0_load32(cpu_T[0], offsetof(CPUState, CP0_TagHi));
T
ths 已提交
4285 4286 4287 4288 4289 4290
            rn = "TagHi";
            break;
        case 1:
        case 3:
        case 5:
        case 7:
T
ths 已提交
4291
            gen_mfc0_load32(cpu_T[0], offsetof(CPUState, CP0_DataHi));
T
ths 已提交
4292 4293 4294 4295 4296 4297 4298 4299 4300
            rn = "DataHi";
            break;
        default:
            goto die;
        }
        break;
    case 30:
        switch (sel) {
        case 0:
T
ths 已提交
4301
            tcg_gen_ld_tl(cpu_T[0], cpu_env, offsetof(CPUState, CP0_ErrorEPC));
T
ths 已提交
4302 4303
            rn = "ErrorEPC";
            break;
T
ths 已提交
4304 4305 4306 4307 4308 4309 4310
        default:
            goto die;
        }
        break;
    case 31:
        switch (sel) {
        case 0:
T
ths 已提交
4311
            /* EJTAG support */
T
ths 已提交
4312
            gen_mfc0_load32(cpu_T[0], offsetof(CPUState, CP0_DESAVE));
T
ths 已提交
4313 4314
            rn = "DESAVE";
            break;
T
ths 已提交
4315 4316 4317 4318 4319
        default:
            goto die;
        }
        break;
    default:
T
ths 已提交
4320
        goto die;
T
ths 已提交
4321 4322 4323 4324 4325 4326 4327 4328 4329 4330 4331 4332 4333 4334 4335 4336 4337 4338 4339
    }
#if defined MIPS_DEBUG_DISAS
    if (loglevel & CPU_LOG_TB_IN_ASM) {
        fprintf(logfile, "dmfc0 %s (reg %d sel %d)\n",
                rn, reg, sel);
    }
#endif
    return;

die:
#if defined MIPS_DEBUG_DISAS
    if (loglevel & CPU_LOG_TB_IN_ASM) {
        fprintf(logfile, "dmfc0 %s (reg %d sel %d)\n",
                rn, reg, sel);
    }
#endif
    generate_exception(ctx, EXCP_RI);
}

4340
static void gen_dmtc0 (CPUState *env, DisasContext *ctx, int reg, int sel)
T
ths 已提交
4341 4342 4343
{
    const char *rn = "invalid";

4344 4345 4346
    if (sel != 0)
        check_insn(env, ctx, ISA_MIPS64);

T
ths 已提交
4347 4348 4349 4350
    switch (reg) {
    case 0:
        switch (sel) {
        case 0:
4351
            tcg_gen_helper_0_0(do_mtc0_index);
T
ths 已提交
4352 4353 4354
            rn = "Index";
            break;
        case 1:
4355
            check_insn(env, ctx, ASE_MT);
4356
            tcg_gen_helper_0_0(do_mtc0_mvpcontrol);
T
ths 已提交
4357
            rn = "MVPControl";
4358
            break;
T
ths 已提交
4359
        case 2:
4360
            check_insn(env, ctx, ASE_MT);
4361
            /* ignored */
T
ths 已提交
4362
            rn = "MVPConf0";
4363
            break;
T
ths 已提交
4364
        case 3:
4365
            check_insn(env, ctx, ASE_MT);
4366
            /* ignored */
T
ths 已提交
4367
            rn = "MVPConf1";
4368
            break;
T
ths 已提交
4369 4370 4371 4372 4373 4374 4375
        default:
            goto die;
        }
        break;
    case 1:
        switch (sel) {
        case 0:
T
ths 已提交
4376
            /* ignored */
T
ths 已提交
4377
            rn = "Random";
T
ths 已提交
4378
            break;
T
ths 已提交
4379
        case 1:
4380
            check_insn(env, ctx, ASE_MT);
4381
            tcg_gen_helper_0_0(do_mtc0_vpecontrol);
T
ths 已提交
4382
            rn = "VPEControl";
4383
            break;
T
ths 已提交
4384
        case 2:
4385
            check_insn(env, ctx, ASE_MT);
4386
            tcg_gen_helper_0_0(do_mtc0_vpeconf0);
T
ths 已提交
4387
            rn = "VPEConf0";
4388
            break;
T
ths 已提交
4389
        case 3:
4390
            check_insn(env, ctx, ASE_MT);
4391
            tcg_gen_helper_0_0(do_mtc0_vpeconf1);
T
ths 已提交
4392
            rn = "VPEConf1";
4393
            break;
T
ths 已提交
4394
        case 4:
4395
            check_insn(env, ctx, ASE_MT);
4396
            tcg_gen_helper_0_0(do_mtc0_yqmask);
T
ths 已提交
4397
            rn = "YQMask";
4398
            break;
T
ths 已提交
4399
        case 5:
4400
            check_insn(env, ctx, ASE_MT);
4401
            tcg_gen_st_tl(cpu_T[0], cpu_env, offsetof(CPUState, CP0_VPESchedule));
T
ths 已提交
4402
            rn = "VPESchedule";
4403
            break;
T
ths 已提交
4404
        case 6:
4405
            check_insn(env, ctx, ASE_MT);
4406
            tcg_gen_st_tl(cpu_T[0], cpu_env, offsetof(CPUState, CP0_VPEScheFBack));
T
ths 已提交
4407
            rn = "VPEScheFBack";
4408
            break;
T
ths 已提交
4409
        case 7:
4410
            check_insn(env, ctx, ASE_MT);
4411
            tcg_gen_helper_0_0(do_mtc0_vpeopt);
T
ths 已提交
4412
            rn = "VPEOpt";
4413
            break;
T
ths 已提交
4414 4415 4416 4417 4418 4419 4420
        default:
            goto die;
        }
        break;
    case 2:
        switch (sel) {
        case 0:
4421
            tcg_gen_helper_0_0(do_mtc0_entrylo0);
T
ths 已提交
4422 4423
            rn = "EntryLo0";
            break;
T
ths 已提交
4424
        case 1:
4425
            check_insn(env, ctx, ASE_MT);
4426
            tcg_gen_helper_0_0(do_mtc0_tcstatus);
T
ths 已提交
4427
            rn = "TCStatus";
4428
            break;
T
ths 已提交
4429
        case 2:
4430
            check_insn(env, ctx, ASE_MT);
4431
            tcg_gen_helper_0_0(do_mtc0_tcbind);
T
ths 已提交
4432
            rn = "TCBind";
4433
            break;
T
ths 已提交
4434
        case 3:
4435
            check_insn(env, ctx, ASE_MT);
4436
            tcg_gen_helper_0_0(do_mtc0_tcrestart);
T
ths 已提交
4437
            rn = "TCRestart";
4438
            break;
T
ths 已提交
4439
        case 4:
4440
            check_insn(env, ctx, ASE_MT);
4441
            tcg_gen_helper_0_0(do_mtc0_tchalt);
T
ths 已提交
4442
            rn = "TCHalt";
4443
            break;
T
ths 已提交
4444
        case 5:
4445
            check_insn(env, ctx, ASE_MT);
4446
            tcg_gen_helper_0_0(do_mtc0_tccontext);
T
ths 已提交
4447
            rn = "TCContext";
4448
            break;
T
ths 已提交
4449
        case 6:
4450
            check_insn(env, ctx, ASE_MT);
4451
            tcg_gen_helper_0_0(do_mtc0_tcschedule);
T
ths 已提交
4452
            rn = "TCSchedule";
4453
            break;
T
ths 已提交
4454
        case 7:
4455
            check_insn(env, ctx, ASE_MT);
4456
            tcg_gen_helper_0_0(do_mtc0_tcschefback);
T
ths 已提交
4457
            rn = "TCScheFBack";
4458
            break;
T
ths 已提交
4459 4460 4461 4462 4463 4464 4465
        default:
            goto die;
        }
        break;
    case 3:
        switch (sel) {
        case 0:
4466
            tcg_gen_helper_0_0(do_mtc0_entrylo1);
T
ths 已提交
4467 4468
            rn = "EntryLo1";
            break;
T
ths 已提交
4469 4470
        default:
            goto die;
T
ths 已提交
4471
        }
T
ths 已提交
4472 4473 4474 4475
        break;
    case 4:
        switch (sel) {
        case 0:
4476
            tcg_gen_helper_0_0(do_mtc0_context);
T
ths 已提交
4477 4478
            rn = "Context";
            break;
T
ths 已提交
4479
        case 1:
4480
//           tcg_gen_helper_0_0(do_mtc0_contextconfig); /* SmartMIPS ASE */
T
ths 已提交
4481 4482
            rn = "ContextConfig";
//           break;
T
ths 已提交
4483 4484
        default:
            goto die;
T
ths 已提交
4485
        }
T
ths 已提交
4486 4487 4488 4489
        break;
    case 5:
        switch (sel) {
        case 0:
4490
            tcg_gen_helper_0_0(do_mtc0_pagemask);
T
ths 已提交
4491 4492
            rn = "PageMask";
            break;
T
ths 已提交
4493
        case 1:
4494
            check_insn(env, ctx, ISA_MIPS32R2);
4495
            tcg_gen_helper_0_0(do_mtc0_pagegrain);
T
ths 已提交
4496 4497
            rn = "PageGrain";
            break;
T
ths 已提交
4498 4499
        default:
            goto die;
T
ths 已提交
4500
        }
T
ths 已提交
4501 4502 4503 4504
        break;
    case 6:
        switch (sel) {
        case 0:
4505
            tcg_gen_helper_0_0(do_mtc0_wired);
T
ths 已提交
4506 4507
            rn = "Wired";
            break;
T
ths 已提交
4508
        case 1:
4509
            check_insn(env, ctx, ISA_MIPS32R2);
4510
            tcg_gen_helper_0_0(do_mtc0_srsconf0);
T
ths 已提交
4511
            rn = "SRSConf0";
4512
            break;
T
ths 已提交
4513
        case 2:
4514
            check_insn(env, ctx, ISA_MIPS32R2);
4515
            tcg_gen_helper_0_0(do_mtc0_srsconf1);
T
ths 已提交
4516
            rn = "SRSConf1";
4517
            break;
T
ths 已提交
4518
        case 3:
4519
            check_insn(env, ctx, ISA_MIPS32R2);
4520
            tcg_gen_helper_0_0(do_mtc0_srsconf2);
T
ths 已提交
4521
            rn = "SRSConf2";
4522
            break;
T
ths 已提交
4523
        case 4:
4524
            check_insn(env, ctx, ISA_MIPS32R2);
4525
            tcg_gen_helper_0_0(do_mtc0_srsconf3);
T
ths 已提交
4526
            rn = "SRSConf3";
4527
            break;
T
ths 已提交
4528
        case 5:
4529
            check_insn(env, ctx, ISA_MIPS32R2);
4530
            tcg_gen_helper_0_0(do_mtc0_srsconf4);
T
ths 已提交
4531
            rn = "SRSConf4";
4532
            break;
T
ths 已提交
4533 4534
        default:
            goto die;
T
ths 已提交
4535
        }
T
ths 已提交
4536 4537 4538 4539
        break;
    case 7:
        switch (sel) {
        case 0:
4540
            check_insn(env, ctx, ISA_MIPS32R2);
4541
            tcg_gen_helper_0_0(do_mtc0_hwrena);
T
ths 已提交
4542 4543
            rn = "HWREna";
            break;
T
ths 已提交
4544 4545
        default:
            goto die;
T
ths 已提交
4546
        }
T
ths 已提交
4547 4548 4549
        break;
    case 8:
        /* ignored */
T
ths 已提交
4550
        rn = "BadVAddr";
T
ths 已提交
4551 4552 4553 4554
        break;
    case 9:
        switch (sel) {
        case 0:
4555
            tcg_gen_helper_0_0(do_mtc0_count);
T
ths 已提交
4556 4557
            rn = "Count";
            break;
T
ths 已提交
4558
        /* 6,7 are implementation dependent */
T
ths 已提交
4559 4560
        default:
            goto die;
T
ths 已提交
4561 4562 4563
        }
        /* Stop translation as we may have switched the execution mode */
        ctx->bstate = BS_STOP;
T
ths 已提交
4564 4565 4566 4567
        break;
    case 10:
        switch (sel) {
        case 0:
4568
            tcg_gen_helper_0_0(do_mtc0_entryhi);
T
ths 已提交
4569 4570
            rn = "EntryHi";
            break;
T
ths 已提交
4571 4572
        default:
            goto die;
T
ths 已提交
4573
        }
T
ths 已提交
4574 4575 4576 4577
        break;
    case 11:
        switch (sel) {
        case 0:
4578
            tcg_gen_helper_0_0(do_mtc0_compare);
T
ths 已提交
4579 4580
            rn = "Compare";
            break;
T
ths 已提交
4581
        /* 6,7 are implementation dependent */
T
ths 已提交
4582 4583
        default:
            goto die;
T
ths 已提交
4584
        }
A
aurel32 已提交
4585 4586
        /* Stop translation as we may have switched the execution mode */
        ctx->bstate = BS_STOP;
T
ths 已提交
4587 4588 4589 4590
        break;
    case 12:
        switch (sel) {
        case 0:
4591
            tcg_gen_helper_0_0(do_mtc0_status);
4592 4593 4594
            /* BS_STOP isn't good enough here, hflags may have changed. */
            gen_save_pc(ctx->pc + 4);
            ctx->bstate = BS_EXCP;
T
ths 已提交
4595 4596
            rn = "Status";
            break;
T
ths 已提交
4597
        case 1:
4598
            check_insn(env, ctx, ISA_MIPS32R2);
4599
            tcg_gen_helper_0_0(do_mtc0_intctl);
4600 4601
            /* Stop translation as we may have switched the execution mode */
            ctx->bstate = BS_STOP;
T
ths 已提交
4602 4603
            rn = "IntCtl";
            break;
T
ths 已提交
4604
        case 2:
4605
            check_insn(env, ctx, ISA_MIPS32R2);
4606
            tcg_gen_helper_0_0(do_mtc0_srsctl);
4607 4608
            /* Stop translation as we may have switched the execution mode */
            ctx->bstate = BS_STOP;
T
ths 已提交
4609 4610
            rn = "SRSCtl";
            break;
T
ths 已提交
4611
        case 3:
4612
            check_insn(env, ctx, ISA_MIPS32R2);
4613
            gen_mtc0_store32(cpu_T[0], offsetof(CPUState, CP0_SRSMap));
4614 4615
            /* Stop translation as we may have switched the execution mode */
            ctx->bstate = BS_STOP;
T
ths 已提交
4616 4617 4618
            rn = "SRSMap";
            break;
        default:
T
ths 已提交
4619
            goto die;
T
ths 已提交
4620
        }
T
ths 已提交
4621 4622 4623 4624
        break;
    case 13:
        switch (sel) {
        case 0:
4625
            tcg_gen_helper_0_0(do_mtc0_cause);
T
ths 已提交
4626 4627
            rn = "Cause";
            break;
T
ths 已提交
4628 4629
        default:
            goto die;
T
ths 已提交
4630 4631 4632
        }
        /* Stop translation as we may have switched the execution mode */
        ctx->bstate = BS_STOP;
T
ths 已提交
4633 4634 4635 4636
        break;
    case 14:
        switch (sel) {
        case 0:
4637
            tcg_gen_st_tl(cpu_T[0], cpu_env, offsetof(CPUState, CP0_EPC));
T
ths 已提交
4638 4639
            rn = "EPC";
            break;
T
ths 已提交
4640 4641
        default:
            goto die;
T
ths 已提交
4642
        }
T
ths 已提交
4643 4644 4645 4646
        break;
    case 15:
        switch (sel) {
        case 0:
T
ths 已提交
4647 4648 4649
            /* ignored */
            rn = "PRid";
            break;
T
ths 已提交
4650
        case 1:
4651
            check_insn(env, ctx, ISA_MIPS32R2);
4652
            tcg_gen_helper_0_0(do_mtc0_ebase);
T
ths 已提交
4653 4654
            rn = "EBase";
            break;
T
ths 已提交
4655 4656
        default:
            goto die;
T
ths 已提交
4657
        }
T
ths 已提交
4658 4659 4660 4661
        break;
    case 16:
        switch (sel) {
        case 0:
4662
            tcg_gen_helper_0_0(do_mtc0_config0);
T
ths 已提交
4663
            rn = "Config";
T
ths 已提交
4664 4665
            /* Stop translation as we may have switched the execution mode */
            ctx->bstate = BS_STOP;
T
ths 已提交
4666 4667
            break;
        case 1:
T
ths 已提交
4668
            /* ignored */
T
ths 已提交
4669 4670 4671
            rn = "Config1";
            break;
        case 2:
4672
            tcg_gen_helper_0_0(do_mtc0_config2);
T
ths 已提交
4673
            rn = "Config2";
T
ths 已提交
4674 4675
            /* Stop translation as we may have switched the execution mode */
            ctx->bstate = BS_STOP;
T
ths 已提交
4676 4677
            break;
        case 3:
T
ths 已提交
4678
            /* ignored */
T
ths 已提交
4679 4680 4681 4682 4683 4684 4685 4686 4687 4688 4689
            rn = "Config3";
            break;
        /* 6,7 are implementation dependent */
        default:
            rn = "Invalid config selector";
            goto die;
        }
        break;
    case 17:
        switch (sel) {
        case 0:
T
ths 已提交
4690 4691 4692
            /* ignored */
            rn = "LLAddr";
            break;
T
ths 已提交
4693 4694 4695 4696 4697 4698
        default:
            goto die;
        }
        break;
    case 18:
        switch (sel) {
4699
        case 0 ... 7:
4700
            tcg_gen_helper_0_1i(do_mtc0_watchlo, sel);
T
ths 已提交
4701 4702
            rn = "WatchLo";
            break;
T
ths 已提交
4703 4704 4705 4706 4707 4708
        default:
            goto die;
        }
        break;
    case 19:
        switch (sel) {
4709
        case 0 ... 7:
4710
            tcg_gen_helper_0_1i(do_mtc0_watchhi, sel);
T
ths 已提交
4711 4712
            rn = "WatchHi";
            break;
T
ths 已提交
4713 4714 4715 4716 4717 4718 4719
        default:
            goto die;
        }
        break;
    case 20:
        switch (sel) {
        case 0:
4720
            check_insn(env, ctx, ISA_MIPS3);
4721
            tcg_gen_helper_0_0(do_mtc0_xcontext);
T
ths 已提交
4722 4723
            rn = "XContext";
            break;
T
ths 已提交
4724 4725 4726 4727 4728 4729 4730 4731
        default:
            goto die;
        }
        break;
    case 21:
       /* Officially reserved, but sel 0 is used for R1x000 framemask */
        switch (sel) {
        case 0:
4732
            tcg_gen_helper_0_0(do_mtc0_framemask);
T
ths 已提交
4733 4734
            rn = "Framemask";
            break;
T
ths 已提交
4735 4736 4737 4738 4739 4740 4741
        default:
            goto die;
        }
        break;
    case 22:
        /* ignored */
        rn = "Diagnostic"; /* implementation dependent */
T
ths 已提交
4742
        break;
T
ths 已提交
4743 4744 4745
    case 23:
        switch (sel) {
        case 0:
4746
            tcg_gen_helper_0_0(do_mtc0_debug); /* EJTAG support */
4747 4748 4749
            /* BS_STOP isn't good enough here, hflags may have changed. */
            gen_save_pc(ctx->pc + 4);
            ctx->bstate = BS_EXCP;
T
ths 已提交
4750 4751
            rn = "Debug";
            break;
T
ths 已提交
4752
        case 1:
4753
//            tcg_gen_helper_0_0(do_mtc0_tracecontrol); /* PDtrace support */
4754 4755
            /* Stop translation as we may have switched the execution mode */
            ctx->bstate = BS_STOP;
T
ths 已提交
4756 4757
            rn = "TraceControl";
//            break;
T
ths 已提交
4758
        case 2:
4759
//            tcg_gen_helper_0_0(do_mtc0_tracecontrol2); /* PDtrace support */
4760 4761
            /* Stop translation as we may have switched the execution mode */
            ctx->bstate = BS_STOP;
T
ths 已提交
4762 4763
            rn = "TraceControl2";
//            break;
T
ths 已提交
4764
        case 3:
4765
//            tcg_gen_helper_0_0(do_mtc0_usertracedata); /* PDtrace support */
4766 4767
            /* Stop translation as we may have switched the execution mode */
            ctx->bstate = BS_STOP;
T
ths 已提交
4768 4769
            rn = "UserTraceData";
//            break;
T
ths 已提交
4770
        case 4:
4771
//            tcg_gen_helper_0_0(do_mtc0_debug); /* PDtrace support */
4772 4773
            /* Stop translation as we may have switched the execution mode */
            ctx->bstate = BS_STOP;
T
ths 已提交
4774 4775
            rn = "TraceBPC";
//            break;
T
ths 已提交
4776 4777 4778 4779 4780 4781 4782
        default:
            goto die;
        }
        break;
    case 24:
        switch (sel) {
        case 0:
4783 4784
            /* EJTAG support */
            tcg_gen_st_tl(cpu_T[0], cpu_env, offsetof(CPUState, CP0_DEPC));
T
ths 已提交
4785 4786
            rn = "DEPC";
            break;
T
ths 已提交
4787 4788 4789 4790 4791 4792 4793
        default:
            goto die;
        }
        break;
    case 25:
        switch (sel) {
        case 0:
4794
            tcg_gen_helper_0_0(do_mtc0_performance0);
T
ths 已提交
4795 4796
            rn = "Performance0";
            break;
T
ths 已提交
4797
        case 1:
4798
//            tcg_gen_helper_0_0(do_mtc0_performance1);
T
ths 已提交
4799 4800
            rn = "Performance1";
//            break;
T
ths 已提交
4801
        case 2:
4802
//            tcg_gen_helper_0_0(do_mtc0_performance2);
T
ths 已提交
4803 4804
            rn = "Performance2";
//            break;
T
ths 已提交
4805
        case 3:
4806
//            tcg_gen_helper_0_0(do_mtc0_performance3);
T
ths 已提交
4807 4808
            rn = "Performance3";
//            break;
T
ths 已提交
4809
        case 4:
4810
//            tcg_gen_helper_0_0(do_mtc0_performance4);
T
ths 已提交
4811 4812
            rn = "Performance4";
//            break;
T
ths 已提交
4813
        case 5:
4814
//            tcg_gen_helper_0_0(do_mtc0_performance5);
T
ths 已提交
4815 4816
            rn = "Performance5";
//            break;
T
ths 已提交
4817
        case 6:
4818
//            tcg_gen_helper_0_0(do_mtc0_performance6);
T
ths 已提交
4819 4820
            rn = "Performance6";
//            break;
T
ths 已提交
4821
        case 7:
4822
//            tcg_gen_helper_0_0(do_mtc0_performance7);
T
ths 已提交
4823 4824
            rn = "Performance7";
//            break;
T
ths 已提交
4825 4826 4827
        default:
            goto die;
        }
T
ths 已提交
4828
        break;
T
ths 已提交
4829
    case 26:
T
ths 已提交
4830
        /* ignored */
T
ths 已提交
4831
        rn = "ECC";
T
ths 已提交
4832
        break;
T
ths 已提交
4833 4834 4835
    case 27:
        switch (sel) {
        case 0 ... 3:
T
ths 已提交
4836 4837 4838
            /* ignored */
            rn = "CacheErr";
            break;
T
ths 已提交
4839 4840 4841
        default:
            goto die;
        }
T
ths 已提交
4842
        break;
T
ths 已提交
4843 4844 4845 4846 4847 4848
    case 28:
        switch (sel) {
        case 0:
        case 2:
        case 4:
        case 6:
4849
            tcg_gen_helper_0_0(do_mtc0_taglo);
T
ths 已提交
4850 4851 4852 4853 4854 4855
            rn = "TagLo";
            break;
        case 1:
        case 3:
        case 5:
        case 7:
4856
            tcg_gen_helper_0_0(do_mtc0_datalo);
T
ths 已提交
4857 4858 4859 4860 4861 4862 4863 4864 4865 4866 4867 4868
            rn = "DataLo";
            break;
        default:
            goto die;
        }
        break;
    case 29:
        switch (sel) {
        case 0:
        case 2:
        case 4:
        case 6:
4869
            tcg_gen_helper_0_0(do_mtc0_taghi);
T
ths 已提交
4870 4871 4872 4873 4874 4875
            rn = "TagHi";
            break;
        case 1:
        case 3:
        case 5:
        case 7:
4876
            tcg_gen_helper_0_0(do_mtc0_datahi);
T
ths 已提交
4877 4878 4879 4880 4881 4882
            rn = "DataHi";
            break;
        default:
            rn = "invalid sel";
            goto die;
        }
T
ths 已提交
4883
        break;
T
ths 已提交
4884 4885 4886
    case 30:
        switch (sel) {
        case 0:
4887
            tcg_gen_st_tl(cpu_T[0], cpu_env, offsetof(CPUState, CP0_ErrorEPC));
T
ths 已提交
4888 4889
            rn = "ErrorEPC";
            break;
T
ths 已提交
4890 4891 4892 4893 4894 4895 4896
        default:
            goto die;
        }
        break;
    case 31:
        switch (sel) {
        case 0:
4897 4898
            /* EJTAG support */
            gen_mtc0_store32(cpu_T[0], offsetof(CPUState, CP0_DESAVE));
T
ths 已提交
4899 4900
            rn = "DESAVE";
            break;
T
ths 已提交
4901 4902 4903
        default:
            goto die;
        }
T
ths 已提交
4904 4905
        /* Stop translation as we may have switched the execution mode */
        ctx->bstate = BS_STOP;
T
ths 已提交
4906 4907
        break;
    default:
T
ths 已提交
4908
        goto die;
T
ths 已提交
4909 4910 4911 4912 4913 4914 4915 4916 4917 4918 4919 4920 4921 4922 4923 4924 4925 4926
    }
#if defined MIPS_DEBUG_DISAS
    if (loglevel & CPU_LOG_TB_IN_ASM) {
        fprintf(logfile, "dmtc0 %s (reg %d sel %d)\n",
                rn, reg, sel);
    }
#endif
    return;

die:
#if defined MIPS_DEBUG_DISAS
    if (loglevel & CPU_LOG_TB_IN_ASM) {
        fprintf(logfile, "dmtc0 %s (reg %d sel %d)\n",
                rn, reg, sel);
    }
#endif
    generate_exception(ctx, EXCP_RI);
}
4927
#endif /* TARGET_MIPS64 */
T
ths 已提交
4928

4929 4930 4931 4932 4933 4934 4935 4936
static void gen_mftr(CPUState *env, DisasContext *ctx, int rt,
                     int u, int sel, int h)
{
    int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);

    if ((env->CP0_VPEConf0 & (1 << CP0VPEC0_MVP)) == 0 &&
        ((env->CP0_TCBind[other_tc] & (0xf << CP0TCBd_CurVPE)) !=
         (env->CP0_TCBind[env->current_tc] & (0xf << CP0TCBd_CurVPE))))
4937
        tcg_gen_movi_tl(cpu_T[0], -1);
4938 4939
    else if ((env->CP0_VPEControl & (0xff << CP0VPECo_TargTC)) >
             (env->mvp->CP0_MVPConf0 & (0xff << CP0MVPC0_PTC)))
4940
        tcg_gen_movi_tl(cpu_T[0], -1);
4941 4942 4943 4944 4945
    else if (u == 0) {
        switch (rt) {
        case 2:
            switch (sel) {
            case 1:
4946
                tcg_gen_helper_0_0(do_mftc0_tcstatus);
4947 4948
                break;
            case 2:
4949
                tcg_gen_helper_0_0(do_mftc0_tcbind);
4950 4951
                break;
            case 3:
4952
                tcg_gen_helper_0_0(do_mftc0_tcrestart);
4953 4954
                break;
            case 4:
4955
                tcg_gen_helper_0_0(do_mftc0_tchalt);
4956 4957
                break;
            case 5:
4958
                tcg_gen_helper_0_0(do_mftc0_tccontext);
4959 4960
                break;
            case 6:
4961
                tcg_gen_helper_0_0(do_mftc0_tcschedule);
4962 4963
                break;
            case 7:
4964
                tcg_gen_helper_0_0(do_mftc0_tcschefback);
4965 4966 4967 4968 4969 4970 4971 4972 4973
                break;
            default:
                gen_mfc0(env, ctx, rt, sel);
                break;
            }
            break;
        case 10:
            switch (sel) {
            case 0:
4974
                tcg_gen_helper_0_0(do_mftc0_entryhi);
4975 4976 4977 4978 4979 4980 4981 4982
                break;
            default:
                gen_mfc0(env, ctx, rt, sel);
                break;
            }
        case 12:
            switch (sel) {
            case 0:
4983
                tcg_gen_helper_0_0(do_mftc0_status);
4984 4985 4986 4987 4988 4989 4990 4991
                break;
            default:
                gen_mfc0(env, ctx, rt, sel);
                break;
            }
        case 23:
            switch (sel) {
            case 0:
4992
                tcg_gen_helper_0_0(do_mftc0_debug);
4993 4994 4995 4996 4997 4998 4999 5000 5001 5002 5003 5004
                break;
            default:
                gen_mfc0(env, ctx, rt, sel);
                break;
            }
            break;
        default:
            gen_mfc0(env, ctx, rt, sel);
        }
    } else switch (sel) {
    /* GPR registers. */
    case 0:
5005
        tcg_gen_helper_0_1i(do_mftgpr, rt);
5006 5007 5008 5009 5010
        break;
    /* Auxiliary CPU registers */
    case 1:
        switch (rt) {
        case 0:
5011
            tcg_gen_helper_0_1i(do_mftlo, 0);
5012 5013
            break;
        case 1:
5014
            tcg_gen_helper_0_1i(do_mfthi, 0);
5015 5016
            break;
        case 2:
5017
            tcg_gen_helper_0_1i(do_mftacx, 0);
5018 5019
            break;
        case 4:
5020
            tcg_gen_helper_0_1i(do_mftlo, 1);
5021 5022
            break;
        case 5:
5023
            tcg_gen_helper_0_1i(do_mfthi, 1);
5024 5025
            break;
        case 6:
5026
            tcg_gen_helper_0_1i(do_mftacx, 1);
5027 5028
            break;
        case 8:
5029
            tcg_gen_helper_0_1i(do_mftlo, 2);
5030 5031
            break;
        case 9:
5032
            tcg_gen_helper_0_1i(do_mfthi, 2);
5033 5034
            break;
        case 10:
5035
            tcg_gen_helper_0_1i(do_mftacx, 2);
5036 5037
            break;
        case 12:
5038
            tcg_gen_helper_0_1i(do_mftlo, 3);
5039 5040
            break;
        case 13:
5041
            tcg_gen_helper_0_1i(do_mfthi, 3);
5042 5043
            break;
        case 14:
5044
            tcg_gen_helper_0_1i(do_mftacx, 3);
5045 5046
            break;
        case 16:
5047
            tcg_gen_helper_0_0(do_mftdsp);
5048 5049 5050 5051 5052 5053 5054 5055 5056
            break;
        default:
            goto die;
        }
        break;
    /* Floating point (COP1). */
    case 2:
        /* XXX: For now we support only a single FPU context. */
        if (h == 0) {
T
ths 已提交
5057 5058
            gen_load_fpr32(fpu32_T[0], rt);
            tcg_gen_ext_i32_tl(cpu_T[0], fpu32_T[0]);
5059
        } else {
T
ths 已提交
5060 5061
            gen_load_fpr32h(fpu32h_T[0], rt);
            tcg_gen_ext_i32_tl(cpu_T[0], fpu32h_T[0]);
5062 5063 5064 5065
        }
        break;
    case 3:
        /* XXX: For now we support only a single FPU context. */
5066
        tcg_gen_helper_0_1i(do_cfc1, rt);
5067 5068 5069 5070 5071 5072 5073 5074 5075 5076 5077 5078 5079 5080 5081 5082 5083 5084 5085 5086 5087 5088 5089 5090 5091 5092 5093 5094 5095 5096 5097 5098 5099 5100 5101 5102 5103 5104 5105 5106 5107 5108 5109
        break;
    /* COP2: Not implemented. */
    case 4:
    case 5:
        /* fall through */
    default:
        goto die;
    }
#if defined MIPS_DEBUG_DISAS
    if (loglevel & CPU_LOG_TB_IN_ASM) {
        fprintf(logfile, "mftr (reg %d u %d sel %d h %d)\n",
                rt, u, sel, h);
    }
#endif
    return;

die:
#if defined MIPS_DEBUG_DISAS
    if (loglevel & CPU_LOG_TB_IN_ASM) {
        fprintf(logfile, "mftr (reg %d u %d sel %d h %d)\n",
                rt, u, sel, h);
    }
#endif
    generate_exception(ctx, EXCP_RI);
}

static void gen_mttr(CPUState *env, DisasContext *ctx, int rd,
                     int u, int sel, int h)
{
    int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);

    if ((env->CP0_VPEConf0 & (1 << CP0VPEC0_MVP)) == 0 &&
        ((env->CP0_TCBind[other_tc] & (0xf << CP0TCBd_CurVPE)) !=
         (env->CP0_TCBind[env->current_tc] & (0xf << CP0TCBd_CurVPE))))
        /* 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:
5110
                tcg_gen_helper_0_0(do_mttc0_tcstatus);
5111 5112
                break;
            case 2:
5113
                tcg_gen_helper_0_0(do_mttc0_tcbind);
5114 5115
                break;
            case 3:
5116
                tcg_gen_helper_0_0(do_mttc0_tcrestart);
5117 5118
                break;
            case 4:
5119
                tcg_gen_helper_0_0(do_mttc0_tchalt);
5120 5121
                break;
            case 5:
5122
                tcg_gen_helper_0_0(do_mttc0_tccontext);
5123 5124
                break;
            case 6:
5125
                tcg_gen_helper_0_0(do_mttc0_tcschedule);
5126 5127
                break;
            case 7:
5128
                tcg_gen_helper_0_0(do_mttc0_tcschefback);
5129 5130 5131 5132 5133 5134 5135 5136 5137
                break;
            default:
                gen_mtc0(env, ctx, rd, sel);
                break;
            }
            break;
        case 10:
            switch (sel) {
            case 0:
5138
                tcg_gen_helper_0_0(do_mttc0_entryhi);
5139 5140 5141 5142 5143 5144 5145 5146
                break;
            default:
                gen_mtc0(env, ctx, rd, sel);
                break;
            }
        case 12:
            switch (sel) {
            case 0:
5147
                tcg_gen_helper_0_0(do_mttc0_status);
5148 5149 5150 5151 5152 5153 5154 5155
                break;
            default:
                gen_mtc0(env, ctx, rd, sel);
                break;
            }
        case 23:
            switch (sel) {
            case 0:
5156
                tcg_gen_helper_0_0(do_mttc0_debug);
5157 5158 5159 5160 5161 5162 5163 5164 5165 5166 5167 5168
                break;
            default:
                gen_mtc0(env, ctx, rd, sel);
                break;
            }
            break;
        default:
            gen_mtc0(env, ctx, rd, sel);
        }
    } else switch (sel) {
    /* GPR registers. */
    case 0:
5169
        tcg_gen_helper_0_1i(do_mttgpr, rd);
5170 5171 5172 5173 5174
        break;
    /* Auxiliary CPU registers */
    case 1:
        switch (rd) {
        case 0:
5175
            tcg_gen_helper_0_1i(do_mttlo, 0);
5176 5177
            break;
        case 1:
5178
            tcg_gen_helper_0_1i(do_mtthi, 0);
5179 5180
            break;
        case 2:
5181
            tcg_gen_helper_0_1i(do_mttacx, 0);
5182 5183
            break;
        case 4:
5184
            tcg_gen_helper_0_1i(do_mttlo, 1);
5185 5186
            break;
        case 5:
5187
            tcg_gen_helper_0_1i(do_mtthi, 1);
5188 5189
            break;
        case 6:
5190
            tcg_gen_helper_0_1i(do_mttacx, 1);
5191 5192
            break;
        case 8:
5193
            tcg_gen_helper_0_1i(do_mttlo, 2);
5194 5195
            break;
        case 9:
5196
            tcg_gen_helper_0_1i(do_mtthi, 2);
5197 5198
            break;
        case 10:
5199
            tcg_gen_helper_0_1i(do_mttacx, 2);
5200 5201
            break;
        case 12:
5202
            tcg_gen_helper_0_1i(do_mttlo, 3);
5203 5204
            break;
        case 13:
5205
            tcg_gen_helper_0_1i(do_mtthi, 3);
5206 5207
            break;
        case 14:
5208
            tcg_gen_helper_0_1i(do_mttacx, 3);
5209 5210
            break;
        case 16:
5211
            tcg_gen_helper_0_0(do_mttdsp);
5212 5213 5214 5215 5216 5217 5218 5219 5220
            break;
        default:
            goto die;
        }
        break;
    /* Floating point (COP1). */
    case 2:
        /* XXX: For now we support only a single FPU context. */
        if (h == 0) {
T
ths 已提交
5221 5222
            tcg_gen_trunc_tl_i32(fpu32_T[0], cpu_T[0]);
            gen_store_fpr32(fpu32_T[0], rd);
5223
        } else {
T
ths 已提交
5224 5225
            tcg_gen_trunc_tl_i32(fpu32h_T[0], cpu_T[0]);
            gen_store_fpr32h(fpu32h_T[0], rd);
5226 5227 5228 5229
        }
        break;
    case 3:
        /* XXX: For now we support only a single FPU context. */
5230
        tcg_gen_helper_0_1i(do_ctc1, rd);
5231 5232 5233 5234 5235 5236 5237 5238 5239 5240 5241 5242 5243 5244 5245 5246 5247 5248 5249 5250 5251 5252 5253 5254 5255 5256
        break;
    /* COP2: Not implemented. */
    case 4:
    case 5:
        /* fall through */
    default:
        goto die;
    }
#if defined MIPS_DEBUG_DISAS
    if (loglevel & CPU_LOG_TB_IN_ASM) {
        fprintf(logfile, "mttr (reg %d u %d sel %d h %d)\n",
                rd, u, sel, h);
    }
#endif
    return;

die:
#if defined MIPS_DEBUG_DISAS
    if (loglevel & CPU_LOG_TB_IN_ASM) {
        fprintf(logfile, "mttr (reg %d u %d sel %d h %d)\n",
                rd, u, sel, h);
    }
#endif
    generate_exception(ctx, EXCP_RI);
}

5257
static void gen_cp0 (CPUState *env, DisasContext *ctx, uint32_t opc, int rt, int rd)
B
bellard 已提交
5258
{
T
ths 已提交
5259
    const char *opn = "ldst";
B
bellard 已提交
5260 5261 5262 5263

    switch (opc) {
    case OPC_MFC0:
        if (rt == 0) {
5264
            /* Treat as NOP. */
B
bellard 已提交
5265 5266
            return;
        }
5267
        gen_mfc0(env, ctx, rd, ctx->opcode & 0x7);
5268
        gen_store_gpr(cpu_T[0], rt);
B
bellard 已提交
5269 5270 5271
        opn = "mfc0";
        break;
    case OPC_MTC0:
5272
        gen_load_gpr(cpu_T[0], rt);
5273
        save_cpu_state(ctx, 1);
5274
        gen_mtc0(env, ctx, rd, ctx->opcode & 0x7);
B
bellard 已提交
5275 5276
        opn = "mtc0";
        break;
5277
#if defined(TARGET_MIPS64)
T
ths 已提交
5278
    case OPC_DMFC0:
5279
        check_insn(env, ctx, ISA_MIPS3);
T
ths 已提交
5280
        if (rt == 0) {
5281
            /* Treat as NOP. */
T
ths 已提交
5282 5283
            return;
        }
5284
        gen_dmfc0(env, ctx, rd, ctx->opcode & 0x7);
5285
        gen_store_gpr(cpu_T[0], rt);
T
ths 已提交
5286 5287 5288
        opn = "dmfc0";
        break;
    case OPC_DMTC0:
5289
        check_insn(env, ctx, ISA_MIPS3);
5290
        gen_load_gpr(cpu_T[0], rt);
5291
        save_cpu_state(ctx, 1);
5292
        gen_dmtc0(env, ctx, rd, ctx->opcode & 0x7);
T
ths 已提交
5293 5294
        opn = "dmtc0";
        break;
5295
#endif
5296
    case OPC_MFTR:
5297
        check_insn(env, ctx, ASE_MT);
5298 5299 5300 5301 5302 5303
        if (rd == 0) {
            /* Treat as NOP. */
            return;
        }
        gen_mftr(env, ctx, rt, (ctx->opcode >> 5) & 1,
                 ctx->opcode & 0x7, (ctx->opcode >> 4) & 1);
5304
        gen_store_gpr(cpu_T[0], rd);
5305 5306 5307
        opn = "mftr";
        break;
    case OPC_MTTR:
5308
        check_insn(env, ctx, ASE_MT);
5309
        gen_load_gpr(cpu_T[0], rt);
5310 5311 5312 5313
        gen_mttr(env, ctx, rd, (ctx->opcode >> 5) & 1,
                 ctx->opcode & 0x7, (ctx->opcode >> 4) & 1);
        opn = "mttr";
        break;
B
bellard 已提交
5314 5315
    case OPC_TLBWI:
        opn = "tlbwi";
5316
        if (!env->tlb->do_tlbwi)
5317 5318
            goto die;
        gen_op_tlbwi();
B
bellard 已提交
5319 5320 5321
        break;
    case OPC_TLBWR:
        opn = "tlbwr";
5322
        if (!env->tlb->do_tlbwr)
5323 5324
            goto die;
        gen_op_tlbwr();
B
bellard 已提交
5325 5326 5327
        break;
    case OPC_TLBP:
        opn = "tlbp";
5328
        if (!env->tlb->do_tlbp)
5329 5330
            goto die;
        gen_op_tlbp();
B
bellard 已提交
5331 5332 5333
        break;
    case OPC_TLBR:
        opn = "tlbr";
5334
        if (!env->tlb->do_tlbr)
5335 5336
            goto die;
        gen_op_tlbr();
B
bellard 已提交
5337 5338 5339
        break;
    case OPC_ERET:
        opn = "eret";
5340
        check_insn(env, ctx, ISA_MIPS2);
5341
        save_cpu_state(ctx, 1);
B
bellard 已提交
5342 5343 5344 5345 5346
        gen_op_eret();
        ctx->bstate = BS_EXCP;
        break;
    case OPC_DERET:
        opn = "deret";
5347
        check_insn(env, ctx, ISA_MIPS32);
B
bellard 已提交
5348
        if (!(ctx->hflags & MIPS_HFLAG_DM)) {
5349
            MIPS_INVAL(opn);
B
bellard 已提交
5350 5351
            generate_exception(ctx, EXCP_RI);
        } else {
5352
            save_cpu_state(ctx, 1);
B
bellard 已提交
5353 5354 5355 5356
            gen_op_deret();
            ctx->bstate = BS_EXCP;
        }
        break;
B
bellard 已提交
5357 5358
    case OPC_WAIT:
        opn = "wait";
5359
        check_insn(env, ctx, ISA_MIPS3 | ISA_MIPS32);
B
bellard 已提交
5360 5361 5362 5363 5364 5365 5366
        /* If we get an exception, we want to restart at next instruction */
        ctx->pc += 4;
        save_cpu_state(ctx, 1);
        ctx->pc -= 4;
        gen_op_wait();
        ctx->bstate = BS_EXCP;
        break;
B
bellard 已提交
5367
    default:
5368
 die:
5369
        MIPS_INVAL(opn);
B
bellard 已提交
5370 5371 5372 5373 5374
        generate_exception(ctx, EXCP_RI);
        return;
    }
    MIPS_DEBUG("%s %s %d", opn, regnames[rt], rd);
}
5375
#endif /* !CONFIG_USER_ONLY */
B
bellard 已提交
5376

B
bellard 已提交
5377
/* CP1 Branches (before delay slot) */
5378
static void gen_compute_branch1 (CPUState *env, DisasContext *ctx, uint32_t op,
5379
                                 int32_t cc, int32_t offset)
B
bellard 已提交
5380 5381
{
    target_ulong btarget;
5382
    const char *opn = "cp1 cond branch";
B
bellard 已提交
5383

5384 5385 5386
    if (cc != 0)
        check_insn(env, ctx, ISA_MIPS4 | ISA_MIPS32);

B
bellard 已提交
5387 5388
    btarget = ctx->pc + 4 + offset;

5389 5390
    switch (op) {
    case OPC_BC1F:
5391
        gen_op_bc1f(cc);
5392
        opn = "bc1f";
B
bellard 已提交
5393
        goto not_likely;
5394
    case OPC_BC1FL:
5395
        gen_op_bc1f(cc);
5396
        opn = "bc1fl";
B
bellard 已提交
5397
        goto likely;
5398
    case OPC_BC1T:
5399
        gen_op_bc1t(cc);
5400
        opn = "bc1t";
5401
        goto not_likely;
5402
    case OPC_BC1TL:
5403
        gen_op_bc1t(cc);
5404
        opn = "bc1tl";
B
bellard 已提交
5405 5406
    likely:
        ctx->hflags |= MIPS_HFLAG_BL;
5407
        tcg_gen_st_tl(cpu_T[0], cpu_env, offsetof(CPUState, bcond));
B
bellard 已提交
5408
        break;
5409
    case OPC_BC1FANY2:
5410 5411
        gen_op_bc1any2f(cc);
        opn = "bc1any2f";
5412 5413
        goto not_likely;
    case OPC_BC1TANY2:
5414 5415
        gen_op_bc1any2t(cc);
        opn = "bc1any2t";
5416 5417
        goto not_likely;
    case OPC_BC1FANY4:
5418 5419
        gen_op_bc1any4f(cc);
        opn = "bc1any4f";
5420 5421
        goto not_likely;
    case OPC_BC1TANY4:
5422 5423
        gen_op_bc1any4t(cc);
        opn = "bc1any4t";
5424 5425
    not_likely:
        ctx->hflags |= MIPS_HFLAG_BC;
5426
        tcg_gen_st_tl(cpu_T[0], cpu_env, offsetof(CPUState, bcond));
5427 5428
        break;
    default:
5429
        MIPS_INVAL(opn);
5430
        generate_exception (ctx, EXCP_RI);
B
bellard 已提交
5431 5432
        return;
    }
5433
    MIPS_DEBUG("%s: cond %02x target " TARGET_FMT_lx, opn,
B
bellard 已提交
5434 5435 5436 5437
               ctx->hflags, btarget);
    ctx->btarget = btarget;
}

B
bellard 已提交
5438
/* Coprocessor 1 (FPU) */
5439 5440 5441

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

5442
static void gen_cp1 (DisasContext *ctx, uint32_t opc, int rt, int fs)
B
bellard 已提交
5443
{
5444
    const char *opn = "cp1 move";
B
bellard 已提交
5445 5446 5447

    switch (opc) {
    case OPC_MFC1:
T
ths 已提交
5448 5449
        gen_load_fpr32(fpu32_T[0], fs);
        tcg_gen_ext_i32_tl(cpu_T[0], fpu32_T[0]);
5450
        gen_store_gpr(cpu_T[0], rt);
B
bellard 已提交
5451 5452 5453
        opn = "mfc1";
        break;
    case OPC_MTC1:
5454
        gen_load_gpr(cpu_T[0], rt);
T
ths 已提交
5455 5456
        tcg_gen_trunc_tl_i32(fpu32_T[0], cpu_T[0]);
        gen_store_fpr32(fpu32_T[0], fs);
B
bellard 已提交
5457 5458 5459
        opn = "mtc1";
        break;
    case OPC_CFC1:
5460
        tcg_gen_helper_0_1i(do_cfc1, fs);
5461
        gen_store_gpr(cpu_T[0], rt);
B
bellard 已提交
5462 5463 5464
        opn = "cfc1";
        break;
    case OPC_CTC1:
5465
        gen_load_gpr(cpu_T[0], rt);
5466
        tcg_gen_helper_0_1i(do_ctc1, fs);
B
bellard 已提交
5467 5468
        opn = "ctc1";
        break;
T
ths 已提交
5469
    case OPC_DMFC1:
T
ths 已提交
5470 5471
        gen_load_fpr64(ctx, fpu64_T[0], fs);
        tcg_gen_mov_tl(cpu_T[0], fpu64_T[0]);
5472
        gen_store_gpr(cpu_T[0], rt);
5473 5474
        opn = "dmfc1";
        break;
T
ths 已提交
5475
    case OPC_DMTC1:
5476
        gen_load_gpr(cpu_T[0], rt);
T
ths 已提交
5477 5478
        tcg_gen_mov_tl(fpu64_T[0], cpu_T[0]);
        gen_store_fpr64(ctx, fpu64_T[0], fs);
5479 5480 5481
        opn = "dmtc1";
        break;
    case OPC_MFHC1:
T
ths 已提交
5482 5483
        gen_load_fpr32h(fpu32h_T[0], fs);
        tcg_gen_ext_i32_tl(cpu_T[0], fpu32h_T[0]);
5484
        gen_store_gpr(cpu_T[0], rt);
5485 5486 5487
        opn = "mfhc1";
        break;
    case OPC_MTHC1:
5488
        gen_load_gpr(cpu_T[0], rt);
T
ths 已提交
5489 5490
        tcg_gen_trunc_tl_i32(fpu32h_T[0], cpu_T[0]);
        gen_store_fpr32h(fpu32h_T[0], fs);
5491 5492
        opn = "mthc1";
        break;
B
bellard 已提交
5493
    default:
5494
        MIPS_INVAL(opn);
5495
        generate_exception (ctx, EXCP_RI);
B
bellard 已提交
5496 5497 5498 5499 5500
        return;
    }
    MIPS_DEBUG("%s %s %s", opn, regnames[rt], fregnames[fs]);
}

5501 5502
static void gen_movci (DisasContext *ctx, int rd, int rs, int cc, int tf)
{
T
ths 已提交
5503
    int l1 = gen_new_label();
5504
    uint32_t ccbit;
T
ths 已提交
5505
    TCGCond cond;
B
bellard 已提交
5506

T
ths 已提交
5507
    if (cc)
5508
        ccbit = 1 << (24 + cc);
T
ths 已提交
5509
    else
5510
        ccbit = 1 << 23;
T
ths 已提交
5511 5512
    if (tf)
        cond = TCG_COND_EQ;
5513 5514 5515 5516 5517 5518 5519
    else
        cond = TCG_COND_NE;

    gen_load_gpr(cpu_T[0], rd);
    gen_load_gpr(cpu_T[1], rs);
    {
        TCGv r_ptr = tcg_temp_new(TCG_TYPE_PTR);
T
ths 已提交
5520
        TCGv r_tmp = tcg_temp_local_new(TCG_TYPE_I32);
5521 5522 5523

        tcg_gen_ld_ptr(r_ptr, cpu_env, offsetof(CPUState, fpu));
        tcg_gen_ld_i32(r_tmp, r_ptr, offsetof(CPUMIPSFPUContext, fcr31));
5524
        tcg_temp_free(r_ptr);
5525 5526
        tcg_gen_andi_i32(r_tmp, r_tmp, ccbit);
        tcg_gen_brcondi_i32(cond, r_tmp, 0, l1);
T
ths 已提交
5527
        tcg_temp_free(r_tmp);
5528 5529
    }
    tcg_gen_mov_tl(cpu_T[0], cpu_T[1]);
T
ths 已提交
5530 5531

    gen_set_label(l1);
5532
    gen_store_gpr(cpu_T[0], rd);
5533 5534 5535 5536 5537 5538 5539
}

#define GEN_MOVCF(fmt)                                                \
static void glue(gen_movcf_, fmt) (DisasContext *ctx, int cc, int tf) \
{                                                                     \
    uint32_t ccbit;                                                   \
                                                                      \
T
ths 已提交
5540
    if (cc) {                                                         \
5541
        ccbit = 1 << (24 + cc);                                       \
T
ths 已提交
5542
    } else                                                            \
5543 5544 5545 5546 5547 5548 5549 5550 5551
        ccbit = 1 << 23;                                              \
    if (!tf)                                                          \
        glue(gen_op_float_movf_, fmt)(ccbit);                         \
    else                                                              \
        glue(gen_op_float_movt_, fmt)(ccbit);                         \
}
GEN_MOVCF(d);
GEN_MOVCF(s);
#undef GEN_MOVCF
B
bellard 已提交
5552

5553 5554
static void gen_farith (DisasContext *ctx, uint32_t op1,
                        int ft, int fs, int fd, int cc)
B
bellard 已提交
5555
{
5556
    const char *opn = "farith";
B
bellard 已提交
5557 5558 5559 5560 5561 5562 5563 5564 5565 5566 5567 5568 5569 5570 5571 5572 5573 5574
    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",
    };
5575 5576 5577 5578 5579 5580 5581 5582 5583 5584 5585 5586 5587 5588 5589 5590 5591 5592 5593
    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;
5594 5595
    uint32_t func = ctx->opcode & 0x3f;

B
bellard 已提交
5596
    switch (ctx->opcode & FOP(0x3f, 0x1f)) {
5597
    case FOP(0, 16):
T
ths 已提交
5598 5599
        gen_load_fpr32(fpu32_T[0], fs);
        gen_load_fpr32(fpu32_T[1], ft);
5600
        gen_op_float_add_s();
T
ths 已提交
5601
        gen_store_fpr32(fpu32_T[2], fd);
5602
        opn = "add.s";
5603
        optype = BINOP;
5604 5605
        break;
    case FOP(1, 16):
T
ths 已提交
5606 5607
        gen_load_fpr32(fpu32_T[0], fs);
        gen_load_fpr32(fpu32_T[1], ft);
5608
        gen_op_float_sub_s();
T
ths 已提交
5609
        gen_store_fpr32(fpu32_T[2], fd);
5610
        opn = "sub.s";
5611
        optype = BINOP;
5612 5613
        break;
    case FOP(2, 16):
T
ths 已提交
5614 5615
        gen_load_fpr32(fpu32_T[0], fs);
        gen_load_fpr32(fpu32_T[1], ft);
5616
        gen_op_float_mul_s();
T
ths 已提交
5617
        gen_store_fpr32(fpu32_T[2], fd);
5618
        opn = "mul.s";
5619
        optype = BINOP;
5620 5621
        break;
    case FOP(3, 16):
T
ths 已提交
5622 5623
        gen_load_fpr32(fpu32_T[0], fs);
        gen_load_fpr32(fpu32_T[1], ft);
5624
        gen_op_float_div_s();
T
ths 已提交
5625
        gen_store_fpr32(fpu32_T[2], fd);
5626
        opn = "div.s";
5627
        optype = BINOP;
5628 5629
        break;
    case FOP(4, 16):
T
ths 已提交
5630
        gen_load_fpr32(fpu32_T[0], fs);
5631
        gen_op_float_sqrt_s();
T
ths 已提交
5632
        gen_store_fpr32(fpu32_T[2], fd);
5633 5634 5635
        opn = "sqrt.s";
        break;
    case FOP(5, 16):
T
ths 已提交
5636
        gen_load_fpr32(fpu32_T[0], fs);
5637
        gen_op_float_abs_s();
T
ths 已提交
5638
        gen_store_fpr32(fpu32_T[2], fd);
5639 5640 5641
        opn = "abs.s";
        break;
    case FOP(6, 16):
T
ths 已提交
5642
        gen_load_fpr32(fpu32_T[0], fs);
5643
        gen_op_float_mov_s();
T
ths 已提交
5644
        gen_store_fpr32(fpu32_T[2], fd);
5645 5646 5647
        opn = "mov.s";
        break;
    case FOP(7, 16):
T
ths 已提交
5648
        gen_load_fpr32(fpu32_T[0], fs);
5649
        gen_op_float_chs_s();
T
ths 已提交
5650
        gen_store_fpr32(fpu32_T[2], fd);
5651 5652 5653
        opn = "neg.s";
        break;
    case FOP(8, 16):
5654
        check_cp1_64bitmode(ctx);
T
ths 已提交
5655
        gen_load_fpr32(fpu32_T[0], fs);
5656
        gen_op_float_roundl_s();
T
ths 已提交
5657
        gen_store_fpr64(ctx, fpu64_T[2], fd);
5658 5659 5660
        opn = "round.l.s";
        break;
    case FOP(9, 16):
5661
        check_cp1_64bitmode(ctx);
T
ths 已提交
5662
        gen_load_fpr32(fpu32_T[0], fs);
5663
        gen_op_float_truncl_s();
T
ths 已提交
5664
        gen_store_fpr64(ctx, fpu64_T[2], fd);
5665 5666 5667
        opn = "trunc.l.s";
        break;
    case FOP(10, 16):
5668
        check_cp1_64bitmode(ctx);
T
ths 已提交
5669
        gen_load_fpr32(fpu32_T[0], fs);
5670
        gen_op_float_ceill_s();
T
ths 已提交
5671
        gen_store_fpr64(ctx, fpu64_T[2], fd);
5672 5673 5674
        opn = "ceil.l.s";
        break;
    case FOP(11, 16):
5675
        check_cp1_64bitmode(ctx);
T
ths 已提交
5676
        gen_load_fpr32(fpu32_T[0], fs);
5677
        gen_op_float_floorl_s();
T
ths 已提交
5678
        gen_store_fpr64(ctx, fpu64_T[2], fd);
5679 5680 5681
        opn = "floor.l.s";
        break;
    case FOP(12, 16):
T
ths 已提交
5682
        gen_load_fpr32(fpu32_T[0], fs);
5683
        gen_op_float_roundw_s();
T
ths 已提交
5684
        gen_store_fpr32(fpu32_T[2], fd);
5685 5686 5687
        opn = "round.w.s";
        break;
    case FOP(13, 16):
T
ths 已提交
5688
        gen_load_fpr32(fpu32_T[0], fs);
5689
        gen_op_float_truncw_s();
T
ths 已提交
5690
        gen_store_fpr32(fpu32_T[2], fd);
5691 5692 5693
        opn = "trunc.w.s";
        break;
    case FOP(14, 16):
T
ths 已提交
5694
        gen_load_fpr32(fpu32_T[0], fs);
5695
        gen_op_float_ceilw_s();
T
ths 已提交
5696
        gen_store_fpr32(fpu32_T[2], fd);
5697 5698 5699
        opn = "ceil.w.s";
        break;
    case FOP(15, 16):
T
ths 已提交
5700
        gen_load_fpr32(fpu32_T[0], fs);
5701
        gen_op_float_floorw_s();
T
ths 已提交
5702
        gen_store_fpr32(fpu32_T[2], fd);
5703 5704 5705
        opn = "floor.w.s";
        break;
    case FOP(17, 16):
5706
        gen_load_gpr(cpu_T[0], ft);
T
ths 已提交
5707 5708
        gen_load_fpr32(fpu32_T[0], fs);
        gen_load_fpr32(fpu32_T[2], fd);
5709
        gen_movcf_s(ctx, (ft >> 2) & 0x7, ft & 0x1);
T
ths 已提交
5710
        gen_store_fpr32(fpu32_T[2], fd);
5711 5712 5713
        opn = "movcf.s";
        break;
    case FOP(18, 16):
5714
        gen_load_gpr(cpu_T[0], ft);
T
ths 已提交
5715 5716
        gen_load_fpr32(fpu32_T[0], fs);
        gen_load_fpr32(fpu32_T[2], fd);
5717
        gen_op_float_movz_s();
T
ths 已提交
5718
        gen_store_fpr32(fpu32_T[2], fd);
5719 5720 5721
        opn = "movz.s";
        break;
    case FOP(19, 16):
5722
        gen_load_gpr(cpu_T[0], ft);
T
ths 已提交
5723 5724
        gen_load_fpr32(fpu32_T[0], fs);
        gen_load_fpr32(fpu32_T[2], fd);
5725
        gen_op_float_movn_s();
T
ths 已提交
5726
        gen_store_fpr32(fpu32_T[2], fd);
5727 5728
        opn = "movn.s";
        break;
T
ths 已提交
5729
    case FOP(21, 16):
5730
        check_cop1x(ctx);
T
ths 已提交
5731
        gen_load_fpr32(fpu32_T[0], fs);
T
ths 已提交
5732
        gen_op_float_recip_s();
T
ths 已提交
5733
        gen_store_fpr32(fpu32_T[2], fd);
T
ths 已提交
5734 5735 5736
        opn = "recip.s";
        break;
    case FOP(22, 16):
5737
        check_cop1x(ctx);
T
ths 已提交
5738
        gen_load_fpr32(fpu32_T[0], fs);
T
ths 已提交
5739
        gen_op_float_rsqrt_s();
T
ths 已提交
5740
        gen_store_fpr32(fpu32_T[2], fd);
T
ths 已提交
5741 5742 5743
        opn = "rsqrt.s";
        break;
    case FOP(28, 16):
5744
        check_cp1_64bitmode(ctx);
T
ths 已提交
5745 5746
        gen_load_fpr32(fpu32_T[0], fs);
        gen_load_fpr32(fpu32_T[2], fd);
T
ths 已提交
5747
        gen_op_float_recip2_s();
T
ths 已提交
5748
        gen_store_fpr32(fpu32_T[2], fd);
T
ths 已提交
5749 5750 5751
        opn = "recip2.s";
        break;
    case FOP(29, 16):
5752
        check_cp1_64bitmode(ctx);
T
ths 已提交
5753
        gen_load_fpr32(fpu32_T[0], fs);
T
ths 已提交
5754
        gen_op_float_recip1_s();
T
ths 已提交
5755
        gen_store_fpr32(fpu32_T[2], fd);
T
ths 已提交
5756 5757 5758
        opn = "recip1.s";
        break;
    case FOP(30, 16):
5759
        check_cp1_64bitmode(ctx);
T
ths 已提交
5760
        gen_load_fpr32(fpu32_T[0], fs);
T
ths 已提交
5761
        gen_op_float_rsqrt1_s();
T
ths 已提交
5762
        gen_store_fpr32(fpu32_T[2], fd);
T
ths 已提交
5763 5764 5765
        opn = "rsqrt1.s";
        break;
    case FOP(31, 16):
5766
        check_cp1_64bitmode(ctx);
T
ths 已提交
5767 5768
        gen_load_fpr32(fpu32_T[0], fs);
        gen_load_fpr32(fpu32_T[2], ft);
T
ths 已提交
5769
        gen_op_float_rsqrt2_s();
T
ths 已提交
5770
        gen_store_fpr32(fpu32_T[2], fd);
T
ths 已提交
5771 5772
        opn = "rsqrt2.s";
        break;
5773
    case FOP(33, 16):
5774
        check_cp1_registers(ctx, fd);
T
ths 已提交
5775
        gen_load_fpr32(fpu32_T[0], fs);
5776
        gen_op_float_cvtd_s();
T
ths 已提交
5777
        gen_store_fpr64(ctx, fpu64_T[2], fd);
5778 5779 5780
        opn = "cvt.d.s";
        break;
    case FOP(36, 16):
T
ths 已提交
5781
        gen_load_fpr32(fpu32_T[0], fs);
5782
        gen_op_float_cvtw_s();
T
ths 已提交
5783
        gen_store_fpr32(fpu32_T[2], fd);
5784 5785 5786
        opn = "cvt.w.s";
        break;
    case FOP(37, 16):
5787
        check_cp1_64bitmode(ctx);
T
ths 已提交
5788
        gen_load_fpr32(fpu32_T[0], fs);
5789
        gen_op_float_cvtl_s();
T
ths 已提交
5790
        gen_store_fpr64(ctx, fpu64_T[2], fd);
5791 5792 5793
        opn = "cvt.l.s";
        break;
    case FOP(38, 16):
5794
        check_cp1_64bitmode(ctx);
T
ths 已提交
5795 5796
        gen_load_fpr32(fpu32_T[1], fs);
        gen_load_fpr32(fpu32_T[0], ft);
5797
        gen_op_float_cvtps_s();
T
ths 已提交
5798
        gen_store_fpr64(ctx, fpu64_T[2], fd);
5799 5800 5801 5802 5803 5804 5805 5806 5807 5808 5809 5810 5811 5812 5813 5814 5815 5816
        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):
T
ths 已提交
5817 5818
        gen_load_fpr32(fpu32_T[0], fs);
        gen_load_fpr32(fpu32_T[1], ft);
5819
        if (ctx->opcode & (1 << 6)) {
5820
            check_cop1x(ctx);
5821 5822 5823 5824 5825 5826
            gen_cmpabs_s(func-48, cc);
            opn = condnames_abs[func-48];
        } else {
            gen_cmp_s(func-48, cc);
            opn = condnames[func-48];
        }
5827
        break;
B
bellard 已提交
5828
    case FOP(0, 17):
5829
        check_cp1_registers(ctx, fs | ft | fd);
T
ths 已提交
5830 5831
        gen_load_fpr64(ctx, fpu64_T[0], fs);
        gen_load_fpr64(ctx, fpu64_T[1], ft);
B
bellard 已提交
5832
        gen_op_float_add_d();
T
ths 已提交
5833
        gen_store_fpr64(ctx, fpu64_T[2], fd);
B
bellard 已提交
5834
        opn = "add.d";
5835
        optype = BINOP;
B
bellard 已提交
5836 5837
        break;
    case FOP(1, 17):
5838
        check_cp1_registers(ctx, fs | ft | fd);
T
ths 已提交
5839 5840
        gen_load_fpr64(ctx, fpu64_T[0], fs);
        gen_load_fpr64(ctx, fpu64_T[1], ft);
B
bellard 已提交
5841
        gen_op_float_sub_d();
T
ths 已提交
5842
        gen_store_fpr64(ctx, fpu64_T[2], fd);
B
bellard 已提交
5843
        opn = "sub.d";
5844
        optype = BINOP;
B
bellard 已提交
5845 5846
        break;
    case FOP(2, 17):
5847
        check_cp1_registers(ctx, fs | ft | fd);
T
ths 已提交
5848 5849
        gen_load_fpr64(ctx, fpu64_T[0], fs);
        gen_load_fpr64(ctx, fpu64_T[1], ft);
B
bellard 已提交
5850
        gen_op_float_mul_d();
T
ths 已提交
5851
        gen_store_fpr64(ctx, fpu64_T[2], fd);
B
bellard 已提交
5852
        opn = "mul.d";
5853
        optype = BINOP;
B
bellard 已提交
5854 5855
        break;
    case FOP(3, 17):
5856
        check_cp1_registers(ctx, fs | ft | fd);
T
ths 已提交
5857 5858
        gen_load_fpr64(ctx, fpu64_T[0], fs);
        gen_load_fpr64(ctx, fpu64_T[1], ft);
B
bellard 已提交
5859
        gen_op_float_div_d();
T
ths 已提交
5860
        gen_store_fpr64(ctx, fpu64_T[2], fd);
B
bellard 已提交
5861
        opn = "div.d";
5862
        optype = BINOP;
B
bellard 已提交
5863 5864
        break;
    case FOP(4, 17):
5865
        check_cp1_registers(ctx, fs | fd);
T
ths 已提交
5866
        gen_load_fpr64(ctx, fpu64_T[0], fs);
B
bellard 已提交
5867
        gen_op_float_sqrt_d();
T
ths 已提交
5868
        gen_store_fpr64(ctx, fpu64_T[2], fd);
B
bellard 已提交
5869 5870 5871
        opn = "sqrt.d";
        break;
    case FOP(5, 17):
5872
        check_cp1_registers(ctx, fs | fd);
T
ths 已提交
5873
        gen_load_fpr64(ctx, fpu64_T[0], fs);
B
bellard 已提交
5874
        gen_op_float_abs_d();
T
ths 已提交
5875
        gen_store_fpr64(ctx, fpu64_T[2], fd);
B
bellard 已提交
5876 5877 5878
        opn = "abs.d";
        break;
    case FOP(6, 17):
5879
        check_cp1_registers(ctx, fs | fd);
T
ths 已提交
5880
        gen_load_fpr64(ctx, fpu64_T[0], fs);
B
bellard 已提交
5881
        gen_op_float_mov_d();
T
ths 已提交
5882
        gen_store_fpr64(ctx, fpu64_T[2], fd);
B
bellard 已提交
5883 5884 5885
        opn = "mov.d";
        break;
    case FOP(7, 17):
5886
        check_cp1_registers(ctx, fs | fd);
T
ths 已提交
5887
        gen_load_fpr64(ctx, fpu64_T[0], fs);
B
bellard 已提交
5888
        gen_op_float_chs_d();
T
ths 已提交
5889
        gen_store_fpr64(ctx, fpu64_T[2], fd);
B
bellard 已提交
5890 5891
        opn = "neg.d";
        break;
5892
    case FOP(8, 17):
5893
        check_cp1_64bitmode(ctx);
T
ths 已提交
5894
        gen_load_fpr64(ctx, fpu64_T[0], fs);
5895
        gen_op_float_roundl_d();
T
ths 已提交
5896
        gen_store_fpr64(ctx, fpu64_T[2], fd);
5897 5898 5899
        opn = "round.l.d";
        break;
    case FOP(9, 17):
5900
        check_cp1_64bitmode(ctx);
T
ths 已提交
5901
        gen_load_fpr64(ctx, fpu64_T[0], fs);
5902
        gen_op_float_truncl_d();
T
ths 已提交
5903
        gen_store_fpr64(ctx, fpu64_T[2], fd);
5904 5905 5906
        opn = "trunc.l.d";
        break;
    case FOP(10, 17):
5907
        check_cp1_64bitmode(ctx);
T
ths 已提交
5908
        gen_load_fpr64(ctx, fpu64_T[0], fs);
5909
        gen_op_float_ceill_d();
T
ths 已提交
5910
        gen_store_fpr64(ctx, fpu64_T[2], fd);
5911 5912 5913
        opn = "ceil.l.d";
        break;
    case FOP(11, 17):
5914
        check_cp1_64bitmode(ctx);
T
ths 已提交
5915
        gen_load_fpr64(ctx, fpu64_T[0], fs);
5916
        gen_op_float_floorl_d();
T
ths 已提交
5917
        gen_store_fpr64(ctx, fpu64_T[2], fd);
5918 5919
        opn = "floor.l.d";
        break;
B
bellard 已提交
5920
    case FOP(12, 17):
5921
        check_cp1_registers(ctx, fs);
T
ths 已提交
5922
        gen_load_fpr64(ctx, fpu64_T[0], fs);
B
bellard 已提交
5923
        gen_op_float_roundw_d();
T
ths 已提交
5924
        gen_store_fpr32(fpu32_T[2], fd);
B
bellard 已提交
5925 5926 5927
        opn = "round.w.d";
        break;
    case FOP(13, 17):
5928
        check_cp1_registers(ctx, fs);
T
ths 已提交
5929
        gen_load_fpr64(ctx, fpu64_T[0], fs);
B
bellard 已提交
5930
        gen_op_float_truncw_d();
T
ths 已提交
5931
        gen_store_fpr32(fpu32_T[2], fd);
B
bellard 已提交
5932 5933 5934
        opn = "trunc.w.d";
        break;
    case FOP(14, 17):
5935
        check_cp1_registers(ctx, fs);
T
ths 已提交
5936
        gen_load_fpr64(ctx, fpu64_T[0], fs);
B
bellard 已提交
5937
        gen_op_float_ceilw_d();
T
ths 已提交
5938
        gen_store_fpr32(fpu32_T[2], fd);
B
bellard 已提交
5939 5940 5941
        opn = "ceil.w.d";
        break;
    case FOP(15, 17):
5942
        check_cp1_registers(ctx, fs);
T
ths 已提交
5943
        gen_load_fpr64(ctx, fpu64_T[0], fs);
B
bellard 已提交
5944
        gen_op_float_floorw_d();
T
ths 已提交
5945
        gen_store_fpr32(fpu32_T[2], fd);
5946
        opn = "floor.w.d";
B
bellard 已提交
5947
        break;
5948
    case FOP(17, 17):
5949
        gen_load_gpr(cpu_T[0], ft);
T
ths 已提交
5950 5951
        gen_load_fpr64(ctx, fpu64_T[0], fs);
        gen_load_fpr64(ctx, fpu64_T[2], fd);
5952
        gen_movcf_d(ctx, (ft >> 2) & 0x7, ft & 0x1);
T
ths 已提交
5953
        gen_store_fpr64(ctx, fpu64_T[2], fd);
5954
        opn = "movcf.d";
5955
        break;
5956
    case FOP(18, 17):
5957
        gen_load_gpr(cpu_T[0], ft);
T
ths 已提交
5958 5959
        gen_load_fpr64(ctx, fpu64_T[0], fs);
        gen_load_fpr64(ctx, fpu64_T[2], fd);
5960
        gen_op_float_movz_d();
T
ths 已提交
5961
        gen_store_fpr64(ctx, fpu64_T[2], fd);
5962 5963 5964
        opn = "movz.d";
        break;
    case FOP(19, 17):
5965
        gen_load_gpr(cpu_T[0], ft);
T
ths 已提交
5966 5967
        gen_load_fpr64(ctx, fpu64_T[0], fs);
        gen_load_fpr64(ctx, fpu64_T[2], fd);
5968
        gen_op_float_movn_d();
T
ths 已提交
5969
        gen_store_fpr64(ctx, fpu64_T[2], fd);
5970
        opn = "movn.d";
B
bellard 已提交
5971
        break;
T
ths 已提交
5972
    case FOP(21, 17):
5973
        check_cp1_64bitmode(ctx);
T
ths 已提交
5974
        gen_load_fpr64(ctx, fpu64_T[0], fs);
T
ths 已提交
5975
        gen_op_float_recip_d();
T
ths 已提交
5976
        gen_store_fpr64(ctx, fpu64_T[2], fd);
T
ths 已提交
5977 5978 5979
        opn = "recip.d";
        break;
    case FOP(22, 17):
5980
        check_cp1_64bitmode(ctx);
T
ths 已提交
5981
        gen_load_fpr64(ctx, fpu64_T[0], fs);
T
ths 已提交
5982
        gen_op_float_rsqrt_d();
T
ths 已提交
5983
        gen_store_fpr64(ctx, fpu64_T[2], fd);
T
ths 已提交
5984 5985 5986
        opn = "rsqrt.d";
        break;
    case FOP(28, 17):
5987
        check_cp1_64bitmode(ctx);
T
ths 已提交
5988 5989
        gen_load_fpr64(ctx, fpu64_T[0], fs);
        gen_load_fpr64(ctx, fpu64_T[2], ft);
T
ths 已提交
5990
        gen_op_float_recip2_d();
T
ths 已提交
5991
        gen_store_fpr64(ctx, fpu64_T[2], fd);
T
ths 已提交
5992 5993 5994
        opn = "recip2.d";
        break;
    case FOP(29, 17):
5995
        check_cp1_64bitmode(ctx);
T
ths 已提交
5996
        gen_load_fpr64(ctx, fpu64_T[0], fs);
T
ths 已提交
5997
        gen_op_float_recip1_d();
T
ths 已提交
5998
        gen_store_fpr64(ctx, fpu64_T[2], fd);
T
ths 已提交
5999 6000 6001
        opn = "recip1.d";
        break;
    case FOP(30, 17):
6002
        check_cp1_64bitmode(ctx);
T
ths 已提交
6003
        gen_load_fpr64(ctx, fpu64_T[0], fs);
T
ths 已提交
6004
        gen_op_float_rsqrt1_d();
T
ths 已提交
6005
        gen_store_fpr64(ctx, fpu64_T[2], fd);
T
ths 已提交
6006 6007 6008
        opn = "rsqrt1.d";
        break;
    case FOP(31, 17):
6009
        check_cp1_64bitmode(ctx);
T
ths 已提交
6010 6011
        gen_load_fpr64(ctx, fpu64_T[0], fs);
        gen_load_fpr64(ctx, fpu64_T[2], ft);
T
ths 已提交
6012
        gen_op_float_rsqrt2_d();
T
ths 已提交
6013
        gen_store_fpr64(ctx, fpu64_T[2], fd);
T
ths 已提交
6014 6015
        opn = "rsqrt2.d";
        break;
B
bellard 已提交
6016 6017 6018 6019 6020 6021 6022 6023 6024 6025 6026 6027 6028 6029 6030 6031
    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):
T
ths 已提交
6032 6033
        gen_load_fpr64(ctx, fpu64_T[0], fs);
        gen_load_fpr64(ctx, fpu64_T[1], ft);
6034
        if (ctx->opcode & (1 << 6)) {
6035 6036
            check_cop1x(ctx);
            check_cp1_registers(ctx, fs | ft);
6037 6038 6039
            gen_cmpabs_d(func-48, cc);
            opn = condnames_abs[func-48];
        } else {
6040
            check_cp1_registers(ctx, fs | ft);
6041 6042 6043
            gen_cmp_d(func-48, cc);
            opn = condnames[func-48];
        }
B
bellard 已提交
6044
        break;
6045
    case FOP(32, 17):
6046
        check_cp1_registers(ctx, fs);
T
ths 已提交
6047
        gen_load_fpr64(ctx, fpu64_T[0], fs);
6048
        gen_op_float_cvts_d();
T
ths 已提交
6049
        gen_store_fpr32(fpu32_T[2], fd);
6050 6051 6052
        opn = "cvt.s.d";
        break;
    case FOP(36, 17):
6053
        check_cp1_registers(ctx, fs);
T
ths 已提交
6054
        gen_load_fpr64(ctx, fpu64_T[0], fs);
6055
        gen_op_float_cvtw_d();
T
ths 已提交
6056
        gen_store_fpr32(fpu32_T[2], fd);
6057 6058 6059
        opn = "cvt.w.d";
        break;
    case FOP(37, 17):
6060
        check_cp1_64bitmode(ctx);
T
ths 已提交
6061
        gen_load_fpr64(ctx, fpu64_T[0], fs);
6062
        gen_op_float_cvtl_d();
T
ths 已提交
6063
        gen_store_fpr64(ctx, fpu64_T[2], fd);
6064 6065 6066
        opn = "cvt.l.d";
        break;
    case FOP(32, 20):
T
ths 已提交
6067
        gen_load_fpr32(fpu32_T[0], fs);
6068
        gen_op_float_cvts_w();
T
ths 已提交
6069
        gen_store_fpr32(fpu32_T[2], fd);
6070
        opn = "cvt.s.w";
B
bellard 已提交
6071
        break;
6072
    case FOP(33, 20):
6073
        check_cp1_registers(ctx, fd);
T
ths 已提交
6074
        gen_load_fpr32(fpu32_T[0], fs);
6075
        gen_op_float_cvtd_w();
T
ths 已提交
6076
        gen_store_fpr64(ctx, fpu64_T[2], fd);
6077 6078 6079
        opn = "cvt.d.w";
        break;
    case FOP(32, 21):
6080
        check_cp1_64bitmode(ctx);
T
ths 已提交
6081
        gen_load_fpr64(ctx, fpu64_T[0], fs);
6082
        gen_op_float_cvts_l();
T
ths 已提交
6083
        gen_store_fpr32(fpu32_T[2], fd);
6084 6085 6086
        opn = "cvt.s.l";
        break;
    case FOP(33, 21):
6087
        check_cp1_64bitmode(ctx);
T
ths 已提交
6088
        gen_load_fpr64(ctx, fpu64_T[0], fs);
6089
        gen_op_float_cvtd_l();
T
ths 已提交
6090
        gen_store_fpr64(ctx, fpu64_T[2], fd);
6091 6092 6093
        opn = "cvt.d.l";
        break;
    case FOP(38, 20):
6094
        check_cp1_64bitmode(ctx);
T
ths 已提交
6095 6096
        gen_load_fpr32(fpu32_T[0], fs);
        gen_load_fpr32h(fpu32h_T[0], fs);
6097
        gen_op_float_cvtps_pw();
T
ths 已提交
6098 6099
        gen_store_fpr32(fpu32_T[2], fd);
        gen_store_fpr32h(fpu32h_T[2], fd);
6100 6101 6102
        opn = "cvt.ps.pw";
        break;
    case FOP(0, 22):
6103
        check_cp1_64bitmode(ctx);
T
ths 已提交
6104 6105 6106 6107
        gen_load_fpr32(fpu32_T[0], fs);
        gen_load_fpr32h(fpu32h_T[0], fs);
        gen_load_fpr32(fpu32_T[1], ft);
        gen_load_fpr32h(fpu32h_T[1], ft);
6108
        gen_op_float_add_ps();
T
ths 已提交
6109 6110
        gen_store_fpr32(fpu32_T[2], fd);
        gen_store_fpr32h(fpu32h_T[2], fd);
6111
        opn = "add.ps";
B
bellard 已提交
6112
        break;
6113
    case FOP(1, 22):
6114
        check_cp1_64bitmode(ctx);
T
ths 已提交
6115 6116 6117 6118
        gen_load_fpr32(fpu32_T[0], fs);
        gen_load_fpr32h(fpu32h_T[0], fs);
        gen_load_fpr32(fpu32_T[1], ft);
        gen_load_fpr32h(fpu32h_T[1], ft);
6119
        gen_op_float_sub_ps();
T
ths 已提交
6120 6121
        gen_store_fpr32(fpu32_T[2], fd);
        gen_store_fpr32h(fpu32h_T[2], fd);
6122
        opn = "sub.ps";
B
bellard 已提交
6123
        break;
6124
    case FOP(2, 22):
6125
        check_cp1_64bitmode(ctx);
T
ths 已提交
6126 6127 6128 6129
        gen_load_fpr32(fpu32_T[0], fs);
        gen_load_fpr32h(fpu32h_T[0], fs);
        gen_load_fpr32(fpu32_T[1], ft);
        gen_load_fpr32h(fpu32h_T[1], ft);
6130
        gen_op_float_mul_ps();
T
ths 已提交
6131 6132
        gen_store_fpr32(fpu32_T[2], fd);
        gen_store_fpr32h(fpu32h_T[2], fd);
6133
        opn = "mul.ps";
B
bellard 已提交
6134
        break;
6135
    case FOP(5, 22):
6136
        check_cp1_64bitmode(ctx);
T
ths 已提交
6137 6138
        gen_load_fpr32(fpu32_T[0], fs);
        gen_load_fpr32h(fpu32h_T[0], fs);
6139
        gen_op_float_abs_ps();
T
ths 已提交
6140 6141
        gen_store_fpr32(fpu32_T[2], fd);
        gen_store_fpr32h(fpu32h_T[2], fd);
6142
        opn = "abs.ps";
B
bellard 已提交
6143
        break;
6144
    case FOP(6, 22):
6145
        check_cp1_64bitmode(ctx);
T
ths 已提交
6146 6147
        gen_load_fpr32(fpu32_T[0], fs);
        gen_load_fpr32h(fpu32h_T[0], fs);
6148
        gen_op_float_mov_ps();
T
ths 已提交
6149 6150
        gen_store_fpr32(fpu32_T[2], fd);
        gen_store_fpr32h(fpu32h_T[2], fd);
6151
        opn = "mov.ps";
B
bellard 已提交
6152
        break;
6153
    case FOP(7, 22):
6154
        check_cp1_64bitmode(ctx);
T
ths 已提交
6155 6156
        gen_load_fpr32(fpu32_T[0], fs);
        gen_load_fpr32h(fpu32h_T[0], fs);
6157
        gen_op_float_chs_ps();
T
ths 已提交
6158 6159
        gen_store_fpr32(fpu32_T[2], fd);
        gen_store_fpr32h(fpu32h_T[2], fd);
6160
        opn = "neg.ps";
B
bellard 已提交
6161
        break;
6162
    case FOP(17, 22):
6163
        check_cp1_64bitmode(ctx);
6164
        gen_load_gpr(cpu_T[0], ft);
T
ths 已提交
6165 6166 6167 6168
        gen_load_fpr32(fpu32_T[0], fs);
        gen_load_fpr32h(fpu32h_T[0], fs);
        gen_load_fpr32(fpu32_T[2], fd);
        gen_load_fpr32h(fpu32h_T[2], fd);
6169 6170 6171 6172
        if (ft & 0x1)
            gen_op_float_movt_ps ((ft >> 2) & 0x7);
        else
            gen_op_float_movf_ps ((ft >> 2) & 0x7);
T
ths 已提交
6173 6174
        gen_store_fpr32(fpu32_T[2], fd);
        gen_store_fpr32h(fpu32h_T[2], fd);
6175
        opn = "movcf.ps";
B
bellard 已提交
6176
        break;
6177
    case FOP(18, 22):
6178
        check_cp1_64bitmode(ctx);
6179
        gen_load_gpr(cpu_T[0], ft);
T
ths 已提交
6180 6181 6182 6183
        gen_load_fpr32(fpu32_T[0], fs);
        gen_load_fpr32h(fpu32h_T[0], fs);
        gen_load_fpr32(fpu32_T[2], fd);
        gen_load_fpr32h(fpu32h_T[2], fd);
6184
        gen_op_float_movz_ps();
T
ths 已提交
6185 6186
        gen_store_fpr32(fpu32_T[2], fd);
        gen_store_fpr32h(fpu32h_T[2], fd);
6187
        opn = "movz.ps";
B
bellard 已提交
6188
        break;
6189
    case FOP(19, 22):
6190
        check_cp1_64bitmode(ctx);
6191
        gen_load_gpr(cpu_T[0], ft);
T
ths 已提交
6192 6193 6194 6195
        gen_load_fpr32(fpu32_T[0], fs);
        gen_load_fpr32h(fpu32h_T[0], fs);
        gen_load_fpr32(fpu32_T[2], fd);
        gen_load_fpr32h(fpu32h_T[2], fd);
6196
        gen_op_float_movn_ps();
T
ths 已提交
6197 6198
        gen_store_fpr32(fpu32_T[2], fd);
        gen_store_fpr32h(fpu32h_T[2], fd);
6199
        opn = "movn.ps";
B
bellard 已提交
6200
        break;
6201
    case FOP(24, 22):
6202
        check_cp1_64bitmode(ctx);
T
ths 已提交
6203 6204 6205 6206
        gen_load_fpr32(fpu32_T[0], ft);
        gen_load_fpr32h(fpu32h_T[0], ft);
        gen_load_fpr32(fpu32_T[1], fs);
        gen_load_fpr32h(fpu32h_T[1], fs);
6207
        gen_op_float_addr_ps();
T
ths 已提交
6208 6209
        gen_store_fpr32(fpu32_T[2], fd);
        gen_store_fpr32h(fpu32h_T[2], fd);
6210 6211
        opn = "addr.ps";
        break;
T
ths 已提交
6212
    case FOP(26, 22):
6213
        check_cp1_64bitmode(ctx);
T
ths 已提交
6214 6215 6216 6217
        gen_load_fpr32(fpu32_T[0], ft);
        gen_load_fpr32h(fpu32h_T[0], ft);
        gen_load_fpr32(fpu32_T[1], fs);
        gen_load_fpr32h(fpu32h_T[1], fs);
T
ths 已提交
6218
        gen_op_float_mulr_ps();
T
ths 已提交
6219 6220
        gen_store_fpr32(fpu32_T[2], fd);
        gen_store_fpr32h(fpu32h_T[2], fd);
T
ths 已提交
6221 6222 6223
        opn = "mulr.ps";
        break;
    case FOP(28, 22):
6224
        check_cp1_64bitmode(ctx);
T
ths 已提交
6225 6226 6227 6228
        gen_load_fpr32(fpu32_T[0], fs);
        gen_load_fpr32h(fpu32h_T[0], fs);
        gen_load_fpr32(fpu32_T[2], fd);
        gen_load_fpr32h(fpu32h_T[2], fd);
T
ths 已提交
6229
        gen_op_float_recip2_ps();
T
ths 已提交
6230 6231
        gen_store_fpr32(fpu32_T[2], fd);
        gen_store_fpr32h(fpu32h_T[2], fd);
T
ths 已提交
6232 6233 6234
        opn = "recip2.ps";
        break;
    case FOP(29, 22):
6235
        check_cp1_64bitmode(ctx);
T
ths 已提交
6236 6237
        gen_load_fpr32(fpu32_T[0], fs);
        gen_load_fpr32h(fpu32h_T[0], fs);
T
ths 已提交
6238
        gen_op_float_recip1_ps();
T
ths 已提交
6239 6240
        gen_store_fpr32(fpu32_T[2], fd);
        gen_store_fpr32h(fpu32h_T[2], fd);
T
ths 已提交
6241 6242 6243
        opn = "recip1.ps";
        break;
    case FOP(30, 22):
6244
        check_cp1_64bitmode(ctx);
T
ths 已提交
6245 6246
        gen_load_fpr32(fpu32_T[0], fs);
        gen_load_fpr32h(fpu32h_T[0], fs);
T
ths 已提交
6247
        gen_op_float_rsqrt1_ps();
T
ths 已提交
6248 6249
        gen_store_fpr32(fpu32_T[2], fd);
        gen_store_fpr32h(fpu32h_T[2], fd);
T
ths 已提交
6250 6251 6252
        opn = "rsqrt1.ps";
        break;
    case FOP(31, 22):
6253
        check_cp1_64bitmode(ctx);
T
ths 已提交
6254 6255 6256 6257
        gen_load_fpr32(fpu32_T[0], fs);
        gen_load_fpr32h(fpu32h_T[0], fs);
        gen_load_fpr32(fpu32_T[2], ft);
        gen_load_fpr32h(fpu32h_T[2], ft);
T
ths 已提交
6258
        gen_op_float_rsqrt2_ps();
T
ths 已提交
6259 6260
        gen_store_fpr32(fpu32_T[2], fd);
        gen_store_fpr32h(fpu32h_T[2], fd);
T
ths 已提交
6261 6262
        opn = "rsqrt2.ps";
        break;
6263
    case FOP(32, 22):
6264
        check_cp1_64bitmode(ctx);
T
ths 已提交
6265
        gen_load_fpr32h(fpu32h_T[0], fs);
6266
        gen_op_float_cvts_pu();
T
ths 已提交
6267
        gen_store_fpr32(fpu32_T[2], fd);
6268
        opn = "cvt.s.pu";
6269
        break;
6270
    case FOP(36, 22):
6271
        check_cp1_64bitmode(ctx);
T
ths 已提交
6272 6273
        gen_load_fpr32(fpu32_T[0], fs);
        gen_load_fpr32h(fpu32h_T[0], fs);
6274
        gen_op_float_cvtpw_ps();
T
ths 已提交
6275 6276
        gen_store_fpr32(fpu32_T[2], fd);
        gen_store_fpr32h(fpu32h_T[2], fd);
6277
        opn = "cvt.pw.ps";
B
bellard 已提交
6278
        break;
6279
    case FOP(40, 22):
6280
        check_cp1_64bitmode(ctx);
T
ths 已提交
6281
        gen_load_fpr32(fpu32_T[0], fs);
6282
        gen_op_float_cvts_pl();
T
ths 已提交
6283
        gen_store_fpr32(fpu32_T[2], fd);
6284
        opn = "cvt.s.pl";
B
bellard 已提交
6285
        break;
6286
    case FOP(44, 22):
6287
        check_cp1_64bitmode(ctx);
T
ths 已提交
6288 6289
        gen_load_fpr32(fpu32_T[0], fs);
        gen_load_fpr32(fpu32_T[1], ft);
6290
        gen_op_float_pll_ps();
T
ths 已提交
6291
        gen_store_fpr64(ctx, fpu64_T[2], fd);
6292
        opn = "pll.ps";
B
bellard 已提交
6293
        break;
6294
    case FOP(45, 22):
6295
        check_cp1_64bitmode(ctx);
T
ths 已提交
6296 6297
        gen_load_fpr32(fpu32_T[0], fs);
        gen_load_fpr32h(fpu32h_T[1], ft);
6298
        gen_op_float_plu_ps();
T
ths 已提交
6299
        gen_store_fpr64(ctx, fpu64_T[2], fd);
6300 6301 6302
        opn = "plu.ps";
        break;
    case FOP(46, 22):
6303
        check_cp1_64bitmode(ctx);
T
ths 已提交
6304 6305
        gen_load_fpr32h(fpu32h_T[0], fs);
        gen_load_fpr32(fpu32_T[1], ft);
6306
        gen_op_float_pul_ps();
T
ths 已提交
6307
        gen_store_fpr64(ctx, fpu64_T[2], fd);
6308 6309 6310
        opn = "pul.ps";
        break;
    case FOP(47, 22):
6311
        check_cp1_64bitmode(ctx);
T
ths 已提交
6312 6313
        gen_load_fpr32h(fpu32h_T[0], fs);
        gen_load_fpr32h(fpu32h_T[1], ft);
6314
        gen_op_float_puu_ps();
T
ths 已提交
6315
        gen_store_fpr64(ctx, fpu64_T[2], fd);
6316 6317 6318 6319 6320 6321 6322 6323 6324 6325 6326 6327 6328 6329 6330 6331 6332 6333
        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):
6334
        check_cp1_64bitmode(ctx);
T
ths 已提交
6335 6336 6337 6338
        gen_load_fpr32(fpu32_T[0], fs);
        gen_load_fpr32h(fpu32h_T[0], fs);
        gen_load_fpr32(fpu32_T[1], ft);
        gen_load_fpr32h(fpu32h_T[1], ft);
6339 6340 6341 6342 6343 6344 6345
        if (ctx->opcode & (1 << 6)) {
            gen_cmpabs_ps(func-48, cc);
            opn = condnames_abs[func-48];
        } else {
            gen_cmp_ps(func-48, cc);
            opn = condnames[func-48];
        }
B
bellard 已提交
6346
        break;
6347
    default:
6348
        MIPS_INVAL(opn);
6349
        generate_exception (ctx, EXCP_RI);
B
bellard 已提交
6350 6351
        return;
    }
6352 6353
    switch (optype) {
    case BINOP:
B
bellard 已提交
6354
        MIPS_DEBUG("%s %s, %s, %s", opn, fregnames[fd], fregnames[fs], fregnames[ft]);
6355 6356 6357 6358 6359
        break;
    case CMPOP:
        MIPS_DEBUG("%s %s,%s", opn, fregnames[fs], fregnames[ft]);
        break;
    default:
B
bellard 已提交
6360
        MIPS_DEBUG("%s %s,%s", opn, fregnames[fd], fregnames[fs]);
6361 6362
        break;
    }
B
bellard 已提交
6363
}
B
bellard 已提交
6364

6365
/* Coprocessor 3 (FPU) */
6366 6367
static void gen_flt3_ldst (DisasContext *ctx, uint32_t opc,
                           int fd, int fs, int base, int index)
6368
{
6369
    const char *opn = "extended float load/store";
T
ths 已提交
6370
    int store = 0;
6371

T
ths 已提交
6372
    if (base == 0) {
6373
        gen_load_gpr(cpu_T[0], index);
T
ths 已提交
6374
    } else if (index == 0) {
6375
        gen_load_gpr(cpu_T[0], base);
T
ths 已提交
6376
    } else {
6377 6378
        gen_load_gpr(cpu_T[0], base);
        gen_load_gpr(cpu_T[1], index);
T
ths 已提交
6379 6380
        gen_op_addr_add();
    }
6381
    /* Don't do NOP if destination is zero: we must perform the actual
6382
       memory access. */
6383 6384
    switch (opc) {
    case OPC_LWXC1:
6385
        check_cop1x(ctx);
T
ths 已提交
6386 6387
        tcg_gen_qemu_ld32s(fpu32_T[0], cpu_T[0], ctx->mem_idx);
        gen_store_fpr32(fpu32_T[0], fd);
6388 6389 6390
        opn = "lwxc1";
        break;
    case OPC_LDXC1:
6391 6392
        check_cop1x(ctx);
        check_cp1_registers(ctx, fd);
T
ths 已提交
6393 6394
        tcg_gen_qemu_ld64(fpu64_T[0], cpu_T[0], ctx->mem_idx);
        gen_store_fpr64(ctx, fpu64_T[0], fd);
6395 6396 6397
        opn = "ldxc1";
        break;
    case OPC_LUXC1:
6398
        check_cp1_64bitmode(ctx);
6399
        op_ldst(luxc1);
T
ths 已提交
6400
        gen_store_fpr64(ctx, fpu64_T[0], fd);
6401 6402 6403
        opn = "luxc1";
        break;
    case OPC_SWXC1:
6404
        check_cop1x(ctx);
T
ths 已提交
6405 6406
        gen_load_fpr32(fpu32_T[0], fs);
        tcg_gen_qemu_st32(fpu32_T[0], cpu_T[0], ctx->mem_idx);
6407
        opn = "swxc1";
T
ths 已提交
6408
        store = 1;
6409 6410
        break;
    case OPC_SDXC1:
6411 6412
        check_cop1x(ctx);
        check_cp1_registers(ctx, fs);
T
ths 已提交
6413 6414
        gen_load_fpr64(ctx, fpu64_T[0], fs);
        tcg_gen_qemu_st64(fpu64_T[0], cpu_T[0], ctx->mem_idx);
6415
        opn = "sdxc1";
T
ths 已提交
6416
        store = 1;
6417 6418
        break;
    case OPC_SUXC1:
6419
        check_cp1_64bitmode(ctx);
T
ths 已提交
6420
        gen_load_fpr64(ctx, fpu64_T[0], fs);
6421 6422
        op_ldst(suxc1);
        opn = "suxc1";
T
ths 已提交
6423
        store = 1;
6424 6425
        break;
    default:
6426
        MIPS_INVAL(opn);
6427 6428 6429
        generate_exception(ctx, EXCP_RI);
        return;
    }
T
ths 已提交
6430 6431
    MIPS_DEBUG("%s %s, %s(%s)", opn, fregnames[store ? fs : fd],
               regnames[index], regnames[base]);
6432 6433
}

6434 6435
static void gen_flt3_arith (DisasContext *ctx, uint32_t opc,
                            int fd, int fr, int fs, int ft)
6436
{
6437
    const char *opn = "flt3_arith";
6438 6439 6440

    switch (opc) {
    case OPC_ALNV_PS:
6441
        check_cp1_64bitmode(ctx);
6442
        gen_load_gpr(cpu_T[0], fr);
T
ths 已提交
6443 6444
        gen_load_fpr64(ctx, fpu64_T[0], fs);
        gen_load_fpr64(ctx, fpu64_T[1], ft);
6445
        gen_op_float_alnv_ps();
T
ths 已提交
6446
        gen_store_fpr64(ctx, fpu64_T[2], fd);
6447 6448 6449
        opn = "alnv.ps";
        break;
    case OPC_MADD_S:
6450
        check_cop1x(ctx);
T
ths 已提交
6451 6452 6453
        gen_load_fpr32(fpu32_T[0], fs);
        gen_load_fpr32(fpu32_T[1], ft);
        gen_load_fpr32(fpu32_T[2], fr);
6454
        gen_op_float_muladd_s();
T
ths 已提交
6455
        gen_store_fpr32(fpu32_T[2], fd);
6456 6457 6458
        opn = "madd.s";
        break;
    case OPC_MADD_D:
6459 6460
        check_cop1x(ctx);
        check_cp1_registers(ctx, fd | fs | ft | fr);
T
ths 已提交
6461 6462 6463
        gen_load_fpr64(ctx, fpu64_T[0], fs);
        gen_load_fpr64(ctx, fpu64_T[1], ft);
        gen_load_fpr64(ctx, fpu64_T[2], fr);
6464
        gen_op_float_muladd_d();
T
ths 已提交
6465
        gen_store_fpr64(ctx, fpu64_T[2], fd);
6466 6467 6468
        opn = "madd.d";
        break;
    case OPC_MADD_PS:
6469
        check_cp1_64bitmode(ctx);
T
ths 已提交
6470 6471 6472 6473 6474 6475
        gen_load_fpr32(fpu32_T[0], fs);
        gen_load_fpr32h(fpu32h_T[0], fs);
        gen_load_fpr32(fpu32_T[1], ft);
        gen_load_fpr32h(fpu32h_T[1], ft);
        gen_load_fpr32(fpu32_T[2], fr);
        gen_load_fpr32h(fpu32h_T[2], fr);
6476
        gen_op_float_muladd_ps();
T
ths 已提交
6477 6478
        gen_store_fpr32(fpu32_T[2], fd);
        gen_store_fpr32h(fpu32h_T[2], fd);
6479 6480 6481
        opn = "madd.ps";
        break;
    case OPC_MSUB_S:
6482
        check_cop1x(ctx);
T
ths 已提交
6483 6484 6485
        gen_load_fpr32(fpu32_T[0], fs);
        gen_load_fpr32(fpu32_T[1], ft);
        gen_load_fpr32(fpu32_T[2], fr);
6486
        gen_op_float_mulsub_s();
T
ths 已提交
6487
        gen_store_fpr32(fpu32_T[2], fd);
6488 6489 6490
        opn = "msub.s";
        break;
    case OPC_MSUB_D:
6491 6492
        check_cop1x(ctx);
        check_cp1_registers(ctx, fd | fs | ft | fr);
T
ths 已提交
6493 6494 6495
        gen_load_fpr64(ctx, fpu64_T[0], fs);
        gen_load_fpr64(ctx, fpu64_T[1], ft);
        gen_load_fpr64(ctx, fpu64_T[2], fr);
6496
        gen_op_float_mulsub_d();
T
ths 已提交
6497
        gen_store_fpr64(ctx, fpu64_T[2], fd);
6498 6499 6500
        opn = "msub.d";
        break;
    case OPC_MSUB_PS:
6501
        check_cp1_64bitmode(ctx);
T
ths 已提交
6502 6503 6504 6505 6506 6507
        gen_load_fpr32(fpu32_T[0], fs);
        gen_load_fpr32h(fpu32h_T[0], fs);
        gen_load_fpr32(fpu32_T[1], ft);
        gen_load_fpr32h(fpu32h_T[1], ft);
        gen_load_fpr32(fpu32_T[2], fr);
        gen_load_fpr32h(fpu32h_T[2], fr);
6508
        gen_op_float_mulsub_ps();
T
ths 已提交
6509 6510
        gen_store_fpr32(fpu32_T[2], fd);
        gen_store_fpr32h(fpu32h_T[2], fd);
6511 6512 6513
        opn = "msub.ps";
        break;
    case OPC_NMADD_S:
6514
        check_cop1x(ctx);
T
ths 已提交
6515 6516 6517
        gen_load_fpr32(fpu32_T[0], fs);
        gen_load_fpr32(fpu32_T[1], ft);
        gen_load_fpr32(fpu32_T[2], fr);
6518
        gen_op_float_nmuladd_s();
T
ths 已提交
6519
        gen_store_fpr32(fpu32_T[2], fd);
6520 6521 6522
        opn = "nmadd.s";
        break;
    case OPC_NMADD_D:
6523 6524
        check_cop1x(ctx);
        check_cp1_registers(ctx, fd | fs | ft | fr);
T
ths 已提交
6525 6526 6527
        gen_load_fpr64(ctx, fpu64_T[0], fs);
        gen_load_fpr64(ctx, fpu64_T[1], ft);
        gen_load_fpr64(ctx, fpu64_T[2], fr);
6528
        gen_op_float_nmuladd_d();
T
ths 已提交
6529
        gen_store_fpr64(ctx, fpu64_T[2], fd);
6530 6531 6532
        opn = "nmadd.d";
        break;
    case OPC_NMADD_PS:
6533
        check_cp1_64bitmode(ctx);
T
ths 已提交
6534 6535 6536 6537 6538 6539
        gen_load_fpr32(fpu32_T[0], fs);
        gen_load_fpr32h(fpu32h_T[0], fs);
        gen_load_fpr32(fpu32_T[1], ft);
        gen_load_fpr32h(fpu32h_T[1], ft);
        gen_load_fpr32(fpu32_T[2], fr);
        gen_load_fpr32h(fpu32h_T[2], fr);
6540
        gen_op_float_nmuladd_ps();
T
ths 已提交
6541 6542
        gen_store_fpr32(fpu32_T[2], fd);
        gen_store_fpr32h(fpu32h_T[2], fd);
6543 6544 6545
        opn = "nmadd.ps";
        break;
    case OPC_NMSUB_S:
6546
        check_cop1x(ctx);
T
ths 已提交
6547 6548 6549
        gen_load_fpr32(fpu32_T[0], fs);
        gen_load_fpr32(fpu32_T[1], ft);
        gen_load_fpr32(fpu32_T[2], fr);
6550
        gen_op_float_nmulsub_s();
T
ths 已提交
6551
        gen_store_fpr32(fpu32_T[2], fd);
6552 6553 6554
        opn = "nmsub.s";
        break;
    case OPC_NMSUB_D:
6555 6556
        check_cop1x(ctx);
        check_cp1_registers(ctx, fd | fs | ft | fr);
T
ths 已提交
6557 6558 6559
        gen_load_fpr64(ctx, fpu64_T[0], fs);
        gen_load_fpr64(ctx, fpu64_T[1], ft);
        gen_load_fpr64(ctx, fpu64_T[2], fr);
6560
        gen_op_float_nmulsub_d();
T
ths 已提交
6561
        gen_store_fpr64(ctx, fpu64_T[2], fd);
6562 6563 6564
        opn = "nmsub.d";
        break;
    case OPC_NMSUB_PS:
6565
        check_cp1_64bitmode(ctx);
T
ths 已提交
6566 6567 6568 6569 6570 6571
        gen_load_fpr32(fpu32_T[0], fs);
        gen_load_fpr32h(fpu32h_T[0], fs);
        gen_load_fpr32(fpu32_T[1], ft);
        gen_load_fpr32h(fpu32h_T[1], ft);
        gen_load_fpr32(fpu32_T[2], fr);
        gen_load_fpr32h(fpu32h_T[2], fr);
6572
        gen_op_float_nmulsub_ps();
T
ths 已提交
6573 6574
        gen_store_fpr32(fpu32_T[2], fd);
        gen_store_fpr32h(fpu32h_T[2], fd);
6575 6576
        opn = "nmsub.ps";
        break;
6577 6578
    default:
        MIPS_INVAL(opn);
6579 6580 6581 6582 6583
        generate_exception (ctx, EXCP_RI);
        return;
    }
    MIPS_DEBUG("%s %s, %s, %s, %s", opn, fregnames[fd], fregnames[fr],
               fregnames[fs], fregnames[ft]);
6584 6585 6586
}

/* ISA extensions (ASEs) */
B
bellard 已提交
6587 6588 6589
/* MIPS16 extension to MIPS32 */
/* SmartMIPS extension to MIPS32 */

6590
#if defined(TARGET_MIPS64)
B
bellard 已提交
6591 6592 6593 6594 6595

/* MDMX extension to MIPS64 */

#endif

6596
static void decode_opc (CPUState *env, DisasContext *ctx)
B
bellard 已提交
6597 6598 6599
{
    int32_t offset;
    int rs, rt, rd, sa;
6600
    uint32_t op, op1, op2;
B
bellard 已提交
6601 6602
    int16_t imm;

6603 6604
    /* make sure instructions are on a word boundary */
    if (ctx->pc & 0x3) {
6605
        env->CP0_BadVAddr = ctx->pc;
6606 6607 6608 6609
        generate_exception(ctx, EXCP_AdEL);
        return;
    }

6610
    /* Handle blikely not taken case */
B
bellard 已提交
6611
    if ((ctx->hflags & MIPS_HFLAG_BMASK) == MIPS_HFLAG_BL) {
T
ths 已提交
6612
        TCGv r_tmp = tcg_temp_local_new(TCG_TYPE_TL);
6613 6614
        int l1 = gen_new_label();

T
ths 已提交
6615
        MIPS_DEBUG("blikely condition (" TARGET_FMT_lx ")", ctx->pc + 4);
6616
        tcg_gen_ld_tl(r_tmp, cpu_env, offsetof(CPUState, bcond));
P
pbrook 已提交
6617
        tcg_gen_brcondi_tl(TCG_COND_NE, r_tmp, 0, l1);
T
ths 已提交
6618
        tcg_temp_free(r_tmp);
6619 6620 6621
        gen_op_save_state(ctx->hflags & ~MIPS_HFLAG_BMASK);
        gen_goto_tb(ctx, 1, ctx->pc + 4);
        gen_set_label(l1);
B
bellard 已提交
6622
    }
6623 6624 6625 6626 6627
    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 已提交
6628 6629
    imm = (int16_t)ctx->opcode;
    switch (op) {
6630 6631
    case OPC_SPECIAL:
        op1 = MASK_SPECIAL(ctx->opcode);
B
bellard 已提交
6632
        switch (op1) {
6633 6634
        case OPC_SLL:          /* Arithmetic with immediate */
        case OPC_SRL ... OPC_SRA:
6635
            gen_arith_imm(env, ctx, op1, rd, rt, sa);
6636
            break;
6637 6638
        case OPC_MOVZ ... OPC_MOVN:
            check_insn(env, ctx, ISA_MIPS4 | ISA_MIPS32);
6639 6640 6641 6642
        case OPC_SLLV:         /* Arithmetic */
        case OPC_SRLV ... OPC_SRAV:
        case OPC_ADD ... OPC_NOR:
        case OPC_SLT ... OPC_SLTU:
6643
            gen_arith(env, ctx, op1, rd, rs, rt);
6644 6645
            break;
        case OPC_MULT ... OPC_DIVU:
6646 6647 6648 6649 6650 6651
            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);
6652 6653 6654
            break;
        case OPC_JR ... OPC_JALR:
            gen_compute_branch(ctx, op1, rs, rd, sa);
B
bellard 已提交
6655
            return;
6656 6657 6658
        case OPC_TGE ... OPC_TEQ: /* Traps */
        case OPC_TNE:
            gen_trap(ctx, op1, rs, rt, -1);
B
bellard 已提交
6659
            break;
6660 6661 6662
        case OPC_MFHI:          /* Move from HI/LO */
        case OPC_MFLO:
            gen_HILO(ctx, op1, rd);
B
bellard 已提交
6663
            break;
6664 6665 6666
        case OPC_MTHI:
        case OPC_MTLO:          /* Move to HI/LO */
            gen_HILO(ctx, op1, rs);
B
bellard 已提交
6667
            break;
6668 6669 6670 6671 6672
        case OPC_PMON:          /* Pmon entry point, also R4010 selsl */
#ifdef MIPS_STRICT_STANDARD
            MIPS_INVAL("PMON / selsl");
            generate_exception(ctx, EXCP_RI);
#else
6673
            gen_op_pmon(sa);
6674
#endif
6675 6676
            break;
        case OPC_SYSCALL:
B
bellard 已提交
6677 6678
            generate_exception(ctx, EXCP_SYSCALL);
            break;
6679
        case OPC_BREAK:
B
bellard 已提交
6680 6681
            generate_exception(ctx, EXCP_BREAK);
            break;
6682 6683 6684 6685 6686
        case OPC_SPIM:
#ifdef MIPS_STRICT_STANDARD
            MIPS_INVAL("SPIM");
            generate_exception(ctx, EXCP_RI);
#else
6687 6688 6689
           /* Implemented as RI exception for now. */
            MIPS_INVAL("spim (unofficial)");
            generate_exception(ctx, EXCP_RI);
6690
#endif
B
bellard 已提交
6691
            break;
6692
        case OPC_SYNC:
6693
            /* Treat as NOP. */
B
bellard 已提交
6694
            break;
B
bellard 已提交
6695

6696
        case OPC_MOVCI:
6697
            check_insn(env, ctx, ISA_MIPS4 | ISA_MIPS32);
6698
            if (env->CP0_Config1 & (1 << CP0C1_FP)) {
6699
                save_cpu_state(ctx, 1);
6700
                check_cp1_enabled(ctx);
6701 6702 6703
                gen_movci(ctx, rd, rs, (ctx->opcode >> 18) & 0x7,
                          (ctx->opcode >> 16) & 1);
            } else {
6704
                generate_exception_err(ctx, EXCP_CpU, 1);
6705
            }
B
bellard 已提交
6706 6707
            break;

6708
#if defined(TARGET_MIPS64)
6709 6710 6711 6712 6713
       /* MIPS64 specific opcodes */
        case OPC_DSLL:
        case OPC_DSRL ... OPC_DSRA:
        case OPC_DSLL32:
        case OPC_DSRL32 ... OPC_DSRA32:
6714 6715 6716
            check_insn(env, ctx, ISA_MIPS3);
            check_mips_64(ctx);
            gen_arith_imm(env, ctx, op1, rd, rt, sa);
6717 6718 6719 6720
            break;
        case OPC_DSLLV:
        case OPC_DSRLV ... OPC_DSRAV:
        case OPC_DADD ... OPC_DSUBU:
6721 6722 6723
            check_insn(env, ctx, ISA_MIPS3);
            check_mips_64(ctx);
            gen_arith(env, ctx, op1, rd, rs, rt);
6724 6725
            break;
        case OPC_DMULT ... OPC_DDIVU:
6726 6727
            check_insn(env, ctx, ISA_MIPS3);
            check_mips_64(ctx);
6728 6729
            gen_muldiv(ctx, op1, rs, rt);
            break;
B
bellard 已提交
6730 6731 6732 6733 6734 6735 6736
#endif
        default:            /* Invalid */
            MIPS_INVAL("special");
            generate_exception(ctx, EXCP_RI);
            break;
        }
        break;
6737 6738
    case OPC_SPECIAL2:
        op1 = MASK_SPECIAL2(ctx->opcode);
B
bellard 已提交
6739
        switch (op1) {
6740 6741
        case OPC_MADD ... OPC_MADDU: /* Multiply and add/sub */
        case OPC_MSUB ... OPC_MSUBU:
6742
            check_insn(env, ctx, ISA_MIPS32);
6743
            gen_muldiv(ctx, op1, rs, rt);
B
bellard 已提交
6744
            break;
6745
        case OPC_MUL:
6746
            gen_arith(env, ctx, op1, rd, rs, rt);
B
bellard 已提交
6747
            break;
6748
        case OPC_CLZ ... OPC_CLO:
6749
            check_insn(env, ctx, ISA_MIPS32);
6750
            gen_cl(ctx, op1, rd, rs);
B
bellard 已提交
6751
            break;
6752
        case OPC_SDBBP:
B
bellard 已提交
6753 6754 6755
            /* XXX: not clear which exception should be raised
             *      when in debug mode...
             */
6756
            check_insn(env, ctx, ISA_MIPS32);
B
bellard 已提交
6757 6758 6759 6760 6761
            if (!(ctx->hflags & MIPS_HFLAG_DM)) {
                generate_exception(ctx, EXCP_DBp);
            } else {
                generate_exception(ctx, EXCP_DBp);
            }
6762
            /* Treat as NOP. */
B
bellard 已提交
6763
            break;
6764
#if defined(TARGET_MIPS64)
6765
        case OPC_DCLZ ... OPC_DCLO:
6766 6767
            check_insn(env, ctx, ISA_MIPS64);
            check_mips_64(ctx);
6768 6769 6770
            gen_cl(ctx, op1, rd, rs);
            break;
#endif
B
bellard 已提交
6771 6772 6773 6774 6775 6776
        default:            /* Invalid */
            MIPS_INVAL("special2");
            generate_exception(ctx, EXCP_RI);
            break;
        }
        break;
6777
    case OPC_SPECIAL3:
6778 6779 6780 6781
         op1 = MASK_SPECIAL3(ctx->opcode);
         switch (op1) {
         case OPC_EXT:
         case OPC_INS:
6782
             check_insn(env, ctx, ISA_MIPS32R2);
6783 6784 6785
             gen_bitops(ctx, op1, rt, rs, sa, rd);
             break;
         case OPC_BSHFL:
6786
             check_insn(env, ctx, ISA_MIPS32R2);
6787 6788 6789
             op2 = MASK_BSHFL(ctx->opcode);
             switch (op2) {
             case OPC_WSBH:
6790
                 gen_load_gpr(cpu_T[1], rt);
6791 6792 6793
                 gen_op_wsbh();
                 break;
             case OPC_SEB:
6794
                 gen_load_gpr(cpu_T[1], rt);
6795
                 tcg_gen_ext8s_tl(cpu_T[0], cpu_T[1]);
6796 6797
                 break;
             case OPC_SEH:
6798
                 gen_load_gpr(cpu_T[1], rt);
6799
                 tcg_gen_ext16s_tl(cpu_T[0], cpu_T[1]);
6800 6801 6802 6803 6804 6805
                 break;
             default:            /* Invalid */
                 MIPS_INVAL("bshfl");
                 generate_exception(ctx, EXCP_RI);
                 break;
            }
6806
            gen_store_gpr(cpu_T[0], rd);
6807
            break;
6808
        case OPC_RDHWR:
6809
            check_insn(env, ctx, ISA_MIPS32R2);
6810 6811
            switch (rd) {
            case 0:
6812
                save_cpu_state(ctx, 1);
6813
                gen_op_rdhwr_cpunum();
6814
                break;
6815
            case 1:
6816
                save_cpu_state(ctx, 1);
6817
                gen_op_rdhwr_synci_step();
6818
                break;
6819
            case 2:
6820
                save_cpu_state(ctx, 1);
6821
                gen_op_rdhwr_cc();
6822
                break;
6823
            case 3:
6824
                save_cpu_state(ctx, 1);
6825
                gen_op_rdhwr_ccres();
6826
                break;
6827
            case 29:
6828
#if defined (CONFIG_USER_ONLY)
6829
                gen_op_tls_value();
6830
                break;
6831
#endif
6832 6833 6834 6835 6836
            default:            /* Invalid */
                MIPS_INVAL("rdhwr");
                generate_exception(ctx, EXCP_RI);
                break;
            }
6837
            gen_store_gpr(cpu_T[0], rt);
6838
            break;
6839
        case OPC_FORK:
6840
            check_insn(env, ctx, ASE_MT);
6841 6842
            gen_load_gpr(cpu_T[0], rt);
            gen_load_gpr(cpu_T[1], rs);
6843
            tcg_gen_helper_0_0(do_fork);
6844 6845
            break;
        case OPC_YIELD:
6846
            check_insn(env, ctx, ASE_MT);
6847
            gen_load_gpr(cpu_T[0], rs);
6848
            tcg_gen_helper_0_0(do_yield);
6849
            gen_store_gpr(cpu_T[0], rd);
6850
            break;
6851
#if defined(TARGET_MIPS64)
6852 6853
        case OPC_DEXTM ... OPC_DEXT:
        case OPC_DINSM ... OPC_DINS:
6854 6855
            check_insn(env, ctx, ISA_MIPS64R2);
            check_mips_64(ctx);
6856
            gen_bitops(ctx, op1, rt, rs, sa, rd);
6857
            break;
6858
        case OPC_DBSHFL:
6859 6860
            check_insn(env, ctx, ISA_MIPS64R2);
            check_mips_64(ctx);
6861 6862 6863
            op2 = MASK_DBSHFL(ctx->opcode);
            switch (op2) {
            case OPC_DSBH:
6864
                gen_load_gpr(cpu_T[1], rt);
6865 6866 6867
                gen_op_dsbh();
                break;
            case OPC_DSHD:
6868
                gen_load_gpr(cpu_T[1], rt);
6869 6870
                gen_op_dshd();
                break;
6871 6872 6873 6874
            default:            /* Invalid */
                MIPS_INVAL("dbshfl");
                generate_exception(ctx, EXCP_RI);
                break;
6875
            }
6876
            gen_store_gpr(cpu_T[0], rd);
T
ths 已提交
6877
            break;
6878 6879 6880 6881 6882 6883 6884 6885 6886 6887 6888 6889 6890
#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 已提交
6891
            return;
6892 6893 6894 6895 6896
        case OPC_TGEI ... OPC_TEQI: /* REGIMM traps */
        case OPC_TNEI:
            gen_trap(ctx, op1, rs, -1, imm);
            break;
        case OPC_SYNCI:
6897
            check_insn(env, ctx, ISA_MIPS32R2);
6898
            /* Treat as NOP. */
B
bellard 已提交
6899 6900
            break;
        default:            /* Invalid */
6901
            MIPS_INVAL("regimm");
B
bellard 已提交
6902 6903 6904 6905
            generate_exception(ctx, EXCP_RI);
            break;
        }
        break;
6906
    case OPC_CP0:
6907
        check_cp0_enabled(ctx);
6908
        op1 = MASK_CP0(ctx->opcode);
B
bellard 已提交
6909
        switch (op1) {
6910 6911
        case OPC_MFC0:
        case OPC_MTC0:
6912 6913
        case OPC_MFTR:
        case OPC_MTTR:
6914
#if defined(TARGET_MIPS64)
6915 6916 6917
        case OPC_DMFC0:
        case OPC_DMTC0:
#endif
6918
#ifndef CONFIG_USER_ONLY
6919
            gen_cp0(env, ctx, op1, rt, rd);
6920
#endif
6921 6922
            break;
        case OPC_C0_FIRST ... OPC_C0_LAST:
6923
#ifndef CONFIG_USER_ONLY
6924
            gen_cp0(env, ctx, MASK_C0(ctx->opcode), rt, rd);
6925
#endif
6926 6927 6928 6929
            break;
        case OPC_MFMC0:
            op2 = MASK_MFMC0(ctx->opcode);
            switch (op2) {
6930
            case OPC_DMT:
6931
                check_insn(env, ctx, ASE_MT);
6932
                tcg_gen_helper_0_0(do_dmt);
6933 6934
                break;
            case OPC_EMT:
6935
                check_insn(env, ctx, ASE_MT);
6936
                tcg_gen_helper_0_0(do_emt);
6937 6938
                break;
            case OPC_DVPE:
6939
                check_insn(env, ctx, ASE_MT);
6940
                tcg_gen_helper_0_0(do_dvpe);
6941 6942
                break;
            case OPC_EVPE:
6943
                check_insn(env, ctx, ASE_MT);
6944
                tcg_gen_helper_0_0(do_evpe);
6945
                break;
6946
            case OPC_DI:
6947
                check_insn(env, ctx, ISA_MIPS32R2);
6948
                save_cpu_state(ctx, 1);
6949 6950 6951 6952 6953
                gen_op_di();
                /* Stop translation as we may have switched the execution mode */
                ctx->bstate = BS_STOP;
                break;
            case OPC_EI:
6954
                check_insn(env, ctx, ISA_MIPS32R2);
6955
                save_cpu_state(ctx, 1);
6956 6957 6958 6959 6960
                gen_op_ei();
                /* Stop translation as we may have switched the execution mode */
                ctx->bstate = BS_STOP;
                break;
            default:            /* Invalid */
6961
                MIPS_INVAL("mfmc0");
6962 6963 6964
                generate_exception(ctx, EXCP_RI);
                break;
            }
6965
            gen_store_gpr(cpu_T[0], rt);
B
bellard 已提交
6966
            break;
6967
        case OPC_RDPGPR:
6968
            check_insn(env, ctx, ISA_MIPS32R2);
6969 6970
            gen_load_srsgpr(cpu_T[0], rt);
            gen_store_gpr(cpu_T[0], rd);
6971
            break;
6972
        case OPC_WRPGPR:
6973
            check_insn(env, ctx, ISA_MIPS32R2);
6974 6975
            gen_load_gpr(cpu_T[0], rt);
            gen_store_srsgpr(cpu_T[0], rd);
6976
            break;
B
bellard 已提交
6977
        default:
6978
            MIPS_INVAL("cp0");
6979
            generate_exception(ctx, EXCP_RI);
B
bellard 已提交
6980 6981 6982
            break;
        }
        break;
6983
    case OPC_ADDI ... OPC_LUI: /* Arithmetic with immediate opcode */
6984
         gen_arith_imm(env, ctx, op, rt, rs, imm);
6985 6986 6987 6988 6989 6990 6991 6992 6993 6994 6995 6996 6997 6998 6999 7000 7001
         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:
7002
        check_insn(env, ctx, ISA_MIPS3 | ISA_MIPS32);
7003
        /* Treat as NOP. */
7004
        break;
7005
    case OPC_PREF:
7006
        check_insn(env, ctx, ISA_MIPS4 | ISA_MIPS32);
7007
        /* Treat as NOP. */
B
bellard 已提交
7008
        break;
B
bellard 已提交
7009

7010
    /* Floating point (COP1). */
7011 7012 7013 7014
    case OPC_LWC1:
    case OPC_LDC1:
    case OPC_SWC1:
    case OPC_SDC1:
7015 7016
        if (env->CP0_Config1 & (1 << CP0C1_FP)) {
            save_cpu_state(ctx, 1);
7017
            check_cp1_enabled(ctx);
7018 7019 7020 7021
            gen_flt_ldst(ctx, op, rt, rs, imm);
        } else {
            generate_exception_err(ctx, EXCP_CpU, 1);
        }
B
bellard 已提交
7022 7023
        break;

7024
    case OPC_CP1:
7025 7026
        if (env->CP0_Config1 & (1 << CP0C1_FP)) {
            save_cpu_state(ctx, 1);
7027
            check_cp1_enabled(ctx);
7028 7029
            op1 = MASK_CP1(ctx->opcode);
            switch (op1) {
7030 7031
            case OPC_MFHC1:
            case OPC_MTHC1:
7032
                check_insn(env, ctx, ISA_MIPS32R2);
7033 7034 7035 7036
            case OPC_MFC1:
            case OPC_CFC1:
            case OPC_MTC1:
            case OPC_CTC1:
7037 7038
                gen_cp1(ctx, op1, rt, rd);
                break;
7039
#if defined(TARGET_MIPS64)
7040 7041
            case OPC_DMFC1:
            case OPC_DMTC1:
7042
                check_insn(env, ctx, ISA_MIPS3);
7043 7044
                gen_cp1(ctx, op1, rt, rd);
                break;
7045
#endif
7046 7047
            case OPC_BC1ANY2:
            case OPC_BC1ANY4:
7048
                check_cop1x(ctx);
7049
                check_insn(env, ctx, ASE_MIPS3D);
7050 7051
                /* fall through */
            case OPC_BC1:
7052
                gen_compute_branch1(env, ctx, MASK_BC1(ctx->opcode),
7053
                                    (rt >> 2) & 0x7, imm << 2);
7054 7055 7056 7057 7058
                return;
            case OPC_S_FMT:
            case OPC_D_FMT:
            case OPC_W_FMT:
            case OPC_L_FMT:
7059 7060 7061
            case OPC_PS_FMT:
                gen_farith(ctx, MASK_CP1_FUNC(ctx->opcode), rt, rd, sa,
                           (imm >> 8) & 0x7);
7062 7063
                break;
            default:
7064
                MIPS_INVAL("cp1");
7065
                generate_exception (ctx, EXCP_RI);
7066 7067 7068 7069
                break;
            }
        } else {
            generate_exception_err(ctx, EXCP_CpU, 1);
B
bellard 已提交
7070
        }
B
bellard 已提交
7071 7072 7073
        break;

    /* COP2.  */
7074 7075 7076 7077 7078 7079
    case OPC_LWC2:
    case OPC_LDC2:
    case OPC_SWC2:
    case OPC_SDC2:
    case OPC_CP2:
        /* COP2: Not implemented. */
B
bellard 已提交
7080 7081 7082
        generate_exception_err(ctx, EXCP_CpU, 2);
        break;

7083
    case OPC_CP3:
7084
        if (env->CP0_Config1 & (1 << CP0C1_FP)) {
7085
            save_cpu_state(ctx, 1);
7086
            check_cp1_enabled(ctx);
7087 7088
            op1 = MASK_CP3(ctx->opcode);
            switch (op1) {
7089 7090 7091 7092 7093 7094
            case OPC_LWXC1:
            case OPC_LDXC1:
            case OPC_LUXC1:
            case OPC_SWXC1:
            case OPC_SDXC1:
            case OPC_SUXC1:
T
ths 已提交
7095
                gen_flt3_ldst(ctx, op1, sa, rd, rs, rt);
7096
                break;
T
ths 已提交
7097
            case OPC_PREFX:
7098
                /* Treat as NOP. */
T
ths 已提交
7099
                break;
7100 7101 7102 7103 7104 7105 7106 7107 7108 7109 7110 7111 7112 7113 7114
            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;
7115
            default:
7116
                MIPS_INVAL("cp3");
7117
                generate_exception (ctx, EXCP_RI);
7118 7119 7120
                break;
            }
        } else {
7121
            generate_exception_err(ctx, EXCP_CpU, 1);
7122
        }
B
bellard 已提交
7123 7124
        break;

7125
#if defined(TARGET_MIPS64)
7126 7127 7128 7129 7130 7131 7132 7133
    /* 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:
7134 7135
        check_insn(env, ctx, ISA_MIPS3);
        check_mips_64(ctx);
7136 7137 7138
        gen_ldst(ctx, op, rt, rs, imm);
        break;
    case OPC_DADDI ... OPC_DADDIU:
7139 7140 7141
        check_insn(env, ctx, ISA_MIPS3);
        check_mips_64(ctx);
        gen_arith_imm(env, ctx, op, rt, rs, imm);
7142
        break;
B
bellard 已提交
7143
#endif
7144
    case OPC_JALX:
7145
        check_insn(env, ctx, ASE_MIPS16);
7146 7147
        /* MIPS16: Not implemented. */
    case OPC_MDMX:
7148
        check_insn(env, ctx, ASE_MDMX);
7149
        /* MDMX: Not implemented. */
B
bellard 已提交
7150
    default:            /* Invalid */
7151
        MIPS_INVAL("major opcode");
B
bellard 已提交
7152 7153 7154
        generate_exception(ctx, EXCP_RI);
        break;
    }
B
bellard 已提交
7155
    if (ctx->hflags & MIPS_HFLAG_BMASK) {
T
ths 已提交
7156
        int hflags = ctx->hflags & MIPS_HFLAG_BMASK;
B
bellard 已提交
7157
        /* Branches completion */
B
bellard 已提交
7158
        ctx->hflags &= ~MIPS_HFLAG_BMASK;
B
bellard 已提交
7159 7160
        ctx->bstate = BS_BRANCH;
        save_cpu_state(ctx, 0);
7161
        switch (hflags) {
B
bellard 已提交
7162 7163 7164
        case MIPS_HFLAG_B:
            /* unconditional branch */
            MIPS_DEBUG("unconditional branch");
7165
            gen_goto_tb(ctx, 0, ctx->btarget);
B
bellard 已提交
7166 7167 7168 7169
            break;
        case MIPS_HFLAG_BL:
            /* blikely taken case */
            MIPS_DEBUG("blikely branch taken");
7170
            gen_goto_tb(ctx, 0, ctx->btarget);
B
bellard 已提交
7171 7172 7173 7174
            break;
        case MIPS_HFLAG_BC:
            /* Conditional branch */
            MIPS_DEBUG("conditional branch");
B
bellard 已提交
7175
            {
T
ths 已提交
7176
                TCGv r_tmp = tcg_temp_local_new(TCG_TYPE_TL);
7177 7178 7179
                int l1 = gen_new_label();

                tcg_gen_ld_tl(r_tmp, cpu_env, offsetof(CPUState, bcond));
P
pbrook 已提交
7180
                tcg_gen_brcondi_tl(TCG_COND_NE, r_tmp, 0, l1);
T
ths 已提交
7181
                tcg_temp_free(r_tmp);
7182 7183 7184
                gen_goto_tb(ctx, 1, ctx->pc + 4);
                gen_set_label(l1);
                gen_goto_tb(ctx, 0, ctx->btarget);
B
bellard 已提交
7185
            }
B
bellard 已提交
7186 7187 7188 7189
            break;
        case MIPS_HFLAG_BR:
            /* unconditional branch to register */
            MIPS_DEBUG("branch to register");
7190
            gen_breg_pc();
B
bellard 已提交
7191
            tcg_gen_exit_tb(0);
B
bellard 已提交
7192 7193 7194 7195 7196 7197 7198 7199
            break;
        default:
            MIPS_DEBUG("unknown branch");
            break;
        }
    }
}

7200
static always_inline int
7201 7202
gen_intermediate_code_internal (CPUState *env, TranslationBlock *tb,
                                int search_pc)
B
bellard 已提交
7203
{
T
ths 已提交
7204
    DisasContext ctx;
B
bellard 已提交
7205 7206 7207 7208
    target_ulong pc_start;
    uint16_t *gen_opc_end;
    int j, lj = -1;

B
bellard 已提交
7209
    if (search_pc && loglevel)
B
bellard 已提交
7210
        fprintf (logfile, "search pc %d\n", search_pc);
B
bellard 已提交
7211

B
bellard 已提交
7212
    pc_start = tb->pc;
T
ths 已提交
7213 7214
    /* Leave some spare opc slots for branch handling. */
    gen_opc_end = gen_opc_buf + OPC_MAX_SIZE - 16;
B
bellard 已提交
7215
    ctx.pc = pc_start;
B
bellard 已提交
7216
    ctx.saved_pc = -1;
B
bellard 已提交
7217 7218
    ctx.tb = tb;
    ctx.bstate = BS_NONE;
B
bellard 已提交
7219
    /* Restore delay slot state from the tb context.  */
7220
    ctx.hflags = (uint32_t)tb->flags; /* FIXME: maybe use 64 bits here? */
7221
    restore_cpu_state(env, &ctx);
B
bellard 已提交
7222
#if defined(CONFIG_USER_ONLY)
T
ths 已提交
7223
    ctx.mem_idx = MIPS_HFLAG_UM;
B
bellard 已提交
7224
#else
T
ths 已提交
7225
    ctx.mem_idx = ctx.hflags & MIPS_HFLAG_KSU;
B
bellard 已提交
7226 7227 7228 7229
#endif
#ifdef DEBUG_DISAS
    if (loglevel & CPU_LOG_TB_CPU) {
        fprintf(logfile, "------------------------------------------------\n");
B
bellard 已提交
7230
        /* FIXME: This may print out stale hflags from env... */
B
bellard 已提交
7231 7232 7233
        cpu_dump_state(env, logfile, fprintf, 0);
    }
#endif
7234
#ifdef MIPS_DEBUG_DISAS
B
bellard 已提交
7235
    if (loglevel & CPU_LOG_TB_IN_ASM)
T
ths 已提交
7236
        fprintf(logfile, "\ntb %p idx %d hflags %04x\n",
B
bellard 已提交
7237
                tb, ctx.mem_idx, ctx.hflags);
B
bellard 已提交
7238
#endif
T
ths 已提交
7239
    while (ctx.bstate == BS_NONE) {
B
bellard 已提交
7240 7241 7242
        if (env->nb_breakpoints > 0) {
            for(j = 0; j < env->nb_breakpoints; j++) {
                if (env->breakpoints[j] == ctx.pc) {
T
ths 已提交
7243
                    save_cpu_state(&ctx, 1);
B
bellard 已提交
7244 7245
                    ctx.bstate = BS_BRANCH;
                    gen_op_debug();
7246 7247 7248
                    /* Include the breakpoint location or the tb won't
                     * be flushed when it must be.  */
                    ctx.pc += 4;
B
bellard 已提交
7249 7250 7251 7252 7253
                    goto done_generating;
                }
            }
        }

B
bellard 已提交
7254 7255 7256 7257 7258 7259 7260
        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 已提交
7261 7262 7263
            gen_opc_pc[lj] = ctx.pc;
            gen_opc_hflags[lj] = ctx.hflags & MIPS_HFLAG_BMASK;
            gen_opc_instr_start[lj] = 1;
B
bellard 已提交
7264 7265
        }
        ctx.opcode = ldl_code(ctx.pc);
7266
        decode_opc(env, &ctx);
B
bellard 已提交
7267
        ctx.pc += 4;
B
bellard 已提交
7268 7269 7270 7271

        if (env->singlestep_enabled)
            break;

B
bellard 已提交
7272 7273
        if ((ctx.pc & (TARGET_PAGE_SIZE - 1)) == 0)
            break;
B
bellard 已提交
7274

T
ths 已提交
7275 7276 7277
        if (gen_opc_ptr >= gen_opc_end)
            break;

T
ths 已提交
7278 7279 7280
        if (gen_opc_ptr >= gen_opc_end)
            break;

B
bellard 已提交
7281 7282 7283 7284
#if defined (MIPS_SINGLE_STEP)
        break;
#endif
    }
B
bellard 已提交
7285
    if (env->singlestep_enabled) {
T
ths 已提交
7286
        save_cpu_state(&ctx, ctx.bstate == BS_NONE);
B
bellard 已提交
7287
        gen_op_debug();
T
ths 已提交
7288 7289 7290
    } else {
	switch (ctx.bstate) {
        case BS_STOP:
7291
            tcg_gen_helper_0_0(do_interrupt_restart);
7292 7293
            gen_goto_tb(&ctx, 0, ctx.pc);
            break;
T
ths 已提交
7294
        case BS_NONE:
T
ths 已提交
7295
            save_cpu_state(&ctx, 0);
T
ths 已提交
7296 7297
            gen_goto_tb(&ctx, 0, ctx.pc);
            break;
7298
        case BS_EXCP:
7299
            tcg_gen_helper_0_0(do_interrupt_restart);
B
bellard 已提交
7300
            tcg_gen_exit_tb(0);
T
ths 已提交
7301
            break;
7302 7303 7304
        case BS_BRANCH:
        default:
            break;
T
ths 已提交
7305
	}
B
bellard 已提交
7306
    }
B
bellard 已提交
7307
done_generating:
B
bellard 已提交
7308 7309 7310 7311 7312 7313 7314 7315 7316 7317 7318 7319 7320 7321 7322 7323
    *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;
    }
#ifdef DEBUG_DISAS
#if defined MIPS_DEBUG_DISAS
    if (loglevel & CPU_LOG_TB_IN_ASM)
        fprintf(logfile, "\n");
#endif
    if (loglevel & CPU_LOG_TB_IN_ASM) {
        fprintf(logfile, "IN: %s\n", lookup_symbol(pc_start));
T
ths 已提交
7324
        target_disas(logfile, pc_start, ctx.pc - pc_start, 0);
B
bellard 已提交
7325 7326 7327 7328 7329 7330
        fprintf(logfile, "\n");
    }
    if (loglevel & CPU_LOG_TB_CPU) {
        fprintf(logfile, "---------------- %d %08x\n", ctx.bstate, ctx.hflags);
    }
#endif
7331

B
bellard 已提交
7332 7333 7334 7335 7336 7337 7338 7339 7340 7341 7342 7343 7344
    return 0;
}

int gen_intermediate_code (CPUState *env, struct TranslationBlock *tb)
{
    return gen_intermediate_code_internal(env, tb, 0);
}

int gen_intermediate_code_pc (CPUState *env, struct TranslationBlock *tb)
{
    return gen_intermediate_code_internal(env, tb, 1);
}

7345
void fpu_dump_state(CPUState *env, FILE *f,
B
bellard 已提交
7346 7347 7348 7349
                    int (*fpu_fprintf)(FILE *f, const char *fmt, ...),
                    int flags)
{
    int i;
7350
    int is_fpu64 = !!(env->hflags & MIPS_HFLAG_F64);
7351 7352 7353 7354 7355 7356 7357 7358 7359 7360 7361 7362 7363 7364 7365

#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 已提交
7366 7367
    } while(0)

7368 7369

    fpu_fprintf(f, "CP1 FCR0 0x%08x  FCR31 0x%08x  SR.FR %d  fp_status 0x%08x(0x%02x)\n",
7370 7371
                env->fpu->fcr0, env->fpu->fcr31, is_fpu64, env->fpu->fp_status,
                get_float_exception_flags(&env->fpu->fp_status));
T
ths 已提交
7372 7373 7374
    fpu_fprintf(f, "FT0: "); printfpr(&env->ft0);
    fpu_fprintf(f, "FT1: "); printfpr(&env->ft1);
    fpu_fprintf(f, "FT2: "); printfpr(&env->ft2);
7375 7376
    for (i = 0; i < 32; (is_fpu64) ? i++ : (i += 2)) {
        fpu_fprintf(f, "%3s: ", fregnames[i]);
7377
        printfpr(&env->fpu->fpr[i]);
B
bellard 已提交
7378 7379 7380 7381 7382
    }

#undef printfpr
}

7383
void dump_fpu (CPUState *env)
B
bellard 已提交
7384
{
7385
    if (loglevel) {
T
ths 已提交
7386 7387 7388 7389 7390 7391 7392
        fprintf(logfile,
                "pc=0x" TARGET_FMT_lx " HI=0x" TARGET_FMT_lx
                " LO=0x" TARGET_FMT_lx " ds %04x " TARGET_FMT_lx
                " %04x\n",
                env->PC[env->current_tc], env->HI[env->current_tc][0],
                env->LO[env->current_tc][0], env->hflags, env->btarget,
                env->bcond);
B
bellard 已提交
7393 7394 7395 7396
       fpu_dump_state(env, logfile, fprintf, 0);
    }
}

7397
#if defined(TARGET_MIPS64) && defined(MIPS_DEBUG_SIGN_EXTENSIONS)
7398 7399 7400 7401 7402 7403 7404 7405 7406 7407 7408
/* Debug help: The architecture requires 32bit code to maintain proper
   sign-extened values on 64bit machines.  */

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

void cpu_mips_check_sign_extensions (CPUState *env, FILE *f,
                     int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
                     int flags)
{
    int i;

7409 7410
    if (!SIGN_EXT_P(env->PC[env->current_tc]))
        cpu_fprintf(f, "BROKEN: pc=0x" TARGET_FMT_lx "\n", env->PC[env->current_tc]);
7411 7412 7413 7414
    if (!SIGN_EXT_P(env->HI[env->current_tc][0]))
        cpu_fprintf(f, "BROKEN: HI=0x" TARGET_FMT_lx "\n", env->HI[env->current_tc][0]);
    if (!SIGN_EXT_P(env->LO[env->current_tc][0]))
        cpu_fprintf(f, "BROKEN: LO=0x" TARGET_FMT_lx "\n", env->LO[env->current_tc][0]);
7415
    if (!SIGN_EXT_P(env->btarget))
T
ths 已提交
7416
        cpu_fprintf(f, "BROKEN: btarget=0x" TARGET_FMT_lx "\n", env->btarget);
7417 7418

    for (i = 0; i < 32; i++) {
7419 7420
        if (!SIGN_EXT_P(env->gpr[env->current_tc][i]))
            cpu_fprintf(f, "BROKEN: %s=0x" TARGET_FMT_lx "\n", regnames[i], env->gpr[env->current_tc][i]);
7421 7422 7423
    }

    if (!SIGN_EXT_P(env->CP0_EPC))
T
ths 已提交
7424
        cpu_fprintf(f, "BROKEN: EPC=0x" TARGET_FMT_lx "\n", env->CP0_EPC);
7425
    if (!SIGN_EXT_P(env->CP0_LLAddr))
T
ths 已提交
7426
        cpu_fprintf(f, "BROKEN: LLAddr=0x" TARGET_FMT_lx "\n", env->CP0_LLAddr);
7427 7428 7429
}
#endif

7430
void cpu_dump_state (CPUState *env, FILE *f,
B
bellard 已提交
7431 7432 7433 7434
                     int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
                     int flags)
{
    int i;
7435

T
ths 已提交
7436
    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",
7437
                env->PC[env->current_tc], env->HI[env->current_tc], env->LO[env->current_tc], env->hflags, env->btarget, env->bcond);
B
bellard 已提交
7438 7439 7440
    for (i = 0; i < 32; i++) {
        if ((i & 3) == 0)
            cpu_fprintf(f, "GPR%02d:", i);
7441
        cpu_fprintf(f, " %s " TARGET_FMT_lx, regnames[i], env->gpr[env->current_tc][i]);
B
bellard 已提交
7442 7443 7444
        if ((i & 3) == 3)
            cpu_fprintf(f, "\n");
    }
7445

T
ths 已提交
7446
    cpu_fprintf(f, "CP0 Status  0x%08x Cause   0x%08x EPC    0x" TARGET_FMT_lx "\n",
7447
                env->CP0_Status, env->CP0_Cause, env->CP0_EPC);
T
ths 已提交
7448
    cpu_fprintf(f, "    Config0 0x%08x Config1 0x%08x LLAddr 0x" TARGET_FMT_lx "\n",
B
bellard 已提交
7449
                env->CP0_Config0, env->CP0_Config1, env->CP0_LLAddr);
7450
    if (env->hflags & MIPS_HFLAG_FPU)
7451
        fpu_dump_state(env, f, cpu_fprintf, flags);
7452
#if defined(TARGET_MIPS64) && defined(MIPS_DEBUG_SIGN_EXTENSIONS)
7453 7454
    cpu_mips_check_sign_extensions(env, f, cpu_fprintf, flags);
#endif
B
bellard 已提交
7455 7456
}

7457 7458 7459 7460 7461 7462 7463 7464 7465
static void mips_tcg_init(void)
{
    static int inited;

    /* Initialize various static tables. */
    if (inited)
	return;

    cpu_env = tcg_global_reg_new(TCG_TYPE_PTR, TCG_AREG0, "env");
T
ths 已提交
7466 7467 7468 7469
    current_tc_gprs = tcg_global_mem_new(TCG_TYPE_PTR,
                                         TCG_AREG0,
                                         offsetof(CPUState, current_tc_gprs),
                                         "current_tc_gprs");
7470 7471 7472 7473
    current_tc_hi = tcg_global_mem_new(TCG_TYPE_PTR,
                                       TCG_AREG0,
                                       offsetof(CPUState, current_tc_hi),
                                       "current_tc_hi");
T
ths 已提交
7474 7475 7476 7477
    current_fpu = tcg_global_mem_new(TCG_TYPE_PTR,
                                     TCG_AREG0,
                                     offsetof(CPUState, fpu),
                                     "current_fpu");
7478 7479 7480 7481 7482 7483
#if TARGET_LONG_BITS > HOST_LONG_BITS
    cpu_T[0] = tcg_global_mem_new(TCG_TYPE_TL,
                                  TCG_AREG0, offsetof(CPUState, t0), "T0");
    cpu_T[1] = tcg_global_mem_new(TCG_TYPE_TL,
                                  TCG_AREG0, offsetof(CPUState, t1), "T1");
#else
T
ths 已提交
7484 7485
    cpu_T[0] = tcg_global_reg_new(TCG_TYPE_TL, TCG_AREG1, "T0");
    cpu_T[1] = tcg_global_reg_new(TCG_TYPE_TL, TCG_AREG2, "T1");
7486 7487
#endif

T
ths 已提交
7488 7489 7490 7491 7492
    /* register helpers */
#undef DEF_HELPER
#define DEF_HELPER(ret, name, params) tcg_register_helper(name, #name);
#include "helper.h"

T
ths 已提交
7493 7494 7495 7496 7497 7498 7499 7500 7501 7502
    fpu32_T[0] = tcg_global_mem_new(TCG_TYPE_I32, TCG_AREG0, offsetof(CPUState, ft0.w[FP_ENDIAN_IDX]), "WT0");
    fpu32_T[1] = tcg_global_mem_new(TCG_TYPE_I32, TCG_AREG0, offsetof(CPUState, ft1.w[FP_ENDIAN_IDX]), "WT1");
    fpu32_T[2] = tcg_global_mem_new(TCG_TYPE_I32, TCG_AREG0, offsetof(CPUState, ft2.w[FP_ENDIAN_IDX]), "WT2");
    fpu64_T[0] = tcg_global_mem_new(TCG_TYPE_I64, TCG_AREG0, offsetof(CPUState, ft0.d), "DT0");
    fpu64_T[1] = tcg_global_mem_new(TCG_TYPE_I64, TCG_AREG0, offsetof(CPUState, ft1.d), "DT1");
    fpu64_T[2] = tcg_global_mem_new(TCG_TYPE_I64, TCG_AREG0, offsetof(CPUState, ft2.d), "DT2");
    fpu32h_T[0] = tcg_global_mem_new(TCG_TYPE_I32, TCG_AREG0, offsetof(CPUState, ft0.w[!FP_ENDIAN_IDX]), "WTH0");
    fpu32h_T[1] = tcg_global_mem_new(TCG_TYPE_I32, TCG_AREG0, offsetof(CPUState, ft1.w[!FP_ENDIAN_IDX]), "WTH1");
    fpu32h_T[2] = tcg_global_mem_new(TCG_TYPE_I32, TCG_AREG0, offsetof(CPUState, ft2.w[!FP_ENDIAN_IDX]), "WTH2");

7503 7504 7505
    inited = 1;
}

B
bellard 已提交
7506 7507 7508
#include "translate_init.c"

CPUMIPSState *cpu_mips_init (const char *cpu_model)
B
bellard 已提交
7509 7510
{
    CPUMIPSState *env;
B
bellard 已提交
7511
    const mips_def_t *def;
B
bellard 已提交
7512

B
bellard 已提交
7513 7514 7515
    def = cpu_mips_find_by_name(cpu_model);
    if (!def)
        return NULL;
B
bellard 已提交
7516 7517 7518
    env = qemu_mallocz(sizeof(CPUMIPSState));
    if (!env)
        return NULL;
B
bellard 已提交
7519 7520
    env->cpu_model = def;

B
bellard 已提交
7521
    cpu_exec_init(env);
7522
    env->cpu_model_str = cpu_model;
7523
    mips_tcg_init();
7524 7525 7526 7527 7528 7529 7530 7531
    cpu_reset(env);
    return env;
}

void cpu_reset (CPUMIPSState *env)
{
    memset(env, 0, offsetof(CPUMIPSState, breakpoints));

B
bellard 已提交
7532
    tlb_flush(env, 1);
7533

B
bellard 已提交
7534
    /* Minimal init */
7535
#if !defined(CONFIG_USER_ONLY)
7536 7537 7538
    if (env->hflags & MIPS_HFLAG_BMASK) {
        /* If the exception was raised from a delay slot,
         * come back to the jump.  */
7539
        env->CP0_ErrorEPC = env->PC[env->current_tc] - 4;
7540
    } else {
7541
        env->CP0_ErrorEPC = env->PC[env->current_tc];
7542
    }
7543
    env->PC[env->current_tc] = (int32_t)0xBFC00000;
B
bellard 已提交
7544
    env->CP0_Wired = 0;
7545
    /* SMP not implemented */
7546
    env->CP0_EBase = 0x80000000;
7547
    env->CP0_Status = (1 << CP0St_BEV) | (1 << CP0St_ERL);
T
ths 已提交
7548 7549 7550
    /* vectored interrupts not implemented, timer on int 7,
       no performance counters. */
    env->CP0_IntCtl = 0xe0000000;
7551 7552 7553 7554 7555 7556 7557 7558 7559 7560
    {
        int i;

        for (i = 0; i < 7; i++) {
            env->CP0_WatchLo[i] = 0;
            env->CP0_WatchHi[i] = 0x80000000;
        }
        env->CP0_WatchLo[7] = 0;
        env->CP0_WatchHi[7] = 0;
    }
B
bellard 已提交
7561 7562
    /* Count register increments in debug mode, EJTAG version 1 */
    env->CP0_Debug = (1 << CP0DB_CNT) | (0x1 << CP0DB_VER);
7563
#endif
B
bellard 已提交
7564
    env->exception_index = EXCP_NONE;
7565
#if defined(CONFIG_USER_ONLY)
7566
    env->hflags = MIPS_HFLAG_UM;
7567
    env->user_mode_only = 1;
7568 7569
#else
    env->hflags = MIPS_HFLAG_CP0;
B
bellard 已提交
7570
#endif
B
bellard 已提交
7571
    cpu_mips_register(env, env->cpu_model);
B
bellard 已提交
7572
}
A
aurel32 已提交
7573 7574 7575 7576 7577 7578 7579 7580

void gen_pc_load(CPUState *env, TranslationBlock *tb,
                unsigned long searched_pc, int pc_pos, void *puc)
{
    env->PC[env->current_tc] = gen_opc_pc[pc_pos];
    env->hflags &= ~MIPS_HFLAG_BMASK;
    env->hflags |= gen_opc_hflags[pc_pos];
}