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