1fcf5ef2aSThomas Huth /* 2fcf5ef2aSThomas Huth * OpenRISC translation 3fcf5ef2aSThomas Huth * 4fcf5ef2aSThomas Huth * Copyright (c) 2011-2012 Jia Liu <proljc@gmail.com> 5fcf5ef2aSThomas Huth * Feng Gao <gf91597@gmail.com> 6fcf5ef2aSThomas Huth * 7fcf5ef2aSThomas Huth * This library is free software; you can redistribute it and/or 8fcf5ef2aSThomas Huth * modify it under the terms of the GNU Lesser General Public 9fcf5ef2aSThomas Huth * License as published by the Free Software Foundation; either 10fcf5ef2aSThomas Huth * version 2 of the License, or (at your option) any later version. 11fcf5ef2aSThomas Huth * 12fcf5ef2aSThomas Huth * This library is distributed in the hope that it will be useful, 13fcf5ef2aSThomas Huth * but WITHOUT ANY WARRANTY; without even the implied warranty of 14fcf5ef2aSThomas Huth * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15fcf5ef2aSThomas Huth * Lesser General Public License for more details. 16fcf5ef2aSThomas Huth * 17fcf5ef2aSThomas Huth * You should have received a copy of the GNU Lesser General Public 18fcf5ef2aSThomas Huth * License along with this library; if not, see <http://www.gnu.org/licenses/>. 19fcf5ef2aSThomas Huth */ 20fcf5ef2aSThomas Huth 21fcf5ef2aSThomas Huth #include "qemu/osdep.h" 22fcf5ef2aSThomas Huth #include "cpu.h" 23fcf5ef2aSThomas Huth #include "exec/exec-all.h" 24fcf5ef2aSThomas Huth #include "disas/disas.h" 25fcf5ef2aSThomas Huth #include "tcg-op.h" 26fcf5ef2aSThomas Huth #include "qemu-common.h" 27fcf5ef2aSThomas Huth #include "qemu/log.h" 28fcf5ef2aSThomas Huth #include "qemu/bitops.h" 29fcf5ef2aSThomas Huth #include "exec/cpu_ldst.h" 3077fc6f5eSLluís Vilanova #include "exec/translator.h" 31fcf5ef2aSThomas Huth 32fcf5ef2aSThomas Huth #include "exec/helper-proto.h" 33fcf5ef2aSThomas Huth #include "exec/helper-gen.h" 347de9729fSRichard Henderson #include "exec/gen-icount.h" 35fcf5ef2aSThomas Huth 36fcf5ef2aSThomas Huth #include "trace-tcg.h" 37fcf5ef2aSThomas Huth #include "exec/log.h" 38fcf5ef2aSThomas Huth 3977fc6f5eSLluís Vilanova /* is_jmp field values */ 4064e46c95SRichard Henderson #define DISAS_EXIT DISAS_TARGET_0 /* force exit to main loop */ 418000ba56SRichard Henderson #define DISAS_JUMP DISAS_TARGET_1 /* exit via jmp_pc/jmp_pc_imm */ 4277fc6f5eSLluís Vilanova 43fcf5ef2aSThomas Huth typedef struct DisasContext { 441ffa4bceSEmilio G. Cota DisasContextBase base; 45fcf5ef2aSThomas Huth uint32_t mem_idx; 46a01deb36SRichard Henderson uint32_t tb_flags; 47fcf5ef2aSThomas Huth uint32_t delayed_branch; 488000ba56SRichard Henderson 498000ba56SRichard Henderson /* If not -1, jmp_pc contains this value and so is a direct jump. */ 508000ba56SRichard Henderson target_ulong jmp_pc_imm; 51fcf5ef2aSThomas Huth } DisasContext; 52fcf5ef2aSThomas Huth 532ba65417SRichard Henderson static inline bool is_user(DisasContext *dc) 542ba65417SRichard Henderson { 552ba65417SRichard Henderson #ifdef CONFIG_USER_ONLY 562ba65417SRichard Henderson return true; 572ba65417SRichard Henderson #else 58*b9bed1b9SRichard Henderson return !(dc->tb_flags & TB_FLAGS_SM); 592ba65417SRichard Henderson #endif 602ba65417SRichard Henderson } 612ba65417SRichard Henderson 627de9729fSRichard Henderson /* Include the auto-generated decoder. */ 637de9729fSRichard Henderson #include "decode.inc.c" 647de9729fSRichard Henderson 65fcf5ef2aSThomas Huth static TCGv cpu_sr; 66fcf5ef2aSThomas Huth static TCGv cpu_R[32]; 676597c28dSRichard Henderson static TCGv cpu_R0; 68fcf5ef2aSThomas Huth static TCGv cpu_pc; 69fcf5ef2aSThomas Huth static TCGv jmp_pc; /* l.jr/l.jalr temp pc */ 70fcf5ef2aSThomas Huth static TCGv cpu_ppc; 7184775c43SRichard Henderson static TCGv cpu_sr_f; /* bf/bnf, F flag taken */ 7297458071SRichard Henderson static TCGv cpu_sr_cy; /* carry (unsigned overflow) */ 7397458071SRichard Henderson static TCGv cpu_sr_ov; /* signed overflow */ 74930c3d00SRichard Henderson static TCGv cpu_lock_addr; 75930c3d00SRichard Henderson static TCGv cpu_lock_value; 76fcf5ef2aSThomas Huth static TCGv_i32 fpcsr; 776f7332baSRichard Henderson static TCGv_i64 cpu_mac; /* MACHI:MACLO */ 78a01deb36SRichard Henderson static TCGv_i32 cpu_dflag; 79fcf5ef2aSThomas Huth 80fcf5ef2aSThomas Huth void openrisc_translate_init(void) 81fcf5ef2aSThomas Huth { 82fcf5ef2aSThomas Huth static const char * const regnames[] = { 83fcf5ef2aSThomas Huth "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", 84fcf5ef2aSThomas Huth "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", 85fcf5ef2aSThomas Huth "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23", 86fcf5ef2aSThomas Huth "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31", 87fcf5ef2aSThomas Huth }; 88fcf5ef2aSThomas Huth int i; 89fcf5ef2aSThomas Huth 90fcf5ef2aSThomas Huth cpu_sr = tcg_global_mem_new(cpu_env, 91fcf5ef2aSThomas Huth offsetof(CPUOpenRISCState, sr), "sr"); 92a01deb36SRichard Henderson cpu_dflag = tcg_global_mem_new_i32(cpu_env, 93a01deb36SRichard Henderson offsetof(CPUOpenRISCState, dflag), 94a01deb36SRichard Henderson "dflag"); 95fcf5ef2aSThomas Huth cpu_pc = tcg_global_mem_new(cpu_env, 96fcf5ef2aSThomas Huth offsetof(CPUOpenRISCState, pc), "pc"); 97fcf5ef2aSThomas Huth cpu_ppc = tcg_global_mem_new(cpu_env, 98fcf5ef2aSThomas Huth offsetof(CPUOpenRISCState, ppc), "ppc"); 99fcf5ef2aSThomas Huth jmp_pc = tcg_global_mem_new(cpu_env, 100fcf5ef2aSThomas Huth offsetof(CPUOpenRISCState, jmp_pc), "jmp_pc"); 10184775c43SRichard Henderson cpu_sr_f = tcg_global_mem_new(cpu_env, 10284775c43SRichard Henderson offsetof(CPUOpenRISCState, sr_f), "sr_f"); 10397458071SRichard Henderson cpu_sr_cy = tcg_global_mem_new(cpu_env, 10497458071SRichard Henderson offsetof(CPUOpenRISCState, sr_cy), "sr_cy"); 10597458071SRichard Henderson cpu_sr_ov = tcg_global_mem_new(cpu_env, 10697458071SRichard Henderson offsetof(CPUOpenRISCState, sr_ov), "sr_ov"); 107930c3d00SRichard Henderson cpu_lock_addr = tcg_global_mem_new(cpu_env, 108930c3d00SRichard Henderson offsetof(CPUOpenRISCState, lock_addr), 109930c3d00SRichard Henderson "lock_addr"); 110930c3d00SRichard Henderson cpu_lock_value = tcg_global_mem_new(cpu_env, 111930c3d00SRichard Henderson offsetof(CPUOpenRISCState, lock_value), 112930c3d00SRichard Henderson "lock_value"); 113fcf5ef2aSThomas Huth fpcsr = tcg_global_mem_new_i32(cpu_env, 114fcf5ef2aSThomas Huth offsetof(CPUOpenRISCState, fpcsr), 115fcf5ef2aSThomas Huth "fpcsr"); 1166f7332baSRichard Henderson cpu_mac = tcg_global_mem_new_i64(cpu_env, 1176f7332baSRichard Henderson offsetof(CPUOpenRISCState, mac), 1186f7332baSRichard Henderson "mac"); 119fcf5ef2aSThomas Huth for (i = 0; i < 32; i++) { 120fcf5ef2aSThomas Huth cpu_R[i] = tcg_global_mem_new(cpu_env, 121d89e71e8SStafford Horne offsetof(CPUOpenRISCState, 122d89e71e8SStafford Horne shadow_gpr[0][i]), 123fcf5ef2aSThomas Huth regnames[i]); 124fcf5ef2aSThomas Huth } 1256597c28dSRichard Henderson cpu_R0 = cpu_R[0]; 126fcf5ef2aSThomas Huth } 127fcf5ef2aSThomas Huth 128fcf5ef2aSThomas Huth static void gen_exception(DisasContext *dc, unsigned int excp) 129fcf5ef2aSThomas Huth { 130fcf5ef2aSThomas Huth TCGv_i32 tmp = tcg_const_i32(excp); 131fcf5ef2aSThomas Huth gen_helper_exception(cpu_env, tmp); 132fcf5ef2aSThomas Huth tcg_temp_free_i32(tmp); 133fcf5ef2aSThomas Huth } 134fcf5ef2aSThomas Huth 135fcf5ef2aSThomas Huth static void gen_illegal_exception(DisasContext *dc) 136fcf5ef2aSThomas Huth { 1371ffa4bceSEmilio G. Cota tcg_gen_movi_tl(cpu_pc, dc->base.pc_next); 138fcf5ef2aSThomas Huth gen_exception(dc, EXCP_ILLEGAL); 1391ffa4bceSEmilio G. Cota dc->base.is_jmp = DISAS_NORETURN; 140fcf5ef2aSThomas Huth } 141fcf5ef2aSThomas Huth 142fcf5ef2aSThomas Huth /* not used yet, open it when we need or64. */ 143fcf5ef2aSThomas Huth /*#ifdef TARGET_OPENRISC64 144fcf5ef2aSThomas Huth static void check_ob64s(DisasContext *dc) 145fcf5ef2aSThomas Huth { 146fcf5ef2aSThomas Huth if (!(dc->flags & CPUCFGR_OB64S)) { 147fcf5ef2aSThomas Huth gen_illegal_exception(dc); 148fcf5ef2aSThomas Huth } 149fcf5ef2aSThomas Huth } 150fcf5ef2aSThomas Huth 151fcf5ef2aSThomas Huth static void check_of64s(DisasContext *dc) 152fcf5ef2aSThomas Huth { 153fcf5ef2aSThomas Huth if (!(dc->flags & CPUCFGR_OF64S)) { 154fcf5ef2aSThomas Huth gen_illegal_exception(dc); 155fcf5ef2aSThomas Huth } 156fcf5ef2aSThomas Huth } 157fcf5ef2aSThomas Huth 158fcf5ef2aSThomas Huth static void check_ov64s(DisasContext *dc) 159fcf5ef2aSThomas Huth { 160fcf5ef2aSThomas Huth if (!(dc->flags & CPUCFGR_OV64S)) { 161fcf5ef2aSThomas Huth gen_illegal_exception(dc); 162fcf5ef2aSThomas Huth } 163fcf5ef2aSThomas Huth } 164fcf5ef2aSThomas Huth #endif*/ 165fcf5ef2aSThomas Huth 1666597c28dSRichard Henderson /* We're about to write to REG. On the off-chance that the user is 1676597c28dSRichard Henderson writing to R0, re-instate the architectural register. */ 1686597c28dSRichard Henderson #define check_r0_write(reg) \ 1696597c28dSRichard Henderson do { \ 1706597c28dSRichard Henderson if (unlikely(reg == 0)) { \ 1716597c28dSRichard Henderson cpu_R[0] = cpu_R0; \ 1726597c28dSRichard Henderson } \ 1736597c28dSRichard Henderson } while (0) 1746597c28dSRichard Henderson 17597458071SRichard Henderson static void gen_ove_cy(DisasContext *dc) 1769ecaa27eSRichard Henderson { 1770c53d734SRichard Henderson if (dc->tb_flags & SR_OVE) { 17897458071SRichard Henderson gen_helper_ove_cy(cpu_env); 1799ecaa27eSRichard Henderson } 1800c53d734SRichard Henderson } 1819ecaa27eSRichard Henderson 18297458071SRichard Henderson static void gen_ove_ov(DisasContext *dc) 1839ecaa27eSRichard Henderson { 1840c53d734SRichard Henderson if (dc->tb_flags & SR_OVE) { 18597458071SRichard Henderson gen_helper_ove_ov(cpu_env); 1869ecaa27eSRichard Henderson } 1870c53d734SRichard Henderson } 1889ecaa27eSRichard Henderson 18997458071SRichard Henderson static void gen_ove_cyov(DisasContext *dc) 1909ecaa27eSRichard Henderson { 1910c53d734SRichard Henderson if (dc->tb_flags & SR_OVE) { 19297458071SRichard Henderson gen_helper_ove_cyov(cpu_env); 1939ecaa27eSRichard Henderson } 1940c53d734SRichard Henderson } 1959ecaa27eSRichard Henderson 1969ecaa27eSRichard Henderson static void gen_add(DisasContext *dc, TCGv dest, TCGv srca, TCGv srcb) 1979ecaa27eSRichard Henderson { 1989ecaa27eSRichard Henderson TCGv t0 = tcg_const_tl(0); 1999ecaa27eSRichard Henderson TCGv res = tcg_temp_new(); 2009ecaa27eSRichard Henderson 20197458071SRichard Henderson tcg_gen_add2_tl(res, cpu_sr_cy, srca, t0, srcb, t0); 20297458071SRichard Henderson tcg_gen_xor_tl(cpu_sr_ov, srca, srcb); 2039ecaa27eSRichard Henderson tcg_gen_xor_tl(t0, res, srcb); 20497458071SRichard Henderson tcg_gen_andc_tl(cpu_sr_ov, t0, cpu_sr_ov); 2059ecaa27eSRichard Henderson tcg_temp_free(t0); 2069ecaa27eSRichard Henderson 2079ecaa27eSRichard Henderson tcg_gen_mov_tl(dest, res); 2089ecaa27eSRichard Henderson tcg_temp_free(res); 2099ecaa27eSRichard Henderson 21097458071SRichard Henderson gen_ove_cyov(dc); 2119ecaa27eSRichard Henderson } 2129ecaa27eSRichard Henderson 2139ecaa27eSRichard Henderson static void gen_addc(DisasContext *dc, TCGv dest, TCGv srca, TCGv srcb) 2149ecaa27eSRichard Henderson { 2159ecaa27eSRichard Henderson TCGv t0 = tcg_const_tl(0); 2169ecaa27eSRichard Henderson TCGv res = tcg_temp_new(); 2179ecaa27eSRichard Henderson 21897458071SRichard Henderson tcg_gen_add2_tl(res, cpu_sr_cy, srca, t0, cpu_sr_cy, t0); 21997458071SRichard Henderson tcg_gen_add2_tl(res, cpu_sr_cy, res, cpu_sr_cy, srcb, t0); 22097458071SRichard Henderson tcg_gen_xor_tl(cpu_sr_ov, srca, srcb); 2219ecaa27eSRichard Henderson tcg_gen_xor_tl(t0, res, srcb); 22297458071SRichard Henderson tcg_gen_andc_tl(cpu_sr_ov, t0, cpu_sr_ov); 2239ecaa27eSRichard Henderson tcg_temp_free(t0); 2249ecaa27eSRichard Henderson 2259ecaa27eSRichard Henderson tcg_gen_mov_tl(dest, res); 2269ecaa27eSRichard Henderson tcg_temp_free(res); 2279ecaa27eSRichard Henderson 22897458071SRichard Henderson gen_ove_cyov(dc); 2299ecaa27eSRichard Henderson } 2309ecaa27eSRichard Henderson 2319ecaa27eSRichard Henderson static void gen_sub(DisasContext *dc, TCGv dest, TCGv srca, TCGv srcb) 2329ecaa27eSRichard Henderson { 2339ecaa27eSRichard Henderson TCGv res = tcg_temp_new(); 2349ecaa27eSRichard Henderson 2359ecaa27eSRichard Henderson tcg_gen_sub_tl(res, srca, srcb); 23697458071SRichard Henderson tcg_gen_xor_tl(cpu_sr_cy, srca, srcb); 23797458071SRichard Henderson tcg_gen_xor_tl(cpu_sr_ov, res, srcb); 23897458071SRichard Henderson tcg_gen_and_tl(cpu_sr_ov, cpu_sr_ov, cpu_sr_cy); 23997458071SRichard Henderson tcg_gen_setcond_tl(TCG_COND_LTU, cpu_sr_cy, srca, srcb); 2409ecaa27eSRichard Henderson 2419ecaa27eSRichard Henderson tcg_gen_mov_tl(dest, res); 2429ecaa27eSRichard Henderson tcg_temp_free(res); 2439ecaa27eSRichard Henderson 24497458071SRichard Henderson gen_ove_cyov(dc); 2459ecaa27eSRichard Henderson } 2469ecaa27eSRichard Henderson 2479ecaa27eSRichard Henderson static void gen_mul(DisasContext *dc, TCGv dest, TCGv srca, TCGv srcb) 2489ecaa27eSRichard Henderson { 2499ecaa27eSRichard Henderson TCGv t0 = tcg_temp_new(); 2509ecaa27eSRichard Henderson 25197458071SRichard Henderson tcg_gen_muls2_tl(dest, cpu_sr_ov, srca, srcb); 2529ecaa27eSRichard Henderson tcg_gen_sari_tl(t0, dest, TARGET_LONG_BITS - 1); 25397458071SRichard Henderson tcg_gen_setcond_tl(TCG_COND_NE, cpu_sr_ov, cpu_sr_ov, t0); 2549ecaa27eSRichard Henderson tcg_temp_free(t0); 2559ecaa27eSRichard Henderson 25697458071SRichard Henderson tcg_gen_neg_tl(cpu_sr_ov, cpu_sr_ov); 25797458071SRichard Henderson gen_ove_ov(dc); 2589ecaa27eSRichard Henderson } 2599ecaa27eSRichard Henderson 2609ecaa27eSRichard Henderson static void gen_mulu(DisasContext *dc, TCGv dest, TCGv srca, TCGv srcb) 2619ecaa27eSRichard Henderson { 26297458071SRichard Henderson tcg_gen_muls2_tl(dest, cpu_sr_cy, srca, srcb); 26397458071SRichard Henderson tcg_gen_setcondi_tl(TCG_COND_NE, cpu_sr_cy, cpu_sr_cy, 0); 2649ecaa27eSRichard Henderson 26597458071SRichard Henderson gen_ove_cy(dc); 2669ecaa27eSRichard Henderson } 2679ecaa27eSRichard Henderson 2689ecaa27eSRichard Henderson static void gen_div(DisasContext *dc, TCGv dest, TCGv srca, TCGv srcb) 2699ecaa27eSRichard Henderson { 2709ecaa27eSRichard Henderson TCGv t0 = tcg_temp_new(); 2719ecaa27eSRichard Henderson 27297458071SRichard Henderson tcg_gen_setcondi_tl(TCG_COND_EQ, cpu_sr_ov, srcb, 0); 2739ecaa27eSRichard Henderson /* The result of divide-by-zero is undefined. 2749ecaa27eSRichard Henderson Supress the host-side exception by dividing by 1. */ 27597458071SRichard Henderson tcg_gen_or_tl(t0, srcb, cpu_sr_ov); 2769ecaa27eSRichard Henderson tcg_gen_div_tl(dest, srca, t0); 2779ecaa27eSRichard Henderson tcg_temp_free(t0); 2789ecaa27eSRichard Henderson 27997458071SRichard Henderson tcg_gen_neg_tl(cpu_sr_ov, cpu_sr_ov); 28097458071SRichard Henderson gen_ove_ov(dc); 2819ecaa27eSRichard Henderson } 2829ecaa27eSRichard Henderson 2839ecaa27eSRichard Henderson static void gen_divu(DisasContext *dc, TCGv dest, TCGv srca, TCGv srcb) 2849ecaa27eSRichard Henderson { 2859ecaa27eSRichard Henderson TCGv t0 = tcg_temp_new(); 2869ecaa27eSRichard Henderson 28797458071SRichard Henderson tcg_gen_setcondi_tl(TCG_COND_EQ, cpu_sr_cy, srcb, 0); 2889ecaa27eSRichard Henderson /* The result of divide-by-zero is undefined. 2899ecaa27eSRichard Henderson Supress the host-side exception by dividing by 1. */ 29097458071SRichard Henderson tcg_gen_or_tl(t0, srcb, cpu_sr_cy); 2919ecaa27eSRichard Henderson tcg_gen_divu_tl(dest, srca, t0); 2929ecaa27eSRichard Henderson tcg_temp_free(t0); 2939ecaa27eSRichard Henderson 29497458071SRichard Henderson gen_ove_cy(dc); 2959ecaa27eSRichard Henderson } 296fcf5ef2aSThomas Huth 297cc5de49eSRichard Henderson static void gen_muld(DisasContext *dc, TCGv srca, TCGv srcb) 298cc5de49eSRichard Henderson { 299cc5de49eSRichard Henderson TCGv_i64 t1 = tcg_temp_new_i64(); 300cc5de49eSRichard Henderson TCGv_i64 t2 = tcg_temp_new_i64(); 301cc5de49eSRichard Henderson 302cc5de49eSRichard Henderson tcg_gen_ext_tl_i64(t1, srca); 303cc5de49eSRichard Henderson tcg_gen_ext_tl_i64(t2, srcb); 304cc5de49eSRichard Henderson if (TARGET_LONG_BITS == 32) { 305cc5de49eSRichard Henderson tcg_gen_mul_i64(cpu_mac, t1, t2); 306cc5de49eSRichard Henderson tcg_gen_movi_tl(cpu_sr_ov, 0); 307cc5de49eSRichard Henderson } else { 308cc5de49eSRichard Henderson TCGv_i64 high = tcg_temp_new_i64(); 309cc5de49eSRichard Henderson 310cc5de49eSRichard Henderson tcg_gen_muls2_i64(cpu_mac, high, t1, t2); 311cc5de49eSRichard Henderson tcg_gen_sari_i64(t1, cpu_mac, 63); 312cc5de49eSRichard Henderson tcg_gen_setcond_i64(TCG_COND_NE, t1, t1, high); 313cc5de49eSRichard Henderson tcg_temp_free_i64(high); 314cc5de49eSRichard Henderson tcg_gen_trunc_i64_tl(cpu_sr_ov, t1); 315cc5de49eSRichard Henderson tcg_gen_neg_tl(cpu_sr_ov, cpu_sr_ov); 316cc5de49eSRichard Henderson 317cc5de49eSRichard Henderson gen_ove_ov(dc); 318cc5de49eSRichard Henderson } 319cc5de49eSRichard Henderson tcg_temp_free_i64(t1); 320cc5de49eSRichard Henderson tcg_temp_free_i64(t2); 321cc5de49eSRichard Henderson } 322cc5de49eSRichard Henderson 323cc5de49eSRichard Henderson static void gen_muldu(DisasContext *dc, TCGv srca, TCGv srcb) 324cc5de49eSRichard Henderson { 325cc5de49eSRichard Henderson TCGv_i64 t1 = tcg_temp_new_i64(); 326cc5de49eSRichard Henderson TCGv_i64 t2 = tcg_temp_new_i64(); 327cc5de49eSRichard Henderson 328cc5de49eSRichard Henderson tcg_gen_extu_tl_i64(t1, srca); 329cc5de49eSRichard Henderson tcg_gen_extu_tl_i64(t2, srcb); 330cc5de49eSRichard Henderson if (TARGET_LONG_BITS == 32) { 331cc5de49eSRichard Henderson tcg_gen_mul_i64(cpu_mac, t1, t2); 332cc5de49eSRichard Henderson tcg_gen_movi_tl(cpu_sr_cy, 0); 333cc5de49eSRichard Henderson } else { 334cc5de49eSRichard Henderson TCGv_i64 high = tcg_temp_new_i64(); 335cc5de49eSRichard Henderson 336cc5de49eSRichard Henderson tcg_gen_mulu2_i64(cpu_mac, high, t1, t2); 337cc5de49eSRichard Henderson tcg_gen_setcondi_i64(TCG_COND_NE, high, high, 0); 338cc5de49eSRichard Henderson tcg_gen_trunc_i64_tl(cpu_sr_cy, high); 339cc5de49eSRichard Henderson tcg_temp_free_i64(high); 340cc5de49eSRichard Henderson 341cc5de49eSRichard Henderson gen_ove_cy(dc); 342cc5de49eSRichard Henderson } 343cc5de49eSRichard Henderson tcg_temp_free_i64(t1); 344cc5de49eSRichard Henderson tcg_temp_free_i64(t2); 345cc5de49eSRichard Henderson } 346cc5de49eSRichard Henderson 3476f7332baSRichard Henderson static void gen_mac(DisasContext *dc, TCGv srca, TCGv srcb) 3486f7332baSRichard Henderson { 3496f7332baSRichard Henderson TCGv_i64 t1 = tcg_temp_new_i64(); 3506f7332baSRichard Henderson TCGv_i64 t2 = tcg_temp_new_i64(); 3516f7332baSRichard Henderson 3526f7332baSRichard Henderson tcg_gen_ext_tl_i64(t1, srca); 3536f7332baSRichard Henderson tcg_gen_ext_tl_i64(t2, srcb); 3546f7332baSRichard Henderson tcg_gen_mul_i64(t1, t1, t2); 3556f7332baSRichard Henderson 3566f7332baSRichard Henderson /* Note that overflow is only computed during addition stage. */ 3576f7332baSRichard Henderson tcg_gen_xor_i64(t2, cpu_mac, t1); 3586f7332baSRichard Henderson tcg_gen_add_i64(cpu_mac, cpu_mac, t1); 3596f7332baSRichard Henderson tcg_gen_xor_i64(t1, t1, cpu_mac); 3606f7332baSRichard Henderson tcg_gen_andc_i64(t1, t1, t2); 3616f7332baSRichard Henderson tcg_temp_free_i64(t2); 3626f7332baSRichard Henderson 3636f7332baSRichard Henderson #if TARGET_LONG_BITS == 32 3646f7332baSRichard Henderson tcg_gen_extrh_i64_i32(cpu_sr_ov, t1); 3656f7332baSRichard Henderson #else 3666f7332baSRichard Henderson tcg_gen_mov_i64(cpu_sr_ov, t1); 3676f7332baSRichard Henderson #endif 3686f7332baSRichard Henderson tcg_temp_free_i64(t1); 3696f7332baSRichard Henderson 3706f7332baSRichard Henderson gen_ove_ov(dc); 3716f7332baSRichard Henderson } 3726f7332baSRichard Henderson 373cc5de49eSRichard Henderson static void gen_macu(DisasContext *dc, TCGv srca, TCGv srcb) 374cc5de49eSRichard Henderson { 375cc5de49eSRichard Henderson TCGv_i64 t1 = tcg_temp_new_i64(); 376cc5de49eSRichard Henderson TCGv_i64 t2 = tcg_temp_new_i64(); 377cc5de49eSRichard Henderson 378cc5de49eSRichard Henderson tcg_gen_extu_tl_i64(t1, srca); 379cc5de49eSRichard Henderson tcg_gen_extu_tl_i64(t2, srcb); 380cc5de49eSRichard Henderson tcg_gen_mul_i64(t1, t1, t2); 381cc5de49eSRichard Henderson tcg_temp_free_i64(t2); 382cc5de49eSRichard Henderson 383cc5de49eSRichard Henderson /* Note that overflow is only computed during addition stage. */ 384cc5de49eSRichard Henderson tcg_gen_add_i64(cpu_mac, cpu_mac, t1); 385cc5de49eSRichard Henderson tcg_gen_setcond_i64(TCG_COND_LTU, t1, cpu_mac, t1); 386cc5de49eSRichard Henderson tcg_gen_trunc_i64_tl(cpu_sr_cy, t1); 387cc5de49eSRichard Henderson tcg_temp_free_i64(t1); 388cc5de49eSRichard Henderson 389cc5de49eSRichard Henderson gen_ove_cy(dc); 390cc5de49eSRichard Henderson } 391cc5de49eSRichard Henderson 3926f7332baSRichard Henderson static void gen_msb(DisasContext *dc, TCGv srca, TCGv srcb) 3936f7332baSRichard Henderson { 3946f7332baSRichard Henderson TCGv_i64 t1 = tcg_temp_new_i64(); 3956f7332baSRichard Henderson TCGv_i64 t2 = tcg_temp_new_i64(); 3966f7332baSRichard Henderson 3976f7332baSRichard Henderson tcg_gen_ext_tl_i64(t1, srca); 3986f7332baSRichard Henderson tcg_gen_ext_tl_i64(t2, srcb); 3996f7332baSRichard Henderson tcg_gen_mul_i64(t1, t1, t2); 4006f7332baSRichard Henderson 4016f7332baSRichard Henderson /* Note that overflow is only computed during subtraction stage. */ 4026f7332baSRichard Henderson tcg_gen_xor_i64(t2, cpu_mac, t1); 4036f7332baSRichard Henderson tcg_gen_sub_i64(cpu_mac, cpu_mac, t1); 4046f7332baSRichard Henderson tcg_gen_xor_i64(t1, t1, cpu_mac); 4056f7332baSRichard Henderson tcg_gen_and_i64(t1, t1, t2); 4066f7332baSRichard Henderson tcg_temp_free_i64(t2); 4076f7332baSRichard Henderson 4086f7332baSRichard Henderson #if TARGET_LONG_BITS == 32 4096f7332baSRichard Henderson tcg_gen_extrh_i64_i32(cpu_sr_ov, t1); 4106f7332baSRichard Henderson #else 4116f7332baSRichard Henderson tcg_gen_mov_i64(cpu_sr_ov, t1); 4126f7332baSRichard Henderson #endif 4136f7332baSRichard Henderson tcg_temp_free_i64(t1); 4146f7332baSRichard Henderson 4156f7332baSRichard Henderson gen_ove_ov(dc); 4166f7332baSRichard Henderson } 4176f7332baSRichard Henderson 418cc5de49eSRichard Henderson static void gen_msbu(DisasContext *dc, TCGv srca, TCGv srcb) 419cc5de49eSRichard Henderson { 420cc5de49eSRichard Henderson TCGv_i64 t1 = tcg_temp_new_i64(); 421cc5de49eSRichard Henderson TCGv_i64 t2 = tcg_temp_new_i64(); 422cc5de49eSRichard Henderson 423cc5de49eSRichard Henderson tcg_gen_extu_tl_i64(t1, srca); 424cc5de49eSRichard Henderson tcg_gen_extu_tl_i64(t2, srcb); 425cc5de49eSRichard Henderson tcg_gen_mul_i64(t1, t1, t2); 426cc5de49eSRichard Henderson 427cc5de49eSRichard Henderson /* Note that overflow is only computed during subtraction stage. */ 428cc5de49eSRichard Henderson tcg_gen_setcond_i64(TCG_COND_LTU, t2, cpu_mac, t1); 429cc5de49eSRichard Henderson tcg_gen_sub_i64(cpu_mac, cpu_mac, t1); 430cc5de49eSRichard Henderson tcg_gen_trunc_i64_tl(cpu_sr_cy, t2); 431cc5de49eSRichard Henderson tcg_temp_free_i64(t2); 432cc5de49eSRichard Henderson tcg_temp_free_i64(t1); 433cc5de49eSRichard Henderson 434cc5de49eSRichard Henderson gen_ove_cy(dc); 435cc5de49eSRichard Henderson } 436cc5de49eSRichard Henderson 4376ad216abSRichard Henderson static bool trans_l_add(DisasContext *dc, arg_dab *a, uint32_t insn) 438fcf5ef2aSThomas Huth { 4396ad216abSRichard Henderson check_r0_write(a->d); 4406ad216abSRichard Henderson gen_add(dc, cpu_R[a->d], cpu_R[a->a], cpu_R[a->b]); 4416ad216abSRichard Henderson return true; 442fcf5ef2aSThomas Huth } 443fcf5ef2aSThomas Huth 4446ad216abSRichard Henderson static bool trans_l_addc(DisasContext *dc, arg_dab *a, uint32_t insn) 445fcf5ef2aSThomas Huth { 4466ad216abSRichard Henderson check_r0_write(a->d); 4476ad216abSRichard Henderson gen_addc(dc, cpu_R[a->d], cpu_R[a->a], cpu_R[a->b]); 4486ad216abSRichard Henderson return true; 4496ad216abSRichard Henderson } 4506ad216abSRichard Henderson 4516ad216abSRichard Henderson static bool trans_l_sub(DisasContext *dc, arg_dab *a, uint32_t insn) 4526ad216abSRichard Henderson { 4536ad216abSRichard Henderson check_r0_write(a->d); 4546ad216abSRichard Henderson gen_sub(dc, cpu_R[a->d], cpu_R[a->a], cpu_R[a->b]); 4556ad216abSRichard Henderson return true; 4566ad216abSRichard Henderson } 4576ad216abSRichard Henderson 4586ad216abSRichard Henderson static bool trans_l_and(DisasContext *dc, arg_dab *a, uint32_t insn) 4596ad216abSRichard Henderson { 4606ad216abSRichard Henderson check_r0_write(a->d); 4616ad216abSRichard Henderson tcg_gen_and_tl(cpu_R[a->d], cpu_R[a->a], cpu_R[a->b]); 4626ad216abSRichard Henderson return true; 4636ad216abSRichard Henderson } 4646ad216abSRichard Henderson 4656ad216abSRichard Henderson static bool trans_l_or(DisasContext *dc, arg_dab *a, uint32_t insn) 4666ad216abSRichard Henderson { 4676ad216abSRichard Henderson check_r0_write(a->d); 4686ad216abSRichard Henderson tcg_gen_or_tl(cpu_R[a->d], cpu_R[a->a], cpu_R[a->b]); 4696ad216abSRichard Henderson return true; 4706ad216abSRichard Henderson } 4716ad216abSRichard Henderson 4726ad216abSRichard Henderson static bool trans_l_xor(DisasContext *dc, arg_dab *a, uint32_t insn) 4736ad216abSRichard Henderson { 4746ad216abSRichard Henderson check_r0_write(a->d); 4756ad216abSRichard Henderson tcg_gen_xor_tl(cpu_R[a->d], cpu_R[a->a], cpu_R[a->b]); 4766ad216abSRichard Henderson return true; 4776ad216abSRichard Henderson } 4786ad216abSRichard Henderson 4796ad216abSRichard Henderson static bool trans_l_sll(DisasContext *dc, arg_dab *a, uint32_t insn) 4806ad216abSRichard Henderson { 4816ad216abSRichard Henderson check_r0_write(a->d); 4826ad216abSRichard Henderson tcg_gen_shl_tl(cpu_R[a->d], cpu_R[a->a], cpu_R[a->b]); 4836ad216abSRichard Henderson return true; 4846ad216abSRichard Henderson } 4856ad216abSRichard Henderson 4866ad216abSRichard Henderson static bool trans_l_srl(DisasContext *dc, arg_dab *a, uint32_t insn) 4876ad216abSRichard Henderson { 4886ad216abSRichard Henderson check_r0_write(a->d); 4896ad216abSRichard Henderson tcg_gen_shr_tl(cpu_R[a->d], cpu_R[a->a], cpu_R[a->b]); 4906ad216abSRichard Henderson return true; 4916ad216abSRichard Henderson } 4926ad216abSRichard Henderson 4936ad216abSRichard Henderson static bool trans_l_sra(DisasContext *dc, arg_dab *a, uint32_t insn) 4946ad216abSRichard Henderson { 4956ad216abSRichard Henderson check_r0_write(a->d); 4966ad216abSRichard Henderson tcg_gen_sar_tl(cpu_R[a->d], cpu_R[a->a], cpu_R[a->b]); 4976ad216abSRichard Henderson return true; 4986ad216abSRichard Henderson } 4996ad216abSRichard Henderson 5006ad216abSRichard Henderson static bool trans_l_ror(DisasContext *dc, arg_dab *a, uint32_t insn) 5016ad216abSRichard Henderson { 5026ad216abSRichard Henderson check_r0_write(a->d); 5036ad216abSRichard Henderson tcg_gen_rotr_tl(cpu_R[a->d], cpu_R[a->a], cpu_R[a->b]); 5046ad216abSRichard Henderson return true; 5056ad216abSRichard Henderson } 5066ad216abSRichard Henderson 5076ad216abSRichard Henderson static bool trans_l_exths(DisasContext *dc, arg_da *a, uint32_t insn) 5086ad216abSRichard Henderson { 5096ad216abSRichard Henderson check_r0_write(a->d); 5106ad216abSRichard Henderson tcg_gen_ext16s_tl(cpu_R[a->d], cpu_R[a->a]); 5116ad216abSRichard Henderson return true; 5126ad216abSRichard Henderson } 5136ad216abSRichard Henderson 5146ad216abSRichard Henderson static bool trans_l_extbs(DisasContext *dc, arg_da *a, uint32_t insn) 5156ad216abSRichard Henderson { 5166ad216abSRichard Henderson check_r0_write(a->d); 5176ad216abSRichard Henderson tcg_gen_ext8s_tl(cpu_R[a->d], cpu_R[a->a]); 5186ad216abSRichard Henderson return true; 5196ad216abSRichard Henderson } 5206ad216abSRichard Henderson 5216ad216abSRichard Henderson static bool trans_l_exthz(DisasContext *dc, arg_da *a, uint32_t insn) 5226ad216abSRichard Henderson { 5236ad216abSRichard Henderson check_r0_write(a->d); 5246ad216abSRichard Henderson tcg_gen_ext16u_tl(cpu_R[a->d], cpu_R[a->a]); 5256ad216abSRichard Henderson return true; 5266ad216abSRichard Henderson } 5276ad216abSRichard Henderson 5286ad216abSRichard Henderson static bool trans_l_extbz(DisasContext *dc, arg_da *a, uint32_t insn) 5296ad216abSRichard Henderson { 5306ad216abSRichard Henderson check_r0_write(a->d); 5316ad216abSRichard Henderson tcg_gen_ext8u_tl(cpu_R[a->d], cpu_R[a->a]); 5326ad216abSRichard Henderson return true; 5336ad216abSRichard Henderson } 5346ad216abSRichard Henderson 5356ad216abSRichard Henderson static bool trans_l_cmov(DisasContext *dc, arg_dab *a, uint32_t insn) 5366ad216abSRichard Henderson { 5376ad216abSRichard Henderson TCGv zero; 5386ad216abSRichard Henderson 5396ad216abSRichard Henderson check_r0_write(a->d); 5406ad216abSRichard Henderson zero = tcg_const_tl(0); 5416ad216abSRichard Henderson tcg_gen_movcond_tl(TCG_COND_NE, cpu_R[a->d], cpu_sr_f, zero, 5426ad216abSRichard Henderson cpu_R[a->a], cpu_R[a->b]); 543784696d1SRichard Henderson tcg_temp_free(zero); 5446ad216abSRichard Henderson return true; 545fcf5ef2aSThomas Huth } 546fcf5ef2aSThomas Huth 5476ad216abSRichard Henderson static bool trans_l_ff1(DisasContext *dc, arg_da *a, uint32_t insn) 5486ad216abSRichard Henderson { 5496ad216abSRichard Henderson check_r0_write(a->d); 5506ad216abSRichard Henderson tcg_gen_ctzi_tl(cpu_R[a->d], cpu_R[a->a], -1); 5516ad216abSRichard Henderson tcg_gen_addi_tl(cpu_R[a->d], cpu_R[a->d], 1); 5526ad216abSRichard Henderson return true; 553cf2ae442SRichard Henderson } 554cf2ae442SRichard Henderson 5556ad216abSRichard Henderson static bool trans_l_fl1(DisasContext *dc, arg_da *a, uint32_t insn) 5566ad216abSRichard Henderson { 5576ad216abSRichard Henderson check_r0_write(a->d); 5586ad216abSRichard Henderson tcg_gen_clzi_tl(cpu_R[a->d], cpu_R[a->a], TARGET_LONG_BITS); 5596ad216abSRichard Henderson tcg_gen_subfi_tl(cpu_R[a->d], TARGET_LONG_BITS, cpu_R[a->d]); 5606ad216abSRichard Henderson return true; 561fcf5ef2aSThomas Huth } 562fcf5ef2aSThomas Huth 5636ad216abSRichard Henderson static bool trans_l_mul(DisasContext *dc, arg_dab *a, uint32_t insn) 5646ad216abSRichard Henderson { 5656ad216abSRichard Henderson check_r0_write(a->d); 5666ad216abSRichard Henderson gen_mul(dc, cpu_R[a->d], cpu_R[a->a], cpu_R[a->b]); 5676ad216abSRichard Henderson return true; 568fcf5ef2aSThomas Huth } 5696ad216abSRichard Henderson 5706ad216abSRichard Henderson static bool trans_l_mulu(DisasContext *dc, arg_dab *a, uint32_t insn) 5716ad216abSRichard Henderson { 5726ad216abSRichard Henderson check_r0_write(a->d); 5736ad216abSRichard Henderson gen_mulu(dc, cpu_R[a->d], cpu_R[a->a], cpu_R[a->b]); 5746ad216abSRichard Henderson return true; 575fcf5ef2aSThomas Huth } 5766ad216abSRichard Henderson 5776ad216abSRichard Henderson static bool trans_l_div(DisasContext *dc, arg_dab *a, uint32_t insn) 5786ad216abSRichard Henderson { 5796ad216abSRichard Henderson check_r0_write(a->d); 5806ad216abSRichard Henderson gen_div(dc, cpu_R[a->d], cpu_R[a->a], cpu_R[a->b]); 5816ad216abSRichard Henderson return true; 5826ad216abSRichard Henderson } 5836ad216abSRichard Henderson 5846ad216abSRichard Henderson static bool trans_l_divu(DisasContext *dc, arg_dab *a, uint32_t insn) 5856ad216abSRichard Henderson { 5866ad216abSRichard Henderson check_r0_write(a->d); 5876ad216abSRichard Henderson gen_divu(dc, cpu_R[a->d], cpu_R[a->a], cpu_R[a->b]); 5886ad216abSRichard Henderson return true; 5896ad216abSRichard Henderson } 5906ad216abSRichard Henderson 5916ad216abSRichard Henderson static bool trans_l_muld(DisasContext *dc, arg_ab *a, uint32_t insn) 5926ad216abSRichard Henderson { 5936ad216abSRichard Henderson gen_muld(dc, cpu_R[a->a], cpu_R[a->b]); 5946ad216abSRichard Henderson return true; 5956ad216abSRichard Henderson } 5966ad216abSRichard Henderson 5976ad216abSRichard Henderson static bool trans_l_muldu(DisasContext *dc, arg_ab *a, uint32_t insn) 5986ad216abSRichard Henderson { 5996ad216abSRichard Henderson gen_muldu(dc, cpu_R[a->a], cpu_R[a->b]); 6006ad216abSRichard Henderson return true; 601fcf5ef2aSThomas Huth } 602fcf5ef2aSThomas Huth 603136e13aeSRichard Henderson static bool trans_l_j(DisasContext *dc, arg_l_j *a, uint32_t insn) 604136e13aeSRichard Henderson { 605136e13aeSRichard Henderson target_ulong tmp_pc = dc->base.pc_next + a->n * 4; 606136e13aeSRichard Henderson 607136e13aeSRichard Henderson tcg_gen_movi_tl(jmp_pc, tmp_pc); 6088000ba56SRichard Henderson dc->jmp_pc_imm = tmp_pc; 609136e13aeSRichard Henderson dc->delayed_branch = 2; 610136e13aeSRichard Henderson return true; 611136e13aeSRichard Henderson } 612136e13aeSRichard Henderson 613136e13aeSRichard Henderson static bool trans_l_jal(DisasContext *dc, arg_l_jal *a, uint32_t insn) 614136e13aeSRichard Henderson { 615136e13aeSRichard Henderson target_ulong tmp_pc = dc->base.pc_next + a->n * 4; 616136e13aeSRichard Henderson target_ulong ret_pc = dc->base.pc_next + 8; 617136e13aeSRichard Henderson 618136e13aeSRichard Henderson tcg_gen_movi_tl(cpu_R[9], ret_pc); 619136e13aeSRichard Henderson /* Optimize jal being used to load the PC for PIC. */ 620136e13aeSRichard Henderson if (tmp_pc != ret_pc) { 621136e13aeSRichard Henderson tcg_gen_movi_tl(jmp_pc, tmp_pc); 6228000ba56SRichard Henderson dc->jmp_pc_imm = tmp_pc; 623136e13aeSRichard Henderson dc->delayed_branch = 2; 624136e13aeSRichard Henderson } 625136e13aeSRichard Henderson return true; 626136e13aeSRichard Henderson } 627136e13aeSRichard Henderson 628136e13aeSRichard Henderson static void do_bf(DisasContext *dc, arg_l_bf *a, TCGCond cond) 629136e13aeSRichard Henderson { 630136e13aeSRichard Henderson target_ulong tmp_pc = dc->base.pc_next + a->n * 4; 631136e13aeSRichard Henderson TCGv t_next = tcg_const_tl(dc->base.pc_next + 8); 632136e13aeSRichard Henderson TCGv t_true = tcg_const_tl(tmp_pc); 633136e13aeSRichard Henderson TCGv t_zero = tcg_const_tl(0); 634136e13aeSRichard Henderson 635136e13aeSRichard Henderson tcg_gen_movcond_tl(cond, jmp_pc, cpu_sr_f, t_zero, t_true, t_next); 636136e13aeSRichard Henderson 637136e13aeSRichard Henderson tcg_temp_free(t_next); 638136e13aeSRichard Henderson tcg_temp_free(t_true); 639136e13aeSRichard Henderson tcg_temp_free(t_zero); 640136e13aeSRichard Henderson dc->delayed_branch = 2; 641136e13aeSRichard Henderson } 642136e13aeSRichard Henderson 643136e13aeSRichard Henderson static bool trans_l_bf(DisasContext *dc, arg_l_bf *a, uint32_t insn) 644136e13aeSRichard Henderson { 645136e13aeSRichard Henderson do_bf(dc, a, TCG_COND_NE); 646136e13aeSRichard Henderson return true; 647136e13aeSRichard Henderson } 648136e13aeSRichard Henderson 649136e13aeSRichard Henderson static bool trans_l_bnf(DisasContext *dc, arg_l_bf *a, uint32_t insn) 650136e13aeSRichard Henderson { 651136e13aeSRichard Henderson do_bf(dc, a, TCG_COND_EQ); 652136e13aeSRichard Henderson return true; 653136e13aeSRichard Henderson } 654136e13aeSRichard Henderson 655136e13aeSRichard Henderson static bool trans_l_jr(DisasContext *dc, arg_l_jr *a, uint32_t insn) 656136e13aeSRichard Henderson { 657136e13aeSRichard Henderson tcg_gen_mov_tl(jmp_pc, cpu_R[a->b]); 658136e13aeSRichard Henderson dc->delayed_branch = 2; 659136e13aeSRichard Henderson return true; 660136e13aeSRichard Henderson } 661136e13aeSRichard Henderson 662136e13aeSRichard Henderson static bool trans_l_jalr(DisasContext *dc, arg_l_jalr *a, uint32_t insn) 663136e13aeSRichard Henderson { 664136e13aeSRichard Henderson tcg_gen_mov_tl(jmp_pc, cpu_R[a->b]); 665136e13aeSRichard Henderson tcg_gen_movi_tl(cpu_R[9], dc->base.pc_next + 8); 666136e13aeSRichard Henderson dc->delayed_branch = 2; 667136e13aeSRichard Henderson return true; 668136e13aeSRichard Henderson } 669136e13aeSRichard Henderson 670d80bff19SRichard Henderson static bool trans_l_lwa(DisasContext *dc, arg_load *a, uint32_t insn) 671d80bff19SRichard Henderson { 672d80bff19SRichard Henderson TCGv ea; 673d80bff19SRichard Henderson 674d80bff19SRichard Henderson check_r0_write(a->d); 675d80bff19SRichard Henderson ea = tcg_temp_new(); 676d80bff19SRichard Henderson tcg_gen_addi_tl(ea, cpu_R[a->a], a->i); 677d80bff19SRichard Henderson tcg_gen_qemu_ld_tl(cpu_R[a->d], ea, dc->mem_idx, MO_TEUL); 678d80bff19SRichard Henderson tcg_gen_mov_tl(cpu_lock_addr, ea); 679d80bff19SRichard Henderson tcg_gen_mov_tl(cpu_lock_value, cpu_R[a->d]); 680d80bff19SRichard Henderson tcg_temp_free(ea); 681d80bff19SRichard Henderson return true; 682d80bff19SRichard Henderson } 683d80bff19SRichard Henderson 684d80bff19SRichard Henderson static void do_load(DisasContext *dc, arg_load *a, TCGMemOp mop) 685d80bff19SRichard Henderson { 686d80bff19SRichard Henderson TCGv ea; 687d80bff19SRichard Henderson 688d80bff19SRichard Henderson check_r0_write(a->d); 689d80bff19SRichard Henderson ea = tcg_temp_new(); 690d80bff19SRichard Henderson tcg_gen_addi_tl(ea, cpu_R[a->a], a->i); 691d80bff19SRichard Henderson tcg_gen_qemu_ld_tl(cpu_R[a->d], ea, dc->mem_idx, mop); 692d80bff19SRichard Henderson tcg_temp_free(ea); 693d80bff19SRichard Henderson } 694d80bff19SRichard Henderson 695d80bff19SRichard Henderson static bool trans_l_lwz(DisasContext *dc, arg_load *a, uint32_t insn) 696d80bff19SRichard Henderson { 697d80bff19SRichard Henderson do_load(dc, a, MO_TEUL); 698d80bff19SRichard Henderson return true; 699d80bff19SRichard Henderson } 700d80bff19SRichard Henderson 701d80bff19SRichard Henderson static bool trans_l_lws(DisasContext *dc, arg_load *a, uint32_t insn) 702d80bff19SRichard Henderson { 703d80bff19SRichard Henderson do_load(dc, a, MO_TESL); 704d80bff19SRichard Henderson return true; 705d80bff19SRichard Henderson } 706d80bff19SRichard Henderson 707d80bff19SRichard Henderson static bool trans_l_lbz(DisasContext *dc, arg_load *a, uint32_t insn) 708d80bff19SRichard Henderson { 709d80bff19SRichard Henderson do_load(dc, a, MO_UB); 710d80bff19SRichard Henderson return true; 711d80bff19SRichard Henderson } 712d80bff19SRichard Henderson 713d80bff19SRichard Henderson static bool trans_l_lbs(DisasContext *dc, arg_load *a, uint32_t insn) 714d80bff19SRichard Henderson { 715d80bff19SRichard Henderson do_load(dc, a, MO_SB); 716d80bff19SRichard Henderson return true; 717d80bff19SRichard Henderson } 718d80bff19SRichard Henderson 719d80bff19SRichard Henderson static bool trans_l_lhz(DisasContext *dc, arg_load *a, uint32_t insn) 720d80bff19SRichard Henderson { 721d80bff19SRichard Henderson do_load(dc, a, MO_TEUW); 722d80bff19SRichard Henderson return true; 723d80bff19SRichard Henderson } 724d80bff19SRichard Henderson 725d80bff19SRichard Henderson static bool trans_l_lhs(DisasContext *dc, arg_load *a, uint32_t insn) 726d80bff19SRichard Henderson { 727d80bff19SRichard Henderson do_load(dc, a, MO_TESW); 728d80bff19SRichard Henderson return true; 729d80bff19SRichard Henderson } 730d80bff19SRichard Henderson 731d80bff19SRichard Henderson static bool trans_l_swa(DisasContext *dc, arg_store *a, uint32_t insn) 732d80bff19SRichard Henderson { 733d80bff19SRichard Henderson TCGv ea, val; 734d80bff19SRichard Henderson TCGLabel *lab_fail, *lab_done; 735d80bff19SRichard Henderson 736d80bff19SRichard Henderson ea = tcg_temp_new(); 737d80bff19SRichard Henderson tcg_gen_addi_tl(ea, cpu_R[a->a], a->i); 738d80bff19SRichard Henderson 739d80bff19SRichard Henderson /* For TB_FLAGS_R0_0, the branch below invalidates the temporary assigned 740d80bff19SRichard Henderson to cpu_R[0]. Since l.swa is quite often immediately followed by a 741d80bff19SRichard Henderson branch, don't bother reallocating; finish the TB using the "real" R0. 742d80bff19SRichard Henderson This also takes care of RB input across the branch. */ 743d80bff19SRichard Henderson cpu_R[0] = cpu_R0; 744d80bff19SRichard Henderson 745d80bff19SRichard Henderson lab_fail = gen_new_label(); 746d80bff19SRichard Henderson lab_done = gen_new_label(); 747d80bff19SRichard Henderson tcg_gen_brcond_tl(TCG_COND_NE, ea, cpu_lock_addr, lab_fail); 748d80bff19SRichard Henderson tcg_temp_free(ea); 749d80bff19SRichard Henderson 750d80bff19SRichard Henderson val = tcg_temp_new(); 751d80bff19SRichard Henderson tcg_gen_atomic_cmpxchg_tl(val, cpu_lock_addr, cpu_lock_value, 752d80bff19SRichard Henderson cpu_R[a->b], dc->mem_idx, MO_TEUL); 753d80bff19SRichard Henderson tcg_gen_setcond_tl(TCG_COND_EQ, cpu_sr_f, val, cpu_lock_value); 754d80bff19SRichard Henderson tcg_temp_free(val); 755d80bff19SRichard Henderson 756d80bff19SRichard Henderson tcg_gen_br(lab_done); 757d80bff19SRichard Henderson 758d80bff19SRichard Henderson gen_set_label(lab_fail); 759d80bff19SRichard Henderson tcg_gen_movi_tl(cpu_sr_f, 0); 760d80bff19SRichard Henderson 761d80bff19SRichard Henderson gen_set_label(lab_done); 762d80bff19SRichard Henderson tcg_gen_movi_tl(cpu_lock_addr, -1); 763d80bff19SRichard Henderson return true; 764d80bff19SRichard Henderson } 765d80bff19SRichard Henderson 766d80bff19SRichard Henderson static void do_store(DisasContext *dc, arg_store *a, TCGMemOp mop) 767d80bff19SRichard Henderson { 768d80bff19SRichard Henderson TCGv t0 = tcg_temp_new(); 769d80bff19SRichard Henderson tcg_gen_addi_tl(t0, cpu_R[a->a], a->i); 770d80bff19SRichard Henderson tcg_gen_qemu_st_tl(cpu_R[a->b], t0, dc->mem_idx, mop); 771d80bff19SRichard Henderson tcg_temp_free(t0); 772d80bff19SRichard Henderson } 773d80bff19SRichard Henderson 774d80bff19SRichard Henderson static bool trans_l_sw(DisasContext *dc, arg_store *a, uint32_t insn) 775d80bff19SRichard Henderson { 776d80bff19SRichard Henderson do_store(dc, a, MO_TEUL); 777d80bff19SRichard Henderson return true; 778d80bff19SRichard Henderson } 779d80bff19SRichard Henderson 780d80bff19SRichard Henderson static bool trans_l_sb(DisasContext *dc, arg_store *a, uint32_t insn) 781d80bff19SRichard Henderson { 782d80bff19SRichard Henderson do_store(dc, a, MO_UB); 783d80bff19SRichard Henderson return true; 784d80bff19SRichard Henderson } 785d80bff19SRichard Henderson 786d80bff19SRichard Henderson static bool trans_l_sh(DisasContext *dc, arg_store *a, uint32_t insn) 787d80bff19SRichard Henderson { 788d80bff19SRichard Henderson do_store(dc, a, MO_TEUW); 789d80bff19SRichard Henderson return true; 790d80bff19SRichard Henderson } 791d80bff19SRichard Henderson 7928816f70bSRichard Henderson static bool trans_l_nop(DisasContext *dc, arg_l_nop *a, uint32_t insn) 793fcf5ef2aSThomas Huth { 7948816f70bSRichard Henderson return true; 7958816f70bSRichard Henderson } 7968816f70bSRichard Henderson 7978816f70bSRichard Henderson static bool trans_l_addi(DisasContext *dc, arg_rri *a, uint32_t insn) 7988816f70bSRichard Henderson { 7999ecaa27eSRichard Henderson TCGv t0; 800fcf5ef2aSThomas Huth 8018816f70bSRichard Henderson check_r0_write(a->d); 8028816f70bSRichard Henderson t0 = tcg_const_tl(a->i); 8038816f70bSRichard Henderson gen_add(dc, cpu_R[a->d], cpu_R[a->a], t0); 8046f7332baSRichard Henderson tcg_temp_free(t0); 8058816f70bSRichard Henderson return true; 8068816f70bSRichard Henderson } 807fcf5ef2aSThomas Huth 8088816f70bSRichard Henderson static bool trans_l_addic(DisasContext *dc, arg_rri *a, uint32_t insn) 809fcf5ef2aSThomas Huth { 8108816f70bSRichard Henderson TCGv t0; 8118816f70bSRichard Henderson 8128816f70bSRichard Henderson check_r0_write(a->d); 8138816f70bSRichard Henderson t0 = tcg_const_tl(a->i); 8148816f70bSRichard Henderson gen_addc(dc, cpu_R[a->d], cpu_R[a->a], t0); 8158816f70bSRichard Henderson tcg_temp_free(t0); 8168816f70bSRichard Henderson return true; 8178816f70bSRichard Henderson } 8188816f70bSRichard Henderson 8198816f70bSRichard Henderson static bool trans_l_muli(DisasContext *dc, arg_rri *a, uint32_t insn) 8208816f70bSRichard Henderson { 8218816f70bSRichard Henderson TCGv t0; 8228816f70bSRichard Henderson 8238816f70bSRichard Henderson check_r0_write(a->d); 8248816f70bSRichard Henderson t0 = tcg_const_tl(a->i); 8258816f70bSRichard Henderson gen_mul(dc, cpu_R[a->d], cpu_R[a->a], t0); 8268816f70bSRichard Henderson tcg_temp_free(t0); 8278816f70bSRichard Henderson return true; 8288816f70bSRichard Henderson } 8298816f70bSRichard Henderson 8308816f70bSRichard Henderson static bool trans_l_maci(DisasContext *dc, arg_l_maci *a, uint32_t insn) 8318816f70bSRichard Henderson { 8328816f70bSRichard Henderson TCGv t0; 8338816f70bSRichard Henderson 8348816f70bSRichard Henderson t0 = tcg_const_tl(a->i); 8358816f70bSRichard Henderson gen_mac(dc, cpu_R[a->a], t0); 8368816f70bSRichard Henderson tcg_temp_free(t0); 8378816f70bSRichard Henderson return true; 8388816f70bSRichard Henderson } 8398816f70bSRichard Henderson 8408816f70bSRichard Henderson static bool trans_l_andi(DisasContext *dc, arg_rrk *a, uint32_t insn) 8418816f70bSRichard Henderson { 8428816f70bSRichard Henderson check_r0_write(a->d); 8438816f70bSRichard Henderson tcg_gen_andi_tl(cpu_R[a->d], cpu_R[a->a], a->k); 8448816f70bSRichard Henderson return true; 8458816f70bSRichard Henderson } 8468816f70bSRichard Henderson 8478816f70bSRichard Henderson static bool trans_l_ori(DisasContext *dc, arg_rrk *a, uint32_t insn) 8488816f70bSRichard Henderson { 8498816f70bSRichard Henderson check_r0_write(a->d); 8508816f70bSRichard Henderson tcg_gen_ori_tl(cpu_R[a->d], cpu_R[a->a], a->k); 8518816f70bSRichard Henderson return true; 8528816f70bSRichard Henderson } 8538816f70bSRichard Henderson 8548816f70bSRichard Henderson static bool trans_l_xori(DisasContext *dc, arg_rri *a, uint32_t insn) 8558816f70bSRichard Henderson { 8568816f70bSRichard Henderson check_r0_write(a->d); 8578816f70bSRichard Henderson tcg_gen_xori_tl(cpu_R[a->d], cpu_R[a->a], a->i); 8588816f70bSRichard Henderson return true; 8598816f70bSRichard Henderson } 8608816f70bSRichard Henderson 8618816f70bSRichard Henderson static bool trans_l_mfspr(DisasContext *dc, arg_l_mfspr *a, uint32_t insn) 8628816f70bSRichard Henderson { 8638816f70bSRichard Henderson check_r0_write(a->d); 8648816f70bSRichard Henderson 8652ba65417SRichard Henderson if (is_user(dc)) { 866fcf5ef2aSThomas Huth gen_illegal_exception(dc); 8678816f70bSRichard Henderson } else { 868c28fa81fSRichard Henderson TCGv spr = tcg_temp_new(); 869c28fa81fSRichard Henderson tcg_gen_ori_tl(spr, cpu_R[a->a], a->k); 870c28fa81fSRichard Henderson gen_helper_mfspr(cpu_R[a->d], cpu_env, cpu_R[a->d], spr); 871c28fa81fSRichard Henderson tcg_temp_free(spr); 872fcf5ef2aSThomas Huth } 8738816f70bSRichard Henderson return true; 8748816f70bSRichard Henderson } 875fcf5ef2aSThomas Huth 8768816f70bSRichard Henderson static bool trans_l_mtspr(DisasContext *dc, arg_l_mtspr *a, uint32_t insn) 877fcf5ef2aSThomas Huth { 8782ba65417SRichard Henderson if (is_user(dc)) { 879fcf5ef2aSThomas Huth gen_illegal_exception(dc); 8808816f70bSRichard Henderson } else { 881c28fa81fSRichard Henderson TCGv spr; 88201ec3ec9SRichard Henderson 88301ec3ec9SRichard Henderson /* For SR, we will need to exit the TB to recognize the new 88401ec3ec9SRichard Henderson * exception state. For NPC, in theory this counts as a branch 88501ec3ec9SRichard Henderson * (although the SPR only exists for use by an ICE). Save all 88601ec3ec9SRichard Henderson * of the cpu state first, allowing it to be overwritten. 88701ec3ec9SRichard Henderson */ 88801ec3ec9SRichard Henderson if (dc->delayed_branch) { 88901ec3ec9SRichard Henderson tcg_gen_mov_tl(cpu_pc, jmp_pc); 89001ec3ec9SRichard Henderson tcg_gen_discard_tl(jmp_pc); 89101ec3ec9SRichard Henderson } else { 89201ec3ec9SRichard Henderson tcg_gen_movi_tl(cpu_pc, dc->base.pc_next + 4); 89301ec3ec9SRichard Henderson } 89401ec3ec9SRichard Henderson dc->base.is_jmp = DISAS_EXIT; 89501ec3ec9SRichard Henderson 896c28fa81fSRichard Henderson spr = tcg_temp_new(); 897c28fa81fSRichard Henderson tcg_gen_ori_tl(spr, cpu_R[a->a], a->k); 898c28fa81fSRichard Henderson gen_helper_mtspr(cpu_env, spr, cpu_R[a->b]); 899c28fa81fSRichard Henderson tcg_temp_free(spr); 900fcf5ef2aSThomas Huth } 9018816f70bSRichard Henderson return true; 902fcf5ef2aSThomas Huth } 903fcf5ef2aSThomas Huth 90499d863d6SRichard Henderson static bool trans_l_mac(DisasContext *dc, arg_ab *a, uint32_t insn) 905fcf5ef2aSThomas Huth { 90699d863d6SRichard Henderson gen_mac(dc, cpu_R[a->a], cpu_R[a->b]); 90799d863d6SRichard Henderson return true; 908fcf5ef2aSThomas Huth } 90999d863d6SRichard Henderson 91099d863d6SRichard Henderson static bool trans_l_msb(DisasContext *dc, arg_ab *a, uint32_t insn) 91199d863d6SRichard Henderson { 91299d863d6SRichard Henderson gen_msb(dc, cpu_R[a->a], cpu_R[a->b]); 91399d863d6SRichard Henderson return true; 91499d863d6SRichard Henderson } 91599d863d6SRichard Henderson 91699d863d6SRichard Henderson static bool trans_l_macu(DisasContext *dc, arg_ab *a, uint32_t insn) 91799d863d6SRichard Henderson { 91899d863d6SRichard Henderson gen_macu(dc, cpu_R[a->a], cpu_R[a->b]); 91999d863d6SRichard Henderson return true; 92099d863d6SRichard Henderson } 92199d863d6SRichard Henderson 92299d863d6SRichard Henderson static bool trans_l_msbu(DisasContext *dc, arg_ab *a, uint32_t insn) 92399d863d6SRichard Henderson { 92499d863d6SRichard Henderson gen_msbu(dc, cpu_R[a->a], cpu_R[a->b]); 92599d863d6SRichard Henderson return true; 926fcf5ef2aSThomas Huth } 927fcf5ef2aSThomas Huth 928e20c2592SRichard Henderson static bool trans_l_slli(DisasContext *dc, arg_dal *a, uint32_t insn) 929fcf5ef2aSThomas Huth { 930e20c2592SRichard Henderson check_r0_write(a->d); 931e20c2592SRichard Henderson tcg_gen_shli_tl(cpu_R[a->d], cpu_R[a->a], a->l & (TARGET_LONG_BITS - 1)); 932e20c2592SRichard Henderson return true; 933fcf5ef2aSThomas Huth } 934e20c2592SRichard Henderson 935e20c2592SRichard Henderson static bool trans_l_srli(DisasContext *dc, arg_dal *a, uint32_t insn) 936e20c2592SRichard Henderson { 937e20c2592SRichard Henderson check_r0_write(a->d); 938e20c2592SRichard Henderson tcg_gen_shri_tl(cpu_R[a->d], cpu_R[a->a], a->l & (TARGET_LONG_BITS - 1)); 939e20c2592SRichard Henderson return true; 940e20c2592SRichard Henderson } 941e20c2592SRichard Henderson 942e20c2592SRichard Henderson static bool trans_l_srai(DisasContext *dc, arg_dal *a, uint32_t insn) 943e20c2592SRichard Henderson { 944e20c2592SRichard Henderson check_r0_write(a->d); 945e20c2592SRichard Henderson tcg_gen_sari_tl(cpu_R[a->d], cpu_R[a->a], a->l & (TARGET_LONG_BITS - 1)); 946e20c2592SRichard Henderson return true; 947e20c2592SRichard Henderson } 948e20c2592SRichard Henderson 949e20c2592SRichard Henderson static bool trans_l_rori(DisasContext *dc, arg_dal *a, uint32_t insn) 950e20c2592SRichard Henderson { 951e20c2592SRichard Henderson check_r0_write(a->d); 952e20c2592SRichard Henderson tcg_gen_rotri_tl(cpu_R[a->d], cpu_R[a->a], a->l & (TARGET_LONG_BITS - 1)); 953e20c2592SRichard Henderson return true; 954fcf5ef2aSThomas Huth } 955fcf5ef2aSThomas Huth 956e720a571SRichard Henderson static bool trans_l_movhi(DisasContext *dc, arg_l_movhi *a, uint32_t insn) 957fcf5ef2aSThomas Huth { 958e720a571SRichard Henderson check_r0_write(a->d); 959e720a571SRichard Henderson tcg_gen_movi_tl(cpu_R[a->d], a->k << 16); 960e720a571SRichard Henderson return true; 961fcf5ef2aSThomas Huth } 962e720a571SRichard Henderson 963e720a571SRichard Henderson static bool trans_l_macrc(DisasContext *dc, arg_l_macrc *a, uint32_t insn) 964e720a571SRichard Henderson { 965e720a571SRichard Henderson check_r0_write(a->d); 966e720a571SRichard Henderson tcg_gen_trunc_i64_tl(cpu_R[a->d], cpu_mac); 967e720a571SRichard Henderson tcg_gen_movi_i64(cpu_mac, 0); 968e720a571SRichard Henderson return true; 969fcf5ef2aSThomas Huth } 970fcf5ef2aSThomas Huth 971fbb3e29aSRichard Henderson static bool trans_l_sfeq(DisasContext *dc, arg_ab *a, TCGCond cond) 972fcf5ef2aSThomas Huth { 973fbb3e29aSRichard Henderson tcg_gen_setcond_tl(TCG_COND_EQ, cpu_sr_f, cpu_R[a->a], cpu_R[a->b]); 974fbb3e29aSRichard Henderson return true; 975fcf5ef2aSThomas Huth } 976fbb3e29aSRichard Henderson 977fbb3e29aSRichard Henderson static bool trans_l_sfne(DisasContext *dc, arg_ab *a, TCGCond cond) 978fbb3e29aSRichard Henderson { 979fbb3e29aSRichard Henderson tcg_gen_setcond_tl(TCG_COND_NE, cpu_sr_f, cpu_R[a->a], cpu_R[a->b]); 980fbb3e29aSRichard Henderson return true; 981fbb3e29aSRichard Henderson } 982fbb3e29aSRichard Henderson 983fbb3e29aSRichard Henderson static bool trans_l_sfgtu(DisasContext *dc, arg_ab *a, TCGCond cond) 984fbb3e29aSRichard Henderson { 985fbb3e29aSRichard Henderson tcg_gen_setcond_tl(TCG_COND_GTU, cpu_sr_f, cpu_R[a->a], cpu_R[a->b]); 986fbb3e29aSRichard Henderson return true; 987fbb3e29aSRichard Henderson } 988fbb3e29aSRichard Henderson 989fbb3e29aSRichard Henderson static bool trans_l_sfgeu(DisasContext *dc, arg_ab *a, TCGCond cond) 990fbb3e29aSRichard Henderson { 991fbb3e29aSRichard Henderson tcg_gen_setcond_tl(TCG_COND_GEU, cpu_sr_f, cpu_R[a->a], cpu_R[a->b]); 992fbb3e29aSRichard Henderson return true; 993fbb3e29aSRichard Henderson } 994fbb3e29aSRichard Henderson 995fbb3e29aSRichard Henderson static bool trans_l_sfltu(DisasContext *dc, arg_ab *a, TCGCond cond) 996fbb3e29aSRichard Henderson { 997fbb3e29aSRichard Henderson tcg_gen_setcond_tl(TCG_COND_LTU, cpu_sr_f, cpu_R[a->a], cpu_R[a->b]); 998fbb3e29aSRichard Henderson return true; 999fbb3e29aSRichard Henderson } 1000fbb3e29aSRichard Henderson 1001fbb3e29aSRichard Henderson static bool trans_l_sfleu(DisasContext *dc, arg_ab *a, TCGCond cond) 1002fbb3e29aSRichard Henderson { 1003fbb3e29aSRichard Henderson tcg_gen_setcond_tl(TCG_COND_LEU, cpu_sr_f, cpu_R[a->a], cpu_R[a->b]); 1004fbb3e29aSRichard Henderson return true; 1005fbb3e29aSRichard Henderson } 1006fbb3e29aSRichard Henderson 1007fbb3e29aSRichard Henderson static bool trans_l_sfgts(DisasContext *dc, arg_ab *a, TCGCond cond) 1008fbb3e29aSRichard Henderson { 1009fbb3e29aSRichard Henderson tcg_gen_setcond_tl(TCG_COND_GT, cpu_sr_f, cpu_R[a->a], cpu_R[a->b]); 1010fbb3e29aSRichard Henderson return true; 1011fbb3e29aSRichard Henderson } 1012fbb3e29aSRichard Henderson 1013fbb3e29aSRichard Henderson static bool trans_l_sfges(DisasContext *dc, arg_ab *a, TCGCond cond) 1014fbb3e29aSRichard Henderson { 1015fbb3e29aSRichard Henderson tcg_gen_setcond_tl(TCG_COND_GE, cpu_sr_f, cpu_R[a->a], cpu_R[a->b]); 1016fbb3e29aSRichard Henderson return true; 1017fbb3e29aSRichard Henderson } 1018fbb3e29aSRichard Henderson 1019fbb3e29aSRichard Henderson static bool trans_l_sflts(DisasContext *dc, arg_ab *a, TCGCond cond) 1020fbb3e29aSRichard Henderson { 1021fbb3e29aSRichard Henderson tcg_gen_setcond_tl(TCG_COND_LT, cpu_sr_f, cpu_R[a->a], cpu_R[a->b]); 1022fbb3e29aSRichard Henderson return true; 1023fbb3e29aSRichard Henderson } 1024fbb3e29aSRichard Henderson 1025fbb3e29aSRichard Henderson static bool trans_l_sfles(DisasContext *dc, arg_ab *a, TCGCond cond) 1026fbb3e29aSRichard Henderson { 1027fbb3e29aSRichard Henderson tcg_gen_setcond_tl(TCG_COND_LE, cpu_sr_f, cpu_R[a->a], cpu_R[a->b]); 1028fbb3e29aSRichard Henderson return true; 1029fcf5ef2aSThomas Huth } 1030fcf5ef2aSThomas Huth 1031032de4fcSRichard Henderson static bool trans_l_sfeqi(DisasContext *dc, arg_ai *a, TCGCond cond) 1032fcf5ef2aSThomas Huth { 1033032de4fcSRichard Henderson tcg_gen_setcondi_tl(TCG_COND_EQ, cpu_sr_f, cpu_R[a->a], a->i); 1034032de4fcSRichard Henderson return true; 1035fcf5ef2aSThomas Huth } 1036032de4fcSRichard Henderson 1037032de4fcSRichard Henderson static bool trans_l_sfnei(DisasContext *dc, arg_ai *a, TCGCond cond) 1038032de4fcSRichard Henderson { 1039032de4fcSRichard Henderson tcg_gen_setcondi_tl(TCG_COND_NE, cpu_sr_f, cpu_R[a->a], a->i); 1040032de4fcSRichard Henderson return true; 1041032de4fcSRichard Henderson } 1042032de4fcSRichard Henderson 1043032de4fcSRichard Henderson static bool trans_l_sfgtui(DisasContext *dc, arg_ai *a, TCGCond cond) 1044032de4fcSRichard Henderson { 1045032de4fcSRichard Henderson tcg_gen_setcondi_tl(TCG_COND_GTU, cpu_sr_f, cpu_R[a->a], a->i); 1046032de4fcSRichard Henderson return true; 1047032de4fcSRichard Henderson } 1048032de4fcSRichard Henderson 1049032de4fcSRichard Henderson static bool trans_l_sfgeui(DisasContext *dc, arg_ai *a, TCGCond cond) 1050032de4fcSRichard Henderson { 1051032de4fcSRichard Henderson tcg_gen_setcondi_tl(TCG_COND_GEU, cpu_sr_f, cpu_R[a->a], a->i); 1052032de4fcSRichard Henderson return true; 1053032de4fcSRichard Henderson } 1054032de4fcSRichard Henderson 1055032de4fcSRichard Henderson static bool trans_l_sfltui(DisasContext *dc, arg_ai *a, TCGCond cond) 1056032de4fcSRichard Henderson { 1057032de4fcSRichard Henderson tcg_gen_setcondi_tl(TCG_COND_LTU, cpu_sr_f, cpu_R[a->a], a->i); 1058032de4fcSRichard Henderson return true; 1059032de4fcSRichard Henderson } 1060032de4fcSRichard Henderson 1061032de4fcSRichard Henderson static bool trans_l_sfleui(DisasContext *dc, arg_ai *a, TCGCond cond) 1062032de4fcSRichard Henderson { 1063032de4fcSRichard Henderson tcg_gen_setcondi_tl(TCG_COND_LEU, cpu_sr_f, cpu_R[a->a], a->i); 1064032de4fcSRichard Henderson return true; 1065032de4fcSRichard Henderson } 1066032de4fcSRichard Henderson 1067032de4fcSRichard Henderson static bool trans_l_sfgtsi(DisasContext *dc, arg_ai *a, TCGCond cond) 1068032de4fcSRichard Henderson { 1069032de4fcSRichard Henderson tcg_gen_setcondi_tl(TCG_COND_GT, cpu_sr_f, cpu_R[a->a], a->i); 1070032de4fcSRichard Henderson return true; 1071032de4fcSRichard Henderson } 1072032de4fcSRichard Henderson 1073032de4fcSRichard Henderson static bool trans_l_sfgesi(DisasContext *dc, arg_ai *a, TCGCond cond) 1074032de4fcSRichard Henderson { 1075032de4fcSRichard Henderson tcg_gen_setcondi_tl(TCG_COND_GE, cpu_sr_f, cpu_R[a->a], a->i); 1076032de4fcSRichard Henderson return true; 1077032de4fcSRichard Henderson } 1078032de4fcSRichard Henderson 1079032de4fcSRichard Henderson static bool trans_l_sfltsi(DisasContext *dc, arg_ai *a, TCGCond cond) 1080032de4fcSRichard Henderson { 1081032de4fcSRichard Henderson tcg_gen_setcondi_tl(TCG_COND_LT, cpu_sr_f, cpu_R[a->a], a->i); 1082032de4fcSRichard Henderson return true; 1083032de4fcSRichard Henderson } 1084032de4fcSRichard Henderson 1085032de4fcSRichard Henderson static bool trans_l_sflesi(DisasContext *dc, arg_ai *a, TCGCond cond) 1086032de4fcSRichard Henderson { 1087032de4fcSRichard Henderson tcg_gen_setcondi_tl(TCG_COND_LE, cpu_sr_f, cpu_R[a->a], a->i); 1088032de4fcSRichard Henderson return true; 1089fcf5ef2aSThomas Huth } 1090fcf5ef2aSThomas Huth 10917de9729fSRichard Henderson static bool trans_l_sys(DisasContext *dc, arg_l_sys *a, uint32_t insn) 1092fcf5ef2aSThomas Huth { 10931ffa4bceSEmilio G. Cota tcg_gen_movi_tl(cpu_pc, dc->base.pc_next); 1094fcf5ef2aSThomas Huth gen_exception(dc, EXCP_SYSCALL); 10951ffa4bceSEmilio G. Cota dc->base.is_jmp = DISAS_NORETURN; 10967de9729fSRichard Henderson return true; 10977de9729fSRichard Henderson } 1098fcf5ef2aSThomas Huth 10997de9729fSRichard Henderson static bool trans_l_trap(DisasContext *dc, arg_l_trap *a, uint32_t insn) 11007de9729fSRichard Henderson { 11011ffa4bceSEmilio G. Cota tcg_gen_movi_tl(cpu_pc, dc->base.pc_next); 1102fcf5ef2aSThomas Huth gen_exception(dc, EXCP_TRAP); 11031ffa4bceSEmilio G. Cota dc->base.is_jmp = DISAS_NORETURN; 11047de9729fSRichard Henderson return true; 11057de9729fSRichard Henderson } 1106fcf5ef2aSThomas Huth 11077de9729fSRichard Henderson static bool trans_l_msync(DisasContext *dc, arg_l_msync *a, uint32_t insn) 11087de9729fSRichard Henderson { 110924fc5c0fSRichard Henderson tcg_gen_mb(TCG_MO_ALL); 11107de9729fSRichard Henderson return true; 1111fcf5ef2aSThomas Huth } 11127de9729fSRichard Henderson 11137de9729fSRichard Henderson static bool trans_l_psync(DisasContext *dc, arg_l_psync *a, uint32_t insn) 11147de9729fSRichard Henderson { 11157de9729fSRichard Henderson return true; 11167de9729fSRichard Henderson } 11177de9729fSRichard Henderson 11187de9729fSRichard Henderson static bool trans_l_csync(DisasContext *dc, arg_l_csync *a, uint32_t insn) 11197de9729fSRichard Henderson { 11207de9729fSRichard Henderson return true; 1121fcf5ef2aSThomas Huth } 1122fcf5ef2aSThomas Huth 11238816f70bSRichard Henderson static bool trans_l_rfe(DisasContext *dc, arg_l_rfe *a, uint32_t insn) 11248816f70bSRichard Henderson { 11252ba65417SRichard Henderson if (is_user(dc)) { 11268816f70bSRichard Henderson gen_illegal_exception(dc); 11278816f70bSRichard Henderson } else { 11288816f70bSRichard Henderson gen_helper_rfe(cpu_env); 112964e46c95SRichard Henderson dc->base.is_jmp = DISAS_EXIT; 11308816f70bSRichard Henderson } 11318816f70bSRichard Henderson return true; 11328816f70bSRichard Henderson } 11338816f70bSRichard Henderson 11346fd204a2SRichard Henderson static void do_fp2(DisasContext *dc, arg_da *a, 11356fd204a2SRichard Henderson void (*fn)(TCGv, TCGv_env, TCGv)) 1136fcf5ef2aSThomas Huth { 11376fd204a2SRichard Henderson check_r0_write(a->d); 11386fd204a2SRichard Henderson fn(cpu_R[a->d], cpu_env, cpu_R[a->a]); 11394e2d3007SRichard Henderson gen_helper_update_fpcsr(cpu_env); 1140fcf5ef2aSThomas Huth } 11416fd204a2SRichard Henderson 11426fd204a2SRichard Henderson static void do_fp3(DisasContext *dc, arg_dab *a, 11436fd204a2SRichard Henderson void (*fn)(TCGv, TCGv_env, TCGv, TCGv)) 11446fd204a2SRichard Henderson { 11456fd204a2SRichard Henderson check_r0_write(a->d); 11466fd204a2SRichard Henderson fn(cpu_R[a->d], cpu_env, cpu_R[a->a], cpu_R[a->b]); 11476fd204a2SRichard Henderson gen_helper_update_fpcsr(cpu_env); 11486fd204a2SRichard Henderson } 11496fd204a2SRichard Henderson 11506fd204a2SRichard Henderson static void do_fpcmp(DisasContext *dc, arg_ab *a, 11516fd204a2SRichard Henderson void (*fn)(TCGv, TCGv_env, TCGv, TCGv), 11526fd204a2SRichard Henderson bool inv, bool swap) 11536fd204a2SRichard Henderson { 11546fd204a2SRichard Henderson if (swap) { 11556fd204a2SRichard Henderson fn(cpu_sr_f, cpu_env, cpu_R[a->b], cpu_R[a->a]); 11566fd204a2SRichard Henderson } else { 11576fd204a2SRichard Henderson fn(cpu_sr_f, cpu_env, cpu_R[a->a], cpu_R[a->b]); 11586fd204a2SRichard Henderson } 11596fd204a2SRichard Henderson if (inv) { 11606fd204a2SRichard Henderson tcg_gen_xori_tl(cpu_sr_f, cpu_sr_f, 1); 11616fd204a2SRichard Henderson } 11626fd204a2SRichard Henderson gen_helper_update_fpcsr(cpu_env); 11636fd204a2SRichard Henderson } 11646fd204a2SRichard Henderson 11656fd204a2SRichard Henderson static bool trans_lf_add_s(DisasContext *dc, arg_dab *a, uint32_t insn) 11666fd204a2SRichard Henderson { 11676fd204a2SRichard Henderson do_fp3(dc, a, gen_helper_float_add_s); 11686fd204a2SRichard Henderson return true; 11696fd204a2SRichard Henderson } 11706fd204a2SRichard Henderson 11716fd204a2SRichard Henderson static bool trans_lf_sub_s(DisasContext *dc, arg_dab *a, uint32_t insn) 11726fd204a2SRichard Henderson { 11736fd204a2SRichard Henderson do_fp3(dc, a, gen_helper_float_sub_s); 11746fd204a2SRichard Henderson return true; 11756fd204a2SRichard Henderson } 11766fd204a2SRichard Henderson 11776fd204a2SRichard Henderson static bool trans_lf_mul_s(DisasContext *dc, arg_dab *a, uint32_t insn) 11786fd204a2SRichard Henderson { 11796fd204a2SRichard Henderson do_fp3(dc, a, gen_helper_float_mul_s); 11806fd204a2SRichard Henderson return true; 11816fd204a2SRichard Henderson } 11826fd204a2SRichard Henderson 11836fd204a2SRichard Henderson static bool trans_lf_div_s(DisasContext *dc, arg_dab *a, uint32_t insn) 11846fd204a2SRichard Henderson { 11856fd204a2SRichard Henderson do_fp3(dc, a, gen_helper_float_div_s); 11866fd204a2SRichard Henderson return true; 11876fd204a2SRichard Henderson } 11886fd204a2SRichard Henderson 11896fd204a2SRichard Henderson static bool trans_lf_rem_s(DisasContext *dc, arg_dab *a, uint32_t insn) 11906fd204a2SRichard Henderson { 11916fd204a2SRichard Henderson do_fp3(dc, a, gen_helper_float_rem_s); 11926fd204a2SRichard Henderson return true; 11936fd204a2SRichard Henderson } 11946fd204a2SRichard Henderson 11956fd204a2SRichard Henderson static bool trans_lf_itof_s(DisasContext *dc, arg_da *a, uint32_t insn) 11966fd204a2SRichard Henderson { 11976fd204a2SRichard Henderson do_fp2(dc, a, gen_helper_itofs); 11986fd204a2SRichard Henderson return true; 11996fd204a2SRichard Henderson } 12006fd204a2SRichard Henderson 12016fd204a2SRichard Henderson static bool trans_lf_ftoi_s(DisasContext *dc, arg_da *a, uint32_t insn) 12026fd204a2SRichard Henderson { 12036fd204a2SRichard Henderson do_fp2(dc, a, gen_helper_ftois); 12046fd204a2SRichard Henderson return true; 12056fd204a2SRichard Henderson } 12066fd204a2SRichard Henderson 12076fd204a2SRichard Henderson static bool trans_lf_madd_s(DisasContext *dc, arg_dab *a, uint32_t insn) 12086fd204a2SRichard Henderson { 12096fd204a2SRichard Henderson check_r0_write(a->d); 12106fd204a2SRichard Henderson gen_helper_float_madd_s(cpu_R[a->d], cpu_env, cpu_R[a->d], 12116fd204a2SRichard Henderson cpu_R[a->a], cpu_R[a->b]); 12126fd204a2SRichard Henderson gen_helper_update_fpcsr(cpu_env); 12136fd204a2SRichard Henderson return true; 12146fd204a2SRichard Henderson } 12156fd204a2SRichard Henderson 12166fd204a2SRichard Henderson static bool trans_lf_sfeq_s(DisasContext *dc, arg_ab *a, uint32_t insn) 12176fd204a2SRichard Henderson { 12186fd204a2SRichard Henderson do_fpcmp(dc, a, gen_helper_float_eq_s, false, false); 12196fd204a2SRichard Henderson return true; 12206fd204a2SRichard Henderson } 12216fd204a2SRichard Henderson 12226fd204a2SRichard Henderson static bool trans_lf_sfne_s(DisasContext *dc, arg_ab *a, uint32_t insn) 12236fd204a2SRichard Henderson { 12246fd204a2SRichard Henderson do_fpcmp(dc, a, gen_helper_float_eq_s, true, false); 12256fd204a2SRichard Henderson return true; 12266fd204a2SRichard Henderson } 12276fd204a2SRichard Henderson 12286fd204a2SRichard Henderson static bool trans_lf_sfgt_s(DisasContext *dc, arg_ab *a, uint32_t insn) 12296fd204a2SRichard Henderson { 12306fd204a2SRichard Henderson do_fpcmp(dc, a, gen_helper_float_lt_s, false, true); 12316fd204a2SRichard Henderson return true; 12326fd204a2SRichard Henderson } 12336fd204a2SRichard Henderson 12346fd204a2SRichard Henderson static bool trans_lf_sfge_s(DisasContext *dc, arg_ab *a, uint32_t insn) 12356fd204a2SRichard Henderson { 12366fd204a2SRichard Henderson do_fpcmp(dc, a, gen_helper_float_le_s, false, true); 12376fd204a2SRichard Henderson return true; 12386fd204a2SRichard Henderson } 12396fd204a2SRichard Henderson 12406fd204a2SRichard Henderson static bool trans_lf_sflt_s(DisasContext *dc, arg_ab *a, uint32_t insn) 12416fd204a2SRichard Henderson { 12426fd204a2SRichard Henderson do_fpcmp(dc, a, gen_helper_float_lt_s, false, false); 12436fd204a2SRichard Henderson return true; 12446fd204a2SRichard Henderson } 12456fd204a2SRichard Henderson 12466fd204a2SRichard Henderson static bool trans_lf_sfle_s(DisasContext *dc, arg_ab *a, uint32_t insn) 12476fd204a2SRichard Henderson { 12486fd204a2SRichard Henderson do_fpcmp(dc, a, gen_helper_float_le_s, false, false); 12496fd204a2SRichard Henderson return true; 1250fcf5ef2aSThomas Huth } 1251fcf5ef2aSThomas Huth 1252a4fd3ec3SEmilio G. Cota static void openrisc_tr_init_disas_context(DisasContextBase *dcb, CPUState *cs) 1253fcf5ef2aSThomas Huth { 1254a4fd3ec3SEmilio G. Cota DisasContext *dc = container_of(dcb, DisasContext, base); 12559c489ea6SLluís Vilanova CPUOpenRISCState *env = cs->env_ptr; 1256a4fd3ec3SEmilio G. Cota int bound; 1257fcf5ef2aSThomas Huth 1258a4fd3ec3SEmilio G. Cota dc->mem_idx = cpu_mmu_index(env, false); 12591ffa4bceSEmilio G. Cota dc->tb_flags = dc->base.tb->flags; 1260a01deb36SRichard Henderson dc->delayed_branch = (dc->tb_flags & TB_FLAGS_DFLAG) != 0; 12618000ba56SRichard Henderson dc->jmp_pc_imm = -1; 12628000ba56SRichard Henderson 1263a4fd3ec3SEmilio G. Cota bound = -(dc->base.pc_first | TARGET_PAGE_MASK) / 4; 1264a4fd3ec3SEmilio G. Cota dc->base.max_insns = MIN(dc->base.max_insns, bound); 1265fcf5ef2aSThomas Huth } 1266fcf5ef2aSThomas Huth 1267a4fd3ec3SEmilio G. Cota static void openrisc_tr_tb_start(DisasContextBase *db, CPUState *cs) 1268a4fd3ec3SEmilio G. Cota { 1269a4fd3ec3SEmilio G. Cota DisasContext *dc = container_of(db, DisasContext, base); 1270fcf5ef2aSThomas Huth 12716597c28dSRichard Henderson /* Allow the TCG optimizer to see that R0 == 0, 12726597c28dSRichard Henderson when it's true, which is the common case. */ 12736597c28dSRichard Henderson if (dc->tb_flags & TB_FLAGS_R0_0) { 12746597c28dSRichard Henderson cpu_R[0] = tcg_const_tl(0); 12756597c28dSRichard Henderson } else { 12766597c28dSRichard Henderson cpu_R[0] = cpu_R0; 12776597c28dSRichard Henderson } 1278a4fd3ec3SEmilio G. Cota } 12796597c28dSRichard Henderson 1280a4fd3ec3SEmilio G. Cota static void openrisc_tr_insn_start(DisasContextBase *dcbase, CPUState *cs) 1281a4fd3ec3SEmilio G. Cota { 1282a4fd3ec3SEmilio G. Cota DisasContext *dc = container_of(dcbase, DisasContext, base); 1283a4fd3ec3SEmilio G. Cota 12841ffa4bceSEmilio G. Cota tcg_gen_insn_start(dc->base.pc_next, (dc->delayed_branch ? 1 : 0) 1285a4fd3ec3SEmilio G. Cota | (dc->base.num_insns > 1 ? 2 : 0)); 1286a4fd3ec3SEmilio G. Cota } 1287fcf5ef2aSThomas Huth 1288a4fd3ec3SEmilio G. Cota static bool openrisc_tr_breakpoint_check(DisasContextBase *dcbase, CPUState *cs, 1289a4fd3ec3SEmilio G. Cota const CPUBreakpoint *bp) 1290a4fd3ec3SEmilio G. Cota { 1291a4fd3ec3SEmilio G. Cota DisasContext *dc = container_of(dcbase, DisasContext, base); 1292a4fd3ec3SEmilio G. Cota 12931ffa4bceSEmilio G. Cota tcg_gen_movi_tl(cpu_pc, dc->base.pc_next); 1294fcf5ef2aSThomas Huth gen_exception(dc, EXCP_DEBUG); 12951ffa4bceSEmilio G. Cota dc->base.is_jmp = DISAS_NORETURN; 1296fcf5ef2aSThomas Huth /* The address covered by the breakpoint must be included in 1297fcf5ef2aSThomas Huth [tb->pc, tb->pc + tb->size) in order to for it to be 1298fcf5ef2aSThomas Huth properly cleared -- thus we increment the PC here so that 1299fcf5ef2aSThomas Huth the logic setting tb->size below does the right thing. */ 13001ffa4bceSEmilio G. Cota dc->base.pc_next += 4; 1301a4fd3ec3SEmilio G. Cota return true; 1302fcf5ef2aSThomas Huth } 1303fcf5ef2aSThomas Huth 1304a4fd3ec3SEmilio G. Cota static void openrisc_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs) 1305a4fd3ec3SEmilio G. Cota { 1306a4fd3ec3SEmilio G. Cota DisasContext *dc = container_of(dcbase, DisasContext, base); 1307a4fd3ec3SEmilio G. Cota OpenRISCCPU *cpu = OPENRISC_CPU(cs); 1308c7b6f54bSRichard Henderson uint32_t insn = cpu_ldl_code(&cpu->env, dc->base.pc_next); 1309a4fd3ec3SEmilio G. Cota 1310c7b6f54bSRichard Henderson if (!decode(dc, insn)) { 1311c7b6f54bSRichard Henderson gen_illegal_exception(dc); 1312c7b6f54bSRichard Henderson } 13131ffa4bceSEmilio G. Cota dc->base.pc_next += 4; 131424c32852SRichard Henderson 13158000ba56SRichard Henderson /* When exiting the delay slot normally, exit via jmp_pc. 13168000ba56SRichard Henderson * For DISAS_NORETURN, we have raised an exception and already exited. 13178000ba56SRichard Henderson * For DISAS_EXIT, we found l.rfe in a delay slot. There's nothing 13188000ba56SRichard Henderson * in the manual saying this is illegal, but it surely it should. 13198000ba56SRichard Henderson * At least or1ksim overrides pcnext and ignores the branch. 13208000ba56SRichard Henderson */ 13218000ba56SRichard Henderson if (dc->delayed_branch 13228000ba56SRichard Henderson && --dc->delayed_branch == 0 13238000ba56SRichard Henderson && dc->base.is_jmp == DISAS_NEXT) { 13248000ba56SRichard Henderson dc->base.is_jmp = DISAS_JUMP; 1325fcf5ef2aSThomas Huth } 1326a4fd3ec3SEmilio G. Cota } 1327fcf5ef2aSThomas Huth 1328a4fd3ec3SEmilio G. Cota static void openrisc_tr_tb_stop(DisasContextBase *dcbase, CPUState *cs) 1329a4fd3ec3SEmilio G. Cota { 1330a4fd3ec3SEmilio G. Cota DisasContext *dc = container_of(dcbase, DisasContext, base); 13318000ba56SRichard Henderson target_ulong jmp_dest; 133224c32852SRichard Henderson 1333e0a369cfSRichard Henderson /* If we have already exited the TB, nothing following has effect. */ 1334e0a369cfSRichard Henderson if (dc->base.is_jmp == DISAS_NORETURN) { 1335e0a369cfSRichard Henderson return; 1336e0a369cfSRichard Henderson } 1337e0a369cfSRichard Henderson 13388000ba56SRichard Henderson /* Adjust the delayed branch state for the next TB. */ 1339a01deb36SRichard Henderson if ((dc->tb_flags & TB_FLAGS_DFLAG ? 1 : 0) != (dc->delayed_branch != 0)) { 1340a01deb36SRichard Henderson tcg_gen_movi_i32(cpu_dflag, dc->delayed_branch != 0); 1341a01deb36SRichard Henderson } 1342a01deb36SRichard Henderson 13438000ba56SRichard Henderson /* For DISAS_TOO_MANY, jump to the next insn. */ 13448000ba56SRichard Henderson jmp_dest = dc->base.pc_next; 13458000ba56SRichard Henderson tcg_gen_movi_tl(cpu_ppc, jmp_dest - 4); 13468000ba56SRichard Henderson 13471ffa4bceSEmilio G. Cota switch (dc->base.is_jmp) { 13488000ba56SRichard Henderson case DISAS_JUMP: 13498000ba56SRichard Henderson jmp_dest = dc->jmp_pc_imm; 13508000ba56SRichard Henderson if (jmp_dest == -1) { 13518000ba56SRichard Henderson /* The jump destination is indirect/computed; use jmp_pc. */ 13528000ba56SRichard Henderson tcg_gen_mov_tl(cpu_pc, jmp_pc); 13538000ba56SRichard Henderson tcg_gen_discard_tl(jmp_pc); 13548000ba56SRichard Henderson if (unlikely(dc->base.singlestep_enabled)) { 13558000ba56SRichard Henderson gen_exception(dc, EXCP_DEBUG); 13568000ba56SRichard Henderson } else { 13578000ba56SRichard Henderson tcg_gen_lookup_and_goto_ptr(); 13588000ba56SRichard Henderson } 1359fcf5ef2aSThomas Huth break; 13608000ba56SRichard Henderson } 13618000ba56SRichard Henderson /* The jump destination is direct; use jmp_pc_imm. 13628000ba56SRichard Henderson However, we will have stored into jmp_pc as well; 13638000ba56SRichard Henderson we know now that it wasn't needed. */ 13648000ba56SRichard Henderson tcg_gen_discard_tl(jmp_pc); 13658000ba56SRichard Henderson /* fallthru */ 13668000ba56SRichard Henderson 13678000ba56SRichard Henderson case DISAS_TOO_MANY: 13688000ba56SRichard Henderson if (unlikely(dc->base.singlestep_enabled)) { 13698000ba56SRichard Henderson tcg_gen_movi_tl(cpu_pc, jmp_dest); 13708000ba56SRichard Henderson gen_exception(dc, EXCP_DEBUG); 13718000ba56SRichard Henderson } else if ((dc->base.pc_first ^ jmp_dest) & TARGET_PAGE_MASK) { 13728000ba56SRichard Henderson tcg_gen_movi_tl(cpu_pc, jmp_dest); 13738000ba56SRichard Henderson tcg_gen_lookup_and_goto_ptr(); 13748000ba56SRichard Henderson } else { 13758000ba56SRichard Henderson tcg_gen_goto_tb(0); 13768000ba56SRichard Henderson tcg_gen_movi_tl(cpu_pc, jmp_dest); 13778000ba56SRichard Henderson tcg_gen_exit_tb(dc->base.tb, 0); 13788000ba56SRichard Henderson } 13798000ba56SRichard Henderson break; 13808000ba56SRichard Henderson 138164e46c95SRichard Henderson case DISAS_EXIT: 1382e0a369cfSRichard Henderson if (unlikely(dc->base.singlestep_enabled)) { 1383e0a369cfSRichard Henderson gen_exception(dc, EXCP_DEBUG); 1384e0a369cfSRichard Henderson } else { 138507ea28b4SRichard Henderson tcg_gen_exit_tb(NULL, 0); 1386e0a369cfSRichard Henderson } 1387fcf5ef2aSThomas Huth break; 1388a4fd3ec3SEmilio G. Cota default: 1389a4fd3ec3SEmilio G. Cota g_assert_not_reached(); 1390a4fd3ec3SEmilio G. Cota } 1391fcf5ef2aSThomas Huth } 1392fcf5ef2aSThomas Huth 1393a4fd3ec3SEmilio G. Cota static void openrisc_tr_disas_log(const DisasContextBase *dcbase, CPUState *cs) 1394a4fd3ec3SEmilio G. Cota { 1395a4fd3ec3SEmilio G. Cota DisasContext *s = container_of(dcbase, DisasContext, base); 1396fcf5ef2aSThomas Huth 1397a4fd3ec3SEmilio G. Cota qemu_log("IN: %s\n", lookup_symbol(s->base.pc_first)); 1398a4fd3ec3SEmilio G. Cota log_target_disas(cs, s->base.pc_first, s->base.tb->size); 1399fcf5ef2aSThomas Huth } 1400a4fd3ec3SEmilio G. Cota 1401a4fd3ec3SEmilio G. Cota static const TranslatorOps openrisc_tr_ops = { 1402a4fd3ec3SEmilio G. Cota .init_disas_context = openrisc_tr_init_disas_context, 1403a4fd3ec3SEmilio G. Cota .tb_start = openrisc_tr_tb_start, 1404a4fd3ec3SEmilio G. Cota .insn_start = openrisc_tr_insn_start, 1405a4fd3ec3SEmilio G. Cota .breakpoint_check = openrisc_tr_breakpoint_check, 1406a4fd3ec3SEmilio G. Cota .translate_insn = openrisc_tr_translate_insn, 1407a4fd3ec3SEmilio G. Cota .tb_stop = openrisc_tr_tb_stop, 1408a4fd3ec3SEmilio G. Cota .disas_log = openrisc_tr_disas_log, 1409a4fd3ec3SEmilio G. Cota }; 1410a4fd3ec3SEmilio G. Cota 1411a4fd3ec3SEmilio G. Cota void gen_intermediate_code(CPUState *cs, struct TranslationBlock *tb) 1412a4fd3ec3SEmilio G. Cota { 1413a4fd3ec3SEmilio G. Cota DisasContext ctx; 1414a4fd3ec3SEmilio G. Cota 1415a4fd3ec3SEmilio G. Cota translator_loop(&openrisc_tr_ops, &ctx.base, cs, tb); 1416fcf5ef2aSThomas Huth } 1417fcf5ef2aSThomas Huth 1418fcf5ef2aSThomas Huth void openrisc_cpu_dump_state(CPUState *cs, FILE *f, 1419fcf5ef2aSThomas Huth fprintf_function cpu_fprintf, 1420fcf5ef2aSThomas Huth int flags) 1421fcf5ef2aSThomas Huth { 1422fcf5ef2aSThomas Huth OpenRISCCPU *cpu = OPENRISC_CPU(cs); 1423fcf5ef2aSThomas Huth CPUOpenRISCState *env = &cpu->env; 1424fcf5ef2aSThomas Huth int i; 1425fcf5ef2aSThomas Huth 1426fcf5ef2aSThomas Huth cpu_fprintf(f, "PC=%08x\n", env->pc); 1427fcf5ef2aSThomas Huth for (i = 0; i < 32; ++i) { 1428d89e71e8SStafford Horne cpu_fprintf(f, "R%02d=%08x%c", i, cpu_get_gpr(env, i), 1429fcf5ef2aSThomas Huth (i % 4) == 3 ? '\n' : ' '); 1430fcf5ef2aSThomas Huth } 1431fcf5ef2aSThomas Huth } 1432fcf5ef2aSThomas Huth 1433fcf5ef2aSThomas Huth void restore_state_to_opc(CPUOpenRISCState *env, TranslationBlock *tb, 1434fcf5ef2aSThomas Huth target_ulong *data) 1435fcf5ef2aSThomas Huth { 1436fcf5ef2aSThomas Huth env->pc = data[0]; 1437a01deb36SRichard Henderson env->dflag = data[1] & 1; 1438a01deb36SRichard Henderson if (data[1] & 2) { 143924c32852SRichard Henderson env->ppc = env->pc - 4; 144024c32852SRichard Henderson } 1441fcf5ef2aSThomas Huth } 1442