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