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 10779fc6adSThomas Huth * version 2.1 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/log.h" 27fcf5ef2aSThomas Huth #include "qemu/bitops.h" 2890c84c56SMarkus Armbruster #include "qemu/qemu-print.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 58b9bed1b9SRichard 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; 66*8bba7619SRichard Henderson static TCGv cpu_regs[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++) { 120*8bba7619SRichard Henderson cpu_regs[i] = tcg_global_mem_new(cpu_env, 121d89e71e8SStafford Horne offsetof(CPUOpenRISCState, 122d89e71e8SStafford Horne shadow_gpr[0][i]), 123fcf5ef2aSThomas Huth regnames[i]); 124fcf5ef2aSThomas Huth } 125*8bba7619SRichard Henderson cpu_R0 = cpu_regs[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 166*8bba7619SRichard Henderson static TCGv cpu_R(DisasContext *dc, int reg) 167*8bba7619SRichard Henderson { 168*8bba7619SRichard Henderson return cpu_regs[reg]; 169*8bba7619SRichard Henderson } 170*8bba7619SRichard Henderson 171cdd0f459SRichard Henderson /* 172cdd0f459SRichard Henderson * We're about to write to REG. On the off-chance that the user is 173cdd0f459SRichard Henderson * writing to R0, re-instate the architectural register. 174cdd0f459SRichard Henderson */ 175cdd0f459SRichard Henderson static void check_r0_write(DisasContext *dc, int reg) 176cdd0f459SRichard Henderson { 177cdd0f459SRichard Henderson if (unlikely(reg == 0)) { 178*8bba7619SRichard Henderson cpu_regs[0] = cpu_R0; 179cdd0f459SRichard Henderson } 180cdd0f459SRichard Henderson } 1816597c28dSRichard Henderson 18297458071SRichard Henderson static void gen_ove_cy(DisasContext *dc) 1839ecaa27eSRichard Henderson { 1840c53d734SRichard Henderson if (dc->tb_flags & SR_OVE) { 18597458071SRichard Henderson gen_helper_ove_cy(cpu_env); 1869ecaa27eSRichard Henderson } 1870c53d734SRichard Henderson } 1889ecaa27eSRichard Henderson 18997458071SRichard Henderson static void gen_ove_ov(DisasContext *dc) 1909ecaa27eSRichard Henderson { 1910c53d734SRichard Henderson if (dc->tb_flags & SR_OVE) { 19297458071SRichard Henderson gen_helper_ove_ov(cpu_env); 1939ecaa27eSRichard Henderson } 1940c53d734SRichard Henderson } 1959ecaa27eSRichard Henderson 19697458071SRichard Henderson static void gen_ove_cyov(DisasContext *dc) 1979ecaa27eSRichard Henderson { 1980c53d734SRichard Henderson if (dc->tb_flags & SR_OVE) { 19997458071SRichard Henderson gen_helper_ove_cyov(cpu_env); 2009ecaa27eSRichard Henderson } 2010c53d734SRichard Henderson } 2029ecaa27eSRichard Henderson 2039ecaa27eSRichard Henderson static void gen_add(DisasContext *dc, TCGv dest, TCGv srca, TCGv srcb) 2049ecaa27eSRichard Henderson { 2059ecaa27eSRichard Henderson TCGv t0 = tcg_const_tl(0); 2069ecaa27eSRichard Henderson TCGv res = tcg_temp_new(); 2079ecaa27eSRichard Henderson 20897458071SRichard Henderson tcg_gen_add2_tl(res, cpu_sr_cy, srca, t0, srcb, t0); 20997458071SRichard Henderson tcg_gen_xor_tl(cpu_sr_ov, srca, srcb); 2109ecaa27eSRichard Henderson tcg_gen_xor_tl(t0, res, srcb); 21197458071SRichard Henderson tcg_gen_andc_tl(cpu_sr_ov, t0, cpu_sr_ov); 2129ecaa27eSRichard Henderson tcg_temp_free(t0); 2139ecaa27eSRichard Henderson 2149ecaa27eSRichard Henderson tcg_gen_mov_tl(dest, res); 2159ecaa27eSRichard Henderson tcg_temp_free(res); 2169ecaa27eSRichard Henderson 21797458071SRichard Henderson gen_ove_cyov(dc); 2189ecaa27eSRichard Henderson } 2199ecaa27eSRichard Henderson 2209ecaa27eSRichard Henderson static void gen_addc(DisasContext *dc, TCGv dest, TCGv srca, TCGv srcb) 2219ecaa27eSRichard Henderson { 2229ecaa27eSRichard Henderson TCGv t0 = tcg_const_tl(0); 2239ecaa27eSRichard Henderson TCGv res = tcg_temp_new(); 2249ecaa27eSRichard Henderson 22597458071SRichard Henderson tcg_gen_add2_tl(res, cpu_sr_cy, srca, t0, cpu_sr_cy, t0); 22697458071SRichard Henderson tcg_gen_add2_tl(res, cpu_sr_cy, res, cpu_sr_cy, srcb, t0); 22797458071SRichard Henderson tcg_gen_xor_tl(cpu_sr_ov, srca, srcb); 2289ecaa27eSRichard Henderson tcg_gen_xor_tl(t0, res, srcb); 22997458071SRichard Henderson tcg_gen_andc_tl(cpu_sr_ov, t0, cpu_sr_ov); 2309ecaa27eSRichard Henderson tcg_temp_free(t0); 2319ecaa27eSRichard Henderson 2329ecaa27eSRichard Henderson tcg_gen_mov_tl(dest, res); 2339ecaa27eSRichard Henderson tcg_temp_free(res); 2349ecaa27eSRichard Henderson 23597458071SRichard Henderson gen_ove_cyov(dc); 2369ecaa27eSRichard Henderson } 2379ecaa27eSRichard Henderson 2389ecaa27eSRichard Henderson static void gen_sub(DisasContext *dc, TCGv dest, TCGv srca, TCGv srcb) 2399ecaa27eSRichard Henderson { 2409ecaa27eSRichard Henderson TCGv res = tcg_temp_new(); 2419ecaa27eSRichard Henderson 2429ecaa27eSRichard Henderson tcg_gen_sub_tl(res, srca, srcb); 24397458071SRichard Henderson tcg_gen_xor_tl(cpu_sr_cy, srca, srcb); 24497458071SRichard Henderson tcg_gen_xor_tl(cpu_sr_ov, res, srcb); 24597458071SRichard Henderson tcg_gen_and_tl(cpu_sr_ov, cpu_sr_ov, cpu_sr_cy); 24697458071SRichard Henderson tcg_gen_setcond_tl(TCG_COND_LTU, cpu_sr_cy, srca, srcb); 2479ecaa27eSRichard Henderson 2489ecaa27eSRichard Henderson tcg_gen_mov_tl(dest, res); 2499ecaa27eSRichard Henderson tcg_temp_free(res); 2509ecaa27eSRichard Henderson 25197458071SRichard Henderson gen_ove_cyov(dc); 2529ecaa27eSRichard Henderson } 2539ecaa27eSRichard Henderson 2549ecaa27eSRichard Henderson static void gen_mul(DisasContext *dc, TCGv dest, TCGv srca, TCGv srcb) 2559ecaa27eSRichard Henderson { 2569ecaa27eSRichard Henderson TCGv t0 = tcg_temp_new(); 2579ecaa27eSRichard Henderson 25897458071SRichard Henderson tcg_gen_muls2_tl(dest, cpu_sr_ov, srca, srcb); 2599ecaa27eSRichard Henderson tcg_gen_sari_tl(t0, dest, TARGET_LONG_BITS - 1); 26097458071SRichard Henderson tcg_gen_setcond_tl(TCG_COND_NE, cpu_sr_ov, cpu_sr_ov, t0); 2619ecaa27eSRichard Henderson tcg_temp_free(t0); 2629ecaa27eSRichard Henderson 26397458071SRichard Henderson tcg_gen_neg_tl(cpu_sr_ov, cpu_sr_ov); 26497458071SRichard Henderson gen_ove_ov(dc); 2659ecaa27eSRichard Henderson } 2669ecaa27eSRichard Henderson 2679ecaa27eSRichard Henderson static void gen_mulu(DisasContext *dc, TCGv dest, TCGv srca, TCGv srcb) 2689ecaa27eSRichard Henderson { 26997458071SRichard Henderson tcg_gen_muls2_tl(dest, cpu_sr_cy, srca, srcb); 27097458071SRichard Henderson tcg_gen_setcondi_tl(TCG_COND_NE, cpu_sr_cy, cpu_sr_cy, 0); 2719ecaa27eSRichard Henderson 27297458071SRichard Henderson gen_ove_cy(dc); 2739ecaa27eSRichard Henderson } 2749ecaa27eSRichard Henderson 2759ecaa27eSRichard Henderson static void gen_div(DisasContext *dc, TCGv dest, TCGv srca, TCGv srcb) 2769ecaa27eSRichard Henderson { 2779ecaa27eSRichard Henderson TCGv t0 = tcg_temp_new(); 2789ecaa27eSRichard Henderson 27997458071SRichard Henderson tcg_gen_setcondi_tl(TCG_COND_EQ, cpu_sr_ov, srcb, 0); 2809ecaa27eSRichard Henderson /* The result of divide-by-zero is undefined. 2819ecaa27eSRichard Henderson Supress the host-side exception by dividing by 1. */ 28297458071SRichard Henderson tcg_gen_or_tl(t0, srcb, cpu_sr_ov); 2839ecaa27eSRichard Henderson tcg_gen_div_tl(dest, srca, t0); 2849ecaa27eSRichard Henderson tcg_temp_free(t0); 2859ecaa27eSRichard Henderson 28697458071SRichard Henderson tcg_gen_neg_tl(cpu_sr_ov, cpu_sr_ov); 28797458071SRichard Henderson gen_ove_ov(dc); 2889ecaa27eSRichard Henderson } 2899ecaa27eSRichard Henderson 2909ecaa27eSRichard Henderson static void gen_divu(DisasContext *dc, TCGv dest, TCGv srca, TCGv srcb) 2919ecaa27eSRichard Henderson { 2929ecaa27eSRichard Henderson TCGv t0 = tcg_temp_new(); 2939ecaa27eSRichard Henderson 29497458071SRichard Henderson tcg_gen_setcondi_tl(TCG_COND_EQ, cpu_sr_cy, srcb, 0); 2959ecaa27eSRichard Henderson /* The result of divide-by-zero is undefined. 2969ecaa27eSRichard Henderson Supress the host-side exception by dividing by 1. */ 29797458071SRichard Henderson tcg_gen_or_tl(t0, srcb, cpu_sr_cy); 2989ecaa27eSRichard Henderson tcg_gen_divu_tl(dest, srca, t0); 2999ecaa27eSRichard Henderson tcg_temp_free(t0); 3009ecaa27eSRichard Henderson 30197458071SRichard Henderson gen_ove_cy(dc); 3029ecaa27eSRichard Henderson } 303fcf5ef2aSThomas Huth 304cc5de49eSRichard Henderson static void gen_muld(DisasContext *dc, TCGv srca, TCGv srcb) 305cc5de49eSRichard Henderson { 306cc5de49eSRichard Henderson TCGv_i64 t1 = tcg_temp_new_i64(); 307cc5de49eSRichard Henderson TCGv_i64 t2 = tcg_temp_new_i64(); 308cc5de49eSRichard Henderson 309cc5de49eSRichard Henderson tcg_gen_ext_tl_i64(t1, srca); 310cc5de49eSRichard Henderson tcg_gen_ext_tl_i64(t2, srcb); 311cc5de49eSRichard Henderson if (TARGET_LONG_BITS == 32) { 312cc5de49eSRichard Henderson tcg_gen_mul_i64(cpu_mac, t1, t2); 313cc5de49eSRichard Henderson tcg_gen_movi_tl(cpu_sr_ov, 0); 314cc5de49eSRichard Henderson } else { 315cc5de49eSRichard Henderson TCGv_i64 high = tcg_temp_new_i64(); 316cc5de49eSRichard Henderson 317cc5de49eSRichard Henderson tcg_gen_muls2_i64(cpu_mac, high, t1, t2); 318cc5de49eSRichard Henderson tcg_gen_sari_i64(t1, cpu_mac, 63); 319cc5de49eSRichard Henderson tcg_gen_setcond_i64(TCG_COND_NE, t1, t1, high); 320cc5de49eSRichard Henderson tcg_temp_free_i64(high); 321cc5de49eSRichard Henderson tcg_gen_trunc_i64_tl(cpu_sr_ov, t1); 322cc5de49eSRichard Henderson tcg_gen_neg_tl(cpu_sr_ov, cpu_sr_ov); 323cc5de49eSRichard Henderson 324cc5de49eSRichard Henderson gen_ove_ov(dc); 325cc5de49eSRichard Henderson } 326cc5de49eSRichard Henderson tcg_temp_free_i64(t1); 327cc5de49eSRichard Henderson tcg_temp_free_i64(t2); 328cc5de49eSRichard Henderson } 329cc5de49eSRichard Henderson 330cc5de49eSRichard Henderson static void gen_muldu(DisasContext *dc, TCGv srca, TCGv srcb) 331cc5de49eSRichard Henderson { 332cc5de49eSRichard Henderson TCGv_i64 t1 = tcg_temp_new_i64(); 333cc5de49eSRichard Henderson TCGv_i64 t2 = tcg_temp_new_i64(); 334cc5de49eSRichard Henderson 335cc5de49eSRichard Henderson tcg_gen_extu_tl_i64(t1, srca); 336cc5de49eSRichard Henderson tcg_gen_extu_tl_i64(t2, srcb); 337cc5de49eSRichard Henderson if (TARGET_LONG_BITS == 32) { 338cc5de49eSRichard Henderson tcg_gen_mul_i64(cpu_mac, t1, t2); 339cc5de49eSRichard Henderson tcg_gen_movi_tl(cpu_sr_cy, 0); 340cc5de49eSRichard Henderson } else { 341cc5de49eSRichard Henderson TCGv_i64 high = tcg_temp_new_i64(); 342cc5de49eSRichard Henderson 343cc5de49eSRichard Henderson tcg_gen_mulu2_i64(cpu_mac, high, t1, t2); 344cc5de49eSRichard Henderson tcg_gen_setcondi_i64(TCG_COND_NE, high, high, 0); 345cc5de49eSRichard Henderson tcg_gen_trunc_i64_tl(cpu_sr_cy, high); 346cc5de49eSRichard Henderson tcg_temp_free_i64(high); 347cc5de49eSRichard Henderson 348cc5de49eSRichard Henderson gen_ove_cy(dc); 349cc5de49eSRichard Henderson } 350cc5de49eSRichard Henderson tcg_temp_free_i64(t1); 351cc5de49eSRichard Henderson tcg_temp_free_i64(t2); 352cc5de49eSRichard Henderson } 353cc5de49eSRichard Henderson 3546f7332baSRichard Henderson static void gen_mac(DisasContext *dc, TCGv srca, TCGv srcb) 3556f7332baSRichard Henderson { 3566f7332baSRichard Henderson TCGv_i64 t1 = tcg_temp_new_i64(); 3576f7332baSRichard Henderson TCGv_i64 t2 = tcg_temp_new_i64(); 3586f7332baSRichard Henderson 3596f7332baSRichard Henderson tcg_gen_ext_tl_i64(t1, srca); 3606f7332baSRichard Henderson tcg_gen_ext_tl_i64(t2, srcb); 3616f7332baSRichard Henderson tcg_gen_mul_i64(t1, t1, t2); 3626f7332baSRichard Henderson 3636f7332baSRichard Henderson /* Note that overflow is only computed during addition stage. */ 3646f7332baSRichard Henderson tcg_gen_xor_i64(t2, cpu_mac, t1); 3656f7332baSRichard Henderson tcg_gen_add_i64(cpu_mac, cpu_mac, t1); 3666f7332baSRichard Henderson tcg_gen_xor_i64(t1, t1, cpu_mac); 3676f7332baSRichard Henderson tcg_gen_andc_i64(t1, t1, t2); 3686f7332baSRichard Henderson tcg_temp_free_i64(t2); 3696f7332baSRichard Henderson 3706f7332baSRichard Henderson #if TARGET_LONG_BITS == 32 3716f7332baSRichard Henderson tcg_gen_extrh_i64_i32(cpu_sr_ov, t1); 3726f7332baSRichard Henderson #else 3736f7332baSRichard Henderson tcg_gen_mov_i64(cpu_sr_ov, t1); 3746f7332baSRichard Henderson #endif 3756f7332baSRichard Henderson tcg_temp_free_i64(t1); 3766f7332baSRichard Henderson 3776f7332baSRichard Henderson gen_ove_ov(dc); 3786f7332baSRichard Henderson } 3796f7332baSRichard Henderson 380cc5de49eSRichard Henderson static void gen_macu(DisasContext *dc, TCGv srca, TCGv srcb) 381cc5de49eSRichard Henderson { 382cc5de49eSRichard Henderson TCGv_i64 t1 = tcg_temp_new_i64(); 383cc5de49eSRichard Henderson TCGv_i64 t2 = tcg_temp_new_i64(); 384cc5de49eSRichard Henderson 385cc5de49eSRichard Henderson tcg_gen_extu_tl_i64(t1, srca); 386cc5de49eSRichard Henderson tcg_gen_extu_tl_i64(t2, srcb); 387cc5de49eSRichard Henderson tcg_gen_mul_i64(t1, t1, t2); 388cc5de49eSRichard Henderson tcg_temp_free_i64(t2); 389cc5de49eSRichard Henderson 390cc5de49eSRichard Henderson /* Note that overflow is only computed during addition stage. */ 391cc5de49eSRichard Henderson tcg_gen_add_i64(cpu_mac, cpu_mac, t1); 392cc5de49eSRichard Henderson tcg_gen_setcond_i64(TCG_COND_LTU, t1, cpu_mac, t1); 393cc5de49eSRichard Henderson tcg_gen_trunc_i64_tl(cpu_sr_cy, t1); 394cc5de49eSRichard Henderson tcg_temp_free_i64(t1); 395cc5de49eSRichard Henderson 396cc5de49eSRichard Henderson gen_ove_cy(dc); 397cc5de49eSRichard Henderson } 398cc5de49eSRichard Henderson 3996f7332baSRichard Henderson static void gen_msb(DisasContext *dc, TCGv srca, TCGv srcb) 4006f7332baSRichard Henderson { 4016f7332baSRichard Henderson TCGv_i64 t1 = tcg_temp_new_i64(); 4026f7332baSRichard Henderson TCGv_i64 t2 = tcg_temp_new_i64(); 4036f7332baSRichard Henderson 4046f7332baSRichard Henderson tcg_gen_ext_tl_i64(t1, srca); 4056f7332baSRichard Henderson tcg_gen_ext_tl_i64(t2, srcb); 4066f7332baSRichard Henderson tcg_gen_mul_i64(t1, t1, t2); 4076f7332baSRichard Henderson 4086f7332baSRichard Henderson /* Note that overflow is only computed during subtraction stage. */ 4096f7332baSRichard Henderson tcg_gen_xor_i64(t2, cpu_mac, t1); 4106f7332baSRichard Henderson tcg_gen_sub_i64(cpu_mac, cpu_mac, t1); 4116f7332baSRichard Henderson tcg_gen_xor_i64(t1, t1, cpu_mac); 4126f7332baSRichard Henderson tcg_gen_and_i64(t1, t1, t2); 4136f7332baSRichard Henderson tcg_temp_free_i64(t2); 4146f7332baSRichard Henderson 4156f7332baSRichard Henderson #if TARGET_LONG_BITS == 32 4166f7332baSRichard Henderson tcg_gen_extrh_i64_i32(cpu_sr_ov, t1); 4176f7332baSRichard Henderson #else 4186f7332baSRichard Henderson tcg_gen_mov_i64(cpu_sr_ov, t1); 4196f7332baSRichard Henderson #endif 4206f7332baSRichard Henderson tcg_temp_free_i64(t1); 4216f7332baSRichard Henderson 4226f7332baSRichard Henderson gen_ove_ov(dc); 4236f7332baSRichard Henderson } 4246f7332baSRichard Henderson 425cc5de49eSRichard Henderson static void gen_msbu(DisasContext *dc, TCGv srca, TCGv srcb) 426cc5de49eSRichard Henderson { 427cc5de49eSRichard Henderson TCGv_i64 t1 = tcg_temp_new_i64(); 428cc5de49eSRichard Henderson TCGv_i64 t2 = tcg_temp_new_i64(); 429cc5de49eSRichard Henderson 430cc5de49eSRichard Henderson tcg_gen_extu_tl_i64(t1, srca); 431cc5de49eSRichard Henderson tcg_gen_extu_tl_i64(t2, srcb); 432cc5de49eSRichard Henderson tcg_gen_mul_i64(t1, t1, t2); 433cc5de49eSRichard Henderson 434cc5de49eSRichard Henderson /* Note that overflow is only computed during subtraction stage. */ 435cc5de49eSRichard Henderson tcg_gen_setcond_i64(TCG_COND_LTU, t2, cpu_mac, t1); 436cc5de49eSRichard Henderson tcg_gen_sub_i64(cpu_mac, cpu_mac, t1); 437cc5de49eSRichard Henderson tcg_gen_trunc_i64_tl(cpu_sr_cy, t2); 438cc5de49eSRichard Henderson tcg_temp_free_i64(t2); 439cc5de49eSRichard Henderson tcg_temp_free_i64(t1); 440cc5de49eSRichard Henderson 441cc5de49eSRichard Henderson gen_ove_cy(dc); 442cc5de49eSRichard Henderson } 443cc5de49eSRichard Henderson 4443a7be554SRichard Henderson static bool trans_l_add(DisasContext *dc, arg_dab *a) 445fcf5ef2aSThomas Huth { 446cdd0f459SRichard Henderson check_r0_write(dc, a->d); 447*8bba7619SRichard Henderson gen_add(dc, cpu_R(dc, a->d), cpu_R(dc, a->a), cpu_R(dc, a->b)); 4486ad216abSRichard Henderson return true; 449fcf5ef2aSThomas Huth } 450fcf5ef2aSThomas Huth 4513a7be554SRichard Henderson static bool trans_l_addc(DisasContext *dc, arg_dab *a) 452fcf5ef2aSThomas Huth { 453cdd0f459SRichard Henderson check_r0_write(dc, a->d); 454*8bba7619SRichard Henderson gen_addc(dc, cpu_R(dc, a->d), cpu_R(dc, a->a), cpu_R(dc, a->b)); 4556ad216abSRichard Henderson return true; 4566ad216abSRichard Henderson } 4576ad216abSRichard Henderson 4583a7be554SRichard Henderson static bool trans_l_sub(DisasContext *dc, arg_dab *a) 4596ad216abSRichard Henderson { 460cdd0f459SRichard Henderson check_r0_write(dc, a->d); 461*8bba7619SRichard Henderson gen_sub(dc, cpu_R(dc, a->d), cpu_R(dc, a->a), cpu_R(dc, a->b)); 4626ad216abSRichard Henderson return true; 4636ad216abSRichard Henderson } 4646ad216abSRichard Henderson 4653a7be554SRichard Henderson static bool trans_l_and(DisasContext *dc, arg_dab *a) 4666ad216abSRichard Henderson { 467cdd0f459SRichard Henderson check_r0_write(dc, a->d); 468*8bba7619SRichard Henderson tcg_gen_and_tl(cpu_R(dc, a->d), cpu_R(dc, a->a), cpu_R(dc, a->b)); 4696ad216abSRichard Henderson return true; 4706ad216abSRichard Henderson } 4716ad216abSRichard Henderson 4723a7be554SRichard Henderson static bool trans_l_or(DisasContext *dc, arg_dab *a) 4736ad216abSRichard Henderson { 474cdd0f459SRichard Henderson check_r0_write(dc, a->d); 475*8bba7619SRichard Henderson tcg_gen_or_tl(cpu_R(dc, a->d), cpu_R(dc, a->a), cpu_R(dc, a->b)); 4766ad216abSRichard Henderson return true; 4776ad216abSRichard Henderson } 4786ad216abSRichard Henderson 4793a7be554SRichard Henderson static bool trans_l_xor(DisasContext *dc, arg_dab *a) 4806ad216abSRichard Henderson { 481cdd0f459SRichard Henderson check_r0_write(dc, a->d); 482*8bba7619SRichard Henderson tcg_gen_xor_tl(cpu_R(dc, a->d), cpu_R(dc, a->a), cpu_R(dc, a->b)); 4836ad216abSRichard Henderson return true; 4846ad216abSRichard Henderson } 4856ad216abSRichard Henderson 4863a7be554SRichard Henderson static bool trans_l_sll(DisasContext *dc, arg_dab *a) 4876ad216abSRichard Henderson { 488cdd0f459SRichard Henderson check_r0_write(dc, a->d); 489*8bba7619SRichard Henderson tcg_gen_shl_tl(cpu_R(dc, a->d), cpu_R(dc, a->a), cpu_R(dc, a->b)); 4906ad216abSRichard Henderson return true; 4916ad216abSRichard Henderson } 4926ad216abSRichard Henderson 4933a7be554SRichard Henderson static bool trans_l_srl(DisasContext *dc, arg_dab *a) 4946ad216abSRichard Henderson { 495cdd0f459SRichard Henderson check_r0_write(dc, a->d); 496*8bba7619SRichard Henderson tcg_gen_shr_tl(cpu_R(dc, a->d), cpu_R(dc, a->a), cpu_R(dc, a->b)); 4976ad216abSRichard Henderson return true; 4986ad216abSRichard Henderson } 4996ad216abSRichard Henderson 5003a7be554SRichard Henderson static bool trans_l_sra(DisasContext *dc, arg_dab *a) 5016ad216abSRichard Henderson { 502cdd0f459SRichard Henderson check_r0_write(dc, a->d); 503*8bba7619SRichard Henderson tcg_gen_sar_tl(cpu_R(dc, a->d), cpu_R(dc, a->a), cpu_R(dc, a->b)); 5046ad216abSRichard Henderson return true; 5056ad216abSRichard Henderson } 5066ad216abSRichard Henderson 5073a7be554SRichard Henderson static bool trans_l_ror(DisasContext *dc, arg_dab *a) 5086ad216abSRichard Henderson { 509cdd0f459SRichard Henderson check_r0_write(dc, a->d); 510*8bba7619SRichard Henderson tcg_gen_rotr_tl(cpu_R(dc, a->d), cpu_R(dc, a->a), cpu_R(dc, a->b)); 5116ad216abSRichard Henderson return true; 5126ad216abSRichard Henderson } 5136ad216abSRichard Henderson 5143a7be554SRichard Henderson static bool trans_l_exths(DisasContext *dc, arg_da *a) 5156ad216abSRichard Henderson { 516cdd0f459SRichard Henderson check_r0_write(dc, a->d); 517*8bba7619SRichard Henderson tcg_gen_ext16s_tl(cpu_R(dc, a->d), cpu_R(dc, a->a)); 5186ad216abSRichard Henderson return true; 5196ad216abSRichard Henderson } 5206ad216abSRichard Henderson 5213a7be554SRichard Henderson static bool trans_l_extbs(DisasContext *dc, arg_da *a) 5226ad216abSRichard Henderson { 523cdd0f459SRichard Henderson check_r0_write(dc, a->d); 524*8bba7619SRichard Henderson tcg_gen_ext8s_tl(cpu_R(dc, a->d), cpu_R(dc, a->a)); 5256ad216abSRichard Henderson return true; 5266ad216abSRichard Henderson } 5276ad216abSRichard Henderson 5283a7be554SRichard Henderson static bool trans_l_exthz(DisasContext *dc, arg_da *a) 5296ad216abSRichard Henderson { 530cdd0f459SRichard Henderson check_r0_write(dc, a->d); 531*8bba7619SRichard Henderson tcg_gen_ext16u_tl(cpu_R(dc, a->d), cpu_R(dc, a->a)); 5326ad216abSRichard Henderson return true; 5336ad216abSRichard Henderson } 5346ad216abSRichard Henderson 5353a7be554SRichard Henderson static bool trans_l_extbz(DisasContext *dc, arg_da *a) 5366ad216abSRichard Henderson { 537cdd0f459SRichard Henderson check_r0_write(dc, a->d); 538*8bba7619SRichard Henderson tcg_gen_ext8u_tl(cpu_R(dc, a->d), cpu_R(dc, a->a)); 5396ad216abSRichard Henderson return true; 5406ad216abSRichard Henderson } 5416ad216abSRichard Henderson 5423a7be554SRichard Henderson static bool trans_l_cmov(DisasContext *dc, arg_dab *a) 5436ad216abSRichard Henderson { 5446ad216abSRichard Henderson TCGv zero; 5456ad216abSRichard Henderson 546cdd0f459SRichard Henderson check_r0_write(dc, a->d); 5476ad216abSRichard Henderson zero = tcg_const_tl(0); 548*8bba7619SRichard Henderson tcg_gen_movcond_tl(TCG_COND_NE, cpu_R(dc, a->d), cpu_sr_f, zero, 549*8bba7619SRichard Henderson cpu_R(dc, a->a), cpu_R(dc, a->b)); 550784696d1SRichard Henderson tcg_temp_free(zero); 5516ad216abSRichard Henderson return true; 552fcf5ef2aSThomas Huth } 553fcf5ef2aSThomas Huth 5543a7be554SRichard Henderson static bool trans_l_ff1(DisasContext *dc, arg_da *a) 5556ad216abSRichard Henderson { 556cdd0f459SRichard Henderson check_r0_write(dc, a->d); 557*8bba7619SRichard Henderson tcg_gen_ctzi_tl(cpu_R(dc, a->d), cpu_R(dc, a->a), -1); 558*8bba7619SRichard Henderson tcg_gen_addi_tl(cpu_R(dc, a->d), cpu_R(dc, a->d), 1); 5596ad216abSRichard Henderson return true; 560cf2ae442SRichard Henderson } 561cf2ae442SRichard Henderson 5623a7be554SRichard Henderson static bool trans_l_fl1(DisasContext *dc, arg_da *a) 5636ad216abSRichard Henderson { 564cdd0f459SRichard Henderson check_r0_write(dc, a->d); 565*8bba7619SRichard Henderson tcg_gen_clzi_tl(cpu_R(dc, a->d), cpu_R(dc, a->a), TARGET_LONG_BITS); 566*8bba7619SRichard Henderson tcg_gen_subfi_tl(cpu_R(dc, a->d), TARGET_LONG_BITS, cpu_R(dc, a->d)); 5676ad216abSRichard Henderson return true; 568fcf5ef2aSThomas Huth } 569fcf5ef2aSThomas Huth 5703a7be554SRichard Henderson static bool trans_l_mul(DisasContext *dc, arg_dab *a) 5716ad216abSRichard Henderson { 572cdd0f459SRichard Henderson check_r0_write(dc, a->d); 573*8bba7619SRichard Henderson gen_mul(dc, cpu_R(dc, a->d), cpu_R(dc, a->a), cpu_R(dc, a->b)); 5746ad216abSRichard Henderson return true; 575fcf5ef2aSThomas Huth } 5766ad216abSRichard Henderson 5773a7be554SRichard Henderson static bool trans_l_mulu(DisasContext *dc, arg_dab *a) 5786ad216abSRichard Henderson { 579cdd0f459SRichard Henderson check_r0_write(dc, a->d); 580*8bba7619SRichard Henderson gen_mulu(dc, cpu_R(dc, a->d), cpu_R(dc, a->a), cpu_R(dc, a->b)); 5816ad216abSRichard Henderson return true; 582fcf5ef2aSThomas Huth } 5836ad216abSRichard Henderson 5843a7be554SRichard Henderson static bool trans_l_div(DisasContext *dc, arg_dab *a) 5856ad216abSRichard Henderson { 586cdd0f459SRichard Henderson check_r0_write(dc, a->d); 587*8bba7619SRichard Henderson gen_div(dc, cpu_R(dc, a->d), cpu_R(dc, a->a), cpu_R(dc, a->b)); 5886ad216abSRichard Henderson return true; 5896ad216abSRichard Henderson } 5906ad216abSRichard Henderson 5913a7be554SRichard Henderson static bool trans_l_divu(DisasContext *dc, arg_dab *a) 5926ad216abSRichard Henderson { 593cdd0f459SRichard Henderson check_r0_write(dc, a->d); 594*8bba7619SRichard Henderson gen_divu(dc, cpu_R(dc, a->d), cpu_R(dc, a->a), cpu_R(dc, a->b)); 5956ad216abSRichard Henderson return true; 5966ad216abSRichard Henderson } 5976ad216abSRichard Henderson 5983a7be554SRichard Henderson static bool trans_l_muld(DisasContext *dc, arg_ab *a) 5996ad216abSRichard Henderson { 600*8bba7619SRichard Henderson gen_muld(dc, cpu_R(dc, a->a), cpu_R(dc, a->b)); 6016ad216abSRichard Henderson return true; 6026ad216abSRichard Henderson } 6036ad216abSRichard Henderson 6043a7be554SRichard Henderson static bool trans_l_muldu(DisasContext *dc, arg_ab *a) 6056ad216abSRichard Henderson { 606*8bba7619SRichard Henderson gen_muldu(dc, cpu_R(dc, a->a), cpu_R(dc, a->b)); 6076ad216abSRichard Henderson return true; 608fcf5ef2aSThomas Huth } 609fcf5ef2aSThomas Huth 6103a7be554SRichard Henderson static bool trans_l_j(DisasContext *dc, arg_l_j *a) 611136e13aeSRichard Henderson { 612136e13aeSRichard Henderson target_ulong tmp_pc = dc->base.pc_next + a->n * 4; 613136e13aeSRichard Henderson 614136e13aeSRichard Henderson tcg_gen_movi_tl(jmp_pc, tmp_pc); 6158000ba56SRichard Henderson dc->jmp_pc_imm = tmp_pc; 616136e13aeSRichard Henderson dc->delayed_branch = 2; 617136e13aeSRichard Henderson return true; 618136e13aeSRichard Henderson } 619136e13aeSRichard Henderson 6203a7be554SRichard Henderson static bool trans_l_jal(DisasContext *dc, arg_l_jal *a) 621136e13aeSRichard Henderson { 622136e13aeSRichard Henderson target_ulong tmp_pc = dc->base.pc_next + a->n * 4; 623136e13aeSRichard Henderson target_ulong ret_pc = dc->base.pc_next + 8; 624136e13aeSRichard Henderson 625*8bba7619SRichard Henderson tcg_gen_movi_tl(cpu_regs[9], ret_pc); 626136e13aeSRichard Henderson /* Optimize jal being used to load the PC for PIC. */ 627136e13aeSRichard Henderson if (tmp_pc != ret_pc) { 628136e13aeSRichard Henderson tcg_gen_movi_tl(jmp_pc, tmp_pc); 6298000ba56SRichard Henderson dc->jmp_pc_imm = tmp_pc; 630136e13aeSRichard Henderson dc->delayed_branch = 2; 631136e13aeSRichard Henderson } 632136e13aeSRichard Henderson return true; 633136e13aeSRichard Henderson } 634136e13aeSRichard Henderson 635136e13aeSRichard Henderson static void do_bf(DisasContext *dc, arg_l_bf *a, TCGCond cond) 636136e13aeSRichard Henderson { 637136e13aeSRichard Henderson target_ulong tmp_pc = dc->base.pc_next + a->n * 4; 638136e13aeSRichard Henderson TCGv t_next = tcg_const_tl(dc->base.pc_next + 8); 639136e13aeSRichard Henderson TCGv t_true = tcg_const_tl(tmp_pc); 640136e13aeSRichard Henderson TCGv t_zero = tcg_const_tl(0); 641136e13aeSRichard Henderson 642136e13aeSRichard Henderson tcg_gen_movcond_tl(cond, jmp_pc, cpu_sr_f, t_zero, t_true, t_next); 643136e13aeSRichard Henderson 644136e13aeSRichard Henderson tcg_temp_free(t_next); 645136e13aeSRichard Henderson tcg_temp_free(t_true); 646136e13aeSRichard Henderson tcg_temp_free(t_zero); 647136e13aeSRichard Henderson dc->delayed_branch = 2; 648136e13aeSRichard Henderson } 649136e13aeSRichard Henderson 6503a7be554SRichard Henderson static bool trans_l_bf(DisasContext *dc, arg_l_bf *a) 651136e13aeSRichard Henderson { 652136e13aeSRichard Henderson do_bf(dc, a, TCG_COND_NE); 653136e13aeSRichard Henderson return true; 654136e13aeSRichard Henderson } 655136e13aeSRichard Henderson 6563a7be554SRichard Henderson static bool trans_l_bnf(DisasContext *dc, arg_l_bf *a) 657136e13aeSRichard Henderson { 658136e13aeSRichard Henderson do_bf(dc, a, TCG_COND_EQ); 659136e13aeSRichard Henderson return true; 660136e13aeSRichard Henderson } 661136e13aeSRichard Henderson 6623a7be554SRichard Henderson static bool trans_l_jr(DisasContext *dc, arg_l_jr *a) 663136e13aeSRichard Henderson { 664*8bba7619SRichard Henderson tcg_gen_mov_tl(jmp_pc, cpu_R(dc, a->b)); 665136e13aeSRichard Henderson dc->delayed_branch = 2; 666136e13aeSRichard Henderson return true; 667136e13aeSRichard Henderson } 668136e13aeSRichard Henderson 6693a7be554SRichard Henderson static bool trans_l_jalr(DisasContext *dc, arg_l_jalr *a) 670136e13aeSRichard Henderson { 671*8bba7619SRichard Henderson tcg_gen_mov_tl(jmp_pc, cpu_R(dc, a->b)); 672*8bba7619SRichard Henderson tcg_gen_movi_tl(cpu_regs[9], dc->base.pc_next + 8); 673136e13aeSRichard Henderson dc->delayed_branch = 2; 674136e13aeSRichard Henderson return true; 675136e13aeSRichard Henderson } 676136e13aeSRichard Henderson 6773a7be554SRichard Henderson static bool trans_l_lwa(DisasContext *dc, arg_load *a) 678d80bff19SRichard Henderson { 679d80bff19SRichard Henderson TCGv ea; 680d80bff19SRichard Henderson 681cdd0f459SRichard Henderson check_r0_write(dc, a->d); 682d80bff19SRichard Henderson ea = tcg_temp_new(); 683*8bba7619SRichard Henderson tcg_gen_addi_tl(ea, cpu_R(dc, a->a), a->i); 684*8bba7619SRichard Henderson tcg_gen_qemu_ld_tl(cpu_R(dc, a->d), ea, dc->mem_idx, MO_TEUL); 685d80bff19SRichard Henderson tcg_gen_mov_tl(cpu_lock_addr, ea); 686*8bba7619SRichard Henderson tcg_gen_mov_tl(cpu_lock_value, cpu_R(dc, a->d)); 687d80bff19SRichard Henderson tcg_temp_free(ea); 688d80bff19SRichard Henderson return true; 689d80bff19SRichard Henderson } 690d80bff19SRichard Henderson 69114776ab5STony Nguyen static void do_load(DisasContext *dc, arg_load *a, MemOp mop) 692d80bff19SRichard Henderson { 693d80bff19SRichard Henderson TCGv ea; 694d80bff19SRichard Henderson 695cdd0f459SRichard Henderson check_r0_write(dc, a->d); 696d80bff19SRichard Henderson ea = tcg_temp_new(); 697*8bba7619SRichard Henderson tcg_gen_addi_tl(ea, cpu_R(dc, a->a), a->i); 698*8bba7619SRichard Henderson tcg_gen_qemu_ld_tl(cpu_R(dc, a->d), ea, dc->mem_idx, mop); 699d80bff19SRichard Henderson tcg_temp_free(ea); 700d80bff19SRichard Henderson } 701d80bff19SRichard Henderson 7023a7be554SRichard Henderson static bool trans_l_lwz(DisasContext *dc, arg_load *a) 703d80bff19SRichard Henderson { 704d80bff19SRichard Henderson do_load(dc, a, MO_TEUL); 705d80bff19SRichard Henderson return true; 706d80bff19SRichard Henderson } 707d80bff19SRichard Henderson 7083a7be554SRichard Henderson static bool trans_l_lws(DisasContext *dc, arg_load *a) 709d80bff19SRichard Henderson { 710d80bff19SRichard Henderson do_load(dc, a, MO_TESL); 711d80bff19SRichard Henderson return true; 712d80bff19SRichard Henderson } 713d80bff19SRichard Henderson 7143a7be554SRichard Henderson static bool trans_l_lbz(DisasContext *dc, arg_load *a) 715d80bff19SRichard Henderson { 716d80bff19SRichard Henderson do_load(dc, a, MO_UB); 717d80bff19SRichard Henderson return true; 718d80bff19SRichard Henderson } 719d80bff19SRichard Henderson 7203a7be554SRichard Henderson static bool trans_l_lbs(DisasContext *dc, arg_load *a) 721d80bff19SRichard Henderson { 722d80bff19SRichard Henderson do_load(dc, a, MO_SB); 723d80bff19SRichard Henderson return true; 724d80bff19SRichard Henderson } 725d80bff19SRichard Henderson 7263a7be554SRichard Henderson static bool trans_l_lhz(DisasContext *dc, arg_load *a) 727d80bff19SRichard Henderson { 728d80bff19SRichard Henderson do_load(dc, a, MO_TEUW); 729d80bff19SRichard Henderson return true; 730d80bff19SRichard Henderson } 731d80bff19SRichard Henderson 7323a7be554SRichard Henderson static bool trans_l_lhs(DisasContext *dc, arg_load *a) 733d80bff19SRichard Henderson { 734d80bff19SRichard Henderson do_load(dc, a, MO_TESW); 735d80bff19SRichard Henderson return true; 736d80bff19SRichard Henderson } 737d80bff19SRichard Henderson 7383a7be554SRichard Henderson static bool trans_l_swa(DisasContext *dc, arg_store *a) 739d80bff19SRichard Henderson { 740d80bff19SRichard Henderson TCGv ea, val; 741d80bff19SRichard Henderson TCGLabel *lab_fail, *lab_done; 742d80bff19SRichard Henderson 743d80bff19SRichard Henderson ea = tcg_temp_new(); 744*8bba7619SRichard Henderson tcg_gen_addi_tl(ea, cpu_R(dc, a->a), a->i); 745d80bff19SRichard Henderson 746d80bff19SRichard Henderson /* For TB_FLAGS_R0_0, the branch below invalidates the temporary assigned 747*8bba7619SRichard Henderson to cpu_regs[0]. Since l.swa is quite often immediately followed by a 748d80bff19SRichard Henderson branch, don't bother reallocating; finish the TB using the "real" R0. 749d80bff19SRichard Henderson This also takes care of RB input across the branch. */ 750*8bba7619SRichard Henderson cpu_regs[0] = cpu_R0; 751d80bff19SRichard Henderson 752d80bff19SRichard Henderson lab_fail = gen_new_label(); 753d80bff19SRichard Henderson lab_done = gen_new_label(); 754d80bff19SRichard Henderson tcg_gen_brcond_tl(TCG_COND_NE, ea, cpu_lock_addr, lab_fail); 755d80bff19SRichard Henderson tcg_temp_free(ea); 756d80bff19SRichard Henderson 757d80bff19SRichard Henderson val = tcg_temp_new(); 758d80bff19SRichard Henderson tcg_gen_atomic_cmpxchg_tl(val, cpu_lock_addr, cpu_lock_value, 759*8bba7619SRichard Henderson cpu_regs[a->b], dc->mem_idx, MO_TEUL); 760d80bff19SRichard Henderson tcg_gen_setcond_tl(TCG_COND_EQ, cpu_sr_f, val, cpu_lock_value); 761d80bff19SRichard Henderson tcg_temp_free(val); 762d80bff19SRichard Henderson 763d80bff19SRichard Henderson tcg_gen_br(lab_done); 764d80bff19SRichard Henderson 765d80bff19SRichard Henderson gen_set_label(lab_fail); 766d80bff19SRichard Henderson tcg_gen_movi_tl(cpu_sr_f, 0); 767d80bff19SRichard Henderson 768d80bff19SRichard Henderson gen_set_label(lab_done); 769d80bff19SRichard Henderson tcg_gen_movi_tl(cpu_lock_addr, -1); 770d80bff19SRichard Henderson return true; 771d80bff19SRichard Henderson } 772d80bff19SRichard Henderson 77314776ab5STony Nguyen static void do_store(DisasContext *dc, arg_store *a, MemOp mop) 774d80bff19SRichard Henderson { 775d80bff19SRichard Henderson TCGv t0 = tcg_temp_new(); 776*8bba7619SRichard Henderson tcg_gen_addi_tl(t0, cpu_R(dc, a->a), a->i); 777*8bba7619SRichard Henderson tcg_gen_qemu_st_tl(cpu_R(dc, a->b), t0, dc->mem_idx, mop); 778d80bff19SRichard Henderson tcg_temp_free(t0); 779d80bff19SRichard Henderson } 780d80bff19SRichard Henderson 7813a7be554SRichard Henderson static bool trans_l_sw(DisasContext *dc, arg_store *a) 782d80bff19SRichard Henderson { 783d80bff19SRichard Henderson do_store(dc, a, MO_TEUL); 784d80bff19SRichard Henderson return true; 785d80bff19SRichard Henderson } 786d80bff19SRichard Henderson 7873a7be554SRichard Henderson static bool trans_l_sb(DisasContext *dc, arg_store *a) 788d80bff19SRichard Henderson { 789d80bff19SRichard Henderson do_store(dc, a, MO_UB); 790d80bff19SRichard Henderson return true; 791d80bff19SRichard Henderson } 792d80bff19SRichard Henderson 7933a7be554SRichard Henderson static bool trans_l_sh(DisasContext *dc, arg_store *a) 794d80bff19SRichard Henderson { 795d80bff19SRichard Henderson do_store(dc, a, MO_TEUW); 796d80bff19SRichard Henderson return true; 797d80bff19SRichard Henderson } 798d80bff19SRichard Henderson 7993a7be554SRichard Henderson static bool trans_l_nop(DisasContext *dc, arg_l_nop *a) 800fcf5ef2aSThomas Huth { 8018816f70bSRichard Henderson return true; 8028816f70bSRichard Henderson } 8038816f70bSRichard Henderson 8043a7be554SRichard Henderson static bool trans_l_addi(DisasContext *dc, arg_rri *a) 8058816f70bSRichard Henderson { 8069ecaa27eSRichard Henderson TCGv t0; 807fcf5ef2aSThomas Huth 808cdd0f459SRichard Henderson check_r0_write(dc, a->d); 8098816f70bSRichard Henderson t0 = tcg_const_tl(a->i); 810*8bba7619SRichard Henderson gen_add(dc, cpu_R(dc, a->d), cpu_R(dc, a->a), t0); 8116f7332baSRichard Henderson tcg_temp_free(t0); 8128816f70bSRichard Henderson return true; 8138816f70bSRichard Henderson } 814fcf5ef2aSThomas Huth 8153a7be554SRichard Henderson static bool trans_l_addic(DisasContext *dc, arg_rri *a) 816fcf5ef2aSThomas Huth { 8178816f70bSRichard Henderson TCGv t0; 8188816f70bSRichard Henderson 819cdd0f459SRichard Henderson check_r0_write(dc, a->d); 8208816f70bSRichard Henderson t0 = tcg_const_tl(a->i); 821*8bba7619SRichard Henderson gen_addc(dc, cpu_R(dc, a->d), cpu_R(dc, a->a), t0); 8228816f70bSRichard Henderson tcg_temp_free(t0); 8238816f70bSRichard Henderson return true; 8248816f70bSRichard Henderson } 8258816f70bSRichard Henderson 8263a7be554SRichard Henderson static bool trans_l_muli(DisasContext *dc, arg_rri *a) 8278816f70bSRichard Henderson { 8288816f70bSRichard Henderson TCGv t0; 8298816f70bSRichard Henderson 830cdd0f459SRichard Henderson check_r0_write(dc, a->d); 8318816f70bSRichard Henderson t0 = tcg_const_tl(a->i); 832*8bba7619SRichard Henderson gen_mul(dc, cpu_R(dc, a->d), cpu_R(dc, a->a), t0); 8338816f70bSRichard Henderson tcg_temp_free(t0); 8348816f70bSRichard Henderson return true; 8358816f70bSRichard Henderson } 8368816f70bSRichard Henderson 8373a7be554SRichard Henderson static bool trans_l_maci(DisasContext *dc, arg_l_maci *a) 8388816f70bSRichard Henderson { 8398816f70bSRichard Henderson TCGv t0; 8408816f70bSRichard Henderson 8418816f70bSRichard Henderson t0 = tcg_const_tl(a->i); 842*8bba7619SRichard Henderson gen_mac(dc, cpu_R(dc, a->a), t0); 8438816f70bSRichard Henderson tcg_temp_free(t0); 8448816f70bSRichard Henderson return true; 8458816f70bSRichard Henderson } 8468816f70bSRichard Henderson 8473a7be554SRichard Henderson static bool trans_l_andi(DisasContext *dc, arg_rrk *a) 8488816f70bSRichard Henderson { 849cdd0f459SRichard Henderson check_r0_write(dc, a->d); 850*8bba7619SRichard Henderson tcg_gen_andi_tl(cpu_R(dc, a->d), cpu_R(dc, a->a), a->k); 8518816f70bSRichard Henderson return true; 8528816f70bSRichard Henderson } 8538816f70bSRichard Henderson 8543a7be554SRichard Henderson static bool trans_l_ori(DisasContext *dc, arg_rrk *a) 8558816f70bSRichard Henderson { 856cdd0f459SRichard Henderson check_r0_write(dc, a->d); 857*8bba7619SRichard Henderson tcg_gen_ori_tl(cpu_R(dc, a->d), cpu_R(dc, a->a), a->k); 8588816f70bSRichard Henderson return true; 8598816f70bSRichard Henderson } 8608816f70bSRichard Henderson 8613a7be554SRichard Henderson static bool trans_l_xori(DisasContext *dc, arg_rri *a) 8628816f70bSRichard Henderson { 863cdd0f459SRichard Henderson check_r0_write(dc, a->d); 864*8bba7619SRichard Henderson tcg_gen_xori_tl(cpu_R(dc, a->d), cpu_R(dc, a->a), a->i); 8658816f70bSRichard Henderson return true; 8668816f70bSRichard Henderson } 8678816f70bSRichard Henderson 8683a7be554SRichard Henderson static bool trans_l_mfspr(DisasContext *dc, arg_l_mfspr *a) 8698816f70bSRichard Henderson { 870cdd0f459SRichard Henderson check_r0_write(dc, a->d); 8718816f70bSRichard Henderson 8722ba65417SRichard Henderson if (is_user(dc)) { 873fcf5ef2aSThomas Huth gen_illegal_exception(dc); 8748816f70bSRichard Henderson } else { 875c28fa81fSRichard Henderson TCGv spr = tcg_temp_new(); 876*8bba7619SRichard Henderson tcg_gen_ori_tl(spr, cpu_R(dc, a->a), a->k); 877*8bba7619SRichard Henderson gen_helper_mfspr(cpu_R(dc, a->d), cpu_env, cpu_R(dc, a->d), spr); 878c28fa81fSRichard Henderson tcg_temp_free(spr); 879fcf5ef2aSThomas Huth } 8808816f70bSRichard Henderson return true; 8818816f70bSRichard Henderson } 882fcf5ef2aSThomas Huth 8833a7be554SRichard Henderson static bool trans_l_mtspr(DisasContext *dc, arg_l_mtspr *a) 884fcf5ef2aSThomas Huth { 8852ba65417SRichard Henderson if (is_user(dc)) { 886fcf5ef2aSThomas Huth gen_illegal_exception(dc); 8878816f70bSRichard Henderson } else { 888c28fa81fSRichard Henderson TCGv spr; 88901ec3ec9SRichard Henderson 89001ec3ec9SRichard Henderson /* For SR, we will need to exit the TB to recognize the new 89101ec3ec9SRichard Henderson * exception state. For NPC, in theory this counts as a branch 89201ec3ec9SRichard Henderson * (although the SPR only exists for use by an ICE). Save all 89301ec3ec9SRichard Henderson * of the cpu state first, allowing it to be overwritten. 89401ec3ec9SRichard Henderson */ 89501ec3ec9SRichard Henderson if (dc->delayed_branch) { 89601ec3ec9SRichard Henderson tcg_gen_mov_tl(cpu_pc, jmp_pc); 89701ec3ec9SRichard Henderson tcg_gen_discard_tl(jmp_pc); 89801ec3ec9SRichard Henderson } else { 89901ec3ec9SRichard Henderson tcg_gen_movi_tl(cpu_pc, dc->base.pc_next + 4); 90001ec3ec9SRichard Henderson } 90101ec3ec9SRichard Henderson dc->base.is_jmp = DISAS_EXIT; 90201ec3ec9SRichard Henderson 903c28fa81fSRichard Henderson spr = tcg_temp_new(); 904*8bba7619SRichard Henderson tcg_gen_ori_tl(spr, cpu_R(dc, a->a), a->k); 905*8bba7619SRichard Henderson gen_helper_mtspr(cpu_env, spr, cpu_R(dc, a->b)); 906c28fa81fSRichard Henderson tcg_temp_free(spr); 907fcf5ef2aSThomas Huth } 9088816f70bSRichard Henderson return true; 909fcf5ef2aSThomas Huth } 910fcf5ef2aSThomas Huth 9113a7be554SRichard Henderson static bool trans_l_mac(DisasContext *dc, arg_ab *a) 912fcf5ef2aSThomas Huth { 913*8bba7619SRichard Henderson gen_mac(dc, cpu_R(dc, a->a), cpu_R(dc, a->b)); 91499d863d6SRichard Henderson return true; 915fcf5ef2aSThomas Huth } 91699d863d6SRichard Henderson 9173a7be554SRichard Henderson static bool trans_l_msb(DisasContext *dc, arg_ab *a) 91899d863d6SRichard Henderson { 919*8bba7619SRichard Henderson gen_msb(dc, cpu_R(dc, a->a), cpu_R(dc, a->b)); 92099d863d6SRichard Henderson return true; 92199d863d6SRichard Henderson } 92299d863d6SRichard Henderson 9233a7be554SRichard Henderson static bool trans_l_macu(DisasContext *dc, arg_ab *a) 92499d863d6SRichard Henderson { 925*8bba7619SRichard Henderson gen_macu(dc, cpu_R(dc, a->a), cpu_R(dc, a->b)); 92699d863d6SRichard Henderson return true; 92799d863d6SRichard Henderson } 92899d863d6SRichard Henderson 9293a7be554SRichard Henderson static bool trans_l_msbu(DisasContext *dc, arg_ab *a) 93099d863d6SRichard Henderson { 931*8bba7619SRichard Henderson gen_msbu(dc, cpu_R(dc, a->a), cpu_R(dc, a->b)); 93299d863d6SRichard Henderson return true; 933fcf5ef2aSThomas Huth } 934fcf5ef2aSThomas Huth 9353a7be554SRichard Henderson static bool trans_l_slli(DisasContext *dc, arg_dal *a) 936fcf5ef2aSThomas Huth { 937cdd0f459SRichard Henderson check_r0_write(dc, a->d); 938*8bba7619SRichard Henderson tcg_gen_shli_tl(cpu_R(dc, a->d), cpu_R(dc, a->a), 939*8bba7619SRichard Henderson a->l & (TARGET_LONG_BITS - 1)); 940e20c2592SRichard Henderson return true; 941fcf5ef2aSThomas Huth } 942e20c2592SRichard Henderson 9433a7be554SRichard Henderson static bool trans_l_srli(DisasContext *dc, arg_dal *a) 944e20c2592SRichard Henderson { 945cdd0f459SRichard Henderson check_r0_write(dc, a->d); 946*8bba7619SRichard Henderson tcg_gen_shri_tl(cpu_R(dc, a->d), cpu_R(dc, a->a), 947*8bba7619SRichard Henderson a->l & (TARGET_LONG_BITS - 1)); 948e20c2592SRichard Henderson return true; 949e20c2592SRichard Henderson } 950e20c2592SRichard Henderson 9513a7be554SRichard Henderson static bool trans_l_srai(DisasContext *dc, arg_dal *a) 952e20c2592SRichard Henderson { 953cdd0f459SRichard Henderson check_r0_write(dc, a->d); 954*8bba7619SRichard Henderson tcg_gen_sari_tl(cpu_R(dc, a->d), cpu_R(dc, a->a), 955*8bba7619SRichard Henderson a->l & (TARGET_LONG_BITS - 1)); 956e20c2592SRichard Henderson return true; 957e20c2592SRichard Henderson } 958e20c2592SRichard Henderson 9593a7be554SRichard Henderson static bool trans_l_rori(DisasContext *dc, arg_dal *a) 960e20c2592SRichard Henderson { 961cdd0f459SRichard Henderson check_r0_write(dc, a->d); 962*8bba7619SRichard Henderson tcg_gen_rotri_tl(cpu_R(dc, a->d), cpu_R(dc, a->a), 963*8bba7619SRichard Henderson a->l & (TARGET_LONG_BITS - 1)); 964e20c2592SRichard Henderson return true; 965fcf5ef2aSThomas Huth } 966fcf5ef2aSThomas Huth 9673a7be554SRichard Henderson static bool trans_l_movhi(DisasContext *dc, arg_l_movhi *a) 968fcf5ef2aSThomas Huth { 969cdd0f459SRichard Henderson check_r0_write(dc, a->d); 970*8bba7619SRichard Henderson tcg_gen_movi_tl(cpu_R(dc, a->d), a->k << 16); 971e720a571SRichard Henderson return true; 972fcf5ef2aSThomas Huth } 973e720a571SRichard Henderson 9743a7be554SRichard Henderson static bool trans_l_macrc(DisasContext *dc, arg_l_macrc *a) 975e720a571SRichard Henderson { 976cdd0f459SRichard Henderson check_r0_write(dc, a->d); 977*8bba7619SRichard Henderson tcg_gen_trunc_i64_tl(cpu_R(dc, a->d), cpu_mac); 978e720a571SRichard Henderson tcg_gen_movi_i64(cpu_mac, 0); 979e720a571SRichard Henderson return true; 980fcf5ef2aSThomas Huth } 981fcf5ef2aSThomas Huth 9823a7be554SRichard Henderson static bool trans_l_sfeq(DisasContext *dc, arg_ab *a) 983fcf5ef2aSThomas Huth { 984*8bba7619SRichard Henderson tcg_gen_setcond_tl(TCG_COND_EQ, cpu_sr_f, 985*8bba7619SRichard Henderson cpu_R(dc, a->a), cpu_R(dc, a->b)); 986fbb3e29aSRichard Henderson return true; 987fcf5ef2aSThomas Huth } 988fbb3e29aSRichard Henderson 9893a7be554SRichard Henderson static bool trans_l_sfne(DisasContext *dc, arg_ab *a) 990fbb3e29aSRichard Henderson { 991*8bba7619SRichard Henderson tcg_gen_setcond_tl(TCG_COND_NE, cpu_sr_f, 992*8bba7619SRichard Henderson cpu_R(dc, a->a), cpu_R(dc, a->b)); 993fbb3e29aSRichard Henderson return true; 994fbb3e29aSRichard Henderson } 995fbb3e29aSRichard Henderson 9963a7be554SRichard Henderson static bool trans_l_sfgtu(DisasContext *dc, arg_ab *a) 997fbb3e29aSRichard Henderson { 998*8bba7619SRichard Henderson tcg_gen_setcond_tl(TCG_COND_GTU, cpu_sr_f, 999*8bba7619SRichard Henderson cpu_R(dc, a->a), cpu_R(dc, a->b)); 1000fbb3e29aSRichard Henderson return true; 1001fbb3e29aSRichard Henderson } 1002fbb3e29aSRichard Henderson 10033a7be554SRichard Henderson static bool trans_l_sfgeu(DisasContext *dc, arg_ab *a) 1004fbb3e29aSRichard Henderson { 1005*8bba7619SRichard Henderson tcg_gen_setcond_tl(TCG_COND_GEU, cpu_sr_f, 1006*8bba7619SRichard Henderson cpu_R(dc, a->a), cpu_R(dc, a->b)); 1007fbb3e29aSRichard Henderson return true; 1008fbb3e29aSRichard Henderson } 1009fbb3e29aSRichard Henderson 10103a7be554SRichard Henderson static bool trans_l_sfltu(DisasContext *dc, arg_ab *a) 1011fbb3e29aSRichard Henderson { 1012*8bba7619SRichard Henderson tcg_gen_setcond_tl(TCG_COND_LTU, cpu_sr_f, 1013*8bba7619SRichard Henderson cpu_R(dc, a->a), cpu_R(dc, a->b)); 1014fbb3e29aSRichard Henderson return true; 1015fbb3e29aSRichard Henderson } 1016fbb3e29aSRichard Henderson 10173a7be554SRichard Henderson static bool trans_l_sfleu(DisasContext *dc, arg_ab *a) 1018fbb3e29aSRichard Henderson { 1019*8bba7619SRichard Henderson tcg_gen_setcond_tl(TCG_COND_LEU, cpu_sr_f, 1020*8bba7619SRichard Henderson cpu_R(dc, a->a), cpu_R(dc, a->b)); 1021fbb3e29aSRichard Henderson return true; 1022fbb3e29aSRichard Henderson } 1023fbb3e29aSRichard Henderson 10243a7be554SRichard Henderson static bool trans_l_sfgts(DisasContext *dc, arg_ab *a) 1025fbb3e29aSRichard Henderson { 1026*8bba7619SRichard Henderson tcg_gen_setcond_tl(TCG_COND_GT, cpu_sr_f, 1027*8bba7619SRichard Henderson cpu_R(dc, a->a), cpu_R(dc, a->b)); 1028fbb3e29aSRichard Henderson return true; 1029fbb3e29aSRichard Henderson } 1030fbb3e29aSRichard Henderson 10313a7be554SRichard Henderson static bool trans_l_sfges(DisasContext *dc, arg_ab *a) 1032fbb3e29aSRichard Henderson { 1033*8bba7619SRichard Henderson tcg_gen_setcond_tl(TCG_COND_GE, cpu_sr_f, 1034*8bba7619SRichard Henderson cpu_R(dc, a->a), cpu_R(dc, a->b)); 1035fbb3e29aSRichard Henderson return true; 1036fbb3e29aSRichard Henderson } 1037fbb3e29aSRichard Henderson 10383a7be554SRichard Henderson static bool trans_l_sflts(DisasContext *dc, arg_ab *a) 1039fbb3e29aSRichard Henderson { 1040*8bba7619SRichard Henderson tcg_gen_setcond_tl(TCG_COND_LT, cpu_sr_f, 1041*8bba7619SRichard Henderson cpu_R(dc, a->a), cpu_R(dc, a->b)); 1042fbb3e29aSRichard Henderson return true; 1043fbb3e29aSRichard Henderson } 1044fbb3e29aSRichard Henderson 10453a7be554SRichard Henderson static bool trans_l_sfles(DisasContext *dc, arg_ab *a) 1046fbb3e29aSRichard Henderson { 1047*8bba7619SRichard Henderson tcg_gen_setcond_tl(TCG_COND_LE, 1048*8bba7619SRichard Henderson cpu_sr_f, cpu_R(dc, a->a), cpu_R(dc, a->b)); 1049fbb3e29aSRichard Henderson return true; 1050fcf5ef2aSThomas Huth } 1051fcf5ef2aSThomas Huth 10523a7be554SRichard Henderson static bool trans_l_sfeqi(DisasContext *dc, arg_ai *a) 1053fcf5ef2aSThomas Huth { 1054*8bba7619SRichard Henderson tcg_gen_setcondi_tl(TCG_COND_EQ, cpu_sr_f, cpu_R(dc, a->a), a->i); 1055032de4fcSRichard Henderson return true; 1056fcf5ef2aSThomas Huth } 1057032de4fcSRichard Henderson 10583a7be554SRichard Henderson static bool trans_l_sfnei(DisasContext *dc, arg_ai *a) 1059032de4fcSRichard Henderson { 1060*8bba7619SRichard Henderson tcg_gen_setcondi_tl(TCG_COND_NE, cpu_sr_f, cpu_R(dc, a->a), a->i); 1061032de4fcSRichard Henderson return true; 1062032de4fcSRichard Henderson } 1063032de4fcSRichard Henderson 10643a7be554SRichard Henderson static bool trans_l_sfgtui(DisasContext *dc, arg_ai *a) 1065032de4fcSRichard Henderson { 1066*8bba7619SRichard Henderson tcg_gen_setcondi_tl(TCG_COND_GTU, cpu_sr_f, cpu_R(dc, a->a), a->i); 1067032de4fcSRichard Henderson return true; 1068032de4fcSRichard Henderson } 1069032de4fcSRichard Henderson 10703a7be554SRichard Henderson static bool trans_l_sfgeui(DisasContext *dc, arg_ai *a) 1071032de4fcSRichard Henderson { 1072*8bba7619SRichard Henderson tcg_gen_setcondi_tl(TCG_COND_GEU, cpu_sr_f, cpu_R(dc, a->a), a->i); 1073032de4fcSRichard Henderson return true; 1074032de4fcSRichard Henderson } 1075032de4fcSRichard Henderson 10763a7be554SRichard Henderson static bool trans_l_sfltui(DisasContext *dc, arg_ai *a) 1077032de4fcSRichard Henderson { 1078*8bba7619SRichard Henderson tcg_gen_setcondi_tl(TCG_COND_LTU, cpu_sr_f, cpu_R(dc, a->a), a->i); 1079032de4fcSRichard Henderson return true; 1080032de4fcSRichard Henderson } 1081032de4fcSRichard Henderson 10823a7be554SRichard Henderson static bool trans_l_sfleui(DisasContext *dc, arg_ai *a) 1083032de4fcSRichard Henderson { 1084*8bba7619SRichard Henderson tcg_gen_setcondi_tl(TCG_COND_LEU, cpu_sr_f, cpu_R(dc, a->a), a->i); 1085032de4fcSRichard Henderson return true; 1086032de4fcSRichard Henderson } 1087032de4fcSRichard Henderson 10883a7be554SRichard Henderson static bool trans_l_sfgtsi(DisasContext *dc, arg_ai *a) 1089032de4fcSRichard Henderson { 1090*8bba7619SRichard Henderson tcg_gen_setcondi_tl(TCG_COND_GT, cpu_sr_f, cpu_R(dc, a->a), a->i); 1091032de4fcSRichard Henderson return true; 1092032de4fcSRichard Henderson } 1093032de4fcSRichard Henderson 10943a7be554SRichard Henderson static bool trans_l_sfgesi(DisasContext *dc, arg_ai *a) 1095032de4fcSRichard Henderson { 1096*8bba7619SRichard Henderson tcg_gen_setcondi_tl(TCG_COND_GE, cpu_sr_f, cpu_R(dc, a->a), a->i); 1097032de4fcSRichard Henderson return true; 1098032de4fcSRichard Henderson } 1099032de4fcSRichard Henderson 11003a7be554SRichard Henderson static bool trans_l_sfltsi(DisasContext *dc, arg_ai *a) 1101032de4fcSRichard Henderson { 1102*8bba7619SRichard Henderson tcg_gen_setcondi_tl(TCG_COND_LT, cpu_sr_f, cpu_R(dc, a->a), a->i); 1103032de4fcSRichard Henderson return true; 1104032de4fcSRichard Henderson } 1105032de4fcSRichard Henderson 11063a7be554SRichard Henderson static bool trans_l_sflesi(DisasContext *dc, arg_ai *a) 1107032de4fcSRichard Henderson { 1108*8bba7619SRichard Henderson tcg_gen_setcondi_tl(TCG_COND_LE, cpu_sr_f, cpu_R(dc, a->a), a->i); 1109032de4fcSRichard Henderson return true; 1110fcf5ef2aSThomas Huth } 1111fcf5ef2aSThomas Huth 11123a7be554SRichard Henderson static bool trans_l_sys(DisasContext *dc, arg_l_sys *a) 1113fcf5ef2aSThomas Huth { 11141ffa4bceSEmilio G. Cota tcg_gen_movi_tl(cpu_pc, dc->base.pc_next); 1115fcf5ef2aSThomas Huth gen_exception(dc, EXCP_SYSCALL); 11161ffa4bceSEmilio G. Cota dc->base.is_jmp = DISAS_NORETURN; 11177de9729fSRichard Henderson return true; 11187de9729fSRichard Henderson } 1119fcf5ef2aSThomas Huth 11203a7be554SRichard Henderson static bool trans_l_trap(DisasContext *dc, arg_l_trap *a) 11217de9729fSRichard Henderson { 11221ffa4bceSEmilio G. Cota tcg_gen_movi_tl(cpu_pc, dc->base.pc_next); 1123fcf5ef2aSThomas Huth gen_exception(dc, EXCP_TRAP); 11241ffa4bceSEmilio G. Cota dc->base.is_jmp = DISAS_NORETURN; 11257de9729fSRichard Henderson return true; 11267de9729fSRichard Henderson } 1127fcf5ef2aSThomas Huth 11283a7be554SRichard Henderson static bool trans_l_msync(DisasContext *dc, arg_l_msync *a) 11297de9729fSRichard Henderson { 113024fc5c0fSRichard Henderson tcg_gen_mb(TCG_MO_ALL); 11317de9729fSRichard Henderson return true; 1132fcf5ef2aSThomas Huth } 11337de9729fSRichard Henderson 11343a7be554SRichard Henderson static bool trans_l_psync(DisasContext *dc, arg_l_psync *a) 11357de9729fSRichard Henderson { 11367de9729fSRichard Henderson return true; 11377de9729fSRichard Henderson } 11387de9729fSRichard Henderson 11393a7be554SRichard Henderson static bool trans_l_csync(DisasContext *dc, arg_l_csync *a) 11407de9729fSRichard Henderson { 11417de9729fSRichard Henderson return true; 1142fcf5ef2aSThomas Huth } 1143fcf5ef2aSThomas Huth 11443a7be554SRichard Henderson static bool trans_l_rfe(DisasContext *dc, arg_l_rfe *a) 11458816f70bSRichard Henderson { 11462ba65417SRichard Henderson if (is_user(dc)) { 11478816f70bSRichard Henderson gen_illegal_exception(dc); 11488816f70bSRichard Henderson } else { 11498816f70bSRichard Henderson gen_helper_rfe(cpu_env); 115064e46c95SRichard Henderson dc->base.is_jmp = DISAS_EXIT; 11518816f70bSRichard Henderson } 11528816f70bSRichard Henderson return true; 11538816f70bSRichard Henderson } 11548816f70bSRichard Henderson 11556fd204a2SRichard Henderson static void do_fp2(DisasContext *dc, arg_da *a, 11566fd204a2SRichard Henderson void (*fn)(TCGv, TCGv_env, TCGv)) 1157fcf5ef2aSThomas Huth { 1158cdd0f459SRichard Henderson check_r0_write(dc, a->d); 1159*8bba7619SRichard Henderson fn(cpu_R(dc, a->d), cpu_env, cpu_R(dc, a->a)); 11604e2d3007SRichard Henderson gen_helper_update_fpcsr(cpu_env); 1161fcf5ef2aSThomas Huth } 11626fd204a2SRichard Henderson 11636fd204a2SRichard Henderson static void do_fp3(DisasContext *dc, arg_dab *a, 11646fd204a2SRichard Henderson void (*fn)(TCGv, TCGv_env, TCGv, TCGv)) 11656fd204a2SRichard Henderson { 1166cdd0f459SRichard Henderson check_r0_write(dc, a->d); 1167*8bba7619SRichard Henderson fn(cpu_R(dc, a->d), cpu_env, cpu_R(dc, a->a), cpu_R(dc, a->b)); 11686fd204a2SRichard Henderson gen_helper_update_fpcsr(cpu_env); 11696fd204a2SRichard Henderson } 11706fd204a2SRichard Henderson 11716fd204a2SRichard Henderson static void do_fpcmp(DisasContext *dc, arg_ab *a, 11726fd204a2SRichard Henderson void (*fn)(TCGv, TCGv_env, TCGv, TCGv), 11736fd204a2SRichard Henderson bool inv, bool swap) 11746fd204a2SRichard Henderson { 11756fd204a2SRichard Henderson if (swap) { 1176*8bba7619SRichard Henderson fn(cpu_sr_f, cpu_env, cpu_R(dc, a->b), cpu_R(dc, a->a)); 11776fd204a2SRichard Henderson } else { 1178*8bba7619SRichard Henderson fn(cpu_sr_f, cpu_env, cpu_R(dc, a->a), cpu_R(dc, a->b)); 11796fd204a2SRichard Henderson } 11806fd204a2SRichard Henderson if (inv) { 11816fd204a2SRichard Henderson tcg_gen_xori_tl(cpu_sr_f, cpu_sr_f, 1); 11826fd204a2SRichard Henderson } 11836fd204a2SRichard Henderson gen_helper_update_fpcsr(cpu_env); 11846fd204a2SRichard Henderson } 11856fd204a2SRichard Henderson 11863a7be554SRichard Henderson static bool trans_lf_add_s(DisasContext *dc, arg_dab *a) 11876fd204a2SRichard Henderson { 11886fd204a2SRichard Henderson do_fp3(dc, a, gen_helper_float_add_s); 11896fd204a2SRichard Henderson return true; 11906fd204a2SRichard Henderson } 11916fd204a2SRichard Henderson 11923a7be554SRichard Henderson static bool trans_lf_sub_s(DisasContext *dc, arg_dab *a) 11936fd204a2SRichard Henderson { 11946fd204a2SRichard Henderson do_fp3(dc, a, gen_helper_float_sub_s); 11956fd204a2SRichard Henderson return true; 11966fd204a2SRichard Henderson } 11976fd204a2SRichard Henderson 11983a7be554SRichard Henderson static bool trans_lf_mul_s(DisasContext *dc, arg_dab *a) 11996fd204a2SRichard Henderson { 12006fd204a2SRichard Henderson do_fp3(dc, a, gen_helper_float_mul_s); 12016fd204a2SRichard Henderson return true; 12026fd204a2SRichard Henderson } 12036fd204a2SRichard Henderson 12043a7be554SRichard Henderson static bool trans_lf_div_s(DisasContext *dc, arg_dab *a) 12056fd204a2SRichard Henderson { 12066fd204a2SRichard Henderson do_fp3(dc, a, gen_helper_float_div_s); 12076fd204a2SRichard Henderson return true; 12086fd204a2SRichard Henderson } 12096fd204a2SRichard Henderson 12103a7be554SRichard Henderson static bool trans_lf_rem_s(DisasContext *dc, arg_dab *a) 12116fd204a2SRichard Henderson { 12126fd204a2SRichard Henderson do_fp3(dc, a, gen_helper_float_rem_s); 12136fd204a2SRichard Henderson return true; 12146fd204a2SRichard Henderson } 12156fd204a2SRichard Henderson 12163a7be554SRichard Henderson static bool trans_lf_itof_s(DisasContext *dc, arg_da *a) 12176fd204a2SRichard Henderson { 12186fd204a2SRichard Henderson do_fp2(dc, a, gen_helper_itofs); 12196fd204a2SRichard Henderson return true; 12206fd204a2SRichard Henderson } 12216fd204a2SRichard Henderson 12223a7be554SRichard Henderson static bool trans_lf_ftoi_s(DisasContext *dc, arg_da *a) 12236fd204a2SRichard Henderson { 12246fd204a2SRichard Henderson do_fp2(dc, a, gen_helper_ftois); 12256fd204a2SRichard Henderson return true; 12266fd204a2SRichard Henderson } 12276fd204a2SRichard Henderson 12283a7be554SRichard Henderson static bool trans_lf_madd_s(DisasContext *dc, arg_dab *a) 12296fd204a2SRichard Henderson { 1230cdd0f459SRichard Henderson check_r0_write(dc, a->d); 1231*8bba7619SRichard Henderson gen_helper_float_madd_s(cpu_R(dc, a->d), cpu_env, cpu_R(dc, a->d), 1232*8bba7619SRichard Henderson cpu_R(dc, a->a), cpu_R(dc, a->b)); 12336fd204a2SRichard Henderson gen_helper_update_fpcsr(cpu_env); 12346fd204a2SRichard Henderson return true; 12356fd204a2SRichard Henderson } 12366fd204a2SRichard Henderson 12373a7be554SRichard Henderson static bool trans_lf_sfeq_s(DisasContext *dc, arg_ab *a) 12386fd204a2SRichard Henderson { 12396fd204a2SRichard Henderson do_fpcmp(dc, a, gen_helper_float_eq_s, false, false); 12406fd204a2SRichard Henderson return true; 12416fd204a2SRichard Henderson } 12426fd204a2SRichard Henderson 12433a7be554SRichard Henderson static bool trans_lf_sfne_s(DisasContext *dc, arg_ab *a) 12446fd204a2SRichard Henderson { 12456fd204a2SRichard Henderson do_fpcmp(dc, a, gen_helper_float_eq_s, true, false); 12466fd204a2SRichard Henderson return true; 12476fd204a2SRichard Henderson } 12486fd204a2SRichard Henderson 12493a7be554SRichard Henderson static bool trans_lf_sfgt_s(DisasContext *dc, arg_ab *a) 12506fd204a2SRichard Henderson { 12516fd204a2SRichard Henderson do_fpcmp(dc, a, gen_helper_float_lt_s, false, true); 12526fd204a2SRichard Henderson return true; 12536fd204a2SRichard Henderson } 12546fd204a2SRichard Henderson 12553a7be554SRichard Henderson static bool trans_lf_sfge_s(DisasContext *dc, arg_ab *a) 12566fd204a2SRichard Henderson { 12576fd204a2SRichard Henderson do_fpcmp(dc, a, gen_helper_float_le_s, false, true); 12586fd204a2SRichard Henderson return true; 12596fd204a2SRichard Henderson } 12606fd204a2SRichard Henderson 12613a7be554SRichard Henderson static bool trans_lf_sflt_s(DisasContext *dc, arg_ab *a) 12626fd204a2SRichard Henderson { 12636fd204a2SRichard Henderson do_fpcmp(dc, a, gen_helper_float_lt_s, false, false); 12646fd204a2SRichard Henderson return true; 12656fd204a2SRichard Henderson } 12666fd204a2SRichard Henderson 12673a7be554SRichard Henderson static bool trans_lf_sfle_s(DisasContext *dc, arg_ab *a) 12686fd204a2SRichard Henderson { 12696fd204a2SRichard Henderson do_fpcmp(dc, a, gen_helper_float_le_s, false, false); 12706fd204a2SRichard Henderson return true; 1271fcf5ef2aSThomas Huth } 1272fcf5ef2aSThomas Huth 1273a4fd3ec3SEmilio G. Cota static void openrisc_tr_init_disas_context(DisasContextBase *dcb, CPUState *cs) 1274fcf5ef2aSThomas Huth { 1275a4fd3ec3SEmilio G. Cota DisasContext *dc = container_of(dcb, DisasContext, base); 12769c489ea6SLluís Vilanova CPUOpenRISCState *env = cs->env_ptr; 1277a4fd3ec3SEmilio G. Cota int bound; 1278fcf5ef2aSThomas Huth 1279a4fd3ec3SEmilio G. Cota dc->mem_idx = cpu_mmu_index(env, false); 12801ffa4bceSEmilio G. Cota dc->tb_flags = dc->base.tb->flags; 1281a01deb36SRichard Henderson dc->delayed_branch = (dc->tb_flags & TB_FLAGS_DFLAG) != 0; 12828000ba56SRichard Henderson dc->jmp_pc_imm = -1; 12838000ba56SRichard Henderson 1284a4fd3ec3SEmilio G. Cota bound = -(dc->base.pc_first | TARGET_PAGE_MASK) / 4; 1285a4fd3ec3SEmilio G. Cota dc->base.max_insns = MIN(dc->base.max_insns, bound); 1286fcf5ef2aSThomas Huth } 1287fcf5ef2aSThomas Huth 1288a4fd3ec3SEmilio G. Cota static void openrisc_tr_tb_start(DisasContextBase *db, CPUState *cs) 1289a4fd3ec3SEmilio G. Cota { 1290a4fd3ec3SEmilio G. Cota DisasContext *dc = container_of(db, DisasContext, base); 1291fcf5ef2aSThomas Huth 12926597c28dSRichard Henderson /* Allow the TCG optimizer to see that R0 == 0, 12936597c28dSRichard Henderson when it's true, which is the common case. */ 12946597c28dSRichard Henderson if (dc->tb_flags & TB_FLAGS_R0_0) { 1295*8bba7619SRichard Henderson cpu_regs[0] = tcg_const_tl(0); 12966597c28dSRichard Henderson } else { 1297*8bba7619SRichard Henderson cpu_regs[0] = cpu_R0; 12986597c28dSRichard Henderson } 1299a4fd3ec3SEmilio G. Cota } 13006597c28dSRichard Henderson 1301a4fd3ec3SEmilio G. Cota static void openrisc_tr_insn_start(DisasContextBase *dcbase, CPUState *cs) 1302a4fd3ec3SEmilio G. Cota { 1303a4fd3ec3SEmilio G. Cota DisasContext *dc = container_of(dcbase, DisasContext, base); 1304a4fd3ec3SEmilio G. Cota 13051ffa4bceSEmilio G. Cota tcg_gen_insn_start(dc->base.pc_next, (dc->delayed_branch ? 1 : 0) 1306a4fd3ec3SEmilio G. Cota | (dc->base.num_insns > 1 ? 2 : 0)); 1307a4fd3ec3SEmilio G. Cota } 1308fcf5ef2aSThomas Huth 1309a4fd3ec3SEmilio G. Cota static bool openrisc_tr_breakpoint_check(DisasContextBase *dcbase, CPUState *cs, 1310a4fd3ec3SEmilio G. Cota const CPUBreakpoint *bp) 1311a4fd3ec3SEmilio G. Cota { 1312a4fd3ec3SEmilio G. Cota DisasContext *dc = container_of(dcbase, DisasContext, base); 1313a4fd3ec3SEmilio G. Cota 13141ffa4bceSEmilio G. Cota tcg_gen_movi_tl(cpu_pc, dc->base.pc_next); 1315fcf5ef2aSThomas Huth gen_exception(dc, EXCP_DEBUG); 13161ffa4bceSEmilio G. Cota dc->base.is_jmp = DISAS_NORETURN; 1317fcf5ef2aSThomas Huth /* The address covered by the breakpoint must be included in 1318fcf5ef2aSThomas Huth [tb->pc, tb->pc + tb->size) in order to for it to be 1319fcf5ef2aSThomas Huth properly cleared -- thus we increment the PC here so that 1320fcf5ef2aSThomas Huth the logic setting tb->size below does the right thing. */ 13211ffa4bceSEmilio G. Cota dc->base.pc_next += 4; 1322a4fd3ec3SEmilio G. Cota return true; 1323fcf5ef2aSThomas Huth } 1324fcf5ef2aSThomas Huth 1325a4fd3ec3SEmilio G. Cota static void openrisc_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs) 1326a4fd3ec3SEmilio G. Cota { 1327a4fd3ec3SEmilio G. Cota DisasContext *dc = container_of(dcbase, DisasContext, base); 1328a4fd3ec3SEmilio G. Cota OpenRISCCPU *cpu = OPENRISC_CPU(cs); 1329c7b6f54bSRichard Henderson uint32_t insn = cpu_ldl_code(&cpu->env, dc->base.pc_next); 1330a4fd3ec3SEmilio G. Cota 1331c7b6f54bSRichard Henderson if (!decode(dc, insn)) { 1332c7b6f54bSRichard Henderson gen_illegal_exception(dc); 1333c7b6f54bSRichard Henderson } 13341ffa4bceSEmilio G. Cota dc->base.pc_next += 4; 133524c32852SRichard Henderson 13368000ba56SRichard Henderson /* When exiting the delay slot normally, exit via jmp_pc. 13378000ba56SRichard Henderson * For DISAS_NORETURN, we have raised an exception and already exited. 13388000ba56SRichard Henderson * For DISAS_EXIT, we found l.rfe in a delay slot. There's nothing 13398000ba56SRichard Henderson * in the manual saying this is illegal, but it surely it should. 13408000ba56SRichard Henderson * At least or1ksim overrides pcnext and ignores the branch. 13418000ba56SRichard Henderson */ 13428000ba56SRichard Henderson if (dc->delayed_branch 13438000ba56SRichard Henderson && --dc->delayed_branch == 0 13448000ba56SRichard Henderson && dc->base.is_jmp == DISAS_NEXT) { 13458000ba56SRichard Henderson dc->base.is_jmp = DISAS_JUMP; 1346fcf5ef2aSThomas Huth } 1347a4fd3ec3SEmilio G. Cota } 1348fcf5ef2aSThomas Huth 1349a4fd3ec3SEmilio G. Cota static void openrisc_tr_tb_stop(DisasContextBase *dcbase, CPUState *cs) 1350a4fd3ec3SEmilio G. Cota { 1351a4fd3ec3SEmilio G. Cota DisasContext *dc = container_of(dcbase, DisasContext, base); 13528000ba56SRichard Henderson target_ulong jmp_dest; 135324c32852SRichard Henderson 1354e0a369cfSRichard Henderson /* If we have already exited the TB, nothing following has effect. */ 1355e0a369cfSRichard Henderson if (dc->base.is_jmp == DISAS_NORETURN) { 1356e0a369cfSRichard Henderson return; 1357e0a369cfSRichard Henderson } 1358e0a369cfSRichard Henderson 13598000ba56SRichard Henderson /* Adjust the delayed branch state for the next TB. */ 1360a01deb36SRichard Henderson if ((dc->tb_flags & TB_FLAGS_DFLAG ? 1 : 0) != (dc->delayed_branch != 0)) { 1361a01deb36SRichard Henderson tcg_gen_movi_i32(cpu_dflag, dc->delayed_branch != 0); 1362a01deb36SRichard Henderson } 1363a01deb36SRichard Henderson 13648000ba56SRichard Henderson /* For DISAS_TOO_MANY, jump to the next insn. */ 13658000ba56SRichard Henderson jmp_dest = dc->base.pc_next; 13668000ba56SRichard Henderson tcg_gen_movi_tl(cpu_ppc, jmp_dest - 4); 13678000ba56SRichard Henderson 13681ffa4bceSEmilio G. Cota switch (dc->base.is_jmp) { 13698000ba56SRichard Henderson case DISAS_JUMP: 13708000ba56SRichard Henderson jmp_dest = dc->jmp_pc_imm; 13718000ba56SRichard Henderson if (jmp_dest == -1) { 13728000ba56SRichard Henderson /* The jump destination is indirect/computed; use jmp_pc. */ 13738000ba56SRichard Henderson tcg_gen_mov_tl(cpu_pc, jmp_pc); 13748000ba56SRichard Henderson tcg_gen_discard_tl(jmp_pc); 13758000ba56SRichard Henderson if (unlikely(dc->base.singlestep_enabled)) { 13768000ba56SRichard Henderson gen_exception(dc, EXCP_DEBUG); 13778000ba56SRichard Henderson } else { 13788000ba56SRichard Henderson tcg_gen_lookup_and_goto_ptr(); 13798000ba56SRichard Henderson } 1380fcf5ef2aSThomas Huth break; 13818000ba56SRichard Henderson } 13828000ba56SRichard Henderson /* The jump destination is direct; use jmp_pc_imm. 13838000ba56SRichard Henderson However, we will have stored into jmp_pc as well; 13848000ba56SRichard Henderson we know now that it wasn't needed. */ 13858000ba56SRichard Henderson tcg_gen_discard_tl(jmp_pc); 13868000ba56SRichard Henderson /* fallthru */ 13878000ba56SRichard Henderson 13888000ba56SRichard Henderson case DISAS_TOO_MANY: 13898000ba56SRichard Henderson if (unlikely(dc->base.singlestep_enabled)) { 13908000ba56SRichard Henderson tcg_gen_movi_tl(cpu_pc, jmp_dest); 13918000ba56SRichard Henderson gen_exception(dc, EXCP_DEBUG); 13928000ba56SRichard Henderson } else if ((dc->base.pc_first ^ jmp_dest) & TARGET_PAGE_MASK) { 13938000ba56SRichard Henderson tcg_gen_movi_tl(cpu_pc, jmp_dest); 13948000ba56SRichard Henderson tcg_gen_lookup_and_goto_ptr(); 13958000ba56SRichard Henderson } else { 13968000ba56SRichard Henderson tcg_gen_goto_tb(0); 13978000ba56SRichard Henderson tcg_gen_movi_tl(cpu_pc, jmp_dest); 13988000ba56SRichard Henderson tcg_gen_exit_tb(dc->base.tb, 0); 13998000ba56SRichard Henderson } 14008000ba56SRichard Henderson break; 14018000ba56SRichard Henderson 140264e46c95SRichard Henderson case DISAS_EXIT: 1403e0a369cfSRichard Henderson if (unlikely(dc->base.singlestep_enabled)) { 1404e0a369cfSRichard Henderson gen_exception(dc, EXCP_DEBUG); 1405e0a369cfSRichard Henderson } else { 140607ea28b4SRichard Henderson tcg_gen_exit_tb(NULL, 0); 1407e0a369cfSRichard Henderson } 1408fcf5ef2aSThomas Huth break; 1409a4fd3ec3SEmilio G. Cota default: 1410a4fd3ec3SEmilio G. Cota g_assert_not_reached(); 1411a4fd3ec3SEmilio G. Cota } 1412fcf5ef2aSThomas Huth } 1413fcf5ef2aSThomas Huth 1414a4fd3ec3SEmilio G. Cota static void openrisc_tr_disas_log(const DisasContextBase *dcbase, CPUState *cs) 1415a4fd3ec3SEmilio G. Cota { 1416a4fd3ec3SEmilio G. Cota DisasContext *s = container_of(dcbase, DisasContext, base); 1417fcf5ef2aSThomas Huth 1418a4fd3ec3SEmilio G. Cota qemu_log("IN: %s\n", lookup_symbol(s->base.pc_first)); 1419a4fd3ec3SEmilio G. Cota log_target_disas(cs, s->base.pc_first, s->base.tb->size); 1420fcf5ef2aSThomas Huth } 1421a4fd3ec3SEmilio G. Cota 1422a4fd3ec3SEmilio G. Cota static const TranslatorOps openrisc_tr_ops = { 1423a4fd3ec3SEmilio G. Cota .init_disas_context = openrisc_tr_init_disas_context, 1424a4fd3ec3SEmilio G. Cota .tb_start = openrisc_tr_tb_start, 1425a4fd3ec3SEmilio G. Cota .insn_start = openrisc_tr_insn_start, 1426a4fd3ec3SEmilio G. Cota .breakpoint_check = openrisc_tr_breakpoint_check, 1427a4fd3ec3SEmilio G. Cota .translate_insn = openrisc_tr_translate_insn, 1428a4fd3ec3SEmilio G. Cota .tb_stop = openrisc_tr_tb_stop, 1429a4fd3ec3SEmilio G. Cota .disas_log = openrisc_tr_disas_log, 1430a4fd3ec3SEmilio G. Cota }; 1431a4fd3ec3SEmilio G. Cota 14328b86d6d2SRichard Henderson void gen_intermediate_code(CPUState *cs, TranslationBlock *tb, int max_insns) 1433a4fd3ec3SEmilio G. Cota { 1434a4fd3ec3SEmilio G. Cota DisasContext ctx; 1435a4fd3ec3SEmilio G. Cota 14368b86d6d2SRichard Henderson translator_loop(&openrisc_tr_ops, &ctx.base, cs, tb, max_insns); 1437fcf5ef2aSThomas Huth } 1438fcf5ef2aSThomas Huth 143990c84c56SMarkus Armbruster void openrisc_cpu_dump_state(CPUState *cs, FILE *f, int flags) 1440fcf5ef2aSThomas Huth { 1441fcf5ef2aSThomas Huth OpenRISCCPU *cpu = OPENRISC_CPU(cs); 1442fcf5ef2aSThomas Huth CPUOpenRISCState *env = &cpu->env; 1443fcf5ef2aSThomas Huth int i; 1444fcf5ef2aSThomas Huth 144590c84c56SMarkus Armbruster qemu_fprintf(f, "PC=%08x\n", env->pc); 1446fcf5ef2aSThomas Huth for (i = 0; i < 32; ++i) { 144790c84c56SMarkus Armbruster qemu_fprintf(f, "R%02d=%08x%c", i, cpu_get_gpr(env, i), 1448fcf5ef2aSThomas Huth (i % 4) == 3 ? '\n' : ' '); 1449fcf5ef2aSThomas Huth } 1450fcf5ef2aSThomas Huth } 1451fcf5ef2aSThomas Huth 1452fcf5ef2aSThomas Huth void restore_state_to_opc(CPUOpenRISCState *env, TranslationBlock *tb, 1453fcf5ef2aSThomas Huth target_ulong *data) 1454fcf5ef2aSThomas Huth { 1455fcf5ef2aSThomas Huth env->pc = data[0]; 1456a01deb36SRichard Henderson env->dflag = data[1] & 1; 1457a01deb36SRichard Henderson if (data[1] & 2) { 145824c32852SRichard Henderson env->ppc = env->pc - 4; 145924c32852SRichard Henderson } 1460fcf5ef2aSThomas Huth } 1461