qemu/target/openrisc/translate.c
<<
>>
Prefs
   1/*
   2 * OpenRISC translation
   3 *
   4 * Copyright (c) 2011-2012 Jia Liu <proljc@gmail.com>
   5 *                         Feng Gao <gf91597@gmail.com>
   6 *
   7 * This library is free software; you can redistribute it and/or
   8 * modify it under the terms of the GNU Lesser General Public
   9 * License as published by the Free Software Foundation; either
  10 * version 2.1 of the License, or (at your option) any later version.
  11 *
  12 * This library is distributed in the hope that it will be useful,
  13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  15 * Lesser General Public License for more details.
  16 *
  17 * You should have received a copy of the GNU Lesser General Public
  18 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
  19 */
  20
  21#include "qemu/osdep.h"
  22#include "cpu.h"
  23#include "exec/exec-all.h"
  24#include "disas/disas.h"
  25#include "tcg-op.h"
  26#include "qemu/log.h"
  27#include "qemu/bitops.h"
  28#include "qemu/qemu-print.h"
  29#include "exec/cpu_ldst.h"
  30#include "exec/translator.h"
  31
  32#include "exec/helper-proto.h"
  33#include "exec/helper-gen.h"
  34#include "exec/gen-icount.h"
  35
  36#include "trace-tcg.h"
  37#include "exec/log.h"
  38
  39/* is_jmp field values */
  40#define DISAS_EXIT    DISAS_TARGET_0  /* force exit to main loop */
  41#define DISAS_JUMP    DISAS_TARGET_1  /* exit via jmp_pc/jmp_pc_imm */
  42
  43typedef struct DisasContext {
  44    DisasContextBase base;
  45    uint32_t mem_idx;
  46    uint32_t tb_flags;
  47    uint32_t delayed_branch;
  48
  49    /* If not -1, jmp_pc contains this value and so is a direct jump.  */
  50    target_ulong jmp_pc_imm;
  51} DisasContext;
  52
  53static inline bool is_user(DisasContext *dc)
  54{
  55#ifdef CONFIG_USER_ONLY
  56    return true;
  57#else
  58    return !(dc->tb_flags & TB_FLAGS_SM);
  59#endif
  60}
  61
  62/* Include the auto-generated decoder.  */
  63#include "decode.inc.c"
  64
  65static TCGv cpu_sr;
  66static TCGv cpu_R[32];
  67static TCGv cpu_R0;
  68static TCGv cpu_pc;
  69static TCGv jmp_pc;            /* l.jr/l.jalr temp pc */
  70static TCGv cpu_ppc;
  71static TCGv cpu_sr_f;           /* bf/bnf, F flag taken */
  72static TCGv cpu_sr_cy;          /* carry (unsigned overflow) */
  73static TCGv cpu_sr_ov;          /* signed overflow */
  74static TCGv cpu_lock_addr;
  75static TCGv cpu_lock_value;
  76static TCGv_i32 fpcsr;
  77static TCGv_i64 cpu_mac;        /* MACHI:MACLO */
  78static TCGv_i32 cpu_dflag;
  79
  80void openrisc_translate_init(void)
  81{
  82    static const char * const regnames[] = {
  83        "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
  84        "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
  85        "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23",
  86        "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31",
  87    };
  88    int i;
  89
  90    cpu_sr = tcg_global_mem_new(cpu_env,
  91                                offsetof(CPUOpenRISCState, sr), "sr");
  92    cpu_dflag = tcg_global_mem_new_i32(cpu_env,
  93                                       offsetof(CPUOpenRISCState, dflag),
  94                                       "dflag");
  95    cpu_pc = tcg_global_mem_new(cpu_env,
  96                                offsetof(CPUOpenRISCState, pc), "pc");
  97    cpu_ppc = tcg_global_mem_new(cpu_env,
  98                                 offsetof(CPUOpenRISCState, ppc), "ppc");
  99    jmp_pc = tcg_global_mem_new(cpu_env,
 100                                offsetof(CPUOpenRISCState, jmp_pc), "jmp_pc");
 101    cpu_sr_f = tcg_global_mem_new(cpu_env,
 102                                  offsetof(CPUOpenRISCState, sr_f), "sr_f");
 103    cpu_sr_cy = tcg_global_mem_new(cpu_env,
 104                                   offsetof(CPUOpenRISCState, sr_cy), "sr_cy");
 105    cpu_sr_ov = tcg_global_mem_new(cpu_env,
 106                                   offsetof(CPUOpenRISCState, sr_ov), "sr_ov");
 107    cpu_lock_addr = tcg_global_mem_new(cpu_env,
 108                                       offsetof(CPUOpenRISCState, lock_addr),
 109                                       "lock_addr");
 110    cpu_lock_value = tcg_global_mem_new(cpu_env,
 111                                        offsetof(CPUOpenRISCState, lock_value),
 112                                        "lock_value");
 113    fpcsr = tcg_global_mem_new_i32(cpu_env,
 114                                   offsetof(CPUOpenRISCState, fpcsr),
 115                                   "fpcsr");
 116    cpu_mac = tcg_global_mem_new_i64(cpu_env,
 117                                     offsetof(CPUOpenRISCState, mac),
 118                                     "mac");
 119    for (i = 0; i < 32; i++) {
 120        cpu_R[i] = tcg_global_mem_new(cpu_env,
 121                                      offsetof(CPUOpenRISCState,
 122                                               shadow_gpr[0][i]),
 123                                      regnames[i]);
 124    }
 125    cpu_R0 = cpu_R[0];
 126}
 127
 128static void gen_exception(DisasContext *dc, unsigned int excp)
 129{
 130    TCGv_i32 tmp = tcg_const_i32(excp);
 131    gen_helper_exception(cpu_env, tmp);
 132    tcg_temp_free_i32(tmp);
 133}
 134
 135static void gen_illegal_exception(DisasContext *dc)
 136{
 137    tcg_gen_movi_tl(cpu_pc, dc->base.pc_next);
 138    gen_exception(dc, EXCP_ILLEGAL);
 139    dc->base.is_jmp = DISAS_NORETURN;
 140}
 141
 142/* not used yet, open it when we need or64.  */
 143/*#ifdef TARGET_OPENRISC64
 144static void check_ob64s(DisasContext *dc)
 145{
 146    if (!(dc->flags & CPUCFGR_OB64S)) {
 147        gen_illegal_exception(dc);
 148    }
 149}
 150
 151static void check_of64s(DisasContext *dc)
 152{
 153    if (!(dc->flags & CPUCFGR_OF64S)) {
 154        gen_illegal_exception(dc);
 155    }
 156}
 157
 158static void check_ov64s(DisasContext *dc)
 159{
 160    if (!(dc->flags & CPUCFGR_OV64S)) {
 161        gen_illegal_exception(dc);
 162    }
 163}
 164#endif*/
 165
 166/* We're about to write to REG.  On the off-chance that the user is
 167   writing to R0, re-instate the architectural register.  */
 168#define check_r0_write(reg)             \
 169    do {                                \
 170        if (unlikely(reg == 0)) {       \
 171            cpu_R[0] = cpu_R0;          \
 172        }                               \
 173    } while (0)
 174
 175static void gen_ove_cy(DisasContext *dc)
 176{
 177    if (dc->tb_flags & SR_OVE) {
 178        gen_helper_ove_cy(cpu_env);
 179    }
 180}
 181
 182static void gen_ove_ov(DisasContext *dc)
 183{
 184    if (dc->tb_flags & SR_OVE) {
 185        gen_helper_ove_ov(cpu_env);
 186    }
 187}
 188
 189static void gen_ove_cyov(DisasContext *dc)
 190{
 191    if (dc->tb_flags & SR_OVE) {
 192        gen_helper_ove_cyov(cpu_env);
 193    }
 194}
 195
 196static void gen_add(DisasContext *dc, TCGv dest, TCGv srca, TCGv srcb)
 197{
 198    TCGv t0 = tcg_const_tl(0);
 199    TCGv res = tcg_temp_new();
 200
 201    tcg_gen_add2_tl(res, cpu_sr_cy, srca, t0, srcb, t0);
 202    tcg_gen_xor_tl(cpu_sr_ov, srca, srcb);
 203    tcg_gen_xor_tl(t0, res, srcb);
 204    tcg_gen_andc_tl(cpu_sr_ov, t0, cpu_sr_ov);
 205    tcg_temp_free(t0);
 206
 207    tcg_gen_mov_tl(dest, res);
 208    tcg_temp_free(res);
 209
 210    gen_ove_cyov(dc);
 211}
 212
 213static void gen_addc(DisasContext *dc, TCGv dest, TCGv srca, TCGv srcb)
 214{
 215    TCGv t0 = tcg_const_tl(0);
 216    TCGv res = tcg_temp_new();
 217
 218    tcg_gen_add2_tl(res, cpu_sr_cy, srca, t0, cpu_sr_cy, t0);
 219    tcg_gen_add2_tl(res, cpu_sr_cy, res, cpu_sr_cy, srcb, t0);
 220    tcg_gen_xor_tl(cpu_sr_ov, srca, srcb);
 221    tcg_gen_xor_tl(t0, res, srcb);
 222    tcg_gen_andc_tl(cpu_sr_ov, t0, cpu_sr_ov);
 223    tcg_temp_free(t0);
 224
 225    tcg_gen_mov_tl(dest, res);
 226    tcg_temp_free(res);
 227
 228    gen_ove_cyov(dc);
 229}
 230
 231static void gen_sub(DisasContext *dc, TCGv dest, TCGv srca, TCGv srcb)
 232{
 233    TCGv res = tcg_temp_new();
 234
 235    tcg_gen_sub_tl(res, srca, srcb);
 236    tcg_gen_xor_tl(cpu_sr_cy, srca, srcb);
 237    tcg_gen_xor_tl(cpu_sr_ov, res, srcb);
 238    tcg_gen_and_tl(cpu_sr_ov, cpu_sr_ov, cpu_sr_cy);
 239    tcg_gen_setcond_tl(TCG_COND_LTU, cpu_sr_cy, srca, srcb);
 240
 241    tcg_gen_mov_tl(dest, res);
 242    tcg_temp_free(res);
 243
 244    gen_ove_cyov(dc);
 245}
 246
 247static void gen_mul(DisasContext *dc, TCGv dest, TCGv srca, TCGv srcb)
 248{
 249    TCGv t0 = tcg_temp_new();
 250
 251    tcg_gen_muls2_tl(dest, cpu_sr_ov, srca, srcb);
 252    tcg_gen_sari_tl(t0, dest, TARGET_LONG_BITS - 1);
 253    tcg_gen_setcond_tl(TCG_COND_NE, cpu_sr_ov, cpu_sr_ov, t0);
 254    tcg_temp_free(t0);
 255
 256    tcg_gen_neg_tl(cpu_sr_ov, cpu_sr_ov);
 257    gen_ove_ov(dc);
 258}
 259
 260static void gen_mulu(DisasContext *dc, TCGv dest, TCGv srca, TCGv srcb)
 261{
 262    tcg_gen_muls2_tl(dest, cpu_sr_cy, srca, srcb);
 263    tcg_gen_setcondi_tl(TCG_COND_NE, cpu_sr_cy, cpu_sr_cy, 0);
 264
 265    gen_ove_cy(dc);
 266}
 267
 268static void gen_div(DisasContext *dc, TCGv dest, TCGv srca, TCGv srcb)
 269{
 270    TCGv t0 = tcg_temp_new();
 271
 272    tcg_gen_setcondi_tl(TCG_COND_EQ, cpu_sr_ov, srcb, 0);
 273    /* The result of divide-by-zero is undefined.
 274       Supress the host-side exception by dividing by 1.  */
 275    tcg_gen_or_tl(t0, srcb, cpu_sr_ov);
 276    tcg_gen_div_tl(dest, srca, t0);
 277    tcg_temp_free(t0);
 278
 279    tcg_gen_neg_tl(cpu_sr_ov, cpu_sr_ov);
 280    gen_ove_ov(dc);
 281}
 282
 283static void gen_divu(DisasContext *dc, TCGv dest, TCGv srca, TCGv srcb)
 284{
 285    TCGv t0 = tcg_temp_new();
 286
 287    tcg_gen_setcondi_tl(TCG_COND_EQ, cpu_sr_cy, srcb, 0);
 288    /* The result of divide-by-zero is undefined.
 289       Supress the host-side exception by dividing by 1.  */
 290    tcg_gen_or_tl(t0, srcb, cpu_sr_cy);
 291    tcg_gen_divu_tl(dest, srca, t0);
 292    tcg_temp_free(t0);
 293
 294    gen_ove_cy(dc);
 295}
 296
 297static void gen_muld(DisasContext *dc, TCGv srca, TCGv srcb)
 298{
 299    TCGv_i64 t1 = tcg_temp_new_i64();
 300    TCGv_i64 t2 = tcg_temp_new_i64();
 301
 302    tcg_gen_ext_tl_i64(t1, srca);
 303    tcg_gen_ext_tl_i64(t2, srcb);
 304    if (TARGET_LONG_BITS == 32) {
 305        tcg_gen_mul_i64(cpu_mac, t1, t2);
 306        tcg_gen_movi_tl(cpu_sr_ov, 0);
 307    } else {
 308        TCGv_i64 high = tcg_temp_new_i64();
 309
 310        tcg_gen_muls2_i64(cpu_mac, high, t1, t2);
 311        tcg_gen_sari_i64(t1, cpu_mac, 63);
 312        tcg_gen_setcond_i64(TCG_COND_NE, t1, t1, high);
 313        tcg_temp_free_i64(high);
 314        tcg_gen_trunc_i64_tl(cpu_sr_ov, t1);
 315        tcg_gen_neg_tl(cpu_sr_ov, cpu_sr_ov);
 316
 317        gen_ove_ov(dc);
 318    }
 319    tcg_temp_free_i64(t1);
 320    tcg_temp_free_i64(t2);
 321}
 322
 323static void gen_muldu(DisasContext *dc, TCGv srca, TCGv srcb)
 324{
 325    TCGv_i64 t1 = tcg_temp_new_i64();
 326    TCGv_i64 t2 = tcg_temp_new_i64();
 327
 328    tcg_gen_extu_tl_i64(t1, srca);
 329    tcg_gen_extu_tl_i64(t2, srcb);
 330    if (TARGET_LONG_BITS == 32) {
 331        tcg_gen_mul_i64(cpu_mac, t1, t2);
 332        tcg_gen_movi_tl(cpu_sr_cy, 0);
 333    } else {
 334        TCGv_i64 high = tcg_temp_new_i64();
 335
 336        tcg_gen_mulu2_i64(cpu_mac, high, t1, t2);
 337        tcg_gen_setcondi_i64(TCG_COND_NE, high, high, 0);
 338        tcg_gen_trunc_i64_tl(cpu_sr_cy, high);
 339        tcg_temp_free_i64(high);
 340
 341        gen_ove_cy(dc);
 342    }
 343    tcg_temp_free_i64(t1);
 344    tcg_temp_free_i64(t2);
 345}
 346
 347static void gen_mac(DisasContext *dc, TCGv srca, TCGv srcb)
 348{
 349    TCGv_i64 t1 = tcg_temp_new_i64();
 350    TCGv_i64 t2 = tcg_temp_new_i64();
 351
 352    tcg_gen_ext_tl_i64(t1, srca);
 353    tcg_gen_ext_tl_i64(t2, srcb);
 354    tcg_gen_mul_i64(t1, t1, t2);
 355
 356    /* Note that overflow is only computed during addition stage.  */
 357    tcg_gen_xor_i64(t2, cpu_mac, t1);
 358    tcg_gen_add_i64(cpu_mac, cpu_mac, t1);
 359    tcg_gen_xor_i64(t1, t1, cpu_mac);
 360    tcg_gen_andc_i64(t1, t1, t2);
 361    tcg_temp_free_i64(t2);
 362
 363#if TARGET_LONG_BITS == 32
 364    tcg_gen_extrh_i64_i32(cpu_sr_ov, t1);
 365#else
 366    tcg_gen_mov_i64(cpu_sr_ov, t1);
 367#endif
 368    tcg_temp_free_i64(t1);
 369
 370    gen_ove_ov(dc);
 371}
 372
 373static void gen_macu(DisasContext *dc, TCGv srca, TCGv srcb)
 374{
 375    TCGv_i64 t1 = tcg_temp_new_i64();
 376    TCGv_i64 t2 = tcg_temp_new_i64();
 377
 378    tcg_gen_extu_tl_i64(t1, srca);
 379    tcg_gen_extu_tl_i64(t2, srcb);
 380    tcg_gen_mul_i64(t1, t1, t2);
 381    tcg_temp_free_i64(t2);
 382
 383    /* Note that overflow is only computed during addition stage.  */
 384    tcg_gen_add_i64(cpu_mac, cpu_mac, t1);
 385    tcg_gen_setcond_i64(TCG_COND_LTU, t1, cpu_mac, t1);
 386    tcg_gen_trunc_i64_tl(cpu_sr_cy, t1);
 387    tcg_temp_free_i64(t1);
 388
 389    gen_ove_cy(dc);
 390}
 391
 392static void gen_msb(DisasContext *dc, TCGv srca, TCGv srcb)
 393{
 394    TCGv_i64 t1 = tcg_temp_new_i64();
 395    TCGv_i64 t2 = tcg_temp_new_i64();
 396
 397    tcg_gen_ext_tl_i64(t1, srca);
 398    tcg_gen_ext_tl_i64(t2, srcb);
 399    tcg_gen_mul_i64(t1, t1, t2);
 400
 401    /* Note that overflow is only computed during subtraction stage.  */
 402    tcg_gen_xor_i64(t2, cpu_mac, t1);
 403    tcg_gen_sub_i64(cpu_mac, cpu_mac, t1);
 404    tcg_gen_xor_i64(t1, t1, cpu_mac);
 405    tcg_gen_and_i64(t1, t1, t2);
 406    tcg_temp_free_i64(t2);
 407
 408#if TARGET_LONG_BITS == 32
 409    tcg_gen_extrh_i64_i32(cpu_sr_ov, t1);
 410#else
 411    tcg_gen_mov_i64(cpu_sr_ov, t1);
 412#endif
 413    tcg_temp_free_i64(t1);
 414
 415    gen_ove_ov(dc);
 416}
 417
 418static void gen_msbu(DisasContext *dc, TCGv srca, TCGv srcb)
 419{
 420    TCGv_i64 t1 = tcg_temp_new_i64();
 421    TCGv_i64 t2 = tcg_temp_new_i64();
 422
 423    tcg_gen_extu_tl_i64(t1, srca);
 424    tcg_gen_extu_tl_i64(t2, srcb);
 425    tcg_gen_mul_i64(t1, t1, t2);
 426
 427    /* Note that overflow is only computed during subtraction stage.  */
 428    tcg_gen_setcond_i64(TCG_COND_LTU, t2, cpu_mac, t1);
 429    tcg_gen_sub_i64(cpu_mac, cpu_mac, t1);
 430    tcg_gen_trunc_i64_tl(cpu_sr_cy, t2);
 431    tcg_temp_free_i64(t2);
 432    tcg_temp_free_i64(t1);
 433
 434    gen_ove_cy(dc);
 435}
 436
 437static bool trans_l_add(DisasContext *dc, arg_dab *a)
 438{
 439    check_r0_write(a->d);
 440    gen_add(dc, cpu_R[a->d], cpu_R[a->a], cpu_R[a->b]);
 441    return true;
 442}
 443
 444static bool trans_l_addc(DisasContext *dc, arg_dab *a)
 445{
 446    check_r0_write(a->d);
 447    gen_addc(dc, cpu_R[a->d], cpu_R[a->a], cpu_R[a->b]);
 448    return true;
 449}
 450
 451static bool trans_l_sub(DisasContext *dc, arg_dab *a)
 452{
 453    check_r0_write(a->d);
 454    gen_sub(dc, cpu_R[a->d], cpu_R[a->a], cpu_R[a->b]);
 455    return true;
 456}
 457
 458static bool trans_l_and(DisasContext *dc, arg_dab *a)
 459{
 460    check_r0_write(a->d);
 461    tcg_gen_and_tl(cpu_R[a->d], cpu_R[a->a], cpu_R[a->b]);
 462    return true;
 463}
 464
 465static bool trans_l_or(DisasContext *dc, arg_dab *a)
 466{
 467    check_r0_write(a->d);
 468    tcg_gen_or_tl(cpu_R[a->d], cpu_R[a->a], cpu_R[a->b]);
 469    return true;
 470}
 471
 472static bool trans_l_xor(DisasContext *dc, arg_dab *a)
 473{
 474    check_r0_write(a->d);
 475    tcg_gen_xor_tl(cpu_R[a->d], cpu_R[a->a], cpu_R[a->b]);
 476    return true;
 477}
 478
 479static bool trans_l_sll(DisasContext *dc, arg_dab *a)
 480{
 481    check_r0_write(a->d);
 482    tcg_gen_shl_tl(cpu_R[a->d], cpu_R[a->a], cpu_R[a->b]);
 483    return true;
 484}
 485
 486static bool trans_l_srl(DisasContext *dc, arg_dab *a)
 487{
 488    check_r0_write(a->d);
 489    tcg_gen_shr_tl(cpu_R[a->d], cpu_R[a->a], cpu_R[a->b]);
 490    return true;
 491}
 492
 493static bool trans_l_sra(DisasContext *dc, arg_dab *a)
 494{
 495    check_r0_write(a->d);
 496    tcg_gen_sar_tl(cpu_R[a->d], cpu_R[a->a], cpu_R[a->b]);
 497    return true;
 498}
 499
 500static bool trans_l_ror(DisasContext *dc, arg_dab *a)
 501{
 502    check_r0_write(a->d);
 503    tcg_gen_rotr_tl(cpu_R[a->d], cpu_R[a->a], cpu_R[a->b]);
 504    return true;
 505}
 506
 507static bool trans_l_exths(DisasContext *dc, arg_da *a)
 508{
 509    check_r0_write(a->d);
 510    tcg_gen_ext16s_tl(cpu_R[a->d], cpu_R[a->a]);
 511    return true;
 512}
 513
 514static bool trans_l_extbs(DisasContext *dc, arg_da *a)
 515{
 516    check_r0_write(a->d);
 517    tcg_gen_ext8s_tl(cpu_R[a->d], cpu_R[a->a]);
 518    return true;
 519}
 520
 521static bool trans_l_exthz(DisasContext *dc, arg_da *a)
 522{
 523    check_r0_write(a->d);
 524    tcg_gen_ext16u_tl(cpu_R[a->d], cpu_R[a->a]);
 525    return true;
 526}
 527
 528static bool trans_l_extbz(DisasContext *dc, arg_da *a)
 529{
 530    check_r0_write(a->d);
 531    tcg_gen_ext8u_tl(cpu_R[a->d], cpu_R[a->a]);
 532    return true;
 533}
 534
 535static bool trans_l_cmov(DisasContext *dc, arg_dab *a)
 536{
 537    TCGv zero;
 538
 539    check_r0_write(a->d);
 540    zero = tcg_const_tl(0);
 541    tcg_gen_movcond_tl(TCG_COND_NE, cpu_R[a->d], cpu_sr_f, zero,
 542                       cpu_R[a->a], cpu_R[a->b]);
 543    tcg_temp_free(zero);
 544    return true;
 545}
 546
 547static bool trans_l_ff1(DisasContext *dc, arg_da *a)
 548{
 549    check_r0_write(a->d);
 550    tcg_gen_ctzi_tl(cpu_R[a->d], cpu_R[a->a], -1);
 551    tcg_gen_addi_tl(cpu_R[a->d], cpu_R[a->d], 1);
 552    return true;
 553}
 554
 555static bool trans_l_fl1(DisasContext *dc, arg_da *a)
 556{
 557    check_r0_write(a->d);
 558    tcg_gen_clzi_tl(cpu_R[a->d], cpu_R[a->a], TARGET_LONG_BITS);
 559    tcg_gen_subfi_tl(cpu_R[a->d], TARGET_LONG_BITS, cpu_R[a->d]);
 560    return true;
 561}
 562
 563static bool trans_l_mul(DisasContext *dc, arg_dab *a)
 564{
 565    check_r0_write(a->d);
 566    gen_mul(dc, cpu_R[a->d], cpu_R[a->a], cpu_R[a->b]);
 567    return true;
 568}
 569
 570static bool trans_l_mulu(DisasContext *dc, arg_dab *a)
 571{
 572    check_r0_write(a->d);
 573    gen_mulu(dc, cpu_R[a->d], cpu_R[a->a], cpu_R[a->b]);
 574    return true;
 575}
 576
 577static bool trans_l_div(DisasContext *dc, arg_dab *a)
 578{
 579    check_r0_write(a->d);
 580    gen_div(dc, cpu_R[a->d], cpu_R[a->a], cpu_R[a->b]);
 581    return true;
 582}
 583
 584static bool trans_l_divu(DisasContext *dc, arg_dab *a)
 585{
 586    check_r0_write(a->d);
 587    gen_divu(dc, cpu_R[a->d], cpu_R[a->a], cpu_R[a->b]);
 588    return true;
 589}
 590
 591static bool trans_l_muld(DisasContext *dc, arg_ab *a)
 592{
 593    gen_muld(dc, cpu_R[a->a], cpu_R[a->b]);
 594    return true;
 595}
 596
 597static bool trans_l_muldu(DisasContext *dc, arg_ab *a)
 598{
 599    gen_muldu(dc, cpu_R[a->a], cpu_R[a->b]);
 600    return true;
 601}
 602
 603static bool trans_l_j(DisasContext *dc, arg_l_j *a)
 604{
 605    target_ulong tmp_pc = dc->base.pc_next + a->n * 4;
 606
 607    tcg_gen_movi_tl(jmp_pc, tmp_pc);
 608    dc->jmp_pc_imm = tmp_pc;
 609    dc->delayed_branch = 2;
 610    return true;
 611}
 612
 613static bool trans_l_jal(DisasContext *dc, arg_l_jal *a)
 614{
 615    target_ulong tmp_pc = dc->base.pc_next + a->n * 4;
 616    target_ulong ret_pc = dc->base.pc_next + 8;
 617
 618    tcg_gen_movi_tl(cpu_R[9], ret_pc);
 619    /* Optimize jal being used to load the PC for PIC.  */
 620    if (tmp_pc != ret_pc) {
 621        tcg_gen_movi_tl(jmp_pc, tmp_pc);
 622        dc->jmp_pc_imm = tmp_pc;
 623        dc->delayed_branch = 2;
 624    }
 625    return true;
 626}
 627
 628static void do_bf(DisasContext *dc, arg_l_bf *a, TCGCond cond)
 629{
 630    target_ulong tmp_pc = dc->base.pc_next + a->n * 4;
 631    TCGv t_next = tcg_const_tl(dc->base.pc_next + 8);
 632    TCGv t_true = tcg_const_tl(tmp_pc);
 633    TCGv t_zero = tcg_const_tl(0);
 634
 635    tcg_gen_movcond_tl(cond, jmp_pc, cpu_sr_f, t_zero, t_true, t_next);
 636
 637    tcg_temp_free(t_next);
 638    tcg_temp_free(t_true);
 639    tcg_temp_free(t_zero);
 640    dc->delayed_branch = 2;
 641}
 642
 643static bool trans_l_bf(DisasContext *dc, arg_l_bf *a)
 644{
 645    do_bf(dc, a, TCG_COND_NE);
 646    return true;
 647}
 648
 649static bool trans_l_bnf(DisasContext *dc, arg_l_bf *a)
 650{
 651    do_bf(dc, a, TCG_COND_EQ);
 652    return true;
 653}
 654
 655static bool trans_l_jr(DisasContext *dc, arg_l_jr *a)
 656{
 657    tcg_gen_mov_tl(jmp_pc, cpu_R[a->b]);
 658    dc->delayed_branch = 2;
 659    return true;
 660}
 661
 662static bool trans_l_jalr(DisasContext *dc, arg_l_jalr *a)
 663{
 664    tcg_gen_mov_tl(jmp_pc, cpu_R[a->b]);
 665    tcg_gen_movi_tl(cpu_R[9], dc->base.pc_next + 8);
 666    dc->delayed_branch = 2;
 667    return true;
 668}
 669
 670static bool trans_l_lwa(DisasContext *dc, arg_load *a)
 671{
 672    TCGv ea;
 673
 674    check_r0_write(a->d);
 675    ea = tcg_temp_new();
 676    tcg_gen_addi_tl(ea, cpu_R[a->a], a->i);
 677    tcg_gen_qemu_ld_tl(cpu_R[a->d], ea, dc->mem_idx, MO_TEUL);
 678    tcg_gen_mov_tl(cpu_lock_addr, ea);
 679    tcg_gen_mov_tl(cpu_lock_value, cpu_R[a->d]);
 680    tcg_temp_free(ea);
 681    return true;
 682}
 683
 684static void do_load(DisasContext *dc, arg_load *a, TCGMemOp mop)
 685{
 686    TCGv ea;
 687
 688    check_r0_write(a->d);
 689    ea = tcg_temp_new();
 690    tcg_gen_addi_tl(ea, cpu_R[a->a], a->i);
 691    tcg_gen_qemu_ld_tl(cpu_R[a->d], ea, dc->mem_idx, mop);
 692    tcg_temp_free(ea);
 693}
 694
 695static bool trans_l_lwz(DisasContext *dc, arg_load *a)
 696{
 697    do_load(dc, a, MO_TEUL);
 698    return true;
 699}
 700
 701static bool trans_l_lws(DisasContext *dc, arg_load *a)
 702{
 703    do_load(dc, a, MO_TESL);
 704    return true;
 705}
 706
 707static bool trans_l_lbz(DisasContext *dc, arg_load *a)
 708{
 709    do_load(dc, a, MO_UB);
 710    return true;
 711}
 712
 713static bool trans_l_lbs(DisasContext *dc, arg_load *a)
 714{
 715    do_load(dc, a, MO_SB);
 716    return true;
 717}
 718
 719static bool trans_l_lhz(DisasContext *dc, arg_load *a)
 720{
 721    do_load(dc, a, MO_TEUW);
 722    return true;
 723}
 724
 725static bool trans_l_lhs(DisasContext *dc, arg_load *a)
 726{
 727    do_load(dc, a, MO_TESW);
 728    return true;
 729}
 730
 731static bool trans_l_swa(DisasContext *dc, arg_store *a)
 732{
 733    TCGv ea, val;
 734    TCGLabel *lab_fail, *lab_done;
 735
 736    ea = tcg_temp_new();
 737    tcg_gen_addi_tl(ea, cpu_R[a->a], a->i);
 738
 739    /* For TB_FLAGS_R0_0, the branch below invalidates the temporary assigned
 740       to cpu_R[0].  Since l.swa is quite often immediately followed by a
 741       branch, don't bother reallocating; finish the TB using the "real" R0.
 742       This also takes care of RB input across the branch.  */
 743    cpu_R[0] = cpu_R0;
 744
 745    lab_fail = gen_new_label();
 746    lab_done = gen_new_label();
 747    tcg_gen_brcond_tl(TCG_COND_NE, ea, cpu_lock_addr, lab_fail);
 748    tcg_temp_free(ea);
 749
 750    val = tcg_temp_new();
 751    tcg_gen_atomic_cmpxchg_tl(val, cpu_lock_addr, cpu_lock_value,
 752                              cpu_R[a->b], dc->mem_idx, MO_TEUL);
 753    tcg_gen_setcond_tl(TCG_COND_EQ, cpu_sr_f, val, cpu_lock_value);
 754    tcg_temp_free(val);
 755
 756    tcg_gen_br(lab_done);
 757
 758    gen_set_label(lab_fail);
 759    tcg_gen_movi_tl(cpu_sr_f, 0);
 760
 761    gen_set_label(lab_done);
 762    tcg_gen_movi_tl(cpu_lock_addr, -1);
 763    return true;
 764}
 765
 766static void do_store(DisasContext *dc, arg_store *a, TCGMemOp mop)
 767{
 768    TCGv t0 = tcg_temp_new();
 769    tcg_gen_addi_tl(t0, cpu_R[a->a], a->i);
 770    tcg_gen_qemu_st_tl(cpu_R[a->b], t0, dc->mem_idx, mop);
 771    tcg_temp_free(t0);
 772}
 773
 774static bool trans_l_sw(DisasContext *dc, arg_store *a)
 775{
 776    do_store(dc, a, MO_TEUL);
 777    return true;
 778}
 779
 780static bool trans_l_sb(DisasContext *dc, arg_store *a)
 781{
 782    do_store(dc, a, MO_UB);
 783    return true;
 784}
 785
 786static bool trans_l_sh(DisasContext *dc, arg_store *a)
 787{
 788    do_store(dc, a, MO_TEUW);
 789    return true;
 790}
 791
 792static bool trans_l_nop(DisasContext *dc, arg_l_nop *a)
 793{
 794    return true;
 795}
 796
 797static bool trans_l_addi(DisasContext *dc, arg_rri *a)
 798{
 799    TCGv t0;
 800
 801    check_r0_write(a->d);
 802    t0 = tcg_const_tl(a->i);
 803    gen_add(dc, cpu_R[a->d], cpu_R[a->a], t0);
 804    tcg_temp_free(t0);
 805    return true;
 806}
 807
 808static bool trans_l_addic(DisasContext *dc, arg_rri *a)
 809{
 810    TCGv t0;
 811
 812    check_r0_write(a->d);
 813    t0 = tcg_const_tl(a->i);
 814    gen_addc(dc, cpu_R[a->d], cpu_R[a->a], t0);
 815    tcg_temp_free(t0);
 816    return true;
 817}
 818
 819static bool trans_l_muli(DisasContext *dc, arg_rri *a)
 820{
 821    TCGv t0;
 822
 823    check_r0_write(a->d);
 824    t0 = tcg_const_tl(a->i);
 825    gen_mul(dc, cpu_R[a->d], cpu_R[a->a], t0);
 826    tcg_temp_free(t0);
 827    return true;
 828}
 829
 830static bool trans_l_maci(DisasContext *dc, arg_l_maci *a)
 831{
 832    TCGv t0;
 833
 834    t0 = tcg_const_tl(a->i);
 835    gen_mac(dc, cpu_R[a->a], t0);
 836    tcg_temp_free(t0);
 837    return true;
 838}
 839
 840static bool trans_l_andi(DisasContext *dc, arg_rrk *a)
 841{
 842    check_r0_write(a->d);
 843    tcg_gen_andi_tl(cpu_R[a->d], cpu_R[a->a], a->k);
 844    return true;
 845}
 846
 847static bool trans_l_ori(DisasContext *dc, arg_rrk *a)
 848{
 849    check_r0_write(a->d);
 850    tcg_gen_ori_tl(cpu_R[a->d], cpu_R[a->a], a->k);
 851    return true;
 852}
 853
 854static bool trans_l_xori(DisasContext *dc, arg_rri *a)
 855{
 856    check_r0_write(a->d);
 857    tcg_gen_xori_tl(cpu_R[a->d], cpu_R[a->a], a->i);
 858    return true;
 859}
 860
 861static bool trans_l_mfspr(DisasContext *dc, arg_l_mfspr *a)
 862{
 863    check_r0_write(a->d);
 864
 865    if (is_user(dc)) {
 866        gen_illegal_exception(dc);
 867    } else {
 868        TCGv spr = tcg_temp_new();
 869        tcg_gen_ori_tl(spr, cpu_R[a->a], a->k);
 870        gen_helper_mfspr(cpu_R[a->d], cpu_env, cpu_R[a->d], spr);
 871        tcg_temp_free(spr);
 872    }
 873    return true;
 874}
 875
 876static bool trans_l_mtspr(DisasContext *dc, arg_l_mtspr *a)
 877{
 878    if (is_user(dc)) {
 879        gen_illegal_exception(dc);
 880    } else {
 881        TCGv spr;
 882
 883        /* For SR, we will need to exit the TB to recognize the new
 884         * exception state.  For NPC, in theory this counts as a branch
 885         * (although the SPR only exists for use by an ICE).  Save all
 886         * of the cpu state first, allowing it to be overwritten.
 887         */
 888        if (dc->delayed_branch) {
 889            tcg_gen_mov_tl(cpu_pc, jmp_pc);
 890            tcg_gen_discard_tl(jmp_pc);
 891        } else {
 892            tcg_gen_movi_tl(cpu_pc, dc->base.pc_next + 4);
 893        }
 894        dc->base.is_jmp = DISAS_EXIT;
 895
 896        spr = tcg_temp_new();
 897        tcg_gen_ori_tl(spr, cpu_R[a->a], a->k);
 898        gen_helper_mtspr(cpu_env, spr, cpu_R[a->b]);
 899        tcg_temp_free(spr);
 900    }
 901    return true;
 902}
 903
 904static bool trans_l_mac(DisasContext *dc, arg_ab *a)
 905{
 906    gen_mac(dc, cpu_R[a->a], cpu_R[a->b]);
 907    return true;
 908}
 909
 910static bool trans_l_msb(DisasContext *dc, arg_ab *a)
 911{
 912    gen_msb(dc, cpu_R[a->a], cpu_R[a->b]);
 913    return true;
 914}
 915
 916static bool trans_l_macu(DisasContext *dc, arg_ab *a)
 917{
 918    gen_macu(dc, cpu_R[a->a], cpu_R[a->b]);
 919    return true;
 920}
 921
 922static bool trans_l_msbu(DisasContext *dc, arg_ab *a)
 923{
 924    gen_msbu(dc, cpu_R[a->a], cpu_R[a->b]);
 925    return true;
 926}
 927
 928static bool trans_l_slli(DisasContext *dc, arg_dal *a)
 929{
 930    check_r0_write(a->d);
 931    tcg_gen_shli_tl(cpu_R[a->d], cpu_R[a->a], a->l & (TARGET_LONG_BITS - 1));
 932    return true;
 933}
 934
 935static bool trans_l_srli(DisasContext *dc, arg_dal *a)
 936{
 937    check_r0_write(a->d);
 938    tcg_gen_shri_tl(cpu_R[a->d], cpu_R[a->a], a->l & (TARGET_LONG_BITS - 1));
 939    return true;
 940}
 941
 942static bool trans_l_srai(DisasContext *dc, arg_dal *a)
 943{
 944    check_r0_write(a->d);
 945    tcg_gen_sari_tl(cpu_R[a->d], cpu_R[a->a], a->l & (TARGET_LONG_BITS - 1));
 946    return true;
 947}
 948
 949static bool trans_l_rori(DisasContext *dc, arg_dal *a)
 950{
 951    check_r0_write(a->d);
 952    tcg_gen_rotri_tl(cpu_R[a->d], cpu_R[a->a], a->l & (TARGET_LONG_BITS - 1));
 953    return true;
 954}
 955
 956static bool trans_l_movhi(DisasContext *dc, arg_l_movhi *a)
 957{
 958    check_r0_write(a->d);
 959    tcg_gen_movi_tl(cpu_R[a->d], a->k << 16);
 960    return true;
 961}
 962
 963static bool trans_l_macrc(DisasContext *dc, arg_l_macrc *a)
 964{
 965    check_r0_write(a->d);
 966    tcg_gen_trunc_i64_tl(cpu_R[a->d], cpu_mac);
 967    tcg_gen_movi_i64(cpu_mac, 0);
 968    return true;
 969}
 970
 971static bool trans_l_sfeq(DisasContext *dc, arg_ab *a)
 972{
 973    tcg_gen_setcond_tl(TCG_COND_EQ, cpu_sr_f, cpu_R[a->a], cpu_R[a->b]);
 974    return true;
 975}
 976
 977static bool trans_l_sfne(DisasContext *dc, arg_ab *a)
 978{
 979    tcg_gen_setcond_tl(TCG_COND_NE, cpu_sr_f, cpu_R[a->a], cpu_R[a->b]);
 980    return true;
 981}
 982
 983static bool trans_l_sfgtu(DisasContext *dc, arg_ab *a)
 984{
 985    tcg_gen_setcond_tl(TCG_COND_GTU, cpu_sr_f, cpu_R[a->a], cpu_R[a->b]);
 986    return true;
 987}
 988
 989static bool trans_l_sfgeu(DisasContext *dc, arg_ab *a)
 990{
 991    tcg_gen_setcond_tl(TCG_COND_GEU, cpu_sr_f, cpu_R[a->a], cpu_R[a->b]);
 992    return true;
 993}
 994
 995static bool trans_l_sfltu(DisasContext *dc, arg_ab *a)
 996{
 997    tcg_gen_setcond_tl(TCG_COND_LTU, cpu_sr_f, cpu_R[a->a], cpu_R[a->b]);
 998    return true;
 999}
1000
1001static bool trans_l_sfleu(DisasContext *dc, arg_ab *a)
1002{
1003    tcg_gen_setcond_tl(TCG_COND_LEU, cpu_sr_f, cpu_R[a->a], cpu_R[a->b]);
1004    return true;
1005}
1006
1007static bool trans_l_sfgts(DisasContext *dc, arg_ab *a)
1008{
1009    tcg_gen_setcond_tl(TCG_COND_GT, cpu_sr_f, cpu_R[a->a], cpu_R[a->b]);
1010    return true;
1011}
1012
1013static bool trans_l_sfges(DisasContext *dc, arg_ab *a)
1014{
1015    tcg_gen_setcond_tl(TCG_COND_GE, cpu_sr_f, cpu_R[a->a], cpu_R[a->b]);
1016    return true;
1017}
1018
1019static bool trans_l_sflts(DisasContext *dc, arg_ab *a)
1020{
1021    tcg_gen_setcond_tl(TCG_COND_LT, cpu_sr_f, cpu_R[a->a], cpu_R[a->b]);
1022    return true;
1023}
1024
1025static bool trans_l_sfles(DisasContext *dc, arg_ab *a)
1026{
1027    tcg_gen_setcond_tl(TCG_COND_LE, cpu_sr_f, cpu_R[a->a], cpu_R[a->b]);
1028    return true;
1029}
1030
1031static bool trans_l_sfeqi(DisasContext *dc, arg_ai *a)
1032{
1033    tcg_gen_setcondi_tl(TCG_COND_EQ, cpu_sr_f, cpu_R[a->a], a->i);
1034    return true;
1035}
1036
1037static bool trans_l_sfnei(DisasContext *dc, arg_ai *a)
1038{
1039    tcg_gen_setcondi_tl(TCG_COND_NE, cpu_sr_f, cpu_R[a->a], a->i);
1040    return true;
1041}
1042
1043static bool trans_l_sfgtui(DisasContext *dc, arg_ai *a)
1044{
1045    tcg_gen_setcondi_tl(TCG_COND_GTU, cpu_sr_f, cpu_R[a->a], a->i);
1046    return true;
1047}
1048
1049static bool trans_l_sfgeui(DisasContext *dc, arg_ai *a)
1050{
1051    tcg_gen_setcondi_tl(TCG_COND_GEU, cpu_sr_f, cpu_R[a->a], a->i);
1052    return true;
1053}
1054
1055static bool trans_l_sfltui(DisasContext *dc, arg_ai *a)
1056{
1057    tcg_gen_setcondi_tl(TCG_COND_LTU, cpu_sr_f, cpu_R[a->a], a->i);
1058    return true;
1059}
1060
1061static bool trans_l_sfleui(DisasContext *dc, arg_ai *a)
1062{
1063    tcg_gen_setcondi_tl(TCG_COND_LEU, cpu_sr_f, cpu_R[a->a], a->i);
1064    return true;
1065}
1066
1067static bool trans_l_sfgtsi(DisasContext *dc, arg_ai *a)
1068{
1069    tcg_gen_setcondi_tl(TCG_COND_GT, cpu_sr_f, cpu_R[a->a], a->i);
1070    return true;
1071}
1072
1073static bool trans_l_sfgesi(DisasContext *dc, arg_ai *a)
1074{
1075    tcg_gen_setcondi_tl(TCG_COND_GE, cpu_sr_f, cpu_R[a->a], a->i);
1076    return true;
1077}
1078
1079static bool trans_l_sfltsi(DisasContext *dc, arg_ai *a)
1080{
1081    tcg_gen_setcondi_tl(TCG_COND_LT, cpu_sr_f, cpu_R[a->a], a->i);
1082    return true;
1083}
1084
1085static bool trans_l_sflesi(DisasContext *dc, arg_ai *a)
1086{
1087    tcg_gen_setcondi_tl(TCG_COND_LE, cpu_sr_f, cpu_R[a->a], a->i);
1088    return true;
1089}
1090
1091static bool trans_l_sys(DisasContext *dc, arg_l_sys *a)
1092{
1093    tcg_gen_movi_tl(cpu_pc, dc->base.pc_next);
1094    gen_exception(dc, EXCP_SYSCALL);
1095    dc->base.is_jmp = DISAS_NORETURN;
1096    return true;
1097}
1098
1099static bool trans_l_trap(DisasContext *dc, arg_l_trap *a)
1100{
1101    tcg_gen_movi_tl(cpu_pc, dc->base.pc_next);
1102    gen_exception(dc, EXCP_TRAP);
1103    dc->base.is_jmp = DISAS_NORETURN;
1104    return true;
1105}
1106
1107static bool trans_l_msync(DisasContext *dc, arg_l_msync *a)
1108{
1109    tcg_gen_mb(TCG_MO_ALL);
1110    return true;
1111}
1112
1113static bool trans_l_psync(DisasContext *dc, arg_l_psync *a)
1114{
1115    return true;
1116}
1117
1118static bool trans_l_csync(DisasContext *dc, arg_l_csync *a)
1119{
1120    return true;
1121}
1122
1123static bool trans_l_rfe(DisasContext *dc, arg_l_rfe *a)
1124{
1125    if (is_user(dc)) {
1126        gen_illegal_exception(dc);
1127    } else {
1128        gen_helper_rfe(cpu_env);
1129        dc->base.is_jmp = DISAS_EXIT;
1130    }
1131    return true;
1132}
1133
1134static void do_fp2(DisasContext *dc, arg_da *a,
1135                   void (*fn)(TCGv, TCGv_env, TCGv))
1136{
1137    check_r0_write(a->d);
1138    fn(cpu_R[a->d], cpu_env, cpu_R[a->a]);
1139    gen_helper_update_fpcsr(cpu_env);
1140}
1141
1142static void do_fp3(DisasContext *dc, arg_dab *a,
1143                   void (*fn)(TCGv, TCGv_env, TCGv, TCGv))
1144{
1145    check_r0_write(a->d);
1146    fn(cpu_R[a->d], cpu_env, cpu_R[a->a], cpu_R[a->b]);
1147    gen_helper_update_fpcsr(cpu_env);
1148}
1149
1150static void do_fpcmp(DisasContext *dc, arg_ab *a,
1151                     void (*fn)(TCGv, TCGv_env, TCGv, TCGv),
1152                     bool inv, bool swap)
1153{
1154    if (swap) {
1155        fn(cpu_sr_f, cpu_env, cpu_R[a->b], cpu_R[a->a]);
1156    } else {
1157        fn(cpu_sr_f, cpu_env, cpu_R[a->a], cpu_R[a->b]);
1158    }
1159    if (inv) {
1160        tcg_gen_xori_tl(cpu_sr_f, cpu_sr_f, 1);
1161    }
1162    gen_helper_update_fpcsr(cpu_env);
1163}
1164
1165static bool trans_lf_add_s(DisasContext *dc, arg_dab *a)
1166{
1167    do_fp3(dc, a, gen_helper_float_add_s);
1168    return true;
1169}
1170
1171static bool trans_lf_sub_s(DisasContext *dc, arg_dab *a)
1172{
1173    do_fp3(dc, a, gen_helper_float_sub_s);
1174    return true;
1175}
1176
1177static bool trans_lf_mul_s(DisasContext *dc, arg_dab *a)
1178{
1179    do_fp3(dc, a, gen_helper_float_mul_s);
1180    return true;
1181}
1182
1183static bool trans_lf_div_s(DisasContext *dc, arg_dab *a)
1184{
1185    do_fp3(dc, a, gen_helper_float_div_s);
1186    return true;
1187}
1188
1189static bool trans_lf_rem_s(DisasContext *dc, arg_dab *a)
1190{
1191    do_fp3(dc, a, gen_helper_float_rem_s);
1192    return true;
1193}
1194
1195static bool trans_lf_itof_s(DisasContext *dc, arg_da *a)
1196{
1197    do_fp2(dc, a, gen_helper_itofs);
1198    return true;
1199}
1200
1201static bool trans_lf_ftoi_s(DisasContext *dc, arg_da *a)
1202{
1203    do_fp2(dc, a, gen_helper_ftois);
1204    return true;
1205}
1206
1207static bool trans_lf_madd_s(DisasContext *dc, arg_dab *a)
1208{
1209    check_r0_write(a->d);
1210    gen_helper_float_madd_s(cpu_R[a->d], cpu_env, cpu_R[a->d],
1211                            cpu_R[a->a], cpu_R[a->b]);
1212    gen_helper_update_fpcsr(cpu_env);
1213    return true;
1214}
1215
1216static bool trans_lf_sfeq_s(DisasContext *dc, arg_ab *a)
1217{
1218    do_fpcmp(dc, a, gen_helper_float_eq_s, false, false);
1219    return true;
1220}
1221
1222static bool trans_lf_sfne_s(DisasContext *dc, arg_ab *a)
1223{
1224    do_fpcmp(dc, a, gen_helper_float_eq_s, true, false);
1225    return true;
1226}
1227
1228static bool trans_lf_sfgt_s(DisasContext *dc, arg_ab *a)
1229{
1230    do_fpcmp(dc, a, gen_helper_float_lt_s, false, true);
1231    return true;
1232}
1233
1234static bool trans_lf_sfge_s(DisasContext *dc, arg_ab *a)
1235{
1236    do_fpcmp(dc, a, gen_helper_float_le_s, false, true);
1237    return true;
1238}
1239
1240static bool trans_lf_sflt_s(DisasContext *dc, arg_ab *a)
1241{
1242    do_fpcmp(dc, a, gen_helper_float_lt_s, false, false);
1243    return true;
1244}
1245
1246static bool trans_lf_sfle_s(DisasContext *dc, arg_ab *a)
1247{
1248    do_fpcmp(dc, a, gen_helper_float_le_s, false, false);
1249    return true;
1250}
1251
1252static void openrisc_tr_init_disas_context(DisasContextBase *dcb, CPUState *cs)
1253{
1254    DisasContext *dc = container_of(dcb, DisasContext, base);
1255    CPUOpenRISCState *env = cs->env_ptr;
1256    int bound;
1257
1258    dc->mem_idx = cpu_mmu_index(env, false);
1259    dc->tb_flags = dc->base.tb->flags;
1260    dc->delayed_branch = (dc->tb_flags & TB_FLAGS_DFLAG) != 0;
1261    dc->jmp_pc_imm = -1;
1262
1263    bound = -(dc->base.pc_first | TARGET_PAGE_MASK) / 4;
1264    dc->base.max_insns = MIN(dc->base.max_insns, bound);
1265}
1266
1267static void openrisc_tr_tb_start(DisasContextBase *db, CPUState *cs)
1268{
1269    DisasContext *dc = container_of(db, DisasContext, base);
1270
1271    /* Allow the TCG optimizer to see that R0 == 0,
1272       when it's true, which is the common case.  */
1273    if (dc->tb_flags & TB_FLAGS_R0_0) {
1274        cpu_R[0] = tcg_const_tl(0);
1275    } else {
1276        cpu_R[0] = cpu_R0;
1277    }
1278}
1279
1280static void openrisc_tr_insn_start(DisasContextBase *dcbase, CPUState *cs)
1281{
1282    DisasContext *dc = container_of(dcbase, DisasContext, base);
1283
1284    tcg_gen_insn_start(dc->base.pc_next, (dc->delayed_branch ? 1 : 0)
1285                       | (dc->base.num_insns > 1 ? 2 : 0));
1286}
1287
1288static bool openrisc_tr_breakpoint_check(DisasContextBase *dcbase, CPUState *cs,
1289                                         const CPUBreakpoint *bp)
1290{
1291    DisasContext *dc = container_of(dcbase, DisasContext, base);
1292
1293    tcg_gen_movi_tl(cpu_pc, dc->base.pc_next);
1294    gen_exception(dc, EXCP_DEBUG);
1295    dc->base.is_jmp = DISAS_NORETURN;
1296    /* The address covered by the breakpoint must be included in
1297       [tb->pc, tb->pc + tb->size) in order to for it to be
1298       properly cleared -- thus we increment the PC here so that
1299       the logic setting tb->size below does the right thing.  */
1300    dc->base.pc_next += 4;
1301    return true;
1302}
1303
1304static void openrisc_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs)
1305{
1306    DisasContext *dc = container_of(dcbase, DisasContext, base);
1307    OpenRISCCPU *cpu = OPENRISC_CPU(cs);
1308    uint32_t insn = cpu_ldl_code(&cpu->env, dc->base.pc_next);
1309
1310    if (!decode(dc, insn)) {
1311        gen_illegal_exception(dc);
1312    }
1313    dc->base.pc_next += 4;
1314
1315    /* When exiting the delay slot normally, exit via jmp_pc.
1316     * For DISAS_NORETURN, we have raised an exception and already exited.
1317     * For DISAS_EXIT, we found l.rfe in a delay slot.  There's nothing
1318     * in the manual saying this is illegal, but it surely it should.
1319     * At least or1ksim overrides pcnext and ignores the branch.
1320     */
1321    if (dc->delayed_branch
1322        && --dc->delayed_branch == 0
1323        && dc->base.is_jmp == DISAS_NEXT) {
1324        dc->base.is_jmp = DISAS_JUMP;
1325    }
1326}
1327
1328static void openrisc_tr_tb_stop(DisasContextBase *dcbase, CPUState *cs)
1329{
1330    DisasContext *dc = container_of(dcbase, DisasContext, base);
1331    target_ulong jmp_dest;
1332
1333    /* If we have already exited the TB, nothing following has effect.  */
1334    if (dc->base.is_jmp == DISAS_NORETURN) {
1335        return;
1336    }
1337
1338    /* Adjust the delayed branch state for the next TB.  */
1339    if ((dc->tb_flags & TB_FLAGS_DFLAG ? 1 : 0) != (dc->delayed_branch != 0)) {
1340        tcg_gen_movi_i32(cpu_dflag, dc->delayed_branch != 0);
1341    }
1342
1343    /* For DISAS_TOO_MANY, jump to the next insn.  */
1344    jmp_dest = dc->base.pc_next;
1345    tcg_gen_movi_tl(cpu_ppc, jmp_dest - 4);
1346
1347    switch (dc->base.is_jmp) {
1348    case DISAS_JUMP:
1349        jmp_dest = dc->jmp_pc_imm;
1350        if (jmp_dest == -1) {
1351            /* The jump destination is indirect/computed; use jmp_pc.  */
1352            tcg_gen_mov_tl(cpu_pc, jmp_pc);
1353            tcg_gen_discard_tl(jmp_pc);
1354            if (unlikely(dc->base.singlestep_enabled)) {
1355                gen_exception(dc, EXCP_DEBUG);
1356            } else {
1357                tcg_gen_lookup_and_goto_ptr();
1358            }
1359            break;
1360        }
1361        /* The jump destination is direct; use jmp_pc_imm.
1362           However, we will have stored into jmp_pc as well;
1363           we know now that it wasn't needed.  */
1364        tcg_gen_discard_tl(jmp_pc);
1365        /* fallthru */
1366
1367    case DISAS_TOO_MANY:
1368        if (unlikely(dc->base.singlestep_enabled)) {
1369            tcg_gen_movi_tl(cpu_pc, jmp_dest);
1370            gen_exception(dc, EXCP_DEBUG);
1371        } else if ((dc->base.pc_first ^ jmp_dest) & TARGET_PAGE_MASK) {
1372            tcg_gen_movi_tl(cpu_pc, jmp_dest);
1373            tcg_gen_lookup_and_goto_ptr();
1374        } else {
1375            tcg_gen_goto_tb(0);
1376            tcg_gen_movi_tl(cpu_pc, jmp_dest);
1377            tcg_gen_exit_tb(dc->base.tb, 0);
1378        }
1379        break;
1380
1381    case DISAS_EXIT:
1382        if (unlikely(dc->base.singlestep_enabled)) {
1383            gen_exception(dc, EXCP_DEBUG);
1384        } else {
1385            tcg_gen_exit_tb(NULL, 0);
1386        }
1387        break;
1388    default:
1389        g_assert_not_reached();
1390    }
1391}
1392
1393static void openrisc_tr_disas_log(const DisasContextBase *dcbase, CPUState *cs)
1394{
1395    DisasContext *s = container_of(dcbase, DisasContext, base);
1396
1397    qemu_log("IN: %s\n", lookup_symbol(s->base.pc_first));
1398    log_target_disas(cs, s->base.pc_first, s->base.tb->size);
1399}
1400
1401static const TranslatorOps openrisc_tr_ops = {
1402    .init_disas_context = openrisc_tr_init_disas_context,
1403    .tb_start           = openrisc_tr_tb_start,
1404    .insn_start         = openrisc_tr_insn_start,
1405    .breakpoint_check   = openrisc_tr_breakpoint_check,
1406    .translate_insn     = openrisc_tr_translate_insn,
1407    .tb_stop            = openrisc_tr_tb_stop,
1408    .disas_log          = openrisc_tr_disas_log,
1409};
1410
1411void gen_intermediate_code(CPUState *cs, TranslationBlock *tb, int max_insns)
1412{
1413    DisasContext ctx;
1414
1415    translator_loop(&openrisc_tr_ops, &ctx.base, cs, tb, max_insns);
1416}
1417
1418void openrisc_cpu_dump_state(CPUState *cs, FILE *f, int flags)
1419{
1420    OpenRISCCPU *cpu = OPENRISC_CPU(cs);
1421    CPUOpenRISCState *env = &cpu->env;
1422    int i;
1423
1424    qemu_fprintf(f, "PC=%08x\n", env->pc);
1425    for (i = 0; i < 32; ++i) {
1426        qemu_fprintf(f, "R%02d=%08x%c", i, cpu_get_gpr(env, i),
1427                     (i % 4) == 3 ? '\n' : ' ');
1428    }
1429}
1430
1431void restore_state_to_opc(CPUOpenRISCState *env, TranslationBlock *tb,
1432                          target_ulong *data)
1433{
1434    env->pc = data[0];
1435    env->dflag = data[1] & 1;
1436    if (data[1] & 2) {
1437        env->ppc = env->pc - 4;
1438    }
1439}
1440