1e67db06eSJia Liu /* 2e67db06eSJia Liu * OpenRISC translation 3e67db06eSJia Liu * 4e67db06eSJia Liu * Copyright (c) 2011-2012 Jia Liu <proljc@gmail.com> 5e67db06eSJia Liu * Feng Gao <gf91597@gmail.com> 6e67db06eSJia Liu * 7e67db06eSJia Liu * This library is free software; you can redistribute it and/or 8e67db06eSJia Liu * modify it under the terms of the GNU Lesser General Public 9e67db06eSJia Liu * License as published by the Free Software Foundation; either 10779fc6adSThomas Huth * version 2.1 of the License, or (at your option) any later version. 11e67db06eSJia Liu * 12e67db06eSJia Liu * This library is distributed in the hope that it will be useful, 13e67db06eSJia Liu * but WITHOUT ANY WARRANTY; without even the implied warranty of 14e67db06eSJia Liu * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15e67db06eSJia Liu * Lesser General Public License for more details. 16e67db06eSJia Liu * 17e67db06eSJia Liu * You should have received a copy of the GNU Lesser General Public 18e67db06eSJia Liu * License along with this library; if not, see <http://www.gnu.org/licenses/>. 19e67db06eSJia Liu */ 20e67db06eSJia Liu 21ed2decc6SPeter Maydell #include "qemu/osdep.h" 22e67db06eSJia Liu #include "cpu.h" 23022c62cbSPaolo Bonzini #include "exec/exec-all.h" 2476cad711SPaolo Bonzini #include "disas/disas.h" 25e67db06eSJia Liu #include "tcg-op.h" 261de7afc9SPaolo Bonzini #include "qemu/log.h" 271de7afc9SPaolo Bonzini #include "qemu/bitops.h" 2890c84c56SMarkus Armbruster #include "qemu/qemu-print.h" 29f08b6170SPaolo Bonzini #include "exec/cpu_ldst.h" 3077fc6f5eSLluís Vilanova #include "exec/translator.h" 31bbe418f2SJia Liu 322ef6175aSRichard Henderson #include "exec/helper-proto.h" 332ef6175aSRichard Henderson #include "exec/helper-gen.h" 347de9729fSRichard Henderson #include "exec/gen-icount.h" 35e67db06eSJia Liu 36a7e30d84SLluís Vilanova #include "trace-tcg.h" 37508127e2SPaolo Bonzini #include "exec/log.h" 38a7e30d84SLluís Vilanova 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 43bbe418f2SJia Liu typedef struct DisasContext { 441ffa4bceSEmilio G. Cota DisasContextBase base; 45bbe418f2SJia Liu uint32_t mem_idx; 46a01deb36SRichard Henderson uint32_t tb_flags; 47bbe418f2SJia Liu 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; 51*d29f4368SRichard Henderson 52*d29f4368SRichard Henderson /* The temporary corresponding to register 0 for this compilation. */ 53*d29f4368SRichard Henderson TCGv R0; 54bbe418f2SJia Liu } DisasContext; 55bbe418f2SJia Liu 562ba65417SRichard Henderson static inline bool is_user(DisasContext *dc) 572ba65417SRichard Henderson { 582ba65417SRichard Henderson #ifdef CONFIG_USER_ONLY 592ba65417SRichard Henderson return true; 602ba65417SRichard Henderson #else 61b9bed1b9SRichard Henderson return !(dc->tb_flags & TB_FLAGS_SM); 622ba65417SRichard Henderson #endif 632ba65417SRichard Henderson } 642ba65417SRichard Henderson 657de9729fSRichard Henderson /* Include the auto-generated decoder. */ 667de9729fSRichard Henderson #include "decode.inc.c" 677de9729fSRichard Henderson 68bbe418f2SJia Liu static TCGv cpu_sr; 698bba7619SRichard Henderson static TCGv cpu_regs[32]; 70bbe418f2SJia Liu static TCGv cpu_pc; 71bbe418f2SJia Liu static TCGv jmp_pc; /* l.jr/l.jalr temp pc */ 72bbe418f2SJia Liu static TCGv cpu_ppc; 7384775c43SRichard Henderson static TCGv cpu_sr_f; /* bf/bnf, F flag taken */ 7497458071SRichard Henderson static TCGv cpu_sr_cy; /* carry (unsigned overflow) */ 7597458071SRichard Henderson static TCGv cpu_sr_ov; /* signed overflow */ 76930c3d00SRichard Henderson static TCGv cpu_lock_addr; 77930c3d00SRichard Henderson static TCGv cpu_lock_value; 78bbe418f2SJia Liu static TCGv_i32 fpcsr; 796f7332baSRichard Henderson static TCGv_i64 cpu_mac; /* MACHI:MACLO */ 80a01deb36SRichard Henderson static TCGv_i32 cpu_dflag; 81bbe418f2SJia Liu 82e67db06eSJia Liu void openrisc_translate_init(void) 83e67db06eSJia Liu { 84bbe418f2SJia Liu static const char * const regnames[] = { 85bbe418f2SJia Liu "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", 86bbe418f2SJia Liu "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", 87bbe418f2SJia Liu "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23", 88bbe418f2SJia Liu "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31", 89bbe418f2SJia Liu }; 90bbe418f2SJia Liu int i; 91bbe418f2SJia Liu 92e1ccc054SRichard Henderson cpu_sr = tcg_global_mem_new(cpu_env, 93bbe418f2SJia Liu offsetof(CPUOpenRISCState, sr), "sr"); 94a01deb36SRichard Henderson cpu_dflag = tcg_global_mem_new_i32(cpu_env, 95a01deb36SRichard Henderson offsetof(CPUOpenRISCState, dflag), 96a01deb36SRichard Henderson "dflag"); 97e1ccc054SRichard Henderson cpu_pc = tcg_global_mem_new(cpu_env, 98bbe418f2SJia Liu offsetof(CPUOpenRISCState, pc), "pc"); 99e1ccc054SRichard Henderson cpu_ppc = tcg_global_mem_new(cpu_env, 100bbe418f2SJia Liu offsetof(CPUOpenRISCState, ppc), "ppc"); 101e1ccc054SRichard Henderson jmp_pc = tcg_global_mem_new(cpu_env, 102bbe418f2SJia Liu offsetof(CPUOpenRISCState, jmp_pc), "jmp_pc"); 10384775c43SRichard Henderson cpu_sr_f = tcg_global_mem_new(cpu_env, 10484775c43SRichard Henderson offsetof(CPUOpenRISCState, sr_f), "sr_f"); 10597458071SRichard Henderson cpu_sr_cy = tcg_global_mem_new(cpu_env, 10697458071SRichard Henderson offsetof(CPUOpenRISCState, sr_cy), "sr_cy"); 10797458071SRichard Henderson cpu_sr_ov = tcg_global_mem_new(cpu_env, 10897458071SRichard Henderson offsetof(CPUOpenRISCState, sr_ov), "sr_ov"); 109930c3d00SRichard Henderson cpu_lock_addr = tcg_global_mem_new(cpu_env, 110930c3d00SRichard Henderson offsetof(CPUOpenRISCState, lock_addr), 111930c3d00SRichard Henderson "lock_addr"); 112930c3d00SRichard Henderson cpu_lock_value = tcg_global_mem_new(cpu_env, 113930c3d00SRichard Henderson offsetof(CPUOpenRISCState, lock_value), 114930c3d00SRichard Henderson "lock_value"); 115e1ccc054SRichard Henderson fpcsr = tcg_global_mem_new_i32(cpu_env, 116bbe418f2SJia Liu offsetof(CPUOpenRISCState, fpcsr), 117bbe418f2SJia Liu "fpcsr"); 1186f7332baSRichard Henderson cpu_mac = tcg_global_mem_new_i64(cpu_env, 1196f7332baSRichard Henderson offsetof(CPUOpenRISCState, mac), 1206f7332baSRichard Henderson "mac"); 121bbe418f2SJia Liu for (i = 0; i < 32; i++) { 1228bba7619SRichard Henderson cpu_regs[i] = tcg_global_mem_new(cpu_env, 123d89e71e8SStafford Horne offsetof(CPUOpenRISCState, 124d89e71e8SStafford Horne shadow_gpr[0][i]), 125bbe418f2SJia Liu regnames[i]); 126bbe418f2SJia Liu } 127bbe418f2SJia Liu } 128bbe418f2SJia Liu 129bbe418f2SJia Liu static void gen_exception(DisasContext *dc, unsigned int excp) 130bbe418f2SJia Liu { 131bbe418f2SJia Liu TCGv_i32 tmp = tcg_const_i32(excp); 132bbe418f2SJia Liu gen_helper_exception(cpu_env, tmp); 133bbe418f2SJia Liu tcg_temp_free_i32(tmp); 134bbe418f2SJia Liu } 135bbe418f2SJia Liu 136bbe418f2SJia Liu static void gen_illegal_exception(DisasContext *dc) 137bbe418f2SJia Liu { 1381ffa4bceSEmilio G. Cota tcg_gen_movi_tl(cpu_pc, dc->base.pc_next); 139bbe418f2SJia Liu gen_exception(dc, EXCP_ILLEGAL); 1401ffa4bceSEmilio G. Cota dc->base.is_jmp = DISAS_NORETURN; 141bbe418f2SJia Liu } 142bbe418f2SJia Liu 143bbe418f2SJia Liu /* not used yet, open it when we need or64. */ 144bbe418f2SJia Liu /*#ifdef TARGET_OPENRISC64 145bbe418f2SJia Liu static void check_ob64s(DisasContext *dc) 146bbe418f2SJia Liu { 147bbe418f2SJia Liu if (!(dc->flags & CPUCFGR_OB64S)) { 148bbe418f2SJia Liu gen_illegal_exception(dc); 149bbe418f2SJia Liu } 150bbe418f2SJia Liu } 151bbe418f2SJia Liu 152bbe418f2SJia Liu static void check_of64s(DisasContext *dc) 153bbe418f2SJia Liu { 154bbe418f2SJia Liu if (!(dc->flags & CPUCFGR_OF64S)) { 155bbe418f2SJia Liu gen_illegal_exception(dc); 156bbe418f2SJia Liu } 157bbe418f2SJia Liu } 158bbe418f2SJia Liu 159bbe418f2SJia Liu static void check_ov64s(DisasContext *dc) 160bbe418f2SJia Liu { 161bbe418f2SJia Liu if (!(dc->flags & CPUCFGR_OV64S)) { 162bbe418f2SJia Liu gen_illegal_exception(dc); 163bbe418f2SJia Liu } 164bbe418f2SJia Liu } 165bbe418f2SJia Liu #endif*/ 166bbe418f2SJia Liu 1678bba7619SRichard Henderson static TCGv cpu_R(DisasContext *dc, int reg) 1688bba7619SRichard Henderson { 169*d29f4368SRichard Henderson if (reg == 0) { 170*d29f4368SRichard Henderson return dc->R0; 171*d29f4368SRichard Henderson } else { 1728bba7619SRichard Henderson return cpu_regs[reg]; 1738bba7619SRichard Henderson } 174*d29f4368SRichard Henderson } 1758bba7619SRichard Henderson 176cdd0f459SRichard Henderson /* 177cdd0f459SRichard Henderson * We're about to write to REG. On the off-chance that the user is 178cdd0f459SRichard Henderson * writing to R0, re-instate the architectural register. 179cdd0f459SRichard Henderson */ 180cdd0f459SRichard Henderson static void check_r0_write(DisasContext *dc, int reg) 181cdd0f459SRichard Henderson { 182cdd0f459SRichard Henderson if (unlikely(reg == 0)) { 183*d29f4368SRichard Henderson dc->R0 = cpu_regs[0]; 184cdd0f459SRichard Henderson } 185cdd0f459SRichard Henderson } 1866597c28dSRichard Henderson 18797458071SRichard Henderson static void gen_ove_cy(DisasContext *dc) 1889ecaa27eSRichard Henderson { 1890c53d734SRichard Henderson if (dc->tb_flags & SR_OVE) { 19097458071SRichard Henderson gen_helper_ove_cy(cpu_env); 1919ecaa27eSRichard Henderson } 1920c53d734SRichard Henderson } 1939ecaa27eSRichard Henderson 19497458071SRichard Henderson static void gen_ove_ov(DisasContext *dc) 1959ecaa27eSRichard Henderson { 1960c53d734SRichard Henderson if (dc->tb_flags & SR_OVE) { 19797458071SRichard Henderson gen_helper_ove_ov(cpu_env); 1989ecaa27eSRichard Henderson } 1990c53d734SRichard Henderson } 2009ecaa27eSRichard Henderson 20197458071SRichard Henderson static void gen_ove_cyov(DisasContext *dc) 2029ecaa27eSRichard Henderson { 2030c53d734SRichard Henderson if (dc->tb_flags & SR_OVE) { 20497458071SRichard Henderson gen_helper_ove_cyov(cpu_env); 2059ecaa27eSRichard Henderson } 2060c53d734SRichard Henderson } 2079ecaa27eSRichard Henderson 2089ecaa27eSRichard Henderson static void gen_add(DisasContext *dc, TCGv dest, TCGv srca, TCGv srcb) 2099ecaa27eSRichard Henderson { 2109ecaa27eSRichard Henderson TCGv t0 = tcg_const_tl(0); 2119ecaa27eSRichard Henderson TCGv res = tcg_temp_new(); 2129ecaa27eSRichard Henderson 21397458071SRichard Henderson tcg_gen_add2_tl(res, cpu_sr_cy, srca, t0, srcb, t0); 21497458071SRichard Henderson tcg_gen_xor_tl(cpu_sr_ov, srca, srcb); 2159ecaa27eSRichard Henderson tcg_gen_xor_tl(t0, res, srcb); 21697458071SRichard Henderson tcg_gen_andc_tl(cpu_sr_ov, t0, cpu_sr_ov); 2179ecaa27eSRichard Henderson tcg_temp_free(t0); 2189ecaa27eSRichard Henderson 2199ecaa27eSRichard Henderson tcg_gen_mov_tl(dest, res); 2209ecaa27eSRichard Henderson tcg_temp_free(res); 2219ecaa27eSRichard Henderson 22297458071SRichard Henderson gen_ove_cyov(dc); 2239ecaa27eSRichard Henderson } 2249ecaa27eSRichard Henderson 2259ecaa27eSRichard Henderson static void gen_addc(DisasContext *dc, TCGv dest, TCGv srca, TCGv srcb) 2269ecaa27eSRichard Henderson { 2279ecaa27eSRichard Henderson TCGv t0 = tcg_const_tl(0); 2289ecaa27eSRichard Henderson TCGv res = tcg_temp_new(); 2299ecaa27eSRichard Henderson 23097458071SRichard Henderson tcg_gen_add2_tl(res, cpu_sr_cy, srca, t0, cpu_sr_cy, t0); 23197458071SRichard Henderson tcg_gen_add2_tl(res, cpu_sr_cy, res, cpu_sr_cy, srcb, t0); 23297458071SRichard Henderson tcg_gen_xor_tl(cpu_sr_ov, srca, srcb); 2339ecaa27eSRichard Henderson tcg_gen_xor_tl(t0, res, srcb); 23497458071SRichard Henderson tcg_gen_andc_tl(cpu_sr_ov, t0, cpu_sr_ov); 2359ecaa27eSRichard Henderson tcg_temp_free(t0); 2369ecaa27eSRichard Henderson 2379ecaa27eSRichard Henderson tcg_gen_mov_tl(dest, res); 2389ecaa27eSRichard Henderson tcg_temp_free(res); 2399ecaa27eSRichard Henderson 24097458071SRichard Henderson gen_ove_cyov(dc); 2419ecaa27eSRichard Henderson } 2429ecaa27eSRichard Henderson 2439ecaa27eSRichard Henderson static void gen_sub(DisasContext *dc, TCGv dest, TCGv srca, TCGv srcb) 2449ecaa27eSRichard Henderson { 2459ecaa27eSRichard Henderson TCGv res = tcg_temp_new(); 2469ecaa27eSRichard Henderson 2479ecaa27eSRichard Henderson tcg_gen_sub_tl(res, srca, srcb); 24897458071SRichard Henderson tcg_gen_xor_tl(cpu_sr_cy, srca, srcb); 24997458071SRichard Henderson tcg_gen_xor_tl(cpu_sr_ov, res, srcb); 25097458071SRichard Henderson tcg_gen_and_tl(cpu_sr_ov, cpu_sr_ov, cpu_sr_cy); 25197458071SRichard Henderson tcg_gen_setcond_tl(TCG_COND_LTU, cpu_sr_cy, srca, srcb); 2529ecaa27eSRichard Henderson 2539ecaa27eSRichard Henderson tcg_gen_mov_tl(dest, res); 2549ecaa27eSRichard Henderson tcg_temp_free(res); 2559ecaa27eSRichard Henderson 25697458071SRichard Henderson gen_ove_cyov(dc); 2579ecaa27eSRichard Henderson } 2589ecaa27eSRichard Henderson 2599ecaa27eSRichard Henderson static void gen_mul(DisasContext *dc, TCGv dest, TCGv srca, TCGv srcb) 2609ecaa27eSRichard Henderson { 2619ecaa27eSRichard Henderson TCGv t0 = tcg_temp_new(); 2629ecaa27eSRichard Henderson 26397458071SRichard Henderson tcg_gen_muls2_tl(dest, cpu_sr_ov, srca, srcb); 2649ecaa27eSRichard Henderson tcg_gen_sari_tl(t0, dest, TARGET_LONG_BITS - 1); 26597458071SRichard Henderson tcg_gen_setcond_tl(TCG_COND_NE, cpu_sr_ov, cpu_sr_ov, t0); 2669ecaa27eSRichard Henderson tcg_temp_free(t0); 2679ecaa27eSRichard Henderson 26897458071SRichard Henderson tcg_gen_neg_tl(cpu_sr_ov, cpu_sr_ov); 26997458071SRichard Henderson gen_ove_ov(dc); 2709ecaa27eSRichard Henderson } 2719ecaa27eSRichard Henderson 2729ecaa27eSRichard Henderson static void gen_mulu(DisasContext *dc, TCGv dest, TCGv srca, TCGv srcb) 2739ecaa27eSRichard Henderson { 27497458071SRichard Henderson tcg_gen_muls2_tl(dest, cpu_sr_cy, srca, srcb); 27597458071SRichard Henderson tcg_gen_setcondi_tl(TCG_COND_NE, cpu_sr_cy, cpu_sr_cy, 0); 2769ecaa27eSRichard Henderson 27797458071SRichard Henderson gen_ove_cy(dc); 2789ecaa27eSRichard Henderson } 2799ecaa27eSRichard Henderson 2809ecaa27eSRichard Henderson static void gen_div(DisasContext *dc, TCGv dest, TCGv srca, TCGv srcb) 2819ecaa27eSRichard Henderson { 2829ecaa27eSRichard Henderson TCGv t0 = tcg_temp_new(); 2839ecaa27eSRichard Henderson 28497458071SRichard Henderson tcg_gen_setcondi_tl(TCG_COND_EQ, cpu_sr_ov, srcb, 0); 2859ecaa27eSRichard Henderson /* The result of divide-by-zero is undefined. 2869ecaa27eSRichard Henderson Supress the host-side exception by dividing by 1. */ 28797458071SRichard Henderson tcg_gen_or_tl(t0, srcb, cpu_sr_ov); 2889ecaa27eSRichard Henderson tcg_gen_div_tl(dest, srca, t0); 2899ecaa27eSRichard Henderson tcg_temp_free(t0); 2909ecaa27eSRichard Henderson 29197458071SRichard Henderson tcg_gen_neg_tl(cpu_sr_ov, cpu_sr_ov); 29297458071SRichard Henderson gen_ove_ov(dc); 2939ecaa27eSRichard Henderson } 2949ecaa27eSRichard Henderson 2959ecaa27eSRichard Henderson static void gen_divu(DisasContext *dc, TCGv dest, TCGv srca, TCGv srcb) 2969ecaa27eSRichard Henderson { 2979ecaa27eSRichard Henderson TCGv t0 = tcg_temp_new(); 2989ecaa27eSRichard Henderson 29997458071SRichard Henderson tcg_gen_setcondi_tl(TCG_COND_EQ, cpu_sr_cy, srcb, 0); 3009ecaa27eSRichard Henderson /* The result of divide-by-zero is undefined. 3019ecaa27eSRichard Henderson Supress the host-side exception by dividing by 1. */ 30297458071SRichard Henderson tcg_gen_or_tl(t0, srcb, cpu_sr_cy); 3039ecaa27eSRichard Henderson tcg_gen_divu_tl(dest, srca, t0); 3049ecaa27eSRichard Henderson tcg_temp_free(t0); 3059ecaa27eSRichard Henderson 30697458071SRichard Henderson gen_ove_cy(dc); 3079ecaa27eSRichard Henderson } 308da1d7759SSebastian Macke 309cc5de49eSRichard Henderson static void gen_muld(DisasContext *dc, TCGv srca, TCGv srcb) 310cc5de49eSRichard Henderson { 311cc5de49eSRichard Henderson TCGv_i64 t1 = tcg_temp_new_i64(); 312cc5de49eSRichard Henderson TCGv_i64 t2 = tcg_temp_new_i64(); 313cc5de49eSRichard Henderson 314cc5de49eSRichard Henderson tcg_gen_ext_tl_i64(t1, srca); 315cc5de49eSRichard Henderson tcg_gen_ext_tl_i64(t2, srcb); 316cc5de49eSRichard Henderson if (TARGET_LONG_BITS == 32) { 317cc5de49eSRichard Henderson tcg_gen_mul_i64(cpu_mac, t1, t2); 318cc5de49eSRichard Henderson tcg_gen_movi_tl(cpu_sr_ov, 0); 319cc5de49eSRichard Henderson } else { 320cc5de49eSRichard Henderson TCGv_i64 high = tcg_temp_new_i64(); 321cc5de49eSRichard Henderson 322cc5de49eSRichard Henderson tcg_gen_muls2_i64(cpu_mac, high, t1, t2); 323cc5de49eSRichard Henderson tcg_gen_sari_i64(t1, cpu_mac, 63); 324cc5de49eSRichard Henderson tcg_gen_setcond_i64(TCG_COND_NE, t1, t1, high); 325cc5de49eSRichard Henderson tcg_temp_free_i64(high); 326cc5de49eSRichard Henderson tcg_gen_trunc_i64_tl(cpu_sr_ov, t1); 327cc5de49eSRichard Henderson tcg_gen_neg_tl(cpu_sr_ov, cpu_sr_ov); 328cc5de49eSRichard Henderson 329cc5de49eSRichard Henderson gen_ove_ov(dc); 330cc5de49eSRichard Henderson } 331cc5de49eSRichard Henderson tcg_temp_free_i64(t1); 332cc5de49eSRichard Henderson tcg_temp_free_i64(t2); 333cc5de49eSRichard Henderson } 334cc5de49eSRichard Henderson 335cc5de49eSRichard Henderson static void gen_muldu(DisasContext *dc, TCGv srca, TCGv srcb) 336cc5de49eSRichard Henderson { 337cc5de49eSRichard Henderson TCGv_i64 t1 = tcg_temp_new_i64(); 338cc5de49eSRichard Henderson TCGv_i64 t2 = tcg_temp_new_i64(); 339cc5de49eSRichard Henderson 340cc5de49eSRichard Henderson tcg_gen_extu_tl_i64(t1, srca); 341cc5de49eSRichard Henderson tcg_gen_extu_tl_i64(t2, srcb); 342cc5de49eSRichard Henderson if (TARGET_LONG_BITS == 32) { 343cc5de49eSRichard Henderson tcg_gen_mul_i64(cpu_mac, t1, t2); 344cc5de49eSRichard Henderson tcg_gen_movi_tl(cpu_sr_cy, 0); 345cc5de49eSRichard Henderson } else { 346cc5de49eSRichard Henderson TCGv_i64 high = tcg_temp_new_i64(); 347cc5de49eSRichard Henderson 348cc5de49eSRichard Henderson tcg_gen_mulu2_i64(cpu_mac, high, t1, t2); 349cc5de49eSRichard Henderson tcg_gen_setcondi_i64(TCG_COND_NE, high, high, 0); 350cc5de49eSRichard Henderson tcg_gen_trunc_i64_tl(cpu_sr_cy, high); 351cc5de49eSRichard Henderson tcg_temp_free_i64(high); 352cc5de49eSRichard Henderson 353cc5de49eSRichard Henderson gen_ove_cy(dc); 354cc5de49eSRichard Henderson } 355cc5de49eSRichard Henderson tcg_temp_free_i64(t1); 356cc5de49eSRichard Henderson tcg_temp_free_i64(t2); 357cc5de49eSRichard Henderson } 358cc5de49eSRichard Henderson 3596f7332baSRichard Henderson static void gen_mac(DisasContext *dc, TCGv srca, TCGv srcb) 3606f7332baSRichard Henderson { 3616f7332baSRichard Henderson TCGv_i64 t1 = tcg_temp_new_i64(); 3626f7332baSRichard Henderson TCGv_i64 t2 = tcg_temp_new_i64(); 3636f7332baSRichard Henderson 3646f7332baSRichard Henderson tcg_gen_ext_tl_i64(t1, srca); 3656f7332baSRichard Henderson tcg_gen_ext_tl_i64(t2, srcb); 3666f7332baSRichard Henderson tcg_gen_mul_i64(t1, t1, t2); 3676f7332baSRichard Henderson 3686f7332baSRichard Henderson /* Note that overflow is only computed during addition stage. */ 3696f7332baSRichard Henderson tcg_gen_xor_i64(t2, cpu_mac, t1); 3706f7332baSRichard Henderson tcg_gen_add_i64(cpu_mac, cpu_mac, t1); 3716f7332baSRichard Henderson tcg_gen_xor_i64(t1, t1, cpu_mac); 3726f7332baSRichard Henderson tcg_gen_andc_i64(t1, t1, t2); 3736f7332baSRichard Henderson tcg_temp_free_i64(t2); 3746f7332baSRichard Henderson 3756f7332baSRichard Henderson #if TARGET_LONG_BITS == 32 3766f7332baSRichard Henderson tcg_gen_extrh_i64_i32(cpu_sr_ov, t1); 3776f7332baSRichard Henderson #else 3786f7332baSRichard Henderson tcg_gen_mov_i64(cpu_sr_ov, t1); 3796f7332baSRichard Henderson #endif 3806f7332baSRichard Henderson tcg_temp_free_i64(t1); 3816f7332baSRichard Henderson 3826f7332baSRichard Henderson gen_ove_ov(dc); 3836f7332baSRichard Henderson } 3846f7332baSRichard Henderson 385cc5de49eSRichard Henderson static void gen_macu(DisasContext *dc, TCGv srca, TCGv srcb) 386cc5de49eSRichard Henderson { 387cc5de49eSRichard Henderson TCGv_i64 t1 = tcg_temp_new_i64(); 388cc5de49eSRichard Henderson TCGv_i64 t2 = tcg_temp_new_i64(); 389cc5de49eSRichard Henderson 390cc5de49eSRichard Henderson tcg_gen_extu_tl_i64(t1, srca); 391cc5de49eSRichard Henderson tcg_gen_extu_tl_i64(t2, srcb); 392cc5de49eSRichard Henderson tcg_gen_mul_i64(t1, t1, t2); 393cc5de49eSRichard Henderson tcg_temp_free_i64(t2); 394cc5de49eSRichard Henderson 395cc5de49eSRichard Henderson /* Note that overflow is only computed during addition stage. */ 396cc5de49eSRichard Henderson tcg_gen_add_i64(cpu_mac, cpu_mac, t1); 397cc5de49eSRichard Henderson tcg_gen_setcond_i64(TCG_COND_LTU, t1, cpu_mac, t1); 398cc5de49eSRichard Henderson tcg_gen_trunc_i64_tl(cpu_sr_cy, t1); 399cc5de49eSRichard Henderson tcg_temp_free_i64(t1); 400cc5de49eSRichard Henderson 401cc5de49eSRichard Henderson gen_ove_cy(dc); 402cc5de49eSRichard Henderson } 403cc5de49eSRichard Henderson 4046f7332baSRichard Henderson static void gen_msb(DisasContext *dc, TCGv srca, TCGv srcb) 4056f7332baSRichard Henderson { 4066f7332baSRichard Henderson TCGv_i64 t1 = tcg_temp_new_i64(); 4076f7332baSRichard Henderson TCGv_i64 t2 = tcg_temp_new_i64(); 4086f7332baSRichard Henderson 4096f7332baSRichard Henderson tcg_gen_ext_tl_i64(t1, srca); 4106f7332baSRichard Henderson tcg_gen_ext_tl_i64(t2, srcb); 4116f7332baSRichard Henderson tcg_gen_mul_i64(t1, t1, t2); 4126f7332baSRichard Henderson 4136f7332baSRichard Henderson /* Note that overflow is only computed during subtraction stage. */ 4146f7332baSRichard Henderson tcg_gen_xor_i64(t2, cpu_mac, t1); 4156f7332baSRichard Henderson tcg_gen_sub_i64(cpu_mac, cpu_mac, t1); 4166f7332baSRichard Henderson tcg_gen_xor_i64(t1, t1, cpu_mac); 4176f7332baSRichard Henderson tcg_gen_and_i64(t1, t1, t2); 4186f7332baSRichard Henderson tcg_temp_free_i64(t2); 4196f7332baSRichard Henderson 4206f7332baSRichard Henderson #if TARGET_LONG_BITS == 32 4216f7332baSRichard Henderson tcg_gen_extrh_i64_i32(cpu_sr_ov, t1); 4226f7332baSRichard Henderson #else 4236f7332baSRichard Henderson tcg_gen_mov_i64(cpu_sr_ov, t1); 4246f7332baSRichard Henderson #endif 4256f7332baSRichard Henderson tcg_temp_free_i64(t1); 4266f7332baSRichard Henderson 4276f7332baSRichard Henderson gen_ove_ov(dc); 4286f7332baSRichard Henderson } 4296f7332baSRichard Henderson 430cc5de49eSRichard Henderson static void gen_msbu(DisasContext *dc, TCGv srca, TCGv srcb) 431cc5de49eSRichard Henderson { 432cc5de49eSRichard Henderson TCGv_i64 t1 = tcg_temp_new_i64(); 433cc5de49eSRichard Henderson TCGv_i64 t2 = tcg_temp_new_i64(); 434cc5de49eSRichard Henderson 435cc5de49eSRichard Henderson tcg_gen_extu_tl_i64(t1, srca); 436cc5de49eSRichard Henderson tcg_gen_extu_tl_i64(t2, srcb); 437cc5de49eSRichard Henderson tcg_gen_mul_i64(t1, t1, t2); 438cc5de49eSRichard Henderson 439cc5de49eSRichard Henderson /* Note that overflow is only computed during subtraction stage. */ 440cc5de49eSRichard Henderson tcg_gen_setcond_i64(TCG_COND_LTU, t2, cpu_mac, t1); 441cc5de49eSRichard Henderson tcg_gen_sub_i64(cpu_mac, cpu_mac, t1); 442cc5de49eSRichard Henderson tcg_gen_trunc_i64_tl(cpu_sr_cy, t2); 443cc5de49eSRichard Henderson tcg_temp_free_i64(t2); 444cc5de49eSRichard Henderson tcg_temp_free_i64(t1); 445cc5de49eSRichard Henderson 446cc5de49eSRichard Henderson gen_ove_cy(dc); 447cc5de49eSRichard Henderson } 448cc5de49eSRichard Henderson 4493a7be554SRichard Henderson static bool trans_l_add(DisasContext *dc, arg_dab *a) 450bbe418f2SJia Liu { 451cdd0f459SRichard Henderson check_r0_write(dc, a->d); 4528bba7619SRichard Henderson gen_add(dc, cpu_R(dc, a->d), cpu_R(dc, a->a), cpu_R(dc, a->b)); 4536ad216abSRichard Henderson return true; 454bbe418f2SJia Liu } 455bbe418f2SJia Liu 4563a7be554SRichard Henderson static bool trans_l_addc(DisasContext *dc, arg_dab *a) 457bbe418f2SJia Liu { 458cdd0f459SRichard Henderson check_r0_write(dc, a->d); 4598bba7619SRichard Henderson gen_addc(dc, cpu_R(dc, a->d), cpu_R(dc, a->a), cpu_R(dc, a->b)); 4606ad216abSRichard Henderson return true; 4616ad216abSRichard Henderson } 4626ad216abSRichard Henderson 4633a7be554SRichard Henderson static bool trans_l_sub(DisasContext *dc, arg_dab *a) 4646ad216abSRichard Henderson { 465cdd0f459SRichard Henderson check_r0_write(dc, a->d); 4668bba7619SRichard Henderson gen_sub(dc, cpu_R(dc, a->d), cpu_R(dc, a->a), cpu_R(dc, a->b)); 4676ad216abSRichard Henderson return true; 4686ad216abSRichard Henderson } 4696ad216abSRichard Henderson 4703a7be554SRichard Henderson static bool trans_l_and(DisasContext *dc, arg_dab *a) 4716ad216abSRichard Henderson { 472cdd0f459SRichard Henderson check_r0_write(dc, a->d); 4738bba7619SRichard Henderson tcg_gen_and_tl(cpu_R(dc, a->d), cpu_R(dc, a->a), cpu_R(dc, a->b)); 4746ad216abSRichard Henderson return true; 4756ad216abSRichard Henderson } 4766ad216abSRichard Henderson 4773a7be554SRichard Henderson static bool trans_l_or(DisasContext *dc, arg_dab *a) 4786ad216abSRichard Henderson { 479cdd0f459SRichard Henderson check_r0_write(dc, a->d); 4808bba7619SRichard Henderson tcg_gen_or_tl(cpu_R(dc, a->d), cpu_R(dc, a->a), cpu_R(dc, a->b)); 4816ad216abSRichard Henderson return true; 4826ad216abSRichard Henderson } 4836ad216abSRichard Henderson 4843a7be554SRichard Henderson static bool trans_l_xor(DisasContext *dc, arg_dab *a) 4856ad216abSRichard Henderson { 486cdd0f459SRichard Henderson check_r0_write(dc, a->d); 4878bba7619SRichard Henderson tcg_gen_xor_tl(cpu_R(dc, a->d), cpu_R(dc, a->a), cpu_R(dc, a->b)); 4886ad216abSRichard Henderson return true; 4896ad216abSRichard Henderson } 4906ad216abSRichard Henderson 4913a7be554SRichard Henderson static bool trans_l_sll(DisasContext *dc, arg_dab *a) 4926ad216abSRichard Henderson { 493cdd0f459SRichard Henderson check_r0_write(dc, a->d); 4948bba7619SRichard Henderson tcg_gen_shl_tl(cpu_R(dc, a->d), cpu_R(dc, a->a), cpu_R(dc, a->b)); 4956ad216abSRichard Henderson return true; 4966ad216abSRichard Henderson } 4976ad216abSRichard Henderson 4983a7be554SRichard Henderson static bool trans_l_srl(DisasContext *dc, arg_dab *a) 4996ad216abSRichard Henderson { 500cdd0f459SRichard Henderson check_r0_write(dc, a->d); 5018bba7619SRichard Henderson tcg_gen_shr_tl(cpu_R(dc, a->d), cpu_R(dc, a->a), cpu_R(dc, a->b)); 5026ad216abSRichard Henderson return true; 5036ad216abSRichard Henderson } 5046ad216abSRichard Henderson 5053a7be554SRichard Henderson static bool trans_l_sra(DisasContext *dc, arg_dab *a) 5066ad216abSRichard Henderson { 507cdd0f459SRichard Henderson check_r0_write(dc, a->d); 5088bba7619SRichard Henderson tcg_gen_sar_tl(cpu_R(dc, a->d), cpu_R(dc, a->a), cpu_R(dc, a->b)); 5096ad216abSRichard Henderson return true; 5106ad216abSRichard Henderson } 5116ad216abSRichard Henderson 5123a7be554SRichard Henderson static bool trans_l_ror(DisasContext *dc, arg_dab *a) 5136ad216abSRichard Henderson { 514cdd0f459SRichard Henderson check_r0_write(dc, a->d); 5158bba7619SRichard Henderson tcg_gen_rotr_tl(cpu_R(dc, a->d), cpu_R(dc, a->a), cpu_R(dc, a->b)); 5166ad216abSRichard Henderson return true; 5176ad216abSRichard Henderson } 5186ad216abSRichard Henderson 5193a7be554SRichard Henderson static bool trans_l_exths(DisasContext *dc, arg_da *a) 5206ad216abSRichard Henderson { 521cdd0f459SRichard Henderson check_r0_write(dc, a->d); 5228bba7619SRichard Henderson tcg_gen_ext16s_tl(cpu_R(dc, a->d), cpu_R(dc, a->a)); 5236ad216abSRichard Henderson return true; 5246ad216abSRichard Henderson } 5256ad216abSRichard Henderson 5263a7be554SRichard Henderson static bool trans_l_extbs(DisasContext *dc, arg_da *a) 5276ad216abSRichard Henderson { 528cdd0f459SRichard Henderson check_r0_write(dc, a->d); 5298bba7619SRichard Henderson tcg_gen_ext8s_tl(cpu_R(dc, a->d), cpu_R(dc, a->a)); 5306ad216abSRichard Henderson return true; 5316ad216abSRichard Henderson } 5326ad216abSRichard Henderson 5333a7be554SRichard Henderson static bool trans_l_exthz(DisasContext *dc, arg_da *a) 5346ad216abSRichard Henderson { 535cdd0f459SRichard Henderson check_r0_write(dc, a->d); 5368bba7619SRichard Henderson tcg_gen_ext16u_tl(cpu_R(dc, a->d), cpu_R(dc, a->a)); 5376ad216abSRichard Henderson return true; 5386ad216abSRichard Henderson } 5396ad216abSRichard Henderson 5403a7be554SRichard Henderson static bool trans_l_extbz(DisasContext *dc, arg_da *a) 5416ad216abSRichard Henderson { 542cdd0f459SRichard Henderson check_r0_write(dc, a->d); 5438bba7619SRichard Henderson tcg_gen_ext8u_tl(cpu_R(dc, a->d), cpu_R(dc, a->a)); 5446ad216abSRichard Henderson return true; 5456ad216abSRichard Henderson } 5466ad216abSRichard Henderson 5473a7be554SRichard Henderson static bool trans_l_cmov(DisasContext *dc, arg_dab *a) 5486ad216abSRichard Henderson { 5496ad216abSRichard Henderson TCGv zero; 5506ad216abSRichard Henderson 551cdd0f459SRichard Henderson check_r0_write(dc, a->d); 5526ad216abSRichard Henderson zero = tcg_const_tl(0); 5538bba7619SRichard Henderson tcg_gen_movcond_tl(TCG_COND_NE, cpu_R(dc, a->d), cpu_sr_f, zero, 5548bba7619SRichard Henderson cpu_R(dc, a->a), cpu_R(dc, a->b)); 555784696d1SRichard Henderson tcg_temp_free(zero); 5566ad216abSRichard Henderson return true; 557bbe418f2SJia Liu } 558bbe418f2SJia Liu 5593a7be554SRichard Henderson static bool trans_l_ff1(DisasContext *dc, arg_da *a) 5606ad216abSRichard Henderson { 561cdd0f459SRichard Henderson check_r0_write(dc, a->d); 5628bba7619SRichard Henderson tcg_gen_ctzi_tl(cpu_R(dc, a->d), cpu_R(dc, a->a), -1); 5638bba7619SRichard Henderson tcg_gen_addi_tl(cpu_R(dc, a->d), cpu_R(dc, a->d), 1); 5646ad216abSRichard Henderson return true; 565cf2ae442SRichard Henderson } 566cf2ae442SRichard Henderson 5673a7be554SRichard Henderson static bool trans_l_fl1(DisasContext *dc, arg_da *a) 5686ad216abSRichard Henderson { 569cdd0f459SRichard Henderson check_r0_write(dc, a->d); 5708bba7619SRichard Henderson tcg_gen_clzi_tl(cpu_R(dc, a->d), cpu_R(dc, a->a), TARGET_LONG_BITS); 5718bba7619SRichard Henderson tcg_gen_subfi_tl(cpu_R(dc, a->d), TARGET_LONG_BITS, cpu_R(dc, a->d)); 5726ad216abSRichard Henderson return true; 573bbe418f2SJia Liu } 574bbe418f2SJia Liu 5753a7be554SRichard Henderson static bool trans_l_mul(DisasContext *dc, arg_dab *a) 5766ad216abSRichard Henderson { 577cdd0f459SRichard Henderson check_r0_write(dc, a->d); 5788bba7619SRichard Henderson gen_mul(dc, cpu_R(dc, a->d), cpu_R(dc, a->a), cpu_R(dc, a->b)); 5796ad216abSRichard Henderson return true; 580bbe418f2SJia Liu } 5816ad216abSRichard Henderson 5823a7be554SRichard Henderson static bool trans_l_mulu(DisasContext *dc, arg_dab *a) 5836ad216abSRichard Henderson { 584cdd0f459SRichard Henderson check_r0_write(dc, a->d); 5858bba7619SRichard Henderson gen_mulu(dc, cpu_R(dc, a->d), cpu_R(dc, a->a), cpu_R(dc, a->b)); 5866ad216abSRichard Henderson return true; 587bbe418f2SJia Liu } 5886ad216abSRichard Henderson 5893a7be554SRichard Henderson static bool trans_l_div(DisasContext *dc, arg_dab *a) 5906ad216abSRichard Henderson { 591cdd0f459SRichard Henderson check_r0_write(dc, a->d); 5928bba7619SRichard Henderson gen_div(dc, cpu_R(dc, a->d), cpu_R(dc, a->a), cpu_R(dc, a->b)); 5936ad216abSRichard Henderson return true; 5946ad216abSRichard Henderson } 5956ad216abSRichard Henderson 5963a7be554SRichard Henderson static bool trans_l_divu(DisasContext *dc, arg_dab *a) 5976ad216abSRichard Henderson { 598cdd0f459SRichard Henderson check_r0_write(dc, a->d); 5998bba7619SRichard Henderson gen_divu(dc, cpu_R(dc, a->d), cpu_R(dc, a->a), cpu_R(dc, a->b)); 6006ad216abSRichard Henderson return true; 6016ad216abSRichard Henderson } 6026ad216abSRichard Henderson 6033a7be554SRichard Henderson static bool trans_l_muld(DisasContext *dc, arg_ab *a) 6046ad216abSRichard Henderson { 6058bba7619SRichard Henderson gen_muld(dc, cpu_R(dc, a->a), cpu_R(dc, a->b)); 6066ad216abSRichard Henderson return true; 6076ad216abSRichard Henderson } 6086ad216abSRichard Henderson 6093a7be554SRichard Henderson static bool trans_l_muldu(DisasContext *dc, arg_ab *a) 6106ad216abSRichard Henderson { 6118bba7619SRichard Henderson gen_muldu(dc, cpu_R(dc, a->a), cpu_R(dc, a->b)); 6126ad216abSRichard Henderson return true; 613bbe418f2SJia Liu } 614bbe418f2SJia Liu 6153a7be554SRichard Henderson static bool trans_l_j(DisasContext *dc, arg_l_j *a) 616136e13aeSRichard Henderson { 617136e13aeSRichard Henderson target_ulong tmp_pc = dc->base.pc_next + a->n * 4; 618136e13aeSRichard Henderson 619136e13aeSRichard Henderson tcg_gen_movi_tl(jmp_pc, tmp_pc); 6208000ba56SRichard Henderson dc->jmp_pc_imm = tmp_pc; 621136e13aeSRichard Henderson dc->delayed_branch = 2; 622136e13aeSRichard Henderson return true; 623136e13aeSRichard Henderson } 624136e13aeSRichard Henderson 6253a7be554SRichard Henderson static bool trans_l_jal(DisasContext *dc, arg_l_jal *a) 626136e13aeSRichard Henderson { 627136e13aeSRichard Henderson target_ulong tmp_pc = dc->base.pc_next + a->n * 4; 628136e13aeSRichard Henderson target_ulong ret_pc = dc->base.pc_next + 8; 629136e13aeSRichard Henderson 6308bba7619SRichard Henderson tcg_gen_movi_tl(cpu_regs[9], ret_pc); 631136e13aeSRichard Henderson /* Optimize jal being used to load the PC for PIC. */ 632136e13aeSRichard Henderson if (tmp_pc != ret_pc) { 633136e13aeSRichard Henderson tcg_gen_movi_tl(jmp_pc, tmp_pc); 6348000ba56SRichard Henderson dc->jmp_pc_imm = tmp_pc; 635136e13aeSRichard Henderson dc->delayed_branch = 2; 636136e13aeSRichard Henderson } 637136e13aeSRichard Henderson return true; 638136e13aeSRichard Henderson } 639136e13aeSRichard Henderson 640136e13aeSRichard Henderson static void do_bf(DisasContext *dc, arg_l_bf *a, TCGCond cond) 641136e13aeSRichard Henderson { 642136e13aeSRichard Henderson target_ulong tmp_pc = dc->base.pc_next + a->n * 4; 643136e13aeSRichard Henderson TCGv t_next = tcg_const_tl(dc->base.pc_next + 8); 644136e13aeSRichard Henderson TCGv t_true = tcg_const_tl(tmp_pc); 645136e13aeSRichard Henderson TCGv t_zero = tcg_const_tl(0); 646136e13aeSRichard Henderson 647136e13aeSRichard Henderson tcg_gen_movcond_tl(cond, jmp_pc, cpu_sr_f, t_zero, t_true, t_next); 648136e13aeSRichard Henderson 649136e13aeSRichard Henderson tcg_temp_free(t_next); 650136e13aeSRichard Henderson tcg_temp_free(t_true); 651136e13aeSRichard Henderson tcg_temp_free(t_zero); 652136e13aeSRichard Henderson dc->delayed_branch = 2; 653136e13aeSRichard Henderson } 654136e13aeSRichard Henderson 6553a7be554SRichard Henderson static bool trans_l_bf(DisasContext *dc, arg_l_bf *a) 656136e13aeSRichard Henderson { 657136e13aeSRichard Henderson do_bf(dc, a, TCG_COND_NE); 658136e13aeSRichard Henderson return true; 659136e13aeSRichard Henderson } 660136e13aeSRichard Henderson 6613a7be554SRichard Henderson static bool trans_l_bnf(DisasContext *dc, arg_l_bf *a) 662136e13aeSRichard Henderson { 663136e13aeSRichard Henderson do_bf(dc, a, TCG_COND_EQ); 664136e13aeSRichard Henderson return true; 665136e13aeSRichard Henderson } 666136e13aeSRichard Henderson 6673a7be554SRichard Henderson static bool trans_l_jr(DisasContext *dc, arg_l_jr *a) 668136e13aeSRichard Henderson { 6698bba7619SRichard Henderson tcg_gen_mov_tl(jmp_pc, cpu_R(dc, a->b)); 670136e13aeSRichard Henderson dc->delayed_branch = 2; 671136e13aeSRichard Henderson return true; 672136e13aeSRichard Henderson } 673136e13aeSRichard Henderson 6743a7be554SRichard Henderson static bool trans_l_jalr(DisasContext *dc, arg_l_jalr *a) 675136e13aeSRichard Henderson { 6768bba7619SRichard Henderson tcg_gen_mov_tl(jmp_pc, cpu_R(dc, a->b)); 6778bba7619SRichard Henderson tcg_gen_movi_tl(cpu_regs[9], dc->base.pc_next + 8); 678136e13aeSRichard Henderson dc->delayed_branch = 2; 679136e13aeSRichard Henderson return true; 680136e13aeSRichard Henderson } 681136e13aeSRichard Henderson 6823a7be554SRichard Henderson static bool trans_l_lwa(DisasContext *dc, arg_load *a) 683d80bff19SRichard Henderson { 684d80bff19SRichard Henderson TCGv ea; 685d80bff19SRichard Henderson 686cdd0f459SRichard Henderson check_r0_write(dc, a->d); 687d80bff19SRichard Henderson ea = tcg_temp_new(); 6888bba7619SRichard Henderson tcg_gen_addi_tl(ea, cpu_R(dc, a->a), a->i); 6898bba7619SRichard Henderson tcg_gen_qemu_ld_tl(cpu_R(dc, a->d), ea, dc->mem_idx, MO_TEUL); 690d80bff19SRichard Henderson tcg_gen_mov_tl(cpu_lock_addr, ea); 6918bba7619SRichard Henderson tcg_gen_mov_tl(cpu_lock_value, cpu_R(dc, a->d)); 692d80bff19SRichard Henderson tcg_temp_free(ea); 693d80bff19SRichard Henderson return true; 694d80bff19SRichard Henderson } 695d80bff19SRichard Henderson 69614776ab5STony Nguyen static void do_load(DisasContext *dc, arg_load *a, MemOp mop) 697d80bff19SRichard Henderson { 698d80bff19SRichard Henderson TCGv ea; 699d80bff19SRichard Henderson 700cdd0f459SRichard Henderson check_r0_write(dc, a->d); 701d80bff19SRichard Henderson ea = tcg_temp_new(); 7028bba7619SRichard Henderson tcg_gen_addi_tl(ea, cpu_R(dc, a->a), a->i); 7038bba7619SRichard Henderson tcg_gen_qemu_ld_tl(cpu_R(dc, a->d), ea, dc->mem_idx, mop); 704d80bff19SRichard Henderson tcg_temp_free(ea); 705d80bff19SRichard Henderson } 706d80bff19SRichard Henderson 7073a7be554SRichard Henderson static bool trans_l_lwz(DisasContext *dc, arg_load *a) 708d80bff19SRichard Henderson { 709d80bff19SRichard Henderson do_load(dc, a, MO_TEUL); 710d80bff19SRichard Henderson return true; 711d80bff19SRichard Henderson } 712d80bff19SRichard Henderson 7133a7be554SRichard Henderson static bool trans_l_lws(DisasContext *dc, arg_load *a) 714d80bff19SRichard Henderson { 715d80bff19SRichard Henderson do_load(dc, a, MO_TESL); 716d80bff19SRichard Henderson return true; 717d80bff19SRichard Henderson } 718d80bff19SRichard Henderson 7193a7be554SRichard Henderson static bool trans_l_lbz(DisasContext *dc, arg_load *a) 720d80bff19SRichard Henderson { 721d80bff19SRichard Henderson do_load(dc, a, MO_UB); 722d80bff19SRichard Henderson return true; 723d80bff19SRichard Henderson } 724d80bff19SRichard Henderson 7253a7be554SRichard Henderson static bool trans_l_lbs(DisasContext *dc, arg_load *a) 726d80bff19SRichard Henderson { 727d80bff19SRichard Henderson do_load(dc, a, MO_SB); 728d80bff19SRichard Henderson return true; 729d80bff19SRichard Henderson } 730d80bff19SRichard Henderson 7313a7be554SRichard Henderson static bool trans_l_lhz(DisasContext *dc, arg_load *a) 732d80bff19SRichard Henderson { 733d80bff19SRichard Henderson do_load(dc, a, MO_TEUW); 734d80bff19SRichard Henderson return true; 735d80bff19SRichard Henderson } 736d80bff19SRichard Henderson 7373a7be554SRichard Henderson static bool trans_l_lhs(DisasContext *dc, arg_load *a) 738d80bff19SRichard Henderson { 739d80bff19SRichard Henderson do_load(dc, a, MO_TESW); 740d80bff19SRichard Henderson return true; 741d80bff19SRichard Henderson } 742d80bff19SRichard Henderson 7433a7be554SRichard Henderson static bool trans_l_swa(DisasContext *dc, arg_store *a) 744d80bff19SRichard Henderson { 745d80bff19SRichard Henderson TCGv ea, val; 746d80bff19SRichard Henderson TCGLabel *lab_fail, *lab_done; 747d80bff19SRichard Henderson 748d80bff19SRichard Henderson ea = tcg_temp_new(); 7498bba7619SRichard Henderson tcg_gen_addi_tl(ea, cpu_R(dc, a->a), a->i); 750d80bff19SRichard Henderson 751d80bff19SRichard Henderson /* For TB_FLAGS_R0_0, the branch below invalidates the temporary assigned 7528bba7619SRichard Henderson to cpu_regs[0]. Since l.swa is quite often immediately followed by a 753d80bff19SRichard Henderson branch, don't bother reallocating; finish the TB using the "real" R0. 754d80bff19SRichard Henderson This also takes care of RB input across the branch. */ 755*d29f4368SRichard Henderson dc->R0 = cpu_regs[0]; 756d80bff19SRichard Henderson 757d80bff19SRichard Henderson lab_fail = gen_new_label(); 758d80bff19SRichard Henderson lab_done = gen_new_label(); 759d80bff19SRichard Henderson tcg_gen_brcond_tl(TCG_COND_NE, ea, cpu_lock_addr, lab_fail); 760d80bff19SRichard Henderson tcg_temp_free(ea); 761d80bff19SRichard Henderson 762d80bff19SRichard Henderson val = tcg_temp_new(); 763d80bff19SRichard Henderson tcg_gen_atomic_cmpxchg_tl(val, cpu_lock_addr, cpu_lock_value, 7648bba7619SRichard Henderson cpu_regs[a->b], dc->mem_idx, MO_TEUL); 765d80bff19SRichard Henderson tcg_gen_setcond_tl(TCG_COND_EQ, cpu_sr_f, val, cpu_lock_value); 766d80bff19SRichard Henderson tcg_temp_free(val); 767d80bff19SRichard Henderson 768d80bff19SRichard Henderson tcg_gen_br(lab_done); 769d80bff19SRichard Henderson 770d80bff19SRichard Henderson gen_set_label(lab_fail); 771d80bff19SRichard Henderson tcg_gen_movi_tl(cpu_sr_f, 0); 772d80bff19SRichard Henderson 773d80bff19SRichard Henderson gen_set_label(lab_done); 774d80bff19SRichard Henderson tcg_gen_movi_tl(cpu_lock_addr, -1); 775d80bff19SRichard Henderson return true; 776d80bff19SRichard Henderson } 777d80bff19SRichard Henderson 77814776ab5STony Nguyen static void do_store(DisasContext *dc, arg_store *a, MemOp mop) 779d80bff19SRichard Henderson { 780d80bff19SRichard Henderson TCGv t0 = tcg_temp_new(); 7818bba7619SRichard Henderson tcg_gen_addi_tl(t0, cpu_R(dc, a->a), a->i); 7828bba7619SRichard Henderson tcg_gen_qemu_st_tl(cpu_R(dc, a->b), t0, dc->mem_idx, mop); 783d80bff19SRichard Henderson tcg_temp_free(t0); 784d80bff19SRichard Henderson } 785d80bff19SRichard Henderson 7863a7be554SRichard Henderson static bool trans_l_sw(DisasContext *dc, arg_store *a) 787d80bff19SRichard Henderson { 788d80bff19SRichard Henderson do_store(dc, a, MO_TEUL); 789d80bff19SRichard Henderson return true; 790d80bff19SRichard Henderson } 791d80bff19SRichard Henderson 7923a7be554SRichard Henderson static bool trans_l_sb(DisasContext *dc, arg_store *a) 793d80bff19SRichard Henderson { 794d80bff19SRichard Henderson do_store(dc, a, MO_UB); 795d80bff19SRichard Henderson return true; 796d80bff19SRichard Henderson } 797d80bff19SRichard Henderson 7983a7be554SRichard Henderson static bool trans_l_sh(DisasContext *dc, arg_store *a) 799d80bff19SRichard Henderson { 800d80bff19SRichard Henderson do_store(dc, a, MO_TEUW); 801d80bff19SRichard Henderson return true; 802d80bff19SRichard Henderson } 803d80bff19SRichard Henderson 8043a7be554SRichard Henderson static bool trans_l_nop(DisasContext *dc, arg_l_nop *a) 805bbe418f2SJia Liu { 8068816f70bSRichard Henderson return true; 8078816f70bSRichard Henderson } 8088816f70bSRichard Henderson 8093a7be554SRichard Henderson static bool trans_l_addi(DisasContext *dc, arg_rri *a) 8108816f70bSRichard Henderson { 8119ecaa27eSRichard Henderson TCGv t0; 8125631e69cSRichard Henderson 813cdd0f459SRichard Henderson check_r0_write(dc, a->d); 8148816f70bSRichard Henderson t0 = tcg_const_tl(a->i); 8158bba7619SRichard Henderson gen_add(dc, cpu_R(dc, a->d), cpu_R(dc, a->a), t0); 8166f7332baSRichard Henderson tcg_temp_free(t0); 8178816f70bSRichard Henderson return true; 8188816f70bSRichard Henderson } 819bbe418f2SJia Liu 8203a7be554SRichard Henderson static bool trans_l_addic(DisasContext *dc, arg_rri *a) 821bbe418f2SJia Liu { 8228816f70bSRichard Henderson TCGv t0; 8238816f70bSRichard Henderson 824cdd0f459SRichard Henderson check_r0_write(dc, a->d); 8258816f70bSRichard Henderson t0 = tcg_const_tl(a->i); 8268bba7619SRichard Henderson gen_addc(dc, cpu_R(dc, a->d), cpu_R(dc, a->a), t0); 8278816f70bSRichard Henderson tcg_temp_free(t0); 8288816f70bSRichard Henderson return true; 8298816f70bSRichard Henderson } 8308816f70bSRichard Henderson 8313a7be554SRichard Henderson static bool trans_l_muli(DisasContext *dc, arg_rri *a) 8328816f70bSRichard Henderson { 8338816f70bSRichard Henderson TCGv t0; 8348816f70bSRichard Henderson 835cdd0f459SRichard Henderson check_r0_write(dc, a->d); 8368816f70bSRichard Henderson t0 = tcg_const_tl(a->i); 8378bba7619SRichard Henderson gen_mul(dc, cpu_R(dc, a->d), cpu_R(dc, a->a), t0); 8388816f70bSRichard Henderson tcg_temp_free(t0); 8398816f70bSRichard Henderson return true; 8408816f70bSRichard Henderson } 8418816f70bSRichard Henderson 8423a7be554SRichard Henderson static bool trans_l_maci(DisasContext *dc, arg_l_maci *a) 8438816f70bSRichard Henderson { 8448816f70bSRichard Henderson TCGv t0; 8458816f70bSRichard Henderson 8468816f70bSRichard Henderson t0 = tcg_const_tl(a->i); 8478bba7619SRichard Henderson gen_mac(dc, cpu_R(dc, a->a), t0); 8488816f70bSRichard Henderson tcg_temp_free(t0); 8498816f70bSRichard Henderson return true; 8508816f70bSRichard Henderson } 8518816f70bSRichard Henderson 8523a7be554SRichard Henderson static bool trans_l_andi(DisasContext *dc, arg_rrk *a) 8538816f70bSRichard Henderson { 854cdd0f459SRichard Henderson check_r0_write(dc, a->d); 8558bba7619SRichard Henderson tcg_gen_andi_tl(cpu_R(dc, a->d), cpu_R(dc, a->a), a->k); 8568816f70bSRichard Henderson return true; 8578816f70bSRichard Henderson } 8588816f70bSRichard Henderson 8593a7be554SRichard Henderson static bool trans_l_ori(DisasContext *dc, arg_rrk *a) 8608816f70bSRichard Henderson { 861cdd0f459SRichard Henderson check_r0_write(dc, a->d); 8628bba7619SRichard Henderson tcg_gen_ori_tl(cpu_R(dc, a->d), cpu_R(dc, a->a), a->k); 8638816f70bSRichard Henderson return true; 8648816f70bSRichard Henderson } 8658816f70bSRichard Henderson 8663a7be554SRichard Henderson static bool trans_l_xori(DisasContext *dc, arg_rri *a) 8678816f70bSRichard Henderson { 868cdd0f459SRichard Henderson check_r0_write(dc, a->d); 8698bba7619SRichard Henderson tcg_gen_xori_tl(cpu_R(dc, a->d), cpu_R(dc, a->a), a->i); 8708816f70bSRichard Henderson return true; 8718816f70bSRichard Henderson } 8728816f70bSRichard Henderson 8733a7be554SRichard Henderson static bool trans_l_mfspr(DisasContext *dc, arg_l_mfspr *a) 8748816f70bSRichard Henderson { 875cdd0f459SRichard Henderson check_r0_write(dc, a->d); 8768816f70bSRichard Henderson 8772ba65417SRichard Henderson if (is_user(dc)) { 878bbe418f2SJia Liu gen_illegal_exception(dc); 8798816f70bSRichard Henderson } else { 880c28fa81fSRichard Henderson TCGv spr = tcg_temp_new(); 8818bba7619SRichard Henderson tcg_gen_ori_tl(spr, cpu_R(dc, a->a), a->k); 8828bba7619SRichard Henderson gen_helper_mfspr(cpu_R(dc, a->d), cpu_env, cpu_R(dc, a->d), spr); 883c28fa81fSRichard Henderson tcg_temp_free(spr); 8844dd044c6SJia Liu } 8858816f70bSRichard Henderson return true; 8868816f70bSRichard Henderson } 887bbe418f2SJia Liu 8883a7be554SRichard Henderson static bool trans_l_mtspr(DisasContext *dc, arg_l_mtspr *a) 8894dd044c6SJia Liu { 8902ba65417SRichard Henderson if (is_user(dc)) { 8914dd044c6SJia Liu gen_illegal_exception(dc); 8928816f70bSRichard Henderson } else { 893c28fa81fSRichard Henderson TCGv spr; 89401ec3ec9SRichard Henderson 89501ec3ec9SRichard Henderson /* For SR, we will need to exit the TB to recognize the new 89601ec3ec9SRichard Henderson * exception state. For NPC, in theory this counts as a branch 89701ec3ec9SRichard Henderson * (although the SPR only exists for use by an ICE). Save all 89801ec3ec9SRichard Henderson * of the cpu state first, allowing it to be overwritten. 89901ec3ec9SRichard Henderson */ 90001ec3ec9SRichard Henderson if (dc->delayed_branch) { 90101ec3ec9SRichard Henderson tcg_gen_mov_tl(cpu_pc, jmp_pc); 90201ec3ec9SRichard Henderson tcg_gen_discard_tl(jmp_pc); 90301ec3ec9SRichard Henderson } else { 90401ec3ec9SRichard Henderson tcg_gen_movi_tl(cpu_pc, dc->base.pc_next + 4); 90501ec3ec9SRichard Henderson } 90601ec3ec9SRichard Henderson dc->base.is_jmp = DISAS_EXIT; 90701ec3ec9SRichard Henderson 908c28fa81fSRichard Henderson spr = tcg_temp_new(); 9098bba7619SRichard Henderson tcg_gen_ori_tl(spr, cpu_R(dc, a->a), a->k); 9108bba7619SRichard Henderson gen_helper_mtspr(cpu_env, spr, cpu_R(dc, a->b)); 911c28fa81fSRichard Henderson tcg_temp_free(spr); 9124dd044c6SJia Liu } 9138816f70bSRichard Henderson return true; 914bbe418f2SJia Liu } 915bbe418f2SJia Liu 9163a7be554SRichard Henderson static bool trans_l_mac(DisasContext *dc, arg_ab *a) 917bbe418f2SJia Liu { 9188bba7619SRichard Henderson gen_mac(dc, cpu_R(dc, a->a), cpu_R(dc, a->b)); 91999d863d6SRichard Henderson return true; 920bbe418f2SJia Liu } 92199d863d6SRichard Henderson 9223a7be554SRichard Henderson static bool trans_l_msb(DisasContext *dc, arg_ab *a) 92399d863d6SRichard Henderson { 9248bba7619SRichard Henderson gen_msb(dc, cpu_R(dc, a->a), cpu_R(dc, a->b)); 92599d863d6SRichard Henderson return true; 92699d863d6SRichard Henderson } 92799d863d6SRichard Henderson 9283a7be554SRichard Henderson static bool trans_l_macu(DisasContext *dc, arg_ab *a) 92999d863d6SRichard Henderson { 9308bba7619SRichard Henderson gen_macu(dc, cpu_R(dc, a->a), cpu_R(dc, a->b)); 93199d863d6SRichard Henderson return true; 93299d863d6SRichard Henderson } 93399d863d6SRichard Henderson 9343a7be554SRichard Henderson static bool trans_l_msbu(DisasContext *dc, arg_ab *a) 93599d863d6SRichard Henderson { 9368bba7619SRichard Henderson gen_msbu(dc, cpu_R(dc, a->a), cpu_R(dc, a->b)); 93799d863d6SRichard Henderson return true; 938bbe418f2SJia Liu } 939bbe418f2SJia Liu 9403a7be554SRichard Henderson static bool trans_l_slli(DisasContext *dc, arg_dal *a) 941bbe418f2SJia Liu { 942cdd0f459SRichard Henderson check_r0_write(dc, a->d); 9438bba7619SRichard Henderson tcg_gen_shli_tl(cpu_R(dc, a->d), cpu_R(dc, a->a), 9448bba7619SRichard Henderson a->l & (TARGET_LONG_BITS - 1)); 945e20c2592SRichard Henderson return true; 946bbe418f2SJia Liu } 947e20c2592SRichard Henderson 9483a7be554SRichard Henderson static bool trans_l_srli(DisasContext *dc, arg_dal *a) 949e20c2592SRichard Henderson { 950cdd0f459SRichard Henderson check_r0_write(dc, a->d); 9518bba7619SRichard Henderson tcg_gen_shri_tl(cpu_R(dc, a->d), cpu_R(dc, a->a), 9528bba7619SRichard Henderson a->l & (TARGET_LONG_BITS - 1)); 953e20c2592SRichard Henderson return true; 954e20c2592SRichard Henderson } 955e20c2592SRichard Henderson 9563a7be554SRichard Henderson static bool trans_l_srai(DisasContext *dc, arg_dal *a) 957e20c2592SRichard Henderson { 958cdd0f459SRichard Henderson check_r0_write(dc, a->d); 9598bba7619SRichard Henderson tcg_gen_sari_tl(cpu_R(dc, a->d), cpu_R(dc, a->a), 9608bba7619SRichard Henderson a->l & (TARGET_LONG_BITS - 1)); 961e20c2592SRichard Henderson return true; 962e20c2592SRichard Henderson } 963e20c2592SRichard Henderson 9643a7be554SRichard Henderson static bool trans_l_rori(DisasContext *dc, arg_dal *a) 965e20c2592SRichard Henderson { 966cdd0f459SRichard Henderson check_r0_write(dc, a->d); 9678bba7619SRichard Henderson tcg_gen_rotri_tl(cpu_R(dc, a->d), cpu_R(dc, a->a), 9688bba7619SRichard Henderson a->l & (TARGET_LONG_BITS - 1)); 969e20c2592SRichard Henderson return true; 970bbe418f2SJia Liu } 971bbe418f2SJia Liu 9723a7be554SRichard Henderson static bool trans_l_movhi(DisasContext *dc, arg_l_movhi *a) 973bbe418f2SJia Liu { 974cdd0f459SRichard Henderson check_r0_write(dc, a->d); 9758bba7619SRichard Henderson tcg_gen_movi_tl(cpu_R(dc, a->d), a->k << 16); 976e720a571SRichard Henderson return true; 977bbe418f2SJia Liu } 978e720a571SRichard Henderson 9793a7be554SRichard Henderson static bool trans_l_macrc(DisasContext *dc, arg_l_macrc *a) 980e720a571SRichard Henderson { 981cdd0f459SRichard Henderson check_r0_write(dc, a->d); 9828bba7619SRichard Henderson tcg_gen_trunc_i64_tl(cpu_R(dc, a->d), cpu_mac); 983e720a571SRichard Henderson tcg_gen_movi_i64(cpu_mac, 0); 984e720a571SRichard Henderson return true; 985bbe418f2SJia Liu } 986bbe418f2SJia Liu 9873a7be554SRichard Henderson static bool trans_l_sfeq(DisasContext *dc, arg_ab *a) 988bbe418f2SJia Liu { 9898bba7619SRichard Henderson tcg_gen_setcond_tl(TCG_COND_EQ, cpu_sr_f, 9908bba7619SRichard Henderson cpu_R(dc, a->a), cpu_R(dc, a->b)); 991fbb3e29aSRichard Henderson return true; 992bbe418f2SJia Liu } 993fbb3e29aSRichard Henderson 9943a7be554SRichard Henderson static bool trans_l_sfne(DisasContext *dc, arg_ab *a) 995fbb3e29aSRichard Henderson { 9968bba7619SRichard Henderson tcg_gen_setcond_tl(TCG_COND_NE, cpu_sr_f, 9978bba7619SRichard Henderson cpu_R(dc, a->a), cpu_R(dc, a->b)); 998fbb3e29aSRichard Henderson return true; 999fbb3e29aSRichard Henderson } 1000fbb3e29aSRichard Henderson 10013a7be554SRichard Henderson static bool trans_l_sfgtu(DisasContext *dc, arg_ab *a) 1002fbb3e29aSRichard Henderson { 10038bba7619SRichard Henderson tcg_gen_setcond_tl(TCG_COND_GTU, cpu_sr_f, 10048bba7619SRichard Henderson cpu_R(dc, a->a), cpu_R(dc, a->b)); 1005fbb3e29aSRichard Henderson return true; 1006fbb3e29aSRichard Henderson } 1007fbb3e29aSRichard Henderson 10083a7be554SRichard Henderson static bool trans_l_sfgeu(DisasContext *dc, arg_ab *a) 1009fbb3e29aSRichard Henderson { 10108bba7619SRichard Henderson tcg_gen_setcond_tl(TCG_COND_GEU, cpu_sr_f, 10118bba7619SRichard Henderson cpu_R(dc, a->a), cpu_R(dc, a->b)); 1012fbb3e29aSRichard Henderson return true; 1013fbb3e29aSRichard Henderson } 1014fbb3e29aSRichard Henderson 10153a7be554SRichard Henderson static bool trans_l_sfltu(DisasContext *dc, arg_ab *a) 1016fbb3e29aSRichard Henderson { 10178bba7619SRichard Henderson tcg_gen_setcond_tl(TCG_COND_LTU, cpu_sr_f, 10188bba7619SRichard Henderson cpu_R(dc, a->a), cpu_R(dc, a->b)); 1019fbb3e29aSRichard Henderson return true; 1020fbb3e29aSRichard Henderson } 1021fbb3e29aSRichard Henderson 10223a7be554SRichard Henderson static bool trans_l_sfleu(DisasContext *dc, arg_ab *a) 1023fbb3e29aSRichard Henderson { 10248bba7619SRichard Henderson tcg_gen_setcond_tl(TCG_COND_LEU, cpu_sr_f, 10258bba7619SRichard Henderson cpu_R(dc, a->a), cpu_R(dc, a->b)); 1026fbb3e29aSRichard Henderson return true; 1027fbb3e29aSRichard Henderson } 1028fbb3e29aSRichard Henderson 10293a7be554SRichard Henderson static bool trans_l_sfgts(DisasContext *dc, arg_ab *a) 1030fbb3e29aSRichard Henderson { 10318bba7619SRichard Henderson tcg_gen_setcond_tl(TCG_COND_GT, cpu_sr_f, 10328bba7619SRichard Henderson cpu_R(dc, a->a), cpu_R(dc, a->b)); 1033fbb3e29aSRichard Henderson return true; 1034fbb3e29aSRichard Henderson } 1035fbb3e29aSRichard Henderson 10363a7be554SRichard Henderson static bool trans_l_sfges(DisasContext *dc, arg_ab *a) 1037fbb3e29aSRichard Henderson { 10388bba7619SRichard Henderson tcg_gen_setcond_tl(TCG_COND_GE, cpu_sr_f, 10398bba7619SRichard Henderson cpu_R(dc, a->a), cpu_R(dc, a->b)); 1040fbb3e29aSRichard Henderson return true; 1041fbb3e29aSRichard Henderson } 1042fbb3e29aSRichard Henderson 10433a7be554SRichard Henderson static bool trans_l_sflts(DisasContext *dc, arg_ab *a) 1044fbb3e29aSRichard Henderson { 10458bba7619SRichard Henderson tcg_gen_setcond_tl(TCG_COND_LT, cpu_sr_f, 10468bba7619SRichard Henderson cpu_R(dc, a->a), cpu_R(dc, a->b)); 1047fbb3e29aSRichard Henderson return true; 1048fbb3e29aSRichard Henderson } 1049fbb3e29aSRichard Henderson 10503a7be554SRichard Henderson static bool trans_l_sfles(DisasContext *dc, arg_ab *a) 1051fbb3e29aSRichard Henderson { 10528bba7619SRichard Henderson tcg_gen_setcond_tl(TCG_COND_LE, 10538bba7619SRichard Henderson cpu_sr_f, cpu_R(dc, a->a), cpu_R(dc, a->b)); 1054fbb3e29aSRichard Henderson return true; 1055bbe418f2SJia Liu } 1056bbe418f2SJia Liu 10573a7be554SRichard Henderson static bool trans_l_sfeqi(DisasContext *dc, arg_ai *a) 1058bbe418f2SJia Liu { 10598bba7619SRichard Henderson tcg_gen_setcondi_tl(TCG_COND_EQ, cpu_sr_f, cpu_R(dc, a->a), a->i); 1060032de4fcSRichard Henderson return true; 1061bbe418f2SJia Liu } 1062032de4fcSRichard Henderson 10633a7be554SRichard Henderson static bool trans_l_sfnei(DisasContext *dc, arg_ai *a) 1064032de4fcSRichard Henderson { 10658bba7619SRichard Henderson tcg_gen_setcondi_tl(TCG_COND_NE, cpu_sr_f, cpu_R(dc, a->a), a->i); 1066032de4fcSRichard Henderson return true; 1067032de4fcSRichard Henderson } 1068032de4fcSRichard Henderson 10693a7be554SRichard Henderson static bool trans_l_sfgtui(DisasContext *dc, arg_ai *a) 1070032de4fcSRichard Henderson { 10718bba7619SRichard Henderson tcg_gen_setcondi_tl(TCG_COND_GTU, cpu_sr_f, cpu_R(dc, a->a), a->i); 1072032de4fcSRichard Henderson return true; 1073032de4fcSRichard Henderson } 1074032de4fcSRichard Henderson 10753a7be554SRichard Henderson static bool trans_l_sfgeui(DisasContext *dc, arg_ai *a) 1076032de4fcSRichard Henderson { 10778bba7619SRichard Henderson tcg_gen_setcondi_tl(TCG_COND_GEU, cpu_sr_f, cpu_R(dc, a->a), a->i); 1078032de4fcSRichard Henderson return true; 1079032de4fcSRichard Henderson } 1080032de4fcSRichard Henderson 10813a7be554SRichard Henderson static bool trans_l_sfltui(DisasContext *dc, arg_ai *a) 1082032de4fcSRichard Henderson { 10838bba7619SRichard Henderson tcg_gen_setcondi_tl(TCG_COND_LTU, cpu_sr_f, cpu_R(dc, a->a), a->i); 1084032de4fcSRichard Henderson return true; 1085032de4fcSRichard Henderson } 1086032de4fcSRichard Henderson 10873a7be554SRichard Henderson static bool trans_l_sfleui(DisasContext *dc, arg_ai *a) 1088032de4fcSRichard Henderson { 10898bba7619SRichard Henderson tcg_gen_setcondi_tl(TCG_COND_LEU, cpu_sr_f, cpu_R(dc, a->a), a->i); 1090032de4fcSRichard Henderson return true; 1091032de4fcSRichard Henderson } 1092032de4fcSRichard Henderson 10933a7be554SRichard Henderson static bool trans_l_sfgtsi(DisasContext *dc, arg_ai *a) 1094032de4fcSRichard Henderson { 10958bba7619SRichard Henderson tcg_gen_setcondi_tl(TCG_COND_GT, cpu_sr_f, cpu_R(dc, a->a), a->i); 1096032de4fcSRichard Henderson return true; 1097032de4fcSRichard Henderson } 1098032de4fcSRichard Henderson 10993a7be554SRichard Henderson static bool trans_l_sfgesi(DisasContext *dc, arg_ai *a) 1100032de4fcSRichard Henderson { 11018bba7619SRichard Henderson tcg_gen_setcondi_tl(TCG_COND_GE, cpu_sr_f, cpu_R(dc, a->a), a->i); 1102032de4fcSRichard Henderson return true; 1103032de4fcSRichard Henderson } 1104032de4fcSRichard Henderson 11053a7be554SRichard Henderson static bool trans_l_sfltsi(DisasContext *dc, arg_ai *a) 1106032de4fcSRichard Henderson { 11078bba7619SRichard Henderson tcg_gen_setcondi_tl(TCG_COND_LT, cpu_sr_f, cpu_R(dc, a->a), a->i); 1108032de4fcSRichard Henderson return true; 1109032de4fcSRichard Henderson } 1110032de4fcSRichard Henderson 11113a7be554SRichard Henderson static bool trans_l_sflesi(DisasContext *dc, arg_ai *a) 1112032de4fcSRichard Henderson { 11138bba7619SRichard Henderson tcg_gen_setcondi_tl(TCG_COND_LE, cpu_sr_f, cpu_R(dc, a->a), a->i); 1114032de4fcSRichard Henderson return true; 1115bbe418f2SJia Liu } 1116bbe418f2SJia Liu 11173a7be554SRichard Henderson static bool trans_l_sys(DisasContext *dc, arg_l_sys *a) 1118bbe418f2SJia Liu { 11191ffa4bceSEmilio G. Cota tcg_gen_movi_tl(cpu_pc, dc->base.pc_next); 1120bbe418f2SJia Liu gen_exception(dc, EXCP_SYSCALL); 11211ffa4bceSEmilio G. Cota dc->base.is_jmp = DISAS_NORETURN; 11227de9729fSRichard Henderson return true; 11237de9729fSRichard Henderson } 1124bbe418f2SJia Liu 11253a7be554SRichard Henderson static bool trans_l_trap(DisasContext *dc, arg_l_trap *a) 11267de9729fSRichard Henderson { 11271ffa4bceSEmilio G. Cota tcg_gen_movi_tl(cpu_pc, dc->base.pc_next); 1128bbe418f2SJia Liu gen_exception(dc, EXCP_TRAP); 11291ffa4bceSEmilio G. Cota dc->base.is_jmp = DISAS_NORETURN; 11307de9729fSRichard Henderson return true; 11317de9729fSRichard Henderson } 1132bbe418f2SJia Liu 11333a7be554SRichard Henderson static bool trans_l_msync(DisasContext *dc, arg_l_msync *a) 11347de9729fSRichard Henderson { 113524fc5c0fSRichard Henderson tcg_gen_mb(TCG_MO_ALL); 11367de9729fSRichard Henderson return true; 1137bbe418f2SJia Liu } 11387de9729fSRichard Henderson 11393a7be554SRichard Henderson static bool trans_l_psync(DisasContext *dc, arg_l_psync *a) 11407de9729fSRichard Henderson { 11417de9729fSRichard Henderson return true; 11427de9729fSRichard Henderson } 11437de9729fSRichard Henderson 11443a7be554SRichard Henderson static bool trans_l_csync(DisasContext *dc, arg_l_csync *a) 11457de9729fSRichard Henderson { 11467de9729fSRichard Henderson return true; 1147bbe418f2SJia Liu } 1148bbe418f2SJia Liu 11493a7be554SRichard Henderson static bool trans_l_rfe(DisasContext *dc, arg_l_rfe *a) 11508816f70bSRichard Henderson { 11512ba65417SRichard Henderson if (is_user(dc)) { 11528816f70bSRichard Henderson gen_illegal_exception(dc); 11538816f70bSRichard Henderson } else { 11548816f70bSRichard Henderson gen_helper_rfe(cpu_env); 115564e46c95SRichard Henderson dc->base.is_jmp = DISAS_EXIT; 11568816f70bSRichard Henderson } 11578816f70bSRichard Henderson return true; 11588816f70bSRichard Henderson } 11598816f70bSRichard Henderson 11606fd204a2SRichard Henderson static void do_fp2(DisasContext *dc, arg_da *a, 11616fd204a2SRichard Henderson void (*fn)(TCGv, TCGv_env, TCGv)) 1162bbe418f2SJia Liu { 1163cdd0f459SRichard Henderson check_r0_write(dc, a->d); 11648bba7619SRichard Henderson fn(cpu_R(dc, a->d), cpu_env, cpu_R(dc, a->a)); 11654e2d3007SRichard Henderson gen_helper_update_fpcsr(cpu_env); 1166bbe418f2SJia Liu } 11676fd204a2SRichard Henderson 11686fd204a2SRichard Henderson static void do_fp3(DisasContext *dc, arg_dab *a, 11696fd204a2SRichard Henderson void (*fn)(TCGv, TCGv_env, TCGv, TCGv)) 11706fd204a2SRichard Henderson { 1171cdd0f459SRichard Henderson check_r0_write(dc, a->d); 11728bba7619SRichard Henderson fn(cpu_R(dc, a->d), cpu_env, cpu_R(dc, a->a), cpu_R(dc, a->b)); 11736fd204a2SRichard Henderson gen_helper_update_fpcsr(cpu_env); 11746fd204a2SRichard Henderson } 11756fd204a2SRichard Henderson 11766fd204a2SRichard Henderson static void do_fpcmp(DisasContext *dc, arg_ab *a, 11776fd204a2SRichard Henderson void (*fn)(TCGv, TCGv_env, TCGv, TCGv), 11786fd204a2SRichard Henderson bool inv, bool swap) 11796fd204a2SRichard Henderson { 11806fd204a2SRichard Henderson if (swap) { 11818bba7619SRichard Henderson fn(cpu_sr_f, cpu_env, cpu_R(dc, a->b), cpu_R(dc, a->a)); 11826fd204a2SRichard Henderson } else { 11838bba7619SRichard Henderson fn(cpu_sr_f, cpu_env, cpu_R(dc, a->a), cpu_R(dc, a->b)); 11846fd204a2SRichard Henderson } 11856fd204a2SRichard Henderson if (inv) { 11866fd204a2SRichard Henderson tcg_gen_xori_tl(cpu_sr_f, cpu_sr_f, 1); 11876fd204a2SRichard Henderson } 11886fd204a2SRichard Henderson gen_helper_update_fpcsr(cpu_env); 11896fd204a2SRichard Henderson } 11906fd204a2SRichard Henderson 11913a7be554SRichard Henderson static bool trans_lf_add_s(DisasContext *dc, arg_dab *a) 11926fd204a2SRichard Henderson { 11936fd204a2SRichard Henderson do_fp3(dc, a, gen_helper_float_add_s); 11946fd204a2SRichard Henderson return true; 11956fd204a2SRichard Henderson } 11966fd204a2SRichard Henderson 11973a7be554SRichard Henderson static bool trans_lf_sub_s(DisasContext *dc, arg_dab *a) 11986fd204a2SRichard Henderson { 11996fd204a2SRichard Henderson do_fp3(dc, a, gen_helper_float_sub_s); 12006fd204a2SRichard Henderson return true; 12016fd204a2SRichard Henderson } 12026fd204a2SRichard Henderson 12033a7be554SRichard Henderson static bool trans_lf_mul_s(DisasContext *dc, arg_dab *a) 12046fd204a2SRichard Henderson { 12056fd204a2SRichard Henderson do_fp3(dc, a, gen_helper_float_mul_s); 12066fd204a2SRichard Henderson return true; 12076fd204a2SRichard Henderson } 12086fd204a2SRichard Henderson 12093a7be554SRichard Henderson static bool trans_lf_div_s(DisasContext *dc, arg_dab *a) 12106fd204a2SRichard Henderson { 12116fd204a2SRichard Henderson do_fp3(dc, a, gen_helper_float_div_s); 12126fd204a2SRichard Henderson return true; 12136fd204a2SRichard Henderson } 12146fd204a2SRichard Henderson 12153a7be554SRichard Henderson static bool trans_lf_rem_s(DisasContext *dc, arg_dab *a) 12166fd204a2SRichard Henderson { 12176fd204a2SRichard Henderson do_fp3(dc, a, gen_helper_float_rem_s); 12186fd204a2SRichard Henderson return true; 12196fd204a2SRichard Henderson } 12206fd204a2SRichard Henderson 12213a7be554SRichard Henderson static bool trans_lf_itof_s(DisasContext *dc, arg_da *a) 12226fd204a2SRichard Henderson { 12236fd204a2SRichard Henderson do_fp2(dc, a, gen_helper_itofs); 12246fd204a2SRichard Henderson return true; 12256fd204a2SRichard Henderson } 12266fd204a2SRichard Henderson 12273a7be554SRichard Henderson static bool trans_lf_ftoi_s(DisasContext *dc, arg_da *a) 12286fd204a2SRichard Henderson { 12296fd204a2SRichard Henderson do_fp2(dc, a, gen_helper_ftois); 12306fd204a2SRichard Henderson return true; 12316fd204a2SRichard Henderson } 12326fd204a2SRichard Henderson 12333a7be554SRichard Henderson static bool trans_lf_madd_s(DisasContext *dc, arg_dab *a) 12346fd204a2SRichard Henderson { 1235cdd0f459SRichard Henderson check_r0_write(dc, a->d); 12368bba7619SRichard Henderson gen_helper_float_madd_s(cpu_R(dc, a->d), cpu_env, cpu_R(dc, a->d), 12378bba7619SRichard Henderson cpu_R(dc, a->a), cpu_R(dc, a->b)); 12386fd204a2SRichard Henderson gen_helper_update_fpcsr(cpu_env); 12396fd204a2SRichard Henderson return true; 12406fd204a2SRichard Henderson } 12416fd204a2SRichard Henderson 12423a7be554SRichard Henderson static bool trans_lf_sfeq_s(DisasContext *dc, arg_ab *a) 12436fd204a2SRichard Henderson { 12446fd204a2SRichard Henderson do_fpcmp(dc, a, gen_helper_float_eq_s, false, false); 12456fd204a2SRichard Henderson return true; 12466fd204a2SRichard Henderson } 12476fd204a2SRichard Henderson 12483a7be554SRichard Henderson static bool trans_lf_sfne_s(DisasContext *dc, arg_ab *a) 12496fd204a2SRichard Henderson { 12506fd204a2SRichard Henderson do_fpcmp(dc, a, gen_helper_float_eq_s, true, false); 12516fd204a2SRichard Henderson return true; 12526fd204a2SRichard Henderson } 12536fd204a2SRichard Henderson 12543a7be554SRichard Henderson static bool trans_lf_sfgt_s(DisasContext *dc, arg_ab *a) 12556fd204a2SRichard Henderson { 12566fd204a2SRichard Henderson do_fpcmp(dc, a, gen_helper_float_lt_s, false, true); 12576fd204a2SRichard Henderson return true; 12586fd204a2SRichard Henderson } 12596fd204a2SRichard Henderson 12603a7be554SRichard Henderson static bool trans_lf_sfge_s(DisasContext *dc, arg_ab *a) 12616fd204a2SRichard Henderson { 12626fd204a2SRichard Henderson do_fpcmp(dc, a, gen_helper_float_le_s, false, true); 12636fd204a2SRichard Henderson return true; 12646fd204a2SRichard Henderson } 12656fd204a2SRichard Henderson 12663a7be554SRichard Henderson static bool trans_lf_sflt_s(DisasContext *dc, arg_ab *a) 12676fd204a2SRichard Henderson { 12686fd204a2SRichard Henderson do_fpcmp(dc, a, gen_helper_float_lt_s, false, false); 12696fd204a2SRichard Henderson return true; 12706fd204a2SRichard Henderson } 12716fd204a2SRichard Henderson 12723a7be554SRichard Henderson static bool trans_lf_sfle_s(DisasContext *dc, arg_ab *a) 12736fd204a2SRichard Henderson { 12746fd204a2SRichard Henderson do_fpcmp(dc, a, gen_helper_float_le_s, false, false); 12756fd204a2SRichard Henderson return true; 1276bbe418f2SJia Liu } 1277bbe418f2SJia Liu 1278a4fd3ec3SEmilio G. Cota static void openrisc_tr_init_disas_context(DisasContextBase *dcb, CPUState *cs) 1279e67db06eSJia Liu { 1280a4fd3ec3SEmilio G. Cota DisasContext *dc = container_of(dcb, DisasContext, base); 12819c489ea6SLluís Vilanova CPUOpenRISCState *env = cs->env_ptr; 1282a4fd3ec3SEmilio G. Cota int bound; 1283bbe418f2SJia Liu 1284a4fd3ec3SEmilio G. Cota dc->mem_idx = cpu_mmu_index(env, false); 12851ffa4bceSEmilio G. Cota dc->tb_flags = dc->base.tb->flags; 1286a01deb36SRichard Henderson dc->delayed_branch = (dc->tb_flags & TB_FLAGS_DFLAG) != 0; 12878000ba56SRichard Henderson dc->jmp_pc_imm = -1; 12888000ba56SRichard Henderson 1289a4fd3ec3SEmilio G. Cota bound = -(dc->base.pc_first | TARGET_PAGE_MASK) / 4; 1290a4fd3ec3SEmilio G. Cota dc->base.max_insns = MIN(dc->base.max_insns, bound); 1291190ce7fbSRichard Henderson } 1292bbe418f2SJia Liu 1293a4fd3ec3SEmilio G. Cota static void openrisc_tr_tb_start(DisasContextBase *db, CPUState *cs) 1294a4fd3ec3SEmilio G. Cota { 1295a4fd3ec3SEmilio G. Cota DisasContext *dc = container_of(db, DisasContext, base); 1296bbe418f2SJia Liu 12976597c28dSRichard Henderson /* Allow the TCG optimizer to see that R0 == 0, 12986597c28dSRichard Henderson when it's true, which is the common case. */ 12996597c28dSRichard Henderson if (dc->tb_flags & TB_FLAGS_R0_0) { 1300*d29f4368SRichard Henderson dc->R0 = tcg_const_tl(0); 13016597c28dSRichard Henderson } else { 1302*d29f4368SRichard Henderson dc->R0 = cpu_regs[0]; 13036597c28dSRichard Henderson } 1304a4fd3ec3SEmilio G. Cota } 13056597c28dSRichard Henderson 1306a4fd3ec3SEmilio G. Cota static void openrisc_tr_insn_start(DisasContextBase *dcbase, CPUState *cs) 1307a4fd3ec3SEmilio G. Cota { 1308a4fd3ec3SEmilio G. Cota DisasContext *dc = container_of(dcbase, DisasContext, base); 1309a4fd3ec3SEmilio G. Cota 13101ffa4bceSEmilio G. Cota tcg_gen_insn_start(dc->base.pc_next, (dc->delayed_branch ? 1 : 0) 1311a4fd3ec3SEmilio G. Cota | (dc->base.num_insns > 1 ? 2 : 0)); 1312a4fd3ec3SEmilio G. Cota } 1313bbe418f2SJia Liu 1314a4fd3ec3SEmilio G. Cota static bool openrisc_tr_breakpoint_check(DisasContextBase *dcbase, CPUState *cs, 1315a4fd3ec3SEmilio G. Cota const CPUBreakpoint *bp) 1316a4fd3ec3SEmilio G. Cota { 1317a4fd3ec3SEmilio G. Cota DisasContext *dc = container_of(dcbase, DisasContext, base); 1318a4fd3ec3SEmilio G. Cota 13191ffa4bceSEmilio G. Cota tcg_gen_movi_tl(cpu_pc, dc->base.pc_next); 1320b933066aSRichard Henderson gen_exception(dc, EXCP_DEBUG); 13211ffa4bceSEmilio G. Cota dc->base.is_jmp = DISAS_NORETURN; 1322522a0d4eSRichard Henderson /* The address covered by the breakpoint must be included in 1323522a0d4eSRichard Henderson [tb->pc, tb->pc + tb->size) in order to for it to be 1324522a0d4eSRichard Henderson properly cleared -- thus we increment the PC here so that 1325522a0d4eSRichard Henderson the logic setting tb->size below does the right thing. */ 13261ffa4bceSEmilio G. Cota dc->base.pc_next += 4; 1327a4fd3ec3SEmilio G. Cota return true; 1328b933066aSRichard Henderson } 1329b933066aSRichard Henderson 1330a4fd3ec3SEmilio G. Cota static void openrisc_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs) 1331a4fd3ec3SEmilio G. Cota { 1332a4fd3ec3SEmilio G. Cota DisasContext *dc = container_of(dcbase, DisasContext, base); 1333a4fd3ec3SEmilio G. Cota OpenRISCCPU *cpu = OPENRISC_CPU(cs); 1334c7b6f54bSRichard Henderson uint32_t insn = cpu_ldl_code(&cpu->env, dc->base.pc_next); 1335a4fd3ec3SEmilio G. Cota 1336c7b6f54bSRichard Henderson if (!decode(dc, insn)) { 1337c7b6f54bSRichard Henderson gen_illegal_exception(dc); 1338c7b6f54bSRichard Henderson } 13391ffa4bceSEmilio G. Cota dc->base.pc_next += 4; 134024c32852SRichard Henderson 13418000ba56SRichard Henderson /* When exiting the delay slot normally, exit via jmp_pc. 13428000ba56SRichard Henderson * For DISAS_NORETURN, we have raised an exception and already exited. 13438000ba56SRichard Henderson * For DISAS_EXIT, we found l.rfe in a delay slot. There's nothing 13448000ba56SRichard Henderson * in the manual saying this is illegal, but it surely it should. 13458000ba56SRichard Henderson * At least or1ksim overrides pcnext and ignores the branch. 13468000ba56SRichard Henderson */ 13478000ba56SRichard Henderson if (dc->delayed_branch 13488000ba56SRichard Henderson && --dc->delayed_branch == 0 13498000ba56SRichard Henderson && dc->base.is_jmp == DISAS_NEXT) { 13508000ba56SRichard Henderson dc->base.is_jmp = DISAS_JUMP; 1351bbe418f2SJia Liu } 1352a4fd3ec3SEmilio G. Cota } 1353bbe418f2SJia Liu 1354a4fd3ec3SEmilio G. Cota static void openrisc_tr_tb_stop(DisasContextBase *dcbase, CPUState *cs) 1355a4fd3ec3SEmilio G. Cota { 1356a4fd3ec3SEmilio G. Cota DisasContext *dc = container_of(dcbase, DisasContext, base); 13578000ba56SRichard Henderson target_ulong jmp_dest; 135824c32852SRichard Henderson 1359e0a369cfSRichard Henderson /* If we have already exited the TB, nothing following has effect. */ 1360e0a369cfSRichard Henderson if (dc->base.is_jmp == DISAS_NORETURN) { 1361e0a369cfSRichard Henderson return; 1362e0a369cfSRichard Henderson } 1363e0a369cfSRichard Henderson 13648000ba56SRichard Henderson /* Adjust the delayed branch state for the next TB. */ 1365a01deb36SRichard Henderson if ((dc->tb_flags & TB_FLAGS_DFLAG ? 1 : 0) != (dc->delayed_branch != 0)) { 1366a01deb36SRichard Henderson tcg_gen_movi_i32(cpu_dflag, dc->delayed_branch != 0); 1367a01deb36SRichard Henderson } 1368a01deb36SRichard Henderson 13698000ba56SRichard Henderson /* For DISAS_TOO_MANY, jump to the next insn. */ 13708000ba56SRichard Henderson jmp_dest = dc->base.pc_next; 13718000ba56SRichard Henderson tcg_gen_movi_tl(cpu_ppc, jmp_dest - 4); 13728000ba56SRichard Henderson 13731ffa4bceSEmilio G. Cota switch (dc->base.is_jmp) { 13748000ba56SRichard Henderson case DISAS_JUMP: 13758000ba56SRichard Henderson jmp_dest = dc->jmp_pc_imm; 13768000ba56SRichard Henderson if (jmp_dest == -1) { 13778000ba56SRichard Henderson /* The jump destination is indirect/computed; use jmp_pc. */ 13788000ba56SRichard Henderson tcg_gen_mov_tl(cpu_pc, jmp_pc); 13798000ba56SRichard Henderson tcg_gen_discard_tl(jmp_pc); 13808000ba56SRichard Henderson if (unlikely(dc->base.singlestep_enabled)) { 13818000ba56SRichard Henderson gen_exception(dc, EXCP_DEBUG); 13828000ba56SRichard Henderson } else { 13838000ba56SRichard Henderson tcg_gen_lookup_and_goto_ptr(); 13848000ba56SRichard Henderson } 1385bbe418f2SJia Liu break; 13868000ba56SRichard Henderson } 13878000ba56SRichard Henderson /* The jump destination is direct; use jmp_pc_imm. 13888000ba56SRichard Henderson However, we will have stored into jmp_pc as well; 13898000ba56SRichard Henderson we know now that it wasn't needed. */ 13908000ba56SRichard Henderson tcg_gen_discard_tl(jmp_pc); 13918000ba56SRichard Henderson /* fallthru */ 13928000ba56SRichard Henderson 13938000ba56SRichard Henderson case DISAS_TOO_MANY: 13948000ba56SRichard Henderson if (unlikely(dc->base.singlestep_enabled)) { 13958000ba56SRichard Henderson tcg_gen_movi_tl(cpu_pc, jmp_dest); 13968000ba56SRichard Henderson gen_exception(dc, EXCP_DEBUG); 13978000ba56SRichard Henderson } else if ((dc->base.pc_first ^ jmp_dest) & TARGET_PAGE_MASK) { 13988000ba56SRichard Henderson tcg_gen_movi_tl(cpu_pc, jmp_dest); 13998000ba56SRichard Henderson tcg_gen_lookup_and_goto_ptr(); 14008000ba56SRichard Henderson } else { 14018000ba56SRichard Henderson tcg_gen_goto_tb(0); 14028000ba56SRichard Henderson tcg_gen_movi_tl(cpu_pc, jmp_dest); 14038000ba56SRichard Henderson tcg_gen_exit_tb(dc->base.tb, 0); 14048000ba56SRichard Henderson } 14058000ba56SRichard Henderson break; 14068000ba56SRichard Henderson 140764e46c95SRichard Henderson case DISAS_EXIT: 1408e0a369cfSRichard Henderson if (unlikely(dc->base.singlestep_enabled)) { 1409e0a369cfSRichard Henderson gen_exception(dc, EXCP_DEBUG); 1410e0a369cfSRichard Henderson } else { 141107ea28b4SRichard Henderson tcg_gen_exit_tb(NULL, 0); 1412e0a369cfSRichard Henderson } 1413bbe418f2SJia Liu break; 1414a4fd3ec3SEmilio G. Cota default: 1415a4fd3ec3SEmilio G. Cota g_assert_not_reached(); 1416a4fd3ec3SEmilio G. Cota } 1417bbe418f2SJia Liu } 1418bbe418f2SJia Liu 1419a4fd3ec3SEmilio G. Cota static void openrisc_tr_disas_log(const DisasContextBase *dcbase, CPUState *cs) 1420a4fd3ec3SEmilio G. Cota { 1421a4fd3ec3SEmilio G. Cota DisasContext *s = container_of(dcbase, DisasContext, base); 14220a7df5daSRichard Henderson 1423a4fd3ec3SEmilio G. Cota qemu_log("IN: %s\n", lookup_symbol(s->base.pc_first)); 1424a4fd3ec3SEmilio G. Cota log_target_disas(cs, s->base.pc_first, s->base.tb->size); 1425bbe418f2SJia Liu } 1426a4fd3ec3SEmilio G. Cota 1427a4fd3ec3SEmilio G. Cota static const TranslatorOps openrisc_tr_ops = { 1428a4fd3ec3SEmilio G. Cota .init_disas_context = openrisc_tr_init_disas_context, 1429a4fd3ec3SEmilio G. Cota .tb_start = openrisc_tr_tb_start, 1430a4fd3ec3SEmilio G. Cota .insn_start = openrisc_tr_insn_start, 1431a4fd3ec3SEmilio G. Cota .breakpoint_check = openrisc_tr_breakpoint_check, 1432a4fd3ec3SEmilio G. Cota .translate_insn = openrisc_tr_translate_insn, 1433a4fd3ec3SEmilio G. Cota .tb_stop = openrisc_tr_tb_stop, 1434a4fd3ec3SEmilio G. Cota .disas_log = openrisc_tr_disas_log, 1435a4fd3ec3SEmilio G. Cota }; 1436a4fd3ec3SEmilio G. Cota 14378b86d6d2SRichard Henderson void gen_intermediate_code(CPUState *cs, TranslationBlock *tb, int max_insns) 1438a4fd3ec3SEmilio G. Cota { 1439a4fd3ec3SEmilio G. Cota DisasContext ctx; 1440a4fd3ec3SEmilio G. Cota 14418b86d6d2SRichard Henderson translator_loop(&openrisc_tr_ops, &ctx.base, cs, tb, max_insns); 1442e67db06eSJia Liu } 1443e67db06eSJia Liu 144490c84c56SMarkus Armbruster void openrisc_cpu_dump_state(CPUState *cs, FILE *f, int flags) 1445e67db06eSJia Liu { 1446878096eeSAndreas Färber OpenRISCCPU *cpu = OPENRISC_CPU(cs); 1447878096eeSAndreas Färber CPUOpenRISCState *env = &cpu->env; 1448e67db06eSJia Liu int i; 1449878096eeSAndreas Färber 145090c84c56SMarkus Armbruster qemu_fprintf(f, "PC=%08x\n", env->pc); 1451e67db06eSJia Liu for (i = 0; i < 32; ++i) { 145290c84c56SMarkus Armbruster qemu_fprintf(f, "R%02d=%08x%c", i, cpu_get_gpr(env, i), 1453e67db06eSJia Liu (i % 4) == 3 ? '\n' : ' '); 1454e67db06eSJia Liu } 1455e67db06eSJia Liu } 1456e67db06eSJia Liu 1457e67db06eSJia Liu void restore_state_to_opc(CPUOpenRISCState *env, TranslationBlock *tb, 1458bad729e2SRichard Henderson target_ulong *data) 1459e67db06eSJia Liu { 1460bad729e2SRichard Henderson env->pc = data[0]; 1461a01deb36SRichard Henderson env->dflag = data[1] & 1; 1462a01deb36SRichard Henderson if (data[1] & 2) { 146324c32852SRichard Henderson env->ppc = env->pc - 4; 146424c32852SRichard Henderson } 1465e67db06eSJia Liu } 1466