translate.c 84.7 KB
Newer Older
J
j_mayer 已提交
1 2
/*
 *  Alpha emulation cpu translation for qemu.
3
 *
J
j_mayer 已提交
4 5 6 7 8 9 10 11 12 13 14 15 16
 *  Copyright (c) 2007 Jocelyn Mayer
 *
 * 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
17
 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
J
j_mayer 已提交
18 19 20
 */

#include "cpu.h"
21
#include "disas/disas.h"
22
#include "qemu/host-utils.h"
B
bellard 已提交
23
#include "tcg-op.h"
P
Paolo Bonzini 已提交
24
#include "exec/cpu_ldst.h"
J
j_mayer 已提交
25

26 27
#include "exec/helper-proto.h"
#include "exec/helper-gen.h"
P
pbrook 已提交
28

29 30 31
#include "trace-tcg.h"


32
#undef ALPHA_DEBUG_DISAS
33
#define CONFIG_SOFTFLOAT_INLINE
34 35

#ifdef ALPHA_DEBUG_DISAS
R
Richard Henderson 已提交
36
#  define LOG_DISAS(...) qemu_log_mask(CPU_LOG_TB_IN_ASM, ## __VA_ARGS__)
37 38 39 40
#else
#  define LOG_DISAS(...) do { } while (0)
#endif

J
j_mayer 已提交
41 42
typedef struct DisasContext DisasContext;
struct DisasContext {
43
    struct TranslationBlock *tb;
J
j_mayer 已提交
44 45
    uint64_t pc;
    int mem_idx;
46 47 48 49 50

    /* Current rounding mode for this TB.  */
    int tb_rm;
    /* Current flush-to-zero setting for this TB.  */
    int tb_ftz;
51

52 53 54
    /* implver value for this CPU.  */
    int implver;

55 56 57 58 59 60
    /* Temporaries for $31 and $f31 as source and destination.  */
    TCGv zero;
    TCGv sink;
    /* Temporary for immediate constants.  */
    TCGv lit;

61
    bool singlestep_enabled;
J
j_mayer 已提交
62 63
};

64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79
/* Return values from translate_one, indicating the state of the TB.
   Note that zero indicates that we are not exiting the TB.  */

typedef enum {
    NO_EXIT,

    /* We have emitted one or more goto_tb.  No fixup required.  */
    EXIT_GOTO_TB,

    /* We are not using a goto_tb (for whatever reason), but have updated
       the PC (for whatever reason), so there's no need to do it again on
       exiting the TB.  */
    EXIT_PC_UPDATED,

    /* We are exiting the TB, but have neither emitted a goto_tb, nor
       updated the PC for the next instruction to be executed.  */
80 81 82 83 84
    EXIT_PC_STALE,

    /* We are ending the TB with a noreturn function call, e.g. longjmp.
       No following code will be executed.  */
    EXIT_NORETURN,
85 86
} ExitStatus;

A
aurel32 已提交
87
/* global register indexes */
P
pbrook 已提交
88
static TCGv_ptr cpu_env;
A
aurel32 已提交
89
static TCGv cpu_ir[31];
A
aurel32 已提交
90
static TCGv cpu_fir[31];
A
aurel32 已提交
91
static TCGv cpu_pc;
92 93 94
static TCGv cpu_lock_addr;
static TCGv cpu_lock_st_addr;
static TCGv cpu_lock_value;
A
aurel32 已提交
95

96
#include "exec/gen-icount.h"
P
pbrook 已提交
97

98
void alpha_translate_init(void)
P
pbrook 已提交
99
{
100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126
#define DEF_VAR(V)  { &cpu_##V, #V, offsetof(CPUAlphaState, V) }

    typedef struct { TCGv *var; const char *name; int ofs; } GlobalVar;
    static const GlobalVar vars[] = {
        DEF_VAR(pc),
        DEF_VAR(lock_addr),
        DEF_VAR(lock_st_addr),
        DEF_VAR(lock_value),
    };

#undef DEF_VAR

    /* Use the symbolic register names that match the disassembler.  */
    static const char greg_names[31][4] = {
        "v0", "t0", "t1", "t2", "t3", "t4", "t5", "t6",
        "t7", "s0", "s1", "s2", "s3", "s4", "s5", "fp",
        "a0", "a1", "a2", "a3", "a4", "a5", "t8", "t9",
        "t10", "t11", "ra", "t12", "at", "gp", "sp"
    };
    static const char freg_names[31][4] = {
        "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"
    };

    static bool done_init = 0;
A
aurel32 已提交
127 128
    int i;

P
Paolo Bonzini 已提交
129
    if (done_init) {
P
pbrook 已提交
130
        return;
P
Paolo Bonzini 已提交
131
    }
132
    done_init = 1;
A
aurel32 已提交
133

P
pbrook 已提交
134
    cpu_env = tcg_global_reg_new_ptr(TCG_AREG0, "env");
A
aurel32 已提交
135 136

    for (i = 0; i < 31; i++) {
P
pbrook 已提交
137
        cpu_ir[i] = tcg_global_mem_new_i64(TCG_AREG0,
138 139 140
                                           offsetof(CPUAlphaState, ir[i]),
                                           greg_names[i]);
    }
A
aurel32 已提交
141

142
    for (i = 0; i < 31; i++) {
P
pbrook 已提交
143
        cpu_fir[i] = tcg_global_mem_new_i64(TCG_AREG0,
144 145
                                            offsetof(CPUAlphaState, fir[i]),
                                            freg_names[i]);
A
aurel32 已提交
146 147
    }

148 149 150 151
    for (i = 0; i < ARRAY_SIZE(vars); ++i) {
        const GlobalVar *v = &vars[i];
        *v->var = tcg_global_mem_new_i64(TCG_AREG0, v->ofs, v->name);
    }
P
pbrook 已提交
152 153
}

154 155 156
static TCGv load_zero(DisasContext *ctx)
{
    if (TCGV_IS_UNUSED_I64(ctx->zero)) {
157
        ctx->zero = tcg_const_i64(0);
158 159 160 161 162 163 164
    }
    return ctx->zero;
}

static TCGv dest_sink(DisasContext *ctx)
{
    if (TCGV_IS_UNUSED_I64(ctx->sink)) {
165
        ctx->sink = tcg_temp_new();
166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200
    }
    return ctx->sink;
}

static TCGv load_gpr(DisasContext *ctx, unsigned reg)
{
    if (likely(reg < 31)) {
        return cpu_ir[reg];
    } else {
        return load_zero(ctx);
    }
}

static TCGv load_gpr_lit(DisasContext *ctx, unsigned reg,
                         uint8_t lit, bool islit)
{
    if (islit) {
        ctx->lit = tcg_const_i64(lit);
        return ctx->lit;
    } else if (likely(reg < 31)) {
        return cpu_ir[reg];
    } else {
        return load_zero(ctx);
    }
}

static TCGv dest_gpr(DisasContext *ctx, unsigned reg)
{
    if (likely(reg < 31)) {
        return cpu_ir[reg];
    } else {
        return dest_sink(ctx);
    }
}

201
static TCGv load_fpr(DisasContext *ctx, unsigned reg)
202 203 204 205 206 207 208 209
{
    if (likely(reg < 31)) {
        return cpu_fir[reg];
    } else {
        return load_zero(ctx);
    }
}

210
static TCGv dest_fpr(DisasContext *ctx, unsigned reg)
211 212 213 214 215 216 217 218
{
    if (likely(reg < 31)) {
        return cpu_fir[reg];
    } else {
        return dest_sink(ctx);
    }
}

219
static void gen_excp_1(int exception, int error_code)
J
j_mayer 已提交
220
{
P
pbrook 已提交
221
    TCGv_i32 tmp1, tmp2;
222 223 224

    tmp1 = tcg_const_i32(exception);
    tmp2 = tcg_const_i32(error_code);
225
    gen_helper_excp(cpu_env, tmp1, tmp2);
P
pbrook 已提交
226 227
    tcg_temp_free_i32(tmp2);
    tcg_temp_free_i32(tmp1);
228
}
229

230 231 232 233
static ExitStatus gen_excp(DisasContext *ctx, int exception, int error_code)
{
    tcg_gen_movi_i64(cpu_pc, ctx->pc);
    gen_excp_1(exception, error_code);
234
    return EXIT_NORETURN;
J
j_mayer 已提交
235 236
}

237
static inline ExitStatus gen_invalid(DisasContext *ctx)
J
j_mayer 已提交
238
{
239
    return gen_excp(ctx, EXCP_OPCDEC, 0);
J
j_mayer 已提交
240 241
}

B
Blue Swirl 已提交
242
static inline void gen_qemu_ldf(TCGv t0, TCGv t1, int flags)
A
aurel32 已提交
243
{
P
pbrook 已提交
244
    TCGv_i32 tmp32 = tcg_temp_new_i32();
245
    tcg_gen_qemu_ld_i32(tmp32, t1, flags, MO_LEUL);
P
pbrook 已提交
246 247
    gen_helper_memory_to_f(t0, tmp32);
    tcg_temp_free_i32(tmp32);
A
aurel32 已提交
248 249
}

B
Blue Swirl 已提交
250
static inline void gen_qemu_ldg(TCGv t0, TCGv t1, int flags)
A
aurel32 已提交
251
{
P
pbrook 已提交
252
    TCGv tmp = tcg_temp_new();
253
    tcg_gen_qemu_ld_i64(tmp, t1, flags, MO_LEQ);
P
pbrook 已提交
254
    gen_helper_memory_to_g(t0, tmp);
A
aurel32 已提交
255 256 257
    tcg_temp_free(tmp);
}

B
Blue Swirl 已提交
258
static inline void gen_qemu_lds(TCGv t0, TCGv t1, int flags)
A
aurel32 已提交
259
{
P
pbrook 已提交
260
    TCGv_i32 tmp32 = tcg_temp_new_i32();
261
    tcg_gen_qemu_ld_i32(tmp32, t1, flags, MO_LEUL);
P
pbrook 已提交
262 263
    gen_helper_memory_to_s(t0, tmp32);
    tcg_temp_free_i32(tmp32);
A
aurel32 已提交
264 265
}

B
Blue Swirl 已提交
266
static inline void gen_qemu_ldl_l(TCGv t0, TCGv t1, int flags)
267
{
268
    tcg_gen_qemu_ld_i64(t0, t1, flags, MO_LESL);
269 270
    tcg_gen_mov_i64(cpu_lock_addr, t1);
    tcg_gen_mov_i64(cpu_lock_value, t0);
271 272
}

B
Blue Swirl 已提交
273
static inline void gen_qemu_ldq_l(TCGv t0, TCGv t1, int flags)
274
{
275
    tcg_gen_qemu_ld_i64(t0, t1, flags, MO_LEQ);
276 277
    tcg_gen_mov_i64(cpu_lock_addr, t1);
    tcg_gen_mov_i64(cpu_lock_value, t0);
278 279
}

B
Blue Swirl 已提交
280 281 282
static inline void gen_load_mem(DisasContext *ctx,
                                void (*tcg_gen_qemu_load)(TCGv t0, TCGv t1,
                                                          int flags),
283 284
                                int ra, int rb, int32_t disp16, bool fp,
                                bool clear)
285
{
286
    TCGv tmp, addr, va;
287

288 289 290 291
    /* LDQ_U with ra $31 is UNOP.  Other various loads are forms of
       prefetches, which we can treat as nops.  No worries about
       missed exceptions here.  */
    if (unlikely(ra == 31)) {
292
        return;
293
    }
294

295 296 297 298 299 300 301 302 303 304
    tmp = tcg_temp_new();
    addr = load_gpr(ctx, rb);

    if (disp16) {
        tcg_gen_addi_i64(tmp, addr, disp16);
        addr = tmp;
    }
    if (clear) {
        tcg_gen_andi_i64(tmp, addr, ~0x7);
        addr = tmp;
305
    }
306 307 308 309

    va = (fp ? cpu_fir[ra] : cpu_ir[ra]);
    tcg_gen_qemu_load(va, addr, ctx->mem_idx);

310
    tcg_temp_free(tmp);
311 312
}

B
Blue Swirl 已提交
313
static inline void gen_qemu_stf(TCGv t0, TCGv t1, int flags)
A
aurel32 已提交
314
{
P
pbrook 已提交
315 316
    TCGv_i32 tmp32 = tcg_temp_new_i32();
    gen_helper_f_to_memory(tmp32, t0);
317
    tcg_gen_qemu_st_i32(tmp32, t1, flags, MO_LEUL);
P
pbrook 已提交
318
    tcg_temp_free_i32(tmp32);
A
aurel32 已提交
319 320
}

B
Blue Swirl 已提交
321
static inline void gen_qemu_stg(TCGv t0, TCGv t1, int flags)
A
aurel32 已提交
322
{
P
pbrook 已提交
323 324
    TCGv tmp = tcg_temp_new();
    gen_helper_g_to_memory(tmp, t0);
325
    tcg_gen_qemu_st_i64(tmp, t1, flags, MO_LEQ);
A
aurel32 已提交
326 327 328
    tcg_temp_free(tmp);
}

B
Blue Swirl 已提交
329
static inline void gen_qemu_sts(TCGv t0, TCGv t1, int flags)
A
aurel32 已提交
330
{
P
pbrook 已提交
331 332
    TCGv_i32 tmp32 = tcg_temp_new_i32();
    gen_helper_s_to_memory(tmp32, t0);
333
    tcg_gen_qemu_st_i32(tmp32, t1, flags, MO_LEUL);
P
pbrook 已提交
334
    tcg_temp_free_i32(tmp32);
A
aurel32 已提交
335 336
}

B
Blue Swirl 已提交
337 338 339
static inline void gen_store_mem(DisasContext *ctx,
                                 void (*tcg_gen_qemu_store)(TCGv t0, TCGv t1,
                                                            int flags),
340 341
                                 int ra, int rb, int32_t disp16, bool fp,
                                 bool clear)
342
{
343
    TCGv tmp, addr, va;
344

345 346
    tmp = tcg_temp_new();
    addr = load_gpr(ctx, rb);
347

348 349 350 351 352 353 354
    if (disp16) {
        tcg_gen_addi_i64(tmp, addr, disp16);
        addr = tmp;
    }
    if (clear) {
        tcg_gen_andi_i64(tmp, addr, ~0x7);
        addr = tmp;
355
    }
356 357

    va = (fp ? load_fpr(ctx, ra) : load_gpr(ctx, ra));
358 359
    tcg_gen_qemu_store(va, addr, ctx->mem_idx);

360
    tcg_temp_free(tmp);
361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376
}

static ExitStatus gen_store_conditional(DisasContext *ctx, int ra, int rb,
                                        int32_t disp16, int quad)
{
    TCGv addr;

    if (ra == 31) {
        /* ??? Don't bother storing anything.  The user can't tell
           the difference, since the zero register always reads zero.  */
        return NO_EXIT;
    }

#if defined(CONFIG_USER_ONLY)
    addr = cpu_lock_st_addr;
#else
377
    addr = tcg_temp_local_new();
378 379
#endif

380
    tcg_gen_addi_i64(addr, load_gpr(ctx, rb), disp16);
381 382 383 384 385 386 387 388 389 390

#if defined(CONFIG_USER_ONLY)
    /* ??? This is handled via a complicated version of compare-and-swap
       in the cpu_loop.  Hopefully one day we'll have a real CAS opcode
       in TCG so that this isn't necessary.  */
    return gen_excp(ctx, quad ? EXCP_STQ_C : EXCP_STL_C, ra);
#else
    /* ??? In system mode we are never multi-threaded, so CAS can be
       implemented via a non-atomic load-compare-store sequence.  */
    {
391
        TCGLabel *lab_fail, *lab_done;
392 393 394 395
        TCGv val;

        lab_fail = gen_new_label();
        lab_done = gen_new_label();
396
        tcg_gen_brcond_i64(TCG_COND_NE, addr, cpu_lock_addr, lab_fail);
397 398

        val = tcg_temp_new();
399
        tcg_gen_qemu_ld_i64(val, addr, ctx->mem_idx, quad ? MO_LEQ : MO_LESL);
400
        tcg_gen_brcond_i64(TCG_COND_NE, val, cpu_lock_value, lab_fail);
401

402 403
        tcg_gen_qemu_st_i64(cpu_ir[ra], addr, ctx->mem_idx,
                            quad ? MO_LEQ : MO_LEUL);
404 405 406 407 408 409 410 411 412 413 414 415 416
        tcg_gen_movi_i64(cpu_ir[ra], 1);
        tcg_gen_br(lab_done);

        gen_set_label(lab_fail);
        tcg_gen_movi_i64(cpu_ir[ra], 0);

        gen_set_label(lab_done);
        tcg_gen_movi_i64(cpu_lock_addr, -1);

        tcg_temp_free(addr);
        return NO_EXIT;
    }
#endif
417 418
}

419
static bool in_superpage(DisasContext *ctx, int64_t addr)
J
j_mayer 已提交
420
{
421 422 423 424 425 426 427 428 429
    return ((ctx->tb->flags & TB_FLAGS_USER_MODE) == 0
            && addr < 0
            && ((addr >> 41) & 3) == 2
            && addr >> TARGET_VIRT_ADDR_SPACE_BITS == addr >> 63);
}

static bool use_goto_tb(DisasContext *ctx, uint64_t dest)
{
    /* Suppress goto_tb in the case of single-steping and IO.  */
430 431
    if ((ctx->tb->cflags & CF_LAST_IO)
        || ctx->singlestep_enabled || singlestep) {
432 433 434 435 436 437 438 439
        return false;
    }
    /* If the destination is in the superpage, the page perms can't change.  */
    if (in_superpage(ctx, dest)) {
        return true;
    }
    /* Check for the dest on the same page as the start of the TB.  */
    return ((ctx->tb->pc ^ dest) & TARGET_PAGE_MASK) == 0;
440
}
441

442 443 444 445 446 447 448 449 450 451 452 453 454 455
static ExitStatus gen_bdirect(DisasContext *ctx, int ra, int32_t disp)
{
    uint64_t dest = ctx->pc + (disp << 2);

    if (ra != 31) {
        tcg_gen_movi_i64(cpu_ir[ra], ctx->pc);
    }

    /* Notice branch-to-next; used to initialize RA with the PC.  */
    if (disp == 0) {
        return 0;
    } else if (use_goto_tb(ctx, dest)) {
        tcg_gen_goto_tb(0);
        tcg_gen_movi_i64(cpu_pc, dest);
456
        tcg_gen_exit_tb((uintptr_t)ctx->tb);
457 458 459 460 461
        return EXIT_GOTO_TB;
    } else {
        tcg_gen_movi_i64(cpu_pc, dest);
        return EXIT_PC_UPDATED;
    }
462 463
}

464 465
static ExitStatus gen_bcond_internal(DisasContext *ctx, TCGCond cond,
                                     TCGv cmp, int32_t disp)
466
{
467
    uint64_t dest = ctx->pc + (disp << 2);
468
    TCGLabel *lab_true = gen_new_label();
A
aurel32 已提交
469

470 471 472 473 474
    if (use_goto_tb(ctx, dest)) {
        tcg_gen_brcondi_i64(cond, cmp, 0, lab_true);

        tcg_gen_goto_tb(0);
        tcg_gen_movi_i64(cpu_pc, ctx->pc);
475
        tcg_gen_exit_tb((uintptr_t)ctx->tb);
476 477 478 479

        gen_set_label(lab_true);
        tcg_gen_goto_tb(1);
        tcg_gen_movi_i64(cpu_pc, dest);
480
        tcg_gen_exit_tb((uintptr_t)ctx->tb + 1);
481 482 483

        return EXIT_GOTO_TB;
    } else {
R
Richard Henderson 已提交
484 485 486
        TCGv_i64 z = tcg_const_i64(0);
        TCGv_i64 d = tcg_const_i64(dest);
        TCGv_i64 p = tcg_const_i64(ctx->pc);
487

R
Richard Henderson 已提交
488
        tcg_gen_movcond_i64(cond, cpu_pc, cmp, z, d, p);
489

R
Richard Henderson 已提交
490 491 492
        tcg_temp_free_i64(z);
        tcg_temp_free_i64(d);
        tcg_temp_free_i64(p);
493 494 495 496 497 498 499 500 501
        return EXIT_PC_UPDATED;
    }
}

static ExitStatus gen_bcond(DisasContext *ctx, TCGCond cond, int ra,
                            int32_t disp, int mask)
{
    TCGv cmp_tmp;

502
    if (mask) {
503
        cmp_tmp = tcg_temp_new();
504 505 506
        tcg_gen_andi_i64(cmp_tmp, load_gpr(ctx, ra), 1);
    } else {
        cmp_tmp = load_gpr(ctx, ra);
A
aurel32 已提交
507
    }
508 509

    return gen_bcond_internal(ctx, cond, cmp_tmp, disp);
J
j_mayer 已提交
510 511
}

512
/* Fold -0.0 for comparison with COND.  */
513

514
static void gen_fold_mzero(TCGCond cond, TCGv dest, TCGv src)
J
j_mayer 已提交
515
{
516
    uint64_t mzero = 1ull << 63;
A
aurel32 已提交
517

518 519 520 521
    switch (cond) {
    case TCG_COND_LE:
    case TCG_COND_GT:
        /* For <= or >, the -0.0 value directly compares the way we want.  */
522
        tcg_gen_mov_i64(dest, src);
P
pbrook 已提交
523
        break;
524 525 526 527

    case TCG_COND_EQ:
    case TCG_COND_NE:
        /* For == or !=, we can simply mask off the sign bit and compare.  */
528
        tcg_gen_andi_i64(dest, src, mzero - 1);
P
pbrook 已提交
529
        break;
530 531 532

    case TCG_COND_GE:
    case TCG_COND_LT:
533 534 535 536
        /* For >= or <, map -0.0 to +0.0 via comparison and mask.  */
        tcg_gen_setcondi_i64(TCG_COND_NE, dest, src, mzero);
        tcg_gen_neg_i64(dest, dest);
        tcg_gen_and_i64(dest, dest, src);
P
pbrook 已提交
537
        break;
538

P
pbrook 已提交
539 540
    default:
        abort();
A
aurel32 已提交
541
    }
542 543
}

544 545
static ExitStatus gen_fbcond(DisasContext *ctx, TCGCond cond, int ra,
                             int32_t disp)
546
{
547 548
    TCGv cmp_tmp = tcg_temp_new();
    gen_fold_mzero(cond, cmp_tmp, load_fpr(ctx, ra));
549
    return gen_bcond_internal(ctx, cond, cmp_tmp, disp);
J
j_mayer 已提交
550 551
}

552
static void gen_fcmov(DisasContext *ctx, TCGCond cond, int ra, int rb, int rc)
553
{
554
    TCGv_i64 va, vb, z;
555

556 557 558 559
    z = load_zero(ctx);
    vb = load_fpr(ctx, rb);
    va = tcg_temp_new();
    gen_fold_mzero(cond, va, load_fpr(ctx, ra));
560

561
    tcg_gen_movcond_i64(cond, dest_fpr(ctx, rc), va, z, vb, load_fpr(ctx, rc));
562

563
    tcg_temp_free(va);
564 565
}

566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598
#define QUAL_RM_N       0x080   /* Round mode nearest even */
#define QUAL_RM_C       0x000   /* Round mode chopped */
#define QUAL_RM_M       0x040   /* Round mode minus infinity */
#define QUAL_RM_D       0x0c0   /* Round mode dynamic */
#define QUAL_RM_MASK    0x0c0

#define QUAL_U          0x100   /* Underflow enable (fp output) */
#define QUAL_V          0x100   /* Overflow enable (int output) */
#define QUAL_S          0x400   /* Software completion enable */
#define QUAL_I          0x200   /* Inexact detection enable */

static void gen_qual_roundmode(DisasContext *ctx, int fn11)
{
    TCGv_i32 tmp;

    fn11 &= QUAL_RM_MASK;
    if (fn11 == ctx->tb_rm) {
        return;
    }
    ctx->tb_rm = fn11;

    tmp = tcg_temp_new_i32();
    switch (fn11) {
    case QUAL_RM_N:
        tcg_gen_movi_i32(tmp, float_round_nearest_even);
        break;
    case QUAL_RM_C:
        tcg_gen_movi_i32(tmp, float_round_to_zero);
        break;
    case QUAL_RM_M:
        tcg_gen_movi_i32(tmp, float_round_down);
        break;
    case QUAL_RM_D:
599 600
        tcg_gen_ld8u_i32(tmp, cpu_env,
                         offsetof(CPUAlphaState, fpcr_dyn_round));
601 602 603 604
        break;
    }

#if defined(CONFIG_SOFTFLOAT_INLINE)
605
    /* ??? The "fpu/softfloat.h" interface is to call set_float_rounding_mode.
606 607 608
       With CONFIG_SOFTFLOAT that expands to an out-of-line call that just
       sets the one field.  */
    tcg_gen_st8_i32(tmp, cpu_env,
609
                    offsetof(CPUAlphaState, fp_status.float_rounding_mode));
610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629
#else
    gen_helper_setroundmode(tmp);
#endif

    tcg_temp_free_i32(tmp);
}

static void gen_qual_flushzero(DisasContext *ctx, int fn11)
{
    TCGv_i32 tmp;

    fn11 &= QUAL_U;
    if (fn11 == ctx->tb_ftz) {
        return;
    }
    ctx->tb_ftz = fn11;

    tmp = tcg_temp_new_i32();
    if (fn11) {
        /* Underflow is enabled, use the FPCR setting.  */
630 631
        tcg_gen_ld8u_i32(tmp, cpu_env,
                         offsetof(CPUAlphaState, fpcr_flush_to_zero));
632 633 634 635 636 637 638
    } else {
        /* Underflow is disabled, force flush-to-zero.  */
        tcg_gen_movi_i32(tmp, 1);
    }

#if defined(CONFIG_SOFTFLOAT_INLINE)
    tcg_gen_st8_i32(tmp, cpu_env,
639
                    offsetof(CPUAlphaState, fp_status.flush_to_zero));
640 641 642 643 644 645 646
#else
    gen_helper_setflushzero(tmp);
#endif

    tcg_temp_free_i32(tmp);
}

647
static TCGv gen_ieee_input(DisasContext *ctx, int reg, int fn11, int is_cmp)
648
{
649
    TCGv val;
650 651 652

    if (unlikely(reg == 31)) {
        val = load_zero(ctx);
653
    } else {
654
        val = cpu_fir[reg];
655 656
        if ((fn11 & QUAL_S) == 0) {
            if (is_cmp) {
657
                gen_helper_ieee_input_cmp(cpu_env, val);
658
            } else {
659
                gen_helper_ieee_input(cpu_env, val);
660
            }
661 662 663 664 665 666 667
        } else {
#ifndef CONFIG_USER_ONLY
            /* In system mode, raise exceptions for denormals like real
               hardware.  In user mode, proceed as if the OS completion
               handler is handling the denormal as per spec.  */
            gen_helper_ieee_input_s(cpu_env, val);
#endif
668
        }
669 670 671 672
    }
    return val;
}

673
static void gen_fp_exc_raise(int rc, int fn11)
674 675 676 677 678 679
{
    /* ??? We ought to be able to do something with imprecise exceptions.
       E.g. notice we're still in the trap shadow of something within the
       TB and do not generate the code to signal the exception; end the TB
       when an exception is forced to arrive, either by consumption of a
       register value or TRAPB or EXCB.  */
680 681 682 683 684 685 686 687 688 689 690
    TCGv_i32 reg, ign;
    uint32_t ignore = 0;

    if (!(fn11 & QUAL_U)) {
        /* Note that QUAL_U == QUAL_V, so ignore either.  */
        ignore |= FPCR_UNF | FPCR_IOV;
    }
    if (!(fn11 & QUAL_I)) {
        ignore |= FPCR_INE;
    }
    ign = tcg_const_i32(ignore);
691 692 693 694 695 696 697 698

    /* ??? Pass in the regno of the destination so that the helper can
       set EXC_MASK, which contains a bitmask of destination registers
       that have caused arithmetic traps.  A simple userspace emulation
       does not require this.  We do need it for a guest kernel's entArith,
       or if we were to do something clever with imprecise exceptions.  */
    reg = tcg_const_i32(rc + 32);
    if (fn11 & QUAL_S) {
699
        gen_helper_fp_exc_raise_s(cpu_env, ign, reg);
700
    } else {
701
        gen_helper_fp_exc_raise(cpu_env, ign, reg);
702 703 704
    }

    tcg_temp_free_i32(reg);
705
    tcg_temp_free_i32(ign);
706 707
}

708
static void gen_cvtlq(TCGv vc, TCGv vb)
709
{
710
    TCGv tmp = tcg_temp_new();
711

712 713 714 715 716 717 718
    /* The arithmetic right shift here, plus the sign-extended mask below
       yields a sign-extended result without an explicit ext32s_i64.  */
    tcg_gen_sari_i64(tmp, vb, 32);
    tcg_gen_shri_i64(vc, vb, 29);
    tcg_gen_andi_i64(tmp, tmp, (int32_t)0xc0000000);
    tcg_gen_andi_i64(vc, vc, 0x3fffffff);
    tcg_gen_or_i64(vc, vc, tmp);
719

720
    tcg_temp_free(tmp);
721 722
}

723 724
static void gen_ieee_arith2(DisasContext *ctx,
                            void (*helper)(TCGv, TCGv_ptr, TCGv),
725 726 727 728 729 730 731
                            int rb, int rc, int fn11)
{
    TCGv vb;

    gen_qual_roundmode(ctx, fn11);
    gen_qual_flushzero(ctx, fn11);

732
    vb = gen_ieee_input(ctx, rb, fn11, 0);
733
    helper(dest_fpr(ctx, rc), cpu_env, vb);
734 735 736 737 738

    gen_fp_exc_raise(rc, fn11);
}

#define IEEE_ARITH2(name)                                       \
739 740
static inline void glue(gen_, name)(DisasContext *ctx,          \
                                    int rb, int rc, int fn11)   \
741 742 743 744 745 746 747 748
{                                                               \
    gen_ieee_arith2(ctx, gen_helper_##name, rb, rc, fn11);      \
}
IEEE_ARITH2(sqrts)
IEEE_ARITH2(sqrtt)
IEEE_ARITH2(cvtst)
IEEE_ARITH2(cvtts)

749
static void gen_cvttq(DisasContext *ctx, int rb, int rc, int fn11)
750
{
751
    TCGv vb, vc;
752 753

    /* No need to set flushzero, since we have an integer output.  */
754
    vb = gen_ieee_input(ctx, rb, fn11, 0);
755
    vc = dest_fpr(ctx, rc);
756

757 758 759
    /* Almost all integer conversions use cropped rounding;
       special case that.  */
    if ((fn11 & QUAL_RM_MASK) == QUAL_RM_C) {
760
        gen_helper_cvttq_c(vc, cpu_env, vb);
761
    } else {
762
        gen_qual_roundmode(ctx, fn11);
763
        gen_helper_cvttq(vc, cpu_env, vb);
764
    }
765
    gen_fp_exc_raise(rc, fn11);
J
j_mayer 已提交
766 767
}

768 769
static void gen_ieee_intcvt(DisasContext *ctx,
                            void (*helper)(TCGv, TCGv_ptr, TCGv),
770 771
			    int rb, int rc, int fn11)
{
772
    TCGv vb, vc;
773 774

    gen_qual_roundmode(ctx, fn11);
775 776
    vb = load_fpr(ctx, rb);
    vc = dest_fpr(ctx, rc);
777 778 779 780 781

    /* The only exception that can be raised by integer conversion
       is inexact.  Thus we only need to worry about exceptions when
       inexact handling is requested.  */
    if (fn11 & QUAL_I) {
782
        helper(vc, cpu_env, vb);
783 784
        gen_fp_exc_raise(rc, fn11);
    } else {
785
        helper(vc, cpu_env, vb);
786 787 788 789
    }
}

#define IEEE_INTCVT(name)                                       \
790 791
static inline void glue(gen_, name)(DisasContext *ctx,          \
                                    int rb, int rc, int fn11)   \
792 793 794 795 796 797
{                                                               \
    gen_ieee_intcvt(ctx, gen_helper_##name, rb, rc, fn11);      \
}
IEEE_INTCVT(cvtqs)
IEEE_INTCVT(cvtqt)

798
static void gen_cpy_mask(TCGv vc, TCGv va, TCGv vb, bool inv_a, uint64_t mask)
799
{
800 801
    TCGv vmask = tcg_const_i64(mask);
    TCGv tmp = tcg_temp_new_i64();
802

803 804
    if (inv_a) {
        tcg_gen_andc_i64(tmp, vmask, va);
805
    } else {
806
        tcg_gen_and_i64(tmp, va, vmask);
807 808
    }

809 810
    tcg_gen_andc_i64(vc, vb, vmask);
    tcg_gen_or_i64(vc, vc, tmp);
811 812

    tcg_temp_free(vmask);
813
    tcg_temp_free(tmp);
814 815
}

816
static void gen_ieee_arith3(DisasContext *ctx,
817
                            void (*helper)(TCGv, TCGv_ptr, TCGv, TCGv),
818 819
                            int ra, int rb, int rc, int fn11)
{
820
    TCGv va, vb, vc;
821 822 823 824

    gen_qual_roundmode(ctx, fn11);
    gen_qual_flushzero(ctx, fn11);

825 826
    va = gen_ieee_input(ctx, ra, fn11, 0);
    vb = gen_ieee_input(ctx, rb, fn11, 0);
827 828
    vc = dest_fpr(ctx, rc);
    helper(vc, cpu_env, va, vb);
829 830 831 832 833

    gen_fp_exc_raise(rc, fn11);
}

#define IEEE_ARITH3(name)                                               \
834 835
static inline void glue(gen_, name)(DisasContext *ctx,                  \
                                    int ra, int rb, int rc, int fn11)   \
836 837 838 839 840 841 842 843 844 845 846 847 848
{                                                                       \
    gen_ieee_arith3(ctx, gen_helper_##name, ra, rb, rc, fn11);          \
}
IEEE_ARITH3(adds)
IEEE_ARITH3(subs)
IEEE_ARITH3(muls)
IEEE_ARITH3(divs)
IEEE_ARITH3(addt)
IEEE_ARITH3(subt)
IEEE_ARITH3(mult)
IEEE_ARITH3(divt)

static void gen_ieee_compare(DisasContext *ctx,
849
                             void (*helper)(TCGv, TCGv_ptr, TCGv, TCGv),
850 851
                             int ra, int rb, int rc, int fn11)
{
852
    TCGv va, vb, vc;
853

854 855
    va = gen_ieee_input(ctx, ra, fn11, 1);
    vb = gen_ieee_input(ctx, rb, fn11, 1);
856 857
    vc = dest_fpr(ctx, rc);
    helper(vc, cpu_env, va, vb);
858 859 860 861 862

    gen_fp_exc_raise(rc, fn11);
}

#define IEEE_CMP3(name)                                                 \
863 864
static inline void glue(gen_, name)(DisasContext *ctx,                  \
                                    int ra, int rb, int rc, int fn11)   \
865 866 867 868 869 870 871
{                                                                       \
    gen_ieee_compare(ctx, gen_helper_##name, ra, rb, rc, fn11);         \
}
IEEE_CMP3(cmptun)
IEEE_CMP3(cmpteq)
IEEE_CMP3(cmptlt)
IEEE_CMP3(cmptle)
P
pbrook 已提交
872

873 874 875 876 877 878
static inline uint64_t zapnot_mask(uint8_t lit)
{
    uint64_t mask = 0;
    int i;

    for (i = 0; i < 8; ++i) {
P
Paolo Bonzini 已提交
879
        if ((lit >> i) & 1) {
880
            mask |= 0xffull << (i * 8);
P
Paolo Bonzini 已提交
881
        }
882 883 884 885
    }
    return mask;
}

886 887 888
/* Implement zapnot with an immediate operand, which expands to some
   form of immediate AND.  This is a basic building block in the
   definition of many of the other byte manipulation instructions.  */
889
static void gen_zapnoti(TCGv dest, TCGv src, uint8_t lit)
890 891 892
{
    switch (lit) {
    case 0x00:
893
        tcg_gen_movi_i64(dest, 0);
894 895
        break;
    case 0x01:
896
        tcg_gen_ext8u_i64(dest, src);
897 898
        break;
    case 0x03:
899
        tcg_gen_ext16u_i64(dest, src);
900 901
        break;
    case 0x0f:
902
        tcg_gen_ext32u_i64(dest, src);
903 904
        break;
    case 0xff:
905
        tcg_gen_mov_i64(dest, src);
906 907
        break;
    default:
908
        tcg_gen_andi_i64(dest, src, zapnot_mask(lit));
909 910 911 912
        break;
    }
}

913
/* EXTWH, EXTLH, EXTQH */
914
static void gen_ext_h(DisasContext *ctx, TCGv vc, TCGv va, int rb, bool islit,
915
                      uint8_t lit, uint8_t byte_mask)
916
{
917 918
    if (islit) {
        tcg_gen_shli_i64(vc, va, (64 - lit * 8) & 0x3f);
P
Paolo Bonzini 已提交
919
    } else {
920 921 922 923 924 925
        TCGv tmp = tcg_temp_new();
        tcg_gen_shli_i64(tmp, load_gpr(ctx, rb), 3);
        tcg_gen_neg_i64(tmp, tmp);
        tcg_gen_andi_i64(tmp, tmp, 0x3f);
        tcg_gen_shl_i64(vc, va, tmp);
        tcg_temp_free(tmp);
926
    }
927
    gen_zapnoti(vc, vc, byte_mask);
928 929
}

930
/* EXTBL, EXTWL, EXTLL, EXTQL */
931
static void gen_ext_l(DisasContext *ctx, TCGv vc, TCGv va, int rb, bool islit,
932
                      uint8_t lit, uint8_t byte_mask)
933
{
934 935
    if (islit) {
        tcg_gen_shri_i64(vc, va, (lit & 7) * 8);
P
Paolo Bonzini 已提交
936
    } else {
937 938 939 940 941
        TCGv tmp = tcg_temp_new();
        tcg_gen_andi_i64(tmp, load_gpr(ctx, rb), 7);
        tcg_gen_shli_i64(tmp, tmp, 3);
        tcg_gen_shr_i64(vc, va, tmp);
        tcg_temp_free(tmp);
942
    }
943
    gen_zapnoti(vc, vc, byte_mask);
944 945
}

946
/* INSWH, INSLH, INSQH */
947
static void gen_ins_h(DisasContext *ctx, TCGv vc, TCGv va, int rb, bool islit,
948 949
                      uint8_t lit, uint8_t byte_mask)
{
950
    TCGv tmp = tcg_temp_new();
951

952 953 954 955
    /* The instruction description has us left-shift the byte mask and extract
       bits <15:8> and apply that zap at the end.  This is equivalent to simply
       performing the zap first and shifting afterward.  */
    gen_zapnoti(tmp, va, byte_mask);
956

957 958 959 960
    if (islit) {
        lit &= 7;
        if (unlikely(lit == 0)) {
            tcg_gen_movi_i64(vc, 0);
961
        } else {
962
            tcg_gen_shri_i64(vc, tmp, 64 - lit * 8);
963
        }
964 965 966 967 968 969 970 971 972 973 974 975 976 977 978
    } else {
        TCGv shift = tcg_temp_new();

        /* If (B & 7) == 0, we need to shift by 64 and leave a zero.  Do this
           portably by splitting the shift into two parts: shift_count-1 and 1.
           Arrange for the -1 by using ones-complement instead of
           twos-complement in the negation: ~(B * 8) & 63.  */

        tcg_gen_shli_i64(shift, load_gpr(ctx, rb), 3);
        tcg_gen_not_i64(shift, shift);
        tcg_gen_andi_i64(shift, shift, 0x3f);

        tcg_gen_shr_i64(vc, tmp, shift);
        tcg_gen_shri_i64(vc, vc, 1);
        tcg_temp_free(shift);
979
    }
980
    tcg_temp_free(tmp);
981 982
}

983
/* INSBL, INSWL, INSLL, INSQL */
984
static void gen_ins_l(DisasContext *ctx, TCGv vc, TCGv va, int rb, bool islit,
985
                      uint8_t lit, uint8_t byte_mask)
986
{
987
    TCGv tmp = tcg_temp_new();
988

989 990 991 992 993
    /* The instruction description has us left-shift the byte mask
       the same number of byte slots as the data and apply the zap
       at the end.  This is equivalent to simply performing the zap
       first and shifting afterward.  */
    gen_zapnoti(tmp, va, byte_mask);
994

995 996 997 998 999 1000 1001 1002
    if (islit) {
        tcg_gen_shli_i64(vc, tmp, (lit & 7) * 8);
    } else {
        TCGv shift = tcg_temp_new();
        tcg_gen_andi_i64(shift, load_gpr(ctx, rb), 7);
        tcg_gen_shli_i64(shift, shift, 3);
        tcg_gen_shl_i64(vc, tmp, shift);
        tcg_temp_free(shift);
1003
    }
1004
    tcg_temp_free(tmp);
1005 1006
}

1007
/* MSKWH, MSKLH, MSKQH */
1008
static void gen_msk_h(DisasContext *ctx, TCGv vc, TCGv va, int rb, bool islit,
1009 1010
                      uint8_t lit, uint8_t byte_mask)
{
1011 1012
    if (islit) {
        gen_zapnoti(vc, va, ~((byte_mask << (lit & 7)) >> 8));
1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023
    } else {
        TCGv shift = tcg_temp_new();
        TCGv mask = tcg_temp_new();

        /* The instruction description is as above, where the byte_mask
           is shifted left, and then we extract bits <15:8>.  This can be
           emulated with a right-shift on the expanded byte mask.  This
           requires extra care because for an input <2:0> == 0 we need a
           shift of 64 bits in order to generate a zero.  This is done by
           splitting the shift into two parts, the variable shift - 1
           followed by a constant 1 shift.  The code we expand below is
1024
           equivalent to ~(B * 8) & 63.  */
1025

1026
        tcg_gen_shli_i64(shift, load_gpr(ctx, rb), 3);
1027 1028 1029 1030 1031 1032
        tcg_gen_not_i64(shift, shift);
        tcg_gen_andi_i64(shift, shift, 0x3f);
        tcg_gen_movi_i64(mask, zapnot_mask (byte_mask));
        tcg_gen_shr_i64(mask, mask, shift);
        tcg_gen_shri_i64(mask, mask, 1);

1033
        tcg_gen_andc_i64(vc, va, mask);
1034 1035 1036 1037 1038 1039

        tcg_temp_free(mask);
        tcg_temp_free(shift);
    }
}

1040
/* MSKBL, MSKWL, MSKLL, MSKQL */
1041
static void gen_msk_l(DisasContext *ctx, TCGv vc, TCGv va, int rb, bool islit,
1042
                      uint8_t lit, uint8_t byte_mask)
1043
{
1044 1045
    if (islit) {
        gen_zapnoti(vc, va, ~(byte_mask << (lit & 7)));
1046 1047 1048 1049
    } else {
        TCGv shift = tcg_temp_new();
        TCGv mask = tcg_temp_new();

1050
        tcg_gen_andi_i64(shift, load_gpr(ctx, rb), 7);
1051
        tcg_gen_shli_i64(shift, shift, 3);
1052
        tcg_gen_movi_i64(mask, zapnot_mask(byte_mask));
1053 1054
        tcg_gen_shl_i64(mask, mask, shift);

1055
        tcg_gen_andc_i64(vc, va, mask);
1056 1057 1058 1059 1060 1061

        tcg_temp_free(mask);
        tcg_temp_free(shift);
    }
}

1062 1063 1064 1065 1066
static void gen_rx(int ra, int set)
{
    TCGv_i32 tmp;

    if (ra != 31) {
1067
        tcg_gen_ld8u_i64(cpu_ir[ra], cpu_env, offsetof(CPUAlphaState, intr_flag));
1068 1069 1070
    }

    tmp = tcg_const_i32(set);
1071
    tcg_gen_st8_i32(tmp, cpu_env, offsetof(CPUAlphaState, intr_flag));
1072 1073 1074
    tcg_temp_free_i32(tmp);
}

1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088
static ExitStatus gen_call_pal(DisasContext *ctx, int palcode)
{
    /* We're emulating OSF/1 PALcode.  Many of these are trivial access
       to internal cpu registers.  */

    /* Unprivileged PAL call */
    if (palcode >= 0x80 && palcode < 0xC0) {
        switch (palcode) {
        case 0x86:
            /* IMB */
            /* No-op inside QEMU.  */
            break;
        case 0x9E:
            /* RDUNIQUE */
1089 1090
            tcg_gen_ld_i64(cpu_ir[IR_V0], cpu_env,
                           offsetof(CPUAlphaState, unique));
1091 1092 1093
            break;
        case 0x9F:
            /* WRUNIQUE */
1094 1095
            tcg_gen_st_i64(cpu_ir[IR_A0], cpu_env,
                           offsetof(CPUAlphaState, unique));
1096 1097
            break;
        default:
1098 1099
            palcode &= 0xbf;
            goto do_call_pal;
1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117
        }
        return NO_EXIT;
    }

#ifndef CONFIG_USER_ONLY
    /* Privileged PAL code */
    if (palcode < 0x40 && (ctx->tb->flags & TB_FLAGS_USER_MODE) == 0) {
        switch (palcode) {
        case 0x01:
            /* CFLUSH */
            /* No-op inside QEMU.  */
            break;
        case 0x02:
            /* DRAINA */
            /* No-op inside QEMU.  */
            break;
        case 0x2D:
            /* WRVPTPTR */
1118 1119
            tcg_gen_st_i64(cpu_ir[IR_A0], cpu_env,
                           offsetof(CPUAlphaState, vptptr));
1120 1121 1122
            break;
        case 0x31:
            /* WRVAL */
1123 1124
            tcg_gen_st_i64(cpu_ir[IR_A0], cpu_env,
                           offsetof(CPUAlphaState, sysval));
1125 1126 1127
            break;
        case 0x32:
            /* RDVAL */
1128 1129
            tcg_gen_ld_i64(cpu_ir[IR_V0], cpu_env,
                           offsetof(CPUAlphaState, sysval));
1130 1131 1132 1133 1134 1135 1136 1137
            break;

        case 0x35: {
            /* SWPIPL */
            TCGv tmp;

            /* Note that we already know we're in kernel mode, so we know
               that PS only contains the 3 IPL bits.  */
1138 1139
            tcg_gen_ld8u_i64(cpu_ir[IR_V0], cpu_env,
                             offsetof(CPUAlphaState, ps));
1140 1141 1142 1143

            /* But make sure and store only the 3 IPL bits from the user.  */
            tmp = tcg_temp_new();
            tcg_gen_andi_i64(tmp, cpu_ir[IR_A0], PS_INT_MASK);
1144
            tcg_gen_st8_i64(tmp, cpu_env, offsetof(CPUAlphaState, ps));
1145 1146 1147 1148 1149 1150
            tcg_temp_free(tmp);
            break;
        }

        case 0x36:
            /* RDPS */
1151 1152
            tcg_gen_ld8u_i64(cpu_ir[IR_V0], cpu_env,
                             offsetof(CPUAlphaState, ps));
1153 1154 1155
            break;
        case 0x38:
            /* WRUSP */
1156 1157
            tcg_gen_st_i64(cpu_ir[IR_A0], cpu_env,
                           offsetof(CPUAlphaState, usp));
1158 1159 1160
            break;
        case 0x3A:
            /* RDUSP */
R
Richard Henderson 已提交
1161
            tcg_gen_ld_i64(cpu_ir[IR_V0], cpu_env,
1162
                           offsetof(CPUAlphaState, usp));
1163 1164 1165 1166
            break;
        case 0x3C:
            /* WHAMI */
            tcg_gen_ld32s_i64(cpu_ir[IR_V0], cpu_env,
1167
                -offsetof(AlphaCPU, env) + offsetof(CPUState, cpu_index));
1168 1169 1170
            break;

        default:
1171 1172
            palcode &= 0x3f;
            goto do_call_pal;
1173 1174 1175 1176 1177
        }
        return NO_EXIT;
    }
#endif
    return gen_invalid(ctx);
1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192

 do_call_pal:
#ifdef CONFIG_USER_ONLY
    return gen_excp(ctx, EXCP_CALL_PAL, palcode);
#else
    {
        TCGv pc = tcg_const_i64(ctx->pc);
        TCGv entry = tcg_const_i64(palcode & 0x80
                                   ? 0x2000 + (palcode - 0x80) * 64
                                   : 0x1000 + palcode * 64);

        gen_helper_call_pal(cpu_env, pc, entry);

        tcg_temp_free(entry);
        tcg_temp_free(pc);
1193 1194

        /* Since the destination is running in PALmode, we don't really
S
Stefan Weil 已提交
1195
           need the page permissions check.  We'll see the existence of
1196 1197 1198 1199
           the page when we create the TB, and we'll flush all TBs if
           we change the PAL base register.  */
        if (!ctx->singlestep_enabled && !(ctx->tb->cflags & CF_LAST_IO)) {
            tcg_gen_goto_tb(0);
1200
            tcg_gen_exit_tb((uintptr_t)ctx->tb);
1201 1202 1203
            return EXIT_GOTO_TB;
        }

1204 1205 1206
        return EXIT_PC_UPDATED;
    }
#endif
1207 1208
}

1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234
#ifndef CONFIG_USER_ONLY

#define PR_BYTE         0x100000
#define PR_LONG         0x200000

static int cpu_pr_data(int pr)
{
    switch (pr) {
    case  0: return offsetof(CPUAlphaState, ps) | PR_BYTE;
    case  1: return offsetof(CPUAlphaState, fen) | PR_BYTE;
    case  2: return offsetof(CPUAlphaState, pcc_ofs) | PR_LONG;
    case  3: return offsetof(CPUAlphaState, trap_arg0);
    case  4: return offsetof(CPUAlphaState, trap_arg1);
    case  5: return offsetof(CPUAlphaState, trap_arg2);
    case  6: return offsetof(CPUAlphaState, exc_addr);
    case  7: return offsetof(CPUAlphaState, palbr);
    case  8: return offsetof(CPUAlphaState, ptbr);
    case  9: return offsetof(CPUAlphaState, vptptr);
    case 10: return offsetof(CPUAlphaState, unique);
    case 11: return offsetof(CPUAlphaState, sysval);
    case 12: return offsetof(CPUAlphaState, usp);

    case 32 ... 39:
        return offsetof(CPUAlphaState, shadow[pr - 32]);
    case 40 ... 63:
        return offsetof(CPUAlphaState, scratch[pr - 40]);
1235 1236 1237

    case 251:
        return offsetof(CPUAlphaState, alarm_expire);
1238 1239 1240 1241
    }
    return 0;
}

1242
static ExitStatus gen_mfpr(DisasContext *ctx, TCGv va, int regno)
1243 1244 1245
{
    int data = cpu_pr_data(regno);

1246 1247 1248 1249 1250 1251
    /* Special help for VMTIME and WALLTIME.  */
    if (regno == 250 || regno == 249) {
	void (*helper)(TCGv) = gen_helper_get_walltime;
	if (regno == 249) {
		helper = gen_helper_get_vmtime;
	}
1252
        if (ctx->tb->cflags & CF_USE_ICOUNT) {
1253
            gen_io_start();
1254
            helper(va);
1255 1256 1257
            gen_io_end();
            return EXIT_PC_STALE;
        } else {
1258
            helper(va);
1259 1260
            return NO_EXIT;
        }
1261 1262 1263 1264 1265
    }

    /* The basic registers are data only, and unknown registers
       are read-zero, write-ignore.  */
    if (data == 0) {
1266
        tcg_gen_movi_i64(va, 0);
1267
    } else if (data & PR_BYTE) {
1268
        tcg_gen_ld8u_i64(va, cpu_env, data & ~PR_BYTE);
1269
    } else if (data & PR_LONG) {
1270
        tcg_gen_ld32s_i64(va, cpu_env, data & ~PR_LONG);
1271
    } else {
1272
        tcg_gen_ld_i64(va, cpu_env, data);
1273
    }
1274
    return NO_EXIT;
1275 1276
}

1277
static ExitStatus gen_mtpr(DisasContext *ctx, TCGv vb, int regno)
1278 1279
{
    TCGv tmp;
1280
    int data;
1281

1282 1283
    switch (regno) {
    case 255:
1284
        /* TBIA */
1285
        gen_helper_tbia(cpu_env);
1286 1287 1288
        break;

    case 254:
1289
        /* TBIS */
1290
        gen_helper_tbis(cpu_env, vb);
1291 1292 1293 1294 1295
        break;

    case 253:
        /* WAIT */
        tmp = tcg_const_i64(1);
1296 1297
        tcg_gen_st32_i64(tmp, cpu_env, -offsetof(AlphaCPU, env) +
                                       offsetof(CPUState, halted));
1298 1299
        return gen_excp(ctx, EXCP_HLT, 0);

1300 1301
    case 252:
        /* HALT */
1302
        gen_helper_halt(vb);
1303 1304
        return EXIT_PC_STALE;

1305 1306
    case 251:
        /* ALARM */
1307
        gen_helper_set_alarm(cpu_env, vb);
1308 1309
        break;

1310 1311
    case 7:
        /* PALBR */
1312
        tcg_gen_st_i64(vb, cpu_env, offsetof(CPUAlphaState, palbr));
1313 1314 1315 1316 1317 1318
        /* Changing the PAL base register implies un-chaining all of the TBs
           that ended with a CALL_PAL.  Since the base register usually only
           changes during boot, flushing everything works well.  */
        gen_helper_tb_flush(cpu_env);
        return EXIT_PC_STALE;

1319
    default:
1320 1321
        /* The basic registers are data only, and unknown registers
           are read-zero, write-ignore.  */
1322
        data = cpu_pr_data(regno);
1323 1324
        if (data != 0) {
            if (data & PR_BYTE) {
1325
                tcg_gen_st8_i64(vb, cpu_env, data & ~PR_BYTE);
1326
            } else if (data & PR_LONG) {
1327
                tcg_gen_st32_i64(vb, cpu_env, data & ~PR_LONG);
1328
            } else {
1329
                tcg_gen_st_i64(vb, cpu_env, data);
1330
            }
1331
        }
1332
        break;
1333 1334
    }

1335
    return NO_EXIT;
1336 1337 1338
}
#endif /* !USER_ONLY*/

1339 1340 1341 1342 1343 1344 1345
#define REQUIRE_NO_LIT                          \
    do {                                        \
        if (real_islit) {                       \
            goto invalid_opc;                   \
        }                                       \
    } while (0)

1346 1347 1348 1349 1350 1351 1352
#define REQUIRE_TB_FLAG(FLAG)                   \
    do {                                        \
        if ((ctx->tb->flags & (FLAG)) == 0) {   \
            goto invalid_opc;                   \
        }                                       \
    } while (0)

1353 1354 1355 1356 1357 1358 1359
#define REQUIRE_REG_31(WHICH)                   \
    do {                                        \
        if (WHICH != 31) {                      \
            goto invalid_opc;                   \
        }                                       \
    } while (0)

1360
static ExitStatus translate_one(DisasContext *ctx, uint32_t insn)
J
j_mayer 已提交
1361
{
1362
    int32_t disp21, disp16, disp12 __attribute__((unused));
1363
    uint16_t fn11;
1364
    uint8_t opc, ra, rb, rc, fpfn, fn7, lit;
1365
    bool islit, real_islit;
1366
    TCGv va, vb, vc, tmp, tmp2;
1367
    TCGv_i32 t32;
1368
    ExitStatus ret;
J
j_mayer 已提交
1369 1370

    /* Decode all instruction fields */
1371 1372 1373 1374
    opc = extract32(insn, 26, 6);
    ra = extract32(insn, 21, 5);
    rb = extract32(insn, 16, 5);
    rc = extract32(insn, 0, 5);
1375
    real_islit = islit = extract32(insn, 12, 1);
1376 1377 1378 1379 1380 1381 1382 1383 1384 1385
    lit = extract32(insn, 13, 8);

    disp21 = sextract32(insn, 0, 21);
    disp16 = sextract32(insn, 0, 16);
    disp12 = sextract32(insn, 0, 12);

    fn11 = extract32(insn, 5, 11);
    fpfn = extract32(insn, 5, 6);
    fn7 = extract32(insn, 5, 7);

1386
    if (rb == 31 && !islit) {
1387
        islit = true;
1388
        lit = 0;
1389
    }
R
Richard Henderson 已提交
1390

1391
    ret = NO_EXIT;
J
j_mayer 已提交
1392 1393 1394
    switch (opc) {
    case 0x00:
        /* CALL_PAL */
1395
        ret = gen_call_pal(ctx, insn & 0x03ffffff);
1396
        break;
J
j_mayer 已提交
1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 1417
    case 0x01:
        /* OPC01 */
        goto invalid_opc;
    case 0x02:
        /* OPC02 */
        goto invalid_opc;
    case 0x03:
        /* OPC03 */
        goto invalid_opc;
    case 0x04:
        /* OPC04 */
        goto invalid_opc;
    case 0x05:
        /* OPC05 */
        goto invalid_opc;
    case 0x06:
        /* OPC06 */
        goto invalid_opc;
    case 0x07:
        /* OPC07 */
        goto invalid_opc;
1418

J
j_mayer 已提交
1419 1420
    case 0x09:
        /* LDAH */
1421 1422 1423 1424 1425 1426 1427 1428 1429 1430
        disp16 = (uint32_t)disp16 << 16;
        /* fall through */
    case 0x08:
        /* LDA */
        va = dest_gpr(ctx, ra);
        /* It's worth special-casing immediate loads.  */
        if (rb == 31) {
            tcg_gen_movi_i64(va, disp16);
        } else {
            tcg_gen_addi_i64(va, load_gpr(ctx, rb), disp16);
A
aurel32 已提交
1431
        }
J
j_mayer 已提交
1432
        break;
1433

J
j_mayer 已提交
1434 1435
    case 0x0A:
        /* LDBU */
1436 1437 1438
        REQUIRE_TB_FLAG(TB_FLAGS_AMASK_BWX);
        gen_load_mem(ctx, &tcg_gen_qemu_ld8u, ra, rb, disp16, 0, 0);
        break;
J
j_mayer 已提交
1439 1440
    case 0x0B:
        /* LDQ_U */
A
aurel32 已提交
1441
        gen_load_mem(ctx, &tcg_gen_qemu_ld64, ra, rb, disp16, 0, 1);
J
j_mayer 已提交
1442 1443 1444
        break;
    case 0x0C:
        /* LDWU */
1445 1446 1447
        REQUIRE_TB_FLAG(TB_FLAGS_AMASK_BWX);
        gen_load_mem(ctx, &tcg_gen_qemu_ld16u, ra, rb, disp16, 0, 0);
        break;
J
j_mayer 已提交
1448 1449
    case 0x0D:
        /* STW */
1450
        REQUIRE_TB_FLAG(TB_FLAGS_AMASK_BWX);
1451
        gen_store_mem(ctx, &tcg_gen_qemu_st16, ra, rb, disp16, 0, 0);
J
j_mayer 已提交
1452 1453 1454
        break;
    case 0x0E:
        /* STB */
1455
        REQUIRE_TB_FLAG(TB_FLAGS_AMASK_BWX);
1456
        gen_store_mem(ctx, &tcg_gen_qemu_st8, ra, rb, disp16, 0, 0);
J
j_mayer 已提交
1457 1458 1459
        break;
    case 0x0F:
        /* STQ_U */
1460
        gen_store_mem(ctx, &tcg_gen_qemu_st64, ra, rb, disp16, 0, 1);
J
j_mayer 已提交
1461
        break;
1462

J
j_mayer 已提交
1463
    case 0x10:
1464 1465 1466 1467 1468 1469 1470 1471 1472 1473 1474 1475 1476 1477 1478 1479 1480
        vc = dest_gpr(ctx, rc);
        vb = load_gpr_lit(ctx, rb, lit, islit);

        if (ra == 31) {
            if (fn7 == 0x00) {
                /* Special case ADDL as SEXTL.  */
                tcg_gen_ext32s_i64(vc, vb);
                break;
            }
            if (fn7 == 0x29) {
                /* Special case SUBQ as NEGQ.  */
                tcg_gen_neg_i64(vc, vb);
                break;
            }
        }

        va = load_gpr(ctx, ra);
J
j_mayer 已提交
1481 1482 1483
        switch (fn7) {
        case 0x00:
            /* ADDL */
1484 1485
            tcg_gen_add_i64(vc, va, vb);
            tcg_gen_ext32s_i64(vc, vc);
J
j_mayer 已提交
1486 1487 1488
            break;
        case 0x02:
            /* S4ADDL */
1489 1490 1491 1492 1493
            tmp = tcg_temp_new();
            tcg_gen_shli_i64(tmp, va, 2);
            tcg_gen_add_i64(tmp, tmp, vb);
            tcg_gen_ext32s_i64(vc, tmp);
            tcg_temp_free(tmp);
J
j_mayer 已提交
1494 1495 1496
            break;
        case 0x09:
            /* SUBL */
1497 1498
            tcg_gen_sub_i64(vc, va, vb);
            tcg_gen_ext32s_i64(vc, vc);
J
j_mayer 已提交
1499 1500 1501
            break;
        case 0x0B:
            /* S4SUBL */
1502 1503 1504 1505 1506
            tmp = tcg_temp_new();
            tcg_gen_shli_i64(tmp, va, 2);
            tcg_gen_sub_i64(tmp, tmp, vb);
            tcg_gen_ext32s_i64(vc, tmp);
            tcg_temp_free(tmp);
J
j_mayer 已提交
1507 1508 1509
            break;
        case 0x0F:
            /* CMPBGE */
1510
            gen_helper_cmpbge(vc, va, vb);
J
j_mayer 已提交
1511 1512 1513
            break;
        case 0x12:
            /* S8ADDL */
1514 1515 1516 1517 1518
            tmp = tcg_temp_new();
            tcg_gen_shli_i64(tmp, va, 3);
            tcg_gen_add_i64(tmp, tmp, vb);
            tcg_gen_ext32s_i64(vc, tmp);
            tcg_temp_free(tmp);
J
j_mayer 已提交
1519 1520 1521
            break;
        case 0x1B:
            /* S8SUBL */
1522 1523 1524 1525 1526
            tmp = tcg_temp_new();
            tcg_gen_shli_i64(tmp, va, 3);
            tcg_gen_sub_i64(tmp, tmp, vb);
            tcg_gen_ext32s_i64(vc, tmp);
            tcg_temp_free(tmp);
J
j_mayer 已提交
1527 1528 1529
            break;
        case 0x1D:
            /* CMPULT */
1530
            tcg_gen_setcond_i64(TCG_COND_LTU, vc, va, vb);
J
j_mayer 已提交
1531 1532 1533
            break;
        case 0x20:
            /* ADDQ */
1534
            tcg_gen_add_i64(vc, va, vb);
J
j_mayer 已提交
1535 1536 1537
            break;
        case 0x22:
            /* S4ADDQ */
1538 1539 1540 1541
            tmp = tcg_temp_new();
            tcg_gen_shli_i64(tmp, va, 2);
            tcg_gen_add_i64(vc, tmp, vb);
            tcg_temp_free(tmp);
J
j_mayer 已提交
1542 1543 1544
            break;
        case 0x29:
            /* SUBQ */
1545
            tcg_gen_sub_i64(vc, va, vb);
J
j_mayer 已提交
1546 1547 1548
            break;
        case 0x2B:
            /* S4SUBQ */
1549 1550 1551 1552
            tmp = tcg_temp_new();
            tcg_gen_shli_i64(tmp, va, 2);
            tcg_gen_sub_i64(vc, tmp, vb);
            tcg_temp_free(tmp);
J
j_mayer 已提交
1553 1554 1555
            break;
        case 0x2D:
            /* CMPEQ */
1556
            tcg_gen_setcond_i64(TCG_COND_EQ, vc, va, vb);
J
j_mayer 已提交
1557 1558 1559
            break;
        case 0x32:
            /* S8ADDQ */
1560 1561 1562 1563
            tmp = tcg_temp_new();
            tcg_gen_shli_i64(tmp, va, 3);
            tcg_gen_add_i64(vc, tmp, vb);
            tcg_temp_free(tmp);
J
j_mayer 已提交
1564 1565 1566
            break;
        case 0x3B:
            /* S8SUBQ */
1567 1568 1569 1570
            tmp = tcg_temp_new();
            tcg_gen_shli_i64(tmp, va, 3);
            tcg_gen_sub_i64(vc, tmp, vb);
            tcg_temp_free(tmp);
J
j_mayer 已提交
1571 1572 1573
            break;
        case 0x3D:
            /* CMPULE */
1574
            tcg_gen_setcond_i64(TCG_COND_LEU, vc, va, vb);
J
j_mayer 已提交
1575 1576 1577
            break;
        case 0x40:
            /* ADDL/V */
1578 1579 1580 1581 1582 1583 1584
            tmp = tcg_temp_new();
            tcg_gen_ext32s_i64(tmp, va);
            tcg_gen_ext32s_i64(vc, vb);
            tcg_gen_add_i64(tmp, tmp, vc);
            tcg_gen_ext32s_i64(vc, tmp);
            gen_helper_check_overflow(cpu_env, vc, tmp);
            tcg_temp_free(tmp);
J
j_mayer 已提交
1585 1586 1587
            break;
        case 0x49:
            /* SUBL/V */
1588 1589 1590 1591 1592 1593 1594
            tmp = tcg_temp_new();
            tcg_gen_ext32s_i64(tmp, va);
            tcg_gen_ext32s_i64(vc, vb);
            tcg_gen_sub_i64(tmp, tmp, vc);
            tcg_gen_ext32s_i64(vc, tmp);
            gen_helper_check_overflow(cpu_env, vc, tmp);
            tcg_temp_free(tmp);
J
j_mayer 已提交
1595 1596 1597
            break;
        case 0x4D:
            /* CMPLT */
1598
            tcg_gen_setcond_i64(TCG_COND_LT, vc, va, vb);
J
j_mayer 已提交
1599 1600 1601
            break;
        case 0x60:
            /* ADDQ/V */
1602 1603 1604 1605 1606 1607 1608 1609 1610 1611 1612 1613
            tmp = tcg_temp_new();
            tmp2 = tcg_temp_new();
            tcg_gen_eqv_i64(tmp, va, vb);
            tcg_gen_mov_i64(tmp2, va);
            tcg_gen_add_i64(vc, va, vb);
            tcg_gen_xor_i64(tmp2, tmp2, vc);
            tcg_gen_and_i64(tmp, tmp, tmp2);
            tcg_gen_shri_i64(tmp, tmp, 63);
            tcg_gen_movi_i64(tmp2, 0);
            gen_helper_check_overflow(cpu_env, tmp, tmp2);
            tcg_temp_free(tmp);
            tcg_temp_free(tmp2);
J
j_mayer 已提交
1614 1615 1616
            break;
        case 0x69:
            /* SUBQ/V */
1617 1618 1619 1620 1621 1622 1623 1624 1625 1626 1627 1628
            tmp = tcg_temp_new();
            tmp2 = tcg_temp_new();
            tcg_gen_xor_i64(tmp, va, vb);
            tcg_gen_mov_i64(tmp2, va);
            tcg_gen_sub_i64(vc, va, vb);
            tcg_gen_xor_i64(tmp2, tmp2, vc);
            tcg_gen_and_i64(tmp, tmp, tmp2);
            tcg_gen_shri_i64(tmp, tmp, 63);
            tcg_gen_movi_i64(tmp2, 0);
            gen_helper_check_overflow(cpu_env, tmp, tmp2);
            tcg_temp_free(tmp);
            tcg_temp_free(tmp2);
J
j_mayer 已提交
1629 1630 1631
            break;
        case 0x6D:
            /* CMPLE */
1632
            tcg_gen_setcond_i64(TCG_COND_LE, vc, va, vb);
J
j_mayer 已提交
1633 1634 1635 1636 1637
            break;
        default:
            goto invalid_opc;
        }
        break;
1638

J
j_mayer 已提交
1639
    case 0x11:
1640 1641 1642 1643 1644 1645 1646 1647 1648 1649
        if (fn7 == 0x20) {
            if (rc == 31) {
                /* Special case BIS as NOP.  */
                break;
            }
            if (ra == 31) {
                /* Special case BIS as MOV.  */
                vc = dest_gpr(ctx, rc);
                if (islit) {
                    tcg_gen_movi_i64(vc, lit);
P
Paolo Bonzini 已提交
1650
                } else {
1651
                    tcg_gen_mov_i64(vc, load_gpr(ctx, rb));
P
Paolo Bonzini 已提交
1652
                }
1653
                break;
1654
            }
1655 1656 1657 1658 1659 1660 1661 1662 1663 1664 1665 1666 1667 1668 1669 1670
        }

        vc = dest_gpr(ctx, rc);
        vb = load_gpr_lit(ctx, rb, lit, islit);

        if (fn7 == 0x28 && ra == 31) {
            /* Special case ORNOT as NOT.  */
            tcg_gen_not_i64(vc, vb);
            break;
        }

        va = load_gpr(ctx, ra);
        switch (fn7) {
        case 0x00:
            /* AND */
            tcg_gen_and_i64(vc, va, vb);
J
j_mayer 已提交
1671 1672 1673
            break;
        case 0x08:
            /* BIC */
1674
            tcg_gen_andc_i64(vc, va, vb);
J
j_mayer 已提交
1675 1676 1677
            break;
        case 0x14:
            /* CMOVLBS */
1678 1679 1680 1681 1682
            tmp = tcg_temp_new();
            tcg_gen_andi_i64(tmp, va, 1);
            tcg_gen_movcond_i64(TCG_COND_NE, vc, tmp, load_zero(ctx),
                                vb, load_gpr(ctx, rc));
            tcg_temp_free(tmp);
J
j_mayer 已提交
1683 1684 1685
            break;
        case 0x16:
            /* CMOVLBC */
1686 1687 1688 1689 1690
            tmp = tcg_temp_new();
            tcg_gen_andi_i64(tmp, va, 1);
            tcg_gen_movcond_i64(TCG_COND_EQ, vc, tmp, load_zero(ctx),
                                vb, load_gpr(ctx, rc));
            tcg_temp_free(tmp);
J
j_mayer 已提交
1691 1692 1693
            break;
        case 0x20:
            /* BIS */
1694
            tcg_gen_or_i64(vc, va, vb);
J
j_mayer 已提交
1695 1696 1697
            break;
        case 0x24:
            /* CMOVEQ */
1698 1699
            tcg_gen_movcond_i64(TCG_COND_EQ, vc, va, load_zero(ctx),
                                vb, load_gpr(ctx, rc));
J
j_mayer 已提交
1700 1701 1702
            break;
        case 0x26:
            /* CMOVNE */
1703 1704
            tcg_gen_movcond_i64(TCG_COND_NE, vc, va, load_zero(ctx),
                                vb, load_gpr(ctx, rc));
J
j_mayer 已提交
1705 1706 1707
            break;
        case 0x28:
            /* ORNOT */
1708
            tcg_gen_orc_i64(vc, va, vb);
J
j_mayer 已提交
1709 1710 1711
            break;
        case 0x40:
            /* XOR */
1712
            tcg_gen_xor_i64(vc, va, vb);
J
j_mayer 已提交
1713 1714 1715
            break;
        case 0x44:
            /* CMOVLT */
1716 1717
            tcg_gen_movcond_i64(TCG_COND_LT, vc, va, load_zero(ctx),
                                vb, load_gpr(ctx, rc));
J
j_mayer 已提交
1718 1719 1720
            break;
        case 0x46:
            /* CMOVGE */
1721 1722
            tcg_gen_movcond_i64(TCG_COND_GE, vc, va, load_zero(ctx),
                                vb, load_gpr(ctx, rc));
J
j_mayer 已提交
1723 1724 1725
            break;
        case 0x48:
            /* EQV */
1726
            tcg_gen_eqv_i64(vc, va, vb);
J
j_mayer 已提交
1727 1728 1729
            break;
        case 0x61:
            /* AMASK */
1730
            REQUIRE_REG_31(ra);
1731
            {
1732
                uint64_t amask = ctx->tb->flags >> TB_FLAGS_AMASK_SHIFT;
1733
                tcg_gen_andi_i64(vc, vb, ~amask);
1734
            }
J
j_mayer 已提交
1735 1736 1737
            break;
        case 0x64:
            /* CMOVLE */
1738 1739
            tcg_gen_movcond_i64(TCG_COND_LE, vc, va, load_zero(ctx),
                                vb, load_gpr(ctx, rc));
J
j_mayer 已提交
1740 1741 1742
            break;
        case 0x66:
            /* CMOVGT */
1743 1744
            tcg_gen_movcond_i64(TCG_COND_GT, vc, va, load_zero(ctx),
                                vb, load_gpr(ctx, rc));
J
j_mayer 已提交
1745 1746 1747
            break;
        case 0x6C:
            /* IMPLVER */
1748
            REQUIRE_REG_31(ra);
1749
            tcg_gen_movi_i64(vc, ctx->implver);
J
j_mayer 已提交
1750 1751 1752 1753 1754
            break;
        default:
            goto invalid_opc;
        }
        break;
1755

J
j_mayer 已提交
1756
    case 0x12:
1757 1758
        vc = dest_gpr(ctx, rc);
        va = load_gpr(ctx, ra);
J
j_mayer 已提交
1759 1760 1761
        switch (fn7) {
        case 0x02:
            /* MSKBL */
1762
            gen_msk_l(ctx, vc, va, rb, islit, lit, 0x01);
J
j_mayer 已提交
1763 1764 1765
            break;
        case 0x06:
            /* EXTBL */
1766
            gen_ext_l(ctx, vc, va, rb, islit, lit, 0x01);
J
j_mayer 已提交
1767 1768 1769
            break;
        case 0x0B:
            /* INSBL */
1770
            gen_ins_l(ctx, vc, va, rb, islit, lit, 0x01);
J
j_mayer 已提交
1771 1772 1773
            break;
        case 0x12:
            /* MSKWL */
1774
            gen_msk_l(ctx, vc, va, rb, islit, lit, 0x03);
J
j_mayer 已提交
1775 1776 1777
            break;
        case 0x16:
            /* EXTWL */
1778
            gen_ext_l(ctx, vc, va, rb, islit, lit, 0x03);
J
j_mayer 已提交
1779 1780 1781
            break;
        case 0x1B:
            /* INSWL */
1782
            gen_ins_l(ctx, vc, va, rb, islit, lit, 0x03);
J
j_mayer 已提交
1783 1784 1785
            break;
        case 0x22:
            /* MSKLL */
1786
            gen_msk_l(ctx, vc, va, rb, islit, lit, 0x0f);
J
j_mayer 已提交
1787 1788 1789
            break;
        case 0x26:
            /* EXTLL */
1790
            gen_ext_l(ctx, vc, va, rb, islit, lit, 0x0f);
J
j_mayer 已提交
1791 1792 1793
            break;
        case 0x2B:
            /* INSLL */
1794
            gen_ins_l(ctx, vc, va, rb, islit, lit, 0x0f);
J
j_mayer 已提交
1795 1796 1797
            break;
        case 0x30:
            /* ZAP */
1798 1799 1800 1801 1802
            if (islit) {
                gen_zapnoti(vc, va, ~lit);
            } else {
                gen_helper_zap(vc, va, load_gpr(ctx, rb));
            }
J
j_mayer 已提交
1803 1804 1805
            break;
        case 0x31:
            /* ZAPNOT */
1806 1807 1808 1809 1810
            if (islit) {
                gen_zapnoti(vc, va, lit);
            } else {
                gen_helper_zapnot(vc, va, load_gpr(ctx, rb));
            }
J
j_mayer 已提交
1811 1812 1813
            break;
        case 0x32:
            /* MSKQL */
1814
            gen_msk_l(ctx, vc, va, rb, islit, lit, 0xff);
J
j_mayer 已提交
1815 1816 1817
            break;
        case 0x34:
            /* SRL */
1818 1819 1820 1821 1822 1823 1824 1825
            if (islit) {
                tcg_gen_shri_i64(vc, va, lit & 0x3f);
            } else {
                tmp = tcg_temp_new();
                vb = load_gpr(ctx, rb);
                tcg_gen_andi_i64(tmp, vb, 0x3f);
                tcg_gen_shr_i64(vc, va, tmp);
                tcg_temp_free(tmp);
1826
            }
J
j_mayer 已提交
1827 1828 1829
            break;
        case 0x36:
            /* EXTQL */
1830
            gen_ext_l(ctx, vc, va, rb, islit, lit, 0xff);
J
j_mayer 已提交
1831 1832 1833
            break;
        case 0x39:
            /* SLL */
1834 1835 1836 1837 1838 1839 1840 1841
            if (islit) {
                tcg_gen_shli_i64(vc, va, lit & 0x3f);
            } else {
                tmp = tcg_temp_new();
                vb = load_gpr(ctx, rb);
                tcg_gen_andi_i64(tmp, vb, 0x3f);
                tcg_gen_shl_i64(vc, va, tmp);
                tcg_temp_free(tmp);
1842
            }
J
j_mayer 已提交
1843 1844 1845
            break;
        case 0x3B:
            /* INSQL */
1846
            gen_ins_l(ctx, vc, va, rb, islit, lit, 0xff);
J
j_mayer 已提交
1847 1848 1849
            break;
        case 0x3C:
            /* SRA */
1850 1851 1852 1853 1854 1855 1856 1857
            if (islit) {
                tcg_gen_sari_i64(vc, va, lit & 0x3f);
            } else {
                tmp = tcg_temp_new();
                vb = load_gpr(ctx, rb);
                tcg_gen_andi_i64(tmp, vb, 0x3f);
                tcg_gen_sar_i64(vc, va, tmp);
                tcg_temp_free(tmp);
1858
            }
J
j_mayer 已提交
1859 1860 1861
            break;
        case 0x52:
            /* MSKWH */
1862
            gen_msk_h(ctx, vc, va, rb, islit, lit, 0x03);
J
j_mayer 已提交
1863 1864 1865
            break;
        case 0x57:
            /* INSWH */
1866
            gen_ins_h(ctx, vc, va, rb, islit, lit, 0x03);
J
j_mayer 已提交
1867 1868 1869
            break;
        case 0x5A:
            /* EXTWH */
1870
            gen_ext_h(ctx, vc, va, rb, islit, lit, 0x03);
J
j_mayer 已提交
1871 1872 1873
            break;
        case 0x62:
            /* MSKLH */
1874
            gen_msk_h(ctx, vc, va, rb, islit, lit, 0x0f);
J
j_mayer 已提交
1875 1876 1877
            break;
        case 0x67:
            /* INSLH */
1878
            gen_ins_h(ctx, vc, va, rb, islit, lit, 0x0f);
J
j_mayer 已提交
1879 1880 1881
            break;
        case 0x6A:
            /* EXTLH */
1882
            gen_ext_h(ctx, vc, va, rb, islit, lit, 0x0f);
J
j_mayer 已提交
1883 1884 1885
            break;
        case 0x72:
            /* MSKQH */
1886
            gen_msk_h(ctx, vc, va, rb, islit, lit, 0xff);
J
j_mayer 已提交
1887 1888 1889
            break;
        case 0x77:
            /* INSQH */
1890
            gen_ins_h(ctx, vc, va, rb, islit, lit, 0xff);
J
j_mayer 已提交
1891 1892 1893
            break;
        case 0x7A:
            /* EXTQH */
1894
            gen_ext_h(ctx, vc, va, rb, islit, lit, 0xff);
J
j_mayer 已提交
1895 1896 1897 1898 1899
            break;
        default:
            goto invalid_opc;
        }
        break;
1900

J
j_mayer 已提交
1901
    case 0x13:
1902 1903 1904
        vc = dest_gpr(ctx, rc);
        vb = load_gpr_lit(ctx, rb, lit, islit);
        va = load_gpr(ctx, ra);
J
j_mayer 已提交
1905 1906 1907
        switch (fn7) {
        case 0x00:
            /* MULL */
1908 1909
            tcg_gen_mul_i64(vc, va, vb);
            tcg_gen_ext32s_i64(vc, vc);
J
j_mayer 已提交
1910 1911 1912
            break;
        case 0x20:
            /* MULQ */
1913
            tcg_gen_mul_i64(vc, va, vb);
J
j_mayer 已提交
1914 1915 1916
            break;
        case 0x30:
            /* UMULH */
1917 1918 1919
            tmp = tcg_temp_new();
            tcg_gen_mulu2_i64(tmp, vc, va, vb);
            tcg_temp_free(tmp);
J
j_mayer 已提交
1920 1921 1922
            break;
        case 0x40:
            /* MULL/V */
1923 1924 1925 1926 1927 1928 1929
            tmp = tcg_temp_new();
            tcg_gen_ext32s_i64(tmp, va);
            tcg_gen_ext32s_i64(vc, vb);
            tcg_gen_mul_i64(tmp, tmp, vc);
            tcg_gen_ext32s_i64(vc, tmp);
            gen_helper_check_overflow(cpu_env, vc, tmp);
            tcg_temp_free(tmp);
J
j_mayer 已提交
1930 1931 1932
            break;
        case 0x60:
            /* MULQ/V */
1933 1934 1935 1936 1937 1938 1939
            tmp = tcg_temp_new();
            tmp2 = tcg_temp_new();
            tcg_gen_muls2_i64(vc, tmp, va, vb);
            tcg_gen_sari_i64(tmp2, vc, 63);
            gen_helper_check_overflow(cpu_env, tmp, tmp2);
            tcg_temp_free(tmp);
            tcg_temp_free(tmp2);
J
j_mayer 已提交
1940 1941 1942 1943 1944
            break;
        default:
            goto invalid_opc;
        }
        break;
1945

J
j_mayer 已提交
1946
    case 0x14:
1947
        REQUIRE_TB_FLAG(TB_FLAGS_AMASK_FIX);
1948
        vc = dest_fpr(ctx, rc);
1949
        switch (fpfn) { /* fn11 & 0x3F */
J
j_mayer 已提交
1950 1951
        case 0x04:
            /* ITOFS */
1952
            REQUIRE_REG_31(rb);
1953 1954 1955 1956 1957
            t32 = tcg_temp_new_i32();
            va = load_gpr(ctx, ra);
            tcg_gen_trunc_i64_i32(t32, va);
            gen_helper_memory_to_s(vc, t32);
            tcg_temp_free_i32(t32);
J
j_mayer 已提交
1958 1959 1960
            break;
        case 0x0A:
            /* SQRTF */
1961
            REQUIRE_REG_31(ra);
1962 1963
            vb = load_fpr(ctx, rb);
            gen_helper_sqrtf(vc, cpu_env, vb);
1964
            break;
J
j_mayer 已提交
1965 1966
        case 0x0B:
            /* SQRTS */
1967
            REQUIRE_REG_31(ra);
1968
            gen_sqrts(ctx, rb, rc, fn11);
1969
            break;
J
j_mayer 已提交
1970 1971
        case 0x14:
            /* ITOFF */
1972
            REQUIRE_REG_31(rb);
1973 1974 1975 1976 1977
            t32 = tcg_temp_new_i32();
            va = load_gpr(ctx, ra);
            tcg_gen_trunc_i64_i32(t32, va);
            gen_helper_memory_to_f(vc, t32);
            tcg_temp_free_i32(t32);
J
j_mayer 已提交
1978 1979 1980
            break;
        case 0x24:
            /* ITOFT */
1981
            REQUIRE_REG_31(rb);
1982 1983
            va = load_gpr(ctx, ra);
            tcg_gen_mov_i64(vc, va);
J
j_mayer 已提交
1984 1985 1986
            break;
        case 0x2A:
            /* SQRTG */
1987
            REQUIRE_REG_31(ra);
1988 1989
            vb = load_fpr(ctx, rb);
            gen_helper_sqrtg(vc, cpu_env, vb);
1990
            break;
J
j_mayer 已提交
1991 1992
        case 0x02B:
            /* SQRTT */
1993
            REQUIRE_REG_31(ra);
1994
            gen_sqrtt(ctx, rb, rc, fn11);
1995
            break;
J
j_mayer 已提交
1996 1997 1998 1999
        default:
            goto invalid_opc;
        }
        break;
2000

J
j_mayer 已提交
2001 2002 2003
    case 0x15:
        /* VAX floating point */
        /* XXX: rounding mode and trap are ignored (!) */
2004 2005
        vc = dest_fpr(ctx, rc);
        vb = load_fpr(ctx, rb);
2006
        va = load_fpr(ctx, ra);
2007
        switch (fpfn) { /* fn11 & 0x3F */
J
j_mayer 已提交
2008 2009
        case 0x00:
            /* ADDF */
2010
            gen_helper_addf(vc, cpu_env, va, vb);
J
j_mayer 已提交
2011 2012 2013
            break;
        case 0x01:
            /* SUBF */
2014
            gen_helper_subf(vc, cpu_env, va, vb);
J
j_mayer 已提交
2015 2016 2017
            break;
        case 0x02:
            /* MULF */
2018
            gen_helper_mulf(vc, cpu_env, va, vb);
J
j_mayer 已提交
2019 2020 2021
            break;
        case 0x03:
            /* DIVF */
2022
            gen_helper_divf(vc, cpu_env, va, vb);
J
j_mayer 已提交
2023 2024
            break;
        case 0x1E:
2025 2026
            /* CVTDG -- TODO */
            REQUIRE_REG_31(ra);
J
j_mayer 已提交
2027 2028 2029
            goto invalid_opc;
        case 0x20:
            /* ADDG */
2030
            gen_helper_addg(vc, cpu_env, va, vb);
J
j_mayer 已提交
2031 2032 2033
            break;
        case 0x21:
            /* SUBG */
2034
            gen_helper_subg(vc, cpu_env, va, vb);
J
j_mayer 已提交
2035 2036 2037
            break;
        case 0x22:
            /* MULG */
2038
            gen_helper_mulg(vc, cpu_env, va, vb);
J
j_mayer 已提交
2039 2040 2041
            break;
        case 0x23:
            /* DIVG */
2042
            gen_helper_divg(vc, cpu_env, va, vb);
J
j_mayer 已提交
2043 2044 2045
            break;
        case 0x25:
            /* CMPGEQ */
2046
            gen_helper_cmpgeq(vc, cpu_env, va, vb);
J
j_mayer 已提交
2047 2048 2049
            break;
        case 0x26:
            /* CMPGLT */
2050
            gen_helper_cmpglt(vc, cpu_env, va, vb);
J
j_mayer 已提交
2051 2052 2053
            break;
        case 0x27:
            /* CMPGLE */
2054
            gen_helper_cmpgle(vc, cpu_env, va, vb);
J
j_mayer 已提交
2055 2056 2057
            break;
        case 0x2C:
            /* CVTGF */
2058
            REQUIRE_REG_31(ra);
2059
            gen_helper_cvtgf(vc, cpu_env, vb);
J
j_mayer 已提交
2060 2061
            break;
        case 0x2D:
2062 2063
            /* CVTGD -- TODO */
            REQUIRE_REG_31(ra);
J
j_mayer 已提交
2064 2065 2066
            goto invalid_opc;
        case 0x2F:
            /* CVTGQ */
2067
            REQUIRE_REG_31(ra);
2068
            gen_helper_cvtgq(vc, cpu_env, vb);
J
j_mayer 已提交
2069 2070 2071
            break;
        case 0x3C:
            /* CVTQF */
2072
            REQUIRE_REG_31(ra);
2073
            gen_helper_cvtqf(vc, cpu_env, vb);
J
j_mayer 已提交
2074 2075 2076
            break;
        case 0x3E:
            /* CVTQG */
2077
            REQUIRE_REG_31(ra);
2078
            gen_helper_cvtqg(vc, cpu_env, vb);
J
j_mayer 已提交
2079 2080 2081 2082 2083
            break;
        default:
            goto invalid_opc;
        }
        break;
2084

J
j_mayer 已提交
2085 2086
    case 0x16:
        /* IEEE floating-point */
2087
        switch (fpfn) { /* fn11 & 0x3F */
J
j_mayer 已提交
2088 2089
        case 0x00:
            /* ADDS */
2090
            gen_adds(ctx, ra, rb, rc, fn11);
J
j_mayer 已提交
2091 2092 2093
            break;
        case 0x01:
            /* SUBS */
2094
            gen_subs(ctx, ra, rb, rc, fn11);
J
j_mayer 已提交
2095 2096 2097
            break;
        case 0x02:
            /* MULS */
2098
            gen_muls(ctx, ra, rb, rc, fn11);
J
j_mayer 已提交
2099 2100 2101
            break;
        case 0x03:
            /* DIVS */
2102
            gen_divs(ctx, ra, rb, rc, fn11);
J
j_mayer 已提交
2103 2104 2105
            break;
        case 0x20:
            /* ADDT */
2106
            gen_addt(ctx, ra, rb, rc, fn11);
J
j_mayer 已提交
2107 2108 2109
            break;
        case 0x21:
            /* SUBT */
2110
            gen_subt(ctx, ra, rb, rc, fn11);
J
j_mayer 已提交
2111 2112 2113
            break;
        case 0x22:
            /* MULT */
2114
            gen_mult(ctx, ra, rb, rc, fn11);
J
j_mayer 已提交
2115 2116 2117
            break;
        case 0x23:
            /* DIVT */
2118
            gen_divt(ctx, ra, rb, rc, fn11);
J
j_mayer 已提交
2119 2120 2121
            break;
        case 0x24:
            /* CMPTUN */
2122
            gen_cmptun(ctx, ra, rb, rc, fn11);
J
j_mayer 已提交
2123 2124 2125
            break;
        case 0x25:
            /* CMPTEQ */
2126
            gen_cmpteq(ctx, ra, rb, rc, fn11);
J
j_mayer 已提交
2127 2128 2129
            break;
        case 0x26:
            /* CMPTLT */
2130
            gen_cmptlt(ctx, ra, rb, rc, fn11);
J
j_mayer 已提交
2131 2132 2133
            break;
        case 0x27:
            /* CMPTLE */
2134
            gen_cmptle(ctx, ra, rb, rc, fn11);
J
j_mayer 已提交
2135 2136
            break;
        case 0x2C:
2137
            REQUIRE_REG_31(ra);
A
aurel32 已提交
2138
            if (fn11 == 0x2AC || fn11 == 0x6AC) {
J
j_mayer 已提交
2139
                /* CVTST */
2140
                gen_cvtst(ctx, rb, rc, fn11);
J
j_mayer 已提交
2141 2142
            } else {
                /* CVTTS */
2143
                gen_cvtts(ctx, rb, rc, fn11);
J
j_mayer 已提交
2144 2145 2146 2147
            }
            break;
        case 0x2F:
            /* CVTTQ */
2148
            REQUIRE_REG_31(ra);
2149
            gen_cvttq(ctx, rb, rc, fn11);
J
j_mayer 已提交
2150 2151 2152
            break;
        case 0x3C:
            /* CVTQS */
2153
            REQUIRE_REG_31(ra);
2154
            gen_cvtqs(ctx, rb, rc, fn11);
J
j_mayer 已提交
2155 2156 2157
            break;
        case 0x3E:
            /* CVTQT */
2158
            REQUIRE_REG_31(ra);
2159
            gen_cvtqt(ctx, rb, rc, fn11);
J
j_mayer 已提交
2160 2161 2162 2163 2164
            break;
        default:
            goto invalid_opc;
        }
        break;
2165

J
j_mayer 已提交
2166 2167 2168 2169
    case 0x17:
        switch (fn11) {
        case 0x010:
            /* CVTLQ */
2170
            REQUIRE_REG_31(ra);
2171 2172
            vc = dest_fpr(ctx, rc);
            vb = load_fpr(ctx, rb);
2173
            gen_cvtlq(vc, vb);
J
j_mayer 已提交
2174 2175
            break;
        case 0x020:
2176 2177 2178
            /* CPYS */
            if (rc == 31) {
                /* Special case CPYS as FNOP.  */
2179
            } else {
2180
                vc = dest_fpr(ctx, rc);
2181 2182 2183
                va = load_fpr(ctx, ra);
                if (ra == rb) {
                    /* Special case CPYS as FMOV.  */
2184
                    tcg_gen_mov_i64(vc, va);
2185 2186 2187
                } else {
                    vb = load_fpr(ctx, rb);
                    gen_cpy_mask(vc, va, vb, 0, 0x8000000000000000ULL);
R
Richard Henderson 已提交
2188
                }
J
j_mayer 已提交
2189 2190 2191 2192
            }
            break;
        case 0x021:
            /* CPYSN */
2193 2194 2195 2196
            vc = dest_fpr(ctx, rc);
            vb = load_fpr(ctx, rb);
            va = load_fpr(ctx, ra);
            gen_cpy_mask(vc, va, vb, 1, 0x8000000000000000ULL);
J
j_mayer 已提交
2197 2198 2199
            break;
        case 0x022:
            /* CPYSE */
2200 2201 2202 2203
            vc = dest_fpr(ctx, rc);
            vb = load_fpr(ctx, rb);
            va = load_fpr(ctx, ra);
            gen_cpy_mask(vc, va, vb, 0, 0xFFF0000000000000ULL);
J
j_mayer 已提交
2204 2205 2206
            break;
        case 0x024:
            /* MT_FPCR */
2207 2208
            va = load_fpr(ctx, ra);
            gen_helper_store_fpcr(cpu_env, va);
2209 2210 2211 2212 2213
            if (ctx->tb_rm == QUAL_RM_D) {
                /* Re-do the copy of the rounding mode to fp_status
                   the next time we use dynamic rounding.  */
                ctx->tb_rm = -1;
            }
J
j_mayer 已提交
2214 2215 2216
            break;
        case 0x025:
            /* MF_FPCR */
2217 2218
            va = dest_fpr(ctx, ra);
            gen_helper_load_fpcr(va, cpu_env);
J
j_mayer 已提交
2219 2220 2221
            break;
        case 0x02A:
            /* FCMOVEQ */
2222
            gen_fcmov(ctx, TCG_COND_EQ, ra, rb, rc);
J
j_mayer 已提交
2223 2224 2225
            break;
        case 0x02B:
            /* FCMOVNE */
2226
            gen_fcmov(ctx, TCG_COND_NE, ra, rb, rc);
J
j_mayer 已提交
2227 2228 2229
            break;
        case 0x02C:
            /* FCMOVLT */
2230
            gen_fcmov(ctx, TCG_COND_LT, ra, rb, rc);
J
j_mayer 已提交
2231 2232 2233
            break;
        case 0x02D:
            /* FCMOVGE */
2234
            gen_fcmov(ctx, TCG_COND_GE, ra, rb, rc);
J
j_mayer 已提交
2235 2236 2237
            break;
        case 0x02E:
            /* FCMOVLE */
2238
            gen_fcmov(ctx, TCG_COND_LE, ra, rb, rc);
J
j_mayer 已提交
2239 2240 2241
            break;
        case 0x02F:
            /* FCMOVGT */
2242
            gen_fcmov(ctx, TCG_COND_GT, ra, rb, rc);
J
j_mayer 已提交
2243
            break;
2244 2245 2246
        case 0x030: /* CVTQL */
        case 0x130: /* CVTQL/V */
        case 0x530: /* CVTQL/SV */
2247
            REQUIRE_REG_31(ra);
2248 2249
            vc = dest_fpr(ctx, rc);
            vb = load_fpr(ctx, rb);
2250 2251
            gen_helper_cvtql(vc, cpu_env, vb);
            gen_fp_exc_raise(rc, fn11);
J
j_mayer 已提交
2252 2253 2254 2255 2256
            break;
        default:
            goto invalid_opc;
        }
        break;
2257

J
j_mayer 已提交
2258 2259 2260 2261
    case 0x18:
        switch ((uint16_t)disp16) {
        case 0x0000:
            /* TRAPB */
2262
            /* No-op.  */
J
j_mayer 已提交
2263 2264 2265
            break;
        case 0x0400:
            /* EXCB */
2266
            /* No-op.  */
J
j_mayer 已提交
2267 2268 2269 2270 2271 2272 2273 2274 2275 2276 2277 2278 2279 2280 2281 2282 2283 2284 2285
            break;
        case 0x4000:
            /* MB */
            /* No-op */
            break;
        case 0x4400:
            /* WMB */
            /* No-op */
            break;
        case 0x8000:
            /* FETCH */
            /* No-op */
            break;
        case 0xA000:
            /* FETCH_M */
            /* No-op */
            break;
        case 0xC000:
            /* RPCC */
2286
            va = dest_gpr(ctx, ra);
2287
            if (ctx->tb->cflags & CF_USE_ICOUNT) {
2288 2289 2290 2291 2292 2293
                gen_io_start();
                gen_helper_load_pcc(va, cpu_env);
                gen_io_end();
                ret = EXIT_PC_STALE;
            } else {
                gen_helper_load_pcc(va, cpu_env);
2294
            }
J
j_mayer 已提交
2295 2296 2297
            break;
        case 0xE000:
            /* RC */
2298
            gen_rx(ra, 0);
J
j_mayer 已提交
2299 2300 2301 2302 2303 2304
            break;
        case 0xE800:
            /* ECB */
            break;
        case 0xF000:
            /* RS */
2305
            gen_rx(ra, 1);
J
j_mayer 已提交
2306 2307 2308 2309 2310
            break;
        case 0xF800:
            /* WH64 */
            /* No-op */
            break;
2311 2312 2313 2314
        case 0xFC00:
            /* WH64EN */
            /* No-op */
            break;
J
j_mayer 已提交
2315 2316 2317 2318
        default:
            goto invalid_opc;
        }
        break;
2319

J
j_mayer 已提交
2320 2321
    case 0x19:
        /* HW_MFPR (PALcode) */
2322
#ifndef CONFIG_USER_ONLY
2323
        REQUIRE_TB_FLAG(TB_FLAGS_PAL_MODE);
2324
        va = dest_gpr(ctx, ra);
2325
        ret = gen_mfpr(ctx, va, insn & 0xffff);
2326
        break;
2327
#else
J
j_mayer 已提交
2328
        goto invalid_opc;
2329
#endif
2330

J
j_mayer 已提交
2331
    case 0x1A:
2332 2333
        /* JMP, JSR, RET, JSR_COROUTINE.  These only differ by the branch
           prediction stack action, which of course we don't implement.  */
2334 2335
        vb = load_gpr(ctx, rb);
        tcg_gen_andi_i64(cpu_pc, vb, ~3);
2336
        if (ra != 31) {
A
aurel32 已提交
2337
            tcg_gen_movi_i64(cpu_ir[ra], ctx->pc);
2338
        }
2339
        ret = EXIT_PC_UPDATED;
J
j_mayer 已提交
2340
        break;
2341

J
j_mayer 已提交
2342 2343
    case 0x1B:
        /* HW_LD (PALcode) */
2344
#ifndef CONFIG_USER_ONLY
2345 2346
        REQUIRE_TB_FLAG(TB_FLAGS_PAL_MODE);
        {
2347 2348 2349
            TCGv addr = tcg_temp_new();
            vb = load_gpr(ctx, rb);
            va = dest_gpr(ctx, ra);
2350

2351
            tcg_gen_addi_i64(addr, vb, disp12);
2352 2353
            switch ((insn >> 12) & 0xF) {
            case 0x0:
2354
                /* Longword physical access (hw_ldl/p) */
2355
                gen_helper_ldl_phys(va, cpu_env, addr);
2356 2357
                break;
            case 0x1:
2358
                /* Quadword physical access (hw_ldq/p) */
2359
                gen_helper_ldq_phys(va, cpu_env, addr);
2360 2361
                break;
            case 0x2:
2362
                /* Longword physical access with lock (hw_ldl_l/p) */
2363
                gen_helper_ldl_l_phys(va, cpu_env, addr);
2364 2365
                break;
            case 0x3:
2366
                /* Quadword physical access with lock (hw_ldq_l/p) */
2367
                gen_helper_ldq_l_phys(va, cpu_env, addr);
2368 2369
                break;
            case 0x4:
2370
                /* Longword virtual PTE fetch (hw_ldl/v) */
2371
                goto invalid_opc;
2372
            case 0x5:
2373
                /* Quadword virtual PTE fetch (hw_ldq/v) */
2374
                goto invalid_opc;
2375 2376 2377
                break;
            case 0x6:
                /* Incpu_ir[ra]id */
2378
                goto invalid_opc;
2379 2380
            case 0x7:
                /* Incpu_ir[ra]id */
2381
                goto invalid_opc;
2382
            case 0x8:
2383
                /* Longword virtual access (hw_ldl) */
2384
                goto invalid_opc;
2385
            case 0x9:
2386
                /* Quadword virtual access (hw_ldq) */
2387
                goto invalid_opc;
2388
            case 0xA:
2389
                /* Longword virtual access with protection check (hw_ldl/w) */
2390
                tcg_gen_qemu_ld_i64(va, addr, MMU_KERNEL_IDX, MO_LESL);
2391 2392
                break;
            case 0xB:
2393
                /* Quadword virtual access with protection check (hw_ldq/w) */
2394
                tcg_gen_qemu_ld_i64(va, addr, MMU_KERNEL_IDX, MO_LEQ);
2395 2396
                break;
            case 0xC:
2397
                /* Longword virtual access with alt access mode (hw_ldl/a)*/
2398
                goto invalid_opc;
2399
            case 0xD:
2400
                /* Quadword virtual access with alt access mode (hw_ldq/a) */
2401
                goto invalid_opc;
2402 2403
            case 0xE:
                /* Longword virtual access with alternate access mode and
2404
                   protection checks (hw_ldl/wa) */
2405
                tcg_gen_qemu_ld_i64(va, addr, MMU_USER_IDX, MO_LESL);
2406 2407 2408
                break;
            case 0xF:
                /* Quadword virtual access with alternate access mode and
2409
                   protection checks (hw_ldq/wa) */
2410
                tcg_gen_qemu_ld_i64(va, addr, MMU_USER_IDX, MO_LEQ);
2411 2412 2413
                break;
            }
            tcg_temp_free(addr);
2414
            break;
J
j_mayer 已提交
2415
        }
2416
#else
2417
        goto invalid_opc;
2418
#endif
2419

J
j_mayer 已提交
2420
    case 0x1C:
2421
        vc = dest_gpr(ctx, rc);
2422 2423 2424 2425 2426 2427 2428 2429 2430 2431 2432 2433 2434 2435 2436 2437 2438 2439 2440 2441
        if (fn7 == 0x70) {
            /* FTOIT */
            REQUIRE_TB_FLAG(TB_FLAGS_AMASK_FIX);
            REQUIRE_REG_31(rb);
            va = load_fpr(ctx, ra);
            tcg_gen_mov_i64(vc, va);
            break;
        } else if (fn7 == 0x78) {
            /* FTOIS */
            REQUIRE_TB_FLAG(TB_FLAGS_AMASK_FIX);
            REQUIRE_REG_31(rb);
            t32 = tcg_temp_new_i32();
            va = load_fpr(ctx, ra);
            gen_helper_s_to_memory(t32, va);
            tcg_gen_ext_i32_i64(vc, t32);
            tcg_temp_free_i32(t32);
            break;
        }

        vb = load_gpr_lit(ctx, rb, lit, islit);
J
j_mayer 已提交
2442 2443 2444
        switch (fn7) {
        case 0x00:
            /* SEXTB */
2445
            REQUIRE_TB_FLAG(TB_FLAGS_AMASK_BWX);
2446
            REQUIRE_REG_31(ra);
2447
            tcg_gen_ext8s_i64(vc, vb);
J
j_mayer 已提交
2448 2449 2450
            break;
        case 0x01:
            /* SEXTW */
2451
            REQUIRE_TB_FLAG(TB_FLAGS_AMASK_BWX);
2452
            REQUIRE_REG_31(ra);
2453
            tcg_gen_ext16s_i64(vc, vb);
2454
            break;
J
j_mayer 已提交
2455 2456
        case 0x30:
            /* CTPOP */
2457
            REQUIRE_TB_FLAG(TB_FLAGS_AMASK_CIX);
2458
            REQUIRE_REG_31(ra);
2459
            REQUIRE_NO_LIT;
2460
            gen_helper_ctpop(vc, vb);
2461
            break;
J
j_mayer 已提交
2462 2463
        case 0x31:
            /* PERR */
2464
            REQUIRE_TB_FLAG(TB_FLAGS_AMASK_MVI);
2465
            REQUIRE_NO_LIT;
2466 2467
            va = load_gpr(ctx, ra);
            gen_helper_perr(vc, va, vb);
2468
            break;
J
j_mayer 已提交
2469 2470
        case 0x32:
            /* CTLZ */
2471
            REQUIRE_TB_FLAG(TB_FLAGS_AMASK_CIX);
2472
            REQUIRE_REG_31(ra);
2473
            REQUIRE_NO_LIT;
2474
            gen_helper_ctlz(vc, vb);
2475
            break;
J
j_mayer 已提交
2476 2477
        case 0x33:
            /* CTTZ */
2478
            REQUIRE_TB_FLAG(TB_FLAGS_AMASK_CIX);
2479
            REQUIRE_REG_31(ra);
2480
            REQUIRE_NO_LIT;
2481
            gen_helper_cttz(vc, vb);
2482
            break;
J
j_mayer 已提交
2483 2484
        case 0x34:
            /* UNPKBW */
2485
            REQUIRE_TB_FLAG(TB_FLAGS_AMASK_MVI);
2486
            REQUIRE_REG_31(ra);
2487
            REQUIRE_NO_LIT;
2488
            gen_helper_unpkbw(vc, vb);
2489
            break;
J
j_mayer 已提交
2490
        case 0x35:
2491
            /* UNPKBL */
2492
            REQUIRE_TB_FLAG(TB_FLAGS_AMASK_MVI);
2493
            REQUIRE_REG_31(ra);
2494
            REQUIRE_NO_LIT;
2495
            gen_helper_unpkbl(vc, vb);
2496
            break;
J
j_mayer 已提交
2497 2498
        case 0x36:
            /* PKWB */
2499
            REQUIRE_TB_FLAG(TB_FLAGS_AMASK_MVI);
2500
            REQUIRE_REG_31(ra);
2501
            REQUIRE_NO_LIT;
2502
            gen_helper_pkwb(vc, vb);
2503
            break;
J
j_mayer 已提交
2504 2505
        case 0x37:
            /* PKLB */
2506
            REQUIRE_TB_FLAG(TB_FLAGS_AMASK_MVI);
2507
            REQUIRE_REG_31(ra);
2508
            REQUIRE_NO_LIT;
2509
            gen_helper_pklb(vc, vb);
2510
            break;
J
j_mayer 已提交
2511 2512
        case 0x38:
            /* MINSB8 */
2513
            REQUIRE_TB_FLAG(TB_FLAGS_AMASK_MVI);
2514 2515
            va = load_gpr(ctx, ra);
            gen_helper_minsb8(vc, va, vb);
2516
            break;
J
j_mayer 已提交
2517 2518
        case 0x39:
            /* MINSW4 */
2519
            REQUIRE_TB_FLAG(TB_FLAGS_AMASK_MVI);
2520 2521
            va = load_gpr(ctx, ra);
            gen_helper_minsw4(vc, va, vb);
2522
            break;
J
j_mayer 已提交
2523 2524
        case 0x3A:
            /* MINUB8 */
2525
            REQUIRE_TB_FLAG(TB_FLAGS_AMASK_MVI);
2526 2527
            va = load_gpr(ctx, ra);
            gen_helper_minub8(vc, va, vb);
2528
            break;
J
j_mayer 已提交
2529 2530
        case 0x3B:
            /* MINUW4 */
2531
            REQUIRE_TB_FLAG(TB_FLAGS_AMASK_MVI);
2532 2533
            va = load_gpr(ctx, ra);
            gen_helper_minuw4(vc, va, vb);
2534
            break;
J
j_mayer 已提交
2535 2536
        case 0x3C:
            /* MAXUB8 */
2537
            REQUIRE_TB_FLAG(TB_FLAGS_AMASK_MVI);
2538 2539
            va = load_gpr(ctx, ra);
            gen_helper_maxub8(vc, va, vb);
2540
            break;
J
j_mayer 已提交
2541 2542
        case 0x3D:
            /* MAXUW4 */
2543
            REQUIRE_TB_FLAG(TB_FLAGS_AMASK_MVI);
2544 2545
            va = load_gpr(ctx, ra);
            gen_helper_maxuw4(vc, va, vb);
2546
            break;
J
j_mayer 已提交
2547 2548
        case 0x3E:
            /* MAXSB8 */
2549
            REQUIRE_TB_FLAG(TB_FLAGS_AMASK_MVI);
2550 2551
            va = load_gpr(ctx, ra);
            gen_helper_maxsb8(vc, va, vb);
2552
            break;
J
j_mayer 已提交
2553 2554
        case 0x3F:
            /* MAXSW4 */
2555
            REQUIRE_TB_FLAG(TB_FLAGS_AMASK_MVI);
2556 2557
            va = load_gpr(ctx, ra);
            gen_helper_maxsw4(vc, va, vb);
J
j_mayer 已提交
2558 2559 2560 2561 2562
            break;
        default:
            goto invalid_opc;
        }
        break;
2563

J
j_mayer 已提交
2564 2565
    case 0x1D:
        /* HW_MTPR (PALcode) */
2566
#ifndef CONFIG_USER_ONLY
2567
        REQUIRE_TB_FLAG(TB_FLAGS_PAL_MODE);
2568
        vb = load_gpr(ctx, rb);
2569 2570
        ret = gen_mtpr(ctx, vb, insn & 0xffff);
        break;
2571
#else
J
j_mayer 已提交
2572
        goto invalid_opc;
2573
#endif
2574

J
j_mayer 已提交
2575
    case 0x1E:
2576
        /* HW_RET (PALcode) */
2577
#ifndef CONFIG_USER_ONLY
2578 2579 2580 2581 2582
        REQUIRE_TB_FLAG(TB_FLAGS_PAL_MODE);
        if (rb == 31) {
            /* Pre-EV6 CPUs interpreted this as HW_REI, loading the return
               address from EXC_ADDR.  This turns out to be useful for our
               emulation PALcode, so continue to accept it.  */
2583
            tmp = tcg_temp_new();
2584 2585 2586 2587
            tcg_gen_ld_i64(tmp, cpu_env, offsetof(CPUAlphaState, exc_addr));
            gen_helper_hw_ret(cpu_env, tmp);
            tcg_temp_free(tmp);
        } else {
2588
            gen_helper_hw_ret(cpu_env, load_gpr(ctx, rb));
J
j_mayer 已提交
2589
        }
2590 2591 2592
        ret = EXIT_PC_UPDATED;
        break;
#else
2593
        goto invalid_opc;
2594
#endif
2595

J
j_mayer 已提交
2596 2597
    case 0x1F:
        /* HW_ST (PALcode) */
2598
#ifndef CONFIG_USER_ONLY
2599 2600
        REQUIRE_TB_FLAG(TB_FLAGS_PAL_MODE);
        {
2601 2602 2603 2604 2605
            TCGv addr = tcg_temp_new();
            va = load_gpr(ctx, ra);
            vb = load_gpr(ctx, rb);

            tcg_gen_addi_i64(addr, vb, disp12);
2606 2607 2608
            switch ((insn >> 12) & 0xF) {
            case 0x0:
                /* Longword physical access */
2609
                gen_helper_stl_phys(cpu_env, addr, va);
2610 2611 2612
                break;
            case 0x1:
                /* Quadword physical access */
2613
                gen_helper_stq_phys(cpu_env, addr, va);
2614 2615 2616
                break;
            case 0x2:
                /* Longword physical access with lock */
2617
                gen_helper_stl_c_phys(dest_gpr(ctx, ra), cpu_env, addr, va);
2618 2619 2620
                break;
            case 0x3:
                /* Quadword physical access with lock */
2621
                gen_helper_stq_c_phys(dest_gpr(ctx, ra), cpu_env, addr, va);
2622 2623 2624
                break;
            case 0x4:
                /* Longword virtual access */
2625
                goto invalid_opc;
2626 2627
            case 0x5:
                /* Quadword virtual access */
2628
                goto invalid_opc;
2629 2630 2631 2632 2633 2634 2635 2636 2637 2638 2639 2640 2641 2642 2643 2644 2645 2646 2647 2648
            case 0x6:
                /* Invalid */
                goto invalid_opc;
            case 0x7:
                /* Invalid */
                goto invalid_opc;
            case 0x8:
                /* Invalid */
                goto invalid_opc;
            case 0x9:
                /* Invalid */
                goto invalid_opc;
            case 0xA:
                /* Invalid */
                goto invalid_opc;
            case 0xB:
                /* Invalid */
                goto invalid_opc;
            case 0xC:
                /* Longword virtual access with alternate access mode */
2649
                goto invalid_opc;
2650 2651
            case 0xD:
                /* Quadword virtual access with alternate access mode */
2652
                goto invalid_opc;
2653 2654 2655 2656 2657 2658 2659 2660
            case 0xE:
                /* Invalid */
                goto invalid_opc;
            case 0xF:
                /* Invalid */
                goto invalid_opc;
            }
            tcg_temp_free(addr);
2661
            break;
J
j_mayer 已提交
2662
        }
2663
#else
2664
        goto invalid_opc;
2665
#endif
J
j_mayer 已提交
2666 2667
    case 0x20:
        /* LDF */
A
aurel32 已提交
2668
        gen_load_mem(ctx, &gen_qemu_ldf, ra, rb, disp16, 1, 0);
J
j_mayer 已提交
2669 2670 2671
        break;
    case 0x21:
        /* LDG */
A
aurel32 已提交
2672
        gen_load_mem(ctx, &gen_qemu_ldg, ra, rb, disp16, 1, 0);
J
j_mayer 已提交
2673 2674 2675
        break;
    case 0x22:
        /* LDS */
A
aurel32 已提交
2676
        gen_load_mem(ctx, &gen_qemu_lds, ra, rb, disp16, 1, 0);
J
j_mayer 已提交
2677 2678 2679
        break;
    case 0x23:
        /* LDT */
A
aurel32 已提交
2680
        gen_load_mem(ctx, &tcg_gen_qemu_ld64, ra, rb, disp16, 1, 0);
J
j_mayer 已提交
2681 2682 2683
        break;
    case 0x24:
        /* STF */
2684
        gen_store_mem(ctx, &gen_qemu_stf, ra, rb, disp16, 1, 0);
J
j_mayer 已提交
2685 2686 2687
        break;
    case 0x25:
        /* STG */
2688
        gen_store_mem(ctx, &gen_qemu_stg, ra, rb, disp16, 1, 0);
J
j_mayer 已提交
2689 2690 2691
        break;
    case 0x26:
        /* STS */
2692
        gen_store_mem(ctx, &gen_qemu_sts, ra, rb, disp16, 1, 0);
J
j_mayer 已提交
2693 2694 2695
        break;
    case 0x27:
        /* STT */
2696
        gen_store_mem(ctx, &tcg_gen_qemu_st64, ra, rb, disp16, 1, 0);
J
j_mayer 已提交
2697 2698 2699
        break;
    case 0x28:
        /* LDL */
A
aurel32 已提交
2700
        gen_load_mem(ctx, &tcg_gen_qemu_ld32s, ra, rb, disp16, 0, 0);
J
j_mayer 已提交
2701 2702 2703
        break;
    case 0x29:
        /* LDQ */
A
aurel32 已提交
2704
        gen_load_mem(ctx, &tcg_gen_qemu_ld64, ra, rb, disp16, 0, 0);
J
j_mayer 已提交
2705 2706 2707
        break;
    case 0x2A:
        /* LDL_L */
2708
        gen_load_mem(ctx, &gen_qemu_ldl_l, ra, rb, disp16, 0, 0);
J
j_mayer 已提交
2709 2710 2711
        break;
    case 0x2B:
        /* LDQ_L */
2712
        gen_load_mem(ctx, &gen_qemu_ldq_l, ra, rb, disp16, 0, 0);
J
j_mayer 已提交
2713 2714 2715
        break;
    case 0x2C:
        /* STL */
2716
        gen_store_mem(ctx, &tcg_gen_qemu_st32, ra, rb, disp16, 0, 0);
J
j_mayer 已提交
2717 2718 2719
        break;
    case 0x2D:
        /* STQ */
2720
        gen_store_mem(ctx, &tcg_gen_qemu_st64, ra, rb, disp16, 0, 0);
J
j_mayer 已提交
2721 2722 2723
        break;
    case 0x2E:
        /* STL_C */
2724
        ret = gen_store_conditional(ctx, ra, rb, disp16, 0);
J
j_mayer 已提交
2725 2726 2727
        break;
    case 0x2F:
        /* STQ_C */
2728
        ret = gen_store_conditional(ctx, ra, rb, disp16, 1);
J
j_mayer 已提交
2729 2730 2731
        break;
    case 0x30:
        /* BR */
2732
        ret = gen_bdirect(ctx, ra, disp21);
J
j_mayer 已提交
2733
        break;
P
pbrook 已提交
2734
    case 0x31: /* FBEQ */
2735
        ret = gen_fbcond(ctx, TCG_COND_EQ, ra, disp21);
2736
        break;
P
pbrook 已提交
2737
    case 0x32: /* FBLT */
2738
        ret = gen_fbcond(ctx, TCG_COND_LT, ra, disp21);
2739
        break;
P
pbrook 已提交
2740
    case 0x33: /* FBLE */
2741
        ret = gen_fbcond(ctx, TCG_COND_LE, ra, disp21);
J
j_mayer 已提交
2742 2743 2744
        break;
    case 0x34:
        /* BSR */
2745
        ret = gen_bdirect(ctx, ra, disp21);
J
j_mayer 已提交
2746
        break;
P
pbrook 已提交
2747
    case 0x35: /* FBNE */
2748
        ret = gen_fbcond(ctx, TCG_COND_NE, ra, disp21);
2749
        break;
P
pbrook 已提交
2750
    case 0x36: /* FBGE */
2751
        ret = gen_fbcond(ctx, TCG_COND_GE, ra, disp21);
2752
        break;
P
pbrook 已提交
2753
    case 0x37: /* FBGT */
2754
        ret = gen_fbcond(ctx, TCG_COND_GT, ra, disp21);
J
j_mayer 已提交
2755 2756 2757
        break;
    case 0x38:
        /* BLBC */
2758
        ret = gen_bcond(ctx, TCG_COND_EQ, ra, disp21, 1);
J
j_mayer 已提交
2759 2760 2761
        break;
    case 0x39:
        /* BEQ */
2762
        ret = gen_bcond(ctx, TCG_COND_EQ, ra, disp21, 0);
J
j_mayer 已提交
2763 2764 2765
        break;
    case 0x3A:
        /* BLT */
2766
        ret = gen_bcond(ctx, TCG_COND_LT, ra, disp21, 0);
J
j_mayer 已提交
2767 2768 2769
        break;
    case 0x3B:
        /* BLE */
2770
        ret = gen_bcond(ctx, TCG_COND_LE, ra, disp21, 0);
J
j_mayer 已提交
2771 2772 2773
        break;
    case 0x3C:
        /* BLBS */
2774
        ret = gen_bcond(ctx, TCG_COND_NE, ra, disp21, 1);
J
j_mayer 已提交
2775 2776 2777
        break;
    case 0x3D:
        /* BNE */
2778
        ret = gen_bcond(ctx, TCG_COND_NE, ra, disp21, 0);
J
j_mayer 已提交
2779 2780 2781
        break;
    case 0x3E:
        /* BGE */
2782
        ret = gen_bcond(ctx, TCG_COND_GE, ra, disp21, 0);
J
j_mayer 已提交
2783 2784 2785
        break;
    case 0x3F:
        /* BGT */
2786
        ret = gen_bcond(ctx, TCG_COND_GT, ra, disp21, 0);
J
j_mayer 已提交
2787 2788
        break;
    invalid_opc:
2789
        ret = gen_invalid(ctx);
J
j_mayer 已提交
2790 2791 2792 2793 2794 2795
        break;
    }

    return ret;
}

2796
static inline void gen_intermediate_code_internal(AlphaCPU *cpu,
B
Blue Swirl 已提交
2797
                                                  TranslationBlock *tb,
2798
                                                  bool search_pc)
J
j_mayer 已提交
2799
{
2800
    CPUState *cs = CPU(cpu);
2801
    CPUAlphaState *env = &cpu->env;
J
j_mayer 已提交
2802 2803
    DisasContext ctx, *ctxp = &ctx;
    target_ulong pc_start;
2804
    target_ulong pc_mask;
J
j_mayer 已提交
2805
    uint32_t insn;
2806
    CPUBreakpoint *bp;
J
j_mayer 已提交
2807
    int j, lj = -1;
2808
    ExitStatus ret;
P
pbrook 已提交
2809 2810
    int num_insns;
    int max_insns;
J
j_mayer 已提交
2811 2812

    pc_start = tb->pc;
2813 2814

    ctx.tb = tb;
J
j_mayer 已提交
2815
    ctx.pc = pc_start;
2816
    ctx.mem_idx = cpu_mmu_index(env);
2817
    ctx.implver = env->implver;
2818
    ctx.singlestep_enabled = cs->singlestep_enabled;
2819 2820 2821 2822 2823 2824 2825 2826 2827 2828 2829

    /* ??? Every TB begins with unset rounding mode, to be initialized on
       the first fp insn of the TB.  Alternately we could define a proper
       default for every TB (e.g. QUAL_RM_N or QUAL_RM_D) and make sure
       to reset the FP_STATUS to that default at the end of any TB that
       changes the default.  We could even (gasp) dynamiclly figure out
       what default would be most efficient given the running program.  */
    ctx.tb_rm = -1;
    /* Similarly for flush-to-zero.  */
    ctx.tb_ftz = -1;

P
pbrook 已提交
2830 2831
    num_insns = 0;
    max_insns = tb->cflags & CF_COUNT_MASK;
2832
    if (max_insns == 0) {
P
pbrook 已提交
2833
        max_insns = CF_COUNT_MASK;
2834 2835 2836 2837 2838 2839 2840
    }

    if (in_superpage(&ctx, pc_start)) {
        pc_mask = (1ULL << 41) - 1;
    } else {
        pc_mask = ~TARGET_PAGE_MASK;
    }
P
pbrook 已提交
2841

2842
    gen_tb_start(tb);
2843
    do {
2844 2845
        if (unlikely(!QTAILQ_EMPTY(&cs->breakpoints))) {
            QTAILQ_FOREACH(bp, &cs->breakpoints, entry) {
2846
                if (bp->pc == ctx.pc) {
J
j_mayer 已提交
2847 2848 2849 2850 2851 2852
                    gen_excp(&ctx, EXCP_DEBUG, 0);
                    break;
                }
            }
        }
        if (search_pc) {
2853
            j = tcg_op_buf_count();
J
j_mayer 已提交
2854 2855
            if (lj < j) {
                lj++;
2856
                while (lj < j) {
2857
                    tcg_ctx.gen_opc_instr_start[lj++] = 0;
2858
                }
J
j_mayer 已提交
2859
            }
2860
            tcg_ctx.gen_opc_pc[lj] = ctx.pc;
2861
            tcg_ctx.gen_opc_instr_start[lj] = 1;
2862
            tcg_ctx.gen_opc_icount[lj] = num_insns;
J
j_mayer 已提交
2863
        }
P
Paolo Bonzini 已提交
2864
        if (num_insns + 1 == max_insns && (tb->cflags & CF_LAST_IO)) {
P
pbrook 已提交
2865
            gen_io_start();
P
Paolo Bonzini 已提交
2866
        }
2867
        insn = cpu_ldl_code(env, ctx.pc);
P
pbrook 已提交
2868
        num_insns++;
2869

2870
	if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP | CPU_LOG_TB_OP_OPT))) {
2871 2872 2873
            tcg_gen_debug_insn_start(ctx.pc);
        }

2874 2875 2876 2877
        TCGV_UNUSED_I64(ctx.zero);
        TCGV_UNUSED_I64(ctx.sink);
        TCGV_UNUSED_I64(ctx.lit);

J
j_mayer 已提交
2878 2879
        ctx.pc += 4;
        ret = translate_one(ctxp, insn);
A
aurel32 已提交
2880

2881 2882 2883 2884 2885 2886 2887 2888 2889 2890 2891
        if (!TCGV_IS_UNUSED_I64(ctx.sink)) {
            tcg_gen_discard_i64(ctx.sink);
            tcg_temp_free(ctx.sink);
        }
        if (!TCGV_IS_UNUSED_I64(ctx.zero)) {
            tcg_temp_free(ctx.zero);
        }
        if (!TCGV_IS_UNUSED_I64(ctx.lit)) {
            tcg_temp_free(ctx.lit);
        }

2892 2893 2894
        /* If we reach a page boundary, are single stepping,
           or exhaust instruction count, stop generation.  */
        if (ret == NO_EXIT
2895
            && ((ctx.pc & pc_mask) == 0
2896
                || tcg_op_buf_full()
2897 2898
                || num_insns >= max_insns
                || singlestep
2899
                || ctx.singlestep_enabled)) {
2900
            ret = EXIT_PC_STALE;
2901
        }
2902 2903 2904 2905
    } while (ret == NO_EXIT);

    if (tb->cflags & CF_LAST_IO) {
        gen_io_end();
J
j_mayer 已提交
2906
    }
2907 2908 2909

    switch (ret) {
    case EXIT_GOTO_TB:
2910
    case EXIT_NORETURN:
2911 2912
        break;
    case EXIT_PC_STALE:
A
aurel32 已提交
2913
        tcg_gen_movi_i64(cpu_pc, ctx.pc);
2914 2915
        /* FALLTHRU */
    case EXIT_PC_UPDATED:
2916
        if (ctx.singlestep_enabled) {
2917 2918 2919 2920
            gen_excp_1(EXCP_DEBUG, 0);
        } else {
            tcg_gen_exit_tb(0);
        }
2921 2922 2923
        break;
    default:
        abort();
J
j_mayer 已提交
2924
    }
2925

2926
    gen_tb_end(tb, num_insns);
2927

J
j_mayer 已提交
2928
    if (search_pc) {
2929
        j = tcg_op_buf_count();
J
j_mayer 已提交
2930
        lj++;
2931
        while (lj <= j) {
2932
            tcg_ctx.gen_opc_instr_start[lj++] = 0;
2933
        }
J
j_mayer 已提交
2934 2935
    } else {
        tb->size = ctx.pc - pc_start;
P
pbrook 已提交
2936
        tb->icount = num_insns;
J
j_mayer 已提交
2937
    }
2938

R
Richard Henderson 已提交
2939
#ifdef DEBUG_DISAS
2940
    if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) {
2941
        qemu_log("IN: %s\n", lookup_symbol(pc_start));
B
Blue Swirl 已提交
2942
        log_target_disas(env, pc_start, ctx.pc - pc_start, 1);
2943
        qemu_log("\n");
J
j_mayer 已提交
2944 2945 2946 2947
    }
#endif
}

2948
void gen_intermediate_code (CPUAlphaState *env, struct TranslationBlock *tb)
J
j_mayer 已提交
2949
{
2950
    gen_intermediate_code_internal(alpha_env_get_cpu(env), tb, false);
J
j_mayer 已提交
2951 2952
}

2953
void gen_intermediate_code_pc (CPUAlphaState *env, struct TranslationBlock *tb)
J
j_mayer 已提交
2954
{
2955
    gen_intermediate_code_internal(alpha_env_get_cpu(env), tb, true);
J
j_mayer 已提交
2956 2957
}

2958
void restore_state_to_opc(CPUAlphaState *env, TranslationBlock *tb, int pc_pos)
A
aurel32 已提交
2959
{
2960
    env->pc = tcg_ctx.gen_opc_pc[pc_pos];
A
aurel32 已提交
2961
}