Revision 4f3adfb2

b/target-s390x/translate.c
79 79
static uint64_t inline_branch_miss[CC_OP_MAX];
80 80
#endif
81 81

  
82
static inline void debug_insn(uint64_t insn)
83
{
84
    LOG_DISAS("insn: 0x%" PRIx64 "\n", insn);
85
}
86

  
87
static inline uint64_t pc_to_link_info(DisasContext *s, uint64_t pc)
82
static uint64_t pc_to_link_info(DisasContext *s, uint64_t pc)
88 83
{
89 84
    if (!(s->tb->flags & FLAG_MASK_64)) {
90 85
        if (s->tb->flags & FLAG_MASK_32) {
......
200 195
#include "helper.h"
201 196
}
202 197

  
203
static inline TCGv_i64 load_reg(int reg)
198
static TCGv_i64 load_reg(int reg)
204 199
{
205 200
    TCGv_i64 r = tcg_temp_new_i64();
206 201
    tcg_gen_mov_i64(r, regs[reg]);
207 202
    return r;
208 203
}
209 204

  
210
static inline TCGv_i64 load_freg(int reg)
211
{
212
    TCGv_i64 r = tcg_temp_new_i64();
213
    tcg_gen_mov_i64(r, fregs[reg]);
214
    return r;
215
}
216

  
217
static inline TCGv_i32 load_freg32(int reg)
218
{
219
    TCGv_i32 r = tcg_temp_new_i32();
220
#if HOST_LONG_BITS == 32
221
    tcg_gen_mov_i32(r, TCGV_HIGH(fregs[reg]));
222
#else
223
    tcg_gen_shri_i64(MAKE_TCGV_I64(GET_TCGV_I32(r)), fregs[reg], 32);
224
#endif
225
    return r;
226
}
227

  
228
static inline TCGv_i64 load_freg32_i64(int reg)
205
static TCGv_i64 load_freg32_i64(int reg)
229 206
{
230 207
    TCGv_i64 r = tcg_temp_new_i64();
231 208
    tcg_gen_shri_i64(r, fregs[reg], 32);
232 209
    return r;
233 210
}
234 211

  
235
static inline TCGv_i32 load_reg32(int reg)
236
{
237
    TCGv_i32 r = tcg_temp_new_i32();
238
    tcg_gen_trunc_i64_i32(r, regs[reg]);
239
    return r;
240
}
241

  
242
static inline TCGv_i64 load_reg32_i64(int reg)
243
{
244
    TCGv_i64 r = tcg_temp_new_i64();
245
    tcg_gen_ext32s_i64(r, regs[reg]);
246
    return r;
247
}
248

  
249
static inline void store_reg(int reg, TCGv_i64 v)
212
static void store_reg(int reg, TCGv_i64 v)
250 213
{
251 214
    tcg_gen_mov_i64(regs[reg], v);
252 215
}
253 216

  
254
static inline void store_freg(int reg, TCGv_i64 v)
217
static void store_freg(int reg, TCGv_i64 v)
255 218
{
256 219
    tcg_gen_mov_i64(fregs[reg], v);
257 220
}
258 221

  
259
static inline void store_reg32(int reg, TCGv_i32 v)
260
{
261
    /* 32 bit register writes keep the upper half */
262
#if HOST_LONG_BITS == 32
263
    tcg_gen_mov_i32(TCGV_LOW(regs[reg]), v);
264
#else
265
    tcg_gen_deposit_i64(regs[reg], regs[reg],
266
                        MAKE_TCGV_I64(GET_TCGV_I32(v)), 0, 32);
267
#endif
268
}
269

  
270
static inline void store_reg32_i64(int reg, TCGv_i64 v)
222
static void store_reg32_i64(int reg, TCGv_i64 v)
271 223
{
272 224
    /* 32 bit register writes keep the upper half */
273 225
    tcg_gen_deposit_i64(regs[reg], regs[reg], v, 0, 32);
274 226
}
275 227

  
276
static inline void store_reg32h_i64(int reg, TCGv_i64 v)
228
static void store_reg32h_i64(int reg, TCGv_i64 v)
277 229
{
278 230
    tcg_gen_deposit_i64(regs[reg], regs[reg], v, 32, 32);
279 231
}
280 232

  
281
static inline void store_freg32(int reg, TCGv_i32 v)
282
{
283
    /* 32 bit register writes keep the lower half */
284
#if HOST_LONG_BITS == 32
285
    tcg_gen_mov_i32(TCGV_HIGH(fregs[reg]), v);
286
#else
287
    tcg_gen_deposit_i64(fregs[reg], fregs[reg],
288
                        MAKE_TCGV_I64(GET_TCGV_I32(v)), 32, 32);
289
#endif
290
}
291

  
292
static inline void store_freg32_i64(int reg, TCGv_i64 v)
233
static void store_freg32_i64(int reg, TCGv_i64 v)
293 234
{
294 235
    tcg_gen_deposit_i64(fregs[reg], fregs[reg], v, 32, 32);
295 236
}
296 237

  
297
static inline void return_low128(TCGv_i64 dest)
238
static void return_low128(TCGv_i64 dest)
298 239
{
299 240
    tcg_gen_ld_i64(dest, cpu_env, offsetof(CPUS390XState, retxl));
300 241
}
301 242

  
302
static inline void update_psw_addr(DisasContext *s)
243
static void update_psw_addr(DisasContext *s)
303 244
{
304 245
    /* psw.addr */
305 246
    tcg_gen_movi_i64(psw_addr, s->pc);
306 247
}
307 248

  
308
static inline void potential_page_fault(DisasContext *s)
249
static void potential_page_fault(DisasContext *s)
309 250
{
310 251
#ifndef CONFIG_USER_ONLY
311 252
    update_psw_addr(s);
......
328 269
    return (ld_code2(env, pc) << 32) | ld_code4(env, pc + 2);
329 270
}
330 271

  
331
static inline int get_mem_index(DisasContext *s)
272
static int get_mem_index(DisasContext *s)
332 273
{
333 274
    switch (s->tb->flags & FLAG_MASK_ASC) {
334 275
    case PSW_ASC_PRIMARY >> 32:
......
440 381
    s->cc_op = op;
441 382
}
442 383

  
443
static void gen_op_update1_cc_i32(DisasContext *s, enum cc_op op, TCGv_i32 dst)
444
{
445
    tcg_gen_discard_i64(cc_src);
446
    tcg_gen_extu_i32_i64(cc_dst, dst);
447
    tcg_gen_discard_i64(cc_vr);
448
    s->cc_op = op;
449
}
450

  
451 384
static void gen_op_update2_cc_i64(DisasContext *s, enum cc_op op, TCGv_i64 src,
452 385
                                  TCGv_i64 dst)
453 386
{
......
457 390
    s->cc_op = op;
458 391
}
459 392

  
460
static void gen_op_update2_cc_i32(DisasContext *s, enum cc_op op, TCGv_i32 src,
461
                                  TCGv_i32 dst)
462
{
463
    tcg_gen_extu_i32_i64(cc_src, src);
464
    tcg_gen_extu_i32_i64(cc_dst, dst);
465
    tcg_gen_discard_i64(cc_vr);
466
    s->cc_op = op;
467
}
468

  
469 393
static void gen_op_update3_cc_i64(DisasContext *s, enum cc_op op, TCGv_i64 src,
470 394
                                  TCGv_i64 dst, TCGv_i64 vr)
471 395
{
......
475 399
    s->cc_op = op;
476 400
}
477 401

  
478
static inline void set_cc_nz_u32(DisasContext *s, TCGv_i32 val)
479
{
480
    gen_op_update1_cc_i32(s, CC_OP_NZ, val);
481
}
482

  
483
static inline void set_cc_nz_u64(DisasContext *s, TCGv_i64 val)
402
static void set_cc_nz_u64(DisasContext *s, TCGv_i64 val)
484 403
{
485 404
    gen_op_update1_cc_i64(s, CC_OP_NZ, val);
486 405
}
487 406

  
488
static inline void gen_set_cc_nz_f32(DisasContext *s, TCGv_i64 val)
407
static void gen_set_cc_nz_f32(DisasContext *s, TCGv_i64 val)
489 408
{
490 409
    gen_op_update1_cc_i64(s, CC_OP_NZ_F32, val);
491 410
}
492 411

  
493
static inline void gen_set_cc_nz_f64(DisasContext *s, TCGv_i64 val)
412
static void gen_set_cc_nz_f64(DisasContext *s, TCGv_i64 val)
494 413
{
495 414
    gen_op_update1_cc_i64(s, CC_OP_NZ_F64, val);
496 415
}
497 416

  
498
static inline void gen_set_cc_nz_f128(DisasContext *s, TCGv_i64 vh, TCGv_i64 vl)
417
static void gen_set_cc_nz_f128(DisasContext *s, TCGv_i64 vh, TCGv_i64 vl)
499 418
{
500 419
    gen_op_update2_cc_i64(s, CC_OP_NZ_F128, vh, vl);
501 420
}
502 421

  
503
static inline void cmp_32(DisasContext *s, TCGv_i32 v1, TCGv_i32 v2,
504
                          enum cc_op cond)
505
{
506
    gen_op_update2_cc_i32(s, cond, v1, v2);
507
}
508

  
509
static inline void cmp_64(DisasContext *s, TCGv_i64 v1, TCGv_i64 v2,
510
                          enum cc_op cond)
511
{
512
    gen_op_update2_cc_i64(s, cond, v1, v2);
513
}
514

  
515
static inline void cmp_s32(DisasContext *s, TCGv_i32 v1, TCGv_i32 v2)
516
{
517
    cmp_32(s, v1, v2, CC_OP_LTGT_32);
518
}
519

  
520
static inline void cmp_u32(DisasContext *s, TCGv_i32 v1, TCGv_i32 v2)
521
{
522
    cmp_32(s, v1, v2, CC_OP_LTUGTU_32);
523
}
524

  
525
static inline void cmp_s32c(DisasContext *s, TCGv_i32 v1, int32_t v2)
526
{
527
    /* XXX optimize for the constant? put it in s? */
528
    TCGv_i32 tmp = tcg_const_i32(v2);
529
    cmp_32(s, v1, tmp, CC_OP_LTGT_32);
530
    tcg_temp_free_i32(tmp);
531
}
532

  
533
static inline void cmp_u32c(DisasContext *s, TCGv_i32 v1, uint32_t v2)
534
{
535
    TCGv_i32 tmp = tcg_const_i32(v2);
536
    cmp_32(s, v1, tmp, CC_OP_LTUGTU_32);
537
    tcg_temp_free_i32(tmp);
538
}
539

  
540
static inline void cmp_s64(DisasContext *s, TCGv_i64 v1, TCGv_i64 v2)
541
{
542
    cmp_64(s, v1, v2, CC_OP_LTGT_64);
543
}
544

  
545
static inline void cmp_u64(DisasContext *s, TCGv_i64 v1, TCGv_i64 v2)
546
{
547
    cmp_64(s, v1, v2, CC_OP_LTUGTU_64);
548
}
549

  
550
static inline void cmp_s64c(DisasContext *s, TCGv_i64 v1, int64_t v2)
551
{
552
    TCGv_i64 tmp = tcg_const_i64(v2);
553
    cmp_s64(s, v1, tmp);
554
    tcg_temp_free_i64(tmp);
555
}
556

  
557
static inline void cmp_u64c(DisasContext *s, TCGv_i64 v1, uint64_t v2)
558
{
559
    TCGv_i64 tmp = tcg_const_i64(v2);
560
    cmp_u64(s, v1, tmp);
561
    tcg_temp_free_i64(tmp);
562
}
563

  
564
static inline void set_cc_s32(DisasContext *s, TCGv_i32 val)
565
{
566
    gen_op_update1_cc_i32(s, CC_OP_LTGT0_32, val);
567
}
568

  
569
static inline void set_cc_s64(DisasContext *s, TCGv_i64 val)
570
{
571
    gen_op_update1_cc_i64(s, CC_OP_LTGT0_64, val);
572
}
573

  
574 422
/* CC value is in env->cc_op */
575
static inline void set_cc_static(DisasContext *s)
423
static void set_cc_static(DisasContext *s)
576 424
{
577 425
    tcg_gen_discard_i64(cc_src);
578 426
    tcg_gen_discard_i64(cc_dst);
......
580 428
    s->cc_op = CC_OP_STATIC;
581 429
}
582 430

  
583
static inline void gen_op_set_cc_op(DisasContext *s)
431
static void gen_op_set_cc_op(DisasContext *s)
584 432
{
585 433
    if (s->cc_op != CC_OP_DYNAMIC && s->cc_op != CC_OP_STATIC) {
586 434
        tcg_gen_movi_i32(cc_op, s->cc_op);
587 435
    }
588 436
}
589 437

  
590
static inline void gen_update_cc_op(DisasContext *s)
438
static void gen_update_cc_op(DisasContext *s)
591 439
{
592 440
    gen_op_set_cc_op(s);
593 441
}
......
667 515
    set_cc_static(s);
668 516
}
669 517

  
670
static inline void decode_rr(DisasContext *s, uint64_t insn, int *r1, int *r2)
671
{
672
    debug_insn(insn);
673

  
674
    *r1 = (insn >> 4) & 0xf;
675
    *r2 = insn & 0xf;
676
}
677

  
678
static inline TCGv_i64 decode_rx(DisasContext *s, uint64_t insn, int *r1,
679
                                 int *x2, int *b2, int *d2)
680
{
681
    debug_insn(insn);
682

  
683
    *r1 = (insn >> 20) & 0xf;
684
    *x2 = (insn >> 16) & 0xf;
685
    *b2 = (insn >> 12) & 0xf;
686
    *d2 = insn & 0xfff;
687

  
688
    return get_address(s, *x2, *b2, *d2);
689
}
690

  
691
static inline void decode_rs(DisasContext *s, uint64_t insn, int *r1, int *r3,
692
                             int *b2, int *d2)
693
{
694
    debug_insn(insn);
695

  
696
    *r1 = (insn >> 20) & 0xf;
697
    /* aka m3 */
698
    *r3 = (insn >> 16) & 0xf;
699
    *b2 = (insn >> 12) & 0xf;
700
    *d2 = insn & 0xfff;
701
}
702

  
703
static inline TCGv_i64 decode_si(DisasContext *s, uint64_t insn, int *i2,
704
                                 int *b1, int *d1)
705
{
706
    debug_insn(insn);
707

  
708
    *i2 = (insn >> 16) & 0xff;
709
    *b1 = (insn >> 12) & 0xf;
710
    *d1 = insn & 0xfff;
711

  
712
    return get_address(s, 0, *b1, *d1);
713
}
714

  
715 518
static int use_goto_tb(DisasContext *s, uint64_t dest)
716 519
{
717 520
    /* NOTE: we handle the case where the TB spans two pages here */
......
721 524
            && !(s->tb->cflags & CF_LAST_IO));
722 525
}
723 526

  
724
static inline void gen_goto_tb(DisasContext *s, int tb_num, target_ulong pc)
725
{
726
    gen_update_cc_op(s);
727

  
728
    if (use_goto_tb(s, pc)) {
729
        tcg_gen_goto_tb(tb_num);
730
        tcg_gen_movi_i64(psw_addr, pc);
731
        tcg_gen_exit_tb((tcg_target_long)s->tb + tb_num);
732
    } else {
733
        /* jump to another page: currently not optimized */
734
        tcg_gen_movi_i64(psw_addr, pc);
735
        tcg_gen_exit_tb(0);
736
    }
737
}
738

  
739
static inline void account_noninline_branch(DisasContext *s, int cc_op)
527
static void account_noninline_branch(DisasContext *s, int cc_op)
740 528
{
741 529
#ifdef DEBUG_INLINE_BRANCHES
742 530
    inline_branch_miss[cc_op]++;
743 531
#endif
744 532
}
745 533

  
746
static inline void account_inline_branch(DisasContext *s, int cc_op)
534
static void account_inline_branch(DisasContext *s, int cc_op)
747 535
{
748 536
#ifdef DEBUG_INLINE_BRANCHES
749 537
    inline_branch_hit[cc_op]++;
......
1018 806
    }
1019 807
}
1020 808

  
1021
static void disas_b2(CPUS390XState *env, DisasContext *s, int op,
1022
                     uint32_t insn)
1023
{
1024
#ifndef CONFIG_USER_ONLY
1025
    switch (op) {
1026
    default:
1027
#endif
1028
        LOG_DISAS("illegal b2 operation 0x%x\n", op);
1029
        gen_illegal_opcode(s);
1030
#ifndef CONFIG_USER_ONLY
1031
        break;
1032
    }
1033
#endif
1034
}
1035

  
1036
static void disas_s390_insn(CPUS390XState *env, DisasContext *s)
1037
{
1038
    unsigned char opc;
1039
    uint64_t insn;
1040
    int op;
1041

  
1042
    opc = cpu_ldub_code(env, s->pc);
1043
    LOG_DISAS("opc 0x%x\n", opc);
1044

  
1045
    switch (opc) {
1046
    case 0xb2:
1047
        insn = ld_code4(env, s->pc);
1048
        op = (insn >> 16) & 0xff;
1049
        disas_b2(env, s, op, insn);
1050
        break;
1051
    default:
1052
        qemu_log_mask(LOG_UNIMP, "unimplemented opcode 0x%x\n", opc);
1053
        gen_illegal_opcode(s);
1054
        break;
1055
    }
1056
}
1057

  
1058 809
/* ====================================================================== */
1059 810
/* Define the insn format enumeration.  */
1060 811
#define F0(N)                         FMT_##N,
......
4108 3859
    DisasFields f;
4109 3860
    DisasOps o;
4110 3861

  
3862
    /* Search for the insn in the table.  */
4111 3863
    insn = extract_insn(env, s, &f);
4112 3864

  
4113
    /* If not found, try the old interpreter.  This includes ILLOPC.  */
3865
    /* Not found means unimplemented/illegal opcode.  */
4114 3866
    if (insn == NULL) {
4115
        disas_s390_insn(env, s);
4116
        switch (s->is_jmp) {
4117
        case DISAS_NEXT:
4118
            ret = NO_EXIT;
4119
            break;
4120
        case DISAS_TB_JUMP:
4121
            ret = EXIT_GOTO_TB;
4122
            break;
4123
        case DISAS_JUMP:
4124
            ret = EXIT_PC_UPDATED;
4125
            break;
4126
        case DISAS_EXCP:
4127
            ret = EXIT_NORETURN;
4128
            break;
4129
        default:
4130
            abort();
4131
        }
4132

  
4133
        s->pc = s->next_pc;
4134
        return ret;
3867
        qemu_log_mask(LOG_UNIMP, "unimplemented opcode 0x%02x%02x\n",
3868
                      f.op, f.op2);
3869
        gen_illegal_opcode(s);
3870
        return EXIT_NORETURN;
4135 3871
    }
4136 3872

  
4137 3873
    /* Set up the strutures we use to communicate with the helpers. */

Also available in: Unified diff