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
  21#include "exec/helper-proto.h"
  22#include "exec/helper-gen.h"
  23
  24#include "trace-tcg.h"
  25#include "exec/log.h"
  26
  27
  28/* internal defines */
  29typedef struct DisasContext {
  30    target_ulong pc;
  31    int is_jmp;
  32    /* Nonzero if this instruction has been conditionally skipped.  */
  33    int condjmp;
  34    /* The label that will be jumped to when the instruction is skipped.  */
  35    TCGLabel *condlabel;
  36    struct TranslationBlock *tb;
  37    int singlestep_enabled;
  38#ifndef CONFIG_USER_ONLY
  39    int user;
  40#endif
  41} DisasContext;
  42
  43#ifndef CONFIG_USER_ONLY
  44#define IS_USER(s)      (s->user)
  45#else
  46#define IS_USER(s)      1
  47#endif
  48
  49/* is_jmp field values */
  50#define DISAS_JUMP    DISAS_TARGET_0 /* only pc was modified dynamically */
  51#define DISAS_UPDATE  DISAS_TARGET_1 /* cpu state was modified dynamically */
  52#define DISAS_TB_JUMP DISAS_TARGET_2 /* only pc was modified statically */
  53/* These instructions trap after executing, so defer them until after the
  54   conditional executions state has been updated.  */
  55#define DISAS_SYSCALL DISAS_TARGET_3
  56
  57static TCGv_i32 cpu_R[32];
  58
  59/* FIXME:  These should be removed.  */
  60static TCGv cpu_F0s, cpu_F1s;
  61static TCGv_i64 cpu_F0d, cpu_F1d;
  62
  63#include "exec/gen-icount.h"
  64
  65static const char *regnames[] = {
  66      "r00", "r01", "r02", "r03", "r04", "r05", "r06", "r07",
  67      "r08", "r09", "r10", "r11", "r12", "r13", "r14", "r15",
  68      "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23",
  69      "r24", "r25", "r26", "r27", "r28", "r29", "r30", "pc" };
  70
  71/* initialize TCG globals.  */
  72void uc32_translate_init(void)
  73{
  74    int i;
  75
  76    for (i = 0; i < 32; i++) {
  77        cpu_R[i] = tcg_global_mem_new_i32(cpu_env,
  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 bool use_goto_tb(DisasContext *s, uint32_t dest)
1096{
1097#ifndef CONFIG_USER_ONLY
1098    return (s->tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK);
1099#else
1100    return true;
1101#endif
1102}
1103
1104static inline void gen_goto_tb(DisasContext *s, int n, uint32_t dest)
1105{
1106    if (use_goto_tb(s, dest)) {
1107        tcg_gen_goto_tb(n);
1108        gen_set_pc_im(dest);
1109        tcg_gen_exit_tb(s->tb, n);
1110    } else {
1111        gen_set_pc_im(dest);
1112        tcg_gen_exit_tb(NULL, 0);
1113    }
1114}
1115
1116static inline void gen_jmp(DisasContext *s, uint32_t dest)
1117{
1118    if (unlikely(s->singlestep_enabled)) {
1119        /* An indirect jump so that we still trigger the debug exception.  */
1120        gen_bx_im(s, dest);
1121    } else {
1122        gen_goto_tb(s, 0, dest);
1123        s->is_jmp = DISAS_TB_JUMP;
1124    }
1125}
1126
1127/* Returns nonzero if access to the PSR is not permitted. Marks t0 as dead. */
1128static int gen_set_psr(DisasContext *s, uint32_t mask, int bsr, TCGv t0)
1129{
1130    TCGv tmp;
1131    if (bsr) {
1132        /* ??? This is also undefined in system mode.  */
1133        if (IS_USER(s)) {
1134            return 1;
1135        }
1136
1137        tmp = load_cpu_field(bsr);
1138        tcg_gen_andi_i32(tmp, tmp, ~mask);
1139        tcg_gen_andi_i32(t0, t0, mask);
1140        tcg_gen_or_i32(tmp, tmp, t0);
1141        store_cpu_field(tmp, bsr);
1142    } else {
1143        gen_set_asr(t0, mask);
1144    }
1145    dead_tmp(t0);
1146    gen_lookup_tb(s);
1147    return 0;
1148}
1149
1150/* Generate an old-style exception return. Marks pc as dead. */
1151static void gen_exception_return(DisasContext *s, TCGv pc)
1152{
1153    TCGv tmp;
1154    store_reg(s, 31, pc);
1155    tmp = load_cpu_field(bsr);
1156    gen_set_asr(tmp, 0xffffffff);
1157    dead_tmp(tmp);
1158    s->is_jmp = DISAS_UPDATE;
1159}
1160
1161static void disas_coproc_insn(CPUUniCore32State *env, DisasContext *s,
1162        uint32_t insn)
1163{
1164    UniCore32CPU *cpu = uc32_env_get_cpu(env);
1165
1166    switch (UCOP_CPNUM) {
1167#ifndef CONFIG_USER_ONLY
1168    case 0:
1169        disas_cp0_insn(env, s, insn);
1170        break;
1171    case 1:
1172        disas_ocd_insn(env, s, insn);
1173        break;
1174#endif
1175    case 2:
1176        disas_ucf64_insn(env, s, insn);
1177        break;
1178    default:
1179        /* Unknown coprocessor. */
1180        cpu_abort(CPU(cpu), "Unknown coprocessor!");
1181    }
1182}
1183
1184/* data processing instructions */
1185static void do_datap(CPUUniCore32State *env, DisasContext *s, uint32_t insn)
1186{
1187    UniCore32CPU *cpu = uc32_env_get_cpu(env);
1188    TCGv tmp;
1189    TCGv tmp2;
1190    int logic_cc;
1191
1192    if (UCOP_OPCODES == 0x0f || UCOP_OPCODES == 0x0d) {
1193        if (UCOP_SET(23)) { /* CMOV instructions */
1194            if ((UCOP_CMOV_COND == 0xe) || (UCOP_CMOV_COND == 0xf)) {
1195                ILLEGAL;
1196            }
1197            /* if not always execute, we generate a conditional jump to
1198               next instruction */
1199            s->condlabel = gen_new_label();
1200            gen_test_cc(UCOP_CMOV_COND ^ 1, s->condlabel);
1201            s->condjmp = 1;
1202        }
1203    }
1204
1205    logic_cc = table_logic_cc[UCOP_OPCODES] & (UCOP_SET_S >> 24);
1206
1207    if (UCOP_SET(29)) {
1208        unsigned int val;
1209        /* immediate operand */
1210        val = UCOP_IMM_9;
1211        if (UCOP_SH_IM) {
1212            val = (val >> UCOP_SH_IM) | (val << (32 - UCOP_SH_IM));
1213        }
1214        tmp2 = new_tmp();
1215        tcg_gen_movi_i32(tmp2, val);
1216        if (logic_cc && UCOP_SH_IM) {
1217            gen_set_CF_bit31(tmp2);
1218        }
1219   } else {
1220        /* register */
1221        tmp2 = load_reg(s, UCOP_REG_M);
1222        if (UCOP_SET(5)) {
1223            tmp = load_reg(s, UCOP_REG_S);
1224            gen_uc32_shift_reg(tmp2, UCOP_SH_OP, tmp, logic_cc);
1225        } else {
1226            gen_uc32_shift_im(tmp2, UCOP_SH_OP, UCOP_SH_IM, logic_cc);
1227        }
1228    }
1229
1230    if (UCOP_OPCODES != 0x0f && UCOP_OPCODES != 0x0d) {
1231        tmp = load_reg(s, UCOP_REG_N);
1232    } else {
1233        tmp = NULL;
1234    }
1235
1236    switch (UCOP_OPCODES) {
1237    case 0x00:
1238        tcg_gen_and_i32(tmp, tmp, tmp2);
1239        if (logic_cc) {
1240            gen_logic_CC(tmp);
1241        }
1242        store_reg_bx(s, UCOP_REG_D, tmp);
1243        break;
1244    case 0x01:
1245        tcg_gen_xor_i32(tmp, tmp, tmp2);
1246        if (logic_cc) {
1247            gen_logic_CC(tmp);
1248        }
1249        store_reg_bx(s, UCOP_REG_D, tmp);
1250        break;
1251    case 0x02:
1252        if (UCOP_SET_S && UCOP_REG_D == 31) {
1253            /* SUBS r31, ... is used for exception return.  */
1254            if (IS_USER(s)) {
1255                ILLEGAL;
1256            }
1257            gen_helper_sub_cc(tmp, cpu_env, tmp, tmp2);
1258            gen_exception_return(s, tmp);
1259        } else {
1260            if (UCOP_SET_S) {
1261                gen_helper_sub_cc(tmp, cpu_env, tmp, tmp2);
1262            } else {
1263                tcg_gen_sub_i32(tmp, tmp, tmp2);
1264            }
1265            store_reg_bx(s, UCOP_REG_D, tmp);
1266        }
1267        break;
1268    case 0x03:
1269        if (UCOP_SET_S) {
1270            gen_helper_sub_cc(tmp, cpu_env, tmp2, tmp);
1271        } else {
1272            tcg_gen_sub_i32(tmp, tmp2, tmp);
1273        }
1274        store_reg_bx(s, UCOP_REG_D, tmp);
1275        break;
1276    case 0x04:
1277        if (UCOP_SET_S) {
1278            gen_helper_add_cc(tmp, cpu_env, tmp, tmp2);
1279        } else {
1280            tcg_gen_add_i32(tmp, tmp, tmp2);
1281        }
1282        store_reg_bx(s, UCOP_REG_D, tmp);
1283        break;
1284    case 0x05:
1285        if (UCOP_SET_S) {
1286            gen_helper_adc_cc(tmp, cpu_env, tmp, tmp2);
1287        } else {
1288            gen_add_carry(tmp, tmp, tmp2);
1289        }
1290        store_reg_bx(s, UCOP_REG_D, tmp);
1291        break;
1292    case 0x06:
1293        if (UCOP_SET_S) {
1294            gen_helper_sbc_cc(tmp, cpu_env, tmp, tmp2);
1295        } else {
1296            gen_sub_carry(tmp, tmp, tmp2);
1297        }
1298        store_reg_bx(s, UCOP_REG_D, tmp);
1299        break;
1300    case 0x07:
1301        if (UCOP_SET_S) {
1302            gen_helper_sbc_cc(tmp, cpu_env, tmp2, tmp);
1303        } else {
1304            gen_sub_carry(tmp, tmp2, tmp);
1305        }
1306        store_reg_bx(s, UCOP_REG_D, tmp);
1307        break;
1308    case 0x08:
1309        if (UCOP_SET_S) {
1310            tcg_gen_and_i32(tmp, tmp, tmp2);
1311            gen_logic_CC(tmp);
1312        }
1313        dead_tmp(tmp);
1314        break;
1315    case 0x09:
1316        if (UCOP_SET_S) {
1317            tcg_gen_xor_i32(tmp, tmp, tmp2);
1318            gen_logic_CC(tmp);
1319        }
1320        dead_tmp(tmp);
1321        break;
1322    case 0x0a:
1323        if (UCOP_SET_S) {
1324            gen_helper_sub_cc(tmp, cpu_env, tmp, tmp2);
1325        }
1326        dead_tmp(tmp);
1327        break;
1328    case 0x0b:
1329        if (UCOP_SET_S) {
1330            gen_helper_add_cc(tmp, cpu_env, tmp, tmp2);
1331        }
1332        dead_tmp(tmp);
1333        break;
1334    case 0x0c:
1335        tcg_gen_or_i32(tmp, tmp, tmp2);
1336        if (logic_cc) {
1337            gen_logic_CC(tmp);
1338        }
1339        store_reg_bx(s, UCOP_REG_D, tmp);
1340        break;
1341    case 0x0d:
1342        if (logic_cc && UCOP_REG_D == 31) {
1343            /* MOVS r31, ... is used for exception return.  */
1344            if (IS_USER(s)) {
1345                ILLEGAL;
1346            }
1347            gen_exception_return(s, tmp2);
1348        } else {
1349            if (logic_cc) {
1350                gen_logic_CC(tmp2);
1351            }
1352            store_reg_bx(s, UCOP_REG_D, tmp2);
1353        }
1354        break;
1355    case 0x0e:
1356        tcg_gen_andc_i32(tmp, tmp, tmp2);
1357        if (logic_cc) {
1358            gen_logic_CC(tmp);
1359        }
1360        store_reg_bx(s, UCOP_REG_D, tmp);
1361        break;
1362    default:
1363    case 0x0f:
1364        tcg_gen_not_i32(tmp2, tmp2);
1365        if (logic_cc) {
1366            gen_logic_CC(tmp2);
1367        }
1368        store_reg_bx(s, UCOP_REG_D, tmp2);
1369        break;
1370    }
1371    if (UCOP_OPCODES != 0x0f && UCOP_OPCODES != 0x0d) {
1372        dead_tmp(tmp2);
1373    }
1374}
1375
1376/* multiply */
1377static void do_mult(CPUUniCore32State *env, DisasContext *s, uint32_t insn)
1378{
1379    TCGv tmp, tmp2, tmp3, tmp4;
1380
1381    if (UCOP_SET(27)) {
1382        /* 64 bit mul */
1383        tmp = load_reg(s, UCOP_REG_M);
1384        tmp2 = load_reg(s, UCOP_REG_N);
1385        if (UCOP_SET(26)) {
1386            tcg_gen_muls2_i32(tmp, tmp2, tmp, tmp2);
1387        } else {
1388            tcg_gen_mulu2_i32(tmp, tmp2, tmp, tmp2);
1389        }
1390        if (UCOP_SET(25)) { /* mult accumulate */
1391            tmp3 = load_reg(s, UCOP_REG_LO);
1392            tmp4 = load_reg(s, UCOP_REG_HI);
1393            tcg_gen_add2_i32(tmp, tmp2, tmp, tmp2, tmp3, tmp4);
1394            dead_tmp(tmp3);
1395            dead_tmp(tmp4);
1396        }
1397        store_reg(s, UCOP_REG_LO, tmp);
1398        store_reg(s, UCOP_REG_HI, tmp2);
1399    } else {
1400        /* 32 bit mul */
1401        tmp = load_reg(s, UCOP_REG_M);
1402        tmp2 = load_reg(s, UCOP_REG_N);
1403        tcg_gen_mul_i32(tmp, tmp, tmp2);
1404        dead_tmp(tmp2);
1405        if (UCOP_SET(25)) {
1406            /* Add */
1407            tmp2 = load_reg(s, UCOP_REG_S);
1408            tcg_gen_add_i32(tmp, tmp, tmp2);
1409            dead_tmp(tmp2);
1410        }
1411        if (UCOP_SET_S) {
1412            gen_logic_CC(tmp);
1413        }
1414        store_reg(s, UCOP_REG_D, tmp);
1415    }
1416}
1417
1418/* miscellaneous instructions */
1419static void do_misc(CPUUniCore32State *env, DisasContext *s, uint32_t insn)
1420{
1421    UniCore32CPU *cpu = uc32_env_get_cpu(env);
1422    unsigned int val;
1423    TCGv tmp;
1424
1425    if ((insn & 0xffffffe0) == 0x10ffc120) {
1426        /* Trivial implementation equivalent to bx.  */
1427        tmp = load_reg(s, UCOP_REG_M);
1428        gen_bx(s, tmp);
1429        return;
1430    }
1431
1432    if ((insn & 0xfbffc000) == 0x30ffc000) {
1433        /* PSR = immediate */
1434        val = UCOP_IMM_9;
1435        if (UCOP_SH_IM) {
1436            val = (val >> UCOP_SH_IM) | (val << (32 - UCOP_SH_IM));
1437        }
1438        tmp = new_tmp();
1439        tcg_gen_movi_i32(tmp, val);
1440        if (gen_set_psr(s, ~ASR_RESERVED, UCOP_SET_B, tmp)) {
1441            ILLEGAL;
1442        }
1443        return;
1444    }
1445
1446    if ((insn & 0xfbffffe0) == 0x12ffc020) {
1447        /* PSR.flag = reg */
1448        tmp = load_reg(s, UCOP_REG_M);
1449        if (gen_set_psr(s, ASR_NZCV, UCOP_SET_B, tmp)) {
1450            ILLEGAL;
1451        }
1452        return;
1453    }
1454
1455    if ((insn & 0xfbffffe0) == 0x10ffc020) {
1456        /* PSR = reg */
1457        tmp = load_reg(s, UCOP_REG_M);
1458        if (gen_set_psr(s, ~ASR_RESERVED, UCOP_SET_B, tmp)) {
1459            ILLEGAL;
1460        }
1461        return;
1462    }
1463
1464    if ((insn & 0xfbf83fff) == 0x10f80000) {
1465        /* reg = PSR */
1466        if (UCOP_SET_B) {
1467            if (IS_USER(s)) {
1468                ILLEGAL;
1469            }
1470            tmp = load_cpu_field(bsr);
1471        } else {
1472            tmp = new_tmp();
1473            gen_helper_asr_read(tmp, cpu_env);
1474        }
1475        store_reg(s, UCOP_REG_D, tmp);
1476        return;
1477    }
1478
1479    if ((insn & 0xfbf83fe0) == 0x12f80120) {
1480        /* clz */
1481        tmp = load_reg(s, UCOP_REG_M);
1482        if (UCOP_SET(26)) {
1483            /* clo */
1484            tcg_gen_not_i32(tmp, tmp);
1485        }
1486        tcg_gen_clzi_i32(tmp, tmp, 32);
1487        store_reg(s, UCOP_REG_D, tmp);
1488        return;
1489    }
1490
1491    /* otherwise */
1492    ILLEGAL;
1493}
1494
1495/* load/store I_offset and R_offset */
1496static void do_ldst_ir(CPUUniCore32State *env, DisasContext *s, uint32_t insn)
1497{
1498    unsigned int mmu_idx;
1499    TCGv tmp;
1500    TCGv tmp2;
1501
1502    tmp2 = load_reg(s, UCOP_REG_N);
1503    mmu_idx = (IS_USER(s) || (!UCOP_SET_P && UCOP_SET_W));
1504
1505    /* immediate */
1506    if (UCOP_SET_P) {
1507        gen_add_data_offset(s, insn, tmp2);
1508    }
1509
1510    if (UCOP_SET_L) {
1511        /* load */
1512        if (UCOP_SET_B) {
1513            tmp = gen_ld8u(tmp2, mmu_idx);
1514        } else {
1515            tmp = gen_ld32(tmp2, mmu_idx);
1516        }
1517    } else {
1518        /* store */
1519        tmp = load_reg(s, UCOP_REG_D);
1520        if (UCOP_SET_B) {
1521            gen_st8(tmp, tmp2, mmu_idx);
1522        } else {
1523            gen_st32(tmp, tmp2, mmu_idx);
1524        }
1525    }
1526    if (!UCOP_SET_P) {
1527        gen_add_data_offset(s, insn, tmp2);
1528        store_reg(s, UCOP_REG_N, tmp2);
1529    } else if (UCOP_SET_W) {
1530        store_reg(s, UCOP_REG_N, tmp2);
1531    } else {
1532        dead_tmp(tmp2);
1533    }
1534    if (UCOP_SET_L) {
1535        /* Complete the load.  */
1536        if (UCOP_REG_D == 31) {
1537            gen_bx(s, tmp);
1538        } else {
1539            store_reg(s, UCOP_REG_D, tmp);
1540        }
1541    }
1542}
1543
1544/* SWP instruction */
1545static void do_swap(CPUUniCore32State *env, DisasContext *s, uint32_t insn)
1546{
1547    UniCore32CPU *cpu = uc32_env_get_cpu(env);
1548    TCGv addr;
1549    TCGv tmp;
1550    TCGv tmp2;
1551
1552    if ((insn & 0xff003fe0) != 0x40000120) {
1553        ILLEGAL;
1554    }
1555
1556    /* ??? This is not really atomic.  However we know
1557       we never have multiple CPUs running in parallel,
1558       so it is good enough.  */
1559    addr = load_reg(s, UCOP_REG_N);
1560    tmp = load_reg(s, UCOP_REG_M);
1561    if (UCOP_SET_B) {
1562        tmp2 = gen_ld8u(addr, IS_USER(s));
1563        gen_st8(tmp, addr, IS_USER(s));
1564    } else {
1565        tmp2 = gen_ld32(addr, IS_USER(s));
1566        gen_st32(tmp, addr, IS_USER(s));
1567    }
1568    dead_tmp(addr);
1569    store_reg(s, UCOP_REG_D, tmp2);
1570}
1571
1572/* load/store hw/sb */
1573static void do_ldst_hwsb(CPUUniCore32State *env, DisasContext *s, uint32_t insn)
1574{
1575    UniCore32CPU *cpu = uc32_env_get_cpu(env);
1576    TCGv addr;
1577    TCGv tmp;
1578
1579    if (UCOP_SH_OP == 0) {
1580        do_swap(env, s, insn);
1581        return;
1582    }
1583
1584    addr = load_reg(s, UCOP_REG_N);
1585    if (UCOP_SET_P) {
1586        gen_add_datah_offset(s, insn, addr);
1587    }
1588
1589    if (UCOP_SET_L) { /* load */
1590        switch (UCOP_SH_OP) {
1591        case 1:
1592            tmp = gen_ld16u(addr, IS_USER(s));
1593            break;
1594        case 2:
1595            tmp = gen_ld8s(addr, IS_USER(s));
1596            break;
1597        default: /* see do_swap */
1598        case 3:
1599            tmp = gen_ld16s(addr, IS_USER(s));
1600            break;
1601        }
1602    } else { /* store */
1603        if (UCOP_SH_OP != 1) {
1604            ILLEGAL;
1605        }
1606        tmp = load_reg(s, UCOP_REG_D);
1607        gen_st16(tmp, addr, IS_USER(s));
1608    }
1609    /* Perform base writeback before the loaded value to
1610       ensure correct behavior with overlapping index registers. */
1611    if (!UCOP_SET_P) {
1612        gen_add_datah_offset(s, insn, addr);
1613        store_reg(s, UCOP_REG_N, addr);
1614    } else if (UCOP_SET_W) {
1615        store_reg(s, UCOP_REG_N, addr);
1616    } else {
1617        dead_tmp(addr);
1618    }
1619    if (UCOP_SET_L) {
1620        /* Complete the load.  */
1621        store_reg(s, UCOP_REG_D, tmp);
1622    }
1623}
1624
1625/* load/store multiple words */
1626static void do_ldst_m(CPUUniCore32State *env, DisasContext *s, uint32_t insn)
1627{
1628    UniCore32CPU *cpu = uc32_env_get_cpu(env);
1629    unsigned int val, i, mmu_idx;
1630    int j, n, reg, user, loaded_base;
1631    TCGv tmp;
1632    TCGv tmp2;
1633    TCGv addr;
1634    TCGv loaded_var;
1635
1636    if (UCOP_SET(7)) {
1637        ILLEGAL;
1638    }
1639    /* XXX: store correct base if write back */
1640    user = 0;
1641    if (UCOP_SET_B) { /* S bit in instruction table */
1642        if (IS_USER(s)) {
1643            ILLEGAL; /* only usable in supervisor mode */
1644        }
1645        if (UCOP_SET(18) == 0) { /* pc reg */
1646            user = 1;
1647        }
1648    }
1649
1650    mmu_idx = (IS_USER(s) || (!UCOP_SET_P && UCOP_SET_W));
1651    addr = load_reg(s, UCOP_REG_N);
1652
1653    /* compute total size */
1654    loaded_base = 0;
1655    loaded_var = NULL;
1656    n = 0;
1657    for (i = 0; i < 6; i++) {
1658        if (UCOP_SET(i)) {
1659            n++;
1660        }
1661    }
1662    for (i = 9; i < 19; i++) {
1663        if (UCOP_SET(i)) {
1664            n++;
1665        }
1666    }
1667    /* XXX: test invalid n == 0 case ? */
1668    if (UCOP_SET_U) {
1669        if (UCOP_SET_P) {
1670            /* pre increment */
1671            tcg_gen_addi_i32(addr, addr, 4);
1672        } else {
1673            /* post increment */
1674        }
1675    } else {
1676        if (UCOP_SET_P) {
1677            /* pre decrement */
1678            tcg_gen_addi_i32(addr, addr, -(n * 4));
1679        } else {
1680            /* post decrement */
1681            if (n != 1) {
1682                tcg_gen_addi_i32(addr, addr, -((n - 1) * 4));
1683            }
1684        }
1685    }
1686
1687    j = 0;
1688    reg = UCOP_SET(6) ? 16 : 0;
1689    for (i = 0; i < 19; i++, reg++) {
1690        if (i == 6) {
1691            i = i + 3;
1692        }
1693        if (UCOP_SET(i)) {
1694            if (UCOP_SET_L) { /* load */
1695                tmp = gen_ld32(addr, mmu_idx);
1696                if (reg == 31) {
1697                    gen_bx(s, tmp);
1698                } else if (user) {
1699                    tmp2 = tcg_const_i32(reg);
1700                    gen_helper_set_user_reg(cpu_env, tmp2, tmp);
1701                    tcg_temp_free_i32(tmp2);
1702                    dead_tmp(tmp);
1703                } else if (reg == UCOP_REG_N) {
1704                    loaded_var = tmp;
1705                    loaded_base = 1;
1706                } else {
1707                    store_reg(s, reg, tmp);
1708                }
1709            } else { /* store */
1710                if (reg == 31) {
1711                    /* special case: r31 = PC + 4 */
1712                    val = (long)s->pc;
1713                    tmp = new_tmp();
1714                    tcg_gen_movi_i32(tmp, val);
1715                } else if (user) {
1716                    tmp = new_tmp();
1717                    tmp2 = tcg_const_i32(reg);
1718                    gen_helper_get_user_reg(tmp, cpu_env, tmp2);
1719                    tcg_temp_free_i32(tmp2);
1720                } else {
1721                    tmp = load_reg(s, reg);
1722                }
1723                gen_st32(tmp, addr, mmu_idx);
1724            }
1725            j++;
1726            /* no need to add after the last transfer */
1727            if (j != n) {
1728                tcg_gen_addi_i32(addr, addr, 4);
1729            }
1730        }
1731    }
1732    if (UCOP_SET_W) { /* write back */
1733        if (UCOP_SET_U) {
1734            if (UCOP_SET_P) {
1735                /* pre increment */
1736            } else {
1737                /* post increment */
1738                tcg_gen_addi_i32(addr, addr, 4);
1739            }
1740        } else {
1741            if (UCOP_SET_P) {
1742                /* pre decrement */
1743                if (n != 1) {
1744                    tcg_gen_addi_i32(addr, addr, -((n - 1) * 4));
1745                }
1746            } else {
1747                /* post decrement */
1748                tcg_gen_addi_i32(addr, addr, -(n * 4));
1749            }
1750        }
1751        store_reg(s, UCOP_REG_N, addr);
1752    } else {
1753        dead_tmp(addr);
1754    }
1755    if (loaded_base) {
1756        store_reg(s, UCOP_REG_N, loaded_var);
1757    }
1758    if (UCOP_SET_B && !user) {
1759        /* Restore ASR from BSR.  */
1760        tmp = load_cpu_field(bsr);
1761        gen_set_asr(tmp, 0xffffffff);
1762        dead_tmp(tmp);
1763        s->is_jmp = DISAS_UPDATE;
1764    }
1765}
1766
1767/* branch (and link) */
1768static void do_branch(CPUUniCore32State *env, DisasContext *s, uint32_t insn)
1769{
1770    UniCore32CPU *cpu = uc32_env_get_cpu(env);
1771    unsigned int val;
1772    int32_t offset;
1773    TCGv tmp;
1774
1775    if (UCOP_COND == 0xf) {
1776        ILLEGAL;
1777    }
1778
1779    if (UCOP_COND != 0xe) {
1780        /* if not always execute, we generate a conditional jump to
1781           next instruction */
1782        s->condlabel = gen_new_label();
1783        gen_test_cc(UCOP_COND ^ 1, s->condlabel);
1784        s->condjmp = 1;
1785    }
1786
1787    val = (int32_t)s->pc;
1788    if (UCOP_SET_L) {
1789        tmp = new_tmp();
1790        tcg_gen_movi_i32(tmp, val);
1791        store_reg(s, 30, tmp);
1792    }
1793    offset = (((int32_t)insn << 8) >> 8);
1794    val += (offset << 2); /* unicore is pc+4 */
1795    gen_jmp(s, val);
1796}
1797
1798static void disas_uc32_insn(CPUUniCore32State *env, DisasContext *s)
1799{
1800    UniCore32CPU *cpu = uc32_env_get_cpu(env);
1801    unsigned int insn;
1802
1803    insn = cpu_ldl_code(env, s->pc);
1804    s->pc += 4;
1805
1806    /* UniCore instructions class:
1807     * AAAB BBBC xxxx xxxx xxxx xxxD xxEx xxxx
1808     * AAA  : see switch case
1809     * BBBB : opcodes or cond or PUBW
1810     * C    : S OR L
1811     * D    : 8
1812     * E    : 5
1813     */
1814    switch (insn >> 29) {
1815    case 0x0:
1816        if (UCOP_SET(5) && UCOP_SET(8) && !UCOP_SET(28)) {
1817            do_mult(env, s, insn);
1818            break;
1819        }
1820
1821        if (UCOP_SET(8)) {
1822            do_misc(env, s, insn);
1823            break;
1824        }
1825    case 0x1:
1826        if (((UCOP_OPCODES >> 2) == 2) && !UCOP_SET_S) {
1827            do_misc(env, s, insn);
1828            break;
1829        }
1830        do_datap(env, s, insn);
1831        break;
1832
1833    case 0x2:
1834        if (UCOP_SET(8) && UCOP_SET(5)) {
1835            do_ldst_hwsb(env, s, insn);
1836            break;
1837        }
1838        if (UCOP_SET(8) || UCOP_SET(5)) {
1839            ILLEGAL;
1840        }
1841    case 0x3:
1842        do_ldst_ir(env, s, insn);
1843        break;
1844
1845    case 0x4:
1846        if (UCOP_SET(8)) {
1847            ILLEGAL; /* extended instructions */
1848        }
1849        do_ldst_m(env, s, insn);
1850        break;
1851    case 0x5:
1852        do_branch(env, s, insn);
1853        break;
1854    case 0x6:
1855        /* Coprocessor.  */
1856        disas_coproc_insn(env, s, insn);
1857        break;
1858    case 0x7:
1859        if (!UCOP_SET(28)) {
1860            disas_coproc_insn(env, s, insn);
1861            break;
1862        }
1863        if ((insn & 0xff000000) == 0xff000000) { /* syscall */
1864            gen_set_pc_im(s->pc);
1865            s->is_jmp = DISAS_SYSCALL;
1866            break;
1867        }
1868        ILLEGAL;
1869    }
1870}
1871
1872/* generate intermediate code for basic block 'tb'.  */
1873void gen_intermediate_code(CPUState *cs, TranslationBlock *tb)
1874{
1875    CPUUniCore32State *env = cs->env_ptr;
1876    DisasContext dc1, *dc = &dc1;
1877    target_ulong pc_start;
1878    uint32_t page_start;
1879    int num_insns;
1880    int max_insns;
1881
1882    /* generate intermediate code */
1883    num_temps = 0;
1884
1885    pc_start = tb->pc;
1886
1887    dc->tb = tb;
1888
1889    dc->is_jmp = DISAS_NEXT;
1890    dc->pc = pc_start;
1891    dc->singlestep_enabled = cs->singlestep_enabled;
1892    dc->condjmp = 0;
1893    cpu_F0s = tcg_temp_new_i32();
1894    cpu_F1s = tcg_temp_new_i32();
1895    cpu_F0d = tcg_temp_new_i64();
1896    cpu_F1d = tcg_temp_new_i64();
1897    page_start = pc_start & TARGET_PAGE_MASK;
1898    num_insns = 0;
1899    max_insns = tb_cflags(tb) & CF_COUNT_MASK;
1900    if (max_insns == 0) {
1901        max_insns = CF_COUNT_MASK;
1902    }
1903    if (max_insns > TCG_MAX_INSNS) {
1904        max_insns = TCG_MAX_INSNS;
1905    }
1906
1907#ifndef CONFIG_USER_ONLY
1908    if ((env->uncached_asr & ASR_M) == ASR_MODE_USER) {
1909        dc->user = 1;
1910    } else {
1911        dc->user = 0;
1912    }
1913#endif
1914
1915    gen_tb_start(tb);
1916    do {
1917        tcg_gen_insn_start(dc->pc);
1918        num_insns++;
1919
1920        if (unlikely(cpu_breakpoint_test(cs, dc->pc, BP_ANY))) {
1921            gen_set_pc_im(dc->pc);
1922            gen_exception(EXCP_DEBUG);
1923            dc->is_jmp = DISAS_JUMP;
1924            /* The address covered by the breakpoint must be included in
1925               [tb->pc, tb->pc + tb->size) in order to for it to be
1926               properly cleared -- thus we increment the PC here so that
1927               the logic setting tb->size below does the right thing.  */
1928            dc->pc += 4;
1929            goto done_generating;
1930        }
1931
1932        if (num_insns == max_insns && (tb_cflags(tb) & CF_LAST_IO)) {
1933            gen_io_start();
1934        }
1935
1936        disas_uc32_insn(env, dc);
1937
1938        if (num_temps) {
1939            fprintf(stderr, "Internal resource leak before %08x\n", dc->pc);
1940            num_temps = 0;
1941        }
1942
1943        if (dc->condjmp && !dc->is_jmp) {
1944            gen_set_label(dc->condlabel);
1945            dc->condjmp = 0;
1946        }
1947        /* Translation stops when a conditional branch is encountered.
1948         * Otherwise the subsequent code could get translated several times.
1949         * Also stop translation when a page boundary is reached.  This
1950         * ensures prefetch aborts occur at the right place.  */
1951    } while (!dc->is_jmp && !tcg_op_buf_full() &&
1952             !cs->singlestep_enabled &&
1953             !singlestep &&
1954             dc->pc - page_start < TARGET_PAGE_SIZE &&
1955             num_insns < max_insns);
1956
1957    if (tb_cflags(tb) & CF_LAST_IO) {
1958        if (dc->condjmp) {
1959            /* FIXME:  This can theoretically happen with self-modifying
1960               code.  */
1961            cpu_abort(cs, "IO on conditional branch instruction");
1962        }
1963        gen_io_end();
1964    }
1965
1966    /* At this stage dc->condjmp will only be set when the skipped
1967       instruction was a conditional branch or trap, and the PC has
1968       already been written.  */
1969    if (unlikely(cs->singlestep_enabled)) {
1970        /* Make sure the pc is updated, and raise a debug exception.  */
1971        if (dc->condjmp) {
1972            if (dc->is_jmp == DISAS_SYSCALL) {
1973                gen_exception(UC32_EXCP_PRIV);
1974            } else {
1975                gen_exception(EXCP_DEBUG);
1976            }
1977            gen_set_label(dc->condlabel);
1978        }
1979        if (dc->condjmp || !dc->is_jmp) {
1980            gen_set_pc_im(dc->pc);
1981            dc->condjmp = 0;
1982        }
1983        if (dc->is_jmp == DISAS_SYSCALL && !dc->condjmp) {
1984            gen_exception(UC32_EXCP_PRIV);
1985        } else {
1986            gen_exception(EXCP_DEBUG);
1987        }
1988    } else {
1989        /* While branches must always occur at the end of an IT block,
1990           there are a few other things that can cause us to terminate
1991           the TB in the middel of an IT block:
1992            - Exception generating instructions (bkpt, swi, undefined).
1993            - Page boundaries.
1994            - Hardware watchpoints.
1995           Hardware breakpoints have already been handled and skip this code.
1996         */
1997        switch (dc->is_jmp) {
1998        case DISAS_NEXT:
1999            gen_goto_tb(dc, 1, dc->pc);
2000            break;
2001        default:
2002        case DISAS_JUMP:
2003        case DISAS_UPDATE:
2004            /* indicate that the hash table must be used to find the next TB */
2005            tcg_gen_exit_tb(NULL, 0);
2006            break;
2007        case DISAS_TB_JUMP:
2008            /* nothing more to generate */
2009            break;
2010        case DISAS_SYSCALL:
2011            gen_exception(UC32_EXCP_PRIV);
2012            break;
2013        }
2014        if (dc->condjmp) {
2015            gen_set_label(dc->condlabel);
2016            gen_goto_tb(dc, 1, dc->pc);
2017            dc->condjmp = 0;
2018        }
2019    }
2020
2021done_generating:
2022    gen_tb_end(tb, num_insns);
2023
2024#ifdef DEBUG_DISAS
2025    if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)
2026        && qemu_log_in_addr_range(pc_start)) {
2027        qemu_log_lock();
2028        qemu_log("----------------\n");
2029        qemu_log("IN: %s\n", lookup_symbol(pc_start));
2030        log_target_disas(cs, pc_start, dc->pc - pc_start);
2031        qemu_log("\n");
2032        qemu_log_unlock();
2033    }
2034#endif
2035    tb->size = dc->pc - pc_start;
2036    tb->icount = num_insns;
2037}
2038
2039static const char *cpu_mode_names[16] = {
2040    "USER", "REAL", "INTR", "PRIV", "UM14", "UM15", "UM16", "TRAP",
2041    "UM18", "UM19", "UM1A", "EXTN", "UM1C", "UM1D", "UM1E", "SUSR"
2042};
2043
2044#undef UCF64_DUMP_STATE
2045#ifdef UCF64_DUMP_STATE
2046static void cpu_dump_state_ucf64(CPUUniCore32State *env, FILE *f,
2047        fprintf_function cpu_fprintf, int flags)
2048{
2049    int i;
2050    union {
2051        uint32_t i;
2052        float s;
2053    } s0, s1;
2054    CPU_DoubleU d;
2055    /* ??? This assumes float64 and double have the same layout.
2056       Oh well, it's only debug dumps.  */
2057    union {
2058        float64 f64;
2059        double d;
2060    } d0;
2061
2062    for (i = 0; i < 16; i++) {
2063        d.d = env->ucf64.regs[i];
2064        s0.i = d.l.lower;
2065        s1.i = d.l.upper;
2066        d0.f64 = d.d;
2067        cpu_fprintf(f, "s%02d=%08x(%8g) s%02d=%08x(%8g)",
2068                    i * 2, (int)s0.i, s0.s,
2069                    i * 2 + 1, (int)s1.i, s1.s);
2070        cpu_fprintf(f, " d%02d=%" PRIx64 "(%8g)\n",
2071                    i, (uint64_t)d0.f64, d0.d);
2072    }
2073    cpu_fprintf(f, "FPSCR: %08x\n", (int)env->ucf64.xregs[UC32_UCF64_FPSCR]);
2074}
2075#else
2076#define cpu_dump_state_ucf64(env, file, pr, flags)      do { } while (0)
2077#endif
2078
2079void uc32_cpu_dump_state(CPUState *cs, FILE *f,
2080                         fprintf_function cpu_fprintf, int flags)
2081{
2082    UniCore32CPU *cpu = UNICORE32_CPU(cs);
2083    CPUUniCore32State *env = &cpu->env;
2084    int i;
2085    uint32_t psr;
2086
2087    for (i = 0; i < 32; i++) {
2088        cpu_fprintf(f, "R%02d=%08x", i, env->regs[i]);
2089        if ((i % 4) == 3) {
2090            cpu_fprintf(f, "\n");
2091        } else {
2092            cpu_fprintf(f, " ");
2093        }
2094    }
2095    psr = cpu_asr_read(env);
2096    cpu_fprintf(f, "PSR=%08x %c%c%c%c %s\n",
2097                psr,
2098                psr & (1 << 31) ? 'N' : '-',
2099                psr & (1 << 30) ? 'Z' : '-',
2100                psr & (1 << 29) ? 'C' : '-',
2101                psr & (1 << 28) ? 'V' : '-',
2102                cpu_mode_names[psr & 0xf]);
2103
2104    if (flags & CPU_DUMP_FPU) {
2105        cpu_dump_state_ucf64(env, f, cpu_fprintf, flags);
2106    }
2107}
2108
2109void restore_state_to_opc(CPUUniCore32State *env, TranslationBlock *tb,
2110                          target_ulong *data)
2111{
2112    env->regs[31] = data[0];
2113}
2114