qemu/target/unicore32/translate.c
<<
>>
Prefs
   1/*
   2 *  UniCore32 translation
   3 *
   4 * Copyright (C) 2010-2012 Guan Xuetao
   5 *
   6 * This program is free software; you can redistribute it and/or modify
   7 * it under the terms of the GNU General Public License version 2 as
   8 * published by the Free Software Foundation, or (at your option) any
   9 * later version. See the COPYING file in the top-level directory.
  10 */
  11#include "qemu/osdep.h"
  12
  13#include "cpu.h"
  14#include "disas/disas.h"
  15#include "exec/exec-all.h"
  16#include "tcg-op.h"
  17#include "qemu/log.h"
  18#include "exec/cpu_ldst.h"
  19#include "exec/translator.h"
  20#include "qemu/qemu-print.h"
  21
  22#include "exec/helper-proto.h"
  23#include "exec/helper-gen.h"
  24
  25#include "trace-tcg.h"
  26#include "exec/log.h"
  27
  28
  29/* internal defines */
  30typedef struct DisasContext {
  31    target_ulong pc;
  32    int is_jmp;
  33    /* Nonzero if this instruction has been conditionally skipped.  */
  34    int condjmp;
  35    /* The label that will be jumped to when the instruction is skipped.  */
  36    TCGLabel *condlabel;
  37    struct TranslationBlock *tb;
  38    int singlestep_enabled;
  39#ifndef CONFIG_USER_ONLY
  40    int user;
  41#endif
  42} DisasContext;
  43
  44#ifndef CONFIG_USER_ONLY
  45#define IS_USER(s)      (s->user)
  46#else
  47#define IS_USER(s)      1
  48#endif
  49
  50/* is_jmp field values */
  51#define DISAS_JUMP    DISAS_TARGET_0 /* only pc was modified dynamically */
  52#define DISAS_UPDATE  DISAS_TARGET_1 /* cpu state was modified dynamically */
  53#define DISAS_TB_JUMP DISAS_TARGET_2 /* only pc was modified statically */
  54/* These instructions trap after executing, so defer them until after the
  55   conditional executions state has been updated.  */
  56#define DISAS_SYSCALL DISAS_TARGET_3
  57
  58static TCGv_i32 cpu_R[32];
  59
  60/* FIXME:  These should be removed.  */
  61static TCGv cpu_F0s, cpu_F1s;
  62static TCGv_i64 cpu_F0d, cpu_F1d;
  63
  64#include "exec/gen-icount.h"
  65
  66static const char *regnames[] = {
  67      "r00", "r01", "r02", "r03", "r04", "r05", "r06", "r07",
  68      "r08", "r09", "r10", "r11", "r12", "r13", "r14", "r15",
  69      "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23",
  70      "r24", "r25", "r26", "r27", "r28", "r29", "r30", "pc" };
  71
  72/* initialize TCG globals.  */
  73void uc32_translate_init(void)
  74{
  75    int i;
  76
  77    for (i = 0; i < 32; i++) {
  78        cpu_R[i] = tcg_global_mem_new_i32(cpu_env,
  79                                offsetof(CPUUniCore32State, regs[i]), regnames[i]);
  80    }
  81}
  82
  83static int num_temps;
  84
  85/* Allocate a temporary variable.  */
  86static TCGv_i32 new_tmp(void)
  87{
  88    num_temps++;
  89    return tcg_temp_new_i32();
  90}
  91
  92/* Release a temporary variable.  */
  93static void dead_tmp(TCGv tmp)
  94{
  95    tcg_temp_free(tmp);
  96    num_temps--;
  97}
  98
  99static inline TCGv load_cpu_offset(int offset)
 100{
 101    TCGv tmp = new_tmp();
 102    tcg_gen_ld_i32(tmp, cpu_env, offset);
 103    return tmp;
 104}
 105
 106#define load_cpu_field(name) load_cpu_offset(offsetof(CPUUniCore32State, name))
 107
 108static inline void store_cpu_offset(TCGv var, int offset)
 109{
 110    tcg_gen_st_i32(var, cpu_env, offset);
 111    dead_tmp(var);
 112}
 113
 114#define store_cpu_field(var, name) \
 115    store_cpu_offset(var, offsetof(CPUUniCore32State, name))
 116
 117/* Set a variable to the value of a CPU register.  */
 118static void load_reg_var(DisasContext *s, TCGv var, int reg)
 119{
 120    if (reg == 31) {
 121        uint32_t addr;
 122        /* normaly, since we updated PC */
 123        addr = (long)s->pc;
 124        tcg_gen_movi_i32(var, addr);
 125    } else {
 126        tcg_gen_mov_i32(var, cpu_R[reg]);
 127    }
 128}
 129
 130/* Create a new temporary and set it to the value of a CPU register.  */
 131static inline TCGv load_reg(DisasContext *s, int reg)
 132{
 133    TCGv tmp = new_tmp();
 134    load_reg_var(s, tmp, reg);
 135    return tmp;
 136}
 137
 138/* Set a CPU register.  The source must be a temporary and will be
 139   marked as dead.  */
 140static void store_reg(DisasContext *s, int reg, TCGv var)
 141{
 142    if (reg == 31) {
 143        tcg_gen_andi_i32(var, var, ~3);
 144        s->is_jmp = DISAS_JUMP;
 145    }
 146    tcg_gen_mov_i32(cpu_R[reg], var);
 147    dead_tmp(var);
 148}
 149
 150/* Value extensions.  */
 151#define gen_uxtb(var)           tcg_gen_ext8u_i32(var, var)
 152#define gen_uxth(var)           tcg_gen_ext16u_i32(var, var)
 153#define gen_sxtb(var)           tcg_gen_ext8s_i32(var, var)
 154#define gen_sxth(var)           tcg_gen_ext16s_i32(var, var)
 155
 156#define UCOP_REG_M              (((insn) >>  0) & 0x1f)
 157#define UCOP_REG_N              (((insn) >> 19) & 0x1f)
 158#define UCOP_REG_D              (((insn) >> 14) & 0x1f)
 159#define UCOP_REG_S              (((insn) >>  9) & 0x1f)
 160#define UCOP_REG_LO             (((insn) >> 14) & 0x1f)
 161#define UCOP_REG_HI             (((insn) >>  9) & 0x1f)
 162#define UCOP_SH_OP              (((insn) >>  6) & 0x03)
 163#define UCOP_SH_IM              (((insn) >>  9) & 0x1f)
 164#define UCOP_OPCODES            (((insn) >> 25) & 0x0f)
 165#define UCOP_IMM_9              (((insn) >>  0) & 0x1ff)
 166#define UCOP_IMM10              (((insn) >>  0) & 0x3ff)
 167#define UCOP_IMM14              (((insn) >>  0) & 0x3fff)
 168#define UCOP_COND               (((insn) >> 25) & 0x0f)
 169#define UCOP_CMOV_COND          (((insn) >> 19) & 0x0f)
 170#define UCOP_CPNUM              (((insn) >> 10) & 0x0f)
 171#define UCOP_UCF64_FMT          (((insn) >> 24) & 0x03)
 172#define UCOP_UCF64_FUNC         (((insn) >>  6) & 0x0f)
 173#define UCOP_UCF64_COND         (((insn) >>  6) & 0x0f)
 174
 175#define UCOP_SET(i)             ((insn) & (1 << (i)))
 176#define UCOP_SET_P              UCOP_SET(28)
 177#define UCOP_SET_U              UCOP_SET(27)
 178#define UCOP_SET_B              UCOP_SET(26)
 179#define UCOP_SET_W              UCOP_SET(25)
 180#define UCOP_SET_L              UCOP_SET(24)
 181#define UCOP_SET_S              UCOP_SET(24)
 182
 183#define ILLEGAL         cpu_abort(env_cpu(env),                         \
 184                        "Illegal UniCore32 instruction %x at line %d!", \
 185                        insn, __LINE__)
 186
 187#ifndef CONFIG_USER_ONLY
 188static void disas_cp0_insn(CPUUniCore32State *env, DisasContext *s,
 189        uint32_t insn)
 190{
 191    TCGv tmp, tmp2, tmp3;
 192    if ((insn & 0xfe000000) == 0xe0000000) {
 193        tmp2 = new_tmp();
 194        tmp3 = new_tmp();
 195        tcg_gen_movi_i32(tmp2, UCOP_REG_N);
 196        tcg_gen_movi_i32(tmp3, UCOP_IMM10);
 197        if (UCOP_SET_L) {
 198            tmp = new_tmp();
 199            gen_helper_cp0_get(tmp, cpu_env, tmp2, tmp3);
 200            store_reg(s, UCOP_REG_D, tmp);
 201        } else {
 202            tmp = load_reg(s, UCOP_REG_D);
 203            gen_helper_cp0_set(cpu_env, tmp, tmp2, tmp3);
 204            dead_tmp(tmp);
 205        }
 206        dead_tmp(tmp2);
 207        dead_tmp(tmp3);
 208        return;
 209    }
 210    ILLEGAL;
 211}
 212
 213static void disas_ocd_insn(CPUUniCore32State *env, DisasContext *s,
 214        uint32_t insn)
 215{
 216    TCGv tmp;
 217
 218    if ((insn & 0xff003fff) == 0xe1000400) {
 219        /*
 220         * movc rd, pp.nn, #imm9
 221         *      rd: UCOP_REG_D
 222         *      nn: UCOP_REG_N (must be 0)
 223         *      imm9: 0
 224         */
 225        if (UCOP_REG_N == 0) {
 226            tmp = new_tmp();
 227            tcg_gen_movi_i32(tmp, 0);
 228            store_reg(s, UCOP_REG_D, tmp);
 229            return;
 230        } else {
 231            ILLEGAL;
 232        }
 233    }
 234    if ((insn & 0xff003fff) == 0xe0000401) {
 235        /*
 236         * movc pp.nn, rn, #imm9
 237         *      rn: UCOP_REG_D
 238         *      nn: UCOP_REG_N (must be 1)
 239         *      imm9: 1
 240         */
 241        if (UCOP_REG_N == 1) {
 242            tmp = load_reg(s, UCOP_REG_D);
 243            gen_helper_cp1_putc(tmp);
 244            dead_tmp(tmp);
 245            return;
 246        } else {
 247            ILLEGAL;
 248        }
 249    }
 250    ILLEGAL;
 251}
 252#endif
 253
 254static inline void gen_set_asr(TCGv var, uint32_t mask)
 255{
 256    TCGv tmp_mask = tcg_const_i32(mask);
 257    gen_helper_asr_write(cpu_env, var, tmp_mask);
 258    tcg_temp_free_i32(tmp_mask);
 259}
 260/* Set NZCV flags from the high 4 bits of var.  */
 261#define gen_set_nzcv(var) gen_set_asr(var, ASR_NZCV)
 262
 263static void gen_exception(int excp)
 264{
 265    TCGv tmp = new_tmp();
 266    tcg_gen_movi_i32(tmp, excp);
 267    gen_helper_exception(cpu_env, tmp);
 268    dead_tmp(tmp);
 269}
 270
 271#define gen_set_CF(var) tcg_gen_st_i32(var, cpu_env, offsetof(CPUUniCore32State, CF))
 272
 273/* Set CF to the top bit of var.  */
 274static void gen_set_CF_bit31(TCGv var)
 275{
 276    TCGv tmp = new_tmp();
 277    tcg_gen_shri_i32(tmp, var, 31);
 278    gen_set_CF(tmp);
 279    dead_tmp(tmp);
 280}
 281
 282/* Set N and Z flags from var.  */
 283static inline void gen_logic_CC(TCGv var)
 284{
 285    tcg_gen_st_i32(var, cpu_env, offsetof(CPUUniCore32State, NF));
 286    tcg_gen_st_i32(var, cpu_env, offsetof(CPUUniCore32State, ZF));
 287}
 288
 289/* dest = T0 + T1 + CF. */
 290static void gen_add_carry(TCGv dest, TCGv t0, TCGv t1)
 291{
 292    TCGv tmp;
 293    tcg_gen_add_i32(dest, t0, t1);
 294    tmp = load_cpu_field(CF);
 295    tcg_gen_add_i32(dest, dest, tmp);
 296    dead_tmp(tmp);
 297}
 298
 299/* dest = T0 - T1 + CF - 1.  */
 300static void gen_sub_carry(TCGv dest, TCGv t0, TCGv t1)
 301{
 302    TCGv tmp;
 303    tcg_gen_sub_i32(dest, t0, t1);
 304    tmp = load_cpu_field(CF);
 305    tcg_gen_add_i32(dest, dest, tmp);
 306    tcg_gen_subi_i32(dest, dest, 1);
 307    dead_tmp(tmp);
 308}
 309
 310static void shifter_out_im(TCGv var, int shift)
 311{
 312    TCGv tmp = new_tmp();
 313    if (shift == 0) {
 314        tcg_gen_andi_i32(tmp, var, 1);
 315    } else {
 316        tcg_gen_shri_i32(tmp, var, shift);
 317        if (shift != 31) {
 318            tcg_gen_andi_i32(tmp, tmp, 1);
 319        }
 320    }
 321    gen_set_CF(tmp);
 322    dead_tmp(tmp);
 323}
 324
 325/* Shift by immediate.  Includes special handling for shift == 0.  */
 326static inline void gen_uc32_shift_im(TCGv var, int shiftop, int shift,
 327        int flags)
 328{
 329    switch (shiftop) {
 330    case 0: /* LSL */
 331        if (shift != 0) {
 332            if (flags) {
 333                shifter_out_im(var, 32 - shift);
 334            }
 335            tcg_gen_shli_i32(var, var, shift);
 336        }
 337        break;
 338    case 1: /* LSR */
 339        if (shift == 0) {
 340            if (flags) {
 341                tcg_gen_shri_i32(var, var, 31);
 342                gen_set_CF(var);
 343            }
 344            tcg_gen_movi_i32(var, 0);
 345        } else {
 346            if (flags) {
 347                shifter_out_im(var, shift - 1);
 348            }
 349            tcg_gen_shri_i32(var, var, shift);
 350        }
 351        break;
 352    case 2: /* ASR */
 353        if (shift == 0) {
 354            shift = 32;
 355        }
 356        if (flags) {
 357            shifter_out_im(var, shift - 1);
 358        }
 359        if (shift == 32) {
 360            shift = 31;
 361        }
 362        tcg_gen_sari_i32(var, var, shift);
 363        break;
 364    case 3: /* ROR/RRX */
 365        if (shift != 0) {
 366            if (flags) {
 367                shifter_out_im(var, shift - 1);
 368            }
 369            tcg_gen_rotri_i32(var, var, shift); break;
 370        } else {
 371            TCGv tmp = load_cpu_field(CF);
 372            if (flags) {
 373                shifter_out_im(var, 0);
 374            }
 375            tcg_gen_shri_i32(var, var, 1);
 376            tcg_gen_shli_i32(tmp, tmp, 31);
 377            tcg_gen_or_i32(var, var, tmp);
 378            dead_tmp(tmp);
 379        }
 380    }
 381};
 382
 383static inline void gen_uc32_shift_reg(TCGv var, int shiftop,
 384                                     TCGv shift, int flags)
 385{
 386    if (flags) {
 387        switch (shiftop) {
 388        case 0:
 389            gen_helper_shl_cc(var, cpu_env, var, shift);
 390            break;
 391        case 1:
 392            gen_helper_shr_cc(var, cpu_env, var, shift);
 393            break;
 394        case 2:
 395            gen_helper_sar_cc(var, cpu_env, var, shift);
 396            break;
 397        case 3:
 398            gen_helper_ror_cc(var, cpu_env, var, shift);
 399            break;
 400        }
 401    } else {
 402        switch (shiftop) {
 403        case 0:
 404            gen_helper_shl(var, var, shift);
 405            break;
 406        case 1:
 407            gen_helper_shr(var, var, shift);
 408            break;
 409        case 2:
 410            gen_helper_sar(var, var, shift);
 411            break;
 412        case 3:
 413            tcg_gen_andi_i32(shift, shift, 0x1f);
 414            tcg_gen_rotr_i32(var, var, shift);
 415            break;
 416        }
 417    }
 418    dead_tmp(shift);
 419}
 420
 421static void gen_test_cc(int cc, TCGLabel *label)
 422{
 423    TCGv tmp;
 424    TCGv tmp2;
 425    TCGLabel *inv;
 426
 427    switch (cc) {
 428    case 0: /* eq: Z */
 429        tmp = load_cpu_field(ZF);
 430        tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, label);
 431        break;
 432    case 1: /* ne: !Z */
 433        tmp = load_cpu_field(ZF);
 434        tcg_gen_brcondi_i32(TCG_COND_NE, tmp, 0, label);
 435        break;
 436    case 2: /* cs: C */
 437        tmp = load_cpu_field(CF);
 438        tcg_gen_brcondi_i32(TCG_COND_NE, tmp, 0, label);
 439        break;
 440    case 3: /* cc: !C */
 441        tmp = load_cpu_field(CF);
 442        tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, label);
 443        break;
 444    case 4: /* mi: N */
 445        tmp = load_cpu_field(NF);
 446        tcg_gen_brcondi_i32(TCG_COND_LT, tmp, 0, label);
 447        break;
 448    case 5: /* pl: !N */
 449        tmp = load_cpu_field(NF);
 450        tcg_gen_brcondi_i32(TCG_COND_GE, tmp, 0, label);
 451        break;
 452    case 6: /* vs: V */
 453        tmp = load_cpu_field(VF);
 454        tcg_gen_brcondi_i32(TCG_COND_LT, tmp, 0, label);
 455        break;
 456    case 7: /* vc: !V */
 457        tmp = load_cpu_field(VF);
 458        tcg_gen_brcondi_i32(TCG_COND_GE, tmp, 0, label);
 459        break;
 460    case 8: /* hi: C && !Z */
 461        inv = gen_new_label();
 462        tmp = load_cpu_field(CF);
 463        tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, inv);
 464        dead_tmp(tmp);
 465        tmp = load_cpu_field(ZF);
 466        tcg_gen_brcondi_i32(TCG_COND_NE, tmp, 0, label);
 467        gen_set_label(inv);
 468        break;
 469    case 9: /* ls: !C || Z */
 470        tmp = load_cpu_field(CF);
 471        tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, label);
 472        dead_tmp(tmp);
 473        tmp = load_cpu_field(ZF);
 474        tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, label);
 475        break;
 476    case 10: /* ge: N == V -> N ^ V == 0 */
 477        tmp = load_cpu_field(VF);
 478        tmp2 = load_cpu_field(NF);
 479        tcg_gen_xor_i32(tmp, tmp, tmp2);
 480        dead_tmp(tmp2);
 481        tcg_gen_brcondi_i32(TCG_COND_GE, tmp, 0, label);
 482        break;
 483    case 11: /* lt: N != V -> N ^ V != 0 */
 484        tmp = load_cpu_field(VF);
 485        tmp2 = load_cpu_field(NF);
 486        tcg_gen_xor_i32(tmp, tmp, tmp2);
 487        dead_tmp(tmp2);
 488        tcg_gen_brcondi_i32(TCG_COND_LT, tmp, 0, label);
 489        break;
 490    case 12: /* gt: !Z && N == V */
 491        inv = gen_new_label();
 492        tmp = load_cpu_field(ZF);
 493        tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, inv);
 494        dead_tmp(tmp);
 495        tmp = load_cpu_field(VF);
 496        tmp2 = load_cpu_field(NF);
 497        tcg_gen_xor_i32(tmp, tmp, tmp2);
 498        dead_tmp(tmp2);
 499        tcg_gen_brcondi_i32(TCG_COND_GE, tmp, 0, label);
 500        gen_set_label(inv);
 501        break;
 502    case 13: /* le: Z || N != V */
 503        tmp = load_cpu_field(ZF);
 504        tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, label);
 505        dead_tmp(tmp);
 506        tmp = load_cpu_field(VF);
 507        tmp2 = load_cpu_field(NF);
 508        tcg_gen_xor_i32(tmp, tmp, tmp2);
 509        dead_tmp(tmp2);
 510        tcg_gen_brcondi_i32(TCG_COND_LT, tmp, 0, label);
 511        break;
 512    default:
 513        fprintf(stderr, "Bad condition code 0x%x\n", cc);
 514        abort();
 515    }
 516    dead_tmp(tmp);
 517}
 518
 519static const uint8_t table_logic_cc[16] = {
 520    1, /* and */    1, /* xor */    0, /* sub */    0, /* rsb */
 521    0, /* add */    0, /* adc */    0, /* sbc */    0, /* rsc */
 522    1, /* andl */   1, /* xorl */   0, /* cmp */    0, /* cmn */
 523    1, /* orr */    1, /* mov */    1, /* bic */    1, /* mvn */
 524};
 525
 526/* Set PC state from an immediate address.  */
 527static inline void gen_bx_im(DisasContext *s, uint32_t addr)
 528{
 529    s->is_jmp = DISAS_UPDATE;
 530    tcg_gen_movi_i32(cpu_R[31], addr & ~3);
 531}
 532
 533/* Set PC state from var.  var is marked as dead.  */
 534static inline void gen_bx(DisasContext *s, TCGv var)
 535{
 536    s->is_jmp = DISAS_UPDATE;
 537    tcg_gen_andi_i32(cpu_R[31], var, ~3);
 538    dead_tmp(var);
 539}
 540
 541static inline void store_reg_bx(DisasContext *s, int reg, TCGv var)
 542{
 543    store_reg(s, reg, var);
 544}
 545
 546static inline TCGv gen_ld8s(TCGv addr, int index)
 547{
 548    TCGv tmp = new_tmp();
 549    tcg_gen_qemu_ld8s(tmp, addr, index);
 550    return tmp;
 551}
 552
 553static inline TCGv gen_ld8u(TCGv addr, int index)
 554{
 555    TCGv tmp = new_tmp();
 556    tcg_gen_qemu_ld8u(tmp, addr, index);
 557    return tmp;
 558}
 559
 560static inline TCGv gen_ld16s(TCGv addr, int index)
 561{
 562    TCGv tmp = new_tmp();
 563    tcg_gen_qemu_ld16s(tmp, addr, index);
 564    return tmp;
 565}
 566
 567static inline TCGv gen_ld16u(TCGv addr, int index)
 568{
 569    TCGv tmp = new_tmp();
 570    tcg_gen_qemu_ld16u(tmp, addr, index);
 571    return tmp;
 572}
 573
 574static inline TCGv gen_ld32(TCGv addr, int index)
 575{
 576    TCGv tmp = new_tmp();
 577    tcg_gen_qemu_ld32u(tmp, addr, index);
 578    return tmp;
 579}
 580
 581static inline void gen_st8(TCGv val, TCGv addr, int index)
 582{
 583    tcg_gen_qemu_st8(val, addr, index);
 584    dead_tmp(val);
 585}
 586
 587static inline void gen_st16(TCGv val, TCGv addr, int index)
 588{
 589    tcg_gen_qemu_st16(val, addr, index);
 590    dead_tmp(val);
 591}
 592
 593static inline void gen_st32(TCGv val, TCGv addr, int index)
 594{
 595    tcg_gen_qemu_st32(val, addr, index);
 596    dead_tmp(val);
 597}
 598
 599static inline void gen_set_pc_im(uint32_t val)
 600{
 601    tcg_gen_movi_i32(cpu_R[31], val);
 602}
 603
 604/* Force a TB lookup after an instruction that changes the CPU state.  */
 605static inline void gen_lookup_tb(DisasContext *s)
 606{
 607    tcg_gen_movi_i32(cpu_R[31], s->pc & ~1);
 608    s->is_jmp = DISAS_UPDATE;
 609}
 610
 611static inline void gen_add_data_offset(DisasContext *s, unsigned int insn,
 612        TCGv var)
 613{
 614    int val;
 615    TCGv offset;
 616
 617    if (UCOP_SET(29)) {
 618        /* immediate */
 619        val = UCOP_IMM14;
 620        if (!UCOP_SET_U) {
 621            val = -val;
 622        }
 623        if (val != 0) {
 624            tcg_gen_addi_i32(var, var, val);
 625        }
 626    } else {
 627        /* shift/register */
 628        offset = load_reg(s, UCOP_REG_M);
 629        gen_uc32_shift_im(offset, UCOP_SH_OP, UCOP_SH_IM, 0);
 630        if (!UCOP_SET_U) {
 631            tcg_gen_sub_i32(var, var, offset);
 632        } else {
 633            tcg_gen_add_i32(var, var, offset);
 634        }
 635        dead_tmp(offset);
 636    }
 637}
 638
 639static inline void gen_add_datah_offset(DisasContext *s, unsigned int insn,
 640        TCGv var)
 641{
 642    int val;
 643    TCGv offset;
 644
 645    if (UCOP_SET(26)) {
 646        /* immediate */
 647        val = (insn & 0x1f) | ((insn >> 4) & 0x3e0);
 648        if (!UCOP_SET_U) {
 649            val = -val;
 650        }
 651        if (val != 0) {
 652            tcg_gen_addi_i32(var, var, val);
 653        }
 654    } else {
 655        /* register */
 656        offset = load_reg(s, UCOP_REG_M);
 657        if (!UCOP_SET_U) {
 658            tcg_gen_sub_i32(var, var, offset);
 659        } else {
 660            tcg_gen_add_i32(var, var, offset);
 661        }
 662        dead_tmp(offset);
 663    }
 664}
 665
 666static inline long ucf64_reg_offset(int reg)
 667{
 668    if (reg & 1) {
 669        return offsetof(CPUUniCore32State, ucf64.regs[reg >> 1])
 670          + offsetof(CPU_DoubleU, l.upper);
 671    } else {
 672        return offsetof(CPUUniCore32State, ucf64.regs[reg >> 1])
 673          + offsetof(CPU_DoubleU, l.lower);
 674    }
 675}
 676
 677#define ucf64_gen_ld32(reg)      load_cpu_offset(ucf64_reg_offset(reg))
 678#define ucf64_gen_st32(var, reg) store_cpu_offset(var, ucf64_reg_offset(reg))
 679
 680/* UniCore-F64 single load/store I_offset */
 681static void do_ucf64_ldst_i(CPUUniCore32State *env, DisasContext *s, uint32_t insn)
 682{
 683    int offset;
 684    TCGv tmp;
 685    TCGv addr;
 686
 687    addr = load_reg(s, UCOP_REG_N);
 688    if (!UCOP_SET_P && !UCOP_SET_W) {
 689        ILLEGAL;
 690    }
 691
 692    if (UCOP_SET_P) {
 693        offset = UCOP_IMM10 << 2;
 694        if (!UCOP_SET_U) {
 695            offset = -offset;
 696        }
 697        if (offset != 0) {
 698            tcg_gen_addi_i32(addr, addr, offset);
 699        }
 700    }
 701
 702    if (UCOP_SET_L) { /* load */
 703        tmp = gen_ld32(addr, IS_USER(s));
 704        ucf64_gen_st32(tmp, UCOP_REG_D);
 705    } else { /* store */
 706        tmp = ucf64_gen_ld32(UCOP_REG_D);
 707        gen_st32(tmp, addr, IS_USER(s));
 708    }
 709
 710    if (!UCOP_SET_P) {
 711        offset = UCOP_IMM10 << 2;
 712        if (!UCOP_SET_U) {
 713            offset = -offset;
 714        }
 715        if (offset != 0) {
 716            tcg_gen_addi_i32(addr, addr, offset);
 717        }
 718    }
 719    if (UCOP_SET_W) {
 720        store_reg(s, UCOP_REG_N, addr);
 721    } else {
 722        dead_tmp(addr);
 723    }
 724}
 725
 726/* UniCore-F64 load/store multiple words */
 727static void do_ucf64_ldst_m(CPUUniCore32State *env, DisasContext *s, uint32_t insn)
 728{
 729    unsigned int i;
 730    int j, n, freg;
 731    TCGv tmp;
 732    TCGv addr;
 733
 734    if (UCOP_REG_D != 0) {
 735        ILLEGAL;
 736    }
 737    if (UCOP_REG_N == 31) {
 738        ILLEGAL;
 739    }
 740    if ((insn << 24) == 0) {
 741        ILLEGAL;
 742    }
 743
 744    addr = load_reg(s, UCOP_REG_N);
 745
 746    n = 0;
 747    for (i = 0; i < 8; i++) {
 748        if (UCOP_SET(i)) {
 749            n++;
 750        }
 751    }
 752
 753    if (UCOP_SET_U) {
 754        if (UCOP_SET_P) { /* pre increment */
 755            tcg_gen_addi_i32(addr, addr, 4);
 756        } /* unnecessary to do anything when post increment */
 757    } else {
 758        if (UCOP_SET_P) { /* pre decrement */
 759            tcg_gen_addi_i32(addr, addr, -(n * 4));
 760        } else { /* post decrement */
 761            if (n != 1) {
 762                tcg_gen_addi_i32(addr, addr, -((n - 1) * 4));
 763            }
 764        }
 765    }
 766
 767    freg = ((insn >> 8) & 3) << 3; /* freg should be 0, 8, 16, 24 */
 768
 769    for (i = 0, j = 0; i < 8; i++, freg++) {
 770        if (!UCOP_SET(i)) {
 771            continue;
 772        }
 773
 774        if (UCOP_SET_L) { /* load */
 775            tmp = gen_ld32(addr, IS_USER(s));
 776            ucf64_gen_st32(tmp, freg);
 777        } else { /* store */
 778            tmp = ucf64_gen_ld32(freg);
 779            gen_st32(tmp, addr, IS_USER(s));
 780        }
 781
 782        j++;
 783        /* unnecessary to add after the last transfer */
 784        if (j != n) {
 785            tcg_gen_addi_i32(addr, addr, 4);
 786        }
 787    }
 788
 789    if (UCOP_SET_W) { /* write back */
 790        if (UCOP_SET_U) {
 791            if (!UCOP_SET_P) { /* post increment */
 792                tcg_gen_addi_i32(addr, addr, 4);
 793            } /* unnecessary to do anything when pre increment */
 794        } else {
 795            if (UCOP_SET_P) {
 796                /* pre decrement */
 797                if (n != 1) {
 798                    tcg_gen_addi_i32(addr, addr, -((n - 1) * 4));
 799                }
 800            } else {
 801                /* post decrement */
 802                tcg_gen_addi_i32(addr, addr, -(n * 4));
 803            }
 804        }
 805        store_reg(s, UCOP_REG_N, addr);
 806    } else {
 807        dead_tmp(addr);
 808    }
 809}
 810
 811/* UniCore-F64 mrc/mcr */
 812static void do_ucf64_trans(CPUUniCore32State *env, DisasContext *s, uint32_t insn)
 813{
 814    TCGv tmp;
 815
 816    if ((insn & 0xfe0003ff) == 0xe2000000) {
 817        /* control register */
 818        if ((UCOP_REG_N != UC32_UCF64_FPSCR) || (UCOP_REG_D == 31)) {
 819            ILLEGAL;
 820        }
 821        if (UCOP_SET(24)) {
 822            /* CFF */
 823            tmp = new_tmp();
 824            gen_helper_ucf64_get_fpscr(tmp, cpu_env);
 825            store_reg(s, UCOP_REG_D, tmp);
 826        } else {
 827            /* CTF */
 828            tmp = load_reg(s, UCOP_REG_D);
 829            gen_helper_ucf64_set_fpscr(cpu_env, tmp);
 830            dead_tmp(tmp);
 831            gen_lookup_tb(s);
 832        }
 833        return;
 834    }
 835    if ((insn & 0xfe0003ff) == 0xe0000000) {
 836        /* general register */
 837        if (UCOP_REG_D == 31) {
 838            ILLEGAL;
 839        }
 840        if (UCOP_SET(24)) { /* MFF */
 841            tmp = ucf64_gen_ld32(UCOP_REG_N);
 842            store_reg(s, UCOP_REG_D, tmp);
 843        } else { /* MTF */
 844            tmp = load_reg(s, UCOP_REG_D);
 845            ucf64_gen_st32(tmp, UCOP_REG_N);
 846        }
 847        return;
 848    }
 849    if ((insn & 0xfb000000) == 0xe9000000) {
 850        /* MFFC */
 851        if (UCOP_REG_D != 31) {
 852            ILLEGAL;
 853        }
 854        if (UCOP_UCF64_COND & 0x8) {
 855            ILLEGAL;
 856        }
 857
 858        tmp = new_tmp();
 859        tcg_gen_movi_i32(tmp, UCOP_UCF64_COND);
 860        if (UCOP_SET(26)) {
 861            tcg_gen_ld_i64(cpu_F0d, cpu_env, ucf64_reg_offset(UCOP_REG_N));
 862            tcg_gen_ld_i64(cpu_F1d, cpu_env, ucf64_reg_offset(UCOP_REG_M));
 863            gen_helper_ucf64_cmpd(cpu_F0d, cpu_F1d, tmp, cpu_env);
 864        } else {
 865            tcg_gen_ld_i32(cpu_F0s, cpu_env, ucf64_reg_offset(UCOP_REG_N));
 866            tcg_gen_ld_i32(cpu_F1s, cpu_env, ucf64_reg_offset(UCOP_REG_M));
 867            gen_helper_ucf64_cmps(cpu_F0s, cpu_F1s, tmp, cpu_env);
 868        }
 869        dead_tmp(tmp);
 870        return;
 871    }
 872    ILLEGAL;
 873}
 874
 875/* UniCore-F64 convert instructions */
 876static void do_ucf64_fcvt(CPUUniCore32State *env, DisasContext *s, uint32_t insn)
 877{
 878    if (UCOP_UCF64_FMT == 3) {
 879        ILLEGAL;
 880    }
 881    if (UCOP_REG_N != 0) {
 882        ILLEGAL;
 883    }
 884    switch (UCOP_UCF64_FUNC) {
 885    case 0: /* cvt.s */
 886        switch (UCOP_UCF64_FMT) {
 887        case 1 /* d */:
 888            tcg_gen_ld_i64(cpu_F0d, cpu_env, ucf64_reg_offset(UCOP_REG_M));
 889            gen_helper_ucf64_df2sf(cpu_F0s, cpu_F0d, cpu_env);
 890            tcg_gen_st_i32(cpu_F0s, cpu_env, ucf64_reg_offset(UCOP_REG_D));
 891            break;
 892        case 2 /* w */:
 893            tcg_gen_ld_i32(cpu_F0s, cpu_env, ucf64_reg_offset(UCOP_REG_M));
 894            gen_helper_ucf64_si2sf(cpu_F0s, cpu_F0s, cpu_env);
 895            tcg_gen_st_i32(cpu_F0s, cpu_env, ucf64_reg_offset(UCOP_REG_D));
 896            break;
 897        default /* s */:
 898            ILLEGAL;
 899            break;
 900        }
 901        break;
 902    case 1: /* cvt.d */
 903        switch (UCOP_UCF64_FMT) {
 904        case 0 /* s */:
 905            tcg_gen_ld_i32(cpu_F0s, cpu_env, ucf64_reg_offset(UCOP_REG_M));
 906            gen_helper_ucf64_sf2df(cpu_F0d, cpu_F0s, cpu_env);
 907            tcg_gen_st_i64(cpu_F0d, cpu_env, ucf64_reg_offset(UCOP_REG_D));
 908            break;
 909        case 2 /* w */:
 910            tcg_gen_ld_i32(cpu_F0s, cpu_env, ucf64_reg_offset(UCOP_REG_M));
 911            gen_helper_ucf64_si2df(cpu_F0d, cpu_F0s, cpu_env);
 912            tcg_gen_st_i64(cpu_F0d, cpu_env, ucf64_reg_offset(UCOP_REG_D));
 913            break;
 914        default /* d */:
 915            ILLEGAL;
 916            break;
 917        }
 918        break;
 919    case 4: /* cvt.w */
 920        switch (UCOP_UCF64_FMT) {
 921        case 0 /* s */:
 922            tcg_gen_ld_i32(cpu_F0s, cpu_env, ucf64_reg_offset(UCOP_REG_M));
 923            gen_helper_ucf64_sf2si(cpu_F0s, cpu_F0s, cpu_env);
 924            tcg_gen_st_i32(cpu_F0s, cpu_env, ucf64_reg_offset(UCOP_REG_D));
 925            break;
 926        case 1 /* d */:
 927            tcg_gen_ld_i64(cpu_F0d, cpu_env, ucf64_reg_offset(UCOP_REG_M));
 928            gen_helper_ucf64_df2si(cpu_F0s, cpu_F0d, cpu_env);
 929            tcg_gen_st_i32(cpu_F0s, cpu_env, ucf64_reg_offset(UCOP_REG_D));
 930            break;
 931    default /* w */:
 932            ILLEGAL;
 933            break;
 934        }
 935        break;
 936    default:
 937        ILLEGAL;
 938    }
 939}
 940
 941/* UniCore-F64 compare instructions */
 942static void do_ucf64_fcmp(CPUUniCore32State *env, DisasContext *s, uint32_t insn)
 943{
 944    if (UCOP_SET(25)) {
 945        ILLEGAL;
 946    }
 947    if (UCOP_REG_D != 0) {
 948        ILLEGAL;
 949    }
 950
 951    ILLEGAL; /* TODO */
 952    if (UCOP_SET(24)) {
 953        tcg_gen_ld_i64(cpu_F0d, cpu_env, ucf64_reg_offset(UCOP_REG_N));
 954        tcg_gen_ld_i64(cpu_F1d, cpu_env, ucf64_reg_offset(UCOP_REG_M));
 955        /* gen_helper_ucf64_cmpd(cpu_F0d, cpu_F1d, cpu_env); */
 956    } else {
 957        tcg_gen_ld_i32(cpu_F0s, cpu_env, ucf64_reg_offset(UCOP_REG_N));
 958        tcg_gen_ld_i32(cpu_F1s, cpu_env, ucf64_reg_offset(UCOP_REG_M));
 959        /* gen_helper_ucf64_cmps(cpu_F0s, cpu_F1s, cpu_env); */
 960    }
 961}
 962
 963#define gen_helper_ucf64_movs(x, y)      do { } while (0)
 964#define gen_helper_ucf64_movd(x, y)      do { } while (0)
 965
 966#define UCF64_OP1(name)    do {                           \
 967        if (UCOP_REG_N != 0) {                            \
 968            ILLEGAL;                                      \
 969        }                                                 \
 970        switch (UCOP_UCF64_FMT) {                         \
 971        case 0 /* s */:                                   \
 972            tcg_gen_ld_i32(cpu_F0s, cpu_env,              \
 973                           ucf64_reg_offset(UCOP_REG_M)); \
 974            gen_helper_ucf64_##name##s(cpu_F0s, cpu_F0s); \
 975            tcg_gen_st_i32(cpu_F0s, cpu_env,              \
 976                           ucf64_reg_offset(UCOP_REG_D)); \
 977            break;                                        \
 978        case 1 /* d */:                                   \
 979            tcg_gen_ld_i64(cpu_F0d, cpu_env,              \
 980                           ucf64_reg_offset(UCOP_REG_M)); \
 981            gen_helper_ucf64_##name##d(cpu_F0d, cpu_F0d); \
 982            tcg_gen_st_i64(cpu_F0d, cpu_env,              \
 983                           ucf64_reg_offset(UCOP_REG_D)); \
 984            break;                                        \
 985        case 2 /* w */:                                   \
 986            ILLEGAL;                                      \
 987            break;                                        \
 988        }                                                 \
 989    } while (0)
 990
 991#define UCF64_OP2(name)    do {                           \
 992        switch (UCOP_UCF64_FMT) {                         \
 993        case 0 /* s */:                                   \
 994            tcg_gen_ld_i32(cpu_F0s, cpu_env,              \
 995                           ucf64_reg_offset(UCOP_REG_N)); \
 996            tcg_gen_ld_i32(cpu_F1s, cpu_env,              \
 997                           ucf64_reg_offset(UCOP_REG_M)); \
 998            gen_helper_ucf64_##name##s(cpu_F0s,           \
 999                           cpu_F0s, cpu_F1s, cpu_env);    \
1000            tcg_gen_st_i32(cpu_F0s, cpu_env,              \
1001                           ucf64_reg_offset(UCOP_REG_D)); \
1002            break;                                        \
1003        case 1 /* d */:                                   \
1004            tcg_gen_ld_i64(cpu_F0d, cpu_env,              \
1005                           ucf64_reg_offset(UCOP_REG_N)); \
1006            tcg_gen_ld_i64(cpu_F1d, cpu_env,              \
1007                           ucf64_reg_offset(UCOP_REG_M)); \
1008            gen_helper_ucf64_##name##d(cpu_F0d,           \
1009                           cpu_F0d, cpu_F1d, cpu_env);    \
1010            tcg_gen_st_i64(cpu_F0d, cpu_env,              \
1011                           ucf64_reg_offset(UCOP_REG_D)); \
1012            break;                                        \
1013        case 2 /* w */:                                   \
1014            ILLEGAL;                                      \
1015            break;                                        \
1016        }                                                 \
1017    } while (0)
1018
1019/* UniCore-F64 data processing */
1020static void do_ucf64_datap(CPUUniCore32State *env, DisasContext *s, uint32_t insn)
1021{
1022    if (UCOP_UCF64_FMT == 3) {
1023        ILLEGAL;
1024    }
1025    switch (UCOP_UCF64_FUNC) {
1026    case 0: /* add */
1027        UCF64_OP2(add);
1028        break;
1029    case 1: /* sub */
1030        UCF64_OP2(sub);
1031        break;
1032    case 2: /* mul */
1033        UCF64_OP2(mul);
1034        break;
1035    case 4: /* div */
1036        UCF64_OP2(div);
1037        break;
1038    case 5: /* abs */
1039        UCF64_OP1(abs);
1040        break;
1041    case 6: /* mov */
1042        UCF64_OP1(mov);
1043        break;
1044    case 7: /* neg */
1045        UCF64_OP1(neg);
1046        break;
1047    default:
1048        ILLEGAL;
1049    }
1050}
1051
1052/* Disassemble an F64 instruction */
1053static void disas_ucf64_insn(CPUUniCore32State *env, DisasContext *s, uint32_t insn)
1054{
1055    if (!UCOP_SET(29)) {
1056        if (UCOP_SET(26)) {
1057            do_ucf64_ldst_m(env, s, insn);
1058        } else {
1059            do_ucf64_ldst_i(env, s, insn);
1060        }
1061    } else {
1062        if (UCOP_SET(5)) {
1063            switch ((insn >> 26) & 0x3) {
1064            case 0:
1065                do_ucf64_datap(env, s, insn);
1066                break;
1067            case 1:
1068                ILLEGAL;
1069                break;
1070            case 2:
1071                do_ucf64_fcvt(env, s, insn);
1072                break;
1073            case 3:
1074                do_ucf64_fcmp(env, s, insn);
1075                break;
1076            }
1077        } else {
1078            do_ucf64_trans(env, s, insn);
1079        }
1080    }
1081}
1082
1083static inline bool use_goto_tb(DisasContext *s, uint32_t dest)
1084{
1085#ifndef CONFIG_USER_ONLY
1086    return (s->tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK);
1087#else
1088    return true;
1089#endif
1090}
1091
1092static inline void gen_goto_tb(DisasContext *s, int n, uint32_t dest)
1093{
1094    if (use_goto_tb(s, dest)) {
1095        tcg_gen_goto_tb(n);
1096        gen_set_pc_im(dest);
1097        tcg_gen_exit_tb(s->tb, n);
1098    } else {
1099        gen_set_pc_im(dest);
1100        tcg_gen_exit_tb(NULL, 0);
1101    }
1102}
1103
1104static inline void gen_jmp(DisasContext *s, uint32_t dest)
1105{
1106    if (unlikely(s->singlestep_enabled)) {
1107        /* An indirect jump so that we still trigger the debug exception.  */
1108        gen_bx_im(s, dest);
1109    } else {
1110        gen_goto_tb(s, 0, dest);
1111        s->is_jmp = DISAS_TB_JUMP;
1112    }
1113}
1114
1115/* Returns nonzero if access to the PSR is not permitted. Marks t0 as dead. */
1116static int gen_set_psr(DisasContext *s, uint32_t mask, int bsr, TCGv t0)
1117{
1118    TCGv tmp;
1119    if (bsr) {
1120        /* ??? This is also undefined in system mode.  */
1121        if (IS_USER(s)) {
1122            return 1;
1123        }
1124
1125        tmp = load_cpu_field(bsr);
1126        tcg_gen_andi_i32(tmp, tmp, ~mask);
1127        tcg_gen_andi_i32(t0, t0, mask);
1128        tcg_gen_or_i32(tmp, tmp, t0);
1129        store_cpu_field(tmp, bsr);
1130    } else {
1131        gen_set_asr(t0, mask);
1132    }
1133    dead_tmp(t0);
1134    gen_lookup_tb(s);
1135    return 0;
1136}
1137
1138/* Generate an old-style exception return. Marks pc as dead. */
1139static void gen_exception_return(DisasContext *s, TCGv pc)
1140{
1141    TCGv tmp;
1142    store_reg(s, 31, pc);
1143    tmp = load_cpu_field(bsr);
1144    gen_set_asr(tmp, 0xffffffff);
1145    dead_tmp(tmp);
1146    s->is_jmp = DISAS_UPDATE;
1147}
1148
1149static void disas_coproc_insn(CPUUniCore32State *env, DisasContext *s,
1150        uint32_t insn)
1151{
1152    switch (UCOP_CPNUM) {
1153#ifndef CONFIG_USER_ONLY
1154    case 0:
1155        disas_cp0_insn(env, s, insn);
1156        break;
1157    case 1:
1158        disas_ocd_insn(env, s, insn);
1159        break;
1160#endif
1161    case 2:
1162        disas_ucf64_insn(env, s, insn);
1163        break;
1164    default:
1165        /* Unknown coprocessor. */
1166        cpu_abort(env_cpu(env), "Unknown coprocessor!");
1167    }
1168}
1169
1170/* data processing instructions */
1171static void do_datap(CPUUniCore32State *env, DisasContext *s, uint32_t insn)
1172{
1173    TCGv tmp;
1174    TCGv tmp2;
1175    int logic_cc;
1176
1177    if (UCOP_OPCODES == 0x0f || UCOP_OPCODES == 0x0d) {
1178        if (UCOP_SET(23)) { /* CMOV instructions */
1179            if ((UCOP_CMOV_COND == 0xe) || (UCOP_CMOV_COND == 0xf)) {
1180                ILLEGAL;
1181            }
1182            /* if not always execute, we generate a conditional jump to
1183               next instruction */
1184            s->condlabel = gen_new_label();
1185            gen_test_cc(UCOP_CMOV_COND ^ 1, s->condlabel);
1186            s->condjmp = 1;
1187        }
1188    }
1189
1190    logic_cc = table_logic_cc[UCOP_OPCODES] & (UCOP_SET_S >> 24);
1191
1192    if (UCOP_SET(29)) {
1193        unsigned int val;
1194        /* immediate operand */
1195        val = UCOP_IMM_9;
1196        if (UCOP_SH_IM) {
1197            val = (val >> UCOP_SH_IM) | (val << (32 - UCOP_SH_IM));
1198        }
1199        tmp2 = new_tmp();
1200        tcg_gen_movi_i32(tmp2, val);
1201        if (logic_cc && UCOP_SH_IM) {
1202            gen_set_CF_bit31(tmp2);
1203        }
1204   } else {
1205        /* register */
1206        tmp2 = load_reg(s, UCOP_REG_M);
1207        if (UCOP_SET(5)) {
1208            tmp = load_reg(s, UCOP_REG_S);
1209            gen_uc32_shift_reg(tmp2, UCOP_SH_OP, tmp, logic_cc);
1210        } else {
1211            gen_uc32_shift_im(tmp2, UCOP_SH_OP, UCOP_SH_IM, logic_cc);
1212        }
1213    }
1214
1215    if (UCOP_OPCODES != 0x0f && UCOP_OPCODES != 0x0d) {
1216        tmp = load_reg(s, UCOP_REG_N);
1217    } else {
1218        tmp = NULL;
1219    }
1220
1221    switch (UCOP_OPCODES) {
1222    case 0x00:
1223        tcg_gen_and_i32(tmp, tmp, tmp2);
1224        if (logic_cc) {
1225            gen_logic_CC(tmp);
1226        }
1227        store_reg_bx(s, UCOP_REG_D, tmp);
1228        break;
1229    case 0x01:
1230        tcg_gen_xor_i32(tmp, tmp, tmp2);
1231        if (logic_cc) {
1232            gen_logic_CC(tmp);
1233        }
1234        store_reg_bx(s, UCOP_REG_D, tmp);
1235        break;
1236    case 0x02:
1237        if (UCOP_SET_S && UCOP_REG_D == 31) {
1238            /* SUBS r31, ... is used for exception return.  */
1239            if (IS_USER(s)) {
1240                ILLEGAL;
1241            }
1242            gen_helper_sub_cc(tmp, cpu_env, tmp, tmp2);
1243            gen_exception_return(s, tmp);
1244        } else {
1245            if (UCOP_SET_S) {
1246                gen_helper_sub_cc(tmp, cpu_env, tmp, tmp2);
1247            } else {
1248                tcg_gen_sub_i32(tmp, tmp, tmp2);
1249            }
1250            store_reg_bx(s, UCOP_REG_D, tmp);
1251        }
1252        break;
1253    case 0x03:
1254        if (UCOP_SET_S) {
1255            gen_helper_sub_cc(tmp, cpu_env, tmp2, tmp);
1256        } else {
1257            tcg_gen_sub_i32(tmp, tmp2, tmp);
1258        }
1259        store_reg_bx(s, UCOP_REG_D, tmp);
1260        break;
1261    case 0x04:
1262        if (UCOP_SET_S) {
1263            gen_helper_add_cc(tmp, cpu_env, tmp, tmp2);
1264        } else {
1265            tcg_gen_add_i32(tmp, tmp, tmp2);
1266        }
1267        store_reg_bx(s, UCOP_REG_D, tmp);
1268        break;
1269    case 0x05:
1270        if (UCOP_SET_S) {
1271            gen_helper_adc_cc(tmp, cpu_env, tmp, tmp2);
1272        } else {
1273            gen_add_carry(tmp, tmp, tmp2);
1274        }
1275        store_reg_bx(s, UCOP_REG_D, tmp);
1276        break;
1277    case 0x06:
1278        if (UCOP_SET_S) {
1279            gen_helper_sbc_cc(tmp, cpu_env, tmp, tmp2);
1280        } else {
1281            gen_sub_carry(tmp, tmp, tmp2);
1282        }
1283        store_reg_bx(s, UCOP_REG_D, tmp);
1284        break;
1285    case 0x07:
1286        if (UCOP_SET_S) {
1287            gen_helper_sbc_cc(tmp, cpu_env, tmp2, tmp);
1288        } else {
1289            gen_sub_carry(tmp, tmp2, tmp);
1290        }
1291        store_reg_bx(s, UCOP_REG_D, tmp);
1292        break;
1293    case 0x08:
1294        if (UCOP_SET_S) {
1295            tcg_gen_and_i32(tmp, tmp, tmp2);
1296            gen_logic_CC(tmp);
1297        }
1298        dead_tmp(tmp);
1299        break;
1300    case 0x09:
1301        if (UCOP_SET_S) {
1302            tcg_gen_xor_i32(tmp, tmp, tmp2);
1303            gen_logic_CC(tmp);
1304        }
1305        dead_tmp(tmp);
1306        break;
1307    case 0x0a:
1308        if (UCOP_SET_S) {
1309            gen_helper_sub_cc(tmp, cpu_env, tmp, tmp2);
1310        }
1311        dead_tmp(tmp);
1312        break;
1313    case 0x0b:
1314        if (UCOP_SET_S) {
1315            gen_helper_add_cc(tmp, cpu_env, tmp, tmp2);
1316        }
1317        dead_tmp(tmp);
1318        break;
1319    case 0x0c:
1320        tcg_gen_or_i32(tmp, tmp, tmp2);
1321        if (logic_cc) {
1322            gen_logic_CC(tmp);
1323        }
1324        store_reg_bx(s, UCOP_REG_D, tmp);
1325        break;
1326    case 0x0d:
1327        if (logic_cc && UCOP_REG_D == 31) {
1328            /* MOVS r31, ... is used for exception return.  */
1329            if (IS_USER(s)) {
1330                ILLEGAL;
1331            }
1332            gen_exception_return(s, tmp2);
1333        } else {
1334            if (logic_cc) {
1335                gen_logic_CC(tmp2);
1336            }
1337            store_reg_bx(s, UCOP_REG_D, tmp2);
1338        }
1339        break;
1340    case 0x0e:
1341        tcg_gen_andc_i32(tmp, tmp, tmp2);
1342        if (logic_cc) {
1343            gen_logic_CC(tmp);
1344        }
1345        store_reg_bx(s, UCOP_REG_D, tmp);
1346        break;
1347    default:
1348    case 0x0f:
1349        tcg_gen_not_i32(tmp2, tmp2);
1350        if (logic_cc) {
1351            gen_logic_CC(tmp2);
1352        }
1353        store_reg_bx(s, UCOP_REG_D, tmp2);
1354        break;
1355    }
1356    if (UCOP_OPCODES != 0x0f && UCOP_OPCODES != 0x0d) {
1357        dead_tmp(tmp2);
1358    }
1359}
1360
1361/* multiply */
1362static void do_mult(CPUUniCore32State *env, DisasContext *s, uint32_t insn)
1363{
1364    TCGv tmp, tmp2, tmp3, tmp4;
1365
1366    if (UCOP_SET(27)) {
1367        /* 64 bit mul */
1368        tmp = load_reg(s, UCOP_REG_M);
1369        tmp2 = load_reg(s, UCOP_REG_N);
1370        if (UCOP_SET(26)) {
1371            tcg_gen_muls2_i32(tmp, tmp2, tmp, tmp2);
1372        } else {
1373            tcg_gen_mulu2_i32(tmp, tmp2, tmp, tmp2);
1374        }
1375        if (UCOP_SET(25)) { /* mult accumulate */
1376            tmp3 = load_reg(s, UCOP_REG_LO);
1377            tmp4 = load_reg(s, UCOP_REG_HI);
1378            tcg_gen_add2_i32(tmp, tmp2, tmp, tmp2, tmp3, tmp4);
1379            dead_tmp(tmp3);
1380            dead_tmp(tmp4);
1381        }
1382        store_reg(s, UCOP_REG_LO, tmp);
1383        store_reg(s, UCOP_REG_HI, tmp2);
1384    } else {
1385        /* 32 bit mul */
1386        tmp = load_reg(s, UCOP_REG_M);
1387        tmp2 = load_reg(s, UCOP_REG_N);
1388        tcg_gen_mul_i32(tmp, tmp, tmp2);
1389        dead_tmp(tmp2);
1390        if (UCOP_SET(25)) {
1391            /* Add */
1392            tmp2 = load_reg(s, UCOP_REG_S);
1393            tcg_gen_add_i32(tmp, tmp, tmp2);
1394            dead_tmp(tmp2);
1395        }
1396        if (UCOP_SET_S) {
1397            gen_logic_CC(tmp);
1398        }
1399        store_reg(s, UCOP_REG_D, tmp);
1400    }
1401}
1402
1403/* miscellaneous instructions */
1404static void do_misc(CPUUniCore32State *env, DisasContext *s, uint32_t insn)
1405{
1406    unsigned int val;
1407    TCGv tmp;
1408
1409    if ((insn & 0xffffffe0) == 0x10ffc120) {
1410        /* Trivial implementation equivalent to bx.  */
1411        tmp = load_reg(s, UCOP_REG_M);
1412        gen_bx(s, tmp);
1413        return;
1414    }
1415
1416    if ((insn & 0xfbffc000) == 0x30ffc000) {
1417        /* PSR = immediate */
1418        val = UCOP_IMM_9;
1419        if (UCOP_SH_IM) {
1420            val = (val >> UCOP_SH_IM) | (val << (32 - UCOP_SH_IM));
1421        }
1422        tmp = new_tmp();
1423        tcg_gen_movi_i32(tmp, val);
1424        if (gen_set_psr(s, ~ASR_RESERVED, UCOP_SET_B, tmp)) {
1425            ILLEGAL;
1426        }
1427        return;
1428    }
1429
1430    if ((insn & 0xfbffffe0) == 0x12ffc020) {
1431        /* PSR.flag = reg */
1432        tmp = load_reg(s, UCOP_REG_M);
1433        if (gen_set_psr(s, ASR_NZCV, UCOP_SET_B, tmp)) {
1434            ILLEGAL;
1435        }
1436        return;
1437    }
1438
1439    if ((insn & 0xfbffffe0) == 0x10ffc020) {
1440        /* PSR = reg */
1441        tmp = load_reg(s, UCOP_REG_M);
1442        if (gen_set_psr(s, ~ASR_RESERVED, UCOP_SET_B, tmp)) {
1443            ILLEGAL;
1444        }
1445        return;
1446    }
1447
1448    if ((insn & 0xfbf83fff) == 0x10f80000) {
1449        /* reg = PSR */
1450        if (UCOP_SET_B) {
1451            if (IS_USER(s)) {
1452                ILLEGAL;
1453            }
1454            tmp = load_cpu_field(bsr);
1455        } else {
1456            tmp = new_tmp();
1457            gen_helper_asr_read(tmp, cpu_env);
1458        }
1459        store_reg(s, UCOP_REG_D, tmp);
1460        return;
1461    }
1462
1463    if ((insn & 0xfbf83fe0) == 0x12f80120) {
1464        /* clz */
1465        tmp = load_reg(s, UCOP_REG_M);
1466        if (UCOP_SET(26)) {
1467            /* clo */
1468            tcg_gen_not_i32(tmp, tmp);
1469        }
1470        tcg_gen_clzi_i32(tmp, tmp, 32);
1471        store_reg(s, UCOP_REG_D, tmp);
1472        return;
1473    }
1474
1475    /* otherwise */
1476    ILLEGAL;
1477}
1478
1479/* load/store I_offset and R_offset */
1480static void do_ldst_ir(CPUUniCore32State *env, DisasContext *s, uint32_t insn)
1481{
1482    unsigned int mmu_idx;
1483    TCGv tmp;
1484    TCGv tmp2;
1485
1486    tmp2 = load_reg(s, UCOP_REG_N);
1487    mmu_idx = (IS_USER(s) || (!UCOP_SET_P && UCOP_SET_W));
1488
1489    /* immediate */
1490    if (UCOP_SET_P) {
1491        gen_add_data_offset(s, insn, tmp2);
1492    }
1493
1494    if (UCOP_SET_L) {
1495        /* load */
1496        if (UCOP_SET_B) {
1497            tmp = gen_ld8u(tmp2, mmu_idx);
1498        } else {
1499            tmp = gen_ld32(tmp2, mmu_idx);
1500        }
1501    } else {
1502        /* store */
1503        tmp = load_reg(s, UCOP_REG_D);
1504        if (UCOP_SET_B) {
1505            gen_st8(tmp, tmp2, mmu_idx);
1506        } else {
1507            gen_st32(tmp, tmp2, mmu_idx);
1508        }
1509    }
1510    if (!UCOP_SET_P) {
1511        gen_add_data_offset(s, insn, tmp2);
1512        store_reg(s, UCOP_REG_N, tmp2);
1513    } else if (UCOP_SET_W) {
1514        store_reg(s, UCOP_REG_N, tmp2);
1515    } else {
1516        dead_tmp(tmp2);
1517    }
1518    if (UCOP_SET_L) {
1519        /* Complete the load.  */
1520        if (UCOP_REG_D == 31) {
1521            gen_bx(s, tmp);
1522        } else {
1523            store_reg(s, UCOP_REG_D, tmp);
1524        }
1525    }
1526}
1527
1528/* SWP instruction */
1529static void do_swap(CPUUniCore32State *env, DisasContext *s, uint32_t insn)
1530{
1531    TCGv addr;
1532    TCGv tmp;
1533    TCGv tmp2;
1534
1535    if ((insn & 0xff003fe0) != 0x40000120) {
1536        ILLEGAL;
1537    }
1538
1539    /* ??? This is not really atomic.  However we know
1540       we never have multiple CPUs running in parallel,
1541       so it is good enough.  */
1542    addr = load_reg(s, UCOP_REG_N);
1543    tmp = load_reg(s, UCOP_REG_M);
1544    if (UCOP_SET_B) {
1545        tmp2 = gen_ld8u(addr, IS_USER(s));
1546        gen_st8(tmp, addr, IS_USER(s));
1547    } else {
1548        tmp2 = gen_ld32(addr, IS_USER(s));
1549        gen_st32(tmp, addr, IS_USER(s));
1550    }
1551    dead_tmp(addr);
1552    store_reg(s, UCOP_REG_D, tmp2);
1553}
1554
1555/* load/store hw/sb */
1556static void do_ldst_hwsb(CPUUniCore32State *env, DisasContext *s, uint32_t insn)
1557{
1558    TCGv addr;
1559    TCGv tmp;
1560
1561    if (UCOP_SH_OP == 0) {
1562        do_swap(env, s, insn);
1563        return;
1564    }
1565
1566    addr = load_reg(s, UCOP_REG_N);
1567    if (UCOP_SET_P) {
1568        gen_add_datah_offset(s, insn, addr);
1569    }
1570
1571    if (UCOP_SET_L) { /* load */
1572        switch (UCOP_SH_OP) {
1573        case 1:
1574            tmp = gen_ld16u(addr, IS_USER(s));
1575            break;
1576        case 2:
1577            tmp = gen_ld8s(addr, IS_USER(s));
1578            break;
1579        default: /* see do_swap */
1580        case 3:
1581            tmp = gen_ld16s(addr, IS_USER(s));
1582            break;
1583        }
1584    } else { /* store */
1585        if (UCOP_SH_OP != 1) {
1586            ILLEGAL;
1587        }
1588        tmp = load_reg(s, UCOP_REG_D);
1589        gen_st16(tmp, addr, IS_USER(s));
1590    }
1591    /* Perform base writeback before the loaded value to
1592       ensure correct behavior with overlapping index registers. */
1593    if (!UCOP_SET_P) {
1594        gen_add_datah_offset(s, insn, addr);
1595        store_reg(s, UCOP_REG_N, addr);
1596    } else if (UCOP_SET_W) {
1597        store_reg(s, UCOP_REG_N, addr);
1598    } else {
1599        dead_tmp(addr);
1600    }
1601    if (UCOP_SET_L) {
1602        /* Complete the load.  */
1603        store_reg(s, UCOP_REG_D, tmp);
1604    }
1605}
1606
1607/* load/store multiple words */
1608static void do_ldst_m(CPUUniCore32State *env, DisasContext *s, uint32_t insn)
1609{
1610    unsigned int val, i, mmu_idx;
1611    int j, n, reg, user, loaded_base;
1612    TCGv tmp;
1613    TCGv tmp2;
1614    TCGv addr;
1615    TCGv loaded_var;
1616
1617    if (UCOP_SET(7)) {
1618        ILLEGAL;
1619    }
1620    /* XXX: store correct base if write back */
1621    user = 0;
1622    if (UCOP_SET_B) { /* S bit in instruction table */
1623        if (IS_USER(s)) {
1624            ILLEGAL; /* only usable in supervisor mode */
1625        }
1626        if (UCOP_SET(18) == 0) { /* pc reg */
1627            user = 1;
1628        }
1629    }
1630
1631    mmu_idx = (IS_USER(s) || (!UCOP_SET_P && UCOP_SET_W));
1632    addr = load_reg(s, UCOP_REG_N);
1633
1634    /* compute total size */
1635    loaded_base = 0;
1636    loaded_var = NULL;
1637    n = 0;
1638    for (i = 0; i < 6; i++) {
1639        if (UCOP_SET(i)) {
1640            n++;
1641        }
1642    }
1643    for (i = 9; i < 19; i++) {
1644        if (UCOP_SET(i)) {
1645            n++;
1646        }
1647    }
1648    /* XXX: test invalid n == 0 case ? */
1649    if (UCOP_SET_U) {
1650        if (UCOP_SET_P) {
1651            /* pre increment */
1652            tcg_gen_addi_i32(addr, addr, 4);
1653        } else {
1654            /* post increment */
1655        }
1656    } else {
1657        if (UCOP_SET_P) {
1658            /* pre decrement */
1659            tcg_gen_addi_i32(addr, addr, -(n * 4));
1660        } else {
1661            /* post decrement */
1662            if (n != 1) {
1663                tcg_gen_addi_i32(addr, addr, -((n - 1) * 4));
1664            }
1665        }
1666    }
1667
1668    j = 0;
1669    reg = UCOP_SET(6) ? 16 : 0;
1670    for (i = 0; i < 19; i++, reg++) {
1671        if (i == 6) {
1672            i = i + 3;
1673        }
1674        if (UCOP_SET(i)) {
1675            if (UCOP_SET_L) { /* load */
1676                tmp = gen_ld32(addr, mmu_idx);
1677                if (reg == 31) {
1678                    gen_bx(s, tmp);
1679                } else if (user) {
1680                    tmp2 = tcg_const_i32(reg);
1681                    gen_helper_set_user_reg(cpu_env, tmp2, tmp);
1682                    tcg_temp_free_i32(tmp2);
1683                    dead_tmp(tmp);
1684                } else if (reg == UCOP_REG_N) {
1685                    loaded_var = tmp;
1686                    loaded_base = 1;
1687                } else {
1688                    store_reg(s, reg, tmp);
1689                }
1690            } else { /* store */
1691                if (reg == 31) {
1692                    /* special case: r31 = PC + 4 */
1693                    val = (long)s->pc;
1694                    tmp = new_tmp();
1695                    tcg_gen_movi_i32(tmp, val);
1696                } else if (user) {
1697                    tmp = new_tmp();
1698                    tmp2 = tcg_const_i32(reg);
1699                    gen_helper_get_user_reg(tmp, cpu_env, tmp2);
1700                    tcg_temp_free_i32(tmp2);
1701                } else {
1702                    tmp = load_reg(s, reg);
1703                }
1704                gen_st32(tmp, addr, mmu_idx);
1705            }
1706            j++;
1707            /* no need to add after the last transfer */
1708            if (j != n) {
1709                tcg_gen_addi_i32(addr, addr, 4);
1710            }
1711        }
1712    }
1713    if (UCOP_SET_W) { /* write back */
1714        if (UCOP_SET_U) {
1715            if (UCOP_SET_P) {
1716                /* pre increment */
1717            } else {
1718                /* post increment */
1719                tcg_gen_addi_i32(addr, addr, 4);
1720            }
1721        } else {
1722            if (UCOP_SET_P) {
1723                /* pre decrement */
1724                if (n != 1) {
1725                    tcg_gen_addi_i32(addr, addr, -((n - 1) * 4));
1726                }
1727            } else {
1728                /* post decrement */
1729                tcg_gen_addi_i32(addr, addr, -(n * 4));
1730            }
1731        }
1732        store_reg(s, UCOP_REG_N, addr);
1733    } else {
1734        dead_tmp(addr);
1735    }
1736    if (loaded_base) {
1737        store_reg(s, UCOP_REG_N, loaded_var);
1738    }
1739    if (UCOP_SET_B && !user) {
1740        /* Restore ASR from BSR.  */
1741        tmp = load_cpu_field(bsr);
1742        gen_set_asr(tmp, 0xffffffff);
1743        dead_tmp(tmp);
1744        s->is_jmp = DISAS_UPDATE;
1745    }
1746}
1747
1748/* branch (and link) */
1749static void do_branch(CPUUniCore32State *env, DisasContext *s, uint32_t insn)
1750{
1751    unsigned int val;
1752    int32_t offset;
1753    TCGv tmp;
1754
1755    if (UCOP_COND == 0xf) {
1756        ILLEGAL;
1757    }
1758
1759    if (UCOP_COND != 0xe) {
1760        /* if not always execute, we generate a conditional jump to
1761           next instruction */
1762        s->condlabel = gen_new_label();
1763        gen_test_cc(UCOP_COND ^ 1, s->condlabel);
1764        s->condjmp = 1;
1765    }
1766
1767    val = (int32_t)s->pc;
1768    if (UCOP_SET_L) {
1769        tmp = new_tmp();
1770        tcg_gen_movi_i32(tmp, val);
1771        store_reg(s, 30, tmp);
1772    }
1773    offset = (((int32_t)insn << 8) >> 8);
1774    val += (offset << 2); /* unicore is pc+4 */
1775    gen_jmp(s, val);
1776}
1777
1778static void disas_uc32_insn(CPUUniCore32State *env, DisasContext *s)
1779{
1780    unsigned int insn;
1781
1782    insn = cpu_ldl_code(env, s->pc);
1783    s->pc += 4;
1784
1785    /* UniCore instructions class:
1786     * AAAB BBBC xxxx xxxx xxxx xxxD xxEx xxxx
1787     * AAA  : see switch case
1788     * BBBB : opcodes or cond or PUBW
1789     * C    : S OR L
1790     * D    : 8
1791     * E    : 5
1792     */
1793    switch (insn >> 29) {
1794    case 0x0:
1795        if (UCOP_SET(5) && UCOP_SET(8) && !UCOP_SET(28)) {
1796            do_mult(env, s, insn);
1797            break;
1798        }
1799
1800        if (UCOP_SET(8)) {
1801            do_misc(env, s, insn);
1802            break;
1803        }
1804    case 0x1:
1805        if (((UCOP_OPCODES >> 2) == 2) && !UCOP_SET_S) {
1806            do_misc(env, s, insn);
1807            break;
1808        }
1809        do_datap(env, s, insn);
1810        break;
1811
1812    case 0x2:
1813        if (UCOP_SET(8) && UCOP_SET(5)) {
1814            do_ldst_hwsb(env, s, insn);
1815            break;
1816        }
1817        if (UCOP_SET(8) || UCOP_SET(5)) {
1818            ILLEGAL;
1819        }
1820    case 0x3:
1821        do_ldst_ir(env, s, insn);
1822        break;
1823
1824    case 0x4:
1825        if (UCOP_SET(8)) {
1826            ILLEGAL; /* extended instructions */
1827        }
1828        do_ldst_m(env, s, insn);
1829        break;
1830    case 0x5:
1831        do_branch(env, s, insn);
1832        break;
1833    case 0x6:
1834        /* Coprocessor.  */
1835        disas_coproc_insn(env, s, insn);
1836        break;
1837    case 0x7:
1838        if (!UCOP_SET(28)) {
1839            disas_coproc_insn(env, s, insn);
1840            break;
1841        }
1842        if ((insn & 0xff000000) == 0xff000000) { /* syscall */
1843            gen_set_pc_im(s->pc);
1844            s->is_jmp = DISAS_SYSCALL;
1845            break;
1846        }
1847        ILLEGAL;
1848    }
1849}
1850
1851/* generate intermediate code for basic block 'tb'.  */
1852void gen_intermediate_code(CPUState *cs, TranslationBlock *tb, int max_insns)
1853{
1854    CPUUniCore32State *env = cs->env_ptr;
1855    DisasContext dc1, *dc = &dc1;
1856    target_ulong pc_start;
1857    uint32_t page_start;
1858    int num_insns;
1859
1860    /* generate intermediate code */
1861    num_temps = 0;
1862
1863    pc_start = tb->pc;
1864
1865    dc->tb = tb;
1866
1867    dc->is_jmp = DISAS_NEXT;
1868    dc->pc = pc_start;
1869    dc->singlestep_enabled = cs->singlestep_enabled;
1870    dc->condjmp = 0;
1871    cpu_F0s = tcg_temp_new_i32();
1872    cpu_F1s = tcg_temp_new_i32();
1873    cpu_F0d = tcg_temp_new_i64();
1874    cpu_F1d = tcg_temp_new_i64();
1875    page_start = pc_start & TARGET_PAGE_MASK;
1876    num_insns = 0;
1877
1878#ifndef CONFIG_USER_ONLY
1879    if ((env->uncached_asr & ASR_M) == ASR_MODE_USER) {
1880        dc->user = 1;
1881    } else {
1882        dc->user = 0;
1883    }
1884#endif
1885
1886    gen_tb_start(tb);
1887    do {
1888        tcg_gen_insn_start(dc->pc);
1889        num_insns++;
1890
1891        if (unlikely(cpu_breakpoint_test(cs, dc->pc, BP_ANY))) {
1892            gen_set_pc_im(dc->pc);
1893            gen_exception(EXCP_DEBUG);
1894            dc->is_jmp = DISAS_JUMP;
1895            /* The address covered by the breakpoint must be included in
1896               [tb->pc, tb->pc + tb->size) in order to for it to be
1897               properly cleared -- thus we increment the PC here so that
1898               the logic setting tb->size below does the right thing.  */
1899            dc->pc += 4;
1900            goto done_generating;
1901        }
1902
1903        if (num_insns == max_insns && (tb_cflags(tb) & CF_LAST_IO)) {
1904            gen_io_start();
1905        }
1906
1907        disas_uc32_insn(env, dc);
1908
1909        if (num_temps) {
1910            fprintf(stderr, "Internal resource leak before %08x\n", dc->pc);
1911            num_temps = 0;
1912        }
1913
1914        if (dc->condjmp && !dc->is_jmp) {
1915            gen_set_label(dc->condlabel);
1916            dc->condjmp = 0;
1917        }
1918        /* Translation stops when a conditional branch is encountered.
1919         * Otherwise the subsequent code could get translated several times.
1920         * Also stop translation when a page boundary is reached.  This
1921         * ensures prefetch aborts occur at the right place.  */
1922    } while (!dc->is_jmp && !tcg_op_buf_full() &&
1923             !cs->singlestep_enabled &&
1924             !singlestep &&
1925             dc->pc - page_start < TARGET_PAGE_SIZE &&
1926             num_insns < max_insns);
1927
1928    if (tb_cflags(tb) & CF_LAST_IO) {
1929        if (dc->condjmp) {
1930            /* FIXME:  This can theoretically happen with self-modifying
1931               code.  */
1932            cpu_abort(cs, "IO on conditional branch instruction");
1933        }
1934        gen_io_end();
1935    }
1936
1937    /* At this stage dc->condjmp will only be set when the skipped
1938       instruction was a conditional branch or trap, and the PC has
1939       already been written.  */
1940    if (unlikely(cs->singlestep_enabled)) {
1941        /* Make sure the pc is updated, and raise a debug exception.  */
1942        if (dc->condjmp) {
1943            if (dc->is_jmp == DISAS_SYSCALL) {
1944                gen_exception(UC32_EXCP_PRIV);
1945            } else {
1946                gen_exception(EXCP_DEBUG);
1947            }
1948            gen_set_label(dc->condlabel);
1949        }
1950        if (dc->condjmp || !dc->is_jmp) {
1951            gen_set_pc_im(dc->pc);
1952            dc->condjmp = 0;
1953        }
1954        if (dc->is_jmp == DISAS_SYSCALL && !dc->condjmp) {
1955            gen_exception(UC32_EXCP_PRIV);
1956        } else {
1957            gen_exception(EXCP_DEBUG);
1958        }
1959    } else {
1960        /* While branches must always occur at the end of an IT block,
1961           there are a few other things that can cause us to terminate
1962           the TB in the middel of an IT block:
1963            - Exception generating instructions (bkpt, swi, undefined).
1964            - Page boundaries.
1965            - Hardware watchpoints.
1966           Hardware breakpoints have already been handled and skip this code.
1967         */
1968        switch (dc->is_jmp) {
1969        case DISAS_NEXT:
1970            gen_goto_tb(dc, 1, dc->pc);
1971            break;
1972        default:
1973        case DISAS_JUMP:
1974        case DISAS_UPDATE:
1975            /* indicate that the hash table must be used to find the next TB */
1976            tcg_gen_exit_tb(NULL, 0);
1977            break;
1978        case DISAS_TB_JUMP:
1979            /* nothing more to generate */
1980            break;
1981        case DISAS_SYSCALL:
1982            gen_exception(UC32_EXCP_PRIV);
1983            break;
1984        }
1985        if (dc->condjmp) {
1986            gen_set_label(dc->condlabel);
1987            gen_goto_tb(dc, 1, dc->pc);
1988            dc->condjmp = 0;
1989        }
1990    }
1991
1992done_generating:
1993    gen_tb_end(tb, num_insns);
1994
1995#ifdef DEBUG_DISAS
1996    if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)
1997        && qemu_log_in_addr_range(pc_start)) {
1998        qemu_log_lock();
1999        qemu_log("----------------\n");
2000        qemu_log("IN: %s\n", lookup_symbol(pc_start));
2001        log_target_disas(cs, pc_start, dc->pc - pc_start);
2002        qemu_log("\n");
2003        qemu_log_unlock();
2004    }
2005#endif
2006    tb->size = dc->pc - pc_start;
2007    tb->icount = num_insns;
2008}
2009
2010static const char *cpu_mode_names[16] = {
2011    "USER", "REAL", "INTR", "PRIV", "UM14", "UM15", "UM16", "TRAP",
2012    "UM18", "UM19", "UM1A", "EXTN", "UM1C", "UM1D", "UM1E", "SUSR"
2013};
2014
2015#undef UCF64_DUMP_STATE
2016#ifdef UCF64_DUMP_STATE
2017static void cpu_dump_state_ucf64(CPUUniCore32State *env, int flags)
2018{
2019    int i;
2020    union {
2021        uint32_t i;
2022        float s;
2023    } s0, s1;
2024    CPU_DoubleU d;
2025    /* ??? This assumes float64 and double have the same layout.
2026       Oh well, it's only debug dumps.  */
2027    union {
2028        float64 f64;
2029        double d;
2030    } d0;
2031
2032    for (i = 0; i < 16; i++) {
2033        d.d = env->ucf64.regs[i];
2034        s0.i = d.l.lower;
2035        s1.i = d.l.upper;
2036        d0.f64 = d.d;
2037        qemu_fprintf(f, "s%02d=%08x(%8g) s%02d=%08x(%8g)",
2038                     i * 2, (int)s0.i, s0.s,
2039                     i * 2 + 1, (int)s1.i, s1.s);
2040        qemu_fprintf(f, " d%02d=%" PRIx64 "(%8g)\n",
2041                     i, (uint64_t)d0.f64, d0.d);
2042    }
2043    qemu_fprintf(f, "FPSCR: %08x\n", (int)env->ucf64.xregs[UC32_UCF64_FPSCR]);
2044}
2045#else
2046#define cpu_dump_state_ucf64(env, file, pr, flags)      do { } while (0)
2047#endif
2048
2049void uc32_cpu_dump_state(CPUState *cs, FILE *f, int flags)
2050{
2051    UniCore32CPU *cpu = UNICORE32_CPU(cs);
2052    CPUUniCore32State *env = &cpu->env;
2053    int i;
2054    uint32_t psr;
2055
2056    for (i = 0; i < 32; i++) {
2057        qemu_fprintf(f, "R%02d=%08x", i, env->regs[i]);
2058        if ((i % 4) == 3) {
2059            qemu_fprintf(f, "\n");
2060        } else {
2061            qemu_fprintf(f, " ");
2062        }
2063    }
2064    psr = cpu_asr_read(env);
2065    qemu_fprintf(f, "PSR=%08x %c%c%c%c %s\n",
2066                 psr,
2067                 psr & (1 << 31) ? 'N' : '-',
2068                 psr & (1 << 30) ? 'Z' : '-',
2069                 psr & (1 << 29) ? 'C' : '-',
2070                 psr & (1 << 28) ? 'V' : '-',
2071                 cpu_mode_names[psr & 0xf]);
2072
2073    if (flags & CPU_DUMP_FPU) {
2074        cpu_dump_state_ucf64(env, f, cpu_fprintf, flags);
2075    }
2076}
2077
2078void restore_state_to_opc(CPUUniCore32State *env, TranslationBlock *tb,
2079                          target_ulong *data)
2080{
2081    env->regs[31] = data[0];
2082}
2083