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; 48*fe636d37SRichard Henderson uint32_t cpucfgr; 498000ba56SRichard Henderson 508000ba56SRichard Henderson /* If not -1, jmp_pc contains this value and so is a direct jump. */ 518000ba56SRichard Henderson target_ulong jmp_pc_imm; 52d29f4368SRichard Henderson 53d29f4368SRichard Henderson /* The temporary corresponding to register 0 for this compilation. */ 54d29f4368SRichard Henderson TCGv R0; 55bbe418f2SJia Liu } DisasContext; 56bbe418f2SJia Liu 572ba65417SRichard Henderson static inline bool is_user(DisasContext *dc) 582ba65417SRichard Henderson { 592ba65417SRichard Henderson #ifdef CONFIG_USER_ONLY 602ba65417SRichard Henderson return true; 612ba65417SRichard Henderson #else 62b9bed1b9SRichard Henderson return !(dc->tb_flags & TB_FLAGS_SM); 632ba65417SRichard Henderson #endif 642ba65417SRichard Henderson } 652ba65417SRichard Henderson 667de9729fSRichard Henderson /* Include the auto-generated decoder. */ 677de9729fSRichard Henderson #include "decode.inc.c" 687de9729fSRichard Henderson 69bbe418f2SJia Liu static TCGv cpu_sr; 708bba7619SRichard Henderson static TCGv cpu_regs[32]; 71bbe418f2SJia Liu static TCGv cpu_pc; 72bbe418f2SJia Liu static TCGv jmp_pc; /* l.jr/l.jalr temp pc */ 73bbe418f2SJia Liu static TCGv cpu_ppc; 7484775c43SRichard Henderson static TCGv cpu_sr_f; /* bf/bnf, F flag taken */ 7597458071SRichard Henderson static TCGv cpu_sr_cy; /* carry (unsigned overflow) */ 7697458071SRichard Henderson static TCGv cpu_sr_ov; /* signed overflow */ 77930c3d00SRichard Henderson static TCGv cpu_lock_addr; 78930c3d00SRichard Henderson static TCGv cpu_lock_value; 79bbe418f2SJia Liu static TCGv_i32 fpcsr; 806f7332baSRichard Henderson static TCGv_i64 cpu_mac; /* MACHI:MACLO */ 81a01deb36SRichard Henderson static TCGv_i32 cpu_dflag; 82bbe418f2SJia Liu 83e67db06eSJia Liu void openrisc_translate_init(void) 84e67db06eSJia Liu { 85bbe418f2SJia Liu static const char * const regnames[] = { 86bbe418f2SJia Liu "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", 87bbe418f2SJia Liu "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", 88bbe418f2SJia Liu "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23", 89bbe418f2SJia Liu "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31", 90bbe418f2SJia Liu }; 91bbe418f2SJia Liu int i; 92bbe418f2SJia Liu 93e1ccc054SRichard Henderson cpu_sr = tcg_global_mem_new(cpu_env, 94bbe418f2SJia Liu offsetof(CPUOpenRISCState, sr), "sr"); 95a01deb36SRichard Henderson cpu_dflag = tcg_global_mem_new_i32(cpu_env, 96a01deb36SRichard Henderson offsetof(CPUOpenRISCState, dflag), 97a01deb36SRichard Henderson "dflag"); 98e1ccc054SRichard Henderson cpu_pc = tcg_global_mem_new(cpu_env, 99bbe418f2SJia Liu offsetof(CPUOpenRISCState, pc), "pc"); 100e1ccc054SRichard Henderson cpu_ppc = tcg_global_mem_new(cpu_env, 101bbe418f2SJia Liu offsetof(CPUOpenRISCState, ppc), "ppc"); 102e1ccc054SRichard Henderson jmp_pc = tcg_global_mem_new(cpu_env, 103bbe418f2SJia Liu offsetof(CPUOpenRISCState, jmp_pc), "jmp_pc"); 10484775c43SRichard Henderson cpu_sr_f = tcg_global_mem_new(cpu_env, 10584775c43SRichard Henderson offsetof(CPUOpenRISCState, sr_f), "sr_f"); 10697458071SRichard Henderson cpu_sr_cy = tcg_global_mem_new(cpu_env, 10797458071SRichard Henderson offsetof(CPUOpenRISCState, sr_cy), "sr_cy"); 10897458071SRichard Henderson cpu_sr_ov = tcg_global_mem_new(cpu_env, 10997458071SRichard Henderson offsetof(CPUOpenRISCState, sr_ov), "sr_ov"); 110930c3d00SRichard Henderson cpu_lock_addr = tcg_global_mem_new(cpu_env, 111930c3d00SRichard Henderson offsetof(CPUOpenRISCState, lock_addr), 112930c3d00SRichard Henderson "lock_addr"); 113930c3d00SRichard Henderson cpu_lock_value = tcg_global_mem_new(cpu_env, 114930c3d00SRichard Henderson offsetof(CPUOpenRISCState, lock_value), 115930c3d00SRichard Henderson "lock_value"); 116e1ccc054SRichard Henderson fpcsr = tcg_global_mem_new_i32(cpu_env, 117bbe418f2SJia Liu offsetof(CPUOpenRISCState, fpcsr), 118bbe418f2SJia Liu "fpcsr"); 1196f7332baSRichard Henderson cpu_mac = tcg_global_mem_new_i64(cpu_env, 1206f7332baSRichard Henderson offsetof(CPUOpenRISCState, mac), 1216f7332baSRichard Henderson "mac"); 122bbe418f2SJia Liu for (i = 0; i < 32; i++) { 1238bba7619SRichard Henderson cpu_regs[i] = tcg_global_mem_new(cpu_env, 124d89e71e8SStafford Horne offsetof(CPUOpenRISCState, 125d89e71e8SStafford Horne shadow_gpr[0][i]), 126bbe418f2SJia Liu regnames[i]); 127bbe418f2SJia Liu } 128bbe418f2SJia Liu } 129bbe418f2SJia Liu 130bbe418f2SJia Liu static void gen_exception(DisasContext *dc, unsigned int excp) 131bbe418f2SJia Liu { 132bbe418f2SJia Liu TCGv_i32 tmp = tcg_const_i32(excp); 133bbe418f2SJia Liu gen_helper_exception(cpu_env, tmp); 134bbe418f2SJia Liu tcg_temp_free_i32(tmp); 135bbe418f2SJia Liu } 136bbe418f2SJia Liu 137bbe418f2SJia Liu static void gen_illegal_exception(DisasContext *dc) 138bbe418f2SJia Liu { 1391ffa4bceSEmilio G. Cota tcg_gen_movi_tl(cpu_pc, dc->base.pc_next); 140bbe418f2SJia Liu gen_exception(dc, EXCP_ILLEGAL); 1411ffa4bceSEmilio G. Cota dc->base.is_jmp = DISAS_NORETURN; 142bbe418f2SJia Liu } 143bbe418f2SJia Liu 144*fe636d37SRichard Henderson static bool check_of32s(DisasContext *dc) 145bbe418f2SJia Liu { 146*fe636d37SRichard Henderson return dc->cpucfgr & CPUCFGR_OF32S; 147bbe418f2SJia Liu } 148bbe418f2SJia Liu 1498bba7619SRichard Henderson static TCGv cpu_R(DisasContext *dc, int reg) 1508bba7619SRichard Henderson { 151d29f4368SRichard Henderson if (reg == 0) { 152d29f4368SRichard Henderson return dc->R0; 153d29f4368SRichard Henderson } else { 1548bba7619SRichard Henderson return cpu_regs[reg]; 1558bba7619SRichard Henderson } 156d29f4368SRichard Henderson } 1578bba7619SRichard Henderson 158cdd0f459SRichard Henderson /* 159cdd0f459SRichard Henderson * We're about to write to REG. On the off-chance that the user is 160cdd0f459SRichard Henderson * writing to R0, re-instate the architectural register. 161cdd0f459SRichard Henderson */ 162cdd0f459SRichard Henderson static void check_r0_write(DisasContext *dc, int reg) 163cdd0f459SRichard Henderson { 164cdd0f459SRichard Henderson if (unlikely(reg == 0)) { 165d29f4368SRichard Henderson dc->R0 = cpu_regs[0]; 166cdd0f459SRichard Henderson } 167cdd0f459SRichard Henderson } 1686597c28dSRichard Henderson 16997458071SRichard Henderson static void gen_ove_cy(DisasContext *dc) 1709ecaa27eSRichard Henderson { 1710c53d734SRichard Henderson if (dc->tb_flags & SR_OVE) { 17297458071SRichard Henderson gen_helper_ove_cy(cpu_env); 1739ecaa27eSRichard Henderson } 1740c53d734SRichard Henderson } 1759ecaa27eSRichard Henderson 17697458071SRichard Henderson static void gen_ove_ov(DisasContext *dc) 1779ecaa27eSRichard Henderson { 1780c53d734SRichard Henderson if (dc->tb_flags & SR_OVE) { 17997458071SRichard Henderson gen_helper_ove_ov(cpu_env); 1809ecaa27eSRichard Henderson } 1810c53d734SRichard Henderson } 1829ecaa27eSRichard Henderson 18397458071SRichard Henderson static void gen_ove_cyov(DisasContext *dc) 1849ecaa27eSRichard Henderson { 1850c53d734SRichard Henderson if (dc->tb_flags & SR_OVE) { 18697458071SRichard Henderson gen_helper_ove_cyov(cpu_env); 1879ecaa27eSRichard Henderson } 1880c53d734SRichard Henderson } 1899ecaa27eSRichard Henderson 1909ecaa27eSRichard Henderson static void gen_add(DisasContext *dc, TCGv dest, TCGv srca, TCGv srcb) 1919ecaa27eSRichard Henderson { 1929ecaa27eSRichard Henderson TCGv t0 = tcg_const_tl(0); 1939ecaa27eSRichard Henderson TCGv res = tcg_temp_new(); 1949ecaa27eSRichard Henderson 19597458071SRichard Henderson tcg_gen_add2_tl(res, cpu_sr_cy, srca, t0, srcb, t0); 19697458071SRichard Henderson tcg_gen_xor_tl(cpu_sr_ov, srca, srcb); 1979ecaa27eSRichard Henderson tcg_gen_xor_tl(t0, res, srcb); 19897458071SRichard Henderson tcg_gen_andc_tl(cpu_sr_ov, t0, cpu_sr_ov); 1999ecaa27eSRichard Henderson tcg_temp_free(t0); 2009ecaa27eSRichard Henderson 2019ecaa27eSRichard Henderson tcg_gen_mov_tl(dest, res); 2029ecaa27eSRichard Henderson tcg_temp_free(res); 2039ecaa27eSRichard Henderson 20497458071SRichard Henderson gen_ove_cyov(dc); 2059ecaa27eSRichard Henderson } 2069ecaa27eSRichard Henderson 2079ecaa27eSRichard Henderson static void gen_addc(DisasContext *dc, TCGv dest, TCGv srca, TCGv srcb) 2089ecaa27eSRichard Henderson { 2099ecaa27eSRichard Henderson TCGv t0 = tcg_const_tl(0); 2109ecaa27eSRichard Henderson TCGv res = tcg_temp_new(); 2119ecaa27eSRichard Henderson 21297458071SRichard Henderson tcg_gen_add2_tl(res, cpu_sr_cy, srca, t0, cpu_sr_cy, t0); 21397458071SRichard Henderson tcg_gen_add2_tl(res, cpu_sr_cy, res, cpu_sr_cy, 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_sub(DisasContext *dc, TCGv dest, TCGv srca, TCGv srcb) 2269ecaa27eSRichard Henderson { 2279ecaa27eSRichard Henderson TCGv res = tcg_temp_new(); 2289ecaa27eSRichard Henderson 2299ecaa27eSRichard Henderson tcg_gen_sub_tl(res, srca, srcb); 23097458071SRichard Henderson tcg_gen_xor_tl(cpu_sr_cy, srca, srcb); 23197458071SRichard Henderson tcg_gen_xor_tl(cpu_sr_ov, res, srcb); 23297458071SRichard Henderson tcg_gen_and_tl(cpu_sr_ov, cpu_sr_ov, cpu_sr_cy); 23397458071SRichard Henderson tcg_gen_setcond_tl(TCG_COND_LTU, cpu_sr_cy, srca, srcb); 2349ecaa27eSRichard Henderson 2359ecaa27eSRichard Henderson tcg_gen_mov_tl(dest, res); 2369ecaa27eSRichard Henderson tcg_temp_free(res); 2379ecaa27eSRichard Henderson 23897458071SRichard Henderson gen_ove_cyov(dc); 2399ecaa27eSRichard Henderson } 2409ecaa27eSRichard Henderson 2419ecaa27eSRichard Henderson static void gen_mul(DisasContext *dc, TCGv dest, TCGv srca, TCGv srcb) 2429ecaa27eSRichard Henderson { 2439ecaa27eSRichard Henderson TCGv t0 = tcg_temp_new(); 2449ecaa27eSRichard Henderson 24597458071SRichard Henderson tcg_gen_muls2_tl(dest, cpu_sr_ov, srca, srcb); 2469ecaa27eSRichard Henderson tcg_gen_sari_tl(t0, dest, TARGET_LONG_BITS - 1); 24797458071SRichard Henderson tcg_gen_setcond_tl(TCG_COND_NE, cpu_sr_ov, cpu_sr_ov, t0); 2489ecaa27eSRichard Henderson tcg_temp_free(t0); 2499ecaa27eSRichard Henderson 25097458071SRichard Henderson tcg_gen_neg_tl(cpu_sr_ov, cpu_sr_ov); 25197458071SRichard Henderson gen_ove_ov(dc); 2529ecaa27eSRichard Henderson } 2539ecaa27eSRichard Henderson 2549ecaa27eSRichard Henderson static void gen_mulu(DisasContext *dc, TCGv dest, TCGv srca, TCGv srcb) 2559ecaa27eSRichard Henderson { 25697458071SRichard Henderson tcg_gen_muls2_tl(dest, cpu_sr_cy, srca, srcb); 25797458071SRichard Henderson tcg_gen_setcondi_tl(TCG_COND_NE, cpu_sr_cy, cpu_sr_cy, 0); 2589ecaa27eSRichard Henderson 25997458071SRichard Henderson gen_ove_cy(dc); 2609ecaa27eSRichard Henderson } 2619ecaa27eSRichard Henderson 2629ecaa27eSRichard Henderson static void gen_div(DisasContext *dc, TCGv dest, TCGv srca, TCGv srcb) 2639ecaa27eSRichard Henderson { 2649ecaa27eSRichard Henderson TCGv t0 = tcg_temp_new(); 2659ecaa27eSRichard Henderson 26697458071SRichard Henderson tcg_gen_setcondi_tl(TCG_COND_EQ, cpu_sr_ov, srcb, 0); 2679ecaa27eSRichard Henderson /* The result of divide-by-zero is undefined. 2689ecaa27eSRichard Henderson Supress the host-side exception by dividing by 1. */ 26997458071SRichard Henderson tcg_gen_or_tl(t0, srcb, cpu_sr_ov); 2709ecaa27eSRichard Henderson tcg_gen_div_tl(dest, srca, t0); 2719ecaa27eSRichard Henderson tcg_temp_free(t0); 2729ecaa27eSRichard Henderson 27397458071SRichard Henderson tcg_gen_neg_tl(cpu_sr_ov, cpu_sr_ov); 27497458071SRichard Henderson gen_ove_ov(dc); 2759ecaa27eSRichard Henderson } 2769ecaa27eSRichard Henderson 2779ecaa27eSRichard Henderson static void gen_divu(DisasContext *dc, TCGv dest, TCGv srca, TCGv srcb) 2789ecaa27eSRichard Henderson { 2799ecaa27eSRichard Henderson TCGv t0 = tcg_temp_new(); 2809ecaa27eSRichard Henderson 28197458071SRichard Henderson tcg_gen_setcondi_tl(TCG_COND_EQ, cpu_sr_cy, srcb, 0); 2829ecaa27eSRichard Henderson /* The result of divide-by-zero is undefined. 2839ecaa27eSRichard Henderson Supress the host-side exception by dividing by 1. */ 28497458071SRichard Henderson tcg_gen_or_tl(t0, srcb, cpu_sr_cy); 2859ecaa27eSRichard Henderson tcg_gen_divu_tl(dest, srca, t0); 2869ecaa27eSRichard Henderson tcg_temp_free(t0); 2879ecaa27eSRichard Henderson 28897458071SRichard Henderson gen_ove_cy(dc); 2899ecaa27eSRichard Henderson } 290da1d7759SSebastian Macke 291cc5de49eSRichard Henderson static void gen_muld(DisasContext *dc, TCGv srca, TCGv srcb) 292cc5de49eSRichard Henderson { 293cc5de49eSRichard Henderson TCGv_i64 t1 = tcg_temp_new_i64(); 294cc5de49eSRichard Henderson TCGv_i64 t2 = tcg_temp_new_i64(); 295cc5de49eSRichard Henderson 296cc5de49eSRichard Henderson tcg_gen_ext_tl_i64(t1, srca); 297cc5de49eSRichard Henderson tcg_gen_ext_tl_i64(t2, srcb); 298cc5de49eSRichard Henderson if (TARGET_LONG_BITS == 32) { 299cc5de49eSRichard Henderson tcg_gen_mul_i64(cpu_mac, t1, t2); 300cc5de49eSRichard Henderson tcg_gen_movi_tl(cpu_sr_ov, 0); 301cc5de49eSRichard Henderson } else { 302cc5de49eSRichard Henderson TCGv_i64 high = tcg_temp_new_i64(); 303cc5de49eSRichard Henderson 304cc5de49eSRichard Henderson tcg_gen_muls2_i64(cpu_mac, high, t1, t2); 305cc5de49eSRichard Henderson tcg_gen_sari_i64(t1, cpu_mac, 63); 306cc5de49eSRichard Henderson tcg_gen_setcond_i64(TCG_COND_NE, t1, t1, high); 307cc5de49eSRichard Henderson tcg_temp_free_i64(high); 308cc5de49eSRichard Henderson tcg_gen_trunc_i64_tl(cpu_sr_ov, t1); 309cc5de49eSRichard Henderson tcg_gen_neg_tl(cpu_sr_ov, cpu_sr_ov); 310cc5de49eSRichard Henderson 311cc5de49eSRichard Henderson gen_ove_ov(dc); 312cc5de49eSRichard Henderson } 313cc5de49eSRichard Henderson tcg_temp_free_i64(t1); 314cc5de49eSRichard Henderson tcg_temp_free_i64(t2); 315cc5de49eSRichard Henderson } 316cc5de49eSRichard Henderson 317cc5de49eSRichard Henderson static void gen_muldu(DisasContext *dc, TCGv srca, TCGv srcb) 318cc5de49eSRichard Henderson { 319cc5de49eSRichard Henderson TCGv_i64 t1 = tcg_temp_new_i64(); 320cc5de49eSRichard Henderson TCGv_i64 t2 = tcg_temp_new_i64(); 321cc5de49eSRichard Henderson 322cc5de49eSRichard Henderson tcg_gen_extu_tl_i64(t1, srca); 323cc5de49eSRichard Henderson tcg_gen_extu_tl_i64(t2, srcb); 324cc5de49eSRichard Henderson if (TARGET_LONG_BITS == 32) { 325cc5de49eSRichard Henderson tcg_gen_mul_i64(cpu_mac, t1, t2); 326cc5de49eSRichard Henderson tcg_gen_movi_tl(cpu_sr_cy, 0); 327cc5de49eSRichard Henderson } else { 328cc5de49eSRichard Henderson TCGv_i64 high = tcg_temp_new_i64(); 329cc5de49eSRichard Henderson 330cc5de49eSRichard Henderson tcg_gen_mulu2_i64(cpu_mac, high, t1, t2); 331cc5de49eSRichard Henderson tcg_gen_setcondi_i64(TCG_COND_NE, high, high, 0); 332cc5de49eSRichard Henderson tcg_gen_trunc_i64_tl(cpu_sr_cy, high); 333cc5de49eSRichard Henderson tcg_temp_free_i64(high); 334cc5de49eSRichard Henderson 335cc5de49eSRichard Henderson gen_ove_cy(dc); 336cc5de49eSRichard Henderson } 337cc5de49eSRichard Henderson tcg_temp_free_i64(t1); 338cc5de49eSRichard Henderson tcg_temp_free_i64(t2); 339cc5de49eSRichard Henderson } 340cc5de49eSRichard Henderson 3416f7332baSRichard Henderson static void gen_mac(DisasContext *dc, TCGv srca, TCGv srcb) 3426f7332baSRichard Henderson { 3436f7332baSRichard Henderson TCGv_i64 t1 = tcg_temp_new_i64(); 3446f7332baSRichard Henderson TCGv_i64 t2 = tcg_temp_new_i64(); 3456f7332baSRichard Henderson 3466f7332baSRichard Henderson tcg_gen_ext_tl_i64(t1, srca); 3476f7332baSRichard Henderson tcg_gen_ext_tl_i64(t2, srcb); 3486f7332baSRichard Henderson tcg_gen_mul_i64(t1, t1, t2); 3496f7332baSRichard Henderson 3506f7332baSRichard Henderson /* Note that overflow is only computed during addition stage. */ 3516f7332baSRichard Henderson tcg_gen_xor_i64(t2, cpu_mac, t1); 3526f7332baSRichard Henderson tcg_gen_add_i64(cpu_mac, cpu_mac, t1); 3536f7332baSRichard Henderson tcg_gen_xor_i64(t1, t1, cpu_mac); 3546f7332baSRichard Henderson tcg_gen_andc_i64(t1, t1, t2); 3556f7332baSRichard Henderson tcg_temp_free_i64(t2); 3566f7332baSRichard Henderson 3576f7332baSRichard Henderson #if TARGET_LONG_BITS == 32 3586f7332baSRichard Henderson tcg_gen_extrh_i64_i32(cpu_sr_ov, t1); 3596f7332baSRichard Henderson #else 3606f7332baSRichard Henderson tcg_gen_mov_i64(cpu_sr_ov, t1); 3616f7332baSRichard Henderson #endif 3626f7332baSRichard Henderson tcg_temp_free_i64(t1); 3636f7332baSRichard Henderson 3646f7332baSRichard Henderson gen_ove_ov(dc); 3656f7332baSRichard Henderson } 3666f7332baSRichard Henderson 367cc5de49eSRichard Henderson static void gen_macu(DisasContext *dc, TCGv srca, TCGv srcb) 368cc5de49eSRichard Henderson { 369cc5de49eSRichard Henderson TCGv_i64 t1 = tcg_temp_new_i64(); 370cc5de49eSRichard Henderson TCGv_i64 t2 = tcg_temp_new_i64(); 371cc5de49eSRichard Henderson 372cc5de49eSRichard Henderson tcg_gen_extu_tl_i64(t1, srca); 373cc5de49eSRichard Henderson tcg_gen_extu_tl_i64(t2, srcb); 374cc5de49eSRichard Henderson tcg_gen_mul_i64(t1, t1, t2); 375cc5de49eSRichard Henderson tcg_temp_free_i64(t2); 376cc5de49eSRichard Henderson 377cc5de49eSRichard Henderson /* Note that overflow is only computed during addition stage. */ 378cc5de49eSRichard Henderson tcg_gen_add_i64(cpu_mac, cpu_mac, t1); 379cc5de49eSRichard Henderson tcg_gen_setcond_i64(TCG_COND_LTU, t1, cpu_mac, t1); 380cc5de49eSRichard Henderson tcg_gen_trunc_i64_tl(cpu_sr_cy, t1); 381cc5de49eSRichard Henderson tcg_temp_free_i64(t1); 382cc5de49eSRichard Henderson 383cc5de49eSRichard Henderson gen_ove_cy(dc); 384cc5de49eSRichard Henderson } 385cc5de49eSRichard Henderson 3866f7332baSRichard Henderson static void gen_msb(DisasContext *dc, TCGv srca, TCGv srcb) 3876f7332baSRichard Henderson { 3886f7332baSRichard Henderson TCGv_i64 t1 = tcg_temp_new_i64(); 3896f7332baSRichard Henderson TCGv_i64 t2 = tcg_temp_new_i64(); 3906f7332baSRichard Henderson 3916f7332baSRichard Henderson tcg_gen_ext_tl_i64(t1, srca); 3926f7332baSRichard Henderson tcg_gen_ext_tl_i64(t2, srcb); 3936f7332baSRichard Henderson tcg_gen_mul_i64(t1, t1, t2); 3946f7332baSRichard Henderson 3956f7332baSRichard Henderson /* Note that overflow is only computed during subtraction stage. */ 3966f7332baSRichard Henderson tcg_gen_xor_i64(t2, cpu_mac, t1); 3976f7332baSRichard Henderson tcg_gen_sub_i64(cpu_mac, cpu_mac, t1); 3986f7332baSRichard Henderson tcg_gen_xor_i64(t1, t1, cpu_mac); 3996f7332baSRichard Henderson tcg_gen_and_i64(t1, t1, t2); 4006f7332baSRichard Henderson tcg_temp_free_i64(t2); 4016f7332baSRichard Henderson 4026f7332baSRichard Henderson #if TARGET_LONG_BITS == 32 4036f7332baSRichard Henderson tcg_gen_extrh_i64_i32(cpu_sr_ov, t1); 4046f7332baSRichard Henderson #else 4056f7332baSRichard Henderson tcg_gen_mov_i64(cpu_sr_ov, t1); 4066f7332baSRichard Henderson #endif 4076f7332baSRichard Henderson tcg_temp_free_i64(t1); 4086f7332baSRichard Henderson 4096f7332baSRichard Henderson gen_ove_ov(dc); 4106f7332baSRichard Henderson } 4116f7332baSRichard Henderson 412cc5de49eSRichard Henderson static void gen_msbu(DisasContext *dc, TCGv srca, TCGv srcb) 413cc5de49eSRichard Henderson { 414cc5de49eSRichard Henderson TCGv_i64 t1 = tcg_temp_new_i64(); 415cc5de49eSRichard Henderson TCGv_i64 t2 = tcg_temp_new_i64(); 416cc5de49eSRichard Henderson 417cc5de49eSRichard Henderson tcg_gen_extu_tl_i64(t1, srca); 418cc5de49eSRichard Henderson tcg_gen_extu_tl_i64(t2, srcb); 419cc5de49eSRichard Henderson tcg_gen_mul_i64(t1, t1, t2); 420cc5de49eSRichard Henderson 421cc5de49eSRichard Henderson /* Note that overflow is only computed during subtraction stage. */ 422cc5de49eSRichard Henderson tcg_gen_setcond_i64(TCG_COND_LTU, t2, cpu_mac, t1); 423cc5de49eSRichard Henderson tcg_gen_sub_i64(cpu_mac, cpu_mac, t1); 424cc5de49eSRichard Henderson tcg_gen_trunc_i64_tl(cpu_sr_cy, t2); 425cc5de49eSRichard Henderson tcg_temp_free_i64(t2); 426cc5de49eSRichard Henderson tcg_temp_free_i64(t1); 427cc5de49eSRichard Henderson 428cc5de49eSRichard Henderson gen_ove_cy(dc); 429cc5de49eSRichard Henderson } 430cc5de49eSRichard Henderson 4313a7be554SRichard Henderson static bool trans_l_add(DisasContext *dc, arg_dab *a) 432bbe418f2SJia Liu { 433cdd0f459SRichard Henderson check_r0_write(dc, a->d); 4348bba7619SRichard Henderson gen_add(dc, cpu_R(dc, a->d), cpu_R(dc, a->a), cpu_R(dc, a->b)); 4356ad216abSRichard Henderson return true; 436bbe418f2SJia Liu } 437bbe418f2SJia Liu 4383a7be554SRichard Henderson static bool trans_l_addc(DisasContext *dc, arg_dab *a) 439bbe418f2SJia Liu { 440cdd0f459SRichard Henderson check_r0_write(dc, a->d); 4418bba7619SRichard Henderson gen_addc(dc, cpu_R(dc, a->d), cpu_R(dc, a->a), cpu_R(dc, a->b)); 4426ad216abSRichard Henderson return true; 4436ad216abSRichard Henderson } 4446ad216abSRichard Henderson 4453a7be554SRichard Henderson static bool trans_l_sub(DisasContext *dc, arg_dab *a) 4466ad216abSRichard Henderson { 447cdd0f459SRichard Henderson check_r0_write(dc, a->d); 4488bba7619SRichard Henderson gen_sub(dc, cpu_R(dc, a->d), cpu_R(dc, a->a), cpu_R(dc, a->b)); 4496ad216abSRichard Henderson return true; 4506ad216abSRichard Henderson } 4516ad216abSRichard Henderson 4523a7be554SRichard Henderson static bool trans_l_and(DisasContext *dc, arg_dab *a) 4536ad216abSRichard Henderson { 454cdd0f459SRichard Henderson check_r0_write(dc, a->d); 4558bba7619SRichard Henderson tcg_gen_and_tl(cpu_R(dc, a->d), cpu_R(dc, a->a), cpu_R(dc, a->b)); 4566ad216abSRichard Henderson return true; 4576ad216abSRichard Henderson } 4586ad216abSRichard Henderson 4593a7be554SRichard Henderson static bool trans_l_or(DisasContext *dc, arg_dab *a) 4606ad216abSRichard Henderson { 461cdd0f459SRichard Henderson check_r0_write(dc, a->d); 4628bba7619SRichard Henderson tcg_gen_or_tl(cpu_R(dc, a->d), cpu_R(dc, a->a), cpu_R(dc, a->b)); 4636ad216abSRichard Henderson return true; 4646ad216abSRichard Henderson } 4656ad216abSRichard Henderson 4663a7be554SRichard Henderson static bool trans_l_xor(DisasContext *dc, arg_dab *a) 4676ad216abSRichard Henderson { 468cdd0f459SRichard Henderson check_r0_write(dc, a->d); 4698bba7619SRichard Henderson tcg_gen_xor_tl(cpu_R(dc, a->d), cpu_R(dc, a->a), cpu_R(dc, a->b)); 4706ad216abSRichard Henderson return true; 4716ad216abSRichard Henderson } 4726ad216abSRichard Henderson 4733a7be554SRichard Henderson static bool trans_l_sll(DisasContext *dc, arg_dab *a) 4746ad216abSRichard Henderson { 475cdd0f459SRichard Henderson check_r0_write(dc, a->d); 4768bba7619SRichard Henderson tcg_gen_shl_tl(cpu_R(dc, a->d), cpu_R(dc, a->a), cpu_R(dc, a->b)); 4776ad216abSRichard Henderson return true; 4786ad216abSRichard Henderson } 4796ad216abSRichard Henderson 4803a7be554SRichard Henderson static bool trans_l_srl(DisasContext *dc, arg_dab *a) 4816ad216abSRichard Henderson { 482cdd0f459SRichard Henderson check_r0_write(dc, a->d); 4838bba7619SRichard Henderson tcg_gen_shr_tl(cpu_R(dc, a->d), cpu_R(dc, a->a), cpu_R(dc, a->b)); 4846ad216abSRichard Henderson return true; 4856ad216abSRichard Henderson } 4866ad216abSRichard Henderson 4873a7be554SRichard Henderson static bool trans_l_sra(DisasContext *dc, arg_dab *a) 4886ad216abSRichard Henderson { 489cdd0f459SRichard Henderson check_r0_write(dc, a->d); 4908bba7619SRichard Henderson tcg_gen_sar_tl(cpu_R(dc, a->d), cpu_R(dc, a->a), cpu_R(dc, a->b)); 4916ad216abSRichard Henderson return true; 4926ad216abSRichard Henderson } 4936ad216abSRichard Henderson 4943a7be554SRichard Henderson static bool trans_l_ror(DisasContext *dc, arg_dab *a) 4956ad216abSRichard Henderson { 496cdd0f459SRichard Henderson check_r0_write(dc, a->d); 4978bba7619SRichard Henderson tcg_gen_rotr_tl(cpu_R(dc, a->d), cpu_R(dc, a->a), cpu_R(dc, a->b)); 4986ad216abSRichard Henderson return true; 4996ad216abSRichard Henderson } 5006ad216abSRichard Henderson 5013a7be554SRichard Henderson static bool trans_l_exths(DisasContext *dc, arg_da *a) 5026ad216abSRichard Henderson { 503cdd0f459SRichard Henderson check_r0_write(dc, a->d); 5048bba7619SRichard Henderson tcg_gen_ext16s_tl(cpu_R(dc, a->d), cpu_R(dc, a->a)); 5056ad216abSRichard Henderson return true; 5066ad216abSRichard Henderson } 5076ad216abSRichard Henderson 5083a7be554SRichard Henderson static bool trans_l_extbs(DisasContext *dc, arg_da *a) 5096ad216abSRichard Henderson { 510cdd0f459SRichard Henderson check_r0_write(dc, a->d); 5118bba7619SRichard Henderson tcg_gen_ext8s_tl(cpu_R(dc, a->d), cpu_R(dc, a->a)); 5126ad216abSRichard Henderson return true; 5136ad216abSRichard Henderson } 5146ad216abSRichard Henderson 5153a7be554SRichard Henderson static bool trans_l_exthz(DisasContext *dc, arg_da *a) 5166ad216abSRichard Henderson { 517cdd0f459SRichard Henderson check_r0_write(dc, a->d); 5188bba7619SRichard Henderson tcg_gen_ext16u_tl(cpu_R(dc, a->d), cpu_R(dc, a->a)); 5196ad216abSRichard Henderson return true; 5206ad216abSRichard Henderson } 5216ad216abSRichard Henderson 5223a7be554SRichard Henderson static bool trans_l_extbz(DisasContext *dc, arg_da *a) 5236ad216abSRichard Henderson { 524cdd0f459SRichard Henderson check_r0_write(dc, a->d); 5258bba7619SRichard Henderson tcg_gen_ext8u_tl(cpu_R(dc, a->d), cpu_R(dc, a->a)); 5266ad216abSRichard Henderson return true; 5276ad216abSRichard Henderson } 5286ad216abSRichard Henderson 5293a7be554SRichard Henderson static bool trans_l_cmov(DisasContext *dc, arg_dab *a) 5306ad216abSRichard Henderson { 5316ad216abSRichard Henderson TCGv zero; 5326ad216abSRichard Henderson 533cdd0f459SRichard Henderson check_r0_write(dc, a->d); 5346ad216abSRichard Henderson zero = tcg_const_tl(0); 5358bba7619SRichard Henderson tcg_gen_movcond_tl(TCG_COND_NE, cpu_R(dc, a->d), cpu_sr_f, zero, 5368bba7619SRichard Henderson cpu_R(dc, a->a), cpu_R(dc, a->b)); 537784696d1SRichard Henderson tcg_temp_free(zero); 5386ad216abSRichard Henderson return true; 539bbe418f2SJia Liu } 540bbe418f2SJia Liu 5413a7be554SRichard Henderson static bool trans_l_ff1(DisasContext *dc, arg_da *a) 5426ad216abSRichard Henderson { 543cdd0f459SRichard Henderson check_r0_write(dc, a->d); 5448bba7619SRichard Henderson tcg_gen_ctzi_tl(cpu_R(dc, a->d), cpu_R(dc, a->a), -1); 5458bba7619SRichard Henderson tcg_gen_addi_tl(cpu_R(dc, a->d), cpu_R(dc, a->d), 1); 5466ad216abSRichard Henderson return true; 547cf2ae442SRichard Henderson } 548cf2ae442SRichard Henderson 5493a7be554SRichard Henderson static bool trans_l_fl1(DisasContext *dc, arg_da *a) 5506ad216abSRichard Henderson { 551cdd0f459SRichard Henderson check_r0_write(dc, a->d); 5528bba7619SRichard Henderson tcg_gen_clzi_tl(cpu_R(dc, a->d), cpu_R(dc, a->a), TARGET_LONG_BITS); 5538bba7619SRichard Henderson tcg_gen_subfi_tl(cpu_R(dc, a->d), TARGET_LONG_BITS, cpu_R(dc, a->d)); 5546ad216abSRichard Henderson return true; 555bbe418f2SJia Liu } 556bbe418f2SJia Liu 5573a7be554SRichard Henderson static bool trans_l_mul(DisasContext *dc, arg_dab *a) 5586ad216abSRichard Henderson { 559cdd0f459SRichard Henderson check_r0_write(dc, a->d); 5608bba7619SRichard Henderson gen_mul(dc, cpu_R(dc, a->d), cpu_R(dc, a->a), cpu_R(dc, a->b)); 5616ad216abSRichard Henderson return true; 562bbe418f2SJia Liu } 5636ad216abSRichard Henderson 5643a7be554SRichard Henderson static bool trans_l_mulu(DisasContext *dc, arg_dab *a) 5656ad216abSRichard Henderson { 566cdd0f459SRichard Henderson check_r0_write(dc, a->d); 5678bba7619SRichard Henderson gen_mulu(dc, cpu_R(dc, a->d), cpu_R(dc, a->a), cpu_R(dc, a->b)); 5686ad216abSRichard Henderson return true; 569bbe418f2SJia Liu } 5706ad216abSRichard Henderson 5713a7be554SRichard Henderson static bool trans_l_div(DisasContext *dc, arg_dab *a) 5726ad216abSRichard Henderson { 573cdd0f459SRichard Henderson check_r0_write(dc, a->d); 5748bba7619SRichard Henderson gen_div(dc, cpu_R(dc, a->d), cpu_R(dc, a->a), cpu_R(dc, a->b)); 5756ad216abSRichard Henderson return true; 5766ad216abSRichard Henderson } 5776ad216abSRichard Henderson 5783a7be554SRichard Henderson static bool trans_l_divu(DisasContext *dc, arg_dab *a) 5796ad216abSRichard Henderson { 580cdd0f459SRichard Henderson check_r0_write(dc, a->d); 5818bba7619SRichard Henderson gen_divu(dc, cpu_R(dc, a->d), cpu_R(dc, a->a), cpu_R(dc, a->b)); 5826ad216abSRichard Henderson return true; 5836ad216abSRichard Henderson } 5846ad216abSRichard Henderson 5853a7be554SRichard Henderson static bool trans_l_muld(DisasContext *dc, arg_ab *a) 5866ad216abSRichard Henderson { 5878bba7619SRichard Henderson gen_muld(dc, cpu_R(dc, a->a), cpu_R(dc, a->b)); 5886ad216abSRichard Henderson return true; 5896ad216abSRichard Henderson } 5906ad216abSRichard Henderson 5913a7be554SRichard Henderson static bool trans_l_muldu(DisasContext *dc, arg_ab *a) 5926ad216abSRichard Henderson { 5938bba7619SRichard Henderson gen_muldu(dc, cpu_R(dc, a->a), cpu_R(dc, a->b)); 5946ad216abSRichard Henderson return true; 595bbe418f2SJia Liu } 596bbe418f2SJia Liu 5973a7be554SRichard Henderson static bool trans_l_j(DisasContext *dc, arg_l_j *a) 598136e13aeSRichard Henderson { 599136e13aeSRichard Henderson target_ulong tmp_pc = dc->base.pc_next + a->n * 4; 600136e13aeSRichard Henderson 601136e13aeSRichard Henderson tcg_gen_movi_tl(jmp_pc, tmp_pc); 6028000ba56SRichard Henderson dc->jmp_pc_imm = tmp_pc; 603136e13aeSRichard Henderson dc->delayed_branch = 2; 604136e13aeSRichard Henderson return true; 605136e13aeSRichard Henderson } 606136e13aeSRichard Henderson 6073a7be554SRichard Henderson static bool trans_l_jal(DisasContext *dc, arg_l_jal *a) 608136e13aeSRichard Henderson { 609136e13aeSRichard Henderson target_ulong tmp_pc = dc->base.pc_next + a->n * 4; 610136e13aeSRichard Henderson target_ulong ret_pc = dc->base.pc_next + 8; 611136e13aeSRichard Henderson 6128bba7619SRichard Henderson tcg_gen_movi_tl(cpu_regs[9], ret_pc); 613136e13aeSRichard Henderson /* Optimize jal being used to load the PC for PIC. */ 614136e13aeSRichard Henderson if (tmp_pc != ret_pc) { 615136e13aeSRichard Henderson tcg_gen_movi_tl(jmp_pc, tmp_pc); 6168000ba56SRichard Henderson dc->jmp_pc_imm = tmp_pc; 617136e13aeSRichard Henderson dc->delayed_branch = 2; 618136e13aeSRichard Henderson } 619136e13aeSRichard Henderson return true; 620136e13aeSRichard Henderson } 621136e13aeSRichard Henderson 622136e13aeSRichard Henderson static void do_bf(DisasContext *dc, arg_l_bf *a, TCGCond cond) 623136e13aeSRichard Henderson { 624136e13aeSRichard Henderson target_ulong tmp_pc = dc->base.pc_next + a->n * 4; 625136e13aeSRichard Henderson TCGv t_next = tcg_const_tl(dc->base.pc_next + 8); 626136e13aeSRichard Henderson TCGv t_true = tcg_const_tl(tmp_pc); 627136e13aeSRichard Henderson TCGv t_zero = tcg_const_tl(0); 628136e13aeSRichard Henderson 629136e13aeSRichard Henderson tcg_gen_movcond_tl(cond, jmp_pc, cpu_sr_f, t_zero, t_true, t_next); 630136e13aeSRichard Henderson 631136e13aeSRichard Henderson tcg_temp_free(t_next); 632136e13aeSRichard Henderson tcg_temp_free(t_true); 633136e13aeSRichard Henderson tcg_temp_free(t_zero); 634136e13aeSRichard Henderson dc->delayed_branch = 2; 635136e13aeSRichard Henderson } 636136e13aeSRichard Henderson 6373a7be554SRichard Henderson static bool trans_l_bf(DisasContext *dc, arg_l_bf *a) 638136e13aeSRichard Henderson { 639136e13aeSRichard Henderson do_bf(dc, a, TCG_COND_NE); 640136e13aeSRichard Henderson return true; 641136e13aeSRichard Henderson } 642136e13aeSRichard Henderson 6433a7be554SRichard Henderson static bool trans_l_bnf(DisasContext *dc, arg_l_bf *a) 644136e13aeSRichard Henderson { 645136e13aeSRichard Henderson do_bf(dc, a, TCG_COND_EQ); 646136e13aeSRichard Henderson return true; 647136e13aeSRichard Henderson } 648136e13aeSRichard Henderson 6493a7be554SRichard Henderson static bool trans_l_jr(DisasContext *dc, arg_l_jr *a) 650136e13aeSRichard Henderson { 6518bba7619SRichard Henderson tcg_gen_mov_tl(jmp_pc, cpu_R(dc, a->b)); 652136e13aeSRichard Henderson dc->delayed_branch = 2; 653136e13aeSRichard Henderson return true; 654136e13aeSRichard Henderson } 655136e13aeSRichard Henderson 6563a7be554SRichard Henderson static bool trans_l_jalr(DisasContext *dc, arg_l_jalr *a) 657136e13aeSRichard Henderson { 6588bba7619SRichard Henderson tcg_gen_mov_tl(jmp_pc, cpu_R(dc, a->b)); 6598bba7619SRichard Henderson tcg_gen_movi_tl(cpu_regs[9], dc->base.pc_next + 8); 660136e13aeSRichard Henderson dc->delayed_branch = 2; 661136e13aeSRichard Henderson return true; 662136e13aeSRichard Henderson } 663136e13aeSRichard Henderson 6643a7be554SRichard Henderson static bool trans_l_lwa(DisasContext *dc, arg_load *a) 665d80bff19SRichard Henderson { 666d80bff19SRichard Henderson TCGv ea; 667d80bff19SRichard Henderson 668cdd0f459SRichard Henderson check_r0_write(dc, a->d); 669d80bff19SRichard Henderson ea = tcg_temp_new(); 6708bba7619SRichard Henderson tcg_gen_addi_tl(ea, cpu_R(dc, a->a), a->i); 6718bba7619SRichard Henderson tcg_gen_qemu_ld_tl(cpu_R(dc, a->d), ea, dc->mem_idx, MO_TEUL); 672d80bff19SRichard Henderson tcg_gen_mov_tl(cpu_lock_addr, ea); 6738bba7619SRichard Henderson tcg_gen_mov_tl(cpu_lock_value, cpu_R(dc, a->d)); 674d80bff19SRichard Henderson tcg_temp_free(ea); 675d80bff19SRichard Henderson return true; 676d80bff19SRichard Henderson } 677d80bff19SRichard Henderson 67814776ab5STony Nguyen static void do_load(DisasContext *dc, arg_load *a, MemOp mop) 679d80bff19SRichard Henderson { 680d80bff19SRichard Henderson TCGv ea; 681d80bff19SRichard Henderson 682cdd0f459SRichard Henderson check_r0_write(dc, a->d); 683d80bff19SRichard Henderson ea = tcg_temp_new(); 6848bba7619SRichard Henderson tcg_gen_addi_tl(ea, cpu_R(dc, a->a), a->i); 6858bba7619SRichard Henderson tcg_gen_qemu_ld_tl(cpu_R(dc, a->d), ea, dc->mem_idx, mop); 686d80bff19SRichard Henderson tcg_temp_free(ea); 687d80bff19SRichard Henderson } 688d80bff19SRichard Henderson 6893a7be554SRichard Henderson static bool trans_l_lwz(DisasContext *dc, arg_load *a) 690d80bff19SRichard Henderson { 691d80bff19SRichard Henderson do_load(dc, a, MO_TEUL); 692d80bff19SRichard Henderson return true; 693d80bff19SRichard Henderson } 694d80bff19SRichard Henderson 6953a7be554SRichard Henderson static bool trans_l_lws(DisasContext *dc, arg_load *a) 696d80bff19SRichard Henderson { 697d80bff19SRichard Henderson do_load(dc, a, MO_TESL); 698d80bff19SRichard Henderson return true; 699d80bff19SRichard Henderson } 700d80bff19SRichard Henderson 7013a7be554SRichard Henderson static bool trans_l_lbz(DisasContext *dc, arg_load *a) 702d80bff19SRichard Henderson { 703d80bff19SRichard Henderson do_load(dc, a, MO_UB); 704d80bff19SRichard Henderson return true; 705d80bff19SRichard Henderson } 706d80bff19SRichard Henderson 7073a7be554SRichard Henderson static bool trans_l_lbs(DisasContext *dc, arg_load *a) 708d80bff19SRichard Henderson { 709d80bff19SRichard Henderson do_load(dc, a, MO_SB); 710d80bff19SRichard Henderson return true; 711d80bff19SRichard Henderson } 712d80bff19SRichard Henderson 7133a7be554SRichard Henderson static bool trans_l_lhz(DisasContext *dc, arg_load *a) 714d80bff19SRichard Henderson { 715d80bff19SRichard Henderson do_load(dc, a, MO_TEUW); 716d80bff19SRichard Henderson return true; 717d80bff19SRichard Henderson } 718d80bff19SRichard Henderson 7193a7be554SRichard Henderson static bool trans_l_lhs(DisasContext *dc, arg_load *a) 720d80bff19SRichard Henderson { 721d80bff19SRichard Henderson do_load(dc, a, MO_TESW); 722d80bff19SRichard Henderson return true; 723d80bff19SRichard Henderson } 724d80bff19SRichard Henderson 7253a7be554SRichard Henderson static bool trans_l_swa(DisasContext *dc, arg_store *a) 726d80bff19SRichard Henderson { 727d80bff19SRichard Henderson TCGv ea, val; 728d80bff19SRichard Henderson TCGLabel *lab_fail, *lab_done; 729d80bff19SRichard Henderson 730d80bff19SRichard Henderson ea = tcg_temp_new(); 7318bba7619SRichard Henderson tcg_gen_addi_tl(ea, cpu_R(dc, a->a), a->i); 732d80bff19SRichard Henderson 733d80bff19SRichard Henderson /* For TB_FLAGS_R0_0, the branch below invalidates the temporary assigned 7348bba7619SRichard Henderson to cpu_regs[0]. Since l.swa is quite often immediately followed by a 735d80bff19SRichard Henderson branch, don't bother reallocating; finish the TB using the "real" R0. 736d80bff19SRichard Henderson This also takes care of RB input across the branch. */ 737d29f4368SRichard Henderson dc->R0 = cpu_regs[0]; 738d80bff19SRichard Henderson 739d80bff19SRichard Henderson lab_fail = gen_new_label(); 740d80bff19SRichard Henderson lab_done = gen_new_label(); 741d80bff19SRichard Henderson tcg_gen_brcond_tl(TCG_COND_NE, ea, cpu_lock_addr, lab_fail); 742d80bff19SRichard Henderson tcg_temp_free(ea); 743d80bff19SRichard Henderson 744d80bff19SRichard Henderson val = tcg_temp_new(); 745d80bff19SRichard Henderson tcg_gen_atomic_cmpxchg_tl(val, cpu_lock_addr, cpu_lock_value, 7468bba7619SRichard Henderson cpu_regs[a->b], dc->mem_idx, MO_TEUL); 747d80bff19SRichard Henderson tcg_gen_setcond_tl(TCG_COND_EQ, cpu_sr_f, val, cpu_lock_value); 748d80bff19SRichard Henderson tcg_temp_free(val); 749d80bff19SRichard Henderson 750d80bff19SRichard Henderson tcg_gen_br(lab_done); 751d80bff19SRichard Henderson 752d80bff19SRichard Henderson gen_set_label(lab_fail); 753d80bff19SRichard Henderson tcg_gen_movi_tl(cpu_sr_f, 0); 754d80bff19SRichard Henderson 755d80bff19SRichard Henderson gen_set_label(lab_done); 756d80bff19SRichard Henderson tcg_gen_movi_tl(cpu_lock_addr, -1); 757d80bff19SRichard Henderson return true; 758d80bff19SRichard Henderson } 759d80bff19SRichard Henderson 76014776ab5STony Nguyen static void do_store(DisasContext *dc, arg_store *a, MemOp mop) 761d80bff19SRichard Henderson { 762d80bff19SRichard Henderson TCGv t0 = tcg_temp_new(); 7638bba7619SRichard Henderson tcg_gen_addi_tl(t0, cpu_R(dc, a->a), a->i); 7648bba7619SRichard Henderson tcg_gen_qemu_st_tl(cpu_R(dc, a->b), t0, dc->mem_idx, mop); 765d80bff19SRichard Henderson tcg_temp_free(t0); 766d80bff19SRichard Henderson } 767d80bff19SRichard Henderson 7683a7be554SRichard Henderson static bool trans_l_sw(DisasContext *dc, arg_store *a) 769d80bff19SRichard Henderson { 770d80bff19SRichard Henderson do_store(dc, a, MO_TEUL); 771d80bff19SRichard Henderson return true; 772d80bff19SRichard Henderson } 773d80bff19SRichard Henderson 7743a7be554SRichard Henderson static bool trans_l_sb(DisasContext *dc, arg_store *a) 775d80bff19SRichard Henderson { 776d80bff19SRichard Henderson do_store(dc, a, MO_UB); 777d80bff19SRichard Henderson return true; 778d80bff19SRichard Henderson } 779d80bff19SRichard Henderson 7803a7be554SRichard Henderson static bool trans_l_sh(DisasContext *dc, arg_store *a) 781d80bff19SRichard Henderson { 782d80bff19SRichard Henderson do_store(dc, a, MO_TEUW); 783d80bff19SRichard Henderson return true; 784d80bff19SRichard Henderson } 785d80bff19SRichard Henderson 7863a7be554SRichard Henderson static bool trans_l_nop(DisasContext *dc, arg_l_nop *a) 787bbe418f2SJia Liu { 7888816f70bSRichard Henderson return true; 7898816f70bSRichard Henderson } 7908816f70bSRichard Henderson 7913a7be554SRichard Henderson static bool trans_l_addi(DisasContext *dc, arg_rri *a) 7928816f70bSRichard Henderson { 7939ecaa27eSRichard Henderson TCGv t0; 7945631e69cSRichard Henderson 795cdd0f459SRichard Henderson check_r0_write(dc, a->d); 7968816f70bSRichard Henderson t0 = tcg_const_tl(a->i); 7978bba7619SRichard Henderson gen_add(dc, cpu_R(dc, a->d), cpu_R(dc, a->a), t0); 7986f7332baSRichard Henderson tcg_temp_free(t0); 7998816f70bSRichard Henderson return true; 8008816f70bSRichard Henderson } 801bbe418f2SJia Liu 8023a7be554SRichard Henderson static bool trans_l_addic(DisasContext *dc, arg_rri *a) 803bbe418f2SJia Liu { 8048816f70bSRichard Henderson TCGv t0; 8058816f70bSRichard Henderson 806cdd0f459SRichard Henderson check_r0_write(dc, a->d); 8078816f70bSRichard Henderson t0 = tcg_const_tl(a->i); 8088bba7619SRichard Henderson gen_addc(dc, cpu_R(dc, a->d), cpu_R(dc, a->a), t0); 8098816f70bSRichard Henderson tcg_temp_free(t0); 8108816f70bSRichard Henderson return true; 8118816f70bSRichard Henderson } 8128816f70bSRichard Henderson 8133a7be554SRichard Henderson static bool trans_l_muli(DisasContext *dc, arg_rri *a) 8148816f70bSRichard Henderson { 8158816f70bSRichard Henderson TCGv t0; 8168816f70bSRichard Henderson 817cdd0f459SRichard Henderson check_r0_write(dc, a->d); 8188816f70bSRichard Henderson t0 = tcg_const_tl(a->i); 8198bba7619SRichard Henderson gen_mul(dc, cpu_R(dc, a->d), cpu_R(dc, a->a), t0); 8208816f70bSRichard Henderson tcg_temp_free(t0); 8218816f70bSRichard Henderson return true; 8228816f70bSRichard Henderson } 8238816f70bSRichard Henderson 8243a7be554SRichard Henderson static bool trans_l_maci(DisasContext *dc, arg_l_maci *a) 8258816f70bSRichard Henderson { 8268816f70bSRichard Henderson TCGv t0; 8278816f70bSRichard Henderson 8288816f70bSRichard Henderson t0 = tcg_const_tl(a->i); 8298bba7619SRichard Henderson gen_mac(dc, cpu_R(dc, a->a), t0); 8308816f70bSRichard Henderson tcg_temp_free(t0); 8318816f70bSRichard Henderson return true; 8328816f70bSRichard Henderson } 8338816f70bSRichard Henderson 8343a7be554SRichard Henderson static bool trans_l_andi(DisasContext *dc, arg_rrk *a) 8358816f70bSRichard Henderson { 836cdd0f459SRichard Henderson check_r0_write(dc, a->d); 8378bba7619SRichard Henderson tcg_gen_andi_tl(cpu_R(dc, a->d), cpu_R(dc, a->a), a->k); 8388816f70bSRichard Henderson return true; 8398816f70bSRichard Henderson } 8408816f70bSRichard Henderson 8413a7be554SRichard Henderson static bool trans_l_ori(DisasContext *dc, arg_rrk *a) 8428816f70bSRichard Henderson { 843cdd0f459SRichard Henderson check_r0_write(dc, a->d); 8448bba7619SRichard Henderson tcg_gen_ori_tl(cpu_R(dc, a->d), cpu_R(dc, a->a), a->k); 8458816f70bSRichard Henderson return true; 8468816f70bSRichard Henderson } 8478816f70bSRichard Henderson 8483a7be554SRichard Henderson static bool trans_l_xori(DisasContext *dc, arg_rri *a) 8498816f70bSRichard Henderson { 850cdd0f459SRichard Henderson check_r0_write(dc, a->d); 8518bba7619SRichard Henderson tcg_gen_xori_tl(cpu_R(dc, a->d), cpu_R(dc, a->a), a->i); 8528816f70bSRichard Henderson return true; 8538816f70bSRichard Henderson } 8548816f70bSRichard Henderson 8553a7be554SRichard Henderson static bool trans_l_mfspr(DisasContext *dc, arg_l_mfspr *a) 8568816f70bSRichard Henderson { 857cdd0f459SRichard Henderson check_r0_write(dc, a->d); 8588816f70bSRichard Henderson 8592ba65417SRichard Henderson if (is_user(dc)) { 860bbe418f2SJia Liu gen_illegal_exception(dc); 8618816f70bSRichard Henderson } else { 862c28fa81fSRichard Henderson TCGv spr = tcg_temp_new(); 8638bba7619SRichard Henderson tcg_gen_ori_tl(spr, cpu_R(dc, a->a), a->k); 8648bba7619SRichard Henderson gen_helper_mfspr(cpu_R(dc, a->d), cpu_env, cpu_R(dc, a->d), spr); 865c28fa81fSRichard Henderson tcg_temp_free(spr); 8664dd044c6SJia Liu } 8678816f70bSRichard Henderson return true; 8688816f70bSRichard Henderson } 869bbe418f2SJia Liu 8703a7be554SRichard Henderson static bool trans_l_mtspr(DisasContext *dc, arg_l_mtspr *a) 8714dd044c6SJia Liu { 8722ba65417SRichard Henderson if (is_user(dc)) { 8734dd044c6SJia Liu gen_illegal_exception(dc); 8748816f70bSRichard Henderson } else { 875c28fa81fSRichard Henderson TCGv spr; 87601ec3ec9SRichard Henderson 87701ec3ec9SRichard Henderson /* For SR, we will need to exit the TB to recognize the new 87801ec3ec9SRichard Henderson * exception state. For NPC, in theory this counts as a branch 87901ec3ec9SRichard Henderson * (although the SPR only exists for use by an ICE). Save all 88001ec3ec9SRichard Henderson * of the cpu state first, allowing it to be overwritten. 88101ec3ec9SRichard Henderson */ 88201ec3ec9SRichard Henderson if (dc->delayed_branch) { 88301ec3ec9SRichard Henderson tcg_gen_mov_tl(cpu_pc, jmp_pc); 88401ec3ec9SRichard Henderson tcg_gen_discard_tl(jmp_pc); 88501ec3ec9SRichard Henderson } else { 88601ec3ec9SRichard Henderson tcg_gen_movi_tl(cpu_pc, dc->base.pc_next + 4); 88701ec3ec9SRichard Henderson } 88801ec3ec9SRichard Henderson dc->base.is_jmp = DISAS_EXIT; 88901ec3ec9SRichard Henderson 890c28fa81fSRichard Henderson spr = tcg_temp_new(); 8918bba7619SRichard Henderson tcg_gen_ori_tl(spr, cpu_R(dc, a->a), a->k); 8928bba7619SRichard Henderson gen_helper_mtspr(cpu_env, spr, cpu_R(dc, a->b)); 893c28fa81fSRichard Henderson tcg_temp_free(spr); 8944dd044c6SJia Liu } 8958816f70bSRichard Henderson return true; 896bbe418f2SJia Liu } 897bbe418f2SJia Liu 8983a7be554SRichard Henderson static bool trans_l_mac(DisasContext *dc, arg_ab *a) 899bbe418f2SJia Liu { 9008bba7619SRichard Henderson gen_mac(dc, cpu_R(dc, a->a), cpu_R(dc, a->b)); 90199d863d6SRichard Henderson return true; 902bbe418f2SJia Liu } 90399d863d6SRichard Henderson 9043a7be554SRichard Henderson static bool trans_l_msb(DisasContext *dc, arg_ab *a) 90599d863d6SRichard Henderson { 9068bba7619SRichard Henderson gen_msb(dc, cpu_R(dc, a->a), cpu_R(dc, a->b)); 90799d863d6SRichard Henderson return true; 90899d863d6SRichard Henderson } 90999d863d6SRichard Henderson 9103a7be554SRichard Henderson static bool trans_l_macu(DisasContext *dc, arg_ab *a) 91199d863d6SRichard Henderson { 9128bba7619SRichard Henderson gen_macu(dc, cpu_R(dc, a->a), cpu_R(dc, a->b)); 91399d863d6SRichard Henderson return true; 91499d863d6SRichard Henderson } 91599d863d6SRichard Henderson 9163a7be554SRichard Henderson static bool trans_l_msbu(DisasContext *dc, arg_ab *a) 91799d863d6SRichard Henderson { 9188bba7619SRichard Henderson gen_msbu(dc, cpu_R(dc, a->a), cpu_R(dc, a->b)); 91999d863d6SRichard Henderson return true; 920bbe418f2SJia Liu } 921bbe418f2SJia Liu 9223a7be554SRichard Henderson static bool trans_l_slli(DisasContext *dc, arg_dal *a) 923bbe418f2SJia Liu { 924cdd0f459SRichard Henderson check_r0_write(dc, a->d); 9258bba7619SRichard Henderson tcg_gen_shli_tl(cpu_R(dc, a->d), cpu_R(dc, a->a), 9268bba7619SRichard Henderson a->l & (TARGET_LONG_BITS - 1)); 927e20c2592SRichard Henderson return true; 928bbe418f2SJia Liu } 929e20c2592SRichard Henderson 9303a7be554SRichard Henderson static bool trans_l_srli(DisasContext *dc, arg_dal *a) 931e20c2592SRichard Henderson { 932cdd0f459SRichard Henderson check_r0_write(dc, a->d); 9338bba7619SRichard Henderson tcg_gen_shri_tl(cpu_R(dc, a->d), cpu_R(dc, a->a), 9348bba7619SRichard Henderson a->l & (TARGET_LONG_BITS - 1)); 935e20c2592SRichard Henderson return true; 936e20c2592SRichard Henderson } 937e20c2592SRichard Henderson 9383a7be554SRichard Henderson static bool trans_l_srai(DisasContext *dc, arg_dal *a) 939e20c2592SRichard Henderson { 940cdd0f459SRichard Henderson check_r0_write(dc, a->d); 9418bba7619SRichard Henderson tcg_gen_sari_tl(cpu_R(dc, a->d), cpu_R(dc, a->a), 9428bba7619SRichard Henderson a->l & (TARGET_LONG_BITS - 1)); 943e20c2592SRichard Henderson return true; 944e20c2592SRichard Henderson } 945e20c2592SRichard Henderson 9463a7be554SRichard Henderson static bool trans_l_rori(DisasContext *dc, arg_dal *a) 947e20c2592SRichard Henderson { 948cdd0f459SRichard Henderson check_r0_write(dc, a->d); 9498bba7619SRichard Henderson tcg_gen_rotri_tl(cpu_R(dc, a->d), cpu_R(dc, a->a), 9508bba7619SRichard Henderson a->l & (TARGET_LONG_BITS - 1)); 951e20c2592SRichard Henderson return true; 952bbe418f2SJia Liu } 953bbe418f2SJia Liu 9543a7be554SRichard Henderson static bool trans_l_movhi(DisasContext *dc, arg_l_movhi *a) 955bbe418f2SJia Liu { 956cdd0f459SRichard Henderson check_r0_write(dc, a->d); 9578bba7619SRichard Henderson tcg_gen_movi_tl(cpu_R(dc, a->d), a->k << 16); 958e720a571SRichard Henderson return true; 959bbe418f2SJia Liu } 960e720a571SRichard Henderson 9613a7be554SRichard Henderson static bool trans_l_macrc(DisasContext *dc, arg_l_macrc *a) 962e720a571SRichard Henderson { 963cdd0f459SRichard Henderson check_r0_write(dc, a->d); 9648bba7619SRichard Henderson tcg_gen_trunc_i64_tl(cpu_R(dc, a->d), cpu_mac); 965e720a571SRichard Henderson tcg_gen_movi_i64(cpu_mac, 0); 966e720a571SRichard Henderson return true; 967bbe418f2SJia Liu } 968bbe418f2SJia Liu 9693a7be554SRichard Henderson static bool trans_l_sfeq(DisasContext *dc, arg_ab *a) 970bbe418f2SJia Liu { 9718bba7619SRichard Henderson tcg_gen_setcond_tl(TCG_COND_EQ, cpu_sr_f, 9728bba7619SRichard Henderson cpu_R(dc, a->a), cpu_R(dc, a->b)); 973fbb3e29aSRichard Henderson return true; 974bbe418f2SJia Liu } 975fbb3e29aSRichard Henderson 9763a7be554SRichard Henderson static bool trans_l_sfne(DisasContext *dc, arg_ab *a) 977fbb3e29aSRichard Henderson { 9788bba7619SRichard Henderson tcg_gen_setcond_tl(TCG_COND_NE, cpu_sr_f, 9798bba7619SRichard Henderson cpu_R(dc, a->a), cpu_R(dc, a->b)); 980fbb3e29aSRichard Henderson return true; 981fbb3e29aSRichard Henderson } 982fbb3e29aSRichard Henderson 9833a7be554SRichard Henderson static bool trans_l_sfgtu(DisasContext *dc, arg_ab *a) 984fbb3e29aSRichard Henderson { 9858bba7619SRichard Henderson tcg_gen_setcond_tl(TCG_COND_GTU, cpu_sr_f, 9868bba7619SRichard Henderson cpu_R(dc, a->a), cpu_R(dc, a->b)); 987fbb3e29aSRichard Henderson return true; 988fbb3e29aSRichard Henderson } 989fbb3e29aSRichard Henderson 9903a7be554SRichard Henderson static bool trans_l_sfgeu(DisasContext *dc, arg_ab *a) 991fbb3e29aSRichard Henderson { 9928bba7619SRichard Henderson tcg_gen_setcond_tl(TCG_COND_GEU, cpu_sr_f, 9938bba7619SRichard Henderson cpu_R(dc, a->a), cpu_R(dc, a->b)); 994fbb3e29aSRichard Henderson return true; 995fbb3e29aSRichard Henderson } 996fbb3e29aSRichard Henderson 9973a7be554SRichard Henderson static bool trans_l_sfltu(DisasContext *dc, arg_ab *a) 998fbb3e29aSRichard Henderson { 9998bba7619SRichard Henderson tcg_gen_setcond_tl(TCG_COND_LTU, cpu_sr_f, 10008bba7619SRichard Henderson cpu_R(dc, a->a), cpu_R(dc, a->b)); 1001fbb3e29aSRichard Henderson return true; 1002fbb3e29aSRichard Henderson } 1003fbb3e29aSRichard Henderson 10043a7be554SRichard Henderson static bool trans_l_sfleu(DisasContext *dc, arg_ab *a) 1005fbb3e29aSRichard Henderson { 10068bba7619SRichard Henderson tcg_gen_setcond_tl(TCG_COND_LEU, cpu_sr_f, 10078bba7619SRichard Henderson cpu_R(dc, a->a), cpu_R(dc, a->b)); 1008fbb3e29aSRichard Henderson return true; 1009fbb3e29aSRichard Henderson } 1010fbb3e29aSRichard Henderson 10113a7be554SRichard Henderson static bool trans_l_sfgts(DisasContext *dc, arg_ab *a) 1012fbb3e29aSRichard Henderson { 10138bba7619SRichard Henderson tcg_gen_setcond_tl(TCG_COND_GT, cpu_sr_f, 10148bba7619SRichard Henderson cpu_R(dc, a->a), cpu_R(dc, a->b)); 1015fbb3e29aSRichard Henderson return true; 1016fbb3e29aSRichard Henderson } 1017fbb3e29aSRichard Henderson 10183a7be554SRichard Henderson static bool trans_l_sfges(DisasContext *dc, arg_ab *a) 1019fbb3e29aSRichard Henderson { 10208bba7619SRichard Henderson tcg_gen_setcond_tl(TCG_COND_GE, cpu_sr_f, 10218bba7619SRichard Henderson cpu_R(dc, a->a), cpu_R(dc, a->b)); 1022fbb3e29aSRichard Henderson return true; 1023fbb3e29aSRichard Henderson } 1024fbb3e29aSRichard Henderson 10253a7be554SRichard Henderson static bool trans_l_sflts(DisasContext *dc, arg_ab *a) 1026fbb3e29aSRichard Henderson { 10278bba7619SRichard Henderson tcg_gen_setcond_tl(TCG_COND_LT, cpu_sr_f, 10288bba7619SRichard Henderson cpu_R(dc, a->a), cpu_R(dc, a->b)); 1029fbb3e29aSRichard Henderson return true; 1030fbb3e29aSRichard Henderson } 1031fbb3e29aSRichard Henderson 10323a7be554SRichard Henderson static bool trans_l_sfles(DisasContext *dc, arg_ab *a) 1033fbb3e29aSRichard Henderson { 10348bba7619SRichard Henderson tcg_gen_setcond_tl(TCG_COND_LE, 10358bba7619SRichard Henderson cpu_sr_f, cpu_R(dc, a->a), cpu_R(dc, a->b)); 1036fbb3e29aSRichard Henderson return true; 1037bbe418f2SJia Liu } 1038bbe418f2SJia Liu 10393a7be554SRichard Henderson static bool trans_l_sfeqi(DisasContext *dc, arg_ai *a) 1040bbe418f2SJia Liu { 10418bba7619SRichard Henderson tcg_gen_setcondi_tl(TCG_COND_EQ, cpu_sr_f, cpu_R(dc, a->a), a->i); 1042032de4fcSRichard Henderson return true; 1043bbe418f2SJia Liu } 1044032de4fcSRichard Henderson 10453a7be554SRichard Henderson static bool trans_l_sfnei(DisasContext *dc, arg_ai *a) 1046032de4fcSRichard Henderson { 10478bba7619SRichard Henderson tcg_gen_setcondi_tl(TCG_COND_NE, cpu_sr_f, cpu_R(dc, a->a), a->i); 1048032de4fcSRichard Henderson return true; 1049032de4fcSRichard Henderson } 1050032de4fcSRichard Henderson 10513a7be554SRichard Henderson static bool trans_l_sfgtui(DisasContext *dc, arg_ai *a) 1052032de4fcSRichard Henderson { 10538bba7619SRichard Henderson tcg_gen_setcondi_tl(TCG_COND_GTU, cpu_sr_f, cpu_R(dc, a->a), a->i); 1054032de4fcSRichard Henderson return true; 1055032de4fcSRichard Henderson } 1056032de4fcSRichard Henderson 10573a7be554SRichard Henderson static bool trans_l_sfgeui(DisasContext *dc, arg_ai *a) 1058032de4fcSRichard Henderson { 10598bba7619SRichard Henderson tcg_gen_setcondi_tl(TCG_COND_GEU, cpu_sr_f, cpu_R(dc, a->a), a->i); 1060032de4fcSRichard Henderson return true; 1061032de4fcSRichard Henderson } 1062032de4fcSRichard Henderson 10633a7be554SRichard Henderson static bool trans_l_sfltui(DisasContext *dc, arg_ai *a) 1064032de4fcSRichard Henderson { 10658bba7619SRichard Henderson tcg_gen_setcondi_tl(TCG_COND_LTU, cpu_sr_f, cpu_R(dc, a->a), a->i); 1066032de4fcSRichard Henderson return true; 1067032de4fcSRichard Henderson } 1068032de4fcSRichard Henderson 10693a7be554SRichard Henderson static bool trans_l_sfleui(DisasContext *dc, arg_ai *a) 1070032de4fcSRichard Henderson { 10718bba7619SRichard Henderson tcg_gen_setcondi_tl(TCG_COND_LEU, cpu_sr_f, cpu_R(dc, a->a), a->i); 1072032de4fcSRichard Henderson return true; 1073032de4fcSRichard Henderson } 1074032de4fcSRichard Henderson 10753a7be554SRichard Henderson static bool trans_l_sfgtsi(DisasContext *dc, arg_ai *a) 1076032de4fcSRichard Henderson { 10778bba7619SRichard Henderson tcg_gen_setcondi_tl(TCG_COND_GT, cpu_sr_f, cpu_R(dc, a->a), a->i); 1078032de4fcSRichard Henderson return true; 1079032de4fcSRichard Henderson } 1080032de4fcSRichard Henderson 10813a7be554SRichard Henderson static bool trans_l_sfgesi(DisasContext *dc, arg_ai *a) 1082032de4fcSRichard Henderson { 10838bba7619SRichard Henderson tcg_gen_setcondi_tl(TCG_COND_GE, cpu_sr_f, cpu_R(dc, a->a), a->i); 1084032de4fcSRichard Henderson return true; 1085032de4fcSRichard Henderson } 1086032de4fcSRichard Henderson 10873a7be554SRichard Henderson static bool trans_l_sfltsi(DisasContext *dc, arg_ai *a) 1088032de4fcSRichard Henderson { 10898bba7619SRichard Henderson tcg_gen_setcondi_tl(TCG_COND_LT, cpu_sr_f, cpu_R(dc, a->a), a->i); 1090032de4fcSRichard Henderson return true; 1091032de4fcSRichard Henderson } 1092032de4fcSRichard Henderson 10933a7be554SRichard Henderson static bool trans_l_sflesi(DisasContext *dc, arg_ai *a) 1094032de4fcSRichard Henderson { 10958bba7619SRichard Henderson tcg_gen_setcondi_tl(TCG_COND_LE, cpu_sr_f, cpu_R(dc, a->a), a->i); 1096032de4fcSRichard Henderson return true; 1097bbe418f2SJia Liu } 1098bbe418f2SJia Liu 10993a7be554SRichard Henderson static bool trans_l_sys(DisasContext *dc, arg_l_sys *a) 1100bbe418f2SJia Liu { 11011ffa4bceSEmilio G. Cota tcg_gen_movi_tl(cpu_pc, dc->base.pc_next); 1102bbe418f2SJia Liu gen_exception(dc, EXCP_SYSCALL); 11031ffa4bceSEmilio G. Cota dc->base.is_jmp = DISAS_NORETURN; 11047de9729fSRichard Henderson return true; 11057de9729fSRichard Henderson } 1106bbe418f2SJia Liu 11073a7be554SRichard Henderson static bool trans_l_trap(DisasContext *dc, arg_l_trap *a) 11087de9729fSRichard Henderson { 11091ffa4bceSEmilio G. Cota tcg_gen_movi_tl(cpu_pc, dc->base.pc_next); 1110bbe418f2SJia Liu gen_exception(dc, EXCP_TRAP); 11111ffa4bceSEmilio G. Cota dc->base.is_jmp = DISAS_NORETURN; 11127de9729fSRichard Henderson return true; 11137de9729fSRichard Henderson } 1114bbe418f2SJia Liu 11153a7be554SRichard Henderson static bool trans_l_msync(DisasContext *dc, arg_l_msync *a) 11167de9729fSRichard Henderson { 111724fc5c0fSRichard Henderson tcg_gen_mb(TCG_MO_ALL); 11187de9729fSRichard Henderson return true; 1119bbe418f2SJia Liu } 11207de9729fSRichard Henderson 11213a7be554SRichard Henderson static bool trans_l_psync(DisasContext *dc, arg_l_psync *a) 11227de9729fSRichard Henderson { 11237de9729fSRichard Henderson return true; 11247de9729fSRichard Henderson } 11257de9729fSRichard Henderson 11263a7be554SRichard Henderson static bool trans_l_csync(DisasContext *dc, arg_l_csync *a) 11277de9729fSRichard Henderson { 11287de9729fSRichard Henderson return true; 1129bbe418f2SJia Liu } 1130bbe418f2SJia Liu 11313a7be554SRichard Henderson static bool trans_l_rfe(DisasContext *dc, arg_l_rfe *a) 11328816f70bSRichard Henderson { 11332ba65417SRichard Henderson if (is_user(dc)) { 11348816f70bSRichard Henderson gen_illegal_exception(dc); 11358816f70bSRichard Henderson } else { 11368816f70bSRichard Henderson gen_helper_rfe(cpu_env); 113764e46c95SRichard Henderson dc->base.is_jmp = DISAS_EXIT; 11388816f70bSRichard Henderson } 11398816f70bSRichard Henderson return true; 11408816f70bSRichard Henderson } 11418816f70bSRichard Henderson 1142*fe636d37SRichard Henderson static bool do_fp2(DisasContext *dc, arg_da *a, 11436fd204a2SRichard Henderson void (*fn)(TCGv, TCGv_env, TCGv)) 1144bbe418f2SJia Liu { 1145*fe636d37SRichard Henderson if (!check_of32s(dc)) { 1146*fe636d37SRichard Henderson return false; 1147*fe636d37SRichard Henderson } 1148cdd0f459SRichard Henderson check_r0_write(dc, a->d); 11498bba7619SRichard Henderson fn(cpu_R(dc, a->d), cpu_env, cpu_R(dc, a->a)); 11504e2d3007SRichard Henderson gen_helper_update_fpcsr(cpu_env); 1151*fe636d37SRichard Henderson return true; 1152bbe418f2SJia Liu } 11536fd204a2SRichard Henderson 1154*fe636d37SRichard Henderson static bool do_fp3(DisasContext *dc, arg_dab *a, 11556fd204a2SRichard Henderson void (*fn)(TCGv, TCGv_env, TCGv, TCGv)) 11566fd204a2SRichard Henderson { 1157*fe636d37SRichard Henderson if (!check_of32s(dc)) { 1158*fe636d37SRichard Henderson return false; 1159*fe636d37SRichard Henderson } 1160cdd0f459SRichard Henderson check_r0_write(dc, a->d); 11618bba7619SRichard Henderson fn(cpu_R(dc, a->d), cpu_env, cpu_R(dc, a->a), cpu_R(dc, a->b)); 11626fd204a2SRichard Henderson gen_helper_update_fpcsr(cpu_env); 1163*fe636d37SRichard Henderson return true; 11646fd204a2SRichard Henderson } 11656fd204a2SRichard Henderson 1166*fe636d37SRichard Henderson static bool do_fpcmp(DisasContext *dc, arg_ab *a, 11676fd204a2SRichard Henderson void (*fn)(TCGv, TCGv_env, TCGv, TCGv), 11686fd204a2SRichard Henderson bool inv, bool swap) 11696fd204a2SRichard Henderson { 1170*fe636d37SRichard Henderson if (!check_of32s(dc)) { 1171*fe636d37SRichard Henderson return false; 1172*fe636d37SRichard Henderson } 11736fd204a2SRichard Henderson if (swap) { 11748bba7619SRichard Henderson fn(cpu_sr_f, cpu_env, cpu_R(dc, a->b), cpu_R(dc, a->a)); 11756fd204a2SRichard Henderson } else { 11768bba7619SRichard Henderson fn(cpu_sr_f, cpu_env, cpu_R(dc, a->a), cpu_R(dc, a->b)); 11776fd204a2SRichard Henderson } 11786fd204a2SRichard Henderson if (inv) { 11796fd204a2SRichard Henderson tcg_gen_xori_tl(cpu_sr_f, cpu_sr_f, 1); 11806fd204a2SRichard Henderson } 11816fd204a2SRichard Henderson gen_helper_update_fpcsr(cpu_env); 1182*fe636d37SRichard Henderson return true; 11836fd204a2SRichard Henderson } 11846fd204a2SRichard Henderson 11853a7be554SRichard Henderson static bool trans_lf_add_s(DisasContext *dc, arg_dab *a) 11866fd204a2SRichard Henderson { 1187*fe636d37SRichard Henderson return do_fp3(dc, a, gen_helper_float_add_s); 11886fd204a2SRichard Henderson } 11896fd204a2SRichard Henderson 11903a7be554SRichard Henderson static bool trans_lf_sub_s(DisasContext *dc, arg_dab *a) 11916fd204a2SRichard Henderson { 1192*fe636d37SRichard Henderson return do_fp3(dc, a, gen_helper_float_sub_s); 11936fd204a2SRichard Henderson } 11946fd204a2SRichard Henderson 11953a7be554SRichard Henderson static bool trans_lf_mul_s(DisasContext *dc, arg_dab *a) 11966fd204a2SRichard Henderson { 1197*fe636d37SRichard Henderson return do_fp3(dc, a, gen_helper_float_mul_s); 11986fd204a2SRichard Henderson } 11996fd204a2SRichard Henderson 12003a7be554SRichard Henderson static bool trans_lf_div_s(DisasContext *dc, arg_dab *a) 12016fd204a2SRichard Henderson { 1202*fe636d37SRichard Henderson return do_fp3(dc, a, gen_helper_float_div_s); 12036fd204a2SRichard Henderson } 12046fd204a2SRichard Henderson 12053a7be554SRichard Henderson static bool trans_lf_rem_s(DisasContext *dc, arg_dab *a) 12066fd204a2SRichard Henderson { 1207*fe636d37SRichard Henderson return do_fp3(dc, a, gen_helper_float_rem_s); 12086fd204a2SRichard Henderson return true; 12096fd204a2SRichard Henderson } 12106fd204a2SRichard Henderson 12113a7be554SRichard Henderson static bool trans_lf_itof_s(DisasContext *dc, arg_da *a) 12126fd204a2SRichard Henderson { 1213*fe636d37SRichard Henderson return do_fp2(dc, a, gen_helper_itofs); 12146fd204a2SRichard Henderson } 12156fd204a2SRichard Henderson 12163a7be554SRichard Henderson static bool trans_lf_ftoi_s(DisasContext *dc, arg_da *a) 12176fd204a2SRichard Henderson { 1218*fe636d37SRichard Henderson return do_fp2(dc, a, gen_helper_ftois); 12196fd204a2SRichard Henderson } 12206fd204a2SRichard Henderson 12213a7be554SRichard Henderson static bool trans_lf_madd_s(DisasContext *dc, arg_dab *a) 12226fd204a2SRichard Henderson { 1223*fe636d37SRichard Henderson if (!check_of32s(dc)) { 1224*fe636d37SRichard Henderson return false; 1225*fe636d37SRichard Henderson } 1226cdd0f459SRichard Henderson check_r0_write(dc, a->d); 12278bba7619SRichard Henderson gen_helper_float_madd_s(cpu_R(dc, a->d), cpu_env, cpu_R(dc, a->d), 12288bba7619SRichard Henderson cpu_R(dc, a->a), cpu_R(dc, a->b)); 12296fd204a2SRichard Henderson gen_helper_update_fpcsr(cpu_env); 12306fd204a2SRichard Henderson return true; 12316fd204a2SRichard Henderson } 12326fd204a2SRichard Henderson 12333a7be554SRichard Henderson static bool trans_lf_sfeq_s(DisasContext *dc, arg_ab *a) 12346fd204a2SRichard Henderson { 1235*fe636d37SRichard Henderson return do_fpcmp(dc, a, gen_helper_float_eq_s, false, false); 12366fd204a2SRichard Henderson } 12376fd204a2SRichard Henderson 12383a7be554SRichard Henderson static bool trans_lf_sfne_s(DisasContext *dc, arg_ab *a) 12396fd204a2SRichard Henderson { 1240*fe636d37SRichard Henderson return do_fpcmp(dc, a, gen_helper_float_eq_s, true, false); 12416fd204a2SRichard Henderson } 12426fd204a2SRichard Henderson 12433a7be554SRichard Henderson static bool trans_lf_sfgt_s(DisasContext *dc, arg_ab *a) 12446fd204a2SRichard Henderson { 1245*fe636d37SRichard Henderson return do_fpcmp(dc, a, gen_helper_float_lt_s, false, true); 12466fd204a2SRichard Henderson } 12476fd204a2SRichard Henderson 12483a7be554SRichard Henderson static bool trans_lf_sfge_s(DisasContext *dc, arg_ab *a) 12496fd204a2SRichard Henderson { 1250*fe636d37SRichard Henderson return do_fpcmp(dc, a, gen_helper_float_le_s, false, true); 12516fd204a2SRichard Henderson } 12526fd204a2SRichard Henderson 12533a7be554SRichard Henderson static bool trans_lf_sflt_s(DisasContext *dc, arg_ab *a) 12546fd204a2SRichard Henderson { 1255*fe636d37SRichard Henderson return do_fpcmp(dc, a, gen_helper_float_lt_s, false, false); 12566fd204a2SRichard Henderson } 12576fd204a2SRichard Henderson 12583a7be554SRichard Henderson static bool trans_lf_sfle_s(DisasContext *dc, arg_ab *a) 12596fd204a2SRichard Henderson { 1260*fe636d37SRichard Henderson return do_fpcmp(dc, a, gen_helper_float_le_s, false, false); 1261bbe418f2SJia Liu } 1262bbe418f2SJia Liu 1263a4fd3ec3SEmilio G. Cota static void openrisc_tr_init_disas_context(DisasContextBase *dcb, CPUState *cs) 1264e67db06eSJia Liu { 1265a4fd3ec3SEmilio G. Cota DisasContext *dc = container_of(dcb, DisasContext, base); 12669c489ea6SLluís Vilanova CPUOpenRISCState *env = cs->env_ptr; 1267a4fd3ec3SEmilio G. Cota int bound; 1268bbe418f2SJia Liu 1269a4fd3ec3SEmilio G. Cota dc->mem_idx = cpu_mmu_index(env, false); 12701ffa4bceSEmilio G. Cota dc->tb_flags = dc->base.tb->flags; 1271a01deb36SRichard Henderson dc->delayed_branch = (dc->tb_flags & TB_FLAGS_DFLAG) != 0; 1272*fe636d37SRichard Henderson dc->cpucfgr = env->cpucfgr; 12738000ba56SRichard Henderson dc->jmp_pc_imm = -1; 12748000ba56SRichard Henderson 1275a4fd3ec3SEmilio G. Cota bound = -(dc->base.pc_first | TARGET_PAGE_MASK) / 4; 1276a4fd3ec3SEmilio G. Cota dc->base.max_insns = MIN(dc->base.max_insns, bound); 1277190ce7fbSRichard Henderson } 1278bbe418f2SJia Liu 1279a4fd3ec3SEmilio G. Cota static void openrisc_tr_tb_start(DisasContextBase *db, CPUState *cs) 1280a4fd3ec3SEmilio G. Cota { 1281a4fd3ec3SEmilio G. Cota DisasContext *dc = container_of(db, DisasContext, base); 1282bbe418f2SJia Liu 12836597c28dSRichard Henderson /* Allow the TCG optimizer to see that R0 == 0, 12846597c28dSRichard Henderson when it's true, which is the common case. */ 12856597c28dSRichard Henderson if (dc->tb_flags & TB_FLAGS_R0_0) { 1286d29f4368SRichard Henderson dc->R0 = tcg_const_tl(0); 12876597c28dSRichard Henderson } else { 1288d29f4368SRichard Henderson dc->R0 = cpu_regs[0]; 12896597c28dSRichard Henderson } 1290a4fd3ec3SEmilio G. Cota } 12916597c28dSRichard Henderson 1292a4fd3ec3SEmilio G. Cota static void openrisc_tr_insn_start(DisasContextBase *dcbase, CPUState *cs) 1293a4fd3ec3SEmilio G. Cota { 1294a4fd3ec3SEmilio G. Cota DisasContext *dc = container_of(dcbase, DisasContext, base); 1295a4fd3ec3SEmilio G. Cota 12961ffa4bceSEmilio G. Cota tcg_gen_insn_start(dc->base.pc_next, (dc->delayed_branch ? 1 : 0) 1297a4fd3ec3SEmilio G. Cota | (dc->base.num_insns > 1 ? 2 : 0)); 1298a4fd3ec3SEmilio G. Cota } 1299bbe418f2SJia Liu 1300a4fd3ec3SEmilio G. Cota static bool openrisc_tr_breakpoint_check(DisasContextBase *dcbase, CPUState *cs, 1301a4fd3ec3SEmilio G. Cota const CPUBreakpoint *bp) 1302a4fd3ec3SEmilio G. Cota { 1303a4fd3ec3SEmilio G. Cota DisasContext *dc = container_of(dcbase, DisasContext, base); 1304a4fd3ec3SEmilio G. Cota 13051ffa4bceSEmilio G. Cota tcg_gen_movi_tl(cpu_pc, dc->base.pc_next); 1306b933066aSRichard Henderson gen_exception(dc, EXCP_DEBUG); 13071ffa4bceSEmilio G. Cota dc->base.is_jmp = DISAS_NORETURN; 1308522a0d4eSRichard Henderson /* The address covered by the breakpoint must be included in 1309522a0d4eSRichard Henderson [tb->pc, tb->pc + tb->size) in order to for it to be 1310522a0d4eSRichard Henderson properly cleared -- thus we increment the PC here so that 1311522a0d4eSRichard Henderson the logic setting tb->size below does the right thing. */ 13121ffa4bceSEmilio G. Cota dc->base.pc_next += 4; 1313a4fd3ec3SEmilio G. Cota return true; 1314b933066aSRichard Henderson } 1315b933066aSRichard Henderson 1316a4fd3ec3SEmilio G. Cota static void openrisc_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs) 1317a4fd3ec3SEmilio G. Cota { 1318a4fd3ec3SEmilio G. Cota DisasContext *dc = container_of(dcbase, DisasContext, base); 1319a4fd3ec3SEmilio G. Cota OpenRISCCPU *cpu = OPENRISC_CPU(cs); 1320c7b6f54bSRichard Henderson uint32_t insn = cpu_ldl_code(&cpu->env, dc->base.pc_next); 1321a4fd3ec3SEmilio G. Cota 1322c7b6f54bSRichard Henderson if (!decode(dc, insn)) { 1323c7b6f54bSRichard Henderson gen_illegal_exception(dc); 1324c7b6f54bSRichard Henderson } 13251ffa4bceSEmilio G. Cota dc->base.pc_next += 4; 132624c32852SRichard Henderson 13278000ba56SRichard Henderson /* When exiting the delay slot normally, exit via jmp_pc. 13288000ba56SRichard Henderson * For DISAS_NORETURN, we have raised an exception and already exited. 13298000ba56SRichard Henderson * For DISAS_EXIT, we found l.rfe in a delay slot. There's nothing 13308000ba56SRichard Henderson * in the manual saying this is illegal, but it surely it should. 13318000ba56SRichard Henderson * At least or1ksim overrides pcnext and ignores the branch. 13328000ba56SRichard Henderson */ 13338000ba56SRichard Henderson if (dc->delayed_branch 13348000ba56SRichard Henderson && --dc->delayed_branch == 0 13358000ba56SRichard Henderson && dc->base.is_jmp == DISAS_NEXT) { 13368000ba56SRichard Henderson dc->base.is_jmp = DISAS_JUMP; 1337bbe418f2SJia Liu } 1338a4fd3ec3SEmilio G. Cota } 1339bbe418f2SJia Liu 1340a4fd3ec3SEmilio G. Cota static void openrisc_tr_tb_stop(DisasContextBase *dcbase, CPUState *cs) 1341a4fd3ec3SEmilio G. Cota { 1342a4fd3ec3SEmilio G. Cota DisasContext *dc = container_of(dcbase, DisasContext, base); 13438000ba56SRichard Henderson target_ulong jmp_dest; 134424c32852SRichard Henderson 1345e0a369cfSRichard Henderson /* If we have already exited the TB, nothing following has effect. */ 1346e0a369cfSRichard Henderson if (dc->base.is_jmp == DISAS_NORETURN) { 1347e0a369cfSRichard Henderson return; 1348e0a369cfSRichard Henderson } 1349e0a369cfSRichard Henderson 13508000ba56SRichard Henderson /* Adjust the delayed branch state for the next TB. */ 1351a01deb36SRichard Henderson if ((dc->tb_flags & TB_FLAGS_DFLAG ? 1 : 0) != (dc->delayed_branch != 0)) { 1352a01deb36SRichard Henderson tcg_gen_movi_i32(cpu_dflag, dc->delayed_branch != 0); 1353a01deb36SRichard Henderson } 1354a01deb36SRichard Henderson 13558000ba56SRichard Henderson /* For DISAS_TOO_MANY, jump to the next insn. */ 13568000ba56SRichard Henderson jmp_dest = dc->base.pc_next; 13578000ba56SRichard Henderson tcg_gen_movi_tl(cpu_ppc, jmp_dest - 4); 13588000ba56SRichard Henderson 13591ffa4bceSEmilio G. Cota switch (dc->base.is_jmp) { 13608000ba56SRichard Henderson case DISAS_JUMP: 13618000ba56SRichard Henderson jmp_dest = dc->jmp_pc_imm; 13628000ba56SRichard Henderson if (jmp_dest == -1) { 13638000ba56SRichard Henderson /* The jump destination is indirect/computed; use jmp_pc. */ 13648000ba56SRichard Henderson tcg_gen_mov_tl(cpu_pc, jmp_pc); 13658000ba56SRichard Henderson tcg_gen_discard_tl(jmp_pc); 13668000ba56SRichard Henderson if (unlikely(dc->base.singlestep_enabled)) { 13678000ba56SRichard Henderson gen_exception(dc, EXCP_DEBUG); 13688000ba56SRichard Henderson } else { 13698000ba56SRichard Henderson tcg_gen_lookup_and_goto_ptr(); 13708000ba56SRichard Henderson } 1371bbe418f2SJia Liu break; 13728000ba56SRichard Henderson } 13738000ba56SRichard Henderson /* The jump destination is direct; use jmp_pc_imm. 13748000ba56SRichard Henderson However, we will have stored into jmp_pc as well; 13758000ba56SRichard Henderson we know now that it wasn't needed. */ 13768000ba56SRichard Henderson tcg_gen_discard_tl(jmp_pc); 13778000ba56SRichard Henderson /* fallthru */ 13788000ba56SRichard Henderson 13798000ba56SRichard Henderson case DISAS_TOO_MANY: 13808000ba56SRichard Henderson if (unlikely(dc->base.singlestep_enabled)) { 13818000ba56SRichard Henderson tcg_gen_movi_tl(cpu_pc, jmp_dest); 13828000ba56SRichard Henderson gen_exception(dc, EXCP_DEBUG); 13838000ba56SRichard Henderson } else if ((dc->base.pc_first ^ jmp_dest) & TARGET_PAGE_MASK) { 13848000ba56SRichard Henderson tcg_gen_movi_tl(cpu_pc, jmp_dest); 13858000ba56SRichard Henderson tcg_gen_lookup_and_goto_ptr(); 13868000ba56SRichard Henderson } else { 13878000ba56SRichard Henderson tcg_gen_goto_tb(0); 13888000ba56SRichard Henderson tcg_gen_movi_tl(cpu_pc, jmp_dest); 13898000ba56SRichard Henderson tcg_gen_exit_tb(dc->base.tb, 0); 13908000ba56SRichard Henderson } 13918000ba56SRichard Henderson break; 13928000ba56SRichard Henderson 139364e46c95SRichard Henderson case DISAS_EXIT: 1394e0a369cfSRichard Henderson if (unlikely(dc->base.singlestep_enabled)) { 1395e0a369cfSRichard Henderson gen_exception(dc, EXCP_DEBUG); 1396e0a369cfSRichard Henderson } else { 139707ea28b4SRichard Henderson tcg_gen_exit_tb(NULL, 0); 1398e0a369cfSRichard Henderson } 1399bbe418f2SJia Liu break; 1400a4fd3ec3SEmilio G. Cota default: 1401a4fd3ec3SEmilio G. Cota g_assert_not_reached(); 1402a4fd3ec3SEmilio G. Cota } 1403bbe418f2SJia Liu } 1404bbe418f2SJia Liu 1405a4fd3ec3SEmilio G. Cota static void openrisc_tr_disas_log(const DisasContextBase *dcbase, CPUState *cs) 1406a4fd3ec3SEmilio G. Cota { 1407a4fd3ec3SEmilio G. Cota DisasContext *s = container_of(dcbase, DisasContext, base); 14080a7df5daSRichard Henderson 1409a4fd3ec3SEmilio G. Cota qemu_log("IN: %s\n", lookup_symbol(s->base.pc_first)); 1410a4fd3ec3SEmilio G. Cota log_target_disas(cs, s->base.pc_first, s->base.tb->size); 1411bbe418f2SJia Liu } 1412a4fd3ec3SEmilio G. Cota 1413a4fd3ec3SEmilio G. Cota static const TranslatorOps openrisc_tr_ops = { 1414a4fd3ec3SEmilio G. Cota .init_disas_context = openrisc_tr_init_disas_context, 1415a4fd3ec3SEmilio G. Cota .tb_start = openrisc_tr_tb_start, 1416a4fd3ec3SEmilio G. Cota .insn_start = openrisc_tr_insn_start, 1417a4fd3ec3SEmilio G. Cota .breakpoint_check = openrisc_tr_breakpoint_check, 1418a4fd3ec3SEmilio G. Cota .translate_insn = openrisc_tr_translate_insn, 1419a4fd3ec3SEmilio G. Cota .tb_stop = openrisc_tr_tb_stop, 1420a4fd3ec3SEmilio G. Cota .disas_log = openrisc_tr_disas_log, 1421a4fd3ec3SEmilio G. Cota }; 1422a4fd3ec3SEmilio G. Cota 14238b86d6d2SRichard Henderson void gen_intermediate_code(CPUState *cs, TranslationBlock *tb, int max_insns) 1424a4fd3ec3SEmilio G. Cota { 1425a4fd3ec3SEmilio G. Cota DisasContext ctx; 1426a4fd3ec3SEmilio G. Cota 14278b86d6d2SRichard Henderson translator_loop(&openrisc_tr_ops, &ctx.base, cs, tb, max_insns); 1428e67db06eSJia Liu } 1429e67db06eSJia Liu 143090c84c56SMarkus Armbruster void openrisc_cpu_dump_state(CPUState *cs, FILE *f, int flags) 1431e67db06eSJia Liu { 1432878096eeSAndreas Färber OpenRISCCPU *cpu = OPENRISC_CPU(cs); 1433878096eeSAndreas Färber CPUOpenRISCState *env = &cpu->env; 1434e67db06eSJia Liu int i; 1435878096eeSAndreas Färber 143690c84c56SMarkus Armbruster qemu_fprintf(f, "PC=%08x\n", env->pc); 1437e67db06eSJia Liu for (i = 0; i < 32; ++i) { 143890c84c56SMarkus Armbruster qemu_fprintf(f, "R%02d=%08x%c", i, cpu_get_gpr(env, i), 1439e67db06eSJia Liu (i % 4) == 3 ? '\n' : ' '); 1440e67db06eSJia Liu } 1441e67db06eSJia Liu } 1442e67db06eSJia Liu 1443e67db06eSJia Liu void restore_state_to_opc(CPUOpenRISCState *env, TranslationBlock *tb, 1444bad729e2SRichard Henderson target_ulong *data) 1445e67db06eSJia Liu { 1446bad729e2SRichard Henderson env->pc = data[0]; 1447a01deb36SRichard Henderson env->dflag = data[1] & 1; 1448a01deb36SRichard Henderson if (data[1] & 2) { 144924c32852SRichard Henderson env->ppc = env->pc - 4; 145024c32852SRichard Henderson } 1451e67db06eSJia Liu } 1452