translate.c 241.3 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 634 635 636 637 638 639 640 641 642 643 644 645 646 647
static inline void get_fp_cond (TCGv t)
{
    TCGv r_tmp1 = tcg_temp_new(TCG_TYPE_I32);
    TCGv r_tmp2 = tcg_temp_new(TCG_TYPE_I32);

    tcg_gen_ld_i32(r_tmp1, current_fpu, offsetof(CPUMIPSFPUContext, fcr31));
    tcg_gen_shri_i32(r_tmp2, r_tmp1, 24);
    tcg_gen_andi_i32(r_tmp2, r_tmp2, 0xfe);
    tcg_gen_shri_i32(r_tmp1, r_tmp1, 23);
    tcg_gen_andi_i32(r_tmp1, r_tmp1, 0x1);
    tcg_gen_or_i32(t, r_tmp1, r_tmp2);
    tcg_temp_free(r_tmp1);
    tcg_temp_free(r_tmp2);
}

648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669
#define FOP_CONDS(type, fmt)                                              \
static GenOpFunc1 * fcmp ## type ## _ ## fmt ## _table[16] = {            \
    do_cmp ## type ## _ ## fmt ## _f,                                     \
    do_cmp ## type ## _ ## fmt ## _un,                                    \
    do_cmp ## type ## _ ## fmt ## _eq,                                    \
    do_cmp ## type ## _ ## fmt ## _ueq,                                   \
    do_cmp ## type ## _ ## fmt ## _olt,                                   \
    do_cmp ## type ## _ ## fmt ## _ult,                                   \
    do_cmp ## type ## _ ## fmt ## _ole,                                   \
    do_cmp ## type ## _ ## fmt ## _ule,                                   \
    do_cmp ## type ## _ ## fmt ## _sf,                                    \
    do_cmp ## type ## _ ## fmt ## _ngle,                                  \
    do_cmp ## type ## _ ## fmt ## _seq,                                   \
    do_cmp ## type ## _ ## fmt ## _ngl,                                   \
    do_cmp ## type ## _ ## fmt ## _lt,                                    \
    do_cmp ## type ## _ ## fmt ## _nge,                                   \
    do_cmp ## type ## _ ## fmt ## _le,                                    \
    do_cmp ## type ## _ ## fmt ## _ngt,                                   \
};                                                                        \
static inline void gen_cmp ## type ## _ ## fmt(int n, long cc)            \
{                                                                         \
    tcg_gen_helper_0_1i(fcmp ## type ## _ ## fmt ## _table[n], cc);       \
B
bellard 已提交
670 671
}

672 673 674 675 676 677
FOP_CONDS(, d)
FOP_CONDS(abs, d)
FOP_CONDS(, s)
FOP_CONDS(abs, s)
FOP_CONDS(, ps)
FOP_CONDS(abs, ps)
678
#undef FOP_CONDS
B
bellard 已提交
679

680 681 682 683 684 685 686 687
/* 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);          \
688
    tcg_gen_movi_tl(cpu_T[0], 0);                             \
689 690
    tcg_gen_br(l2);                                           \
    gen_set_label(l1);                                        \
691
    tcg_gen_movi_tl(cpu_T[0], 1);                             \
692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707
    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 已提交
708
    tcg_gen_brcondi_tl(cond, cpu_T[0], val, l1);              \
709
    tcg_gen_movi_tl(cpu_T[0], 0);                             \
710 711
    tcg_gen_br(l2);                                           \
    gen_set_label(l1);                                        \
712
    tcg_gen_movi_tl(cpu_T[0], 1);                             \
713 714 715 716 717 718 719 720 721 722 723 724
    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 已提交
725
    tcg_gen_brcondi_tl(cond, cpu_T[0], 0, l1);                \
726
    tcg_gen_movi_tl(cpu_T[0], 0);                             \
727 728
    tcg_gen_br(l2);                                           \
    gen_set_label(l1);                                        \
729
    tcg_gen_movi_tl(cpu_T[0], 1);                             \
730 731 732 733 734 735 736 737
    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

738 739 740
static inline void gen_save_pc(target_ulong pc)
{
    TCGv r_tmp = tcg_temp_new(TCG_TYPE_TL);
741
    TCGv r_tc_off = tcg_temp_new(TCG_TYPE_I32);
742
    TCGv r_tc_off_ptr = tcg_temp_new(TCG_TYPE_PTR);
743 744 745 746 747
    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));
748 749
    tcg_gen_ext_i32_ptr(r_tc_off_ptr, r_tc_off);
    tcg_gen_add_ptr(r_ptr, cpu_env, r_tc_off_ptr);
750
    tcg_gen_st_tl(r_tmp, r_ptr, offsetof(CPUState, PC));
751
    tcg_temp_free(r_tc_off);
T
ths 已提交
752
    tcg_temp_free(r_tc_off_ptr);
753 754
    tcg_temp_free(r_ptr);
    tcg_temp_free(r_tmp);
755
}
756

757 758 759
static inline void gen_breg_pc(void)
{
    TCGv r_tmp = tcg_temp_new(TCG_TYPE_TL);
760
    TCGv r_tc_off = tcg_temp_new(TCG_TYPE_I32);
761
    TCGv r_tc_off_ptr = tcg_temp_new(TCG_TYPE_PTR);
762 763 764 765 766
    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));
767 768
    tcg_gen_ext_i32_ptr(r_tc_off_ptr, r_tc_off);
    tcg_gen_add_ptr(r_ptr, cpu_env, r_tc_off_ptr);
769
    tcg_gen_st_tl(r_tmp, r_ptr, offsetof(CPUState, PC));
770
    tcg_temp_free(r_tc_off);
T
ths 已提交
771
    tcg_temp_free(r_tc_off_ptr);
772 773
    tcg_temp_free(r_ptr);
    tcg_temp_free(r_tmp);
774
}
B
bellard 已提交
775

776
static inline void gen_save_btarget(target_ulong btarget)
777
{
778 779 780 781
    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 已提交
782
    tcg_temp_free(r_tmp);
783 784
}

785
static always_inline void gen_save_breg_target(int reg)
786
{
787 788 789 790
    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 已提交
791
    tcg_temp_free(r_tmp);
792 793
}

794
static always_inline void save_cpu_state (DisasContext *ctx, int do_save_pc)
B
bellard 已提交
795 796 797 798 799 800 801 802
{
#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) {
803
        gen_save_pc(ctx->pc);
B
bellard 已提交
804 805 806
        ctx->saved_pc = ctx->pc;
    }
    if (ctx->hflags != ctx->saved_hflags) {
T
ths 已提交
807 808 809 810 811
        TCGv r_tmp = tcg_temp_new(TCG_TYPE_I32);

        tcg_gen_movi_i32(r_tmp, ctx->hflags);
        tcg_gen_st_i32(r_tmp, cpu_env, offsetof(CPUState, hflags));
        tcg_temp_free(r_tmp);
B
bellard 已提交
812
        ctx->saved_hflags = ctx->hflags;
813 814 815 816 817 818
        switch (ctx->hflags & MIPS_HFLAG_BMASK) {
        case MIPS_HFLAG_BR:
            break;
        case MIPS_HFLAG_BC:
        case MIPS_HFLAG_BL:
        case MIPS_HFLAG_B:
819
            gen_save_btarget(ctx->btarget);
820
            break;
B
bellard 已提交
821 822 823 824
        }
    }
}

825
static always_inline void restore_cpu_state (CPUState *env, DisasContext *ctx)
826
{
827 828 829 830 831 832
    ctx->saved_hflags = ctx->hflags;
    switch (ctx->hflags & MIPS_HFLAG_BMASK) {
    case MIPS_HFLAG_BR:
        break;
    case MIPS_HFLAG_BC:
    case MIPS_HFLAG_BL:
833
    case MIPS_HFLAG_B:
834 835
        ctx->btarget = env->btarget;
        break;
836 837 838
    }
}

839
static always_inline void
840
generate_exception_err (DisasContext *ctx, int excp, int err)
841 842
{
    save_cpu_state(ctx, 1);
T
ths 已提交
843
    tcg_gen_helper_0_2ii(do_raise_exception_err, excp, err);
844
    tcg_gen_helper_0_0(do_interrupt_restart);
845 846 847 848
    tcg_gen_exit_tb(0);
}

static always_inline void
849
generate_exception (DisasContext *ctx, int excp)
850
{
B
bellard 已提交
851
    save_cpu_state(ctx, 1);
T
ths 已提交
852
    tcg_gen_helper_0_1i(do_raise_exception, excp);
853 854
    tcg_gen_helper_0_0(do_interrupt_restart);
    tcg_gen_exit_tb(0);
B
bellard 已提交
855 856
}

857 858
/* Addresses computation */
static inline void gen_op_addr_add (void)
B
bellard 已提交
859
{
860 861 862 863 864 865 866 867
    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 已提交
868 869 870 871 872 873 874 875 876
        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);
877 878 879 880
        tcg_gen_ext32s_i64(cpu_T[0], cpu_T[0]);
        gen_set_label(l1);
    }
#endif
B
bellard 已提交
881 882
}

883
static always_inline void check_cp0_enabled(DisasContext *ctx)
884
{
885
    if (unlikely(!(ctx->hflags & MIPS_HFLAG_CP0)))
886 887 888
        generate_exception_err(ctx, EXCP_CpU, 1);
}

889
static always_inline void check_cp1_enabled(DisasContext *ctx)
890
{
891
    if (unlikely(!(ctx->hflags & MIPS_HFLAG_FPU)))
892 893 894
        generate_exception_err(ctx, EXCP_CpU, 1);
}

895 896 897 898 899 900 901 902 903 904 905 906 907
/* 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.  */

908
static always_inline void check_cp1_64bitmode(DisasContext *ctx)
909
{
910
    if (unlikely(~ctx->hflags & (MIPS_HFLAG_F64 | MIPS_HFLAG_COP1X)))
911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926
        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)
{
927
    if (unlikely(!(ctx->hflags & MIPS_HFLAG_F64) && (regs & 1)))
928 929 930
        generate_exception(ctx, EXCP_RI);
}

931
/* This code generates a "reserved instruction" exception if the
932
   CPU does not support the instruction set corresponding to flags. */
933
static always_inline void check_insn(CPUState *env, DisasContext *ctx, int flags)
934
{
935
    if (unlikely(!(env->insn_flags & flags)))
936 937 938
        generate_exception(ctx, EXCP_RI);
}

939 940
/* This code generates a "reserved instruction" exception if 64-bit
   instructions are not enabled. */
941
static always_inline void check_mips_64(DisasContext *ctx)
942
{
943
    if (unlikely(!(ctx->hflags & MIPS_HFLAG_64)))
944 945 946
        generate_exception(ctx, EXCP_RI);
}

T
ths 已提交
947
/* load/store instructions. */
B
bellard 已提交
948 949 950 951 952 953 954 955 956
#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 已提交
957 958
    &gen_op_l##width##_super,                                                 \
    &gen_op_l##width##_user,                                                  \
B
bellard 已提交
959 960 961 962
}
#define OP_ST_TABLE(width)                                                    \
static GenOpFunc *gen_op_s##width[] = {                                       \
    &gen_op_s##width##_kernel,                                                \
T
ths 已提交
963 964
    &gen_op_s##width##_super,                                                 \
    &gen_op_s##width##_user,                                                  \
B
bellard 已提交
965 966 967
}
#endif

968
#if defined(TARGET_MIPS64)
B
bellard 已提交
969 970 971 972 973 974 975 976 977 978
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);

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 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023
#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 已提交
1024
    TCGv r_tmp = tcg_temp_local_new(TCG_TYPE_TL);                       \
1025 1026 1027 1028 1029
    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 已提交
1030
    tcg_gen_brcondi_tl(TCG_COND_EQ, r_tmp, 0, l1);                      \
1031
    tcg_gen_st_tl(cpu_T[0], cpu_env, offsetof(CPUState, CP0_BadVAddr)); \
T
ths 已提交
1032
    generate_exception(ctx, EXCP_AdES);                                 \
1033 1034 1035
    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 已提交
1036
    tcg_temp_free(r_tmp);                                               \
1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049
    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 已提交
1050
/* Load and store */
1051
static void gen_ldst (DisasContext *ctx, uint32_t opc, int rt,
B
bellard 已提交
1052 1053
                      int base, int16_t offset)
{
1054
    const char *opn = "ldst";
B
bellard 已提交
1055 1056

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

B
bellard 已提交
1201
/* Load and store */
1202
static void gen_flt_ldst (DisasContext *ctx, uint32_t opc, int ft,
B
bellard 已提交
1203 1204
                      int base, int16_t offset)
{
1205
    const char *opn = "flt_ldst";
B
bellard 已提交
1206 1207

    if (base == 0) {
1208
        tcg_gen_movi_tl(cpu_T[0], offset);
B
bellard 已提交
1209
    } else if (offset == 0) {
1210
        gen_load_gpr(cpu_T[0], base);
B
bellard 已提交
1211
    } else {
1212 1213
        gen_load_gpr(cpu_T[0], base);
        tcg_gen_movi_tl(cpu_T[1], offset);
1214
        gen_op_addr_add();
B
bellard 已提交
1215 1216
    }
    /* Don't do NOP if destination is zero: we must perform the actual
1217
       memory access. */
B
bellard 已提交
1218 1219
    switch (opc) {
    case OPC_LWC1:
T
ths 已提交
1220 1221
        tcg_gen_qemu_ld32s(fpu32_T[0], cpu_T[0], ctx->mem_idx);
        gen_store_fpr32(fpu32_T[0], ft);
B
bellard 已提交
1222 1223 1224
        opn = "lwc1";
        break;
    case OPC_SWC1:
T
ths 已提交
1225 1226
        gen_load_fpr32(fpu32_T[0], ft);
        tcg_gen_qemu_st32(fpu32_T[0], cpu_T[0], ctx->mem_idx);
B
bellard 已提交
1227 1228 1229
        opn = "swc1";
        break;
    case OPC_LDC1:
T
ths 已提交
1230 1231
        tcg_gen_qemu_ld64(fpu64_T[0], cpu_T[0], ctx->mem_idx);
        gen_store_fpr64(ctx, fpu64_T[0], ft);
B
bellard 已提交
1232 1233 1234
        opn = "ldc1";
        break;
    case OPC_SDC1:
T
ths 已提交
1235 1236
        gen_load_fpr64(ctx, fpu64_T[0], ft);
        tcg_gen_qemu_st64(fpu64_T[0], cpu_T[0], ctx->mem_idx);
B
bellard 已提交
1237 1238 1239
        opn = "sdc1";
        break;
    default:
1240
        MIPS_INVAL(opn);
1241
        generate_exception(ctx, EXCP_RI);
B
bellard 已提交
1242 1243 1244 1245 1246
        return;
    }
    MIPS_DEBUG("%s %s, %d(%s)", opn, fregnames[ft], offset, regnames[base]);
}

B
bellard 已提交
1247
/* Arithmetic with immediate operand */
1248 1249
static void gen_arith_imm (CPUState *env, DisasContext *ctx, uint32_t opc,
                           int rt, int rs, int16_t imm)
B
bellard 已提交
1250
{
1251
    target_ulong uimm;
1252
    const char *opn = "imm arith";
B
bellard 已提交
1253

1254
    if (rt == 0 && opc != OPC_ADDI && opc != OPC_DADDI) {
1255 1256
        /* If no destination, treat it as a NOP.
           For addi, we must generate the overflow exception when needed. */
B
bellard 已提交
1257 1258 1259
        MIPS_DEBUG("NOP");
        return;
    }
1260 1261 1262 1263
    uimm = (uint16_t)imm;
    switch (opc) {
    case OPC_ADDI:
    case OPC_ADDIU:
1264
#if defined(TARGET_MIPS64)
1265 1266 1267 1268 1269
    case OPC_DADDI:
    case OPC_DADDIU:
#endif
    case OPC_SLTI:
    case OPC_SLTIU:
1270
        uimm = (target_long)imm; /* Sign extend to 32/64 bits */
1271
        tcg_gen_movi_tl(cpu_T[1], uimm);
1272 1273 1274 1275
        /* Fall through. */
    case OPC_ANDI:
    case OPC_ORI:
    case OPC_XORI:
1276
        gen_load_gpr(cpu_T[0], rs);
1277 1278
        break;
    case OPC_LUI:
1279
        tcg_gen_movi_tl(cpu_T[0], imm << 16);
1280 1281 1282 1283
        break;
    case OPC_SLL:
    case OPC_SRA:
    case OPC_SRL:
1284
#if defined(TARGET_MIPS64)
1285 1286 1287 1288 1289 1290 1291 1292
    case OPC_DSLL:
    case OPC_DSRA:
    case OPC_DSRL:
    case OPC_DSLL32:
    case OPC_DSRA32:
    case OPC_DSRL32:
#endif
        uimm &= 0x1f;
1293
        gen_load_gpr(cpu_T[0], rs);
1294
        break;
B
bellard 已提交
1295 1296 1297
    }
    switch (opc) {
    case OPC_ADDI:
1298
        {
T
ths 已提交
1299
            TCGv r_tmp1 = tcg_temp_local_new(TCG_TYPE_TL);
1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310
            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 已提交
1311
            tcg_temp_free(r_tmp2);
1312
            tcg_gen_shri_tl(r_tmp1, r_tmp1, 31);
P
pbrook 已提交
1313
            tcg_gen_brcondi_tl(TCG_COND_EQ, r_tmp1, 0, l1);
T
ths 已提交
1314
            tcg_temp_free(r_tmp1);
1315 1316 1317 1318 1319 1320
            /* 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 已提交
1321 1322 1323
        opn = "addi";
        break;
    case OPC_ADDIU:
1324 1325 1326
        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 已提交
1327 1328
        opn = "addiu";
        break;
1329
#if defined(TARGET_MIPS64)
1330
    case OPC_DADDI:
1331
        {
T
ths 已提交
1332
            TCGv r_tmp1 = tcg_temp_local_new(TCG_TYPE_TL);
1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343
            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 已提交
1344
            tcg_temp_free(r_tmp2);
1345
            tcg_gen_shri_tl(r_tmp1, r_tmp1, 63);
P
pbrook 已提交
1346
            tcg_gen_brcondi_tl(TCG_COND_EQ, r_tmp1, 0, l1);
T
ths 已提交
1347
            tcg_temp_free(r_tmp1);
1348 1349 1350 1351
            /* operands of same sign, result different sign */
            generate_exception(ctx, EXCP_OVERFLOW);
            gen_set_label(l1);
        }
1352 1353 1354
        opn = "daddi";
        break;
    case OPC_DADDIU:
1355
        tcg_gen_addi_tl(cpu_T[0], cpu_T[0], uimm);
1356 1357 1358
        opn = "daddiu";
        break;
#endif
B
bellard 已提交
1359
    case OPC_SLTI:
1360
        gen_op_lti(uimm);
B
bellard 已提交
1361 1362 1363
        opn = "slti";
        break;
    case OPC_SLTIU:
1364
        gen_op_ltiu(uimm);
B
bellard 已提交
1365 1366 1367
        opn = "sltiu";
        break;
    case OPC_ANDI:
1368
        tcg_gen_andi_tl(cpu_T[0], cpu_T[0], uimm);
B
bellard 已提交
1369 1370 1371
        opn = "andi";
        break;
    case OPC_ORI:
1372
        tcg_gen_ori_tl(cpu_T[0], cpu_T[0], uimm);
B
bellard 已提交
1373 1374 1375
        opn = "ori";
        break;
    case OPC_XORI:
1376
        tcg_gen_xori_tl(cpu_T[0], cpu_T[0], uimm);
B
bellard 已提交
1377 1378 1379 1380 1381 1382
        opn = "xori";
        break;
    case OPC_LUI:
        opn = "lui";
        break;
    case OPC_SLL:
1383 1384 1385
        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 已提交
1386 1387 1388
        opn = "sll";
        break;
    case OPC_SRA:
1389 1390 1391
        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 已提交
1392 1393 1394
        opn = "sra";
        break;
    case OPC_SRL:
1395 1396
        switch ((ctx->opcode >> 21) & 0x1f) {
        case 0:
1397 1398 1399
            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]);
1400
            opn = "srl";
1401 1402
            break;
        case 1:
1403 1404
            /* rotr is decoded as srl on non-R2 CPUs */
            if (env->insn_flags & ISA_MIPS32R2) {
1405
                if (uimm != 0) {
1406 1407
                    TCGv r_tmp1 = tcg_temp_new(TCG_TYPE_I32);
                    TCGv r_tmp2 = tcg_temp_new(TCG_TYPE_I32);
1408 1409 1410 1411 1412 1413 1414

                    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 已提交
1415
                    tcg_gen_ext_i32_tl(cpu_T[0], r_tmp1);
1416 1417
                    tcg_temp_free(r_tmp1);
                    tcg_temp_free(r_tmp2);
1418
                }
1419 1420
                opn = "rotr";
            } else {
1421 1422 1423
                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]);
1424 1425
                opn = "srl";
            }
1426 1427 1428 1429 1430 1431
            break;
        default:
            MIPS_INVAL("invalid srl flag");
            generate_exception(ctx, EXCP_RI);
            break;
        }
1432
        break;
1433
#if defined(TARGET_MIPS64)
1434
    case OPC_DSLL:
1435
        tcg_gen_shli_tl(cpu_T[0], cpu_T[0], uimm);
1436 1437 1438
        opn = "dsll";
        break;
    case OPC_DSRA:
1439
        tcg_gen_sari_tl(cpu_T[0], cpu_T[0], uimm);
1440 1441 1442
        opn = "dsra";
        break;
    case OPC_DSRL:
1443 1444
        switch ((ctx->opcode >> 21) & 0x1f) {
        case 0:
1445
            tcg_gen_shri_tl(cpu_T[0], cpu_T[0], uimm);
1446
            opn = "dsrl";
1447 1448
            break;
        case 1:
1449 1450
            /* drotr is decoded as dsrl on non-R2 CPUs */
            if (env->insn_flags & ISA_MIPS32R2) {
1451 1452 1453 1454 1455 1456 1457 1458
                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 已提交
1459
                    tcg_temp_free(r_tmp1);
1460
                }
1461 1462
                opn = "drotr";
            } else {
1463
                tcg_gen_shri_tl(cpu_T[0], cpu_T[0], uimm);
1464 1465
                opn = "dsrl";
            }
1466 1467 1468 1469 1470 1471
            break;
        default:
            MIPS_INVAL("invalid dsrl flag");
            generate_exception(ctx, EXCP_RI);
            break;
        }
1472 1473
        break;
    case OPC_DSLL32:
1474
        tcg_gen_shli_tl(cpu_T[0], cpu_T[0], uimm + 32);
1475 1476 1477
        opn = "dsll32";
        break;
    case OPC_DSRA32:
1478
        tcg_gen_sari_tl(cpu_T[0], cpu_T[0], uimm + 32);
1479 1480 1481
        opn = "dsra32";
        break;
    case OPC_DSRL32:
1482 1483
        switch ((ctx->opcode >> 21) & 0x1f) {
        case 0:
1484
            tcg_gen_shri_tl(cpu_T[0], cpu_T[0], uimm + 32);
1485
            opn = "dsrl32";
1486 1487
            break;
        case 1:
1488 1489
            /* drotr32 is decoded as dsrl32 on non-R2 CPUs */
            if (env->insn_flags & ISA_MIPS32R2) {
1490 1491 1492 1493 1494 1495 1496 1497 1498 1499
                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 已提交
1500 1501
                tcg_temp_free(r_tmp1);
                tcg_temp_free(r_tmp2);
1502 1503
                opn = "drotr32";
            } else {
1504
                tcg_gen_shri_tl(cpu_T[0], cpu_T[0], uimm + 32);
1505 1506
                opn = "dsrl32";
            }
1507 1508 1509 1510 1511 1512
            break;
        default:
            MIPS_INVAL("invalid dsrl32 flag");
            generate_exception(ctx, EXCP_RI);
            break;
        }
B
bellard 已提交
1513
        break;
1514
#endif
B
bellard 已提交
1515
    default:
1516
        MIPS_INVAL(opn);
B
bellard 已提交
1517 1518 1519
        generate_exception(ctx, EXCP_RI);
        return;
    }
1520
    gen_store_gpr(cpu_T[0], rt);
T
ths 已提交
1521
    MIPS_DEBUG("%s %s, %s, " TARGET_FMT_lx, opn, regnames[rt], regnames[rs], uimm);
B
bellard 已提交
1522 1523 1524
}

/* Arithmetic */
1525
static void gen_arith (CPUState *env, DisasContext *ctx, uint32_t opc,
B
bellard 已提交
1526 1527
                       int rd, int rs, int rt)
{
1528
    const char *opn = "arith";
B
bellard 已提交
1529

1530 1531
    if (rd == 0 && opc != OPC_ADD && opc != OPC_SUB
       && opc != OPC_DADD && opc != OPC_DSUB) {
1532 1533
        /* If no destination, treat it as a NOP.
           For add & sub, we must generate the overflow exception when needed. */
B
bellard 已提交
1534 1535 1536
        MIPS_DEBUG("NOP");
        return;
    }
1537
    gen_load_gpr(cpu_T[0], rs);
T
ths 已提交
1538 1539 1540
    /* Specialcase the conventional move operation. */
    if (rt == 0 && (opc == OPC_ADDU || opc == OPC_DADDU
                    || opc == OPC_SUBU || opc == OPC_DSUBU)) {
1541
        gen_store_gpr(cpu_T[0], rd);
T
ths 已提交
1542 1543
        return;
    }
1544
    gen_load_gpr(cpu_T[1], rt);
B
bellard 已提交
1545 1546
    switch (opc) {
    case OPC_ADD:
1547
        {
T
ths 已提交
1548
            TCGv r_tmp1 = tcg_temp_local_new(TCG_TYPE_TL);
1549 1550 1551 1552 1553 1554 1555 1556 1557 1558 1559 1560
            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 已提交
1561
            tcg_temp_free(r_tmp2);
1562
            tcg_gen_shri_tl(r_tmp1, r_tmp1, 31);
P
pbrook 已提交
1563
            tcg_gen_brcondi_tl(TCG_COND_EQ, r_tmp1, 0, l1);
T
ths 已提交
1564
            tcg_temp_free(r_tmp1);
1565 1566 1567 1568 1569 1570
            /* 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 已提交
1571 1572 1573
        opn = "add";
        break;
    case OPC_ADDU:
1574 1575 1576 1577
        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 已提交
1578 1579 1580
        opn = "addu";
        break;
    case OPC_SUB:
1581
        {
T
ths 已提交
1582
            TCGv r_tmp1 = tcg_temp_local_new(TCG_TYPE_TL);
1583 1584 1585 1586 1587 1588 1589 1590 1591 1592 1593
            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 已提交
1594
            tcg_temp_free(r_tmp2);
1595
            tcg_gen_shri_tl(r_tmp1, r_tmp1, 31);
P
pbrook 已提交
1596
            tcg_gen_brcondi_tl(TCG_COND_EQ, r_tmp1, 0, l1);
T
ths 已提交
1597
            tcg_temp_free(r_tmp1);
1598 1599 1600 1601 1602 1603
            /* 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 已提交
1604 1605 1606
        opn = "sub";
        break;
    case OPC_SUBU:
1607 1608 1609 1610
        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 已提交
1611 1612
        opn = "subu";
        break;
1613
#if defined(TARGET_MIPS64)
1614
    case OPC_DADD:
1615
        {
T
ths 已提交
1616
            TCGv r_tmp1 = tcg_temp_local_new(TCG_TYPE_TL);
1617 1618 1619 1620 1621 1622 1623 1624 1625 1626 1627
            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 已提交
1628
            tcg_temp_free(r_tmp2);
1629
            tcg_gen_shri_tl(r_tmp1, r_tmp1, 63);
P
pbrook 已提交
1630
            tcg_gen_brcondi_tl(TCG_COND_EQ, r_tmp1, 0, l1);
T
ths 已提交
1631
            tcg_temp_free(r_tmp1);
1632 1633 1634 1635
            /* operands of same sign, result different sign */
            generate_exception(ctx, EXCP_OVERFLOW);
            gen_set_label(l1);
        }
1636 1637 1638
        opn = "dadd";
        break;
    case OPC_DADDU:
1639
        tcg_gen_add_tl(cpu_T[0], cpu_T[0], cpu_T[1]);
1640 1641 1642
        opn = "daddu";
        break;
    case OPC_DSUB:
1643
        {
T
ths 已提交
1644
            TCGv r_tmp1 = tcg_temp_local_new(TCG_TYPE_TL);
1645 1646 1647 1648 1649 1650 1651 1652 1653 1654
            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 已提交
1655
            tcg_temp_free(r_tmp2);
1656
            tcg_gen_shri_tl(r_tmp1, r_tmp1, 63);
P
pbrook 已提交
1657
            tcg_gen_brcondi_tl(TCG_COND_EQ, r_tmp1, 0, l1);
T
ths 已提交
1658
            tcg_temp_free(r_tmp1);
1659 1660 1661 1662
            /* operands of different sign, first operand and result different sign */
            generate_exception(ctx, EXCP_OVERFLOW);
            gen_set_label(l1);
        }
1663 1664 1665
        opn = "dsub";
        break;
    case OPC_DSUBU:
1666
        tcg_gen_sub_tl(cpu_T[0], cpu_T[0], cpu_T[1]);
1667 1668 1669
        opn = "dsubu";
        break;
#endif
B
bellard 已提交
1670 1671 1672 1673 1674 1675 1676 1677 1678
    case OPC_SLT:
        gen_op_lt();
        opn = "slt";
        break;
    case OPC_SLTU:
        gen_op_ltu();
        opn = "sltu";
        break;
    case OPC_AND:
1679
        tcg_gen_and_tl(cpu_T[0], cpu_T[0], cpu_T[1]);
B
bellard 已提交
1680 1681 1682
        opn = "and";
        break;
    case OPC_NOR:
1683 1684
        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 已提交
1685 1686 1687
        opn = "nor";
        break;
    case OPC_OR:
1688
        tcg_gen_or_tl(cpu_T[0], cpu_T[0], cpu_T[1]);
B
bellard 已提交
1689 1690 1691
        opn = "or";
        break;
    case OPC_XOR:
1692
        tcg_gen_xor_tl(cpu_T[0], cpu_T[0], cpu_T[1]);
B
bellard 已提交
1693 1694 1695
        opn = "xor";
        break;
    case OPC_MUL:
1696 1697 1698 1699
        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 已提交
1700 1701 1702
        opn = "mul";
        break;
    case OPC_MOVN:
T
ths 已提交
1703 1704 1705
        {
            int l1 = gen_new_label();

P
pbrook 已提交
1706
            tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_T[1], 0, l1);
1707
            gen_store_gpr(cpu_T[0], rd);
T
ths 已提交
1708 1709
            gen_set_label(l1);
        }
B
bellard 已提交
1710 1711 1712
        opn = "movn";
        goto print;
    case OPC_MOVZ:
T
ths 已提交
1713 1714 1715
        {
            int l1 = gen_new_label();

P
pbrook 已提交
1716
            tcg_gen_brcondi_tl(TCG_COND_NE, cpu_T[1], 0, l1);
1717
            gen_store_gpr(cpu_T[0], rd);
T
ths 已提交
1718 1719
            gen_set_label(l1);
        }
B
bellard 已提交
1720 1721 1722
        opn = "movz";
        goto print;
    case OPC_SLLV:
1723 1724 1725 1726 1727
        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 已提交
1728 1729 1730
        opn = "sllv";
        break;
    case OPC_SRAV:
1731 1732 1733 1734
        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 已提交
1735 1736 1737
        opn = "srav";
        break;
    case OPC_SRLV:
1738 1739
        switch ((ctx->opcode >> 6) & 0x1f) {
        case 0:
1740 1741 1742 1743
            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]);
1744
            opn = "srlv";
1745 1746
            break;
        case 1:
1747 1748
            /* rotrv is decoded as srlv on non-R2 CPUs */
            if (env->insn_flags & ISA_MIPS32R2) {
1749 1750 1751 1752
                int l1 = gen_new_label();
                int l2 = gen_new_label();

                tcg_gen_andi_tl(cpu_T[0], cpu_T[0], 0x1f);
P
pbrook 已提交
1753
                tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_T[0], 0, l1);
1754
                {
1755 1756 1757
                    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);
1758 1759 1760 1761 1762 1763 1764 1765

                    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 已提交
1766
                    tcg_gen_ext_i32_tl(cpu_T[0], r_tmp1);
1767 1768 1769
                    tcg_temp_free(r_tmp1);
                    tcg_temp_free(r_tmp2);
                    tcg_temp_free(r_tmp3);
1770 1771 1772 1773 1774
                    tcg_gen_br(l2);
                }
                gen_set_label(l1);
                tcg_gen_mov_tl(cpu_T[0], cpu_T[1]);
                gen_set_label(l2);
1775 1776
                opn = "rotrv";
            } else {
1777 1778 1779 1780
                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]);
1781 1782
                opn = "srlv";
            }
1783 1784 1785 1786 1787 1788
            break;
        default:
            MIPS_INVAL("invalid srlv flag");
            generate_exception(ctx, EXCP_RI);
            break;
        }
1789
        break;
1790
#if defined(TARGET_MIPS64)
1791
    case OPC_DSLLV:
1792 1793
        tcg_gen_andi_tl(cpu_T[0], cpu_T[0], 0x3f);
        tcg_gen_shl_tl(cpu_T[0], cpu_T[1], cpu_T[0]);
1794 1795 1796
        opn = "dsllv";
        break;
    case OPC_DSRAV:
1797 1798
        tcg_gen_andi_tl(cpu_T[0], cpu_T[0], 0x3f);
        tcg_gen_sar_tl(cpu_T[0], cpu_T[1], cpu_T[0]);
1799 1800 1801
        opn = "dsrav";
        break;
    case OPC_DSRLV:
1802 1803
        switch ((ctx->opcode >> 6) & 0x1f) {
        case 0:
1804 1805
            tcg_gen_andi_tl(cpu_T[0], cpu_T[0], 0x3f);
            tcg_gen_shr_tl(cpu_T[0], cpu_T[1], cpu_T[0]);
1806
            opn = "dsrlv";
1807 1808
            break;
        case 1:
1809 1810
            /* drotrv is decoded as dsrlv on non-R2 CPUs */
            if (env->insn_flags & ISA_MIPS32R2) {
1811 1812 1813 1814
                int l1 = gen_new_label();
                int l2 = gen_new_label();

                tcg_gen_andi_tl(cpu_T[0], cpu_T[0], 0x3f);
P
pbrook 已提交
1815
                tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_T[0], 0, l1);
1816 1817 1818 1819 1820 1821 1822 1823
                {
                    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 已提交
1824
                    tcg_temp_free(r_tmp1);
1825 1826 1827 1828 1829
                    tcg_gen_br(l2);
                }
                gen_set_label(l1);
                tcg_gen_mov_tl(cpu_T[0], cpu_T[1]);
                gen_set_label(l2);
1830 1831
                opn = "drotrv";
            } else {
1832 1833
                tcg_gen_andi_tl(cpu_T[0], cpu_T[0], 0x3f);
                tcg_gen_shr_tl(cpu_T[0], cpu_T[1], cpu_T[0]);
1834 1835
                opn = "dsrlv";
            }
1836 1837 1838 1839 1840 1841
            break;
        default:
            MIPS_INVAL("invalid dsrlv flag");
            generate_exception(ctx, EXCP_RI);
            break;
        }
B
bellard 已提交
1842
        break;
1843
#endif
B
bellard 已提交
1844
    default:
1845
        MIPS_INVAL(opn);
B
bellard 已提交
1846 1847 1848
        generate_exception(ctx, EXCP_RI);
        return;
    }
1849
    gen_store_gpr(cpu_T[0], rd);
B
bellard 已提交
1850 1851 1852 1853 1854
 print:
    MIPS_DEBUG("%s %s, %s, %s", opn, regnames[rd], regnames[rs], regnames[rt]);
}

/* Arithmetic on HI/LO registers */
1855
static void gen_HILO (DisasContext *ctx, uint32_t opc, int reg)
B
bellard 已提交
1856
{
1857
    const char *opn = "hilo";
B
bellard 已提交
1858 1859

    if (reg == 0 && (opc == OPC_MFHI || opc == OPC_MFLO)) {
1860
        /* Treat as NOP. */
B
bellard 已提交
1861 1862 1863 1864 1865
        MIPS_DEBUG("NOP");
        return;
    }
    switch (opc) {
    case OPC_MFHI:
1866
        gen_load_HI(cpu_T[0], 0);
1867
        gen_store_gpr(cpu_T[0], reg);
B
bellard 已提交
1868 1869 1870
        opn = "mfhi";
        break;
    case OPC_MFLO:
1871
        gen_load_LO(cpu_T[0], 0);
1872
        gen_store_gpr(cpu_T[0], reg);
B
bellard 已提交
1873 1874 1875
        opn = "mflo";
        break;
    case OPC_MTHI:
1876
        gen_load_gpr(cpu_T[0], reg);
1877
        gen_store_HI(cpu_T[0], 0);
B
bellard 已提交
1878 1879 1880
        opn = "mthi";
        break;
    case OPC_MTLO:
1881
        gen_load_gpr(cpu_T[0], reg);
1882
        gen_store_LO(cpu_T[0], 0);
B
bellard 已提交
1883 1884 1885
        opn = "mtlo";
        break;
    default:
1886
        MIPS_INVAL(opn);
B
bellard 已提交
1887 1888 1889 1890 1891 1892
        generate_exception(ctx, EXCP_RI);
        return;
    }
    MIPS_DEBUG("%s %s", opn, regnames[reg]);
}

1893
static void gen_muldiv (DisasContext *ctx, uint32_t opc,
B
bellard 已提交
1894 1895
                        int rs, int rt)
{
1896
    const char *opn = "mul/div";
B
bellard 已提交
1897

1898 1899
    gen_load_gpr(cpu_T[0], rs);
    gen_load_gpr(cpu_T[1], rt);
B
bellard 已提交
1900 1901
    switch (opc) {
    case OPC_DIV:
1902 1903 1904
        {
            int l1 = gen_new_label();

1905 1906
            tcg_gen_ext32s_tl(cpu_T[0], cpu_T[0]);
            tcg_gen_ext32s_tl(cpu_T[1], cpu_T[1]);
P
pbrook 已提交
1907
            tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_T[1], 0, l1);
1908
            {
1909 1910
                TCGv r_tmp1 = tcg_temp_new(TCG_TYPE_I64);
                TCGv r_tmp2 = tcg_temp_new(TCG_TYPE_I64);
T
ths 已提交
1911 1912 1913 1914 1915 1916 1917 1918
                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 已提交
1919 1920 1921
                tcg_temp_free(r_tmp1);
                tcg_temp_free(r_tmp2);
                tcg_temp_free(r_tmp3);
1922 1923
                tcg_gen_ext32s_tl(cpu_T[0], cpu_T[0]);
                tcg_gen_ext32s_tl(cpu_T[1], cpu_T[1]);
T
ths 已提交
1924 1925
                gen_store_LO(cpu_T[0], 0);
                gen_store_HI(cpu_T[1], 0);
1926 1927 1928
            }
            gen_set_label(l1);
        }
B
bellard 已提交
1929 1930 1931
        opn = "div";
        break;
    case OPC_DIVU:
1932 1933 1934
        {
            int l1 = gen_new_label();

1935
            tcg_gen_ext32s_tl(cpu_T[1], cpu_T[1]);
P
pbrook 已提交
1936
            tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_T[1], 0, l1);
1937
            {
1938 1939 1940
                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);
1941

1942 1943
                tcg_gen_trunc_tl_i32(r_tmp1, cpu_T[0]);
                tcg_gen_trunc_tl_i32(r_tmp2, cpu_T[1]);
1944 1945
                tcg_gen_divu_i32(r_tmp3, r_tmp1, r_tmp2);
                tcg_gen_remu_i32(r_tmp1, r_tmp1, r_tmp2);
1946 1947
                tcg_gen_ext_i32_tl(cpu_T[0], r_tmp3);
                tcg_gen_ext_i32_tl(cpu_T[1], r_tmp1);
1948 1949 1950
                tcg_temp_free(r_tmp1);
                tcg_temp_free(r_tmp2);
                tcg_temp_free(r_tmp3);
1951 1952
                gen_store_LO(cpu_T[0], 0);
                gen_store_HI(cpu_T[1], 0);
1953 1954 1955
            }
            gen_set_label(l1);
        }
B
bellard 已提交
1956 1957 1958
        opn = "divu";
        break;
    case OPC_MULT:
1959 1960 1961 1962 1963 1964 1965 1966 1967 1968 1969 1970 1971 1972 1973 1974 1975 1976 1977
        {
            TCGv r_tmp1 = tcg_temp_new(TCG_TYPE_I64);
            TCGv r_tmp2 = tcg_temp_new(TCG_TYPE_I64);

            tcg_gen_ext32s_tl(cpu_T[0], cpu_T[0]);
            tcg_gen_ext32s_tl(cpu_T[1], cpu_T[1]);
            tcg_gen_ext_tl_i64(r_tmp1, cpu_T[0]);
            tcg_gen_ext_tl_i64(r_tmp2, cpu_T[1]);
            tcg_gen_mul_i64(r_tmp1, r_tmp1, r_tmp2);
            tcg_temp_free(r_tmp2);
            tcg_gen_trunc_i64_tl(cpu_T[0], r_tmp1);
            tcg_gen_shri_i64(r_tmp1, r_tmp1, 32);
            tcg_gen_trunc_i64_tl(cpu_T[1], r_tmp1);
            tcg_temp_free(r_tmp1);
            tcg_gen_ext32s_tl(cpu_T[0], cpu_T[0]);
            tcg_gen_ext32s_tl(cpu_T[1], cpu_T[1]);
            gen_store_LO(cpu_T[0], 0);
            gen_store_HI(cpu_T[1], 0);
        }
B
bellard 已提交
1978 1979 1980
        opn = "mult";
        break;
    case OPC_MULTU:
1981 1982 1983 1984 1985 1986 1987 1988 1989 1990 1991 1992 1993 1994 1995 1996 1997 1998 1999
        {
            TCGv r_tmp1 = tcg_temp_new(TCG_TYPE_I64);
            TCGv r_tmp2 = tcg_temp_new(TCG_TYPE_I64);

            tcg_gen_ext32u_tl(cpu_T[0], cpu_T[0]);
            tcg_gen_ext32u_tl(cpu_T[1], cpu_T[1]);
            tcg_gen_extu_tl_i64(r_tmp1, cpu_T[0]);
            tcg_gen_extu_tl_i64(r_tmp2, cpu_T[1]);
            tcg_gen_mul_i64(r_tmp1, r_tmp1, r_tmp2);
            tcg_temp_free(r_tmp2);
            tcg_gen_trunc_i64_tl(cpu_T[0], r_tmp1);
            tcg_gen_shri_i64(r_tmp1, r_tmp1, 32);
            tcg_gen_trunc_i64_tl(cpu_T[1], r_tmp1);
            tcg_temp_free(r_tmp1);
            tcg_gen_ext32s_tl(cpu_T[0], cpu_T[0]);
            tcg_gen_ext32s_tl(cpu_T[1], cpu_T[1]);
            gen_store_LO(cpu_T[0], 0);
            gen_store_HI(cpu_T[1], 0);
        }
B
bellard 已提交
2000 2001
        opn = "multu";
        break;
2002
#if defined(TARGET_MIPS64)
2003
    case OPC_DDIV:
2004 2005 2006
        {
            int l1 = gen_new_label();

P
pbrook 已提交
2007
            tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_T[1], 0, l1);
2008 2009 2010
            {
                int l2 = gen_new_label();

2011 2012
                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);
2013 2014 2015 2016 2017 2018
                {
                    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);
                }
2019
                gen_set_label(l2);
2020 2021 2022
                {
                    TCGv r_tmp1 = tcg_temp_new(TCG_TYPE_I64);
                    TCGv r_tmp2 = tcg_temp_new(TCG_TYPE_I64);
2023

2024 2025 2026 2027
                    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 已提交
2028 2029
                    tcg_temp_free(r_tmp1);
                    tcg_temp_free(r_tmp2);
2030
                }
2031 2032 2033
            }
            gen_set_label(l1);
        }
2034 2035 2036
        opn = "ddiv";
        break;
    case OPC_DDIVU:
2037 2038 2039
        {
            int l1 = gen_new_label();

P
pbrook 已提交
2040
            tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_T[1], 0, l1);
2041 2042 2043 2044 2045 2046
            {
                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 已提交
2047 2048
                tcg_temp_free(r_tmp1);
                tcg_temp_free(r_tmp2);
2049 2050
                gen_store_LO(r_tmp1, 0);
                gen_store_HI(r_tmp2, 0);
2051 2052 2053
            }
            gen_set_label(l1);
        }
2054 2055 2056
        opn = "ddivu";
        break;
    case OPC_DMULT:
2057
        tcg_gen_helper_0_0(do_dmult);
2058 2059 2060
        opn = "dmult";
        break;
    case OPC_DMULTU:
2061
        tcg_gen_helper_0_0(do_dmultu);
2062 2063 2064
        opn = "dmultu";
        break;
#endif
B
bellard 已提交
2065
    case OPC_MADD:
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
        {
            TCGv r_tmp1 = tcg_temp_new(TCG_TYPE_I64);
            TCGv r_tmp2 = tcg_temp_new(TCG_TYPE_I64);
            TCGv r_tmp3 = tcg_temp_new(TCG_TYPE_I64);

            tcg_gen_ext32s_tl(cpu_T[0], cpu_T[0]);
            tcg_gen_ext32s_tl(cpu_T[1], cpu_T[1]);
            tcg_gen_ext_tl_i64(r_tmp1, cpu_T[0]);
            tcg_gen_ext_tl_i64(r_tmp2, cpu_T[1]);
            tcg_gen_mul_i64(r_tmp1, r_tmp1, r_tmp2);
            gen_load_LO(cpu_T[0], 0);
            gen_load_HI(cpu_T[1], 0);
            tcg_gen_extu_tl_i64(r_tmp2, cpu_T[0]);
            tcg_gen_extu_tl_i64(r_tmp3, cpu_T[1]);
            tcg_gen_shli_i64(r_tmp3, r_tmp3, 32);
            tcg_gen_or_i64(r_tmp2, r_tmp2, r_tmp3);
            tcg_temp_free(r_tmp3);
            tcg_gen_add_i64(r_tmp1, r_tmp1, r_tmp2);
            tcg_temp_free(r_tmp2);
            tcg_gen_trunc_i64_tl(cpu_T[0], r_tmp1);
            tcg_gen_shri_i64(r_tmp1, r_tmp1, 32);
            tcg_gen_trunc_i64_tl(cpu_T[1], r_tmp1);
            tcg_temp_free(r_tmp1);
            tcg_gen_ext32s_tl(cpu_T[0], cpu_T[0]);
            tcg_gen_ext32s_tl(cpu_T[1], cpu_T[1]);
            gen_store_LO(cpu_T[0], 0);
            gen_store_HI(cpu_T[1], 0);
        }
B
bellard 已提交
2094 2095 2096
        opn = "madd";
        break;
    case OPC_MADDU:
2097 2098 2099 2100 2101 2102 2103 2104 2105 2106 2107 2108 2109 2110 2111 2112 2113 2114 2115 2116 2117 2118 2119 2120 2121 2122 2123 2124
       {
            TCGv r_tmp1 = tcg_temp_new(TCG_TYPE_I64);
            TCGv r_tmp2 = tcg_temp_new(TCG_TYPE_I64);
            TCGv r_tmp3 = tcg_temp_new(TCG_TYPE_I64);

            tcg_gen_ext32u_tl(cpu_T[0], cpu_T[0]);
            tcg_gen_ext32u_tl(cpu_T[1], cpu_T[1]);
            tcg_gen_extu_tl_i64(r_tmp1, cpu_T[0]);
            tcg_gen_extu_tl_i64(r_tmp2, cpu_T[1]);
            tcg_gen_mul_i64(r_tmp1, r_tmp1, r_tmp2);
            gen_load_LO(cpu_T[0], 0);
            gen_load_HI(cpu_T[1], 0);
            tcg_gen_extu_tl_i64(r_tmp2, cpu_T[0]);
            tcg_gen_extu_tl_i64(r_tmp3, cpu_T[1]);
            tcg_gen_shli_i64(r_tmp3, r_tmp3, 32);
            tcg_gen_or_i64(r_tmp2, r_tmp2, r_tmp3);
            tcg_temp_free(r_tmp3);
            tcg_gen_add_i64(r_tmp1, r_tmp1, r_tmp2);
            tcg_temp_free(r_tmp2);
            tcg_gen_trunc_i64_tl(cpu_T[0], r_tmp1);
            tcg_gen_shri_i64(r_tmp1, r_tmp1, 32);
            tcg_gen_trunc_i64_tl(cpu_T[1], r_tmp1);
            tcg_temp_free(r_tmp1);
            tcg_gen_ext32s_tl(cpu_T[0], cpu_T[0]);
            tcg_gen_ext32s_tl(cpu_T[1], cpu_T[1]);
            gen_store_LO(cpu_T[0], 0);
            gen_store_HI(cpu_T[1], 0);
        }
B
bellard 已提交
2125 2126 2127
        opn = "maddu";
        break;
    case OPC_MSUB:
2128 2129 2130 2131 2132 2133 2134 2135 2136 2137 2138 2139 2140 2141 2142 2143 2144 2145 2146 2147 2148 2149 2150 2151 2152 2153 2154 2155
        {
            TCGv r_tmp1 = tcg_temp_new(TCG_TYPE_I64);
            TCGv r_tmp2 = tcg_temp_new(TCG_TYPE_I64);
            TCGv r_tmp3 = tcg_temp_new(TCG_TYPE_I64);

            tcg_gen_ext32s_tl(cpu_T[0], cpu_T[0]);
            tcg_gen_ext32s_tl(cpu_T[1], cpu_T[1]);
            tcg_gen_ext_tl_i64(r_tmp1, cpu_T[0]);
            tcg_gen_ext_tl_i64(r_tmp2, cpu_T[1]);
            tcg_gen_mul_i64(r_tmp1, r_tmp1, r_tmp2);
            gen_load_LO(cpu_T[0], 0);
            gen_load_HI(cpu_T[1], 0);
            tcg_gen_extu_tl_i64(r_tmp2, cpu_T[0]);
            tcg_gen_extu_tl_i64(r_tmp3, cpu_T[1]);
            tcg_gen_shli_i64(r_tmp3, r_tmp3, 32);
            tcg_gen_or_i64(r_tmp2, r_tmp2, r_tmp3);
            tcg_temp_free(r_tmp3);
            tcg_gen_sub_i64(r_tmp1, r_tmp1, r_tmp2);
            tcg_temp_free(r_tmp2);
            tcg_gen_trunc_i64_tl(cpu_T[0], r_tmp1);
            tcg_gen_shri_i64(r_tmp1, r_tmp1, 32);
            tcg_gen_trunc_i64_tl(cpu_T[1], r_tmp1);
            tcg_temp_free(r_tmp1);
            tcg_gen_ext32s_tl(cpu_T[0], cpu_T[0]);
            tcg_gen_ext32s_tl(cpu_T[1], cpu_T[1]);
            gen_store_LO(cpu_T[0], 0);
            gen_store_HI(cpu_T[1], 0);
        }
B
bellard 已提交
2156 2157 2158
        opn = "msub";
        break;
    case OPC_MSUBU:
2159 2160 2161 2162 2163 2164 2165 2166 2167 2168 2169 2170 2171 2172 2173 2174 2175 2176 2177 2178 2179 2180 2181 2182 2183 2184 2185 2186
        {
            TCGv r_tmp1 = tcg_temp_new(TCG_TYPE_I64);
            TCGv r_tmp2 = tcg_temp_new(TCG_TYPE_I64);
            TCGv r_tmp3 = tcg_temp_new(TCG_TYPE_I64);

            tcg_gen_ext32u_tl(cpu_T[0], cpu_T[0]);
            tcg_gen_ext32u_tl(cpu_T[1], cpu_T[1]);
            tcg_gen_extu_tl_i64(r_tmp1, cpu_T[0]);
            tcg_gen_extu_tl_i64(r_tmp2, cpu_T[1]);
            tcg_gen_mul_i64(r_tmp1, r_tmp1, r_tmp2);
            gen_load_LO(cpu_T[0], 0);
            gen_load_HI(cpu_T[1], 0);
            tcg_gen_extu_tl_i64(r_tmp2, cpu_T[0]);
            tcg_gen_extu_tl_i64(r_tmp3, cpu_T[1]);
            tcg_gen_shli_i64(r_tmp3, r_tmp3, 32);
            tcg_gen_or_i64(r_tmp2, r_tmp2, r_tmp3);
            tcg_temp_free(r_tmp3);
            tcg_gen_sub_i64(r_tmp1, r_tmp1, r_tmp2);
            tcg_temp_free(r_tmp2);
            tcg_gen_trunc_i64_tl(cpu_T[0], r_tmp1);
            tcg_gen_shri_i64(r_tmp1, r_tmp1, 32);
            tcg_gen_trunc_i64_tl(cpu_T[1], r_tmp1);
            tcg_temp_free(r_tmp1);
            tcg_gen_ext32s_tl(cpu_T[0], cpu_T[0]);
            tcg_gen_ext32s_tl(cpu_T[1], cpu_T[1]);
            gen_store_LO(cpu_T[0], 0);
            gen_store_HI(cpu_T[1], 0);
        }
B
bellard 已提交
2187 2188 2189
        opn = "msubu";
        break;
    default:
2190
        MIPS_INVAL(opn);
B
bellard 已提交
2191 2192 2193 2194 2195 2196
        generate_exception(ctx, EXCP_RI);
        return;
    }
    MIPS_DEBUG("%s %s %s", opn, regnames[rs], regnames[rt]);
}

2197 2198 2199 2200 2201
static void gen_mul_vr54xx (DisasContext *ctx, uint32_t opc,
                            int rd, int rs, int rt)
{
    const char *opn = "mul vr54xx";

2202 2203
    gen_load_gpr(cpu_T[0], rs);
    gen_load_gpr(cpu_T[1], rt);
2204 2205 2206

    switch (opc) {
    case OPC_VR54XX_MULS:
2207
        tcg_gen_helper_0_0(do_muls);
2208 2209 2210
        opn = "muls";
	break;
    case OPC_VR54XX_MULSU:
2211
        tcg_gen_helper_0_0(do_mulsu);
2212 2213 2214
        opn = "mulsu";
	break;
    case OPC_VR54XX_MACC:
2215
        tcg_gen_helper_0_0(do_macc);
2216 2217 2218
        opn = "macc";
	break;
    case OPC_VR54XX_MACCU:
2219
        tcg_gen_helper_0_0(do_maccu);
2220 2221 2222
        opn = "maccu";
	break;
    case OPC_VR54XX_MSAC:
2223
        tcg_gen_helper_0_0(do_msac);
2224 2225 2226
        opn = "msac";
	break;
    case OPC_VR54XX_MSACU:
2227
        tcg_gen_helper_0_0(do_msacu);
2228 2229 2230
        opn = "msacu";
	break;
    case OPC_VR54XX_MULHI:
2231
        tcg_gen_helper_0_0(do_mulhi);
2232 2233 2234
        opn = "mulhi";
	break;
    case OPC_VR54XX_MULHIU:
2235
        tcg_gen_helper_0_0(do_mulhiu);
2236 2237 2238
        opn = "mulhiu";
	break;
    case OPC_VR54XX_MULSHI:
2239
        tcg_gen_helper_0_0(do_mulshi);
2240 2241 2242
        opn = "mulshi";
	break;
    case OPC_VR54XX_MULSHIU:
2243
        tcg_gen_helper_0_0(do_mulshiu);
2244 2245 2246
        opn = "mulshiu";
	break;
    case OPC_VR54XX_MACCHI:
2247
        tcg_gen_helper_0_0(do_macchi);
2248 2249 2250
        opn = "macchi";
	break;
    case OPC_VR54XX_MACCHIU:
2251
        tcg_gen_helper_0_0(do_macchiu);
2252 2253 2254
        opn = "macchiu";
	break;
    case OPC_VR54XX_MSACHI:
2255
        tcg_gen_helper_0_0(do_msachi);
2256 2257 2258
        opn = "msachi";
	break;
    case OPC_VR54XX_MSACHIU:
2259
        tcg_gen_helper_0_0(do_msachiu);
2260 2261 2262 2263 2264 2265 2266
        opn = "msachiu";
	break;
    default:
        MIPS_INVAL("mul vr54xx");
        generate_exception(ctx, EXCP_RI);
        return;
    }
2267
    gen_store_gpr(cpu_T[0], rd);
2268 2269 2270
    MIPS_DEBUG("%s %s, %s, %s", opn, regnames[rd], regnames[rs], regnames[rt]);
}

2271
static void gen_cl (DisasContext *ctx, uint32_t opc,
B
bellard 已提交
2272 2273
                    int rd, int rs)
{
2274
    const char *opn = "CLx";
B
bellard 已提交
2275
    if (rd == 0) {
2276
        /* Treat as NOP. */
B
bellard 已提交
2277 2278 2279
        MIPS_DEBUG("NOP");
        return;
    }
2280
    gen_load_gpr(cpu_T[0], rs);
B
bellard 已提交
2281 2282
    switch (opc) {
    case OPC_CLO:
2283
        tcg_gen_helper_0_0(do_clo);
B
bellard 已提交
2284 2285 2286
        opn = "clo";
        break;
    case OPC_CLZ:
2287
        tcg_gen_helper_0_0(do_clz);
B
bellard 已提交
2288 2289
        opn = "clz";
        break;
2290
#if defined(TARGET_MIPS64)
2291
    case OPC_DCLO:
2292
        tcg_gen_helper_0_0(do_dclo);
2293 2294 2295
        opn = "dclo";
        break;
    case OPC_DCLZ:
2296
        tcg_gen_helper_0_0(do_dclz);
2297 2298 2299
        opn = "dclz";
        break;
#endif
B
bellard 已提交
2300
    default:
2301
        MIPS_INVAL(opn);
B
bellard 已提交
2302 2303 2304
        generate_exception(ctx, EXCP_RI);
        return;
    }
2305
    gen_store_gpr(cpu_T[0], rd);
B
bellard 已提交
2306 2307 2308 2309
    MIPS_DEBUG("%s %s, %s", opn, regnames[rd], regnames[rs]);
}

/* Traps */
2310
static void gen_trap (DisasContext *ctx, uint32_t opc,
B
bellard 已提交
2311 2312 2313 2314 2315 2316 2317 2318 2319 2320 2321 2322 2323 2324 2325
                      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) {
2326 2327
            gen_load_gpr(cpu_T[0], rs);
            gen_load_gpr(cpu_T[1], rt);
B
bellard 已提交
2328 2329
            cond = 1;
        }
2330
        break;
B
bellard 已提交
2331 2332 2333 2334 2335 2336 2337 2338
    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) {
2339 2340
            gen_load_gpr(cpu_T[0], rs);
            tcg_gen_movi_tl(cpu_T[1], (int32_t)imm);
B
bellard 已提交
2341 2342 2343 2344 2345 2346 2347 2348 2349 2350 2351 2352 2353
            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 */
2354
            tcg_gen_movi_tl(cpu_T[0], 1);
B
bellard 已提交
2355 2356 2357 2358 2359 2360 2361
            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           */
2362
            /* Never trap: treat as NOP. */
B
bellard 已提交
2363 2364
            return;
        default:
2365
            MIPS_INVAL("trap");
B
bellard 已提交
2366 2367 2368 2369 2370 2371 2372 2373 2374 2375 2376 2377 2378 2379 2380 2381 2382 2383 2384 2385 2386 2387 2388 2389 2390 2391 2392 2393 2394 2395
            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:
2396
            MIPS_INVAL("trap");
B
bellard 已提交
2397 2398 2399 2400 2401
            generate_exception(ctx, EXCP_RI);
            return;
        }
    }
    save_cpu_state(ctx, 1);
T
ths 已提交
2402 2403 2404 2405 2406 2407 2408
    {
        int l1 = gen_new_label();

        tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_T[0], 0, l1);
        tcg_gen_helper_0_1i(do_raise_exception, EXCP_TRAP);
        gen_set_label(l1);
    }
B
bellard 已提交
2409 2410 2411
    ctx->bstate = BS_STOP;
}

2412
static always_inline void gen_goto_tb(DisasContext *ctx, int n, target_ulong dest)
B
bellard 已提交
2413
{
2414 2415 2416
    TranslationBlock *tb;
    tb = ctx->tb;
    if ((tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK)) {
B
bellard 已提交
2417
        tcg_gen_goto_tb(n);
2418
        gen_save_pc(dest);
B
bellard 已提交
2419
        tcg_gen_exit_tb((long)tb + n);
2420
    } else {
2421
        gen_save_pc(dest);
B
bellard 已提交
2422
        tcg_gen_exit_tb(0);
2423
    }
B
bellard 已提交
2424 2425
}

B
bellard 已提交
2426
/* Branches (before delay slot) */
2427
static void gen_compute_branch (DisasContext *ctx, uint32_t opc,
B
bellard 已提交
2428 2429
                                int rs, int rt, int32_t offset)
{
2430 2431 2432 2433 2434
    target_ulong btarget = -1;
    int blink = 0;
    int bcond = 0;

    if (ctx->hflags & MIPS_HFLAG_BMASK) {
2435
#ifdef MIPS_DEBUG_DISAS
2436 2437
        if (loglevel & CPU_LOG_TB_IN_ASM) {
            fprintf(logfile,
2438
                    "Branch in delay slot at PC 0x" TARGET_FMT_lx "\n",
2439
                    ctx->pc);
2440
	}
2441
#endif
2442 2443 2444
        generate_exception(ctx, EXCP_RI);
        return;
    }
B
bellard 已提交
2445 2446 2447 2448 2449 2450 2451 2452 2453

    /* Load needed operands */
    switch (opc) {
    case OPC_BEQ:
    case OPC_BEQL:
    case OPC_BNE:
    case OPC_BNEL:
        /* Compare two registers */
        if (rs != rt) {
2454 2455
            gen_load_gpr(cpu_T[0], rs);
            gen_load_gpr(cpu_T[1], rt);
B
bellard 已提交
2456 2457 2458 2459 2460 2461 2462 2463 2464 2465 2466 2467 2468 2469 2470 2471 2472 2473
            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) {
2474
            gen_load_gpr(cpu_T[0], rs);
B
bellard 已提交
2475 2476 2477 2478 2479 2480 2481
            bcond = 1;
        }
        btarget = ctx->pc + 4 + offset;
        break;
    case OPC_J:
    case OPC_JAL:
        /* Jump to immediate */
2482
        btarget = ((ctx->pc + 4) & (int32_t)0xF0000000) | (uint32_t)offset;
B
bellard 已提交
2483 2484 2485 2486
        break;
    case OPC_JR:
    case OPC_JALR:
        /* Jump to register */
2487 2488
        if (offset != 0 && offset != 16) {
            /* Hint = 0 is JR/JALR, hint 16 is JR.HB/JALR.HB, the
2489
               others are reserved. */
2490
            MIPS_INVAL("jump hint");
B
bellard 已提交
2491 2492 2493
            generate_exception(ctx, EXCP_RI);
            return;
        }
2494
        gen_save_breg_target(rs);
B
bellard 已提交
2495 2496 2497 2498 2499 2500 2501 2502 2503 2504 2505 2506 2507 2508 2509 2510
        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 已提交
2511
            ctx->hflags |= MIPS_HFLAG_B;
B
bellard 已提交
2512 2513 2514 2515 2516 2517
            MIPS_DEBUG("balways");
            break;
        case OPC_BGEZAL:  /* 0 >= 0          */
        case OPC_BGEZALL: /* 0 >= 0 likely   */
            /* Always take and link */
            blink = 31;
B
bellard 已提交
2518
            ctx->hflags |= MIPS_HFLAG_B;
B
bellard 已提交
2519 2520 2521 2522 2523
            MIPS_DEBUG("balways and link");
            break;
        case OPC_BNE:     /* rx != rx        */
        case OPC_BGTZ:    /* 0 > 0           */
        case OPC_BLTZ:    /* 0 < 0           */
2524
            /* Treat as NOP. */
B
bellard 已提交
2525 2526
            MIPS_DEBUG("bnever (NOP)");
            return;
2527
        case OPC_BLTZAL:  /* 0 < 0           */
2528 2529
            tcg_gen_movi_tl(cpu_T[0], ctx->pc + 8);
            gen_store_gpr(cpu_T[0], 31);
T
ths 已提交
2530
            MIPS_DEBUG("bnever and link");
2531 2532
            return;
        case OPC_BLTZALL: /* 0 < 0 likely */
2533 2534
            tcg_gen_movi_tl(cpu_T[0], ctx->pc + 8);
            gen_store_gpr(cpu_T[0], 31);
T
ths 已提交
2535 2536 2537
            /* Skip the instruction in the delay slot */
            MIPS_DEBUG("bnever, link and skip");
            ctx->pc += 4;
2538
            return;
B
bellard 已提交
2539 2540 2541 2542 2543
        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 已提交
2544
            ctx->pc += 4;
B
bellard 已提交
2545 2546
            return;
        case OPC_J:
B
bellard 已提交
2547
            ctx->hflags |= MIPS_HFLAG_B;
2548
            MIPS_DEBUG("j " TARGET_FMT_lx, btarget);
B
bellard 已提交
2549 2550 2551
            break;
        case OPC_JAL:
            blink = 31;
B
bellard 已提交
2552
            ctx->hflags |= MIPS_HFLAG_B;
2553
            MIPS_DEBUG("jal " TARGET_FMT_lx, btarget);
B
bellard 已提交
2554 2555
            break;
        case OPC_JR:
B
bellard 已提交
2556
            ctx->hflags |= MIPS_HFLAG_BR;
B
bellard 已提交
2557 2558 2559 2560
            MIPS_DEBUG("jr %s", regnames[rs]);
            break;
        case OPC_JALR:
            blink = rt;
B
bellard 已提交
2561
            ctx->hflags |= MIPS_HFLAG_BR;
B
bellard 已提交
2562 2563 2564 2565 2566 2567 2568 2569 2570 2571 2572
            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();
2573
            MIPS_DEBUG("beq %s, %s, " TARGET_FMT_lx,
B
bellard 已提交
2574 2575 2576 2577
                       regnames[rs], regnames[rt], btarget);
            goto not_likely;
        case OPC_BEQL:
            gen_op_eq();
2578
            MIPS_DEBUG("beql %s, %s, " TARGET_FMT_lx,
B
bellard 已提交
2579 2580 2581 2582
                       regnames[rs], regnames[rt], btarget);
            goto likely;
        case OPC_BNE:
            gen_op_ne();
2583
            MIPS_DEBUG("bne %s, %s, " TARGET_FMT_lx,
B
bellard 已提交
2584 2585 2586 2587
                       regnames[rs], regnames[rt], btarget);
            goto not_likely;
        case OPC_BNEL:
            gen_op_ne();
2588
            MIPS_DEBUG("bnel %s, %s, " TARGET_FMT_lx,
B
bellard 已提交
2589 2590 2591 2592
                       regnames[rs], regnames[rt], btarget);
            goto likely;
        case OPC_BGEZ:
            gen_op_gez();
2593
            MIPS_DEBUG("bgez %s, " TARGET_FMT_lx, regnames[rs], btarget);
B
bellard 已提交
2594 2595 2596
            goto not_likely;
        case OPC_BGEZL:
            gen_op_gez();
2597
            MIPS_DEBUG("bgezl %s, " TARGET_FMT_lx, regnames[rs], btarget);
B
bellard 已提交
2598 2599 2600
            goto likely;
        case OPC_BGEZAL:
            gen_op_gez();
2601
            MIPS_DEBUG("bgezal %s, " TARGET_FMT_lx, regnames[rs], btarget);
B
bellard 已提交
2602 2603 2604 2605 2606
            blink = 31;
            goto not_likely;
        case OPC_BGEZALL:
            gen_op_gez();
            blink = 31;
2607
            MIPS_DEBUG("bgezall %s, " TARGET_FMT_lx, regnames[rs], btarget);
B
bellard 已提交
2608 2609 2610
            goto likely;
        case OPC_BGTZ:
            gen_op_gtz();
2611
            MIPS_DEBUG("bgtz %s, " TARGET_FMT_lx, regnames[rs], btarget);
B
bellard 已提交
2612 2613 2614
            goto not_likely;
        case OPC_BGTZL:
            gen_op_gtz();
2615
            MIPS_DEBUG("bgtzl %s, " TARGET_FMT_lx, regnames[rs], btarget);
B
bellard 已提交
2616 2617 2618
            goto likely;
        case OPC_BLEZ:
            gen_op_lez();
2619
            MIPS_DEBUG("blez %s, " TARGET_FMT_lx, regnames[rs], btarget);
B
bellard 已提交
2620 2621 2622
            goto not_likely;
        case OPC_BLEZL:
            gen_op_lez();
2623
            MIPS_DEBUG("blezl %s, " TARGET_FMT_lx, regnames[rs], btarget);
B
bellard 已提交
2624 2625 2626
            goto likely;
        case OPC_BLTZ:
            gen_op_ltz();
2627
            MIPS_DEBUG("bltz %s, " TARGET_FMT_lx, regnames[rs], btarget);
B
bellard 已提交
2628 2629 2630
            goto not_likely;
        case OPC_BLTZL:
            gen_op_ltz();
2631
            MIPS_DEBUG("bltzl %s, " TARGET_FMT_lx, regnames[rs], btarget);
B
bellard 已提交
2632 2633 2634 2635
            goto likely;
        case OPC_BLTZAL:
            gen_op_ltz();
            blink = 31;
2636
            MIPS_DEBUG("bltzal %s, " TARGET_FMT_lx, regnames[rs], btarget);
B
bellard 已提交
2637
        not_likely:
B
bellard 已提交
2638
            ctx->hflags |= MIPS_HFLAG_BC;
2639
            tcg_gen_st_tl(cpu_T[0], cpu_env, offsetof(CPUState, bcond));
B
bellard 已提交
2640 2641 2642 2643
            break;
        case OPC_BLTZALL:
            gen_op_ltz();
            blink = 31;
2644
            MIPS_DEBUG("bltzall %s, " TARGET_FMT_lx, regnames[rs], btarget);
B
bellard 已提交
2645
        likely:
B
bellard 已提交
2646
            ctx->hflags |= MIPS_HFLAG_BL;
2647
            tcg_gen_st_tl(cpu_T[0], cpu_env, offsetof(CPUState, bcond));
B
bellard 已提交
2648
            break;
T
ths 已提交
2649 2650 2651 2652
        default:
            MIPS_INVAL("conditional branch/jump");
            generate_exception(ctx, EXCP_RI);
            return;
B
bellard 已提交
2653 2654
        }
    }
2655
    MIPS_DEBUG("enter ds: link %d cond %02x target " TARGET_FMT_lx,
B
bellard 已提交
2656
               blink, ctx->hflags, btarget);
2657

B
bellard 已提交
2658 2659
    ctx->btarget = btarget;
    if (blink > 0) {
2660 2661
        tcg_gen_movi_tl(cpu_T[0], ctx->pc + 8);
        gen_store_gpr(cpu_T[0], blink);
B
bellard 已提交
2662 2663 2664
    }
}

2665 2666 2667 2668
/* special3 bitfield operations */
static void gen_bitops (DisasContext *ctx, uint32_t opc, int rt,
                       int rs, int lsb, int msb)
{
2669
    gen_load_gpr(cpu_T[1], rs);
2670 2671 2672 2673
    switch (opc) {
    case OPC_EXT:
        if (lsb + msb > 31)
            goto fail;
2674
        tcg_gen_helper_0_2ii(do_ext, lsb, msb + 1);
2675
        break;
T
ths 已提交
2676
#if defined(TARGET_MIPS64)
2677 2678 2679
    case OPC_DEXTM:
        if (lsb + msb > 63)
            goto fail;
2680
        tcg_gen_helper_0_2ii(do_dext, lsb, msb + 1 + 32);
2681 2682 2683 2684
        break;
    case OPC_DEXTU:
        if (lsb + msb > 63)
            goto fail;
2685
        tcg_gen_helper_0_2ii(do_dext, lsb + 32, msb + 1);
2686 2687
        break;
    case OPC_DEXT:
T
ths 已提交
2688 2689
        if (lsb + msb > 63)
            goto fail;
2690
        tcg_gen_helper_0_2ii(do_dext, lsb, msb + 1);
2691
        break;
T
ths 已提交
2692
#endif
2693 2694 2695
    case OPC_INS:
        if (lsb > msb)
            goto fail;
2696
        gen_load_gpr(cpu_T[0], rt);
2697
        tcg_gen_helper_0_2ii(do_ins, lsb, msb - lsb + 1);
2698
        break;
T
ths 已提交
2699
#if defined(TARGET_MIPS64)
2700 2701 2702
    case OPC_DINSM:
        if (lsb > msb)
            goto fail;
2703
        gen_load_gpr(cpu_T[0], rt);
2704
        tcg_gen_helper_0_2ii(do_dins, lsb, msb - lsb + 1 + 32);
2705 2706 2707 2708
        break;
    case OPC_DINSU:
        if (lsb > msb)
            goto fail;
2709
        gen_load_gpr(cpu_T[0], rt);
2710
        tcg_gen_helper_0_2ii(do_dins, lsb + 32, msb - lsb + 1);
2711 2712 2713 2714
        break;
    case OPC_DINS:
        if (lsb > msb)
            goto fail;
2715
        gen_load_gpr(cpu_T[0], rt);
2716
        tcg_gen_helper_0_2ii(do_dins, lsb, msb - lsb + 1);
2717
        break;
T
ths 已提交
2718
#endif
2719 2720 2721 2722 2723 2724
    default:
fail:
        MIPS_INVAL("bitops");
        generate_exception(ctx, EXCP_RI);
        return;
    }
2725
    gen_store_gpr(cpu_T[0], rt);
2726 2727
}

B
bellard 已提交
2728
/* CP0 (MMU and control) */
2729
#ifndef CONFIG_USER_ONLY
T
ths 已提交
2730 2731 2732 2733 2734 2735 2736 2737 2738 2739 2740
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 已提交
2741 2742
    tcg_gen_ld_tl(t, cpu_env, off);
    tcg_gen_ext32s_tl(t, t);
T
ths 已提交
2743 2744
}

2745 2746 2747 2748 2749 2750 2751 2752 2753 2754 2755
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 已提交
2756 2757
    tcg_gen_ext32s_tl(t, t);
    tcg_gen_st_tl(t, cpu_env, off);
2758 2759
}

2760
static void gen_mfc0 (CPUState *env, DisasContext *ctx, int reg, int sel)
2761
{
2762
    const char *rn = "invalid";
2763

2764 2765 2766
    if (sel != 0)
        check_insn(env, ctx, ISA_MIPS32);

2767 2768
    switch (reg) {
    case 0:
2769 2770
        switch (sel) {
        case 0:
T
ths 已提交
2771
            gen_mfc0_load32(cpu_T[0], offsetof(CPUState, CP0_Index));
2772 2773 2774
            rn = "Index";
            break;
        case 1:
2775
            check_insn(env, ctx, ASE_MT);
2776
            tcg_gen_helper_0_0(do_mfc0_mvpcontrol);
2777
            rn = "MVPControl";
2778
            break;
2779
        case 2:
2780
            check_insn(env, ctx, ASE_MT);
2781
            tcg_gen_helper_0_0(do_mfc0_mvpconf0);
2782
            rn = "MVPConf0";
2783
            break;
2784
        case 3:
2785
            check_insn(env, ctx, ASE_MT);
2786
            tcg_gen_helper_0_0(do_mfc0_mvpconf1);
2787
            rn = "MVPConf1";
2788
            break;
2789 2790 2791
        default:
            goto die;
        }
2792 2793
        break;
    case 1:
2794 2795
        switch (sel) {
        case 0:
2796
            tcg_gen_helper_0_0(do_mfc0_random);
2797
            rn = "Random";
T
ths 已提交
2798
            break;
2799
        case 1:
2800
            check_insn(env, ctx, ASE_MT);
T
ths 已提交
2801
            gen_mfc0_load32(cpu_T[0], offsetof(CPUState, CP0_VPEControl));
2802
            rn = "VPEControl";
2803
            break;
2804
        case 2:
2805
            check_insn(env, ctx, ASE_MT);
T
ths 已提交
2806
            gen_mfc0_load32(cpu_T[0], offsetof(CPUState, CP0_VPEConf0));
2807
            rn = "VPEConf0";
2808
            break;
2809
        case 3:
2810
            check_insn(env, ctx, ASE_MT);
T
ths 已提交
2811
            gen_mfc0_load32(cpu_T[0], offsetof(CPUState, CP0_VPEConf1));
2812
            rn = "VPEConf1";
2813
            break;
2814
        case 4:
2815
            check_insn(env, ctx, ASE_MT);
T
ths 已提交
2816
            gen_mfc0_load64(cpu_T[0], offsetof(CPUState, CP0_YQMask));
2817
            rn = "YQMask";
2818
            break;
2819
        case 5:
2820
            check_insn(env, ctx, ASE_MT);
T
ths 已提交
2821
            gen_mfc0_load64(cpu_T[0], offsetof(CPUState, CP0_VPESchedule));
2822
            rn = "VPESchedule";
2823
            break;
2824
        case 6:
2825
            check_insn(env, ctx, ASE_MT);
T
ths 已提交
2826
            gen_mfc0_load64(cpu_T[0], offsetof(CPUState, CP0_VPEScheFBack));
2827
            rn = "VPEScheFBack";
2828
            break;
2829
        case 7:
2830
            check_insn(env, ctx, ASE_MT);
T
ths 已提交
2831
            gen_mfc0_load32(cpu_T[0], offsetof(CPUState, CP0_VPEOpt));
2832
            rn = "VPEOpt";
2833
            break;
2834 2835 2836
        default:
            goto die;
        }
2837 2838
        break;
    case 2:
2839 2840
        switch (sel) {
        case 0:
T
ths 已提交
2841 2842
            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 已提交
2843 2844
            rn = "EntryLo0";
            break;
2845
        case 1:
2846
            check_insn(env, ctx, ASE_MT);
2847
            tcg_gen_helper_0_0(do_mfc0_tcstatus);
T
ths 已提交
2848
            rn = "TCStatus";
2849
            break;
2850
        case 2:
2851
            check_insn(env, ctx, ASE_MT);
2852
            tcg_gen_helper_0_0(do_mfc0_tcbind);
T
ths 已提交
2853
            rn = "TCBind";
2854
            break;
2855
        case 3:
2856
            check_insn(env, ctx, ASE_MT);
2857
            tcg_gen_helper_0_0(do_mfc0_tcrestart);
T
ths 已提交
2858
            rn = "TCRestart";
2859
            break;
2860
        case 4:
2861
            check_insn(env, ctx, ASE_MT);
2862
            tcg_gen_helper_0_0(do_mfc0_tchalt);
T
ths 已提交
2863
            rn = "TCHalt";
2864
            break;
2865
        case 5:
2866
            check_insn(env, ctx, ASE_MT);
2867
            tcg_gen_helper_0_0(do_mfc0_tccontext);
T
ths 已提交
2868
            rn = "TCContext";
2869
            break;
2870
        case 6:
2871
            check_insn(env, ctx, ASE_MT);
2872
            tcg_gen_helper_0_0(do_mfc0_tcschedule);
T
ths 已提交
2873
            rn = "TCSchedule";
2874
            break;
2875
        case 7:
2876
            check_insn(env, ctx, ASE_MT);
2877
            tcg_gen_helper_0_0(do_mfc0_tcschefback);
T
ths 已提交
2878
            rn = "TCScheFBack";
2879
            break;
2880 2881 2882
        default:
            goto die;
        }
2883 2884
        break;
    case 3:
2885 2886
        switch (sel) {
        case 0:
T
ths 已提交
2887 2888
            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 已提交
2889 2890
            rn = "EntryLo1";
            break;
2891 2892
        default:
            goto die;
2893
        }
2894 2895
        break;
    case 4:
2896 2897
        switch (sel) {
        case 0:
T
ths 已提交
2898 2899
            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 已提交
2900 2901
            rn = "Context";
            break;
2902
        case 1:
2903
//            tcg_gen_helper_0_0(do_mfc0_contextconfig); /* SmartMIPS ASE */
T
ths 已提交
2904 2905
            rn = "ContextConfig";
//            break;
2906 2907
        default:
            goto die;
2908
        }
2909 2910
        break;
    case 5:
2911 2912
        switch (sel) {
        case 0:
T
ths 已提交
2913
            gen_mfc0_load32(cpu_T[0], offsetof(CPUState, CP0_PageMask));
T
ths 已提交
2914 2915
            rn = "PageMask";
            break;
2916
        case 1:
2917
            check_insn(env, ctx, ISA_MIPS32R2);
T
ths 已提交
2918
            gen_mfc0_load32(cpu_T[0], offsetof(CPUState, CP0_PageGrain));
T
ths 已提交
2919 2920
            rn = "PageGrain";
            break;
2921 2922
        default:
            goto die;
2923
        }
2924 2925
        break;
    case 6:
2926 2927
        switch (sel) {
        case 0:
T
ths 已提交
2928
            gen_mfc0_load32(cpu_T[0], offsetof(CPUState, CP0_Wired));
T
ths 已提交
2929 2930
            rn = "Wired";
            break;
2931
        case 1:
2932
            check_insn(env, ctx, ISA_MIPS32R2);
T
ths 已提交
2933
            gen_mfc0_load32(cpu_T[0], offsetof(CPUState, CP0_SRSConf0));
T
ths 已提交
2934
            rn = "SRSConf0";
2935
            break;
2936
        case 2:
2937
            check_insn(env, ctx, ISA_MIPS32R2);
T
ths 已提交
2938
            gen_mfc0_load32(cpu_T[0], offsetof(CPUState, CP0_SRSConf1));
T
ths 已提交
2939
            rn = "SRSConf1";
2940
            break;
2941
        case 3:
2942
            check_insn(env, ctx, ISA_MIPS32R2);
T
ths 已提交
2943
            gen_mfc0_load32(cpu_T[0], offsetof(CPUState, CP0_SRSConf2));
T
ths 已提交
2944
            rn = "SRSConf2";
2945
            break;
2946
        case 4:
2947
            check_insn(env, ctx, ISA_MIPS32R2);
T
ths 已提交
2948
            gen_mfc0_load32(cpu_T[0], offsetof(CPUState, CP0_SRSConf3));
T
ths 已提交
2949
            rn = "SRSConf3";
2950
            break;
2951
        case 5:
2952
            check_insn(env, ctx, ISA_MIPS32R2);
T
ths 已提交
2953
            gen_mfc0_load32(cpu_T[0], offsetof(CPUState, CP0_SRSConf4));
T
ths 已提交
2954
            rn = "SRSConf4";
2955
            break;
2956 2957
        default:
            goto die;
2958
        }
2959
        break;
2960
    case 7:
2961 2962
        switch (sel) {
        case 0:
2963
            check_insn(env, ctx, ISA_MIPS32R2);
T
ths 已提交
2964
            gen_mfc0_load32(cpu_T[0], offsetof(CPUState, CP0_HWREna));
T
ths 已提交
2965 2966
            rn = "HWREna";
            break;
2967 2968
        default:
            goto die;
2969
        }
2970
        break;
2971
    case 8:
2972 2973
        switch (sel) {
        case 0:
T
ths 已提交
2974 2975 2976
            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 已提交
2977
            break;
2978 2979 2980
        default:
            goto die;
       }
2981 2982
        break;
    case 9:
2983 2984
        switch (sel) {
        case 0:
2985
            tcg_gen_helper_0_0(do_mfc0_count);
T
ths 已提交
2986 2987 2988
            rn = "Count";
            break;
        /* 6,7 are implementation dependent */
2989 2990
        default:
            goto die;
T
ths 已提交
2991
        }
2992 2993
        break;
    case 10:
2994 2995
        switch (sel) {
        case 0:
T
ths 已提交
2996 2997
            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 已提交
2998 2999
            rn = "EntryHi";
            break;
3000 3001
        default:
            goto die;
3002
        }
3003 3004
        break;
    case 11:
3005 3006
        switch (sel) {
        case 0:
T
ths 已提交
3007
            gen_mfc0_load32(cpu_T[0], offsetof(CPUState, CP0_Compare));
T
ths 已提交
3008 3009 3010
            rn = "Compare";
            break;
        /* 6,7 are implementation dependent */
3011 3012
        default:
            goto die;
T
ths 已提交
3013
        }
3014 3015
        break;
    case 12:
3016 3017
        switch (sel) {
        case 0:
T
ths 已提交
3018
            gen_mfc0_load32(cpu_T[0], offsetof(CPUState, CP0_Status));
T
ths 已提交
3019 3020
            rn = "Status";
            break;
3021
        case 1:
3022
            check_insn(env, ctx, ISA_MIPS32R2);
T
ths 已提交
3023
            gen_mfc0_load32(cpu_T[0], offsetof(CPUState, CP0_IntCtl));
T
ths 已提交
3024 3025
            rn = "IntCtl";
            break;
3026
        case 2:
3027
            check_insn(env, ctx, ISA_MIPS32R2);
T
ths 已提交
3028
            gen_mfc0_load32(cpu_T[0], offsetof(CPUState, CP0_SRSCtl));
T
ths 已提交
3029 3030
            rn = "SRSCtl";
            break;
3031
        case 3:
3032
            check_insn(env, ctx, ISA_MIPS32R2);
T
ths 已提交
3033
            gen_mfc0_load32(cpu_T[0], offsetof(CPUState, CP0_SRSMap));
T
ths 已提交
3034
            rn = "SRSMap";
3035
            break;
3036 3037 3038
        default:
            goto die;
       }
3039 3040
        break;
    case 13:
3041 3042
        switch (sel) {
        case 0:
T
ths 已提交
3043
            gen_mfc0_load32(cpu_T[0], offsetof(CPUState, CP0_Cause));
T
ths 已提交
3044 3045
            rn = "Cause";
            break;
3046 3047 3048
        default:
            goto die;
       }
3049 3050
        break;
    case 14:
3051 3052
        switch (sel) {
        case 0:
T
ths 已提交
3053 3054
            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 已提交
3055 3056
            rn = "EPC";
            break;
3057 3058
        default:
            goto die;
3059
        }
3060 3061
        break;
    case 15:
3062 3063
        switch (sel) {
        case 0:
T
ths 已提交
3064
            gen_mfc0_load32(cpu_T[0], offsetof(CPUState, CP0_PRid));
T
ths 已提交
3065 3066
            rn = "PRid";
            break;
3067
        case 1:
3068
            check_insn(env, ctx, ISA_MIPS32R2);
T
ths 已提交
3069
            gen_mfc0_load32(cpu_T[0], offsetof(CPUState, CP0_EBase));
T
ths 已提交
3070 3071
            rn = "EBase";
            break;
3072 3073 3074
        default:
            goto die;
       }
3075 3076 3077 3078
        break;
    case 16:
        switch (sel) {
        case 0:
T
ths 已提交
3079
            gen_mfc0_load32(cpu_T[0], offsetof(CPUState, CP0_Config0));
3080 3081 3082
            rn = "Config";
            break;
        case 1:
T
ths 已提交
3083
            gen_mfc0_load32(cpu_T[0], offsetof(CPUState, CP0_Config1));
3084 3085
            rn = "Config1";
            break;
3086
        case 2:
T
ths 已提交
3087
            gen_mfc0_load32(cpu_T[0], offsetof(CPUState, CP0_Config2));
3088 3089 3090
            rn = "Config2";
            break;
        case 3:
T
ths 已提交
3091
            gen_mfc0_load32(cpu_T[0], offsetof(CPUState, CP0_Config3));
3092 3093
            rn = "Config3";
            break;
3094 3095 3096
        /* 4,5 are reserved */
        /* 6,7 are implementation dependent */
        case 6:
T
ths 已提交
3097
            gen_mfc0_load32(cpu_T[0], offsetof(CPUState, CP0_Config6));
3098 3099 3100
            rn = "Config6";
            break;
        case 7:
T
ths 已提交
3101
            gen_mfc0_load32(cpu_T[0], offsetof(CPUState, CP0_Config7));
3102 3103
            rn = "Config7";
            break;
3104 3105 3106 3107 3108
        default:
            goto die;
        }
        break;
    case 17:
3109 3110
        switch (sel) {
        case 0:
3111
            tcg_gen_helper_0_0(do_mfc0_lladdr);
T
ths 已提交
3112 3113
            rn = "LLAddr";
            break;
3114 3115 3116
        default:
            goto die;
        }
3117 3118
        break;
    case 18:
3119
        switch (sel) {
3120
        case 0 ... 7:
3121
            tcg_gen_helper_0_1i(do_mfc0_watchlo, sel);
T
ths 已提交
3122 3123
            rn = "WatchLo";
            break;
3124 3125 3126
        default:
            goto die;
        }
3127 3128
        break;
    case 19:
3129
        switch (sel) {
3130
        case 0 ...7:
3131
            tcg_gen_helper_0_1i(do_mfc0_watchhi, sel);
T
ths 已提交
3132 3133
            rn = "WatchHi";
            break;
3134 3135 3136
        default:
            goto die;
        }
3137
        break;
3138
    case 20:
3139 3140
        switch (sel) {
        case 0:
3141
#if defined(TARGET_MIPS64)
3142
            check_insn(env, ctx, ISA_MIPS3);
T
ths 已提交
3143 3144
            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 已提交
3145 3146
            rn = "XContext";
            break;
T
ths 已提交
3147
#endif
3148 3149 3150
        default:
            goto die;
        }
3151 3152
        break;
    case 21:
3153 3154 3155
       /* Officially reserved, but sel 0 is used for R1x000 framemask */
        switch (sel) {
        case 0:
T
ths 已提交
3156
            gen_mfc0_load32(cpu_T[0], offsetof(CPUState, CP0_Framemask));
T
ths 已提交
3157 3158
            rn = "Framemask";
            break;
3159 3160 3161
        default:
            goto die;
        }
3162 3163
        break;
    case 22:
T
ths 已提交
3164 3165 3166
        /* ignored */
        rn = "'Diagnostic"; /* implementation dependent */
        break;
3167
    case 23:
3168 3169
        switch (sel) {
        case 0:
3170
            tcg_gen_helper_0_0(do_mfc0_debug); /* EJTAG support */
T
ths 已提交
3171 3172
            rn = "Debug";
            break;
3173
        case 1:
3174
//            tcg_gen_helper_0_0(do_mfc0_tracecontrol); /* PDtrace support */
T
ths 已提交
3175 3176
            rn = "TraceControl";
//            break;
3177
        case 2:
3178
//            tcg_gen_helper_0_0(do_mfc0_tracecontrol2); /* PDtrace support */
T
ths 已提交
3179 3180
            rn = "TraceControl2";
//            break;
3181
        case 3:
3182
//            tcg_gen_helper_0_0(do_mfc0_usertracedata); /* PDtrace support */
T
ths 已提交
3183 3184
            rn = "UserTraceData";
//            break;
3185
        case 4:
3186
//            tcg_gen_helper_0_0(do_mfc0_debug); /* PDtrace support */
T
ths 已提交
3187 3188
            rn = "TraceBPC";
//            break;
3189 3190 3191
        default:
            goto die;
        }
3192 3193
        break;
    case 24:
3194 3195
        switch (sel) {
        case 0:
T
ths 已提交
3196 3197 3198
            /* 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 已提交
3199 3200
            rn = "DEPC";
            break;
3201 3202 3203
        default:
            goto die;
        }
3204
        break;
3205
    case 25:
3206 3207
        switch (sel) {
        case 0:
T
ths 已提交
3208
            gen_mfc0_load32(cpu_T[0], offsetof(CPUState, CP0_Performance0));
T
ths 已提交
3209
            rn = "Performance0";
3210 3211
            break;
        case 1:
3212
//            tcg_gen_helper_0_0(do_mfc0_performance1);
T
ths 已提交
3213 3214
            rn = "Performance1";
//            break;
3215
        case 2:
3216
//            tcg_gen_helper_0_0(do_mfc0_performance2);
T
ths 已提交
3217 3218
            rn = "Performance2";
//            break;
3219
        case 3:
3220
//            tcg_gen_helper_0_0(do_mfc0_performance3);
T
ths 已提交
3221 3222
            rn = "Performance3";
//            break;
3223
        case 4:
3224
//            tcg_gen_helper_0_0(do_mfc0_performance4);
T
ths 已提交
3225 3226
            rn = "Performance4";
//            break;
3227
        case 5:
3228
//            tcg_gen_helper_0_0(do_mfc0_performance5);
T
ths 已提交
3229 3230
            rn = "Performance5";
//            break;
3231
        case 6:
3232
//            tcg_gen_helper_0_0(do_mfc0_performance6);
T
ths 已提交
3233 3234
            rn = "Performance6";
//            break;
3235
        case 7:
3236
//            tcg_gen_helper_0_0(do_mfc0_performance7);
T
ths 已提交
3237 3238
            rn = "Performance7";
//            break;
3239 3240 3241
        default:
            goto die;
        }
3242 3243
        break;
    case 26:
3244 3245
       rn = "ECC";
       break;
3246
    case 27:
3247 3248 3249
        switch (sel) {
        /* ignored */
        case 0 ... 3:
T
ths 已提交
3250 3251
            rn = "CacheErr";
            break;
3252 3253 3254
        default:
            goto die;
        }
3255
        break;
3256 3257 3258
    case 28:
        switch (sel) {
        case 0:
3259 3260 3261
        case 2:
        case 4:
        case 6:
T
ths 已提交
3262
            gen_mfc0_load32(cpu_T[0], offsetof(CPUState, CP0_TagLo));
3263 3264 3265
            rn = "TagLo";
            break;
        case 1:
3266 3267 3268
        case 3:
        case 5:
        case 7:
T
ths 已提交
3269
            gen_mfc0_load32(cpu_T[0], offsetof(CPUState, CP0_DataLo));
3270 3271 3272 3273 3274 3275
            rn = "DataLo";
            break;
        default:
            goto die;
        }
        break;
3276
    case 29:
3277 3278 3279 3280 3281
        switch (sel) {
        case 0:
        case 2:
        case 4:
        case 6:
T
ths 已提交
3282
            gen_mfc0_load32(cpu_T[0], offsetof(CPUState, CP0_TagHi));
3283 3284 3285 3286 3287 3288
            rn = "TagHi";
            break;
        case 1:
        case 3:
        case 5:
        case 7:
T
ths 已提交
3289
            gen_mfc0_load32(cpu_T[0], offsetof(CPUState, CP0_DataHi));
3290 3291 3292 3293 3294
            rn = "DataHi";
            break;
        default:
            goto die;
        }
3295
        break;
3296
    case 30:
3297 3298
        switch (sel) {
        case 0:
T
ths 已提交
3299 3300
            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 已提交
3301 3302
            rn = "ErrorEPC";
            break;
3303 3304 3305
        default:
            goto die;
        }
3306 3307
        break;
    case 31:
3308 3309
        switch (sel) {
        case 0:
T
ths 已提交
3310
            /* EJTAG support */
T
ths 已提交
3311
            gen_mfc0_load32(cpu_T[0], offsetof(CPUState, CP0_DESAVE));
T
ths 已提交
3312 3313
            rn = "DESAVE";
            break;
3314 3315 3316
        default:
            goto die;
        }
3317 3318 3319 3320 3321 3322
        break;
    default:
       goto die;
    }
#if defined MIPS_DEBUG_DISAS
    if (loglevel & CPU_LOG_TB_IN_ASM) {
3323 3324
        fprintf(logfile, "mfc0 %s (reg %d sel %d)\n",
                rn, reg, sel);
3325 3326 3327 3328 3329 3330 3331
    }
#endif
    return;

die:
#if defined MIPS_DEBUG_DISAS
    if (loglevel & CPU_LOG_TB_IN_ASM) {
3332 3333
        fprintf(logfile, "mfc0 %s (reg %d sel %d)\n",
                rn, reg, sel);
3334 3335 3336 3337 3338
    }
#endif
    generate_exception(ctx, EXCP_RI);
}

3339
static void gen_mtc0 (CPUState *env, DisasContext *ctx, int reg, int sel)
3340
{
3341 3342
    const char *rn = "invalid";

3343 3344 3345
    if (sel != 0)
        check_insn(env, ctx, ISA_MIPS32);

3346 3347
    switch (reg) {
    case 0:
3348 3349
        switch (sel) {
        case 0:
3350
            tcg_gen_helper_0_0(do_mtc0_index);
3351 3352 3353
            rn = "Index";
            break;
        case 1:
3354
            check_insn(env, ctx, ASE_MT);
3355
            tcg_gen_helper_0_0(do_mtc0_mvpcontrol);
3356
            rn = "MVPControl";
3357
            break;
3358
        case 2:
3359
            check_insn(env, ctx, ASE_MT);
3360
            /* ignored */
3361
            rn = "MVPConf0";
3362
            break;
3363
        case 3:
3364
            check_insn(env, ctx, ASE_MT);
3365
            /* ignored */
3366
            rn = "MVPConf1";
3367
            break;
3368 3369 3370
        default:
            goto die;
        }
3371 3372
        break;
    case 1:
3373 3374
        switch (sel) {
        case 0:
T
ths 已提交
3375
            /* ignored */
3376
            rn = "Random";
T
ths 已提交
3377
            break;
3378
        case 1:
3379
            check_insn(env, ctx, ASE_MT);
3380
            tcg_gen_helper_0_0(do_mtc0_vpecontrol);
3381
            rn = "VPEControl";
3382
            break;
3383
        case 2:
3384
            check_insn(env, ctx, ASE_MT);
3385
            tcg_gen_helper_0_0(do_mtc0_vpeconf0);
3386
            rn = "VPEConf0";
3387
            break;
3388
        case 3:
3389
            check_insn(env, ctx, ASE_MT);
3390
            tcg_gen_helper_0_0(do_mtc0_vpeconf1);
3391
            rn = "VPEConf1";
3392
            break;
3393
        case 4:
3394
            check_insn(env, ctx, ASE_MT);
3395
            tcg_gen_helper_0_0(do_mtc0_yqmask);
3396
            rn = "YQMask";
3397
            break;
3398
        case 5:
3399
            check_insn(env, ctx, ASE_MT);
3400
            gen_mtc0_store64(cpu_T[0], offsetof(CPUState, CP0_VPESchedule));
3401
            rn = "VPESchedule";
3402
            break;
3403
        case 6:
3404
            check_insn(env, ctx, ASE_MT);
3405
            gen_mtc0_store64(cpu_T[0], offsetof(CPUState, CP0_VPEScheFBack));
3406
            rn = "VPEScheFBack";
3407
            break;
3408
        case 7:
3409
            check_insn(env, ctx, ASE_MT);
3410
            tcg_gen_helper_0_0(do_mtc0_vpeopt);
3411
            rn = "VPEOpt";
3412
            break;
3413 3414 3415
        default:
            goto die;
        }
3416 3417
        break;
    case 2:
3418 3419
        switch (sel) {
        case 0:
3420
            tcg_gen_helper_0_0(do_mtc0_entrylo0);
T
ths 已提交
3421 3422
            rn = "EntryLo0";
            break;
3423
        case 1:
3424
            check_insn(env, ctx, ASE_MT);
3425
            tcg_gen_helper_0_0(do_mtc0_tcstatus);
T
ths 已提交
3426
            rn = "TCStatus";
3427
            break;
3428
        case 2:
3429
            check_insn(env, ctx, ASE_MT);
3430
            tcg_gen_helper_0_0(do_mtc0_tcbind);
T
ths 已提交
3431
            rn = "TCBind";
3432
            break;
3433
        case 3:
3434
            check_insn(env, ctx, ASE_MT);
3435
            tcg_gen_helper_0_0(do_mtc0_tcrestart);
T
ths 已提交
3436
            rn = "TCRestart";
3437
            break;
3438
        case 4:
3439
            check_insn(env, ctx, ASE_MT);
3440
            tcg_gen_helper_0_0(do_mtc0_tchalt);
T
ths 已提交
3441
            rn = "TCHalt";
3442
            break;
3443
        case 5:
3444
            check_insn(env, ctx, ASE_MT);
3445
            tcg_gen_helper_0_0(do_mtc0_tccontext);
T
ths 已提交
3446
            rn = "TCContext";
3447
            break;
3448
        case 6:
3449
            check_insn(env, ctx, ASE_MT);
3450
            tcg_gen_helper_0_0(do_mtc0_tcschedule);
T
ths 已提交
3451
            rn = "TCSchedule";
3452
            break;
3453
        case 7:
3454
            check_insn(env, ctx, ASE_MT);
3455
            tcg_gen_helper_0_0(do_mtc0_tcschefback);
T
ths 已提交
3456
            rn = "TCScheFBack";
3457
            break;
3458 3459 3460
        default:
            goto die;
        }
3461 3462
        break;
    case 3:
3463 3464
        switch (sel) {
        case 0:
3465
            tcg_gen_helper_0_0(do_mtc0_entrylo1);
T
ths 已提交
3466 3467
            rn = "EntryLo1";
            break;
3468 3469
        default:
            goto die;
T
ths 已提交
3470
        }
3471 3472
        break;
    case 4:
3473 3474
        switch (sel) {
        case 0:
3475
            tcg_gen_helper_0_0(do_mtc0_context);
T
ths 已提交
3476 3477
            rn = "Context";
            break;
3478
        case 1:
3479
//            tcg_gen_helper_0_0(do_mtc0_contextconfig); /* SmartMIPS ASE */
T
ths 已提交
3480 3481
            rn = "ContextConfig";
//            break;
3482 3483
        default:
            goto die;
T
ths 已提交
3484
        }
3485 3486
        break;
    case 5:
3487 3488
        switch (sel) {
        case 0:
3489
            tcg_gen_helper_0_0(do_mtc0_pagemask);
T
ths 已提交
3490 3491
            rn = "PageMask";
            break;
3492
        case 1:
3493
            check_insn(env, ctx, ISA_MIPS32R2);
3494
            tcg_gen_helper_0_0(do_mtc0_pagegrain);
T
ths 已提交
3495 3496
            rn = "PageGrain";
            break;
3497 3498
        default:
            goto die;
T
ths 已提交
3499
        }
3500 3501
        break;
    case 6:
3502 3503
        switch (sel) {
        case 0:
3504
            tcg_gen_helper_0_0(do_mtc0_wired);
T
ths 已提交
3505 3506
            rn = "Wired";
            break;
3507
        case 1:
3508
            check_insn(env, ctx, ISA_MIPS32R2);
3509
            tcg_gen_helper_0_0(do_mtc0_srsconf0);
T
ths 已提交
3510
            rn = "SRSConf0";
3511
            break;
3512
        case 2:
3513
            check_insn(env, ctx, ISA_MIPS32R2);
3514
            tcg_gen_helper_0_0(do_mtc0_srsconf1);
T
ths 已提交
3515
            rn = "SRSConf1";
3516
            break;
3517
        case 3:
3518
            check_insn(env, ctx, ISA_MIPS32R2);
3519
            tcg_gen_helper_0_0(do_mtc0_srsconf2);
T
ths 已提交
3520
            rn = "SRSConf2";
3521
            break;
3522
        case 4:
3523
            check_insn(env, ctx, ISA_MIPS32R2);
3524
            tcg_gen_helper_0_0(do_mtc0_srsconf3);
T
ths 已提交
3525
            rn = "SRSConf3";
3526
            break;
3527
        case 5:
3528
            check_insn(env, ctx, ISA_MIPS32R2);
3529
            tcg_gen_helper_0_0(do_mtc0_srsconf4);
T
ths 已提交
3530
            rn = "SRSConf4";
3531
            break;
3532 3533
        default:
            goto die;
T
ths 已提交
3534
        }
3535 3536
        break;
    case 7:
3537 3538
        switch (sel) {
        case 0:
3539
            check_insn(env, ctx, ISA_MIPS32R2);
3540
            tcg_gen_helper_0_0(do_mtc0_hwrena);
T
ths 已提交
3541 3542
            rn = "HWREna";
            break;
3543 3544
        default:
            goto die;
T
ths 已提交
3545
        }
3546 3547
        break;
    case 8:
3548
        /* ignored */
T
ths 已提交
3549
        rn = "BadVAddr";
3550 3551
        break;
    case 9:
3552 3553
        switch (sel) {
        case 0:
3554
            tcg_gen_helper_0_0(do_mtc0_count);
T
ths 已提交
3555 3556
            rn = "Count";
            break;
T
ths 已提交
3557
        /* 6,7 are implementation dependent */
3558 3559
        default:
            goto die;
T
ths 已提交
3560 3561 3562
        }
        /* Stop translation as we may have switched the execution mode */
        ctx->bstate = BS_STOP;
3563 3564
        break;
    case 10:
3565 3566
        switch (sel) {
        case 0:
3567
            tcg_gen_helper_0_0(do_mtc0_entryhi);
T
ths 已提交
3568 3569
            rn = "EntryHi";
            break;
3570 3571
        default:
            goto die;
T
ths 已提交
3572
        }
3573 3574
        break;
    case 11:
3575 3576
        switch (sel) {
        case 0:
3577
            tcg_gen_helper_0_0(do_mtc0_compare);
T
ths 已提交
3578 3579 3580
            rn = "Compare";
            break;
        /* 6,7 are implementation dependent */
3581 3582
        default:
            goto die;
T
ths 已提交
3583
        }
A
aurel32 已提交
3584 3585
        /* Stop translation as we may have switched the execution mode */
        ctx->bstate = BS_STOP;
3586 3587
        break;
    case 12:
3588 3589
        switch (sel) {
        case 0:
3590
            tcg_gen_helper_0_0(do_mtc0_status);
3591 3592 3593
            /* BS_STOP isn't good enough here, hflags may have changed. */
            gen_save_pc(ctx->pc + 4);
            ctx->bstate = BS_EXCP;
T
ths 已提交
3594 3595
            rn = "Status";
            break;
3596
        case 1:
3597
            check_insn(env, ctx, ISA_MIPS32R2);
3598
            tcg_gen_helper_0_0(do_mtc0_intctl);
3599 3600
            /* Stop translation as we may have switched the execution mode */
            ctx->bstate = BS_STOP;
T
ths 已提交
3601 3602
            rn = "IntCtl";
            break;
3603
        case 2:
3604
            check_insn(env, ctx, ISA_MIPS32R2);
3605
            tcg_gen_helper_0_0(do_mtc0_srsctl);
3606 3607
            /* Stop translation as we may have switched the execution mode */
            ctx->bstate = BS_STOP;
T
ths 已提交
3608 3609
            rn = "SRSCtl";
            break;
3610
        case 3:
3611
            check_insn(env, ctx, ISA_MIPS32R2);
3612
            gen_mtc0_store32(cpu_T[0], offsetof(CPUState, CP0_SRSMap));
3613 3614
            /* Stop translation as we may have switched the execution mode */
            ctx->bstate = BS_STOP;
T
ths 已提交
3615
            rn = "SRSMap";
3616
            break;
3617 3618
        default:
            goto die;
T
ths 已提交
3619
        }
3620 3621
        break;
    case 13:
3622 3623
        switch (sel) {
        case 0:
3624
            tcg_gen_helper_0_0(do_mtc0_cause);
T
ths 已提交
3625 3626
            rn = "Cause";
            break;
3627 3628
        default:
            goto die;
T
ths 已提交
3629 3630 3631
        }
        /* Stop translation as we may have switched the execution mode */
        ctx->bstate = BS_STOP;
3632 3633
        break;
    case 14:
3634 3635
        switch (sel) {
        case 0:
3636
            gen_mtc0_store64(cpu_T[0], offsetof(CPUState, CP0_EPC));
T
ths 已提交
3637 3638
            rn = "EPC";
            break;
3639 3640
        default:
            goto die;
T
ths 已提交
3641
        }
3642 3643
        break;
    case 15:
3644 3645
        switch (sel) {
        case 0:
T
ths 已提交
3646 3647 3648
            /* ignored */
            rn = "PRid";
            break;
3649
        case 1:
3650
            check_insn(env, ctx, ISA_MIPS32R2);
3651
            tcg_gen_helper_0_0(do_mtc0_ebase);
T
ths 已提交
3652 3653
            rn = "EBase";
            break;
3654 3655
        default:
            goto die;
3656
        }
3657 3658 3659 3660
        break;
    case 16:
        switch (sel) {
        case 0:
3661
            tcg_gen_helper_0_0(do_mtc0_config0);
3662
            rn = "Config";
T
ths 已提交
3663 3664
            /* Stop translation as we may have switched the execution mode */
            ctx->bstate = BS_STOP;
3665 3666
            break;
        case 1:
3667
            /* ignored, read only */
3668 3669 3670
            rn = "Config1";
            break;
        case 2:
3671
            tcg_gen_helper_0_0(do_mtc0_config2);
3672
            rn = "Config2";
T
ths 已提交
3673 3674
            /* Stop translation as we may have switched the execution mode */
            ctx->bstate = BS_STOP;
3675
            break;
3676
        case 3:
3677
            /* ignored, read only */
3678 3679
            rn = "Config3";
            break;
3680 3681 3682 3683 3684 3685 3686 3687 3688 3689
        /* 4,5 are reserved */
        /* 6,7 are implementation dependent */
        case 6:
            /* ignored */
            rn = "Config6";
            break;
        case 7:
            /* ignored */
            rn = "Config7";
            break;
3690 3691 3692 3693 3694 3695
        default:
            rn = "Invalid config selector";
            goto die;
        }
        break;
    case 17:
3696 3697
        switch (sel) {
        case 0:
T
ths 已提交
3698 3699 3700
            /* ignored */
            rn = "LLAddr";
            break;
3701 3702 3703
        default:
            goto die;
        }
3704 3705
        break;
    case 18:
3706
        switch (sel) {
3707
        case 0 ... 7:
3708
            tcg_gen_helper_0_1i(do_mtc0_watchlo, sel);
T
ths 已提交
3709 3710
            rn = "WatchLo";
            break;
3711 3712 3713
        default:
            goto die;
        }
3714 3715
        break;
    case 19:
3716
        switch (sel) {
3717
        case 0 ... 7:
3718
            tcg_gen_helper_0_1i(do_mtc0_watchhi, sel);
T
ths 已提交
3719 3720
            rn = "WatchHi";
            break;
3721 3722 3723
        default:
            goto die;
        }
3724 3725
        break;
    case 20:
3726 3727
        switch (sel) {
        case 0:
3728
#if defined(TARGET_MIPS64)
3729
            check_insn(env, ctx, ISA_MIPS3);
3730
            tcg_gen_helper_0_0(do_mtc0_xcontext);
T
ths 已提交
3731 3732
            rn = "XContext";
            break;
T
ths 已提交
3733
#endif
3734 3735 3736
        default:
            goto die;
        }
3737 3738
        break;
    case 21:
3739 3740 3741
       /* Officially reserved, but sel 0 is used for R1x000 framemask */
        switch (sel) {
        case 0:
3742
            tcg_gen_helper_0_0(do_mtc0_framemask);
T
ths 已提交
3743 3744
            rn = "Framemask";
            break;
3745 3746 3747 3748
        default:
            goto die;
        }
        break;
3749
    case 22:
3750 3751
        /* ignored */
        rn = "Diagnostic"; /* implementation dependent */
T
ths 已提交
3752
        break;
3753
    case 23:
3754 3755
        switch (sel) {
        case 0:
3756
            tcg_gen_helper_0_0(do_mtc0_debug); /* EJTAG support */
3757 3758 3759
            /* BS_STOP isn't good enough here, hflags may have changed. */
            gen_save_pc(ctx->pc + 4);
            ctx->bstate = BS_EXCP;
T
ths 已提交
3760 3761
            rn = "Debug";
            break;
3762
        case 1:
3763
//            tcg_gen_helper_0_0(do_mtc0_tracecontrol); /* PDtrace support */
T
ths 已提交
3764
            rn = "TraceControl";
3765 3766
            /* Stop translation as we may have switched the execution mode */
            ctx->bstate = BS_STOP;
T
ths 已提交
3767
//            break;
3768
        case 2:
3769
//            tcg_gen_helper_0_0(do_mtc0_tracecontrol2); /* PDtrace support */
T
ths 已提交
3770
            rn = "TraceControl2";
3771 3772
            /* Stop translation as we may have switched the execution mode */
            ctx->bstate = BS_STOP;
T
ths 已提交
3773
//            break;
3774
        case 3:
3775 3776
            /* Stop translation as we may have switched the execution mode */
            ctx->bstate = BS_STOP;
3777
//            tcg_gen_helper_0_0(do_mtc0_usertracedata); /* PDtrace support */
T
ths 已提交
3778
            rn = "UserTraceData";
3779 3780
            /* Stop translation as we may have switched the execution mode */
            ctx->bstate = BS_STOP;
T
ths 已提交
3781
//            break;
3782
        case 4:
3783
//            tcg_gen_helper_0_0(do_mtc0_debug); /* PDtrace support */
3784 3785
            /* Stop translation as we may have switched the execution mode */
            ctx->bstate = BS_STOP;
T
ths 已提交
3786 3787
            rn = "TraceBPC";
//            break;
3788 3789 3790
        default:
            goto die;
        }
3791 3792
        break;
    case 24:
3793 3794
        switch (sel) {
        case 0:
3795 3796
            /* EJTAG support */
            gen_mtc0_store64(cpu_T[0], offsetof(CPUState, CP0_DEPC));
T
ths 已提交
3797 3798
            rn = "DEPC";
            break;
3799 3800 3801
        default:
            goto die;
        }
3802 3803
        break;
    case 25:
3804 3805
        switch (sel) {
        case 0:
3806
            tcg_gen_helper_0_0(do_mtc0_performance0);
T
ths 已提交
3807 3808
            rn = "Performance0";
            break;
3809
        case 1:
3810
//            tcg_gen_helper_0_0(do_mtc0_performance1);
T
ths 已提交
3811 3812
            rn = "Performance1";
//            break;
3813
        case 2:
3814
//            tcg_gen_helper_0_0(do_mtc0_performance2);
T
ths 已提交
3815 3816
            rn = "Performance2";
//            break;
3817
        case 3:
3818
//            tcg_gen_helper_0_0(do_mtc0_performance3);
T
ths 已提交
3819 3820
            rn = "Performance3";
//            break;
3821
        case 4:
3822
//            tcg_gen_helper_0_0(do_mtc0_performance4);
T
ths 已提交
3823 3824
            rn = "Performance4";
//            break;
3825
        case 5:
3826
//            tcg_gen_helper_0_0(do_mtc0_performance5);
T
ths 已提交
3827 3828
            rn = "Performance5";
//            break;
3829
        case 6:
3830
//            tcg_gen_helper_0_0(do_mtc0_performance6);
T
ths 已提交
3831 3832
            rn = "Performance6";
//            break;
3833
        case 7:
3834
//            tcg_gen_helper_0_0(do_mtc0_performance7);
T
ths 已提交
3835 3836
            rn = "Performance7";
//            break;
3837 3838 3839
        default:
            goto die;
        }
3840 3841
       break;
    case 26:
T
ths 已提交
3842
        /* ignored */
3843
        rn = "ECC";
T
ths 已提交
3844
        break;
3845
    case 27:
3846 3847
        switch (sel) {
        case 0 ... 3:
T
ths 已提交
3848 3849 3850
            /* ignored */
            rn = "CacheErr";
            break;
3851 3852 3853
        default:
            goto die;
        }
3854 3855 3856 3857
       break;
    case 28:
        switch (sel) {
        case 0:
3858 3859 3860
        case 2:
        case 4:
        case 6:
3861
            tcg_gen_helper_0_0(do_mtc0_taglo);
3862 3863
            rn = "TagLo";
            break;
3864 3865 3866 3867
        case 1:
        case 3:
        case 5:
        case 7:
3868
            tcg_gen_helper_0_0(do_mtc0_datalo);
3869 3870
            rn = "DataLo";
            break;
3871 3872 3873 3874 3875
        default:
            goto die;
        }
        break;
    case 29:
3876 3877 3878 3879 3880
        switch (sel) {
        case 0:
        case 2:
        case 4:
        case 6:
3881
            tcg_gen_helper_0_0(do_mtc0_taghi);
3882 3883 3884 3885 3886 3887
            rn = "TagHi";
            break;
        case 1:
        case 3:
        case 5:
        case 7:
3888
            tcg_gen_helper_0_0(do_mtc0_datahi);
3889 3890 3891 3892 3893 3894
            rn = "DataHi";
            break;
        default:
            rn = "invalid sel";
            goto die;
        }
3895 3896
       break;
    case 30:
3897 3898
        switch (sel) {
        case 0:
3899
            gen_mtc0_store64(cpu_T[0], offsetof(CPUState, CP0_ErrorEPC));
T
ths 已提交
3900 3901
            rn = "ErrorEPC";
            break;
3902 3903 3904
        default:
            goto die;
        }
3905 3906
        break;
    case 31:
3907 3908
        switch (sel) {
        case 0:
3909 3910
            /* EJTAG support */
            gen_mtc0_store32(cpu_T[0], offsetof(CPUState, CP0_DESAVE));
T
ths 已提交
3911 3912
            rn = "DESAVE";
            break;
3913 3914 3915
        default:
            goto die;
        }
T
ths 已提交
3916 3917
        /* Stop translation as we may have switched the execution mode */
        ctx->bstate = BS_STOP;
3918 3919 3920 3921 3922 3923
        break;
    default:
       goto die;
    }
#if defined MIPS_DEBUG_DISAS
    if (loglevel & CPU_LOG_TB_IN_ASM) {
3924 3925
        fprintf(logfile, "mtc0 %s (reg %d sel %d)\n",
                rn, reg, sel);
3926 3927 3928 3929 3930 3931 3932
    }
#endif
    return;

die:
#if defined MIPS_DEBUG_DISAS
    if (loglevel & CPU_LOG_TB_IN_ASM) {
3933 3934
        fprintf(logfile, "mtc0 %s (reg %d sel %d)\n",
                rn, reg, sel);
3935 3936 3937 3938 3939
    }
#endif
    generate_exception(ctx, EXCP_RI);
}

3940
#if defined(TARGET_MIPS64)
3941
static void gen_dmfc0 (CPUState *env, DisasContext *ctx, int reg, int sel)
T
ths 已提交
3942 3943 3944
{
    const char *rn = "invalid";

3945 3946 3947
    if (sel != 0)
        check_insn(env, ctx, ISA_MIPS64);

T
ths 已提交
3948 3949 3950 3951
    switch (reg) {
    case 0:
        switch (sel) {
        case 0:
T
ths 已提交
3952
            gen_mfc0_load32(cpu_T[0], offsetof(CPUState, CP0_Index));
T
ths 已提交
3953 3954 3955
            rn = "Index";
            break;
        case 1:
3956
            check_insn(env, ctx, ASE_MT);
3957
            tcg_gen_helper_0_0(do_mfc0_mvpcontrol);
T
ths 已提交
3958
            rn = "MVPControl";
3959
            break;
T
ths 已提交
3960
        case 2:
3961
            check_insn(env, ctx, ASE_MT);
3962
            tcg_gen_helper_0_0(do_mfc0_mvpconf0);
T
ths 已提交
3963
            rn = "MVPConf0";
3964
            break;
T
ths 已提交
3965
        case 3:
3966
            check_insn(env, ctx, ASE_MT);
3967
            tcg_gen_helper_0_0(do_mfc0_mvpconf1);
T
ths 已提交
3968
            rn = "MVPConf1";
3969
            break;
T
ths 已提交
3970 3971 3972 3973 3974 3975 3976
        default:
            goto die;
        }
        break;
    case 1:
        switch (sel) {
        case 0:
3977
            tcg_gen_helper_0_0(do_mfc0_random);
T
ths 已提交
3978
            rn = "Random";
T
ths 已提交
3979
            break;
T
ths 已提交
3980
        case 1:
3981
            check_insn(env, ctx, ASE_MT);
T
ths 已提交
3982
            gen_mfc0_load32(cpu_T[0], offsetof(CPUState, CP0_VPEControl));
T
ths 已提交
3983
            rn = "VPEControl";
3984
            break;
T
ths 已提交
3985
        case 2:
3986
            check_insn(env, ctx, ASE_MT);
T
ths 已提交
3987
            gen_mfc0_load32(cpu_T[0], offsetof(CPUState, CP0_VPEConf0));
T
ths 已提交
3988
            rn = "VPEConf0";
3989
            break;
T
ths 已提交
3990
        case 3:
3991
            check_insn(env, ctx, ASE_MT);
T
ths 已提交
3992
            gen_mfc0_load32(cpu_T[0], offsetof(CPUState, CP0_VPEConf1));
T
ths 已提交
3993
            rn = "VPEConf1";
3994
            break;
T
ths 已提交
3995
        case 4:
3996
            check_insn(env, ctx, ASE_MT);
T
ths 已提交
3997
            tcg_gen_ld_tl(cpu_T[0], cpu_env, offsetof(CPUState, CP0_YQMask));
T
ths 已提交
3998
            rn = "YQMask";
3999
            break;
T
ths 已提交
4000
        case 5:
4001
            check_insn(env, ctx, ASE_MT);
T
ths 已提交
4002
            tcg_gen_ld_tl(cpu_T[0], cpu_env, offsetof(CPUState, CP0_VPESchedule));
T
ths 已提交
4003
            rn = "VPESchedule";
4004
            break;
T
ths 已提交
4005
        case 6:
4006
            check_insn(env, ctx, ASE_MT);
T
ths 已提交
4007
            tcg_gen_ld_tl(cpu_T[0], cpu_env, offsetof(CPUState, CP0_VPEScheFBack));
T
ths 已提交
4008
            rn = "VPEScheFBack";
4009
            break;
T
ths 已提交
4010
        case 7:
4011
            check_insn(env, ctx, ASE_MT);
T
ths 已提交
4012
            gen_mfc0_load32(cpu_T[0], offsetof(CPUState, CP0_VPEOpt));
T
ths 已提交
4013
            rn = "VPEOpt";
4014
            break;
T
ths 已提交
4015 4016 4017 4018 4019 4020 4021
        default:
            goto die;
        }
        break;
    case 2:
        switch (sel) {
        case 0:
T
ths 已提交
4022
            tcg_gen_ld_tl(cpu_T[0], cpu_env, offsetof(CPUState, CP0_EntryLo0));
T
ths 已提交
4023 4024
            rn = "EntryLo0";
            break;
T
ths 已提交
4025
        case 1:
4026
            check_insn(env, ctx, ASE_MT);
4027
            tcg_gen_helper_0_0(do_mfc0_tcstatus);
T
ths 已提交
4028
            rn = "TCStatus";
4029
            break;
T
ths 已提交
4030
        case 2:
4031
            check_insn(env, ctx, ASE_MT);
4032
            tcg_gen_helper_0_0(do_mfc0_tcbind);
T
ths 已提交
4033
            rn = "TCBind";
4034
            break;
T
ths 已提交
4035
        case 3:
4036
            check_insn(env, ctx, ASE_MT);
4037
            tcg_gen_helper_0_0(do_dmfc0_tcrestart);
T
ths 已提交
4038
            rn = "TCRestart";
4039
            break;
T
ths 已提交
4040
        case 4:
4041
            check_insn(env, ctx, ASE_MT);
4042
            tcg_gen_helper_0_0(do_dmfc0_tchalt);
T
ths 已提交
4043
            rn = "TCHalt";
4044
            break;
T
ths 已提交
4045
        case 5:
4046
            check_insn(env, ctx, ASE_MT);
4047
            tcg_gen_helper_0_0(do_dmfc0_tccontext);
T
ths 已提交
4048
            rn = "TCContext";
4049
            break;
T
ths 已提交
4050
        case 6:
4051
            check_insn(env, ctx, ASE_MT);
4052
            tcg_gen_helper_0_0(do_dmfc0_tcschedule);
T
ths 已提交
4053
            rn = "TCSchedule";
4054
            break;
T
ths 已提交
4055
        case 7:
4056
            check_insn(env, ctx, ASE_MT);
4057
            tcg_gen_helper_0_0(do_dmfc0_tcschefback);
T
ths 已提交
4058
            rn = "TCScheFBack";
4059
            break;
T
ths 已提交
4060 4061 4062 4063 4064 4065 4066
        default:
            goto die;
        }
        break;
    case 3:
        switch (sel) {
        case 0:
T
ths 已提交
4067
            tcg_gen_ld_tl(cpu_T[0], cpu_env, offsetof(CPUState, CP0_EntryLo1));
T
ths 已提交
4068 4069
            rn = "EntryLo1";
            break;
T
ths 已提交
4070 4071
        default:
            goto die;
4072
        }
T
ths 已提交
4073 4074 4075 4076
        break;
    case 4:
        switch (sel) {
        case 0:
T
ths 已提交
4077
            tcg_gen_ld_tl(cpu_T[0], cpu_env, offsetof(CPUState, CP0_Context));
T
ths 已提交
4078 4079
            rn = "Context";
            break;
T
ths 已提交
4080
        case 1:
4081
//            tcg_gen_helper_0_0(do_dmfc0_contextconfig); /* SmartMIPS ASE */
T
ths 已提交
4082 4083
            rn = "ContextConfig";
//            break;
T
ths 已提交
4084 4085
        default:
            goto die;
T
ths 已提交
4086
        }
T
ths 已提交
4087 4088 4089 4090
        break;
    case 5:
        switch (sel) {
        case 0:
T
ths 已提交
4091
            gen_mfc0_load32(cpu_T[0], offsetof(CPUState, CP0_PageMask));
T
ths 已提交
4092 4093
            rn = "PageMask";
            break;
T
ths 已提交
4094
        case 1:
4095
            check_insn(env, ctx, ISA_MIPS32R2);
T
ths 已提交
4096
            gen_mfc0_load32(cpu_T[0], offsetof(CPUState, CP0_PageGrain));
T
ths 已提交
4097 4098
            rn = "PageGrain";
            break;
T
ths 已提交
4099 4100
        default:
            goto die;
T
ths 已提交
4101
        }
T
ths 已提交
4102 4103 4104 4105
        break;
    case 6:
        switch (sel) {
        case 0:
T
ths 已提交
4106
            gen_mfc0_load32(cpu_T[0], offsetof(CPUState, CP0_Wired));
T
ths 已提交
4107 4108
            rn = "Wired";
            break;
T
ths 已提交
4109
        case 1:
4110
            check_insn(env, ctx, ISA_MIPS32R2);
T
ths 已提交
4111
            gen_mfc0_load32(cpu_T[0], offsetof(CPUState, CP0_SRSConf0));
T
ths 已提交
4112
            rn = "SRSConf0";
4113
            break;
T
ths 已提交
4114
        case 2:
4115
            check_insn(env, ctx, ISA_MIPS32R2);
T
ths 已提交
4116
            gen_mfc0_load32(cpu_T[0], offsetof(CPUState, CP0_SRSConf1));
T
ths 已提交
4117
            rn = "SRSConf1";
4118
            break;
T
ths 已提交
4119
        case 3:
4120
            check_insn(env, ctx, ISA_MIPS32R2);
T
ths 已提交
4121
            gen_mfc0_load32(cpu_T[0], offsetof(CPUState, CP0_SRSConf2));
T
ths 已提交
4122
            rn = "SRSConf2";
4123
            break;
T
ths 已提交
4124
        case 4:
4125
            check_insn(env, ctx, ISA_MIPS32R2);
T
ths 已提交
4126
            gen_mfc0_load32(cpu_T[0], offsetof(CPUState, CP0_SRSConf3));
T
ths 已提交
4127
            rn = "SRSConf3";
4128
            break;
T
ths 已提交
4129
        case 5:
4130
            check_insn(env, ctx, ISA_MIPS32R2);
T
ths 已提交
4131
            gen_mfc0_load32(cpu_T[0], offsetof(CPUState, CP0_SRSConf4));
T
ths 已提交
4132
            rn = "SRSConf4";
4133
            break;
T
ths 已提交
4134 4135
        default:
            goto die;
T
ths 已提交
4136
        }
T
ths 已提交
4137 4138 4139 4140
        break;
    case 7:
        switch (sel) {
        case 0:
4141
            check_insn(env, ctx, ISA_MIPS32R2);
T
ths 已提交
4142
            gen_mfc0_load32(cpu_T[0], offsetof(CPUState, CP0_HWREna));
T
ths 已提交
4143 4144
            rn = "HWREna";
            break;
T
ths 已提交
4145 4146
        default:
            goto die;
T
ths 已提交
4147
        }
T
ths 已提交
4148 4149 4150 4151
        break;
    case 8:
        switch (sel) {
        case 0:
T
ths 已提交
4152 4153
            tcg_gen_ld_tl(cpu_T[0], cpu_env, offsetof(CPUState, CP0_BadVAddr));
            rn = "BadVAddr";
T
ths 已提交
4154
            break;
T
ths 已提交
4155 4156
        default:
            goto die;
T
ths 已提交
4157
        }
T
ths 已提交
4158 4159 4160 4161
        break;
    case 9:
        switch (sel) {
        case 0:
4162
            tcg_gen_helper_0_0(do_mfc0_count);
T
ths 已提交
4163 4164 4165
            rn = "Count";
            break;
        /* 6,7 are implementation dependent */
T
ths 已提交
4166 4167
        default:
            goto die;
T
ths 已提交
4168
        }
T
ths 已提交
4169 4170 4171 4172
        break;
    case 10:
        switch (sel) {
        case 0:
T
ths 已提交
4173
            tcg_gen_ld_tl(cpu_T[0], cpu_env, offsetof(CPUState, CP0_EntryHi));
T
ths 已提交
4174 4175
            rn = "EntryHi";
            break;
T
ths 已提交
4176 4177
        default:
            goto die;
T
ths 已提交
4178
        }
T
ths 已提交
4179 4180 4181 4182
        break;
    case 11:
        switch (sel) {
        case 0:
T
ths 已提交
4183
            gen_mfc0_load32(cpu_T[0], offsetof(CPUState, CP0_Compare));
T
ths 已提交
4184 4185
            rn = "Compare";
            break;
T
ths 已提交
4186
        /* 6,7 are implementation dependent */
T
ths 已提交
4187 4188
        default:
            goto die;
T
ths 已提交
4189
        }
T
ths 已提交
4190 4191 4192 4193
        break;
    case 12:
        switch (sel) {
        case 0:
T
ths 已提交
4194
            gen_mfc0_load32(cpu_T[0], offsetof(CPUState, CP0_Status));
T
ths 已提交
4195 4196
            rn = "Status";
            break;
T
ths 已提交
4197
        case 1:
4198
            check_insn(env, ctx, ISA_MIPS32R2);
T
ths 已提交
4199
            gen_mfc0_load32(cpu_T[0], offsetof(CPUState, CP0_IntCtl));
T
ths 已提交
4200 4201
            rn = "IntCtl";
            break;
T
ths 已提交
4202
        case 2:
4203
            check_insn(env, ctx, ISA_MIPS32R2);
T
ths 已提交
4204
            gen_mfc0_load32(cpu_T[0], offsetof(CPUState, CP0_SRSCtl));
T
ths 已提交
4205 4206
            rn = "SRSCtl";
            break;
T
ths 已提交
4207
        case 3:
4208
            check_insn(env, ctx, ISA_MIPS32R2);
T
ths 已提交
4209
            gen_mfc0_load32(cpu_T[0], offsetof(CPUState, CP0_SRSMap));
T
ths 已提交
4210 4211
            rn = "SRSMap";
            break;
T
ths 已提交
4212 4213
        default:
            goto die;
T
ths 已提交
4214
        }
T
ths 已提交
4215 4216 4217 4218
        break;
    case 13:
        switch (sel) {
        case 0:
T
ths 已提交
4219
            gen_mfc0_load32(cpu_T[0], offsetof(CPUState, CP0_Cause));
T
ths 已提交
4220 4221
            rn = "Cause";
            break;
T
ths 已提交
4222 4223
        default:
            goto die;
T
ths 已提交
4224
        }
T
ths 已提交
4225 4226 4227 4228
        break;
    case 14:
        switch (sel) {
        case 0:
T
ths 已提交
4229
            tcg_gen_ld_tl(cpu_T[0], cpu_env, offsetof(CPUState, CP0_EPC));
T
ths 已提交
4230 4231
            rn = "EPC";
            break;
T
ths 已提交
4232 4233
        default:
            goto die;
T
ths 已提交
4234
        }
T
ths 已提交
4235 4236 4237 4238
        break;
    case 15:
        switch (sel) {
        case 0:
T
ths 已提交
4239
            gen_mfc0_load32(cpu_T[0], offsetof(CPUState, CP0_PRid));
T
ths 已提交
4240 4241
            rn = "PRid";
            break;
T
ths 已提交
4242
        case 1:
4243
            check_insn(env, ctx, ISA_MIPS32R2);
T
ths 已提交
4244
            gen_mfc0_load32(cpu_T[0], offsetof(CPUState, CP0_EBase));
T
ths 已提交
4245 4246
            rn = "EBase";
            break;
T
ths 已提交
4247 4248
        default:
            goto die;
T
ths 已提交
4249
        }
T
ths 已提交
4250 4251 4252 4253
        break;
    case 16:
        switch (sel) {
        case 0:
T
ths 已提交
4254
            gen_mfc0_load32(cpu_T[0], offsetof(CPUState, CP0_Config0));
T
ths 已提交
4255 4256 4257
            rn = "Config";
            break;
        case 1:
T
ths 已提交
4258
            gen_mfc0_load32(cpu_T[0], offsetof(CPUState, CP0_Config1));
T
ths 已提交
4259 4260 4261
            rn = "Config1";
            break;
        case 2:
T
ths 已提交
4262
            gen_mfc0_load32(cpu_T[0], offsetof(CPUState, CP0_Config2));
T
ths 已提交
4263 4264 4265
            rn = "Config2";
            break;
        case 3:
T
ths 已提交
4266
            gen_mfc0_load32(cpu_T[0], offsetof(CPUState, CP0_Config3));
T
ths 已提交
4267 4268 4269
            rn = "Config3";
            break;
       /* 6,7 are implementation dependent */
T
ths 已提交
4270
        case 6:
T
ths 已提交
4271
            gen_mfc0_load32(cpu_T[0], offsetof(CPUState, CP0_Config6));
T
ths 已提交
4272 4273 4274
            rn = "Config6";
            break;
        case 7:
T
ths 已提交
4275
            gen_mfc0_load32(cpu_T[0], offsetof(CPUState, CP0_Config7));
T
ths 已提交
4276 4277
            rn = "Config7";
            break;
T
ths 已提交
4278 4279 4280 4281 4282 4283 4284
        default:
            goto die;
        }
        break;
    case 17:
        switch (sel) {
        case 0:
4285
            tcg_gen_helper_0_0(do_dmfc0_lladdr);
T
ths 已提交
4286 4287
            rn = "LLAddr";
            break;
T
ths 已提交
4288 4289 4290 4291 4292 4293
        default:
            goto die;
        }
        break;
    case 18:
        switch (sel) {
4294
        case 0 ... 7:
4295
            tcg_gen_helper_0_1i(do_dmfc0_watchlo, sel);
T
ths 已提交
4296 4297
            rn = "WatchLo";
            break;
T
ths 已提交
4298 4299 4300 4301 4302 4303
        default:
            goto die;
        }
        break;
    case 19:
        switch (sel) {
4304
        case 0 ... 7:
4305
            tcg_gen_helper_0_1i(do_mfc0_watchhi, sel);
T
ths 已提交
4306 4307
            rn = "WatchHi";
            break;
T
ths 已提交
4308 4309 4310 4311 4312 4313 4314
        default:
            goto die;
        }
        break;
    case 20:
        switch (sel) {
        case 0:
4315
            check_insn(env, ctx, ISA_MIPS3);
T
ths 已提交
4316
            tcg_gen_ld_tl(cpu_T[0], cpu_env, offsetof(CPUState, CP0_XContext));
T
ths 已提交
4317 4318
            rn = "XContext";
            break;
T
ths 已提交
4319 4320 4321 4322 4323 4324 4325 4326
        default:
            goto die;
        }
        break;
    case 21:
       /* Officially reserved, but sel 0 is used for R1x000 framemask */
        switch (sel) {
        case 0:
T
ths 已提交
4327
            gen_mfc0_load32(cpu_T[0], offsetof(CPUState, CP0_Framemask));
T
ths 已提交
4328 4329
            rn = "Framemask";
            break;
T
ths 已提交
4330 4331 4332 4333 4334
        default:
            goto die;
        }
        break;
    case 22:
T
ths 已提交
4335 4336 4337
        /* ignored */
        rn = "'Diagnostic"; /* implementation dependent */
        break;
T
ths 已提交
4338 4339 4340
    case 23:
        switch (sel) {
        case 0:
4341
            tcg_gen_helper_0_0(do_mfc0_debug); /* EJTAG support */
T
ths 已提交
4342 4343
            rn = "Debug";
            break;
T
ths 已提交
4344
        case 1:
4345
//            tcg_gen_helper_0_0(do_dmfc0_tracecontrol); /* PDtrace support */
T
ths 已提交
4346 4347
            rn = "TraceControl";
//            break;
T
ths 已提交
4348
        case 2:
4349
//            tcg_gen_helper_0_0(do_dmfc0_tracecontrol2); /* PDtrace support */
T
ths 已提交
4350 4351
            rn = "TraceControl2";
//            break;
T
ths 已提交
4352
        case 3:
4353
//            tcg_gen_helper_0_0(do_dmfc0_usertracedata); /* PDtrace support */
T
ths 已提交
4354 4355
            rn = "UserTraceData";
//            break;
T
ths 已提交
4356
        case 4:
4357
//            tcg_gen_helper_0_0(do_dmfc0_debug); /* PDtrace support */
T
ths 已提交
4358 4359
            rn = "TraceBPC";
//            break;
T
ths 已提交
4360 4361 4362 4363 4364 4365 4366
        default:
            goto die;
        }
        break;
    case 24:
        switch (sel) {
        case 0:
T
ths 已提交
4367 4368
            /* EJTAG support */
            tcg_gen_ld_tl(cpu_T[0], cpu_env, offsetof(CPUState, CP0_DEPC));
T
ths 已提交
4369 4370
            rn = "DEPC";
            break;
T
ths 已提交
4371 4372 4373 4374 4375 4376 4377
        default:
            goto die;
        }
        break;
    case 25:
        switch (sel) {
        case 0:
T
ths 已提交
4378
            gen_mfc0_load32(cpu_T[0], offsetof(CPUState, CP0_Performance0));
T
ths 已提交
4379
            rn = "Performance0";
T
ths 已提交
4380 4381
            break;
        case 1:
4382
//            tcg_gen_helper_0_0(do_dmfc0_performance1);
T
ths 已提交
4383 4384
            rn = "Performance1";
//            break;
T
ths 已提交
4385
        case 2:
4386
//            tcg_gen_helper_0_0(do_dmfc0_performance2);
T
ths 已提交
4387 4388
            rn = "Performance2";
//            break;
T
ths 已提交
4389
        case 3:
4390
//            tcg_gen_helper_0_0(do_dmfc0_performance3);
T
ths 已提交
4391 4392
            rn = "Performance3";
//            break;
T
ths 已提交
4393
        case 4:
4394
//            tcg_gen_helper_0_0(do_dmfc0_performance4);
T
ths 已提交
4395 4396
            rn = "Performance4";
//            break;
T
ths 已提交
4397
        case 5:
4398
//            tcg_gen_helper_0_0(do_dmfc0_performance5);
T
ths 已提交
4399 4400
            rn = "Performance5";
//            break;
T
ths 已提交
4401
        case 6:
4402
//            tcg_gen_helper_0_0(do_dmfc0_performance6);
T
ths 已提交
4403 4404
            rn = "Performance6";
//            break;
T
ths 已提交
4405
        case 7:
4406
//            tcg_gen_helper_0_0(do_dmfc0_performance7);
T
ths 已提交
4407 4408
            rn = "Performance7";
//            break;
T
ths 已提交
4409 4410 4411 4412 4413 4414 4415 4416 4417 4418 4419
        default:
            goto die;
        }
        break;
    case 26:
       rn = "ECC";
       break;
    case 27:
        switch (sel) {
        /* ignored */
        case 0 ... 3:
T
ths 已提交
4420 4421
            rn = "CacheErr";
            break;
T
ths 已提交
4422 4423 4424 4425 4426 4427 4428 4429 4430 4431
        default:
            goto die;
        }
        break;
    case 28:
        switch (sel) {
        case 0:
        case 2:
        case 4:
        case 6:
T
ths 已提交
4432
            gen_mfc0_load32(cpu_T[0], offsetof(CPUState, CP0_TagLo));
T
ths 已提交
4433 4434 4435 4436 4437 4438
            rn = "TagLo";
            break;
        case 1:
        case 3:
        case 5:
        case 7:
T
ths 已提交
4439
            gen_mfc0_load32(cpu_T[0], offsetof(CPUState, CP0_DataLo));
T
ths 已提交
4440 4441 4442 4443 4444 4445 4446 4447 4448 4449 4450 4451
            rn = "DataLo";
            break;
        default:
            goto die;
        }
        break;
    case 29:
        switch (sel) {
        case 0:
        case 2:
        case 4:
        case 6:
T
ths 已提交
4452
            gen_mfc0_load32(cpu_T[0], offsetof(CPUState, CP0_TagHi));
T
ths 已提交
4453 4454 4455 4456 4457 4458
            rn = "TagHi";
            break;
        case 1:
        case 3:
        case 5:
        case 7:
T
ths 已提交
4459
            gen_mfc0_load32(cpu_T[0], offsetof(CPUState, CP0_DataHi));
T
ths 已提交
4460 4461 4462 4463 4464 4465 4466 4467 4468
            rn = "DataHi";
            break;
        default:
            goto die;
        }
        break;
    case 30:
        switch (sel) {
        case 0:
T
ths 已提交
4469
            tcg_gen_ld_tl(cpu_T[0], cpu_env, offsetof(CPUState, CP0_ErrorEPC));
T
ths 已提交
4470 4471
            rn = "ErrorEPC";
            break;
T
ths 已提交
4472 4473 4474 4475 4476 4477 4478
        default:
            goto die;
        }
        break;
    case 31:
        switch (sel) {
        case 0:
T
ths 已提交
4479
            /* EJTAG support */
T
ths 已提交
4480
            gen_mfc0_load32(cpu_T[0], offsetof(CPUState, CP0_DESAVE));
T
ths 已提交
4481 4482
            rn = "DESAVE";
            break;
T
ths 已提交
4483 4484 4485 4486 4487
        default:
            goto die;
        }
        break;
    default:
T
ths 已提交
4488
        goto die;
T
ths 已提交
4489 4490 4491 4492 4493 4494 4495 4496 4497 4498 4499 4500 4501 4502 4503 4504 4505 4506 4507
    }
#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);
}

4508
static void gen_dmtc0 (CPUState *env, DisasContext *ctx, int reg, int sel)
T
ths 已提交
4509 4510 4511
{
    const char *rn = "invalid";

4512 4513 4514
    if (sel != 0)
        check_insn(env, ctx, ISA_MIPS64);

T
ths 已提交
4515 4516 4517 4518
    switch (reg) {
    case 0:
        switch (sel) {
        case 0:
4519
            tcg_gen_helper_0_0(do_mtc0_index);
T
ths 已提交
4520 4521 4522
            rn = "Index";
            break;
        case 1:
4523
            check_insn(env, ctx, ASE_MT);
4524
            tcg_gen_helper_0_0(do_mtc0_mvpcontrol);
T
ths 已提交
4525
            rn = "MVPControl";
4526
            break;
T
ths 已提交
4527
        case 2:
4528
            check_insn(env, ctx, ASE_MT);
4529
            /* ignored */
T
ths 已提交
4530
            rn = "MVPConf0";
4531
            break;
T
ths 已提交
4532
        case 3:
4533
            check_insn(env, ctx, ASE_MT);
4534
            /* ignored */
T
ths 已提交
4535
            rn = "MVPConf1";
4536
            break;
T
ths 已提交
4537 4538 4539 4540 4541 4542 4543
        default:
            goto die;
        }
        break;
    case 1:
        switch (sel) {
        case 0:
T
ths 已提交
4544
            /* ignored */
T
ths 已提交
4545
            rn = "Random";
T
ths 已提交
4546
            break;
T
ths 已提交
4547
        case 1:
4548
            check_insn(env, ctx, ASE_MT);
4549
            tcg_gen_helper_0_0(do_mtc0_vpecontrol);
T
ths 已提交
4550
            rn = "VPEControl";
4551
            break;
T
ths 已提交
4552
        case 2:
4553
            check_insn(env, ctx, ASE_MT);
4554
            tcg_gen_helper_0_0(do_mtc0_vpeconf0);
T
ths 已提交
4555
            rn = "VPEConf0";
4556
            break;
T
ths 已提交
4557
        case 3:
4558
            check_insn(env, ctx, ASE_MT);
4559
            tcg_gen_helper_0_0(do_mtc0_vpeconf1);
T
ths 已提交
4560
            rn = "VPEConf1";
4561
            break;
T
ths 已提交
4562
        case 4:
4563
            check_insn(env, ctx, ASE_MT);
4564
            tcg_gen_helper_0_0(do_mtc0_yqmask);
T
ths 已提交
4565
            rn = "YQMask";
4566
            break;
T
ths 已提交
4567
        case 5:
4568
            check_insn(env, ctx, ASE_MT);
4569
            tcg_gen_st_tl(cpu_T[0], cpu_env, offsetof(CPUState, CP0_VPESchedule));
T
ths 已提交
4570
            rn = "VPESchedule";
4571
            break;
T
ths 已提交
4572
        case 6:
4573
            check_insn(env, ctx, ASE_MT);
4574
            tcg_gen_st_tl(cpu_T[0], cpu_env, offsetof(CPUState, CP0_VPEScheFBack));
T
ths 已提交
4575
            rn = "VPEScheFBack";
4576
            break;
T
ths 已提交
4577
        case 7:
4578
            check_insn(env, ctx, ASE_MT);
4579
            tcg_gen_helper_0_0(do_mtc0_vpeopt);
T
ths 已提交
4580
            rn = "VPEOpt";
4581
            break;
T
ths 已提交
4582 4583 4584 4585 4586 4587 4588
        default:
            goto die;
        }
        break;
    case 2:
        switch (sel) {
        case 0:
4589
            tcg_gen_helper_0_0(do_mtc0_entrylo0);
T
ths 已提交
4590 4591
            rn = "EntryLo0";
            break;
T
ths 已提交
4592
        case 1:
4593
            check_insn(env, ctx, ASE_MT);
4594
            tcg_gen_helper_0_0(do_mtc0_tcstatus);
T
ths 已提交
4595
            rn = "TCStatus";
4596
            break;
T
ths 已提交
4597
        case 2:
4598
            check_insn(env, ctx, ASE_MT);
4599
            tcg_gen_helper_0_0(do_mtc0_tcbind);
T
ths 已提交
4600
            rn = "TCBind";
4601
            break;
T
ths 已提交
4602
        case 3:
4603
            check_insn(env, ctx, ASE_MT);
4604
            tcg_gen_helper_0_0(do_mtc0_tcrestart);
T
ths 已提交
4605
            rn = "TCRestart";
4606
            break;
T
ths 已提交
4607
        case 4:
4608
            check_insn(env, ctx, ASE_MT);
4609
            tcg_gen_helper_0_0(do_mtc0_tchalt);
T
ths 已提交
4610
            rn = "TCHalt";
4611
            break;
T
ths 已提交
4612
        case 5:
4613
            check_insn(env, ctx, ASE_MT);
4614
            tcg_gen_helper_0_0(do_mtc0_tccontext);
T
ths 已提交
4615
            rn = "TCContext";
4616
            break;
T
ths 已提交
4617
        case 6:
4618
            check_insn(env, ctx, ASE_MT);
4619
            tcg_gen_helper_0_0(do_mtc0_tcschedule);
T
ths 已提交
4620
            rn = "TCSchedule";
4621
            break;
T
ths 已提交
4622
        case 7:
4623
            check_insn(env, ctx, ASE_MT);
4624
            tcg_gen_helper_0_0(do_mtc0_tcschefback);
T
ths 已提交
4625
            rn = "TCScheFBack";
4626
            break;
T
ths 已提交
4627 4628 4629 4630 4631 4632 4633
        default:
            goto die;
        }
        break;
    case 3:
        switch (sel) {
        case 0:
4634
            tcg_gen_helper_0_0(do_mtc0_entrylo1);
T
ths 已提交
4635 4636
            rn = "EntryLo1";
            break;
T
ths 已提交
4637 4638
        default:
            goto die;
T
ths 已提交
4639
        }
T
ths 已提交
4640 4641 4642 4643
        break;
    case 4:
        switch (sel) {
        case 0:
4644
            tcg_gen_helper_0_0(do_mtc0_context);
T
ths 已提交
4645 4646
            rn = "Context";
            break;
T
ths 已提交
4647
        case 1:
4648
//           tcg_gen_helper_0_0(do_mtc0_contextconfig); /* SmartMIPS ASE */
T
ths 已提交
4649 4650
            rn = "ContextConfig";
//           break;
T
ths 已提交
4651 4652
        default:
            goto die;
T
ths 已提交
4653
        }
T
ths 已提交
4654 4655 4656 4657
        break;
    case 5:
        switch (sel) {
        case 0:
4658
            tcg_gen_helper_0_0(do_mtc0_pagemask);
T
ths 已提交
4659 4660
            rn = "PageMask";
            break;
T
ths 已提交
4661
        case 1:
4662
            check_insn(env, ctx, ISA_MIPS32R2);
4663
            tcg_gen_helper_0_0(do_mtc0_pagegrain);
T
ths 已提交
4664 4665
            rn = "PageGrain";
            break;
T
ths 已提交
4666 4667
        default:
            goto die;
T
ths 已提交
4668
        }
T
ths 已提交
4669 4670 4671 4672
        break;
    case 6:
        switch (sel) {
        case 0:
4673
            tcg_gen_helper_0_0(do_mtc0_wired);
T
ths 已提交
4674 4675
            rn = "Wired";
            break;
T
ths 已提交
4676
        case 1:
4677
            check_insn(env, ctx, ISA_MIPS32R2);
4678
            tcg_gen_helper_0_0(do_mtc0_srsconf0);
T
ths 已提交
4679
            rn = "SRSConf0";
4680
            break;
T
ths 已提交
4681
        case 2:
4682
            check_insn(env, ctx, ISA_MIPS32R2);
4683
            tcg_gen_helper_0_0(do_mtc0_srsconf1);
T
ths 已提交
4684
            rn = "SRSConf1";
4685
            break;
T
ths 已提交
4686
        case 3:
4687
            check_insn(env, ctx, ISA_MIPS32R2);
4688
            tcg_gen_helper_0_0(do_mtc0_srsconf2);
T
ths 已提交
4689
            rn = "SRSConf2";
4690
            break;
T
ths 已提交
4691
        case 4:
4692
            check_insn(env, ctx, ISA_MIPS32R2);
4693
            tcg_gen_helper_0_0(do_mtc0_srsconf3);
T
ths 已提交
4694
            rn = "SRSConf3";
4695
            break;
T
ths 已提交
4696
        case 5:
4697
            check_insn(env, ctx, ISA_MIPS32R2);
4698
            tcg_gen_helper_0_0(do_mtc0_srsconf4);
T
ths 已提交
4699
            rn = "SRSConf4";
4700
            break;
T
ths 已提交
4701 4702
        default:
            goto die;
T
ths 已提交
4703
        }
T
ths 已提交
4704 4705 4706 4707
        break;
    case 7:
        switch (sel) {
        case 0:
4708
            check_insn(env, ctx, ISA_MIPS32R2);
4709
            tcg_gen_helper_0_0(do_mtc0_hwrena);
T
ths 已提交
4710 4711
            rn = "HWREna";
            break;
T
ths 已提交
4712 4713
        default:
            goto die;
T
ths 已提交
4714
        }
T
ths 已提交
4715 4716 4717
        break;
    case 8:
        /* ignored */
T
ths 已提交
4718
        rn = "BadVAddr";
T
ths 已提交
4719 4720 4721 4722
        break;
    case 9:
        switch (sel) {
        case 0:
4723
            tcg_gen_helper_0_0(do_mtc0_count);
T
ths 已提交
4724 4725
            rn = "Count";
            break;
T
ths 已提交
4726
        /* 6,7 are implementation dependent */
T
ths 已提交
4727 4728
        default:
            goto die;
T
ths 已提交
4729 4730 4731
        }
        /* Stop translation as we may have switched the execution mode */
        ctx->bstate = BS_STOP;
T
ths 已提交
4732 4733 4734 4735
        break;
    case 10:
        switch (sel) {
        case 0:
4736
            tcg_gen_helper_0_0(do_mtc0_entryhi);
T
ths 已提交
4737 4738
            rn = "EntryHi";
            break;
T
ths 已提交
4739 4740
        default:
            goto die;
T
ths 已提交
4741
        }
T
ths 已提交
4742 4743 4744 4745
        break;
    case 11:
        switch (sel) {
        case 0:
4746
            tcg_gen_helper_0_0(do_mtc0_compare);
T
ths 已提交
4747 4748
            rn = "Compare";
            break;
T
ths 已提交
4749
        /* 6,7 are implementation dependent */
T
ths 已提交
4750 4751
        default:
            goto die;
T
ths 已提交
4752
        }
A
aurel32 已提交
4753 4754
        /* Stop translation as we may have switched the execution mode */
        ctx->bstate = BS_STOP;
T
ths 已提交
4755 4756 4757 4758
        break;
    case 12:
        switch (sel) {
        case 0:
4759
            tcg_gen_helper_0_0(do_mtc0_status);
4760 4761 4762
            /* BS_STOP isn't good enough here, hflags may have changed. */
            gen_save_pc(ctx->pc + 4);
            ctx->bstate = BS_EXCP;
T
ths 已提交
4763 4764
            rn = "Status";
            break;
T
ths 已提交
4765
        case 1:
4766
            check_insn(env, ctx, ISA_MIPS32R2);
4767
            tcg_gen_helper_0_0(do_mtc0_intctl);
4768 4769
            /* Stop translation as we may have switched the execution mode */
            ctx->bstate = BS_STOP;
T
ths 已提交
4770 4771
            rn = "IntCtl";
            break;
T
ths 已提交
4772
        case 2:
4773
            check_insn(env, ctx, ISA_MIPS32R2);
4774
            tcg_gen_helper_0_0(do_mtc0_srsctl);
4775 4776
            /* Stop translation as we may have switched the execution mode */
            ctx->bstate = BS_STOP;
T
ths 已提交
4777 4778
            rn = "SRSCtl";
            break;
T
ths 已提交
4779
        case 3:
4780
            check_insn(env, ctx, ISA_MIPS32R2);
4781
            gen_mtc0_store32(cpu_T[0], offsetof(CPUState, CP0_SRSMap));
4782 4783
            /* Stop translation as we may have switched the execution mode */
            ctx->bstate = BS_STOP;
T
ths 已提交
4784 4785 4786
            rn = "SRSMap";
            break;
        default:
T
ths 已提交
4787
            goto die;
T
ths 已提交
4788
        }
T
ths 已提交
4789 4790 4791 4792
        break;
    case 13:
        switch (sel) {
        case 0:
4793
            tcg_gen_helper_0_0(do_mtc0_cause);
T
ths 已提交
4794 4795
            rn = "Cause";
            break;
T
ths 已提交
4796 4797
        default:
            goto die;
T
ths 已提交
4798 4799 4800
        }
        /* Stop translation as we may have switched the execution mode */
        ctx->bstate = BS_STOP;
T
ths 已提交
4801 4802 4803 4804
        break;
    case 14:
        switch (sel) {
        case 0:
4805
            tcg_gen_st_tl(cpu_T[0], cpu_env, offsetof(CPUState, CP0_EPC));
T
ths 已提交
4806 4807
            rn = "EPC";
            break;
T
ths 已提交
4808 4809
        default:
            goto die;
T
ths 已提交
4810
        }
T
ths 已提交
4811 4812 4813 4814
        break;
    case 15:
        switch (sel) {
        case 0:
T
ths 已提交
4815 4816 4817
            /* ignored */
            rn = "PRid";
            break;
T
ths 已提交
4818
        case 1:
4819
            check_insn(env, ctx, ISA_MIPS32R2);
4820
            tcg_gen_helper_0_0(do_mtc0_ebase);
T
ths 已提交
4821 4822
            rn = "EBase";
            break;
T
ths 已提交
4823 4824
        default:
            goto die;
T
ths 已提交
4825
        }
T
ths 已提交
4826 4827 4828 4829
        break;
    case 16:
        switch (sel) {
        case 0:
4830
            tcg_gen_helper_0_0(do_mtc0_config0);
T
ths 已提交
4831
            rn = "Config";
T
ths 已提交
4832 4833
            /* Stop translation as we may have switched the execution mode */
            ctx->bstate = BS_STOP;
T
ths 已提交
4834 4835
            break;
        case 1:
T
ths 已提交
4836
            /* ignored */
T
ths 已提交
4837 4838 4839
            rn = "Config1";
            break;
        case 2:
4840
            tcg_gen_helper_0_0(do_mtc0_config2);
T
ths 已提交
4841
            rn = "Config2";
T
ths 已提交
4842 4843
            /* Stop translation as we may have switched the execution mode */
            ctx->bstate = BS_STOP;
T
ths 已提交
4844 4845
            break;
        case 3:
T
ths 已提交
4846
            /* ignored */
T
ths 已提交
4847 4848 4849 4850 4851 4852 4853 4854 4855 4856 4857
            rn = "Config3";
            break;
        /* 6,7 are implementation dependent */
        default:
            rn = "Invalid config selector";
            goto die;
        }
        break;
    case 17:
        switch (sel) {
        case 0:
T
ths 已提交
4858 4859 4860
            /* ignored */
            rn = "LLAddr";
            break;
T
ths 已提交
4861 4862 4863 4864 4865 4866
        default:
            goto die;
        }
        break;
    case 18:
        switch (sel) {
4867
        case 0 ... 7:
4868
            tcg_gen_helper_0_1i(do_mtc0_watchlo, sel);
T
ths 已提交
4869 4870
            rn = "WatchLo";
            break;
T
ths 已提交
4871 4872 4873 4874 4875 4876
        default:
            goto die;
        }
        break;
    case 19:
        switch (sel) {
4877
        case 0 ... 7:
4878
            tcg_gen_helper_0_1i(do_mtc0_watchhi, sel);
T
ths 已提交
4879 4880
            rn = "WatchHi";
            break;
T
ths 已提交
4881 4882 4883 4884 4885 4886 4887
        default:
            goto die;
        }
        break;
    case 20:
        switch (sel) {
        case 0:
4888
            check_insn(env, ctx, ISA_MIPS3);
4889
            tcg_gen_helper_0_0(do_mtc0_xcontext);
T
ths 已提交
4890 4891
            rn = "XContext";
            break;
T
ths 已提交
4892 4893 4894 4895 4896 4897 4898 4899
        default:
            goto die;
        }
        break;
    case 21:
       /* Officially reserved, but sel 0 is used for R1x000 framemask */
        switch (sel) {
        case 0:
4900
            tcg_gen_helper_0_0(do_mtc0_framemask);
T
ths 已提交
4901 4902
            rn = "Framemask";
            break;
T
ths 已提交
4903 4904 4905 4906 4907 4908 4909
        default:
            goto die;
        }
        break;
    case 22:
        /* ignored */
        rn = "Diagnostic"; /* implementation dependent */
T
ths 已提交
4910
        break;
T
ths 已提交
4911 4912 4913
    case 23:
        switch (sel) {
        case 0:
4914
            tcg_gen_helper_0_0(do_mtc0_debug); /* EJTAG support */
4915 4916 4917
            /* BS_STOP isn't good enough here, hflags may have changed. */
            gen_save_pc(ctx->pc + 4);
            ctx->bstate = BS_EXCP;
T
ths 已提交
4918 4919
            rn = "Debug";
            break;
T
ths 已提交
4920
        case 1:
4921
//            tcg_gen_helper_0_0(do_mtc0_tracecontrol); /* PDtrace support */
4922 4923
            /* Stop translation as we may have switched the execution mode */
            ctx->bstate = BS_STOP;
T
ths 已提交
4924 4925
            rn = "TraceControl";
//            break;
T
ths 已提交
4926
        case 2:
4927
//            tcg_gen_helper_0_0(do_mtc0_tracecontrol2); /* PDtrace support */
4928 4929
            /* Stop translation as we may have switched the execution mode */
            ctx->bstate = BS_STOP;
T
ths 已提交
4930 4931
            rn = "TraceControl2";
//            break;
T
ths 已提交
4932
        case 3:
4933
//            tcg_gen_helper_0_0(do_mtc0_usertracedata); /* PDtrace support */
4934 4935
            /* Stop translation as we may have switched the execution mode */
            ctx->bstate = BS_STOP;
T
ths 已提交
4936 4937
            rn = "UserTraceData";
//            break;
T
ths 已提交
4938
        case 4:
4939
//            tcg_gen_helper_0_0(do_mtc0_debug); /* PDtrace support */
4940 4941
            /* Stop translation as we may have switched the execution mode */
            ctx->bstate = BS_STOP;
T
ths 已提交
4942 4943
            rn = "TraceBPC";
//            break;
T
ths 已提交
4944 4945 4946 4947 4948 4949 4950
        default:
            goto die;
        }
        break;
    case 24:
        switch (sel) {
        case 0:
4951 4952
            /* EJTAG support */
            tcg_gen_st_tl(cpu_T[0], cpu_env, offsetof(CPUState, CP0_DEPC));
T
ths 已提交
4953 4954
            rn = "DEPC";
            break;
T
ths 已提交
4955 4956 4957 4958 4959 4960 4961
        default:
            goto die;
        }
        break;
    case 25:
        switch (sel) {
        case 0:
4962
            tcg_gen_helper_0_0(do_mtc0_performance0);
T
ths 已提交
4963 4964
            rn = "Performance0";
            break;
T
ths 已提交
4965
        case 1:
4966
//            tcg_gen_helper_0_0(do_mtc0_performance1);
T
ths 已提交
4967 4968
            rn = "Performance1";
//            break;
T
ths 已提交
4969
        case 2:
4970
//            tcg_gen_helper_0_0(do_mtc0_performance2);
T
ths 已提交
4971 4972
            rn = "Performance2";
//            break;
T
ths 已提交
4973
        case 3:
4974
//            tcg_gen_helper_0_0(do_mtc0_performance3);
T
ths 已提交
4975 4976
            rn = "Performance3";
//            break;
T
ths 已提交
4977
        case 4:
4978
//            tcg_gen_helper_0_0(do_mtc0_performance4);
T
ths 已提交
4979 4980
            rn = "Performance4";
//            break;
T
ths 已提交
4981
        case 5:
4982
//            tcg_gen_helper_0_0(do_mtc0_performance5);
T
ths 已提交
4983 4984
            rn = "Performance5";
//            break;
T
ths 已提交
4985
        case 6:
4986
//            tcg_gen_helper_0_0(do_mtc0_performance6);
T
ths 已提交
4987 4988
            rn = "Performance6";
//            break;
T
ths 已提交
4989
        case 7:
4990
//            tcg_gen_helper_0_0(do_mtc0_performance7);
T
ths 已提交
4991 4992
            rn = "Performance7";
//            break;
T
ths 已提交
4993 4994 4995
        default:
            goto die;
        }
T
ths 已提交
4996
        break;
T
ths 已提交
4997
    case 26:
T
ths 已提交
4998
        /* ignored */
T
ths 已提交
4999
        rn = "ECC";
T
ths 已提交
5000
        break;
T
ths 已提交
5001 5002 5003
    case 27:
        switch (sel) {
        case 0 ... 3:
T
ths 已提交
5004 5005 5006
            /* ignored */
            rn = "CacheErr";
            break;
T
ths 已提交
5007 5008 5009
        default:
            goto die;
        }
T
ths 已提交
5010
        break;
T
ths 已提交
5011 5012 5013 5014 5015 5016
    case 28:
        switch (sel) {
        case 0:
        case 2:
        case 4:
        case 6:
5017
            tcg_gen_helper_0_0(do_mtc0_taglo);
T
ths 已提交
5018 5019 5020 5021 5022 5023
            rn = "TagLo";
            break;
        case 1:
        case 3:
        case 5:
        case 7:
5024
            tcg_gen_helper_0_0(do_mtc0_datalo);
T
ths 已提交
5025 5026 5027 5028 5029 5030 5031 5032 5033 5034 5035 5036
            rn = "DataLo";
            break;
        default:
            goto die;
        }
        break;
    case 29:
        switch (sel) {
        case 0:
        case 2:
        case 4:
        case 6:
5037
            tcg_gen_helper_0_0(do_mtc0_taghi);
T
ths 已提交
5038 5039 5040 5041 5042 5043
            rn = "TagHi";
            break;
        case 1:
        case 3:
        case 5:
        case 7:
5044
            tcg_gen_helper_0_0(do_mtc0_datahi);
T
ths 已提交
5045 5046 5047 5048 5049 5050
            rn = "DataHi";
            break;
        default:
            rn = "invalid sel";
            goto die;
        }
T
ths 已提交
5051
        break;
T
ths 已提交
5052 5053 5054
    case 30:
        switch (sel) {
        case 0:
5055
            tcg_gen_st_tl(cpu_T[0], cpu_env, offsetof(CPUState, CP0_ErrorEPC));
T
ths 已提交
5056 5057
            rn = "ErrorEPC";
            break;
T
ths 已提交
5058 5059 5060 5061 5062 5063 5064
        default:
            goto die;
        }
        break;
    case 31:
        switch (sel) {
        case 0:
5065 5066
            /* EJTAG support */
            gen_mtc0_store32(cpu_T[0], offsetof(CPUState, CP0_DESAVE));
T
ths 已提交
5067 5068
            rn = "DESAVE";
            break;
T
ths 已提交
5069 5070 5071
        default:
            goto die;
        }
T
ths 已提交
5072 5073
        /* Stop translation as we may have switched the execution mode */
        ctx->bstate = BS_STOP;
T
ths 已提交
5074 5075
        break;
    default:
T
ths 已提交
5076
        goto die;
T
ths 已提交
5077 5078 5079 5080 5081 5082 5083 5084 5085 5086 5087 5088 5089 5090 5091 5092 5093 5094
    }
#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);
}
5095
#endif /* TARGET_MIPS64 */
T
ths 已提交
5096

5097 5098 5099 5100 5101 5102 5103 5104
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))))
5105
        tcg_gen_movi_tl(cpu_T[0], -1);
5106 5107
    else if ((env->CP0_VPEControl & (0xff << CP0VPECo_TargTC)) >
             (env->mvp->CP0_MVPConf0 & (0xff << CP0MVPC0_PTC)))
5108
        tcg_gen_movi_tl(cpu_T[0], -1);
5109 5110 5111 5112 5113
    else if (u == 0) {
        switch (rt) {
        case 2:
            switch (sel) {
            case 1:
5114
                tcg_gen_helper_0_0(do_mftc0_tcstatus);
5115 5116
                break;
            case 2:
5117
                tcg_gen_helper_0_0(do_mftc0_tcbind);
5118 5119
                break;
            case 3:
5120
                tcg_gen_helper_0_0(do_mftc0_tcrestart);
5121 5122
                break;
            case 4:
5123
                tcg_gen_helper_0_0(do_mftc0_tchalt);
5124 5125
                break;
            case 5:
5126
                tcg_gen_helper_0_0(do_mftc0_tccontext);
5127 5128
                break;
            case 6:
5129
                tcg_gen_helper_0_0(do_mftc0_tcschedule);
5130 5131
                break;
            case 7:
5132
                tcg_gen_helper_0_0(do_mftc0_tcschefback);
5133 5134 5135 5136 5137 5138 5139 5140 5141
                break;
            default:
                gen_mfc0(env, ctx, rt, sel);
                break;
            }
            break;
        case 10:
            switch (sel) {
            case 0:
5142
                tcg_gen_helper_0_0(do_mftc0_entryhi);
5143 5144 5145 5146 5147 5148 5149 5150
                break;
            default:
                gen_mfc0(env, ctx, rt, sel);
                break;
            }
        case 12:
            switch (sel) {
            case 0:
5151
                tcg_gen_helper_0_0(do_mftc0_status);
5152 5153 5154 5155 5156 5157 5158 5159
                break;
            default:
                gen_mfc0(env, ctx, rt, sel);
                break;
            }
        case 23:
            switch (sel) {
            case 0:
5160
                tcg_gen_helper_0_0(do_mftc0_debug);
5161 5162 5163 5164 5165 5166 5167 5168 5169 5170 5171 5172
                break;
            default:
                gen_mfc0(env, ctx, rt, sel);
                break;
            }
            break;
        default:
            gen_mfc0(env, ctx, rt, sel);
        }
    } else switch (sel) {
    /* GPR registers. */
    case 0:
5173
        tcg_gen_helper_0_1i(do_mftgpr, rt);
5174 5175 5176 5177 5178
        break;
    /* Auxiliary CPU registers */
    case 1:
        switch (rt) {
        case 0:
5179
            tcg_gen_helper_0_1i(do_mftlo, 0);
5180 5181
            break;
        case 1:
5182
            tcg_gen_helper_0_1i(do_mfthi, 0);
5183 5184
            break;
        case 2:
5185
            tcg_gen_helper_0_1i(do_mftacx, 0);
5186 5187
            break;
        case 4:
5188
            tcg_gen_helper_0_1i(do_mftlo, 1);
5189 5190
            break;
        case 5:
5191
            tcg_gen_helper_0_1i(do_mfthi, 1);
5192 5193
            break;
        case 6:
5194
            tcg_gen_helper_0_1i(do_mftacx, 1);
5195 5196
            break;
        case 8:
5197
            tcg_gen_helper_0_1i(do_mftlo, 2);
5198 5199
            break;
        case 9:
5200
            tcg_gen_helper_0_1i(do_mfthi, 2);
5201 5202
            break;
        case 10:
5203
            tcg_gen_helper_0_1i(do_mftacx, 2);
5204 5205
            break;
        case 12:
5206
            tcg_gen_helper_0_1i(do_mftlo, 3);
5207 5208
            break;
        case 13:
5209
            tcg_gen_helper_0_1i(do_mfthi, 3);
5210 5211
            break;
        case 14:
5212
            tcg_gen_helper_0_1i(do_mftacx, 3);
5213 5214
            break;
        case 16:
5215
            tcg_gen_helper_0_0(do_mftdsp);
5216 5217 5218 5219 5220 5221 5222 5223 5224
            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 已提交
5225 5226
            gen_load_fpr32(fpu32_T[0], rt);
            tcg_gen_ext_i32_tl(cpu_T[0], fpu32_T[0]);
5227
        } else {
T
ths 已提交
5228 5229
            gen_load_fpr32h(fpu32h_T[0], rt);
            tcg_gen_ext_i32_tl(cpu_T[0], fpu32h_T[0]);
5230 5231 5232 5233
        }
        break;
    case 3:
        /* XXX: For now we support only a single FPU context. */
5234
        tcg_gen_helper_0_1i(do_cfc1, rt);
5235 5236 5237 5238 5239 5240 5241 5242 5243 5244 5245 5246 5247 5248 5249 5250 5251 5252 5253 5254 5255 5256 5257 5258 5259 5260 5261 5262 5263 5264 5265 5266 5267 5268 5269 5270 5271 5272 5273 5274 5275 5276 5277
        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:
5278
                tcg_gen_helper_0_0(do_mttc0_tcstatus);
5279 5280
                break;
            case 2:
5281
                tcg_gen_helper_0_0(do_mttc0_tcbind);
5282 5283
                break;
            case 3:
5284
                tcg_gen_helper_0_0(do_mttc0_tcrestart);
5285 5286
                break;
            case 4:
5287
                tcg_gen_helper_0_0(do_mttc0_tchalt);
5288 5289
                break;
            case 5:
5290
                tcg_gen_helper_0_0(do_mttc0_tccontext);
5291 5292
                break;
            case 6:
5293
                tcg_gen_helper_0_0(do_mttc0_tcschedule);
5294 5295
                break;
            case 7:
5296
                tcg_gen_helper_0_0(do_mttc0_tcschefback);
5297 5298 5299 5300 5301 5302 5303 5304 5305
                break;
            default:
                gen_mtc0(env, ctx, rd, sel);
                break;
            }
            break;
        case 10:
            switch (sel) {
            case 0:
5306
                tcg_gen_helper_0_0(do_mttc0_entryhi);
5307 5308 5309 5310 5311 5312 5313 5314
                break;
            default:
                gen_mtc0(env, ctx, rd, sel);
                break;
            }
        case 12:
            switch (sel) {
            case 0:
5315
                tcg_gen_helper_0_0(do_mttc0_status);
5316 5317 5318 5319 5320 5321 5322 5323
                break;
            default:
                gen_mtc0(env, ctx, rd, sel);
                break;
            }
        case 23:
            switch (sel) {
            case 0:
5324
                tcg_gen_helper_0_0(do_mttc0_debug);
5325 5326 5327 5328 5329 5330 5331 5332 5333 5334 5335 5336
                break;
            default:
                gen_mtc0(env, ctx, rd, sel);
                break;
            }
            break;
        default:
            gen_mtc0(env, ctx, rd, sel);
        }
    } else switch (sel) {
    /* GPR registers. */
    case 0:
5337
        tcg_gen_helper_0_1i(do_mttgpr, rd);
5338 5339 5340 5341 5342
        break;
    /* Auxiliary CPU registers */
    case 1:
        switch (rd) {
        case 0:
5343
            tcg_gen_helper_0_1i(do_mttlo, 0);
5344 5345
            break;
        case 1:
5346
            tcg_gen_helper_0_1i(do_mtthi, 0);
5347 5348
            break;
        case 2:
5349
            tcg_gen_helper_0_1i(do_mttacx, 0);
5350 5351
            break;
        case 4:
5352
            tcg_gen_helper_0_1i(do_mttlo, 1);
5353 5354
            break;
        case 5:
5355
            tcg_gen_helper_0_1i(do_mtthi, 1);
5356 5357
            break;
        case 6:
5358
            tcg_gen_helper_0_1i(do_mttacx, 1);
5359 5360
            break;
        case 8:
5361
            tcg_gen_helper_0_1i(do_mttlo, 2);
5362 5363
            break;
        case 9:
5364
            tcg_gen_helper_0_1i(do_mtthi, 2);
5365 5366
            break;
        case 10:
5367
            tcg_gen_helper_0_1i(do_mttacx, 2);
5368 5369
            break;
        case 12:
5370
            tcg_gen_helper_0_1i(do_mttlo, 3);
5371 5372
            break;
        case 13:
5373
            tcg_gen_helper_0_1i(do_mtthi, 3);
5374 5375
            break;
        case 14:
5376
            tcg_gen_helper_0_1i(do_mttacx, 3);
5377 5378
            break;
        case 16:
5379
            tcg_gen_helper_0_0(do_mttdsp);
5380 5381 5382 5383 5384 5385 5386 5387 5388
            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 已提交
5389 5390
            tcg_gen_trunc_tl_i32(fpu32_T[0], cpu_T[0]);
            gen_store_fpr32(fpu32_T[0], rd);
5391
        } else {
T
ths 已提交
5392 5393
            tcg_gen_trunc_tl_i32(fpu32h_T[0], cpu_T[0]);
            gen_store_fpr32h(fpu32h_T[0], rd);
5394 5395 5396 5397
        }
        break;
    case 3:
        /* XXX: For now we support only a single FPU context. */
5398
        tcg_gen_helper_0_1i(do_ctc1, rd);
5399 5400 5401 5402 5403 5404 5405 5406 5407 5408 5409 5410 5411 5412 5413 5414 5415 5416 5417 5418 5419 5420 5421 5422 5423 5424
        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);
}

5425
static void gen_cp0 (CPUState *env, DisasContext *ctx, uint32_t opc, int rt, int rd)
B
bellard 已提交
5426
{
T
ths 已提交
5427
    const char *opn = "ldst";
B
bellard 已提交
5428 5429 5430 5431

    switch (opc) {
    case OPC_MFC0:
        if (rt == 0) {
5432
            /* Treat as NOP. */
B
bellard 已提交
5433 5434
            return;
        }
5435
        gen_mfc0(env, ctx, rd, ctx->opcode & 0x7);
5436
        gen_store_gpr(cpu_T[0], rt);
B
bellard 已提交
5437 5438 5439
        opn = "mfc0";
        break;
    case OPC_MTC0:
5440
        gen_load_gpr(cpu_T[0], rt);
5441
        save_cpu_state(ctx, 1);
5442
        gen_mtc0(env, ctx, rd, ctx->opcode & 0x7);
B
bellard 已提交
5443 5444
        opn = "mtc0";
        break;
5445
#if defined(TARGET_MIPS64)
T
ths 已提交
5446
    case OPC_DMFC0:
5447
        check_insn(env, ctx, ISA_MIPS3);
T
ths 已提交
5448
        if (rt == 0) {
5449
            /* Treat as NOP. */
T
ths 已提交
5450 5451
            return;
        }
5452
        gen_dmfc0(env, ctx, rd, ctx->opcode & 0x7);
5453
        gen_store_gpr(cpu_T[0], rt);
T
ths 已提交
5454 5455 5456
        opn = "dmfc0";
        break;
    case OPC_DMTC0:
5457
        check_insn(env, ctx, ISA_MIPS3);
5458
        gen_load_gpr(cpu_T[0], rt);
5459
        save_cpu_state(ctx, 1);
5460
        gen_dmtc0(env, ctx, rd, ctx->opcode & 0x7);
T
ths 已提交
5461 5462
        opn = "dmtc0";
        break;
5463
#endif
5464
    case OPC_MFTR:
5465
        check_insn(env, ctx, ASE_MT);
5466 5467 5468 5469 5470 5471
        if (rd == 0) {
            /* Treat as NOP. */
            return;
        }
        gen_mftr(env, ctx, rt, (ctx->opcode >> 5) & 1,
                 ctx->opcode & 0x7, (ctx->opcode >> 4) & 1);
5472
        gen_store_gpr(cpu_T[0], rd);
5473 5474 5475
        opn = "mftr";
        break;
    case OPC_MTTR:
5476
        check_insn(env, ctx, ASE_MT);
5477
        gen_load_gpr(cpu_T[0], rt);
5478 5479 5480 5481
        gen_mttr(env, ctx, rd, (ctx->opcode >> 5) & 1,
                 ctx->opcode & 0x7, (ctx->opcode >> 4) & 1);
        opn = "mttr";
        break;
B
bellard 已提交
5482 5483
    case OPC_TLBWI:
        opn = "tlbwi";
5484
        if (!env->tlb->do_tlbwi)
5485
            goto die;
T
ths 已提交
5486
        tcg_gen_helper_0_0(env->tlb->do_tlbwi);
B
bellard 已提交
5487 5488 5489
        break;
    case OPC_TLBWR:
        opn = "tlbwr";
5490
        if (!env->tlb->do_tlbwr)
5491
            goto die;
T
ths 已提交
5492
        tcg_gen_helper_0_0(env->tlb->do_tlbwr);
B
bellard 已提交
5493 5494 5495
        break;
    case OPC_TLBP:
        opn = "tlbp";
5496
        if (!env->tlb->do_tlbp)
5497
            goto die;
T
ths 已提交
5498
        tcg_gen_helper_0_0(env->tlb->do_tlbp);
B
bellard 已提交
5499 5500 5501
        break;
    case OPC_TLBR:
        opn = "tlbr";
5502
        if (!env->tlb->do_tlbr)
5503
            goto die;
T
ths 已提交
5504
        tcg_gen_helper_0_0(env->tlb->do_tlbr);
B
bellard 已提交
5505 5506 5507
        break;
    case OPC_ERET:
        opn = "eret";
5508
        check_insn(env, ctx, ISA_MIPS2);
5509
        save_cpu_state(ctx, 1);
5510
        tcg_gen_helper_0_0(do_eret);
B
bellard 已提交
5511 5512 5513 5514
        ctx->bstate = BS_EXCP;
        break;
    case OPC_DERET:
        opn = "deret";
5515
        check_insn(env, ctx, ISA_MIPS32);
B
bellard 已提交
5516
        if (!(ctx->hflags & MIPS_HFLAG_DM)) {
5517
            MIPS_INVAL(opn);
B
bellard 已提交
5518 5519
            generate_exception(ctx, EXCP_RI);
        } else {
5520
            save_cpu_state(ctx, 1);
5521
            tcg_gen_helper_0_0(do_deret);
B
bellard 已提交
5522 5523 5524
            ctx->bstate = BS_EXCP;
        }
        break;
B
bellard 已提交
5525 5526
    case OPC_WAIT:
        opn = "wait";
5527
        check_insn(env, ctx, ISA_MIPS3 | ISA_MIPS32);
B
bellard 已提交
5528 5529 5530 5531
        /* If we get an exception, we want to restart at next instruction */
        ctx->pc += 4;
        save_cpu_state(ctx, 1);
        ctx->pc -= 4;
T
ths 已提交
5532
        tcg_gen_helper_0_0(do_wait);
B
bellard 已提交
5533 5534
        ctx->bstate = BS_EXCP;
        break;
B
bellard 已提交
5535
    default:
5536
 die:
5537
        MIPS_INVAL(opn);
B
bellard 已提交
5538 5539 5540 5541 5542
        generate_exception(ctx, EXCP_RI);
        return;
    }
    MIPS_DEBUG("%s %s %d", opn, regnames[rt], rd);
}
5543
#endif /* !CONFIG_USER_ONLY */
B
bellard 已提交
5544

B
bellard 已提交
5545
/* CP1 Branches (before delay slot) */
5546
static void gen_compute_branch1 (CPUState *env, DisasContext *ctx, uint32_t op,
5547
                                 int32_t cc, int32_t offset)
B
bellard 已提交
5548 5549
{
    target_ulong btarget;
5550
    const char *opn = "cp1 cond branch";
B
bellard 已提交
5551

5552 5553 5554
    if (cc != 0)
        check_insn(env, ctx, ISA_MIPS4 | ISA_MIPS32);

B
bellard 已提交
5555 5556
    btarget = ctx->pc + 4 + offset;

5557 5558
    switch (op) {
    case OPC_BC1F:
5559 5560 5561 5562 5563 5564 5565 5566 5567 5568 5569 5570 5571 5572 5573 5574 5575 5576
        {
            int l1 = gen_new_label();
            int l2 = gen_new_label();
            TCGv r_tmp1 = tcg_temp_new(TCG_TYPE_I32);

            get_fp_cond(r_tmp1);
            tcg_gen_ext_i32_tl(cpu_T[0], r_tmp1);
            tcg_temp_free(r_tmp1);
            tcg_gen_not_tl(cpu_T[0], cpu_T[0]);
            tcg_gen_movi_tl(cpu_T[1], 0x1 << cc);
            tcg_gen_and_tl(cpu_T[0], cpu_T[0], cpu_T[1]);
            tcg_gen_brcondi_tl(TCG_COND_NE, cpu_T[0], 0, l1);
            tcg_gen_movi_tl(cpu_T[0], 0);
            tcg_gen_br(l2);
            gen_set_label(l1);
            tcg_gen_movi_tl(cpu_T[0], 1);
            gen_set_label(l2);
        }
5577
        opn = "bc1f";
B
bellard 已提交
5578
        goto not_likely;
5579
    case OPC_BC1FL:
5580 5581 5582 5583 5584 5585 5586 5587 5588 5589 5590 5591 5592 5593 5594 5595 5596 5597
        {
            int l1 = gen_new_label();
            int l2 = gen_new_label();
            TCGv r_tmp1 = tcg_temp_new(TCG_TYPE_I32);

            get_fp_cond(r_tmp1);
            tcg_gen_ext_i32_tl(cpu_T[0], r_tmp1);
            tcg_temp_free(r_tmp1);
            tcg_gen_not_tl(cpu_T[0], cpu_T[0]);
            tcg_gen_movi_tl(cpu_T[1], 0x1 << cc);
            tcg_gen_and_tl(cpu_T[0], cpu_T[0], cpu_T[1]);
            tcg_gen_brcondi_tl(TCG_COND_NE, cpu_T[0], 0, l1);
            tcg_gen_movi_tl(cpu_T[0], 0);
            tcg_gen_br(l2);
            gen_set_label(l1);
            tcg_gen_movi_tl(cpu_T[0], 1);
            gen_set_label(l2);
        }
5598
        opn = "bc1fl";
B
bellard 已提交
5599
        goto likely;
5600
    case OPC_BC1T:
5601 5602 5603 5604 5605 5606 5607 5608 5609 5610 5611 5612 5613 5614 5615 5616 5617
        {
            int l1 = gen_new_label();
            int l2 = gen_new_label();
            TCGv r_tmp1 = tcg_temp_new(TCG_TYPE_I32);

            get_fp_cond(r_tmp1);
            tcg_gen_ext_i32_tl(cpu_T[0], r_tmp1);
            tcg_temp_free(r_tmp1);
            tcg_gen_movi_tl(cpu_T[1], 0x1 << cc);
            tcg_gen_and_tl(cpu_T[0], cpu_T[0], cpu_T[1]);
            tcg_gen_brcondi_tl(TCG_COND_NE, cpu_T[0], 0, l1);
            tcg_gen_movi_tl(cpu_T[0], 0);
            tcg_gen_br(l2);
            gen_set_label(l1);
            tcg_gen_movi_tl(cpu_T[0], 1);
            gen_set_label(l2);
        }
5618
        opn = "bc1t";
5619
        goto not_likely;
5620
    case OPC_BC1TL:
5621 5622 5623 5624 5625 5626 5627 5628 5629 5630 5631 5632 5633 5634 5635 5636 5637
        {
            int l1 = gen_new_label();
            int l2 = gen_new_label();
            TCGv r_tmp1 = tcg_temp_new(TCG_TYPE_I32);

            get_fp_cond(r_tmp1);
            tcg_gen_ext_i32_tl(cpu_T[0], r_tmp1);
            tcg_temp_free(r_tmp1);
            tcg_gen_movi_tl(cpu_T[1], 0x1 << cc);
            tcg_gen_and_tl(cpu_T[0], cpu_T[0], cpu_T[1]);
            tcg_gen_brcondi_tl(TCG_COND_NE, cpu_T[0], 0, l1);
            tcg_gen_movi_tl(cpu_T[0], 0);
            tcg_gen_br(l2);
            gen_set_label(l1);
            tcg_gen_movi_tl(cpu_T[0], 1);
            gen_set_label(l2);
        }
5638
        opn = "bc1tl";
B
bellard 已提交
5639 5640
    likely:
        ctx->hflags |= MIPS_HFLAG_BL;
5641
        tcg_gen_st_tl(cpu_T[0], cpu_env, offsetof(CPUState, bcond));
B
bellard 已提交
5642
        break;
5643
    case OPC_BC1FANY2:
5644 5645 5646 5647 5648 5649 5650 5651 5652 5653 5654 5655 5656 5657 5658 5659 5660 5661
        {
            int l1 = gen_new_label();
            int l2 = gen_new_label();
            TCGv r_tmp1 = tcg_temp_new(TCG_TYPE_I32);

            get_fp_cond(r_tmp1);
            tcg_gen_ext_i32_tl(cpu_T[0], r_tmp1);
            tcg_temp_free(r_tmp1);
            tcg_gen_not_tl(cpu_T[0], cpu_T[0]);
            tcg_gen_movi_tl(cpu_T[1], 0x3 << cc);
            tcg_gen_and_tl(cpu_T[0], cpu_T[0], cpu_T[1]);
            tcg_gen_brcondi_tl(TCG_COND_NE, cpu_T[0], 0, l1);
            tcg_gen_movi_tl(cpu_T[0], 0);
            tcg_gen_br(l2);
            gen_set_label(l1);
            tcg_gen_movi_tl(cpu_T[0], 1);
            gen_set_label(l2);
        }
5662
        opn = "bc1any2f";
5663 5664
        goto not_likely;
    case OPC_BC1TANY2:
5665 5666 5667 5668 5669 5670 5671 5672 5673 5674 5675 5676 5677 5678 5679 5680 5681
        {
            int l1 = gen_new_label();
            int l2 = gen_new_label();
            TCGv r_tmp1 = tcg_temp_new(TCG_TYPE_I32);

            get_fp_cond(r_tmp1);
            tcg_gen_ext_i32_tl(cpu_T[0], r_tmp1);
            tcg_temp_free(r_tmp1);
            tcg_gen_movi_tl(cpu_T[1], 0x3 << cc);
            tcg_gen_and_tl(cpu_T[0], cpu_T[0], cpu_T[1]);
            tcg_gen_brcondi_tl(TCG_COND_NE, cpu_T[0], 0, l1);
            tcg_gen_movi_tl(cpu_T[0], 0);
            tcg_gen_br(l2);
            gen_set_label(l1);
            tcg_gen_movi_tl(cpu_T[0], 1);
            gen_set_label(l2);
        }
5682
        opn = "bc1any2t";
5683 5684
        goto not_likely;
    case OPC_BC1FANY4:
5685 5686 5687 5688 5689 5690 5691 5692 5693 5694 5695 5696 5697 5698 5699 5700 5701 5702
        {
            int l1 = gen_new_label();
            int l2 = gen_new_label();
            TCGv r_tmp1 = tcg_temp_new(TCG_TYPE_I32);

            get_fp_cond(r_tmp1);
            tcg_gen_ext_i32_tl(cpu_T[0], r_tmp1);
            tcg_temp_free(r_tmp1);
            tcg_gen_not_tl(cpu_T[0], cpu_T[0]);
            tcg_gen_movi_tl(cpu_T[1], 0xf << cc);
            tcg_gen_and_tl(cpu_T[0], cpu_T[0], cpu_T[1]);
            tcg_gen_brcondi_tl(TCG_COND_NE, cpu_T[0], 0, l1);
            tcg_gen_movi_tl(cpu_T[0], 0);
            tcg_gen_br(l2);
            gen_set_label(l1);
            tcg_gen_movi_tl(cpu_T[0], 1);
            gen_set_label(l2);
        }
5703
        opn = "bc1any4f";
5704 5705
        goto not_likely;
    case OPC_BC1TANY4:
5706 5707 5708 5709 5710 5711 5712 5713 5714 5715 5716 5717 5718 5719 5720 5721 5722
        {
            int l1 = gen_new_label();
            int l2 = gen_new_label();
            TCGv r_tmp1 = tcg_temp_new(TCG_TYPE_I32);

            get_fp_cond(r_tmp1);
            tcg_gen_ext_i32_tl(cpu_T[0], r_tmp1);
            tcg_temp_free(r_tmp1);
            tcg_gen_movi_tl(cpu_T[1], 0xf << cc);
            tcg_gen_and_tl(cpu_T[0], cpu_T[0], cpu_T[1]);
            tcg_gen_brcondi_tl(TCG_COND_NE, cpu_T[0], 0, l1);
            tcg_gen_movi_tl(cpu_T[0], 0);
            tcg_gen_br(l2);
            gen_set_label(l1);
            tcg_gen_movi_tl(cpu_T[0], 1);
            gen_set_label(l2);
        }
5723
        opn = "bc1any4t";
5724 5725
    not_likely:
        ctx->hflags |= MIPS_HFLAG_BC;
5726
        tcg_gen_st_tl(cpu_T[0], cpu_env, offsetof(CPUState, bcond));
5727 5728
        break;
    default:
5729
        MIPS_INVAL(opn);
5730
        generate_exception (ctx, EXCP_RI);
B
bellard 已提交
5731 5732
        return;
    }
5733
    MIPS_DEBUG("%s: cond %02x target " TARGET_FMT_lx, opn,
B
bellard 已提交
5734 5735 5736 5737
               ctx->hflags, btarget);
    ctx->btarget = btarget;
}

B
bellard 已提交
5738
/* Coprocessor 1 (FPU) */
5739 5740 5741

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

5742
static void gen_cp1 (DisasContext *ctx, uint32_t opc, int rt, int fs)
B
bellard 已提交
5743
{
5744
    const char *opn = "cp1 move";
B
bellard 已提交
5745 5746 5747

    switch (opc) {
    case OPC_MFC1:
T
ths 已提交
5748 5749
        gen_load_fpr32(fpu32_T[0], fs);
        tcg_gen_ext_i32_tl(cpu_T[0], fpu32_T[0]);
5750
        gen_store_gpr(cpu_T[0], rt);
B
bellard 已提交
5751 5752 5753
        opn = "mfc1";
        break;
    case OPC_MTC1:
5754
        gen_load_gpr(cpu_T[0], rt);
T
ths 已提交
5755 5756
        tcg_gen_trunc_tl_i32(fpu32_T[0], cpu_T[0]);
        gen_store_fpr32(fpu32_T[0], fs);
B
bellard 已提交
5757 5758 5759
        opn = "mtc1";
        break;
    case OPC_CFC1:
5760
        tcg_gen_helper_0_1i(do_cfc1, fs);
5761
        gen_store_gpr(cpu_T[0], rt);
B
bellard 已提交
5762 5763 5764
        opn = "cfc1";
        break;
    case OPC_CTC1:
5765
        gen_load_gpr(cpu_T[0], rt);
5766
        tcg_gen_helper_0_1i(do_ctc1, fs);
B
bellard 已提交
5767 5768
        opn = "ctc1";
        break;
T
ths 已提交
5769
    case OPC_DMFC1:
T
ths 已提交
5770 5771
        gen_load_fpr64(ctx, fpu64_T[0], fs);
        tcg_gen_mov_tl(cpu_T[0], fpu64_T[0]);
5772
        gen_store_gpr(cpu_T[0], rt);
5773 5774
        opn = "dmfc1";
        break;
T
ths 已提交
5775
    case OPC_DMTC1:
5776
        gen_load_gpr(cpu_T[0], rt);
T
ths 已提交
5777 5778
        tcg_gen_mov_tl(fpu64_T[0], cpu_T[0]);
        gen_store_fpr64(ctx, fpu64_T[0], fs);
5779 5780 5781
        opn = "dmtc1";
        break;
    case OPC_MFHC1:
T
ths 已提交
5782 5783
        gen_load_fpr32h(fpu32h_T[0], fs);
        tcg_gen_ext_i32_tl(cpu_T[0], fpu32h_T[0]);
5784
        gen_store_gpr(cpu_T[0], rt);
5785 5786 5787
        opn = "mfhc1";
        break;
    case OPC_MTHC1:
5788
        gen_load_gpr(cpu_T[0], rt);
T
ths 已提交
5789 5790
        tcg_gen_trunc_tl_i32(fpu32h_T[0], cpu_T[0]);
        gen_store_fpr32h(fpu32h_T[0], fs);
5791 5792
        opn = "mthc1";
        break;
B
bellard 已提交
5793
    default:
5794
        MIPS_INVAL(opn);
5795
        generate_exception (ctx, EXCP_RI);
B
bellard 已提交
5796 5797 5798 5799 5800
        return;
    }
    MIPS_DEBUG("%s %s %s", opn, regnames[rt], fregnames[fs]);
}

5801 5802
static void gen_movci (DisasContext *ctx, int rd, int rs, int cc, int tf)
{
T
ths 已提交
5803
    int l1 = gen_new_label();
5804
    uint32_t ccbit;
T
ths 已提交
5805
    TCGCond cond;
B
bellard 已提交
5806

T
ths 已提交
5807
    if (cc)
5808
        ccbit = 1 << (24 + cc);
T
ths 已提交
5809
    else
5810
        ccbit = 1 << 23;
T
ths 已提交
5811 5812
    if (tf)
        cond = TCG_COND_EQ;
5813 5814 5815 5816 5817 5818 5819
    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 已提交
5820
        TCGv r_tmp = tcg_temp_local_new(TCG_TYPE_I32);
5821 5822 5823

        tcg_gen_ld_ptr(r_ptr, cpu_env, offsetof(CPUState, fpu));
        tcg_gen_ld_i32(r_tmp, r_ptr, offsetof(CPUMIPSFPUContext, fcr31));
5824
        tcg_temp_free(r_ptr);
5825 5826
        tcg_gen_andi_i32(r_tmp, r_tmp, ccbit);
        tcg_gen_brcondi_i32(cond, r_tmp, 0, l1);
T
ths 已提交
5827
        tcg_temp_free(r_tmp);
5828 5829
    }
    tcg_gen_mov_tl(cpu_T[0], cpu_T[1]);
T
ths 已提交
5830 5831

    gen_set_label(l1);
5832
    gen_store_gpr(cpu_T[0], rd);
5833 5834
}

5835 5836 5837 5838 5839 5840 5841 5842 5843 5844 5845 5846 5847 5848 5849 5850 5851 5852 5853 5854 5855 5856 5857
static inline void gen_movcf_s (int cc, int tf)
{
    uint32_t ccbit;
    int cond;
    TCGv r_tmp1 = tcg_temp_new(TCG_TYPE_I32);
    int l1 = gen_new_label();

    if (cc)
        ccbit = 1 << (24 + cc);
    else
        ccbit = 1 << 23;

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

    tcg_gen_ld_i32(r_tmp1, current_fpu, offsetof(CPUMIPSFPUContext, fcr31));
    tcg_gen_andi_i32(r_tmp1, r_tmp1, ccbit);
    tcg_gen_brcondi_i32(cond, r_tmp1, 0, l1);
    tcg_gen_movi_i32(fpu32_T[2], fpu32_T[0]);
    gen_set_label(l1);
    tcg_temp_free(r_tmp1);
5858
}
5859 5860 5861 5862 5863 5864 5865 5866 5867 5868 5869 5870 5871 5872 5873 5874 5875 5876 5877 5878 5879 5880 5881 5882 5883 5884 5885 5886 5887 5888 5889 5890 5891 5892 5893 5894 5895 5896 5897 5898 5899 5900 5901 5902 5903 5904 5905 5906 5907 5908 5909 5910 5911

static inline void gen_movcf_d (int cc, int tf)
{
    uint32_t ccbit;
    int cond;
    TCGv r_tmp1 = tcg_temp_new(TCG_TYPE_I32);
    int l1 = gen_new_label();

    if (cc)
        ccbit = 1 << (24 + cc);
    else
        ccbit = 1 << 23;

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

    tcg_gen_ld_i32(r_tmp1, current_fpu, offsetof(CPUMIPSFPUContext, fcr31));
    tcg_gen_andi_i32(r_tmp1, r_tmp1, ccbit);
    tcg_gen_brcondi_i32(cond, r_tmp1, 0, l1);
    tcg_gen_movi_i64(fpu64_T[2], fpu64_T[0]);
    gen_set_label(l1);
    tcg_temp_free(r_tmp1);
}

static inline void gen_movcf_ps (int cc, int tf)
{
    int cond;
    TCGv r_tmp1 = tcg_temp_local_new(TCG_TYPE_I32);
    TCGv r_tmp2 = tcg_temp_local_new(TCG_TYPE_I32);
    int l1 = gen_new_label();
    int l2 = gen_new_label();

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

    get_fp_cond(r_tmp1);
    tcg_gen_shri_i32(r_tmp1, r_tmp1, cc);
    tcg_gen_andi_i32(r_tmp2, r_tmp1, 0x1);
    tcg_gen_brcondi_i32(cond, r_tmp2, 0, l1);
    tcg_gen_movi_i32(fpu32_T[2], fpu32_T[0]);
    gen_set_label(l1);
    tcg_gen_andi_i32(r_tmp2, r_tmp1, 0x2);
    tcg_gen_brcondi_i32(cond, r_tmp2, 0, l2);
    tcg_gen_movi_i32(fpu32h_T[2], fpu32h_T[0]);
    gen_set_label(l2);
    tcg_temp_free(r_tmp1);
    tcg_temp_free(r_tmp2);
}

B
bellard 已提交
5912

5913 5914
static void gen_farith (DisasContext *ctx, uint32_t op1,
                        int ft, int fs, int fd, int cc)
B
bellard 已提交
5915
{
5916
    const char *opn = "farith";
B
bellard 已提交
5917 5918 5919 5920 5921 5922 5923 5924 5925 5926 5927 5928 5929 5930 5931 5932 5933 5934
    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",
    };
5935 5936 5937 5938 5939 5940 5941 5942 5943 5944 5945 5946 5947 5948 5949 5950 5951 5952 5953
    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;
5954 5955
    uint32_t func = ctx->opcode & 0x3f;

B
bellard 已提交
5956
    switch (ctx->opcode & FOP(0x3f, 0x1f)) {
5957
    case FOP(0, 16):
T
ths 已提交
5958 5959
        gen_load_fpr32(fpu32_T[0], fs);
        gen_load_fpr32(fpu32_T[1], ft);
5960
        tcg_gen_helper_0_0(do_float_add_s);
T
ths 已提交
5961
        gen_store_fpr32(fpu32_T[2], fd);
5962
        opn = "add.s";
5963
        optype = BINOP;
5964 5965
        break;
    case FOP(1, 16):
T
ths 已提交
5966 5967
        gen_load_fpr32(fpu32_T[0], fs);
        gen_load_fpr32(fpu32_T[1], ft);
5968
        tcg_gen_helper_0_0(do_float_sub_s);
T
ths 已提交
5969
        gen_store_fpr32(fpu32_T[2], fd);
5970
        opn = "sub.s";
5971
        optype = BINOP;
5972 5973
        break;
    case FOP(2, 16):
T
ths 已提交
5974 5975
        gen_load_fpr32(fpu32_T[0], fs);
        gen_load_fpr32(fpu32_T[1], ft);
5976
        tcg_gen_helper_0_0(do_float_mul_s);
T
ths 已提交
5977
        gen_store_fpr32(fpu32_T[2], fd);
5978
        opn = "mul.s";
5979
        optype = BINOP;
5980 5981
        break;
    case FOP(3, 16):
T
ths 已提交
5982 5983
        gen_load_fpr32(fpu32_T[0], fs);
        gen_load_fpr32(fpu32_T[1], ft);
5984
        tcg_gen_helper_0_0(do_float_div_s);
T
ths 已提交
5985
        gen_store_fpr32(fpu32_T[2], fd);
5986
        opn = "div.s";
5987
        optype = BINOP;
5988 5989
        break;
    case FOP(4, 16):
T
ths 已提交
5990
        gen_load_fpr32(fpu32_T[0], fs);
5991
        tcg_gen_helper_0_0(do_float_sqrt_s);
T
ths 已提交
5992
        gen_store_fpr32(fpu32_T[2], fd);
5993 5994 5995
        opn = "sqrt.s";
        break;
    case FOP(5, 16):
T
ths 已提交
5996
        gen_load_fpr32(fpu32_T[0], fs);
5997
        tcg_gen_helper_0_0(do_float_abs_s);
T
ths 已提交
5998
        gen_store_fpr32(fpu32_T[2], fd);
5999 6000 6001
        opn = "abs.s";
        break;
    case FOP(6, 16):
T
ths 已提交
6002
        gen_load_fpr32(fpu32_T[0], fs);
T
ths 已提交
6003
        gen_store_fpr32(fpu32_T[0], fd);
6004 6005 6006
        opn = "mov.s";
        break;
    case FOP(7, 16):
T
ths 已提交
6007
        gen_load_fpr32(fpu32_T[0], fs);
6008
        tcg_gen_helper_0_0(do_float_chs_s);
T
ths 已提交
6009
        gen_store_fpr32(fpu32_T[2], fd);
6010 6011 6012
        opn = "neg.s";
        break;
    case FOP(8, 16):
6013
        check_cp1_64bitmode(ctx);
T
ths 已提交
6014
        gen_load_fpr32(fpu32_T[0], fs);
6015
        tcg_gen_helper_0_0(do_float_roundl_s);
T
ths 已提交
6016
        gen_store_fpr64(ctx, fpu64_T[2], fd);
6017 6018 6019
        opn = "round.l.s";
        break;
    case FOP(9, 16):
6020
        check_cp1_64bitmode(ctx);
T
ths 已提交
6021
        gen_load_fpr32(fpu32_T[0], fs);
6022
        tcg_gen_helper_0_0(do_float_truncl_s);
T
ths 已提交
6023
        gen_store_fpr64(ctx, fpu64_T[2], fd);
6024 6025 6026
        opn = "trunc.l.s";
        break;
    case FOP(10, 16):
6027
        check_cp1_64bitmode(ctx);
T
ths 已提交
6028
        gen_load_fpr32(fpu32_T[0], fs);
6029
        tcg_gen_helper_0_0(do_float_ceill_s);
T
ths 已提交
6030
        gen_store_fpr64(ctx, fpu64_T[2], fd);
6031 6032 6033
        opn = "ceil.l.s";
        break;
    case FOP(11, 16):
6034
        check_cp1_64bitmode(ctx);
T
ths 已提交
6035
        gen_load_fpr32(fpu32_T[0], fs);
6036
        tcg_gen_helper_0_0(do_float_floorl_s);
T
ths 已提交
6037
        gen_store_fpr64(ctx, fpu64_T[2], fd);
6038 6039 6040
        opn = "floor.l.s";
        break;
    case FOP(12, 16):
T
ths 已提交
6041
        gen_load_fpr32(fpu32_T[0], fs);
6042
        tcg_gen_helper_0_0(do_float_roundw_s);
T
ths 已提交
6043
        gen_store_fpr32(fpu32_T[2], fd);
6044 6045 6046
        opn = "round.w.s";
        break;
    case FOP(13, 16):
T
ths 已提交
6047
        gen_load_fpr32(fpu32_T[0], fs);
6048
        tcg_gen_helper_0_0(do_float_truncw_s);
T
ths 已提交
6049
        gen_store_fpr32(fpu32_T[2], fd);
6050 6051 6052
        opn = "trunc.w.s";
        break;
    case FOP(14, 16):
T
ths 已提交
6053
        gen_load_fpr32(fpu32_T[0], fs);
6054
        tcg_gen_helper_0_0(do_float_ceilw_s);
T
ths 已提交
6055
        gen_store_fpr32(fpu32_T[2], fd);
6056 6057 6058
        opn = "ceil.w.s";
        break;
    case FOP(15, 16):
T
ths 已提交
6059
        gen_load_fpr32(fpu32_T[0], fs);
6060
        tcg_gen_helper_0_0(do_float_floorw_s);
T
ths 已提交
6061
        gen_store_fpr32(fpu32_T[2], fd);
6062 6063 6064
        opn = "floor.w.s";
        break;
    case FOP(17, 16):
T
ths 已提交
6065 6066
        gen_load_fpr32(fpu32_T[0], fs);
        gen_load_fpr32(fpu32_T[2], fd);
6067
        gen_movcf_s((ft >> 2) & 0x7, ft & 0x1);
T
ths 已提交
6068
        gen_store_fpr32(fpu32_T[2], fd);
6069 6070 6071
        opn = "movcf.s";
        break;
    case FOP(18, 16):
6072
        gen_load_gpr(cpu_T[0], ft);
T
ths 已提交
6073 6074
        gen_load_fpr32(fpu32_T[0], fs);
        gen_load_fpr32(fpu32_T[2], fd);
6075 6076 6077 6078 6079 6080 6081
        {
            int l1 = gen_new_label();

            tcg_gen_brcondi_tl(TCG_COND_NE, cpu_T[0], 0, l1);
            tcg_gen_mov_i32(fpu32_T[2], fpu32_T[0]);
            gen_set_label(l1);
        }
T
ths 已提交
6082
        gen_store_fpr32(fpu32_T[2], fd);
6083 6084 6085
        opn = "movz.s";
        break;
    case FOP(19, 16):
6086
        gen_load_gpr(cpu_T[0], ft);
T
ths 已提交
6087 6088
        gen_load_fpr32(fpu32_T[0], fs);
        gen_load_fpr32(fpu32_T[2], fd);
6089 6090 6091 6092 6093 6094 6095
        {
            int l1 = gen_new_label();

            tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_T[0], 0, l1);
            tcg_gen_mov_i32(fpu32_T[2], fpu32_T[0]);
            gen_set_label(l1);
        }
T
ths 已提交
6096
        gen_store_fpr32(fpu32_T[2], fd);
6097 6098
        opn = "movn.s";
        break;
T
ths 已提交
6099
    case FOP(21, 16):
6100
        check_cop1x(ctx);
T
ths 已提交
6101
        gen_load_fpr32(fpu32_T[0], fs);
6102
        tcg_gen_helper_0_0(do_float_recip_s);
T
ths 已提交
6103
        gen_store_fpr32(fpu32_T[2], fd);
T
ths 已提交
6104 6105 6106
        opn = "recip.s";
        break;
    case FOP(22, 16):
6107
        check_cop1x(ctx);
T
ths 已提交
6108
        gen_load_fpr32(fpu32_T[0], fs);
6109
        tcg_gen_helper_0_0(do_float_rsqrt_s);
T
ths 已提交
6110
        gen_store_fpr32(fpu32_T[2], fd);
T
ths 已提交
6111 6112 6113
        opn = "rsqrt.s";
        break;
    case FOP(28, 16):
6114
        check_cp1_64bitmode(ctx);
T
ths 已提交
6115 6116
        gen_load_fpr32(fpu32_T[0], fs);
        gen_load_fpr32(fpu32_T[2], fd);
6117
        tcg_gen_helper_0_0(do_float_recip2_s);
T
ths 已提交
6118
        gen_store_fpr32(fpu32_T[2], fd);
T
ths 已提交
6119 6120 6121
        opn = "recip2.s";
        break;
    case FOP(29, 16):
6122
        check_cp1_64bitmode(ctx);
T
ths 已提交
6123
        gen_load_fpr32(fpu32_T[0], fs);
6124
        tcg_gen_helper_0_0(do_float_recip1_s);
T
ths 已提交
6125
        gen_store_fpr32(fpu32_T[2], fd);
T
ths 已提交
6126 6127 6128
        opn = "recip1.s";
        break;
    case FOP(30, 16):
6129
        check_cp1_64bitmode(ctx);
T
ths 已提交
6130
        gen_load_fpr32(fpu32_T[0], fs);
6131
        tcg_gen_helper_0_0(do_float_rsqrt1_s);
T
ths 已提交
6132
        gen_store_fpr32(fpu32_T[2], fd);
T
ths 已提交
6133 6134 6135
        opn = "rsqrt1.s";
        break;
    case FOP(31, 16):
6136
        check_cp1_64bitmode(ctx);
T
ths 已提交
6137 6138
        gen_load_fpr32(fpu32_T[0], fs);
        gen_load_fpr32(fpu32_T[2], ft);
6139
        tcg_gen_helper_0_0(do_float_rsqrt2_s);
T
ths 已提交
6140
        gen_store_fpr32(fpu32_T[2], fd);
T
ths 已提交
6141 6142
        opn = "rsqrt2.s";
        break;
6143
    case FOP(33, 16):
6144
        check_cp1_registers(ctx, fd);
T
ths 已提交
6145
        gen_load_fpr32(fpu32_T[0], fs);
6146
        tcg_gen_helper_0_0(do_float_cvtd_s);
T
ths 已提交
6147
        gen_store_fpr64(ctx, fpu64_T[2], fd);
6148 6149 6150
        opn = "cvt.d.s";
        break;
    case FOP(36, 16):
T
ths 已提交
6151
        gen_load_fpr32(fpu32_T[0], fs);
6152
        tcg_gen_helper_0_0(do_float_cvtw_s);
T
ths 已提交
6153
        gen_store_fpr32(fpu32_T[2], fd);
6154 6155 6156
        opn = "cvt.w.s";
        break;
    case FOP(37, 16):
6157
        check_cp1_64bitmode(ctx);
T
ths 已提交
6158
        gen_load_fpr32(fpu32_T[0], fs);
6159
        tcg_gen_helper_0_0(do_float_cvtl_s);
T
ths 已提交
6160
        gen_store_fpr64(ctx, fpu64_T[2], fd);
6161 6162 6163
        opn = "cvt.l.s";
        break;
    case FOP(38, 16):
6164
        check_cp1_64bitmode(ctx);
T
ths 已提交
6165 6166 6167 6168 6169 6170
        gen_load_fpr32(fpu32_T[0], fs);
        gen_load_fpr32(fpu32_T[1], ft);
        tcg_gen_extu_i32_i64(fpu64_T[0], fpu32_T[0]);
        tcg_gen_extu_i32_i64(fpu64_T[1], fpu32_T[1]);
        tcg_gen_shli_i64(fpu64_T[1], fpu64_T[1], 32);
        tcg_gen_or_i64(fpu64_T[2], fpu64_T[0], fpu64_T[1]);
T
ths 已提交
6171
        gen_store_fpr64(ctx, fpu64_T[2], fd);
6172 6173 6174 6175 6176 6177 6178 6179 6180 6181 6182 6183 6184 6185 6186 6187 6188 6189
        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 已提交
6190 6191
        gen_load_fpr32(fpu32_T[0], fs);
        gen_load_fpr32(fpu32_T[1], ft);
6192
        if (ctx->opcode & (1 << 6)) {
6193
            check_cop1x(ctx);
6194 6195 6196 6197 6198 6199
            gen_cmpabs_s(func-48, cc);
            opn = condnames_abs[func-48];
        } else {
            gen_cmp_s(func-48, cc);
            opn = condnames[func-48];
        }
6200
        break;
B
bellard 已提交
6201
    case FOP(0, 17):
6202
        check_cp1_registers(ctx, fs | ft | fd);
T
ths 已提交
6203 6204
        gen_load_fpr64(ctx, fpu64_T[0], fs);
        gen_load_fpr64(ctx, fpu64_T[1], ft);
6205
        tcg_gen_helper_0_0(do_float_add_d);
T
ths 已提交
6206
        gen_store_fpr64(ctx, fpu64_T[2], fd);
B
bellard 已提交
6207
        opn = "add.d";
6208
        optype = BINOP;
B
bellard 已提交
6209 6210
        break;
    case FOP(1, 17):
6211
        check_cp1_registers(ctx, fs | ft | fd);
T
ths 已提交
6212 6213
        gen_load_fpr64(ctx, fpu64_T[0], fs);
        gen_load_fpr64(ctx, fpu64_T[1], ft);
6214
        tcg_gen_helper_0_0(do_float_sub_d);
T
ths 已提交
6215
        gen_store_fpr64(ctx, fpu64_T[2], fd);
B
bellard 已提交
6216
        opn = "sub.d";
6217
        optype = BINOP;
B
bellard 已提交
6218 6219
        break;
    case FOP(2, 17):
6220
        check_cp1_registers(ctx, fs | ft | fd);
T
ths 已提交
6221 6222
        gen_load_fpr64(ctx, fpu64_T[0], fs);
        gen_load_fpr64(ctx, fpu64_T[1], ft);
6223
        tcg_gen_helper_0_0(do_float_mul_d);
T
ths 已提交
6224
        gen_store_fpr64(ctx, fpu64_T[2], fd);
B
bellard 已提交
6225
        opn = "mul.d";
6226
        optype = BINOP;
B
bellard 已提交
6227 6228
        break;
    case FOP(3, 17):
6229
        check_cp1_registers(ctx, fs | ft | fd);
T
ths 已提交
6230 6231
        gen_load_fpr64(ctx, fpu64_T[0], fs);
        gen_load_fpr64(ctx, fpu64_T[1], ft);
6232
        tcg_gen_helper_0_0(do_float_div_d);
T
ths 已提交
6233
        gen_store_fpr64(ctx, fpu64_T[2], fd);
B
bellard 已提交
6234
        opn = "div.d";
6235
        optype = BINOP;
B
bellard 已提交
6236 6237
        break;
    case FOP(4, 17):
6238
        check_cp1_registers(ctx, fs | fd);
T
ths 已提交
6239
        gen_load_fpr64(ctx, fpu64_T[0], fs);
6240
        tcg_gen_helper_0_0(do_float_sqrt_d);
T
ths 已提交
6241
        gen_store_fpr64(ctx, fpu64_T[2], fd);
B
bellard 已提交
6242 6243 6244
        opn = "sqrt.d";
        break;
    case FOP(5, 17):
6245
        check_cp1_registers(ctx, fs | fd);
T
ths 已提交
6246
        gen_load_fpr64(ctx, fpu64_T[0], fs);
6247
        tcg_gen_helper_0_0(do_float_abs_d);
T
ths 已提交
6248
        gen_store_fpr64(ctx, fpu64_T[2], fd);
B
bellard 已提交
6249 6250 6251
        opn = "abs.d";
        break;
    case FOP(6, 17):
6252
        check_cp1_registers(ctx, fs | fd);
T
ths 已提交
6253
        gen_load_fpr64(ctx, fpu64_T[0], fs);
T
ths 已提交
6254
        gen_store_fpr64(ctx, fpu64_T[0], fd);
B
bellard 已提交
6255 6256 6257
        opn = "mov.d";
        break;
    case FOP(7, 17):
6258
        check_cp1_registers(ctx, fs | fd);
T
ths 已提交
6259
        gen_load_fpr64(ctx, fpu64_T[0], fs);
6260
        tcg_gen_helper_0_0(do_float_chs_d);
T
ths 已提交
6261
        gen_store_fpr64(ctx, fpu64_T[2], fd);
B
bellard 已提交
6262 6263
        opn = "neg.d";
        break;
6264
    case FOP(8, 17):
6265
        check_cp1_64bitmode(ctx);
T
ths 已提交
6266
        gen_load_fpr64(ctx, fpu64_T[0], fs);
6267
        tcg_gen_helper_0_0(do_float_roundl_d);
T
ths 已提交
6268
        gen_store_fpr64(ctx, fpu64_T[2], fd);
6269 6270 6271
        opn = "round.l.d";
        break;
    case FOP(9, 17):
6272
        check_cp1_64bitmode(ctx);
T
ths 已提交
6273
        gen_load_fpr64(ctx, fpu64_T[0], fs);
6274
        tcg_gen_helper_0_0(do_float_truncl_d);
T
ths 已提交
6275
        gen_store_fpr64(ctx, fpu64_T[2], fd);
6276 6277 6278
        opn = "trunc.l.d";
        break;
    case FOP(10, 17):
6279
        check_cp1_64bitmode(ctx);
T
ths 已提交
6280
        gen_load_fpr64(ctx, fpu64_T[0], fs);
6281
        tcg_gen_helper_0_0(do_float_ceill_d);
T
ths 已提交
6282
        gen_store_fpr64(ctx, fpu64_T[2], fd);
6283 6284 6285
        opn = "ceil.l.d";
        break;
    case FOP(11, 17):
6286
        check_cp1_64bitmode(ctx);
T
ths 已提交
6287
        gen_load_fpr64(ctx, fpu64_T[0], fs);
6288
        tcg_gen_helper_0_0(do_float_floorl_d);
T
ths 已提交
6289
        gen_store_fpr64(ctx, fpu64_T[2], fd);
6290 6291
        opn = "floor.l.d";
        break;
B
bellard 已提交
6292
    case FOP(12, 17):
6293
        check_cp1_registers(ctx, fs);
T
ths 已提交
6294
        gen_load_fpr64(ctx, fpu64_T[0], fs);
6295
        tcg_gen_helper_0_0(do_float_roundw_d);
T
ths 已提交
6296
        gen_store_fpr32(fpu32_T[2], fd);
B
bellard 已提交
6297 6298 6299
        opn = "round.w.d";
        break;
    case FOP(13, 17):
6300
        check_cp1_registers(ctx, fs);
T
ths 已提交
6301
        gen_load_fpr64(ctx, fpu64_T[0], fs);
6302
        tcg_gen_helper_0_0(do_float_truncw_d);
T
ths 已提交
6303
        gen_store_fpr32(fpu32_T[2], fd);
B
bellard 已提交
6304 6305 6306
        opn = "trunc.w.d";
        break;
    case FOP(14, 17):
6307
        check_cp1_registers(ctx, fs);
T
ths 已提交
6308
        gen_load_fpr64(ctx, fpu64_T[0], fs);
6309
        tcg_gen_helper_0_0(do_float_ceilw_d);
T
ths 已提交
6310
        gen_store_fpr32(fpu32_T[2], fd);
B
bellard 已提交
6311 6312 6313
        opn = "ceil.w.d";
        break;
    case FOP(15, 17):
6314
        check_cp1_registers(ctx, fs);
T
ths 已提交
6315
        gen_load_fpr64(ctx, fpu64_T[0], fs);
6316
        tcg_gen_helper_0_0(do_float_floorw_d);
T
ths 已提交
6317
        gen_store_fpr32(fpu32_T[2], fd);
6318
        opn = "floor.w.d";
B
bellard 已提交
6319
        break;
6320
    case FOP(17, 17):
T
ths 已提交
6321 6322
        gen_load_fpr64(ctx, fpu64_T[0], fs);
        gen_load_fpr64(ctx, fpu64_T[2], fd);
6323
        gen_movcf_d((ft >> 2) & 0x7, ft & 0x1);
T
ths 已提交
6324
        gen_store_fpr64(ctx, fpu64_T[2], fd);
6325
        opn = "movcf.d";
6326
        break;
6327
    case FOP(18, 17):
6328
        gen_load_gpr(cpu_T[0], ft);
T
ths 已提交
6329 6330
        gen_load_fpr64(ctx, fpu64_T[0], fs);
        gen_load_fpr64(ctx, fpu64_T[2], fd);
6331 6332 6333 6334 6335 6336 6337
        {
            int l1 = gen_new_label();

            tcg_gen_brcondi_tl(TCG_COND_NE, cpu_T[0], 0, l1);
            tcg_gen_mov_i64(fpu64_T[2], fpu64_T[0]);
            gen_set_label(l1);
        }
T
ths 已提交
6338
        gen_store_fpr64(ctx, fpu64_T[2], fd);
6339 6340 6341
        opn = "movz.d";
        break;
    case FOP(19, 17):
6342
        gen_load_gpr(cpu_T[0], ft);
T
ths 已提交
6343 6344
        gen_load_fpr64(ctx, fpu64_T[0], fs);
        gen_load_fpr64(ctx, fpu64_T[2], fd);
6345 6346 6347 6348 6349 6350 6351
        {
            int l1 = gen_new_label();

            tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_T[0], 0, l1);
            tcg_gen_mov_i64(fpu64_T[2], fpu64_T[0]);
            gen_set_label(l1);
        }
T
ths 已提交
6352
        gen_store_fpr64(ctx, fpu64_T[2], fd);
6353
        opn = "movn.d";
B
bellard 已提交
6354
        break;
T
ths 已提交
6355
    case FOP(21, 17):
6356
        check_cp1_64bitmode(ctx);
T
ths 已提交
6357
        gen_load_fpr64(ctx, fpu64_T[0], fs);
6358
        tcg_gen_helper_0_0(do_float_recip_d);
T
ths 已提交
6359
        gen_store_fpr64(ctx, fpu64_T[2], fd);
T
ths 已提交
6360 6361 6362
        opn = "recip.d";
        break;
    case FOP(22, 17):
6363
        check_cp1_64bitmode(ctx);
T
ths 已提交
6364
        gen_load_fpr64(ctx, fpu64_T[0], fs);
6365
        tcg_gen_helper_0_0(do_float_rsqrt_d);
T
ths 已提交
6366
        gen_store_fpr64(ctx, fpu64_T[2], fd);
T
ths 已提交
6367 6368 6369
        opn = "rsqrt.d";
        break;
    case FOP(28, 17):
6370
        check_cp1_64bitmode(ctx);
T
ths 已提交
6371 6372
        gen_load_fpr64(ctx, fpu64_T[0], fs);
        gen_load_fpr64(ctx, fpu64_T[2], ft);
6373
        tcg_gen_helper_0_0(do_float_recip2_d);
T
ths 已提交
6374
        gen_store_fpr64(ctx, fpu64_T[2], fd);
T
ths 已提交
6375 6376 6377
        opn = "recip2.d";
        break;
    case FOP(29, 17):
6378
        check_cp1_64bitmode(ctx);
T
ths 已提交
6379
        gen_load_fpr64(ctx, fpu64_T[0], fs);
6380
        tcg_gen_helper_0_0(do_float_recip1_d);
T
ths 已提交
6381
        gen_store_fpr64(ctx, fpu64_T[2], fd);
T
ths 已提交
6382 6383 6384
        opn = "recip1.d";
        break;
    case FOP(30, 17):
6385
        check_cp1_64bitmode(ctx);
T
ths 已提交
6386
        gen_load_fpr64(ctx, fpu64_T[0], fs);
6387
        tcg_gen_helper_0_0(do_float_rsqrt1_d);
T
ths 已提交
6388
        gen_store_fpr64(ctx, fpu64_T[2], fd);
T
ths 已提交
6389 6390 6391
        opn = "rsqrt1.d";
        break;
    case FOP(31, 17):
6392
        check_cp1_64bitmode(ctx);
T
ths 已提交
6393 6394
        gen_load_fpr64(ctx, fpu64_T[0], fs);
        gen_load_fpr64(ctx, fpu64_T[2], ft);
6395
        tcg_gen_helper_0_0(do_float_rsqrt2_d);
T
ths 已提交
6396
        gen_store_fpr64(ctx, fpu64_T[2], fd);
T
ths 已提交
6397 6398
        opn = "rsqrt2.d";
        break;
B
bellard 已提交
6399 6400 6401 6402 6403 6404 6405 6406 6407 6408 6409 6410 6411 6412 6413 6414
    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 已提交
6415 6416
        gen_load_fpr64(ctx, fpu64_T[0], fs);
        gen_load_fpr64(ctx, fpu64_T[1], ft);
6417
        if (ctx->opcode & (1 << 6)) {
6418 6419
            check_cop1x(ctx);
            check_cp1_registers(ctx, fs | ft);
6420 6421 6422
            gen_cmpabs_d(func-48, cc);
            opn = condnames_abs[func-48];
        } else {
6423
            check_cp1_registers(ctx, fs | ft);
6424 6425 6426
            gen_cmp_d(func-48, cc);
            opn = condnames[func-48];
        }
B
bellard 已提交
6427
        break;
6428
    case FOP(32, 17):
6429
        check_cp1_registers(ctx, fs);
T
ths 已提交
6430
        gen_load_fpr64(ctx, fpu64_T[0], fs);
6431
        tcg_gen_helper_0_0(do_float_cvts_d);
T
ths 已提交
6432
        gen_store_fpr32(fpu32_T[2], fd);
6433 6434 6435
        opn = "cvt.s.d";
        break;
    case FOP(36, 17):
6436
        check_cp1_registers(ctx, fs);
T
ths 已提交
6437
        gen_load_fpr64(ctx, fpu64_T[0], fs);
6438
        tcg_gen_helper_0_0(do_float_cvtw_d);
T
ths 已提交
6439
        gen_store_fpr32(fpu32_T[2], fd);
6440 6441 6442
        opn = "cvt.w.d";
        break;
    case FOP(37, 17):
6443
        check_cp1_64bitmode(ctx);
T
ths 已提交
6444
        gen_load_fpr64(ctx, fpu64_T[0], fs);
6445
        tcg_gen_helper_0_0(do_float_cvtl_d);
T
ths 已提交
6446
        gen_store_fpr64(ctx, fpu64_T[2], fd);
6447 6448 6449
        opn = "cvt.l.d";
        break;
    case FOP(32, 20):
T
ths 已提交
6450
        gen_load_fpr32(fpu32_T[0], fs);
6451
        tcg_gen_helper_0_0(do_float_cvts_w);
T
ths 已提交
6452
        gen_store_fpr32(fpu32_T[2], fd);
6453
        opn = "cvt.s.w";
B
bellard 已提交
6454
        break;
6455
    case FOP(33, 20):
6456
        check_cp1_registers(ctx, fd);
T
ths 已提交
6457
        gen_load_fpr32(fpu32_T[0], fs);
6458
        tcg_gen_helper_0_0(do_float_cvtd_w);
T
ths 已提交
6459
        gen_store_fpr64(ctx, fpu64_T[2], fd);
6460 6461 6462
        opn = "cvt.d.w";
        break;
    case FOP(32, 21):
6463
        check_cp1_64bitmode(ctx);
T
ths 已提交
6464
        gen_load_fpr64(ctx, fpu64_T[0], fs);
6465
        tcg_gen_helper_0_0(do_float_cvts_l);
T
ths 已提交
6466
        gen_store_fpr32(fpu32_T[2], fd);
6467 6468 6469
        opn = "cvt.s.l";
        break;
    case FOP(33, 21):
6470
        check_cp1_64bitmode(ctx);
T
ths 已提交
6471
        gen_load_fpr64(ctx, fpu64_T[0], fs);
6472
        tcg_gen_helper_0_0(do_float_cvtd_l);
T
ths 已提交
6473
        gen_store_fpr64(ctx, fpu64_T[2], fd);
6474 6475 6476
        opn = "cvt.d.l";
        break;
    case FOP(38, 20):
6477
        check_cp1_64bitmode(ctx);
T
ths 已提交
6478 6479
        gen_load_fpr32(fpu32_T[0], fs);
        gen_load_fpr32h(fpu32h_T[0], fs);
6480
        tcg_gen_helper_0_0(do_float_cvtps_pw);
T
ths 已提交
6481 6482
        gen_store_fpr32(fpu32_T[2], fd);
        gen_store_fpr32h(fpu32h_T[2], fd);
6483 6484 6485
        opn = "cvt.ps.pw";
        break;
    case FOP(0, 22):
6486
        check_cp1_64bitmode(ctx);
T
ths 已提交
6487 6488 6489 6490
        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);
6491
        tcg_gen_helper_0_0(do_float_add_ps);
T
ths 已提交
6492 6493
        gen_store_fpr32(fpu32_T[2], fd);
        gen_store_fpr32h(fpu32h_T[2], fd);
6494
        opn = "add.ps";
B
bellard 已提交
6495
        break;
6496
    case FOP(1, 22):
6497
        check_cp1_64bitmode(ctx);
T
ths 已提交
6498 6499 6500 6501
        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);
6502
        tcg_gen_helper_0_0(do_float_sub_ps);
T
ths 已提交
6503 6504
        gen_store_fpr32(fpu32_T[2], fd);
        gen_store_fpr32h(fpu32h_T[2], fd);
6505
        opn = "sub.ps";
B
bellard 已提交
6506
        break;
6507
    case FOP(2, 22):
6508
        check_cp1_64bitmode(ctx);
T
ths 已提交
6509 6510 6511 6512
        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);
6513
        tcg_gen_helper_0_0(do_float_mul_ps);
T
ths 已提交
6514 6515
        gen_store_fpr32(fpu32_T[2], fd);
        gen_store_fpr32h(fpu32h_T[2], fd);
6516
        opn = "mul.ps";
B
bellard 已提交
6517
        break;
6518
    case FOP(5, 22):
6519
        check_cp1_64bitmode(ctx);
T
ths 已提交
6520 6521
        gen_load_fpr32(fpu32_T[0], fs);
        gen_load_fpr32h(fpu32h_T[0], fs);
6522
        tcg_gen_helper_0_0(do_float_abs_ps);
T
ths 已提交
6523 6524
        gen_store_fpr32(fpu32_T[2], fd);
        gen_store_fpr32h(fpu32h_T[2], fd);
6525
        opn = "abs.ps";
B
bellard 已提交
6526
        break;
6527
    case FOP(6, 22):
6528
        check_cp1_64bitmode(ctx);
T
ths 已提交
6529 6530
        gen_load_fpr32(fpu32_T[0], fs);
        gen_load_fpr32h(fpu32h_T[0], fs);
T
ths 已提交
6531 6532
        gen_store_fpr32(fpu32_T[0], fd);
        gen_store_fpr32h(fpu32h_T[0], fd);
6533
        opn = "mov.ps";
B
bellard 已提交
6534
        break;
6535
    case FOP(7, 22):
6536
        check_cp1_64bitmode(ctx);
T
ths 已提交
6537 6538
        gen_load_fpr32(fpu32_T[0], fs);
        gen_load_fpr32h(fpu32h_T[0], fs);
6539
        tcg_gen_helper_0_0(do_float_chs_ps);
T
ths 已提交
6540 6541
        gen_store_fpr32(fpu32_T[2], fd);
        gen_store_fpr32h(fpu32h_T[2], fd);
6542
        opn = "neg.ps";
B
bellard 已提交
6543
        break;
6544
    case FOP(17, 22):
6545
        check_cp1_64bitmode(ctx);
T
ths 已提交
6546 6547 6548 6549
        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);
6550
        gen_movcf_ps((ft >> 2) & 0x7, ft & 0x1);
T
ths 已提交
6551 6552
        gen_store_fpr32(fpu32_T[2], fd);
        gen_store_fpr32h(fpu32h_T[2], fd);
6553
        opn = "movcf.ps";
B
bellard 已提交
6554
        break;
6555
    case FOP(18, 22):
6556
        check_cp1_64bitmode(ctx);
6557
        gen_load_gpr(cpu_T[0], ft);
T
ths 已提交
6558 6559 6560 6561
        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);
6562 6563 6564 6565 6566 6567 6568 6569
        {
            int l1 = gen_new_label();

            tcg_gen_brcondi_tl(TCG_COND_NE, cpu_T[0], 0, l1);
            tcg_gen_mov_i32(fpu32_T[2], fpu32_T[0]);
            tcg_gen_mov_i32(fpu32h_T[2], fpu32h_T[0]);
            gen_set_label(l1);
        }
T
ths 已提交
6570 6571
        gen_store_fpr32(fpu32_T[2], fd);
        gen_store_fpr32h(fpu32h_T[2], fd);
6572
        opn = "movz.ps";
B
bellard 已提交
6573
        break;
6574
    case FOP(19, 22):
6575
        check_cp1_64bitmode(ctx);
6576
        gen_load_gpr(cpu_T[0], ft);
T
ths 已提交
6577 6578 6579 6580
        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);
6581 6582 6583 6584 6585 6586 6587 6588
        {
            int l1 = gen_new_label();

            tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_T[0], 0, l1);
            tcg_gen_mov_i32(fpu32_T[2], fpu32_T[0]);
            tcg_gen_mov_i32(fpu32h_T[2], fpu32h_T[0]);
            gen_set_label(l1);
        }
T
ths 已提交
6589 6590
        gen_store_fpr32(fpu32_T[2], fd);
        gen_store_fpr32h(fpu32h_T[2], fd);
6591
        opn = "movn.ps";
B
bellard 已提交
6592
        break;
6593
    case FOP(24, 22):
6594
        check_cp1_64bitmode(ctx);
T
ths 已提交
6595 6596 6597 6598
        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);
6599
        tcg_gen_helper_0_0(do_float_addr_ps);
T
ths 已提交
6600 6601
        gen_store_fpr32(fpu32_T[2], fd);
        gen_store_fpr32h(fpu32h_T[2], fd);
6602 6603
        opn = "addr.ps";
        break;
T
ths 已提交
6604
    case FOP(26, 22):
6605
        check_cp1_64bitmode(ctx);
T
ths 已提交
6606 6607 6608 6609
        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);
6610
        tcg_gen_helper_0_0(do_float_mulr_ps);
T
ths 已提交
6611 6612
        gen_store_fpr32(fpu32_T[2], fd);
        gen_store_fpr32h(fpu32h_T[2], fd);
T
ths 已提交
6613 6614 6615
        opn = "mulr.ps";
        break;
    case FOP(28, 22):
6616
        check_cp1_64bitmode(ctx);
T
ths 已提交
6617 6618 6619 6620
        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);
6621
        tcg_gen_helper_0_0(do_float_recip2_ps);
T
ths 已提交
6622 6623
        gen_store_fpr32(fpu32_T[2], fd);
        gen_store_fpr32h(fpu32h_T[2], fd);
T
ths 已提交
6624 6625 6626
        opn = "recip2.ps";
        break;
    case FOP(29, 22):
6627
        check_cp1_64bitmode(ctx);
T
ths 已提交
6628 6629
        gen_load_fpr32(fpu32_T[0], fs);
        gen_load_fpr32h(fpu32h_T[0], fs);
6630
        tcg_gen_helper_0_0(do_float_recip1_ps);
T
ths 已提交
6631 6632
        gen_store_fpr32(fpu32_T[2], fd);
        gen_store_fpr32h(fpu32h_T[2], fd);
T
ths 已提交
6633 6634 6635
        opn = "recip1.ps";
        break;
    case FOP(30, 22):
6636
        check_cp1_64bitmode(ctx);
T
ths 已提交
6637 6638
        gen_load_fpr32(fpu32_T[0], fs);
        gen_load_fpr32h(fpu32h_T[0], fs);
6639
        tcg_gen_helper_0_0(do_float_rsqrt1_ps);
T
ths 已提交
6640 6641
        gen_store_fpr32(fpu32_T[2], fd);
        gen_store_fpr32h(fpu32h_T[2], fd);
T
ths 已提交
6642 6643 6644
        opn = "rsqrt1.ps";
        break;
    case FOP(31, 22):
6645
        check_cp1_64bitmode(ctx);
T
ths 已提交
6646 6647 6648 6649
        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);
6650
        tcg_gen_helper_0_0(do_float_rsqrt2_ps);
T
ths 已提交
6651 6652
        gen_store_fpr32(fpu32_T[2], fd);
        gen_store_fpr32h(fpu32h_T[2], fd);
T
ths 已提交
6653 6654
        opn = "rsqrt2.ps";
        break;
6655
    case FOP(32, 22):
6656
        check_cp1_64bitmode(ctx);
T
ths 已提交
6657
        gen_load_fpr32h(fpu32h_T[0], fs);
6658
        tcg_gen_helper_0_0(do_float_cvts_pu);
T
ths 已提交
6659
        gen_store_fpr32(fpu32_T[2], fd);
6660
        opn = "cvt.s.pu";
6661
        break;
6662
    case FOP(36, 22):
6663
        check_cp1_64bitmode(ctx);
T
ths 已提交
6664 6665
        gen_load_fpr32(fpu32_T[0], fs);
        gen_load_fpr32h(fpu32h_T[0], fs);
6666
        tcg_gen_helper_0_0(do_float_cvtpw_ps);
T
ths 已提交
6667 6668
        gen_store_fpr32(fpu32_T[2], fd);
        gen_store_fpr32h(fpu32h_T[2], fd);
6669
        opn = "cvt.pw.ps";
B
bellard 已提交
6670
        break;
6671
    case FOP(40, 22):
6672
        check_cp1_64bitmode(ctx);
T
ths 已提交
6673
        gen_load_fpr32(fpu32_T[0], fs);
6674
        tcg_gen_helper_0_0(do_float_cvts_pl);
T
ths 已提交
6675
        gen_store_fpr32(fpu32_T[2], fd);
6676
        opn = "cvt.s.pl";
B
bellard 已提交
6677
        break;
6678
    case FOP(44, 22):
6679
        check_cp1_64bitmode(ctx);
T
ths 已提交
6680 6681
        gen_load_fpr32(fpu32_T[0], fs);
        gen_load_fpr32(fpu32_T[1], ft);
6682 6683
        gen_store_fpr32h(fpu32_T[0], fd);
        gen_store_fpr32(fpu32_T[1], fd);
6684
        opn = "pll.ps";
B
bellard 已提交
6685
        break;
6686
    case FOP(45, 22):
6687
        check_cp1_64bitmode(ctx);
T
ths 已提交
6688 6689
        gen_load_fpr32(fpu32_T[0], fs);
        gen_load_fpr32h(fpu32h_T[1], ft);
6690 6691
        gen_store_fpr32(fpu32h_T[1], fd);
        gen_store_fpr32h(fpu32_T[0], fd);
6692 6693 6694
        opn = "plu.ps";
        break;
    case FOP(46, 22):
6695
        check_cp1_64bitmode(ctx);
T
ths 已提交
6696 6697
        gen_load_fpr32h(fpu32h_T[0], fs);
        gen_load_fpr32(fpu32_T[1], ft);
6698 6699
        gen_store_fpr32(fpu32_T[1], fd);
        gen_store_fpr32h(fpu32h_T[0], fd);
6700 6701 6702
        opn = "pul.ps";
        break;
    case FOP(47, 22):
6703
        check_cp1_64bitmode(ctx);
T
ths 已提交
6704 6705
        gen_load_fpr32h(fpu32h_T[0], fs);
        gen_load_fpr32h(fpu32h_T[1], ft);
6706 6707
        gen_store_fpr32(fpu32h_T[1], fd);
        gen_store_fpr32h(fpu32h_T[0], fd);
6708 6709 6710 6711 6712 6713 6714 6715 6716 6717 6718 6719 6720 6721 6722 6723 6724 6725
        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):
6726
        check_cp1_64bitmode(ctx);
T
ths 已提交
6727 6728 6729 6730
        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);
6731 6732 6733 6734 6735 6736 6737
        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 已提交
6738
        break;
6739
    default:
6740
        MIPS_INVAL(opn);
6741
        generate_exception (ctx, EXCP_RI);
B
bellard 已提交
6742 6743
        return;
    }
6744 6745
    switch (optype) {
    case BINOP:
B
bellard 已提交
6746
        MIPS_DEBUG("%s %s, %s, %s", opn, fregnames[fd], fregnames[fs], fregnames[ft]);
6747 6748 6749 6750 6751
        break;
    case CMPOP:
        MIPS_DEBUG("%s %s,%s", opn, fregnames[fs], fregnames[ft]);
        break;
    default:
B
bellard 已提交
6752
        MIPS_DEBUG("%s %s,%s", opn, fregnames[fd], fregnames[fs]);
6753 6754
        break;
    }
B
bellard 已提交
6755
}
B
bellard 已提交
6756

6757
/* Coprocessor 3 (FPU) */
6758 6759
static void gen_flt3_ldst (DisasContext *ctx, uint32_t opc,
                           int fd, int fs, int base, int index)
6760
{
6761
    const char *opn = "extended float load/store";
T
ths 已提交
6762
    int store = 0;
6763

T
ths 已提交
6764
    if (base == 0) {
6765
        gen_load_gpr(cpu_T[0], index);
T
ths 已提交
6766
    } else if (index == 0) {
6767
        gen_load_gpr(cpu_T[0], base);
T
ths 已提交
6768
    } else {
6769 6770
        gen_load_gpr(cpu_T[0], base);
        gen_load_gpr(cpu_T[1], index);
T
ths 已提交
6771 6772
        gen_op_addr_add();
    }
6773
    /* Don't do NOP if destination is zero: we must perform the actual
6774
       memory access. */
6775 6776
    switch (opc) {
    case OPC_LWXC1:
6777
        check_cop1x(ctx);
T
ths 已提交
6778 6779
        tcg_gen_qemu_ld32s(fpu32_T[0], cpu_T[0], ctx->mem_idx);
        gen_store_fpr32(fpu32_T[0], fd);
6780 6781 6782
        opn = "lwxc1";
        break;
    case OPC_LDXC1:
6783 6784
        check_cop1x(ctx);
        check_cp1_registers(ctx, fd);
T
ths 已提交
6785 6786
        tcg_gen_qemu_ld64(fpu64_T[0], cpu_T[0], ctx->mem_idx);
        gen_store_fpr64(ctx, fpu64_T[0], fd);
6787 6788 6789
        opn = "ldxc1";
        break;
    case OPC_LUXC1:
6790
        check_cp1_64bitmode(ctx);
T
ths 已提交
6791 6792
        tcg_gen_andi_tl(cpu_T[0], cpu_T[0], ~0x7);
        tcg_gen_qemu_ld64(fpu64_T[0], cpu_T[0], ctx->mem_idx);
T
ths 已提交
6793
        gen_store_fpr64(ctx, fpu64_T[0], fd);
6794 6795 6796
        opn = "luxc1";
        break;
    case OPC_SWXC1:
6797
        check_cop1x(ctx);
T
ths 已提交
6798 6799
        gen_load_fpr32(fpu32_T[0], fs);
        tcg_gen_qemu_st32(fpu32_T[0], cpu_T[0], ctx->mem_idx);
6800
        opn = "swxc1";
T
ths 已提交
6801
        store = 1;
6802 6803
        break;
    case OPC_SDXC1:
6804 6805
        check_cop1x(ctx);
        check_cp1_registers(ctx, fs);
T
ths 已提交
6806 6807
        gen_load_fpr64(ctx, fpu64_T[0], fs);
        tcg_gen_qemu_st64(fpu64_T[0], cpu_T[0], ctx->mem_idx);
6808
        opn = "sdxc1";
T
ths 已提交
6809
        store = 1;
6810 6811
        break;
    case OPC_SUXC1:
6812
        check_cp1_64bitmode(ctx);
T
ths 已提交
6813
        gen_load_fpr64(ctx, fpu64_T[0], fs);
T
ths 已提交
6814 6815
        tcg_gen_andi_tl(cpu_T[0], cpu_T[0], ~0x7);
        tcg_gen_qemu_st64(fpu64_T[0], cpu_T[0], ctx->mem_idx);
6816
        opn = "suxc1";
T
ths 已提交
6817
        store = 1;
6818 6819
        break;
    default:
6820
        MIPS_INVAL(opn);
6821 6822 6823
        generate_exception(ctx, EXCP_RI);
        return;
    }
T
ths 已提交
6824 6825
    MIPS_DEBUG("%s %s, %s(%s)", opn, fregnames[store ? fs : fd],
               regnames[index], regnames[base]);
6826 6827
}

6828 6829
static void gen_flt3_arith (DisasContext *ctx, uint32_t opc,
                            int fd, int fr, int fs, int ft)
6830
{
6831
    const char *opn = "flt3_arith";
6832 6833 6834

    switch (opc) {
    case OPC_ALNV_PS:
6835
        check_cp1_64bitmode(ctx);
6836
        gen_load_gpr(cpu_T[0], fr);
6837 6838 6839 6840 6841 6842 6843 6844 6845 6846 6847 6848 6849 6850 6851 6852 6853 6854 6855 6856 6857 6858 6859 6860 6861 6862
        tcg_gen_andi_tl(cpu_T[0], cpu_T[0], 0x7);
        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);
        {
            int l1 = gen_new_label();
            int l2 = gen_new_label();

            tcg_gen_brcondi_tl(TCG_COND_NE, cpu_T[0], 0, l1);
            tcg_gen_mov_i32(fpu32_T[2], fpu32_T[0]);
            tcg_gen_mov_i32(fpu32h_T[2], fpu32h_T[0]);
            tcg_gen_br(l2);
            gen_set_label(l1);
            tcg_gen_brcondi_tl(TCG_COND_NE, cpu_T[0], 4, l2);
#ifdef TARGET_WORDS_BIGENDIAN
            tcg_gen_mov_i32(fpu32h_T[2], fpu32_T[0]);
            tcg_gen_mov_i32(fpu32_T[2], fpu32h_T[1]);
#else
            tcg_gen_mov_i32(fpu32h_T[2], fpu32_T[1]);
            tcg_gen_mov_i32(fpu32_T[2], fpu32h_T[0]);
#endif
            gen_set_label(l2);
        }
        gen_store_fpr32(fpu32_T[2], fd);
        gen_store_fpr32h(fpu32h_T[2], fd);
6863 6864 6865
        opn = "alnv.ps";
        break;
    case OPC_MADD_S:
6866
        check_cop1x(ctx);
T
ths 已提交
6867 6868 6869
        gen_load_fpr32(fpu32_T[0], fs);
        gen_load_fpr32(fpu32_T[1], ft);
        gen_load_fpr32(fpu32_T[2], fr);
6870
        tcg_gen_helper_0_0(do_float_muladd_s);
T
ths 已提交
6871
        gen_store_fpr32(fpu32_T[2], fd);
6872 6873 6874
        opn = "madd.s";
        break;
    case OPC_MADD_D:
6875 6876
        check_cop1x(ctx);
        check_cp1_registers(ctx, fd | fs | ft | fr);
T
ths 已提交
6877 6878 6879
        gen_load_fpr64(ctx, fpu64_T[0], fs);
        gen_load_fpr64(ctx, fpu64_T[1], ft);
        gen_load_fpr64(ctx, fpu64_T[2], fr);
6880
        tcg_gen_helper_0_0(do_float_muladd_d);
T
ths 已提交
6881
        gen_store_fpr64(ctx, fpu64_T[2], fd);
6882 6883 6884
        opn = "madd.d";
        break;
    case OPC_MADD_PS:
6885
        check_cp1_64bitmode(ctx);
T
ths 已提交
6886 6887 6888 6889 6890 6891
        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);
6892
        tcg_gen_helper_0_0(do_float_muladd_ps);
T
ths 已提交
6893 6894
        gen_store_fpr32(fpu32_T[2], fd);
        gen_store_fpr32h(fpu32h_T[2], fd);
6895 6896 6897
        opn = "madd.ps";
        break;
    case OPC_MSUB_S:
6898
        check_cop1x(ctx);
T
ths 已提交
6899 6900 6901
        gen_load_fpr32(fpu32_T[0], fs);
        gen_load_fpr32(fpu32_T[1], ft);
        gen_load_fpr32(fpu32_T[2], fr);
6902
        tcg_gen_helper_0_0(do_float_mulsub_s);
T
ths 已提交
6903
        gen_store_fpr32(fpu32_T[2], fd);
6904 6905 6906
        opn = "msub.s";
        break;
    case OPC_MSUB_D:
6907 6908
        check_cop1x(ctx);
        check_cp1_registers(ctx, fd | fs | ft | fr);
T
ths 已提交
6909 6910 6911
        gen_load_fpr64(ctx, fpu64_T[0], fs);
        gen_load_fpr64(ctx, fpu64_T[1], ft);
        gen_load_fpr64(ctx, fpu64_T[2], fr);
6912
        tcg_gen_helper_0_0(do_float_mulsub_d);
T
ths 已提交
6913
        gen_store_fpr64(ctx, fpu64_T[2], fd);
6914 6915 6916
        opn = "msub.d";
        break;
    case OPC_MSUB_PS:
6917
        check_cp1_64bitmode(ctx);
T
ths 已提交
6918 6919 6920 6921 6922 6923
        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);
6924
        tcg_gen_helper_0_0(do_float_mulsub_ps);
T
ths 已提交
6925 6926
        gen_store_fpr32(fpu32_T[2], fd);
        gen_store_fpr32h(fpu32h_T[2], fd);
6927 6928 6929
        opn = "msub.ps";
        break;
    case OPC_NMADD_S:
6930
        check_cop1x(ctx);
T
ths 已提交
6931 6932 6933
        gen_load_fpr32(fpu32_T[0], fs);
        gen_load_fpr32(fpu32_T[1], ft);
        gen_load_fpr32(fpu32_T[2], fr);
6934
        tcg_gen_helper_0_0(do_float_nmuladd_s);
T
ths 已提交
6935
        gen_store_fpr32(fpu32_T[2], fd);
6936 6937 6938
        opn = "nmadd.s";
        break;
    case OPC_NMADD_D:
6939 6940
        check_cop1x(ctx);
        check_cp1_registers(ctx, fd | fs | ft | fr);
T
ths 已提交
6941 6942 6943
        gen_load_fpr64(ctx, fpu64_T[0], fs);
        gen_load_fpr64(ctx, fpu64_T[1], ft);
        gen_load_fpr64(ctx, fpu64_T[2], fr);
6944
        tcg_gen_helper_0_0(do_float_nmuladd_d);
T
ths 已提交
6945
        gen_store_fpr64(ctx, fpu64_T[2], fd);
6946 6947 6948
        opn = "nmadd.d";
        break;
    case OPC_NMADD_PS:
6949
        check_cp1_64bitmode(ctx);
T
ths 已提交
6950 6951 6952 6953 6954 6955
        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);
6956
        tcg_gen_helper_0_0(do_float_nmuladd_ps);
T
ths 已提交
6957 6958
        gen_store_fpr32(fpu32_T[2], fd);
        gen_store_fpr32h(fpu32h_T[2], fd);
6959 6960 6961
        opn = "nmadd.ps";
        break;
    case OPC_NMSUB_S:
6962
        check_cop1x(ctx);
T
ths 已提交
6963 6964 6965
        gen_load_fpr32(fpu32_T[0], fs);
        gen_load_fpr32(fpu32_T[1], ft);
        gen_load_fpr32(fpu32_T[2], fr);
6966
        tcg_gen_helper_0_0(do_float_nmulsub_s);
T
ths 已提交
6967
        gen_store_fpr32(fpu32_T[2], fd);
6968 6969 6970
        opn = "nmsub.s";
        break;
    case OPC_NMSUB_D:
6971 6972
        check_cop1x(ctx);
        check_cp1_registers(ctx, fd | fs | ft | fr);
T
ths 已提交
6973 6974 6975
        gen_load_fpr64(ctx, fpu64_T[0], fs);
        gen_load_fpr64(ctx, fpu64_T[1], ft);
        gen_load_fpr64(ctx, fpu64_T[2], fr);
6976
        tcg_gen_helper_0_0(do_float_nmulsub_d);
T
ths 已提交
6977
        gen_store_fpr64(ctx, fpu64_T[2], fd);
6978 6979 6980
        opn = "nmsub.d";
        break;
    case OPC_NMSUB_PS:
6981
        check_cp1_64bitmode(ctx);
T
ths 已提交
6982 6983 6984 6985 6986 6987
        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);
6988
        tcg_gen_helper_0_0(do_float_nmulsub_ps);
T
ths 已提交
6989 6990
        gen_store_fpr32(fpu32_T[2], fd);
        gen_store_fpr32h(fpu32h_T[2], fd);
6991 6992
        opn = "nmsub.ps";
        break;
6993 6994
    default:
        MIPS_INVAL(opn);
6995 6996 6997 6998 6999
        generate_exception (ctx, EXCP_RI);
        return;
    }
    MIPS_DEBUG("%s %s, %s, %s, %s", opn, fregnames[fd], fregnames[fr],
               fregnames[fs], fregnames[ft]);
7000 7001 7002
}

/* ISA extensions (ASEs) */
B
bellard 已提交
7003 7004 7005
/* MIPS16 extension to MIPS32 */
/* SmartMIPS extension to MIPS32 */

7006
#if defined(TARGET_MIPS64)
B
bellard 已提交
7007 7008 7009 7010 7011

/* MDMX extension to MIPS64 */

#endif

7012
static void decode_opc (CPUState *env, DisasContext *ctx)
B
bellard 已提交
7013 7014 7015
{
    int32_t offset;
    int rs, rt, rd, sa;
7016
    uint32_t op, op1, op2;
B
bellard 已提交
7017 7018
    int16_t imm;

7019 7020
    /* make sure instructions are on a word boundary */
    if (ctx->pc & 0x3) {
7021
        env->CP0_BadVAddr = ctx->pc;
7022 7023 7024 7025
        generate_exception(ctx, EXCP_AdEL);
        return;
    }

7026
    /* Handle blikely not taken case */
B
bellard 已提交
7027
    if ((ctx->hflags & MIPS_HFLAG_BMASK) == MIPS_HFLAG_BL) {
T
ths 已提交
7028
        TCGv r_tmp = tcg_temp_local_new(TCG_TYPE_TL);
7029 7030
        int l1 = gen_new_label();

T
ths 已提交
7031
        MIPS_DEBUG("blikely condition (" TARGET_FMT_lx ")", ctx->pc + 4);
7032
        tcg_gen_ld_tl(r_tmp, cpu_env, offsetof(CPUState, bcond));
P
pbrook 已提交
7033
        tcg_gen_brcondi_tl(TCG_COND_NE, r_tmp, 0, l1);
T
ths 已提交
7034
        tcg_temp_free(r_tmp);
T
ths 已提交
7035 7036 7037 7038 7039 7040 7041
        {
            TCGv r_tmp2 = tcg_temp_new(TCG_TYPE_I32);

            tcg_gen_movi_i32(r_tmp2, ctx->hflags & ~MIPS_HFLAG_BMASK);
            tcg_gen_st_i32(r_tmp2, cpu_env, offsetof(CPUState, hflags));
            tcg_temp_free(r_tmp2);
        }
7042 7043
        gen_goto_tb(ctx, 1, ctx->pc + 4);
        gen_set_label(l1);
B
bellard 已提交
7044
    }
7045 7046 7047 7048 7049
    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 已提交
7050 7051
    imm = (int16_t)ctx->opcode;
    switch (op) {
7052 7053
    case OPC_SPECIAL:
        op1 = MASK_SPECIAL(ctx->opcode);
B
bellard 已提交
7054
        switch (op1) {
7055 7056
        case OPC_SLL:          /* Arithmetic with immediate */
        case OPC_SRL ... OPC_SRA:
7057
            gen_arith_imm(env, ctx, op1, rd, rt, sa);
7058
            break;
7059 7060
        case OPC_MOVZ ... OPC_MOVN:
            check_insn(env, ctx, ISA_MIPS4 | ISA_MIPS32);
7061 7062 7063 7064
        case OPC_SLLV:         /* Arithmetic */
        case OPC_SRLV ... OPC_SRAV:
        case OPC_ADD ... OPC_NOR:
        case OPC_SLT ... OPC_SLTU:
7065
            gen_arith(env, ctx, op1, rd, rs, rt);
7066 7067
            break;
        case OPC_MULT ... OPC_DIVU:
7068 7069 7070 7071 7072 7073
            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);
7074 7075 7076
            break;
        case OPC_JR ... OPC_JALR:
            gen_compute_branch(ctx, op1, rs, rd, sa);
B
bellard 已提交
7077
            return;
7078 7079 7080
        case OPC_TGE ... OPC_TEQ: /* Traps */
        case OPC_TNE:
            gen_trap(ctx, op1, rs, rt, -1);
B
bellard 已提交
7081
            break;
7082 7083 7084
        case OPC_MFHI:          /* Move from HI/LO */
        case OPC_MFLO:
            gen_HILO(ctx, op1, rd);
B
bellard 已提交
7085
            break;
7086 7087 7088
        case OPC_MTHI:
        case OPC_MTLO:          /* Move to HI/LO */
            gen_HILO(ctx, op1, rs);
B
bellard 已提交
7089
            break;
7090 7091 7092 7093 7094
        case OPC_PMON:          /* Pmon entry point, also R4010 selsl */
#ifdef MIPS_STRICT_STANDARD
            MIPS_INVAL("PMON / selsl");
            generate_exception(ctx, EXCP_RI);
#else
T
ths 已提交
7095
            tcg_gen_helper_0_1i(do_pmon, sa);
7096
#endif
7097 7098
            break;
        case OPC_SYSCALL:
B
bellard 已提交
7099 7100
            generate_exception(ctx, EXCP_SYSCALL);
            break;
7101
        case OPC_BREAK:
B
bellard 已提交
7102 7103
            generate_exception(ctx, EXCP_BREAK);
            break;
7104 7105 7106 7107 7108
        case OPC_SPIM:
#ifdef MIPS_STRICT_STANDARD
            MIPS_INVAL("SPIM");
            generate_exception(ctx, EXCP_RI);
#else
7109 7110 7111
           /* Implemented as RI exception for now. */
            MIPS_INVAL("spim (unofficial)");
            generate_exception(ctx, EXCP_RI);
7112
#endif
B
bellard 已提交
7113
            break;
7114
        case OPC_SYNC:
7115
            /* Treat as NOP. */
B
bellard 已提交
7116
            break;
B
bellard 已提交
7117

7118
        case OPC_MOVCI:
7119
            check_insn(env, ctx, ISA_MIPS4 | ISA_MIPS32);
7120
            if (env->CP0_Config1 & (1 << CP0C1_FP)) {
7121
                save_cpu_state(ctx, 1);
7122
                check_cp1_enabled(ctx);
7123 7124 7125
                gen_movci(ctx, rd, rs, (ctx->opcode >> 18) & 0x7,
                          (ctx->opcode >> 16) & 1);
            } else {
7126
                generate_exception_err(ctx, EXCP_CpU, 1);
7127
            }
B
bellard 已提交
7128 7129
            break;

7130
#if defined(TARGET_MIPS64)
7131 7132 7133 7134 7135
       /* MIPS64 specific opcodes */
        case OPC_DSLL:
        case OPC_DSRL ... OPC_DSRA:
        case OPC_DSLL32:
        case OPC_DSRL32 ... OPC_DSRA32:
7136 7137 7138
            check_insn(env, ctx, ISA_MIPS3);
            check_mips_64(ctx);
            gen_arith_imm(env, ctx, op1, rd, rt, sa);
7139 7140 7141 7142
            break;
        case OPC_DSLLV:
        case OPC_DSRLV ... OPC_DSRAV:
        case OPC_DADD ... OPC_DSUBU:
7143 7144 7145
            check_insn(env, ctx, ISA_MIPS3);
            check_mips_64(ctx);
            gen_arith(env, ctx, op1, rd, rs, rt);
7146 7147
            break;
        case OPC_DMULT ... OPC_DDIVU:
7148 7149
            check_insn(env, ctx, ISA_MIPS3);
            check_mips_64(ctx);
7150 7151
            gen_muldiv(ctx, op1, rs, rt);
            break;
B
bellard 已提交
7152 7153 7154 7155 7156 7157 7158
#endif
        default:            /* Invalid */
            MIPS_INVAL("special");
            generate_exception(ctx, EXCP_RI);
            break;
        }
        break;
7159 7160
    case OPC_SPECIAL2:
        op1 = MASK_SPECIAL2(ctx->opcode);
B
bellard 已提交
7161
        switch (op1) {
7162 7163
        case OPC_MADD ... OPC_MADDU: /* Multiply and add/sub */
        case OPC_MSUB ... OPC_MSUBU:
7164
            check_insn(env, ctx, ISA_MIPS32);
7165
            gen_muldiv(ctx, op1, rs, rt);
B
bellard 已提交
7166
            break;
7167
        case OPC_MUL:
7168
            gen_arith(env, ctx, op1, rd, rs, rt);
B
bellard 已提交
7169
            break;
7170
        case OPC_CLZ ... OPC_CLO:
7171
            check_insn(env, ctx, ISA_MIPS32);
7172
            gen_cl(ctx, op1, rd, rs);
B
bellard 已提交
7173
            break;
7174
        case OPC_SDBBP:
B
bellard 已提交
7175 7176 7177
            /* XXX: not clear which exception should be raised
             *      when in debug mode...
             */
7178
            check_insn(env, ctx, ISA_MIPS32);
B
bellard 已提交
7179 7180 7181 7182 7183
            if (!(ctx->hflags & MIPS_HFLAG_DM)) {
                generate_exception(ctx, EXCP_DBp);
            } else {
                generate_exception(ctx, EXCP_DBp);
            }
7184
            /* Treat as NOP. */
B
bellard 已提交
7185
            break;
7186
#if defined(TARGET_MIPS64)
7187
        case OPC_DCLZ ... OPC_DCLO:
7188 7189
            check_insn(env, ctx, ISA_MIPS64);
            check_mips_64(ctx);
7190 7191 7192
            gen_cl(ctx, op1, rd, rs);
            break;
#endif
B
bellard 已提交
7193 7194 7195 7196 7197 7198
        default:            /* Invalid */
            MIPS_INVAL("special2");
            generate_exception(ctx, EXCP_RI);
            break;
        }
        break;
7199
    case OPC_SPECIAL3:
7200 7201 7202 7203 7204 7205 7206 7207 7208 7209 7210 7211 7212 7213 7214 7215 7216 7217 7218 7219 7220 7221 7222 7223 7224 7225 7226
        op1 = MASK_SPECIAL3(ctx->opcode);
        switch (op1) {
        case OPC_EXT:
        case OPC_INS:
            check_insn(env, ctx, ISA_MIPS32R2);
            gen_bitops(ctx, op1, rt, rs, sa, rd);
            break;
        case OPC_BSHFL:
            check_insn(env, ctx, ISA_MIPS32R2);
            op2 = MASK_BSHFL(ctx->opcode);
            switch (op2) {
            case OPC_WSBH:
                gen_load_gpr(cpu_T[1], rt);
                tcg_gen_helper_0_0(do_wsbh);
                break;
            case OPC_SEB:
                gen_load_gpr(cpu_T[1], rt);
                tcg_gen_ext8s_tl(cpu_T[0], cpu_T[1]);
                break;
            case OPC_SEH:
                gen_load_gpr(cpu_T[1], rt);
                tcg_gen_ext16s_tl(cpu_T[0], cpu_T[1]);
                break;
            default:            /* Invalid */
                MIPS_INVAL("bshfl");
                generate_exception(ctx, EXCP_RI);
                break;
7227
            }
7228
            gen_store_gpr(cpu_T[0], rd);
7229
            break;
7230
        case OPC_RDHWR:
7231
            check_insn(env, ctx, ISA_MIPS32R2);
7232 7233
            switch (rd) {
            case 0:
7234
                save_cpu_state(ctx, 1);
7235
                tcg_gen_helper_0_0(do_rdhwr_cpunum);
7236
                break;
7237
            case 1:
7238
                save_cpu_state(ctx, 1);
7239
                tcg_gen_helper_0_0(do_rdhwr_synci_step);
7240
                break;
7241
            case 2:
7242
                save_cpu_state(ctx, 1);
7243
                tcg_gen_helper_0_0(do_rdhwr_cc);
7244
                break;
7245
            case 3:
7246
                save_cpu_state(ctx, 1);
7247
                tcg_gen_helper_0_0(do_rdhwr_ccres);
7248
                break;
7249
            case 29:
7250
#if defined (CONFIG_USER_ONLY)
T
ths 已提交
7251
                tcg_gen_ld_tl(cpu_T[0], cpu_env, offsetof(CPUState, tls_value));
7252
                break;
7253 7254
#else
                /* XXX: Some CPUs implement this in hardware. Not supported yet. */
7255
#endif
7256 7257 7258 7259 7260
            default:            /* Invalid */
                MIPS_INVAL("rdhwr");
                generate_exception(ctx, EXCP_RI);
                break;
            }
7261
            gen_store_gpr(cpu_T[0], rt);
7262
            break;
7263
        case OPC_FORK:
7264
            check_insn(env, ctx, ASE_MT);
7265 7266
            gen_load_gpr(cpu_T[0], rt);
            gen_load_gpr(cpu_T[1], rs);
7267
            tcg_gen_helper_0_0(do_fork);
7268 7269
            break;
        case OPC_YIELD:
7270
            check_insn(env, ctx, ASE_MT);
7271
            gen_load_gpr(cpu_T[0], rs);
7272
            tcg_gen_helper_0_0(do_yield);
7273
            gen_store_gpr(cpu_T[0], rd);
7274
            break;
7275
#if defined(TARGET_MIPS64)
7276 7277
        case OPC_DEXTM ... OPC_DEXT:
        case OPC_DINSM ... OPC_DINS:
7278 7279
            check_insn(env, ctx, ISA_MIPS64R2);
            check_mips_64(ctx);
7280
            gen_bitops(ctx, op1, rt, rs, sa, rd);
7281
            break;
7282
        case OPC_DBSHFL:
7283 7284
            check_insn(env, ctx, ISA_MIPS64R2);
            check_mips_64(ctx);
7285 7286 7287
            op2 = MASK_DBSHFL(ctx->opcode);
            switch (op2) {
            case OPC_DSBH:
7288
                gen_load_gpr(cpu_T[1], rt);
7289
                tcg_gen_helper_0_0(do_dsbh);
7290 7291
                break;
            case OPC_DSHD:
7292
                gen_load_gpr(cpu_T[1], rt);
7293
                tcg_gen_helper_0_0(do_dshd);
7294
                break;
7295 7296 7297 7298
            default:            /* Invalid */
                MIPS_INVAL("dbshfl");
                generate_exception(ctx, EXCP_RI);
                break;
7299
            }
7300
            gen_store_gpr(cpu_T[0], rd);
T
ths 已提交
7301
            break;
7302 7303 7304 7305 7306 7307 7308 7309 7310 7311 7312 7313 7314
#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 已提交
7315
            return;
7316 7317 7318 7319 7320
        case OPC_TGEI ... OPC_TEQI: /* REGIMM traps */
        case OPC_TNEI:
            gen_trap(ctx, op1, rs, -1, imm);
            break;
        case OPC_SYNCI:
7321
            check_insn(env, ctx, ISA_MIPS32R2);
7322
            /* Treat as NOP. */
B
bellard 已提交
7323 7324
            break;
        default:            /* Invalid */
7325
            MIPS_INVAL("regimm");
B
bellard 已提交
7326 7327 7328 7329
            generate_exception(ctx, EXCP_RI);
            break;
        }
        break;
7330
    case OPC_CP0:
7331
        check_cp0_enabled(ctx);
7332
        op1 = MASK_CP0(ctx->opcode);
B
bellard 已提交
7333
        switch (op1) {
7334 7335
        case OPC_MFC0:
        case OPC_MTC0:
7336 7337
        case OPC_MFTR:
        case OPC_MTTR:
7338
#if defined(TARGET_MIPS64)
7339 7340 7341
        case OPC_DMFC0:
        case OPC_DMTC0:
#endif
7342
#ifndef CONFIG_USER_ONLY
7343
            gen_cp0(env, ctx, op1, rt, rd);
7344
#endif
7345 7346
            break;
        case OPC_C0_FIRST ... OPC_C0_LAST:
7347
#ifndef CONFIG_USER_ONLY
7348
            gen_cp0(env, ctx, MASK_C0(ctx->opcode), rt, rd);
7349
#endif
7350 7351 7352 7353
            break;
        case OPC_MFMC0:
            op2 = MASK_MFMC0(ctx->opcode);
            switch (op2) {
7354
            case OPC_DMT:
7355
                check_insn(env, ctx, ASE_MT);
7356
                tcg_gen_helper_0_0(do_dmt);
7357 7358
                break;
            case OPC_EMT:
7359
                check_insn(env, ctx, ASE_MT);
7360
                tcg_gen_helper_0_0(do_emt);
7361 7362
                break;
            case OPC_DVPE:
7363
                check_insn(env, ctx, ASE_MT);
7364
                tcg_gen_helper_0_0(do_dvpe);
7365 7366
                break;
            case OPC_EVPE:
7367
                check_insn(env, ctx, ASE_MT);
7368
                tcg_gen_helper_0_0(do_evpe);
7369
                break;
7370
            case OPC_DI:
7371
                check_insn(env, ctx, ISA_MIPS32R2);
7372
                save_cpu_state(ctx, 1);
7373
                tcg_gen_helper_0_0(do_di);
7374 7375 7376 7377
                /* Stop translation as we may have switched the execution mode */
                ctx->bstate = BS_STOP;
                break;
            case OPC_EI:
7378
                check_insn(env, ctx, ISA_MIPS32R2);
7379
                save_cpu_state(ctx, 1);
7380
                tcg_gen_helper_0_0(do_ei);
7381 7382 7383 7384
                /* Stop translation as we may have switched the execution mode */
                ctx->bstate = BS_STOP;
                break;
            default:            /* Invalid */
7385
                MIPS_INVAL("mfmc0");
7386 7387 7388
                generate_exception(ctx, EXCP_RI);
                break;
            }
7389
            gen_store_gpr(cpu_T[0], rt);
B
bellard 已提交
7390
            break;
7391
        case OPC_RDPGPR:
7392
            check_insn(env, ctx, ISA_MIPS32R2);
7393 7394
            gen_load_srsgpr(cpu_T[0], rt);
            gen_store_gpr(cpu_T[0], rd);
7395
            break;
7396
        case OPC_WRPGPR:
7397
            check_insn(env, ctx, ISA_MIPS32R2);
7398 7399
            gen_load_gpr(cpu_T[0], rt);
            gen_store_srsgpr(cpu_T[0], rd);
7400
            break;
B
bellard 已提交
7401
        default:
7402
            MIPS_INVAL("cp0");
7403
            generate_exception(ctx, EXCP_RI);
B
bellard 已提交
7404 7405 7406
            break;
        }
        break;
7407
    case OPC_ADDI ... OPC_LUI: /* Arithmetic with immediate opcode */
7408
         gen_arith_imm(env, ctx, op, rt, rs, imm);
7409 7410 7411 7412 7413 7414 7415 7416 7417 7418 7419 7420 7421 7422 7423 7424 7425
         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:
7426
        check_insn(env, ctx, ISA_MIPS3 | ISA_MIPS32);
7427
        /* Treat as NOP. */
7428
        break;
7429
    case OPC_PREF:
7430
        check_insn(env, ctx, ISA_MIPS4 | ISA_MIPS32);
7431
        /* Treat as NOP. */
B
bellard 已提交
7432
        break;
B
bellard 已提交
7433

7434
    /* Floating point (COP1). */
7435 7436 7437 7438
    case OPC_LWC1:
    case OPC_LDC1:
    case OPC_SWC1:
    case OPC_SDC1:
7439 7440
        if (env->CP0_Config1 & (1 << CP0C1_FP)) {
            save_cpu_state(ctx, 1);
7441
            check_cp1_enabled(ctx);
7442 7443 7444 7445
            gen_flt_ldst(ctx, op, rt, rs, imm);
        } else {
            generate_exception_err(ctx, EXCP_CpU, 1);
        }
B
bellard 已提交
7446 7447
        break;

7448
    case OPC_CP1:
7449 7450
        if (env->CP0_Config1 & (1 << CP0C1_FP)) {
            save_cpu_state(ctx, 1);
7451
            check_cp1_enabled(ctx);
7452 7453
            op1 = MASK_CP1(ctx->opcode);
            switch (op1) {
7454 7455
            case OPC_MFHC1:
            case OPC_MTHC1:
7456
                check_insn(env, ctx, ISA_MIPS32R2);
7457 7458 7459 7460
            case OPC_MFC1:
            case OPC_CFC1:
            case OPC_MTC1:
            case OPC_CTC1:
7461 7462
                gen_cp1(ctx, op1, rt, rd);
                break;
7463
#if defined(TARGET_MIPS64)
7464 7465
            case OPC_DMFC1:
            case OPC_DMTC1:
7466
                check_insn(env, ctx, ISA_MIPS3);
7467 7468
                gen_cp1(ctx, op1, rt, rd);
                break;
7469
#endif
7470 7471
            case OPC_BC1ANY2:
            case OPC_BC1ANY4:
7472
                check_cop1x(ctx);
7473
                check_insn(env, ctx, ASE_MIPS3D);
7474 7475
                /* fall through */
            case OPC_BC1:
7476
                gen_compute_branch1(env, ctx, MASK_BC1(ctx->opcode),
7477
                                    (rt >> 2) & 0x7, imm << 2);
7478 7479 7480 7481 7482
                return;
            case OPC_S_FMT:
            case OPC_D_FMT:
            case OPC_W_FMT:
            case OPC_L_FMT:
7483 7484 7485
            case OPC_PS_FMT:
                gen_farith(ctx, MASK_CP1_FUNC(ctx->opcode), rt, rd, sa,
                           (imm >> 8) & 0x7);
7486 7487
                break;
            default:
7488
                MIPS_INVAL("cp1");
7489
                generate_exception (ctx, EXCP_RI);
7490 7491 7492 7493
                break;
            }
        } else {
            generate_exception_err(ctx, EXCP_CpU, 1);
B
bellard 已提交
7494
        }
B
bellard 已提交
7495 7496 7497
        break;

    /* COP2.  */
7498 7499 7500 7501 7502 7503
    case OPC_LWC2:
    case OPC_LDC2:
    case OPC_SWC2:
    case OPC_SDC2:
    case OPC_CP2:
        /* COP2: Not implemented. */
B
bellard 已提交
7504 7505 7506
        generate_exception_err(ctx, EXCP_CpU, 2);
        break;

7507
    case OPC_CP3:
7508
        if (env->CP0_Config1 & (1 << CP0C1_FP)) {
7509
            save_cpu_state(ctx, 1);
7510
            check_cp1_enabled(ctx);
7511 7512
            op1 = MASK_CP3(ctx->opcode);
            switch (op1) {
7513 7514 7515 7516 7517 7518
            case OPC_LWXC1:
            case OPC_LDXC1:
            case OPC_LUXC1:
            case OPC_SWXC1:
            case OPC_SDXC1:
            case OPC_SUXC1:
T
ths 已提交
7519
                gen_flt3_ldst(ctx, op1, sa, rd, rs, rt);
7520
                break;
T
ths 已提交
7521
            case OPC_PREFX:
7522
                /* Treat as NOP. */
T
ths 已提交
7523
                break;
7524 7525 7526 7527 7528 7529 7530 7531 7532 7533 7534 7535 7536 7537 7538
            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;
7539
            default:
7540
                MIPS_INVAL("cp3");
7541
                generate_exception (ctx, EXCP_RI);
7542 7543 7544
                break;
            }
        } else {
7545
            generate_exception_err(ctx, EXCP_CpU, 1);
7546
        }
B
bellard 已提交
7547 7548
        break;

7549
#if defined(TARGET_MIPS64)
7550 7551 7552 7553 7554 7555 7556 7557
    /* 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:
7558 7559
        check_insn(env, ctx, ISA_MIPS3);
        check_mips_64(ctx);
7560 7561 7562
        gen_ldst(ctx, op, rt, rs, imm);
        break;
    case OPC_DADDI ... OPC_DADDIU:
7563 7564 7565
        check_insn(env, ctx, ISA_MIPS3);
        check_mips_64(ctx);
        gen_arith_imm(env, ctx, op, rt, rs, imm);
7566
        break;
B
bellard 已提交
7567
#endif
7568
    case OPC_JALX:
7569
        check_insn(env, ctx, ASE_MIPS16);
7570 7571
        /* MIPS16: Not implemented. */
    case OPC_MDMX:
7572
        check_insn(env, ctx, ASE_MDMX);
7573
        /* MDMX: Not implemented. */
B
bellard 已提交
7574
    default:            /* Invalid */
7575
        MIPS_INVAL("major opcode");
B
bellard 已提交
7576 7577 7578
        generate_exception(ctx, EXCP_RI);
        break;
    }
B
bellard 已提交
7579
    if (ctx->hflags & MIPS_HFLAG_BMASK) {
T
ths 已提交
7580
        int hflags = ctx->hflags & MIPS_HFLAG_BMASK;
B
bellard 已提交
7581
        /* Branches completion */
B
bellard 已提交
7582
        ctx->hflags &= ~MIPS_HFLAG_BMASK;
B
bellard 已提交
7583 7584
        ctx->bstate = BS_BRANCH;
        save_cpu_state(ctx, 0);
7585
        switch (hflags) {
B
bellard 已提交
7586 7587 7588
        case MIPS_HFLAG_B:
            /* unconditional branch */
            MIPS_DEBUG("unconditional branch");
7589
            gen_goto_tb(ctx, 0, ctx->btarget);
B
bellard 已提交
7590 7591 7592 7593
            break;
        case MIPS_HFLAG_BL:
            /* blikely taken case */
            MIPS_DEBUG("blikely branch taken");
7594
            gen_goto_tb(ctx, 0, ctx->btarget);
B
bellard 已提交
7595 7596 7597 7598
            break;
        case MIPS_HFLAG_BC:
            /* Conditional branch */
            MIPS_DEBUG("conditional branch");
B
bellard 已提交
7599
            {
T
ths 已提交
7600
                TCGv r_tmp = tcg_temp_local_new(TCG_TYPE_TL);
7601 7602 7603
                int l1 = gen_new_label();

                tcg_gen_ld_tl(r_tmp, cpu_env, offsetof(CPUState, bcond));
P
pbrook 已提交
7604
                tcg_gen_brcondi_tl(TCG_COND_NE, r_tmp, 0, l1);
T
ths 已提交
7605
                tcg_temp_free(r_tmp);
7606 7607 7608
                gen_goto_tb(ctx, 1, ctx->pc + 4);
                gen_set_label(l1);
                gen_goto_tb(ctx, 0, ctx->btarget);
B
bellard 已提交
7609
            }
B
bellard 已提交
7610 7611 7612 7613
            break;
        case MIPS_HFLAG_BR:
            /* unconditional branch to register */
            MIPS_DEBUG("branch to register");
7614
            gen_breg_pc();
B
bellard 已提交
7615
            tcg_gen_exit_tb(0);
B
bellard 已提交
7616 7617 7618 7619 7620 7621 7622 7623
            break;
        default:
            MIPS_DEBUG("unknown branch");
            break;
        }
    }
}

7624
static always_inline int
7625 7626
gen_intermediate_code_internal (CPUState *env, TranslationBlock *tb,
                                int search_pc)
B
bellard 已提交
7627
{
T
ths 已提交
7628
    DisasContext ctx;
B
bellard 已提交
7629 7630 7631 7632
    target_ulong pc_start;
    uint16_t *gen_opc_end;
    int j, lj = -1;

B
bellard 已提交
7633
    if (search_pc && loglevel)
B
bellard 已提交
7634
        fprintf (logfile, "search pc %d\n", search_pc);
B
bellard 已提交
7635

B
bellard 已提交
7636
    pc_start = tb->pc;
T
ths 已提交
7637 7638
    /* Leave some spare opc slots for branch handling. */
    gen_opc_end = gen_opc_buf + OPC_MAX_SIZE - 16;
B
bellard 已提交
7639
    ctx.pc = pc_start;
B
bellard 已提交
7640
    ctx.saved_pc = -1;
B
bellard 已提交
7641 7642
    ctx.tb = tb;
    ctx.bstate = BS_NONE;
B
bellard 已提交
7643
    /* Restore delay slot state from the tb context.  */
7644
    ctx.hflags = (uint32_t)tb->flags; /* FIXME: maybe use 64 bits here? */
7645
    restore_cpu_state(env, &ctx);
B
bellard 已提交
7646
#if defined(CONFIG_USER_ONLY)
T
ths 已提交
7647
    ctx.mem_idx = MIPS_HFLAG_UM;
B
bellard 已提交
7648
#else
T
ths 已提交
7649
    ctx.mem_idx = ctx.hflags & MIPS_HFLAG_KSU;
B
bellard 已提交
7650 7651 7652 7653
#endif
#ifdef DEBUG_DISAS
    if (loglevel & CPU_LOG_TB_CPU) {
        fprintf(logfile, "------------------------------------------------\n");
B
bellard 已提交
7654
        /* FIXME: This may print out stale hflags from env... */
B
bellard 已提交
7655 7656 7657
        cpu_dump_state(env, logfile, fprintf, 0);
    }
#endif
7658
#ifdef MIPS_DEBUG_DISAS
B
bellard 已提交
7659
    if (loglevel & CPU_LOG_TB_IN_ASM)
T
ths 已提交
7660
        fprintf(logfile, "\ntb %p idx %d hflags %04x\n",
B
bellard 已提交
7661
                tb, ctx.mem_idx, ctx.hflags);
B
bellard 已提交
7662
#endif
T
ths 已提交
7663
    while (ctx.bstate == BS_NONE) {
B
bellard 已提交
7664 7665 7666
        if (env->nb_breakpoints > 0) {
            for(j = 0; j < env->nb_breakpoints; j++) {
                if (env->breakpoints[j] == ctx.pc) {
T
ths 已提交
7667
                    save_cpu_state(&ctx, 1);
B
bellard 已提交
7668
                    ctx.bstate = BS_BRANCH;
T
ths 已提交
7669
                    tcg_gen_helper_0_1i(do_raise_exception, EXCP_DEBUG);
7670 7671 7672
                    /* Include the breakpoint location or the tb won't
                     * be flushed when it must be.  */
                    ctx.pc += 4;
B
bellard 已提交
7673 7674 7675 7676 7677
                    goto done_generating;
                }
            }
        }

B
bellard 已提交
7678 7679 7680 7681 7682 7683 7684
        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 已提交
7685 7686 7687
            gen_opc_pc[lj] = ctx.pc;
            gen_opc_hflags[lj] = ctx.hflags & MIPS_HFLAG_BMASK;
            gen_opc_instr_start[lj] = 1;
B
bellard 已提交
7688 7689
        }
        ctx.opcode = ldl_code(ctx.pc);
7690
        decode_opc(env, &ctx);
B
bellard 已提交
7691
        ctx.pc += 4;
B
bellard 已提交
7692 7693 7694 7695

        if (env->singlestep_enabled)
            break;

B
bellard 已提交
7696 7697
        if ((ctx.pc & (TARGET_PAGE_SIZE - 1)) == 0)
            break;
B
bellard 已提交
7698

T
ths 已提交
7699 7700 7701
        if (gen_opc_ptr >= gen_opc_end)
            break;

T
ths 已提交
7702 7703 7704
        if (gen_opc_ptr >= gen_opc_end)
            break;

B
bellard 已提交
7705 7706 7707 7708
#if defined (MIPS_SINGLE_STEP)
        break;
#endif
    }
B
bellard 已提交
7709
    if (env->singlestep_enabled) {
T
ths 已提交
7710
        save_cpu_state(&ctx, ctx.bstate == BS_NONE);
T
ths 已提交
7711
        tcg_gen_helper_0_1i(do_raise_exception, EXCP_DEBUG);
T
ths 已提交
7712 7713 7714
    } else {
	switch (ctx.bstate) {
        case BS_STOP:
7715
            tcg_gen_helper_0_0(do_interrupt_restart);
7716 7717
            gen_goto_tb(&ctx, 0, ctx.pc);
            break;
T
ths 已提交
7718
        case BS_NONE:
T
ths 已提交
7719
            save_cpu_state(&ctx, 0);
T
ths 已提交
7720 7721
            gen_goto_tb(&ctx, 0, ctx.pc);
            break;
7722
        case BS_EXCP:
7723
            tcg_gen_helper_0_0(do_interrupt_restart);
B
bellard 已提交
7724
            tcg_gen_exit_tb(0);
T
ths 已提交
7725
            break;
7726 7727 7728
        case BS_BRANCH:
        default:
            break;
T
ths 已提交
7729
	}
B
bellard 已提交
7730
    }
B
bellard 已提交
7731
done_generating:
B
bellard 已提交
7732 7733 7734 7735 7736 7737 7738 7739 7740 7741 7742 7743 7744 7745 7746 7747
    *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 已提交
7748
        target_disas(logfile, pc_start, ctx.pc - pc_start, 0);
B
bellard 已提交
7749 7750 7751 7752 7753 7754
        fprintf(logfile, "\n");
    }
    if (loglevel & CPU_LOG_TB_CPU) {
        fprintf(logfile, "---------------- %d %08x\n", ctx.bstate, ctx.hflags);
    }
#endif
7755

B
bellard 已提交
7756 7757 7758 7759 7760 7761 7762 7763 7764 7765 7766 7767 7768
    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);
}

7769
void fpu_dump_state(CPUState *env, FILE *f,
B
bellard 已提交
7770 7771 7772 7773
                    int (*fpu_fprintf)(FILE *f, const char *fmt, ...),
                    int flags)
{
    int i;
7774
    int is_fpu64 = !!(env->hflags & MIPS_HFLAG_F64);
7775 7776 7777 7778 7779 7780 7781 7782 7783 7784 7785 7786 7787 7788 7789

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

7792 7793

    fpu_fprintf(f, "CP1 FCR0 0x%08x  FCR31 0x%08x  SR.FR %d  fp_status 0x%08x(0x%02x)\n",
7794 7795
                env->fpu->fcr0, env->fpu->fcr31, is_fpu64, env->fpu->fp_status,
                get_float_exception_flags(&env->fpu->fp_status));
T
ths 已提交
7796 7797 7798
    fpu_fprintf(f, "FT0: "); printfpr(&env->ft0);
    fpu_fprintf(f, "FT1: "); printfpr(&env->ft1);
    fpu_fprintf(f, "FT2: "); printfpr(&env->ft2);
7799 7800
    for (i = 0; i < 32; (is_fpu64) ? i++ : (i += 2)) {
        fpu_fprintf(f, "%3s: ", fregnames[i]);
7801
        printfpr(&env->fpu->fpr[i]);
B
bellard 已提交
7802 7803 7804 7805 7806
    }

#undef printfpr
}

7807
void dump_fpu (CPUState *env)
B
bellard 已提交
7808
{
7809
    if (loglevel) {
T
ths 已提交
7810 7811 7812 7813 7814 7815 7816
        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 已提交
7817 7818 7819 7820
       fpu_dump_state(env, logfile, fprintf, 0);
    }
}

7821
#if defined(TARGET_MIPS64) && defined(MIPS_DEBUG_SIGN_EXTENSIONS)
7822 7823 7824 7825 7826 7827 7828 7829 7830 7831 7832
/* 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;

7833 7834
    if (!SIGN_EXT_P(env->PC[env->current_tc]))
        cpu_fprintf(f, "BROKEN: pc=0x" TARGET_FMT_lx "\n", env->PC[env->current_tc]);
7835 7836 7837 7838
    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]);
7839
    if (!SIGN_EXT_P(env->btarget))
T
ths 已提交
7840
        cpu_fprintf(f, "BROKEN: btarget=0x" TARGET_FMT_lx "\n", env->btarget);
7841 7842

    for (i = 0; i < 32; i++) {
7843 7844
        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]);
7845 7846 7847
    }

    if (!SIGN_EXT_P(env->CP0_EPC))
T
ths 已提交
7848
        cpu_fprintf(f, "BROKEN: EPC=0x" TARGET_FMT_lx "\n", env->CP0_EPC);
7849
    if (!SIGN_EXT_P(env->CP0_LLAddr))
T
ths 已提交
7850
        cpu_fprintf(f, "BROKEN: LLAddr=0x" TARGET_FMT_lx "\n", env->CP0_LLAddr);
7851 7852 7853
}
#endif

7854
void cpu_dump_state (CPUState *env, FILE *f,
B
bellard 已提交
7855 7856 7857 7858
                     int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
                     int flags)
{
    int i;
7859

T
ths 已提交
7860
    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",
7861
                env->PC[env->current_tc], env->HI[env->current_tc], env->LO[env->current_tc], env->hflags, env->btarget, env->bcond);
B
bellard 已提交
7862 7863 7864
    for (i = 0; i < 32; i++) {
        if ((i & 3) == 0)
            cpu_fprintf(f, "GPR%02d:", i);
7865
        cpu_fprintf(f, " %s " TARGET_FMT_lx, regnames[i], env->gpr[env->current_tc][i]);
B
bellard 已提交
7866 7867 7868
        if ((i & 3) == 3)
            cpu_fprintf(f, "\n");
    }
7869

T
ths 已提交
7870
    cpu_fprintf(f, "CP0 Status  0x%08x Cause   0x%08x EPC    0x" TARGET_FMT_lx "\n",
7871
                env->CP0_Status, env->CP0_Cause, env->CP0_EPC);
T
ths 已提交
7872
    cpu_fprintf(f, "    Config0 0x%08x Config1 0x%08x LLAddr 0x" TARGET_FMT_lx "\n",
B
bellard 已提交
7873
                env->CP0_Config0, env->CP0_Config1, env->CP0_LLAddr);
7874
    if (env->hflags & MIPS_HFLAG_FPU)
7875
        fpu_dump_state(env, f, cpu_fprintf, flags);
7876
#if defined(TARGET_MIPS64) && defined(MIPS_DEBUG_SIGN_EXTENSIONS)
7877 7878
    cpu_mips_check_sign_extensions(env, f, cpu_fprintf, flags);
#endif
B
bellard 已提交
7879 7880
}

7881 7882 7883 7884 7885 7886 7887 7888 7889
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 已提交
7890 7891 7892 7893
    current_tc_gprs = tcg_global_mem_new(TCG_TYPE_PTR,
                                         TCG_AREG0,
                                         offsetof(CPUState, current_tc_gprs),
                                         "current_tc_gprs");
7894 7895 7896 7897
    current_tc_hi = tcg_global_mem_new(TCG_TYPE_PTR,
                                       TCG_AREG0,
                                       offsetof(CPUState, current_tc_hi),
                                       "current_tc_hi");
T
ths 已提交
7898 7899 7900 7901
    current_fpu = tcg_global_mem_new(TCG_TYPE_PTR,
                                     TCG_AREG0,
                                     offsetof(CPUState, fpu),
                                     "current_fpu");
7902 7903 7904 7905 7906 7907
#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 已提交
7908 7909
    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");
7910 7911
#endif

T
ths 已提交
7912 7913 7914 7915 7916
    /* register helpers */
#undef DEF_HELPER
#define DEF_HELPER(ret, name, params) tcg_register_helper(name, #name);
#include "helper.h"

T
ths 已提交
7917 7918 7919 7920 7921 7922 7923 7924 7925 7926
    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");

7927 7928 7929
    inited = 1;
}

B
bellard 已提交
7930 7931 7932
#include "translate_init.c"

CPUMIPSState *cpu_mips_init (const char *cpu_model)
B
bellard 已提交
7933 7934
{
    CPUMIPSState *env;
B
bellard 已提交
7935
    const mips_def_t *def;
B
bellard 已提交
7936

B
bellard 已提交
7937 7938 7939
    def = cpu_mips_find_by_name(cpu_model);
    if (!def)
        return NULL;
B
bellard 已提交
7940 7941 7942
    env = qemu_mallocz(sizeof(CPUMIPSState));
    if (!env)
        return NULL;
B
bellard 已提交
7943 7944
    env->cpu_model = def;

B
bellard 已提交
7945
    cpu_exec_init(env);
7946
    env->cpu_model_str = cpu_model;
7947
    mips_tcg_init();
7948 7949 7950 7951 7952 7953 7954 7955
    cpu_reset(env);
    return env;
}

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

B
bellard 已提交
7956
    tlb_flush(env, 1);
7957

B
bellard 已提交
7958
    /* Minimal init */
7959
#if !defined(CONFIG_USER_ONLY)
7960 7961 7962
    if (env->hflags & MIPS_HFLAG_BMASK) {
        /* If the exception was raised from a delay slot,
         * come back to the jump.  */
7963
        env->CP0_ErrorEPC = env->PC[env->current_tc] - 4;
7964
    } else {
7965
        env->CP0_ErrorEPC = env->PC[env->current_tc];
7966
    }
7967
    env->PC[env->current_tc] = (int32_t)0xBFC00000;
B
bellard 已提交
7968
    env->CP0_Wired = 0;
7969
    /* SMP not implemented */
7970
    env->CP0_EBase = 0x80000000;
7971
    env->CP0_Status = (1 << CP0St_BEV) | (1 << CP0St_ERL);
T
ths 已提交
7972 7973 7974
    /* vectored interrupts not implemented, timer on int 7,
       no performance counters. */
    env->CP0_IntCtl = 0xe0000000;
7975 7976 7977 7978 7979 7980 7981 7982 7983 7984
    {
        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 已提交
7985 7986
    /* Count register increments in debug mode, EJTAG version 1 */
    env->CP0_Debug = (1 << CP0DB_CNT) | (0x1 << CP0DB_VER);
7987
#endif
B
bellard 已提交
7988
    env->exception_index = EXCP_NONE;
7989
#if defined(CONFIG_USER_ONLY)
7990
    env->hflags = MIPS_HFLAG_UM;
7991
    env->user_mode_only = 1;
7992 7993
#else
    env->hflags = MIPS_HFLAG_CP0;
B
bellard 已提交
7994
#endif
B
bellard 已提交
7995
    cpu_mips_register(env, env->cpu_model);
B
bellard 已提交
7996
}
A
aurel32 已提交
7997 7998 7999 8000 8001 8002 8003 8004

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];
}