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; 48fe636d37SRichard 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 144fe636d37SRichard Henderson static bool check_of32s(DisasContext *dc) 145bbe418f2SJia Liu { 146fe636d37SRichard Henderson return dc->cpucfgr & CPUCFGR_OF32S; 147bbe418f2SJia Liu } 148bbe418f2SJia Liu 149*62f2b038SRichard Henderson static bool check_of64a32s(DisasContext *dc) 150*62f2b038SRichard Henderson { 151*62f2b038SRichard Henderson return dc->cpucfgr & CPUCFGR_OF64A32S; 152*62f2b038SRichard Henderson } 153*62f2b038SRichard Henderson 1548bba7619SRichard Henderson static TCGv cpu_R(DisasContext *dc, int reg) 1558bba7619SRichard Henderson { 156d29f4368SRichard Henderson if (reg == 0) { 157d29f4368SRichard Henderson return dc->R0; 158d29f4368SRichard Henderson } else { 1598bba7619SRichard Henderson return cpu_regs[reg]; 1608bba7619SRichard Henderson } 161d29f4368SRichard Henderson } 1628bba7619SRichard Henderson 163cdd0f459SRichard Henderson /* 164cdd0f459SRichard Henderson * We're about to write to REG. On the off-chance that the user is 165cdd0f459SRichard Henderson * writing to R0, re-instate the architectural register. 166cdd0f459SRichard Henderson */ 167cdd0f459SRichard Henderson static void check_r0_write(DisasContext *dc, int reg) 168cdd0f459SRichard Henderson { 169cdd0f459SRichard Henderson if (unlikely(reg == 0)) { 170d29f4368SRichard Henderson dc->R0 = cpu_regs[0]; 171cdd0f459SRichard Henderson } 172cdd0f459SRichard Henderson } 1736597c28dSRichard Henderson 17497458071SRichard Henderson static void gen_ove_cy(DisasContext *dc) 1759ecaa27eSRichard Henderson { 1760c53d734SRichard Henderson if (dc->tb_flags & SR_OVE) { 17797458071SRichard Henderson gen_helper_ove_cy(cpu_env); 1789ecaa27eSRichard Henderson } 1790c53d734SRichard Henderson } 1809ecaa27eSRichard Henderson 18197458071SRichard Henderson static void gen_ove_ov(DisasContext *dc) 1829ecaa27eSRichard Henderson { 1830c53d734SRichard Henderson if (dc->tb_flags & SR_OVE) { 18497458071SRichard Henderson gen_helper_ove_ov(cpu_env); 1859ecaa27eSRichard Henderson } 1860c53d734SRichard Henderson } 1879ecaa27eSRichard Henderson 18897458071SRichard Henderson static void gen_ove_cyov(DisasContext *dc) 1899ecaa27eSRichard Henderson { 1900c53d734SRichard Henderson if (dc->tb_flags & SR_OVE) { 19197458071SRichard Henderson gen_helper_ove_cyov(cpu_env); 1929ecaa27eSRichard Henderson } 1930c53d734SRichard Henderson } 1949ecaa27eSRichard Henderson 1959ecaa27eSRichard Henderson static void gen_add(DisasContext *dc, TCGv dest, TCGv srca, TCGv srcb) 1969ecaa27eSRichard Henderson { 1979ecaa27eSRichard Henderson TCGv t0 = tcg_const_tl(0); 1989ecaa27eSRichard Henderson TCGv res = tcg_temp_new(); 1999ecaa27eSRichard Henderson 20097458071SRichard Henderson tcg_gen_add2_tl(res, cpu_sr_cy, srca, t0, srcb, t0); 20197458071SRichard Henderson tcg_gen_xor_tl(cpu_sr_ov, srca, srcb); 2029ecaa27eSRichard Henderson tcg_gen_xor_tl(t0, res, srcb); 20397458071SRichard Henderson tcg_gen_andc_tl(cpu_sr_ov, t0, cpu_sr_ov); 2049ecaa27eSRichard Henderson tcg_temp_free(t0); 2059ecaa27eSRichard Henderson 2069ecaa27eSRichard Henderson tcg_gen_mov_tl(dest, res); 2079ecaa27eSRichard Henderson tcg_temp_free(res); 2089ecaa27eSRichard Henderson 20997458071SRichard Henderson gen_ove_cyov(dc); 2109ecaa27eSRichard Henderson } 2119ecaa27eSRichard Henderson 2129ecaa27eSRichard Henderson static void gen_addc(DisasContext *dc, TCGv dest, TCGv srca, TCGv srcb) 2139ecaa27eSRichard Henderson { 2149ecaa27eSRichard Henderson TCGv t0 = tcg_const_tl(0); 2159ecaa27eSRichard Henderson TCGv res = tcg_temp_new(); 2169ecaa27eSRichard Henderson 21797458071SRichard Henderson tcg_gen_add2_tl(res, cpu_sr_cy, srca, t0, cpu_sr_cy, t0); 21897458071SRichard Henderson tcg_gen_add2_tl(res, cpu_sr_cy, res, cpu_sr_cy, srcb, t0); 21997458071SRichard Henderson tcg_gen_xor_tl(cpu_sr_ov, srca, srcb); 2209ecaa27eSRichard Henderson tcg_gen_xor_tl(t0, res, srcb); 22197458071SRichard Henderson tcg_gen_andc_tl(cpu_sr_ov, t0, cpu_sr_ov); 2229ecaa27eSRichard Henderson tcg_temp_free(t0); 2239ecaa27eSRichard Henderson 2249ecaa27eSRichard Henderson tcg_gen_mov_tl(dest, res); 2259ecaa27eSRichard Henderson tcg_temp_free(res); 2269ecaa27eSRichard Henderson 22797458071SRichard Henderson gen_ove_cyov(dc); 2289ecaa27eSRichard Henderson } 2299ecaa27eSRichard Henderson 2309ecaa27eSRichard Henderson static void gen_sub(DisasContext *dc, TCGv dest, TCGv srca, TCGv srcb) 2319ecaa27eSRichard Henderson { 2329ecaa27eSRichard Henderson TCGv res = tcg_temp_new(); 2339ecaa27eSRichard Henderson 2349ecaa27eSRichard Henderson tcg_gen_sub_tl(res, srca, srcb); 23597458071SRichard Henderson tcg_gen_xor_tl(cpu_sr_cy, srca, srcb); 23697458071SRichard Henderson tcg_gen_xor_tl(cpu_sr_ov, res, srcb); 23797458071SRichard Henderson tcg_gen_and_tl(cpu_sr_ov, cpu_sr_ov, cpu_sr_cy); 23897458071SRichard Henderson tcg_gen_setcond_tl(TCG_COND_LTU, cpu_sr_cy, srca, srcb); 2399ecaa27eSRichard Henderson 2409ecaa27eSRichard Henderson tcg_gen_mov_tl(dest, res); 2419ecaa27eSRichard Henderson tcg_temp_free(res); 2429ecaa27eSRichard Henderson 24397458071SRichard Henderson gen_ove_cyov(dc); 2449ecaa27eSRichard Henderson } 2459ecaa27eSRichard Henderson 2469ecaa27eSRichard Henderson static void gen_mul(DisasContext *dc, TCGv dest, TCGv srca, TCGv srcb) 2479ecaa27eSRichard Henderson { 2489ecaa27eSRichard Henderson TCGv t0 = tcg_temp_new(); 2499ecaa27eSRichard Henderson 25097458071SRichard Henderson tcg_gen_muls2_tl(dest, cpu_sr_ov, srca, srcb); 2519ecaa27eSRichard Henderson tcg_gen_sari_tl(t0, dest, TARGET_LONG_BITS - 1); 25297458071SRichard Henderson tcg_gen_setcond_tl(TCG_COND_NE, cpu_sr_ov, cpu_sr_ov, t0); 2539ecaa27eSRichard Henderson tcg_temp_free(t0); 2549ecaa27eSRichard Henderson 25597458071SRichard Henderson tcg_gen_neg_tl(cpu_sr_ov, cpu_sr_ov); 25697458071SRichard Henderson gen_ove_ov(dc); 2579ecaa27eSRichard Henderson } 2589ecaa27eSRichard Henderson 2599ecaa27eSRichard Henderson static void gen_mulu(DisasContext *dc, TCGv dest, TCGv srca, TCGv srcb) 2609ecaa27eSRichard Henderson { 26197458071SRichard Henderson tcg_gen_muls2_tl(dest, cpu_sr_cy, srca, srcb); 26297458071SRichard Henderson tcg_gen_setcondi_tl(TCG_COND_NE, cpu_sr_cy, cpu_sr_cy, 0); 2639ecaa27eSRichard Henderson 26497458071SRichard Henderson gen_ove_cy(dc); 2659ecaa27eSRichard Henderson } 2669ecaa27eSRichard Henderson 2679ecaa27eSRichard Henderson static void gen_div(DisasContext *dc, TCGv dest, TCGv srca, TCGv srcb) 2689ecaa27eSRichard Henderson { 2699ecaa27eSRichard Henderson TCGv t0 = tcg_temp_new(); 2709ecaa27eSRichard Henderson 27197458071SRichard Henderson tcg_gen_setcondi_tl(TCG_COND_EQ, cpu_sr_ov, srcb, 0); 2729ecaa27eSRichard Henderson /* The result of divide-by-zero is undefined. 2739ecaa27eSRichard Henderson Supress the host-side exception by dividing by 1. */ 27497458071SRichard Henderson tcg_gen_or_tl(t0, srcb, cpu_sr_ov); 2759ecaa27eSRichard Henderson tcg_gen_div_tl(dest, srca, t0); 2769ecaa27eSRichard Henderson tcg_temp_free(t0); 2779ecaa27eSRichard Henderson 27897458071SRichard Henderson tcg_gen_neg_tl(cpu_sr_ov, cpu_sr_ov); 27997458071SRichard Henderson gen_ove_ov(dc); 2809ecaa27eSRichard Henderson } 2819ecaa27eSRichard Henderson 2829ecaa27eSRichard Henderson static void gen_divu(DisasContext *dc, TCGv dest, TCGv srca, TCGv srcb) 2839ecaa27eSRichard Henderson { 2849ecaa27eSRichard Henderson TCGv t0 = tcg_temp_new(); 2859ecaa27eSRichard Henderson 28697458071SRichard Henderson tcg_gen_setcondi_tl(TCG_COND_EQ, cpu_sr_cy, srcb, 0); 2879ecaa27eSRichard Henderson /* The result of divide-by-zero is undefined. 2889ecaa27eSRichard Henderson Supress the host-side exception by dividing by 1. */ 28997458071SRichard Henderson tcg_gen_or_tl(t0, srcb, cpu_sr_cy); 2909ecaa27eSRichard Henderson tcg_gen_divu_tl(dest, srca, t0); 2919ecaa27eSRichard Henderson tcg_temp_free(t0); 2929ecaa27eSRichard Henderson 29397458071SRichard Henderson gen_ove_cy(dc); 2949ecaa27eSRichard Henderson } 295da1d7759SSebastian Macke 296cc5de49eSRichard Henderson static void gen_muld(DisasContext *dc, TCGv srca, TCGv srcb) 297cc5de49eSRichard Henderson { 298cc5de49eSRichard Henderson TCGv_i64 t1 = tcg_temp_new_i64(); 299cc5de49eSRichard Henderson TCGv_i64 t2 = tcg_temp_new_i64(); 300cc5de49eSRichard Henderson 301cc5de49eSRichard Henderson tcg_gen_ext_tl_i64(t1, srca); 302cc5de49eSRichard Henderson tcg_gen_ext_tl_i64(t2, srcb); 303cc5de49eSRichard Henderson if (TARGET_LONG_BITS == 32) { 304cc5de49eSRichard Henderson tcg_gen_mul_i64(cpu_mac, t1, t2); 305cc5de49eSRichard Henderson tcg_gen_movi_tl(cpu_sr_ov, 0); 306cc5de49eSRichard Henderson } else { 307cc5de49eSRichard Henderson TCGv_i64 high = tcg_temp_new_i64(); 308cc5de49eSRichard Henderson 309cc5de49eSRichard Henderson tcg_gen_muls2_i64(cpu_mac, high, t1, t2); 310cc5de49eSRichard Henderson tcg_gen_sari_i64(t1, cpu_mac, 63); 311cc5de49eSRichard Henderson tcg_gen_setcond_i64(TCG_COND_NE, t1, t1, high); 312cc5de49eSRichard Henderson tcg_temp_free_i64(high); 313cc5de49eSRichard Henderson tcg_gen_trunc_i64_tl(cpu_sr_ov, t1); 314cc5de49eSRichard Henderson tcg_gen_neg_tl(cpu_sr_ov, cpu_sr_ov); 315cc5de49eSRichard Henderson 316cc5de49eSRichard Henderson gen_ove_ov(dc); 317cc5de49eSRichard Henderson } 318cc5de49eSRichard Henderson tcg_temp_free_i64(t1); 319cc5de49eSRichard Henderson tcg_temp_free_i64(t2); 320cc5de49eSRichard Henderson } 321cc5de49eSRichard Henderson 322cc5de49eSRichard Henderson static void gen_muldu(DisasContext *dc, TCGv srca, TCGv srcb) 323cc5de49eSRichard Henderson { 324cc5de49eSRichard Henderson TCGv_i64 t1 = tcg_temp_new_i64(); 325cc5de49eSRichard Henderson TCGv_i64 t2 = tcg_temp_new_i64(); 326cc5de49eSRichard Henderson 327cc5de49eSRichard Henderson tcg_gen_extu_tl_i64(t1, srca); 328cc5de49eSRichard Henderson tcg_gen_extu_tl_i64(t2, srcb); 329cc5de49eSRichard Henderson if (TARGET_LONG_BITS == 32) { 330cc5de49eSRichard Henderson tcg_gen_mul_i64(cpu_mac, t1, t2); 331cc5de49eSRichard Henderson tcg_gen_movi_tl(cpu_sr_cy, 0); 332cc5de49eSRichard Henderson } else { 333cc5de49eSRichard Henderson TCGv_i64 high = tcg_temp_new_i64(); 334cc5de49eSRichard Henderson 335cc5de49eSRichard Henderson tcg_gen_mulu2_i64(cpu_mac, high, t1, t2); 336cc5de49eSRichard Henderson tcg_gen_setcondi_i64(TCG_COND_NE, high, high, 0); 337cc5de49eSRichard Henderson tcg_gen_trunc_i64_tl(cpu_sr_cy, high); 338cc5de49eSRichard Henderson tcg_temp_free_i64(high); 339cc5de49eSRichard Henderson 340cc5de49eSRichard Henderson gen_ove_cy(dc); 341cc5de49eSRichard Henderson } 342cc5de49eSRichard Henderson tcg_temp_free_i64(t1); 343cc5de49eSRichard Henderson tcg_temp_free_i64(t2); 344cc5de49eSRichard Henderson } 345cc5de49eSRichard Henderson 3466f7332baSRichard Henderson static void gen_mac(DisasContext *dc, TCGv srca, TCGv srcb) 3476f7332baSRichard Henderson { 3486f7332baSRichard Henderson TCGv_i64 t1 = tcg_temp_new_i64(); 3496f7332baSRichard Henderson TCGv_i64 t2 = tcg_temp_new_i64(); 3506f7332baSRichard Henderson 3516f7332baSRichard Henderson tcg_gen_ext_tl_i64(t1, srca); 3526f7332baSRichard Henderson tcg_gen_ext_tl_i64(t2, srcb); 3536f7332baSRichard Henderson tcg_gen_mul_i64(t1, t1, t2); 3546f7332baSRichard Henderson 3556f7332baSRichard Henderson /* Note that overflow is only computed during addition stage. */ 3566f7332baSRichard Henderson tcg_gen_xor_i64(t2, cpu_mac, t1); 3576f7332baSRichard Henderson tcg_gen_add_i64(cpu_mac, cpu_mac, t1); 3586f7332baSRichard Henderson tcg_gen_xor_i64(t1, t1, cpu_mac); 3596f7332baSRichard Henderson tcg_gen_andc_i64(t1, t1, t2); 3606f7332baSRichard Henderson tcg_temp_free_i64(t2); 3616f7332baSRichard Henderson 3626f7332baSRichard Henderson #if TARGET_LONG_BITS == 32 3636f7332baSRichard Henderson tcg_gen_extrh_i64_i32(cpu_sr_ov, t1); 3646f7332baSRichard Henderson #else 3656f7332baSRichard Henderson tcg_gen_mov_i64(cpu_sr_ov, t1); 3666f7332baSRichard Henderson #endif 3676f7332baSRichard Henderson tcg_temp_free_i64(t1); 3686f7332baSRichard Henderson 3696f7332baSRichard Henderson gen_ove_ov(dc); 3706f7332baSRichard Henderson } 3716f7332baSRichard Henderson 372cc5de49eSRichard Henderson static void gen_macu(DisasContext *dc, TCGv srca, TCGv srcb) 373cc5de49eSRichard Henderson { 374cc5de49eSRichard Henderson TCGv_i64 t1 = tcg_temp_new_i64(); 375cc5de49eSRichard Henderson TCGv_i64 t2 = tcg_temp_new_i64(); 376cc5de49eSRichard Henderson 377cc5de49eSRichard Henderson tcg_gen_extu_tl_i64(t1, srca); 378cc5de49eSRichard Henderson tcg_gen_extu_tl_i64(t2, srcb); 379cc5de49eSRichard Henderson tcg_gen_mul_i64(t1, t1, t2); 380cc5de49eSRichard Henderson tcg_temp_free_i64(t2); 381cc5de49eSRichard Henderson 382cc5de49eSRichard Henderson /* Note that overflow is only computed during addition stage. */ 383cc5de49eSRichard Henderson tcg_gen_add_i64(cpu_mac, cpu_mac, t1); 384cc5de49eSRichard Henderson tcg_gen_setcond_i64(TCG_COND_LTU, t1, cpu_mac, t1); 385cc5de49eSRichard Henderson tcg_gen_trunc_i64_tl(cpu_sr_cy, t1); 386cc5de49eSRichard Henderson tcg_temp_free_i64(t1); 387cc5de49eSRichard Henderson 388cc5de49eSRichard Henderson gen_ove_cy(dc); 389cc5de49eSRichard Henderson } 390cc5de49eSRichard Henderson 3916f7332baSRichard Henderson static void gen_msb(DisasContext *dc, TCGv srca, TCGv srcb) 3926f7332baSRichard Henderson { 3936f7332baSRichard Henderson TCGv_i64 t1 = tcg_temp_new_i64(); 3946f7332baSRichard Henderson TCGv_i64 t2 = tcg_temp_new_i64(); 3956f7332baSRichard Henderson 3966f7332baSRichard Henderson tcg_gen_ext_tl_i64(t1, srca); 3976f7332baSRichard Henderson tcg_gen_ext_tl_i64(t2, srcb); 3986f7332baSRichard Henderson tcg_gen_mul_i64(t1, t1, t2); 3996f7332baSRichard Henderson 4006f7332baSRichard Henderson /* Note that overflow is only computed during subtraction stage. */ 4016f7332baSRichard Henderson tcg_gen_xor_i64(t2, cpu_mac, t1); 4026f7332baSRichard Henderson tcg_gen_sub_i64(cpu_mac, cpu_mac, t1); 4036f7332baSRichard Henderson tcg_gen_xor_i64(t1, t1, cpu_mac); 4046f7332baSRichard Henderson tcg_gen_and_i64(t1, t1, t2); 4056f7332baSRichard Henderson tcg_temp_free_i64(t2); 4066f7332baSRichard Henderson 4076f7332baSRichard Henderson #if TARGET_LONG_BITS == 32 4086f7332baSRichard Henderson tcg_gen_extrh_i64_i32(cpu_sr_ov, t1); 4096f7332baSRichard Henderson #else 4106f7332baSRichard Henderson tcg_gen_mov_i64(cpu_sr_ov, t1); 4116f7332baSRichard Henderson #endif 4126f7332baSRichard Henderson tcg_temp_free_i64(t1); 4136f7332baSRichard Henderson 4146f7332baSRichard Henderson gen_ove_ov(dc); 4156f7332baSRichard Henderson } 4166f7332baSRichard Henderson 417cc5de49eSRichard Henderson static void gen_msbu(DisasContext *dc, TCGv srca, TCGv srcb) 418cc5de49eSRichard Henderson { 419cc5de49eSRichard Henderson TCGv_i64 t1 = tcg_temp_new_i64(); 420cc5de49eSRichard Henderson TCGv_i64 t2 = tcg_temp_new_i64(); 421cc5de49eSRichard Henderson 422cc5de49eSRichard Henderson tcg_gen_extu_tl_i64(t1, srca); 423cc5de49eSRichard Henderson tcg_gen_extu_tl_i64(t2, srcb); 424cc5de49eSRichard Henderson tcg_gen_mul_i64(t1, t1, t2); 425cc5de49eSRichard Henderson 426cc5de49eSRichard Henderson /* Note that overflow is only computed during subtraction stage. */ 427cc5de49eSRichard Henderson tcg_gen_setcond_i64(TCG_COND_LTU, t2, cpu_mac, t1); 428cc5de49eSRichard Henderson tcg_gen_sub_i64(cpu_mac, cpu_mac, t1); 429cc5de49eSRichard Henderson tcg_gen_trunc_i64_tl(cpu_sr_cy, t2); 430cc5de49eSRichard Henderson tcg_temp_free_i64(t2); 431cc5de49eSRichard Henderson tcg_temp_free_i64(t1); 432cc5de49eSRichard Henderson 433cc5de49eSRichard Henderson gen_ove_cy(dc); 434cc5de49eSRichard Henderson } 435cc5de49eSRichard Henderson 4363a7be554SRichard Henderson static bool trans_l_add(DisasContext *dc, arg_dab *a) 437bbe418f2SJia Liu { 438cdd0f459SRichard Henderson check_r0_write(dc, a->d); 4398bba7619SRichard Henderson gen_add(dc, cpu_R(dc, a->d), cpu_R(dc, a->a), cpu_R(dc, a->b)); 4406ad216abSRichard Henderson return true; 441bbe418f2SJia Liu } 442bbe418f2SJia Liu 4433a7be554SRichard Henderson static bool trans_l_addc(DisasContext *dc, arg_dab *a) 444bbe418f2SJia Liu { 445cdd0f459SRichard Henderson check_r0_write(dc, a->d); 4468bba7619SRichard Henderson gen_addc(dc, cpu_R(dc, a->d), cpu_R(dc, a->a), cpu_R(dc, a->b)); 4476ad216abSRichard Henderson return true; 4486ad216abSRichard Henderson } 4496ad216abSRichard Henderson 4503a7be554SRichard Henderson static bool trans_l_sub(DisasContext *dc, arg_dab *a) 4516ad216abSRichard Henderson { 452cdd0f459SRichard Henderson check_r0_write(dc, a->d); 4538bba7619SRichard Henderson gen_sub(dc, cpu_R(dc, a->d), cpu_R(dc, a->a), cpu_R(dc, a->b)); 4546ad216abSRichard Henderson return true; 4556ad216abSRichard Henderson } 4566ad216abSRichard Henderson 4573a7be554SRichard Henderson static bool trans_l_and(DisasContext *dc, arg_dab *a) 4586ad216abSRichard Henderson { 459cdd0f459SRichard Henderson check_r0_write(dc, a->d); 4608bba7619SRichard Henderson tcg_gen_and_tl(cpu_R(dc, a->d), cpu_R(dc, a->a), cpu_R(dc, a->b)); 4616ad216abSRichard Henderson return true; 4626ad216abSRichard Henderson } 4636ad216abSRichard Henderson 4643a7be554SRichard Henderson static bool trans_l_or(DisasContext *dc, arg_dab *a) 4656ad216abSRichard Henderson { 466cdd0f459SRichard Henderson check_r0_write(dc, a->d); 4678bba7619SRichard Henderson tcg_gen_or_tl(cpu_R(dc, a->d), cpu_R(dc, a->a), cpu_R(dc, a->b)); 4686ad216abSRichard Henderson return true; 4696ad216abSRichard Henderson } 4706ad216abSRichard Henderson 4713a7be554SRichard Henderson static bool trans_l_xor(DisasContext *dc, arg_dab *a) 4726ad216abSRichard Henderson { 473cdd0f459SRichard Henderson check_r0_write(dc, a->d); 4748bba7619SRichard Henderson tcg_gen_xor_tl(cpu_R(dc, a->d), cpu_R(dc, a->a), cpu_R(dc, a->b)); 4756ad216abSRichard Henderson return true; 4766ad216abSRichard Henderson } 4776ad216abSRichard Henderson 4783a7be554SRichard Henderson static bool trans_l_sll(DisasContext *dc, arg_dab *a) 4796ad216abSRichard Henderson { 480cdd0f459SRichard Henderson check_r0_write(dc, a->d); 4818bba7619SRichard Henderson tcg_gen_shl_tl(cpu_R(dc, a->d), cpu_R(dc, a->a), cpu_R(dc, a->b)); 4826ad216abSRichard Henderson return true; 4836ad216abSRichard Henderson } 4846ad216abSRichard Henderson 4853a7be554SRichard Henderson static bool trans_l_srl(DisasContext *dc, arg_dab *a) 4866ad216abSRichard Henderson { 487cdd0f459SRichard Henderson check_r0_write(dc, a->d); 4888bba7619SRichard Henderson tcg_gen_shr_tl(cpu_R(dc, a->d), cpu_R(dc, a->a), cpu_R(dc, a->b)); 4896ad216abSRichard Henderson return true; 4906ad216abSRichard Henderson } 4916ad216abSRichard Henderson 4923a7be554SRichard Henderson static bool trans_l_sra(DisasContext *dc, arg_dab *a) 4936ad216abSRichard Henderson { 494cdd0f459SRichard Henderson check_r0_write(dc, a->d); 4958bba7619SRichard Henderson tcg_gen_sar_tl(cpu_R(dc, a->d), cpu_R(dc, a->a), cpu_R(dc, a->b)); 4966ad216abSRichard Henderson return true; 4976ad216abSRichard Henderson } 4986ad216abSRichard Henderson 4993a7be554SRichard Henderson static bool trans_l_ror(DisasContext *dc, arg_dab *a) 5006ad216abSRichard Henderson { 501cdd0f459SRichard Henderson check_r0_write(dc, a->d); 5028bba7619SRichard Henderson tcg_gen_rotr_tl(cpu_R(dc, a->d), cpu_R(dc, a->a), cpu_R(dc, a->b)); 5036ad216abSRichard Henderson return true; 5046ad216abSRichard Henderson } 5056ad216abSRichard Henderson 5063a7be554SRichard Henderson static bool trans_l_exths(DisasContext *dc, arg_da *a) 5076ad216abSRichard Henderson { 508cdd0f459SRichard Henderson check_r0_write(dc, a->d); 5098bba7619SRichard Henderson tcg_gen_ext16s_tl(cpu_R(dc, a->d), cpu_R(dc, a->a)); 5106ad216abSRichard Henderson return true; 5116ad216abSRichard Henderson } 5126ad216abSRichard Henderson 5133a7be554SRichard Henderson static bool trans_l_extbs(DisasContext *dc, arg_da *a) 5146ad216abSRichard Henderson { 515cdd0f459SRichard Henderson check_r0_write(dc, a->d); 5168bba7619SRichard Henderson tcg_gen_ext8s_tl(cpu_R(dc, a->d), cpu_R(dc, a->a)); 5176ad216abSRichard Henderson return true; 5186ad216abSRichard Henderson } 5196ad216abSRichard Henderson 5203a7be554SRichard Henderson static bool trans_l_exthz(DisasContext *dc, arg_da *a) 5216ad216abSRichard Henderson { 522cdd0f459SRichard Henderson check_r0_write(dc, a->d); 5238bba7619SRichard Henderson tcg_gen_ext16u_tl(cpu_R(dc, a->d), cpu_R(dc, a->a)); 5246ad216abSRichard Henderson return true; 5256ad216abSRichard Henderson } 5266ad216abSRichard Henderson 5273a7be554SRichard Henderson static bool trans_l_extbz(DisasContext *dc, arg_da *a) 5286ad216abSRichard Henderson { 529cdd0f459SRichard Henderson check_r0_write(dc, a->d); 5308bba7619SRichard Henderson tcg_gen_ext8u_tl(cpu_R(dc, a->d), cpu_R(dc, a->a)); 5316ad216abSRichard Henderson return true; 5326ad216abSRichard Henderson } 5336ad216abSRichard Henderson 5343a7be554SRichard Henderson static bool trans_l_cmov(DisasContext *dc, arg_dab *a) 5356ad216abSRichard Henderson { 5366ad216abSRichard Henderson TCGv zero; 5376ad216abSRichard Henderson 538cdd0f459SRichard Henderson check_r0_write(dc, a->d); 5396ad216abSRichard Henderson zero = tcg_const_tl(0); 5408bba7619SRichard Henderson tcg_gen_movcond_tl(TCG_COND_NE, cpu_R(dc, a->d), cpu_sr_f, zero, 5418bba7619SRichard Henderson cpu_R(dc, a->a), cpu_R(dc, a->b)); 542784696d1SRichard Henderson tcg_temp_free(zero); 5436ad216abSRichard Henderson return true; 544bbe418f2SJia Liu } 545bbe418f2SJia Liu 5463a7be554SRichard Henderson static bool trans_l_ff1(DisasContext *dc, arg_da *a) 5476ad216abSRichard Henderson { 548cdd0f459SRichard Henderson check_r0_write(dc, a->d); 5498bba7619SRichard Henderson tcg_gen_ctzi_tl(cpu_R(dc, a->d), cpu_R(dc, a->a), -1); 5508bba7619SRichard Henderson tcg_gen_addi_tl(cpu_R(dc, a->d), cpu_R(dc, a->d), 1); 5516ad216abSRichard Henderson return true; 552cf2ae442SRichard Henderson } 553cf2ae442SRichard Henderson 5543a7be554SRichard Henderson static bool trans_l_fl1(DisasContext *dc, arg_da *a) 5556ad216abSRichard Henderson { 556cdd0f459SRichard Henderson check_r0_write(dc, a->d); 5578bba7619SRichard Henderson tcg_gen_clzi_tl(cpu_R(dc, a->d), cpu_R(dc, a->a), TARGET_LONG_BITS); 5588bba7619SRichard Henderson tcg_gen_subfi_tl(cpu_R(dc, a->d), TARGET_LONG_BITS, cpu_R(dc, a->d)); 5596ad216abSRichard Henderson return true; 560bbe418f2SJia Liu } 561bbe418f2SJia Liu 5623a7be554SRichard Henderson static bool trans_l_mul(DisasContext *dc, arg_dab *a) 5636ad216abSRichard Henderson { 564cdd0f459SRichard Henderson check_r0_write(dc, a->d); 5658bba7619SRichard Henderson gen_mul(dc, cpu_R(dc, a->d), cpu_R(dc, a->a), cpu_R(dc, a->b)); 5666ad216abSRichard Henderson return true; 567bbe418f2SJia Liu } 5686ad216abSRichard Henderson 5693a7be554SRichard Henderson static bool trans_l_mulu(DisasContext *dc, arg_dab *a) 5706ad216abSRichard Henderson { 571cdd0f459SRichard Henderson check_r0_write(dc, a->d); 5728bba7619SRichard Henderson gen_mulu(dc, cpu_R(dc, a->d), cpu_R(dc, a->a), cpu_R(dc, a->b)); 5736ad216abSRichard Henderson return true; 574bbe418f2SJia Liu } 5756ad216abSRichard Henderson 5763a7be554SRichard Henderson static bool trans_l_div(DisasContext *dc, arg_dab *a) 5776ad216abSRichard Henderson { 578cdd0f459SRichard Henderson check_r0_write(dc, a->d); 5798bba7619SRichard Henderson gen_div(dc, cpu_R(dc, a->d), cpu_R(dc, a->a), cpu_R(dc, a->b)); 5806ad216abSRichard Henderson return true; 5816ad216abSRichard Henderson } 5826ad216abSRichard Henderson 5833a7be554SRichard Henderson static bool trans_l_divu(DisasContext *dc, arg_dab *a) 5846ad216abSRichard Henderson { 585cdd0f459SRichard Henderson check_r0_write(dc, a->d); 5868bba7619SRichard Henderson gen_divu(dc, cpu_R(dc, a->d), cpu_R(dc, a->a), cpu_R(dc, a->b)); 5876ad216abSRichard Henderson return true; 5886ad216abSRichard Henderson } 5896ad216abSRichard Henderson 5903a7be554SRichard Henderson static bool trans_l_muld(DisasContext *dc, arg_ab *a) 5916ad216abSRichard Henderson { 5928bba7619SRichard Henderson gen_muld(dc, cpu_R(dc, a->a), cpu_R(dc, a->b)); 5936ad216abSRichard Henderson return true; 5946ad216abSRichard Henderson } 5956ad216abSRichard Henderson 5963a7be554SRichard Henderson static bool trans_l_muldu(DisasContext *dc, arg_ab *a) 5976ad216abSRichard Henderson { 5988bba7619SRichard Henderson gen_muldu(dc, cpu_R(dc, a->a), cpu_R(dc, a->b)); 5996ad216abSRichard Henderson return true; 600bbe418f2SJia Liu } 601bbe418f2SJia Liu 6023a7be554SRichard Henderson static bool trans_l_j(DisasContext *dc, arg_l_j *a) 603136e13aeSRichard Henderson { 604136e13aeSRichard Henderson target_ulong tmp_pc = dc->base.pc_next + a->n * 4; 605136e13aeSRichard Henderson 606136e13aeSRichard Henderson tcg_gen_movi_tl(jmp_pc, tmp_pc); 6078000ba56SRichard Henderson dc->jmp_pc_imm = tmp_pc; 608136e13aeSRichard Henderson dc->delayed_branch = 2; 609136e13aeSRichard Henderson return true; 610136e13aeSRichard Henderson } 611136e13aeSRichard Henderson 6123a7be554SRichard Henderson static bool trans_l_jal(DisasContext *dc, arg_l_jal *a) 613136e13aeSRichard Henderson { 614136e13aeSRichard Henderson target_ulong tmp_pc = dc->base.pc_next + a->n * 4; 615136e13aeSRichard Henderson target_ulong ret_pc = dc->base.pc_next + 8; 616136e13aeSRichard Henderson 6178bba7619SRichard Henderson tcg_gen_movi_tl(cpu_regs[9], ret_pc); 618136e13aeSRichard Henderson /* Optimize jal being used to load the PC for PIC. */ 619136e13aeSRichard Henderson if (tmp_pc != ret_pc) { 620136e13aeSRichard Henderson tcg_gen_movi_tl(jmp_pc, tmp_pc); 6218000ba56SRichard Henderson dc->jmp_pc_imm = tmp_pc; 622136e13aeSRichard Henderson dc->delayed_branch = 2; 623136e13aeSRichard Henderson } 624136e13aeSRichard Henderson return true; 625136e13aeSRichard Henderson } 626136e13aeSRichard Henderson 627136e13aeSRichard Henderson static void do_bf(DisasContext *dc, arg_l_bf *a, TCGCond cond) 628136e13aeSRichard Henderson { 629136e13aeSRichard Henderson target_ulong tmp_pc = dc->base.pc_next + a->n * 4; 630136e13aeSRichard Henderson TCGv t_next = tcg_const_tl(dc->base.pc_next + 8); 631136e13aeSRichard Henderson TCGv t_true = tcg_const_tl(tmp_pc); 632136e13aeSRichard Henderson TCGv t_zero = tcg_const_tl(0); 633136e13aeSRichard Henderson 634136e13aeSRichard Henderson tcg_gen_movcond_tl(cond, jmp_pc, cpu_sr_f, t_zero, t_true, t_next); 635136e13aeSRichard Henderson 636136e13aeSRichard Henderson tcg_temp_free(t_next); 637136e13aeSRichard Henderson tcg_temp_free(t_true); 638136e13aeSRichard Henderson tcg_temp_free(t_zero); 639136e13aeSRichard Henderson dc->delayed_branch = 2; 640136e13aeSRichard Henderson } 641136e13aeSRichard Henderson 6423a7be554SRichard Henderson static bool trans_l_bf(DisasContext *dc, arg_l_bf *a) 643136e13aeSRichard Henderson { 644136e13aeSRichard Henderson do_bf(dc, a, TCG_COND_NE); 645136e13aeSRichard Henderson return true; 646136e13aeSRichard Henderson } 647136e13aeSRichard Henderson 6483a7be554SRichard Henderson static bool trans_l_bnf(DisasContext *dc, arg_l_bf *a) 649136e13aeSRichard Henderson { 650136e13aeSRichard Henderson do_bf(dc, a, TCG_COND_EQ); 651136e13aeSRichard Henderson return true; 652136e13aeSRichard Henderson } 653136e13aeSRichard Henderson 6543a7be554SRichard Henderson static bool trans_l_jr(DisasContext *dc, arg_l_jr *a) 655136e13aeSRichard Henderson { 6568bba7619SRichard Henderson tcg_gen_mov_tl(jmp_pc, cpu_R(dc, a->b)); 657136e13aeSRichard Henderson dc->delayed_branch = 2; 658136e13aeSRichard Henderson return true; 659136e13aeSRichard Henderson } 660136e13aeSRichard Henderson 6613a7be554SRichard Henderson static bool trans_l_jalr(DisasContext *dc, arg_l_jalr *a) 662136e13aeSRichard Henderson { 6638bba7619SRichard Henderson tcg_gen_mov_tl(jmp_pc, cpu_R(dc, a->b)); 6648bba7619SRichard Henderson tcg_gen_movi_tl(cpu_regs[9], dc->base.pc_next + 8); 665136e13aeSRichard Henderson dc->delayed_branch = 2; 666136e13aeSRichard Henderson return true; 667136e13aeSRichard Henderson } 668136e13aeSRichard Henderson 6693a7be554SRichard Henderson static bool trans_l_lwa(DisasContext *dc, arg_load *a) 670d80bff19SRichard Henderson { 671d80bff19SRichard Henderson TCGv ea; 672d80bff19SRichard Henderson 673cdd0f459SRichard Henderson check_r0_write(dc, a->d); 674d80bff19SRichard Henderson ea = tcg_temp_new(); 6758bba7619SRichard Henderson tcg_gen_addi_tl(ea, cpu_R(dc, a->a), a->i); 6768bba7619SRichard Henderson tcg_gen_qemu_ld_tl(cpu_R(dc, a->d), ea, dc->mem_idx, MO_TEUL); 677d80bff19SRichard Henderson tcg_gen_mov_tl(cpu_lock_addr, ea); 6788bba7619SRichard Henderson tcg_gen_mov_tl(cpu_lock_value, cpu_R(dc, a->d)); 679d80bff19SRichard Henderson tcg_temp_free(ea); 680d80bff19SRichard Henderson return true; 681d80bff19SRichard Henderson } 682d80bff19SRichard Henderson 68314776ab5STony Nguyen static void do_load(DisasContext *dc, arg_load *a, MemOp mop) 684d80bff19SRichard Henderson { 685d80bff19SRichard Henderson TCGv ea; 686d80bff19SRichard Henderson 687cdd0f459SRichard Henderson check_r0_write(dc, a->d); 688d80bff19SRichard Henderson ea = tcg_temp_new(); 6898bba7619SRichard Henderson tcg_gen_addi_tl(ea, cpu_R(dc, a->a), a->i); 6908bba7619SRichard Henderson tcg_gen_qemu_ld_tl(cpu_R(dc, a->d), ea, dc->mem_idx, mop); 691d80bff19SRichard Henderson tcg_temp_free(ea); 692d80bff19SRichard Henderson } 693d80bff19SRichard Henderson 6943a7be554SRichard Henderson static bool trans_l_lwz(DisasContext *dc, arg_load *a) 695d80bff19SRichard Henderson { 696d80bff19SRichard Henderson do_load(dc, a, MO_TEUL); 697d80bff19SRichard Henderson return true; 698d80bff19SRichard Henderson } 699d80bff19SRichard Henderson 7003a7be554SRichard Henderson static bool trans_l_lws(DisasContext *dc, arg_load *a) 701d80bff19SRichard Henderson { 702d80bff19SRichard Henderson do_load(dc, a, MO_TESL); 703d80bff19SRichard Henderson return true; 704d80bff19SRichard Henderson } 705d80bff19SRichard Henderson 7063a7be554SRichard Henderson static bool trans_l_lbz(DisasContext *dc, arg_load *a) 707d80bff19SRichard Henderson { 708d80bff19SRichard Henderson do_load(dc, a, MO_UB); 709d80bff19SRichard Henderson return true; 710d80bff19SRichard Henderson } 711d80bff19SRichard Henderson 7123a7be554SRichard Henderson static bool trans_l_lbs(DisasContext *dc, arg_load *a) 713d80bff19SRichard Henderson { 714d80bff19SRichard Henderson do_load(dc, a, MO_SB); 715d80bff19SRichard Henderson return true; 716d80bff19SRichard Henderson } 717d80bff19SRichard Henderson 7183a7be554SRichard Henderson static bool trans_l_lhz(DisasContext *dc, arg_load *a) 719d80bff19SRichard Henderson { 720d80bff19SRichard Henderson do_load(dc, a, MO_TEUW); 721d80bff19SRichard Henderson return true; 722d80bff19SRichard Henderson } 723d80bff19SRichard Henderson 7243a7be554SRichard Henderson static bool trans_l_lhs(DisasContext *dc, arg_load *a) 725d80bff19SRichard Henderson { 726d80bff19SRichard Henderson do_load(dc, a, MO_TESW); 727d80bff19SRichard Henderson return true; 728d80bff19SRichard Henderson } 729d80bff19SRichard Henderson 7303a7be554SRichard Henderson static bool trans_l_swa(DisasContext *dc, arg_store *a) 731d80bff19SRichard Henderson { 732d80bff19SRichard Henderson TCGv ea, val; 733d80bff19SRichard Henderson TCGLabel *lab_fail, *lab_done; 734d80bff19SRichard Henderson 735d80bff19SRichard Henderson ea = tcg_temp_new(); 7368bba7619SRichard Henderson tcg_gen_addi_tl(ea, cpu_R(dc, a->a), a->i); 737d80bff19SRichard Henderson 738d80bff19SRichard Henderson /* For TB_FLAGS_R0_0, the branch below invalidates the temporary assigned 7398bba7619SRichard Henderson to cpu_regs[0]. Since l.swa is quite often immediately followed by a 740d80bff19SRichard Henderson branch, don't bother reallocating; finish the TB using the "real" R0. 741d80bff19SRichard Henderson This also takes care of RB input across the branch. */ 742d29f4368SRichard Henderson dc->R0 = cpu_regs[0]; 743d80bff19SRichard Henderson 744d80bff19SRichard Henderson lab_fail = gen_new_label(); 745d80bff19SRichard Henderson lab_done = gen_new_label(); 746d80bff19SRichard Henderson tcg_gen_brcond_tl(TCG_COND_NE, ea, cpu_lock_addr, lab_fail); 747d80bff19SRichard Henderson tcg_temp_free(ea); 748d80bff19SRichard Henderson 749d80bff19SRichard Henderson val = tcg_temp_new(); 750d80bff19SRichard Henderson tcg_gen_atomic_cmpxchg_tl(val, cpu_lock_addr, cpu_lock_value, 7518bba7619SRichard Henderson cpu_regs[a->b], dc->mem_idx, MO_TEUL); 752d80bff19SRichard Henderson tcg_gen_setcond_tl(TCG_COND_EQ, cpu_sr_f, val, cpu_lock_value); 753d80bff19SRichard Henderson tcg_temp_free(val); 754d80bff19SRichard Henderson 755d80bff19SRichard Henderson tcg_gen_br(lab_done); 756d80bff19SRichard Henderson 757d80bff19SRichard Henderson gen_set_label(lab_fail); 758d80bff19SRichard Henderson tcg_gen_movi_tl(cpu_sr_f, 0); 759d80bff19SRichard Henderson 760d80bff19SRichard Henderson gen_set_label(lab_done); 761d80bff19SRichard Henderson tcg_gen_movi_tl(cpu_lock_addr, -1); 762d80bff19SRichard Henderson return true; 763d80bff19SRichard Henderson } 764d80bff19SRichard Henderson 76514776ab5STony Nguyen static void do_store(DisasContext *dc, arg_store *a, MemOp mop) 766d80bff19SRichard Henderson { 767d80bff19SRichard Henderson TCGv t0 = tcg_temp_new(); 7688bba7619SRichard Henderson tcg_gen_addi_tl(t0, cpu_R(dc, a->a), a->i); 7698bba7619SRichard Henderson tcg_gen_qemu_st_tl(cpu_R(dc, a->b), t0, dc->mem_idx, mop); 770d80bff19SRichard Henderson tcg_temp_free(t0); 771d80bff19SRichard Henderson } 772d80bff19SRichard Henderson 7733a7be554SRichard Henderson static bool trans_l_sw(DisasContext *dc, arg_store *a) 774d80bff19SRichard Henderson { 775d80bff19SRichard Henderson do_store(dc, a, MO_TEUL); 776d80bff19SRichard Henderson return true; 777d80bff19SRichard Henderson } 778d80bff19SRichard Henderson 7793a7be554SRichard Henderson static bool trans_l_sb(DisasContext *dc, arg_store *a) 780d80bff19SRichard Henderson { 781d80bff19SRichard Henderson do_store(dc, a, MO_UB); 782d80bff19SRichard Henderson return true; 783d80bff19SRichard Henderson } 784d80bff19SRichard Henderson 7853a7be554SRichard Henderson static bool trans_l_sh(DisasContext *dc, arg_store *a) 786d80bff19SRichard Henderson { 787d80bff19SRichard Henderson do_store(dc, a, MO_TEUW); 788d80bff19SRichard Henderson return true; 789d80bff19SRichard Henderson } 790d80bff19SRichard Henderson 7913a7be554SRichard Henderson static bool trans_l_nop(DisasContext *dc, arg_l_nop *a) 792bbe418f2SJia Liu { 7938816f70bSRichard Henderson return true; 7948816f70bSRichard Henderson } 7958816f70bSRichard Henderson 7963a7be554SRichard Henderson static bool trans_l_addi(DisasContext *dc, arg_rri *a) 7978816f70bSRichard Henderson { 7989ecaa27eSRichard Henderson TCGv t0; 7995631e69cSRichard Henderson 800cdd0f459SRichard Henderson check_r0_write(dc, a->d); 8018816f70bSRichard Henderson t0 = tcg_const_tl(a->i); 8028bba7619SRichard Henderson gen_add(dc, cpu_R(dc, a->d), cpu_R(dc, a->a), t0); 8036f7332baSRichard Henderson tcg_temp_free(t0); 8048816f70bSRichard Henderson return true; 8058816f70bSRichard Henderson } 806bbe418f2SJia Liu 8073a7be554SRichard Henderson static bool trans_l_addic(DisasContext *dc, arg_rri *a) 808bbe418f2SJia Liu { 8098816f70bSRichard Henderson TCGv t0; 8108816f70bSRichard Henderson 811cdd0f459SRichard Henderson check_r0_write(dc, a->d); 8128816f70bSRichard Henderson t0 = tcg_const_tl(a->i); 8138bba7619SRichard Henderson gen_addc(dc, cpu_R(dc, a->d), cpu_R(dc, a->a), t0); 8148816f70bSRichard Henderson tcg_temp_free(t0); 8158816f70bSRichard Henderson return true; 8168816f70bSRichard Henderson } 8178816f70bSRichard Henderson 8183a7be554SRichard Henderson static bool trans_l_muli(DisasContext *dc, arg_rri *a) 8198816f70bSRichard Henderson { 8208816f70bSRichard Henderson TCGv t0; 8218816f70bSRichard Henderson 822cdd0f459SRichard Henderson check_r0_write(dc, a->d); 8238816f70bSRichard Henderson t0 = tcg_const_tl(a->i); 8248bba7619SRichard Henderson gen_mul(dc, cpu_R(dc, a->d), cpu_R(dc, a->a), t0); 8258816f70bSRichard Henderson tcg_temp_free(t0); 8268816f70bSRichard Henderson return true; 8278816f70bSRichard Henderson } 8288816f70bSRichard Henderson 8293a7be554SRichard Henderson static bool trans_l_maci(DisasContext *dc, arg_l_maci *a) 8308816f70bSRichard Henderson { 8318816f70bSRichard Henderson TCGv t0; 8328816f70bSRichard Henderson 8338816f70bSRichard Henderson t0 = tcg_const_tl(a->i); 8348bba7619SRichard Henderson gen_mac(dc, cpu_R(dc, a->a), t0); 8358816f70bSRichard Henderson tcg_temp_free(t0); 8368816f70bSRichard Henderson return true; 8378816f70bSRichard Henderson } 8388816f70bSRichard Henderson 8393a7be554SRichard Henderson static bool trans_l_andi(DisasContext *dc, arg_rrk *a) 8408816f70bSRichard Henderson { 841cdd0f459SRichard Henderson check_r0_write(dc, a->d); 8428bba7619SRichard Henderson tcg_gen_andi_tl(cpu_R(dc, a->d), cpu_R(dc, a->a), a->k); 8438816f70bSRichard Henderson return true; 8448816f70bSRichard Henderson } 8458816f70bSRichard Henderson 8463a7be554SRichard Henderson static bool trans_l_ori(DisasContext *dc, arg_rrk *a) 8478816f70bSRichard Henderson { 848cdd0f459SRichard Henderson check_r0_write(dc, a->d); 8498bba7619SRichard Henderson tcg_gen_ori_tl(cpu_R(dc, a->d), cpu_R(dc, a->a), a->k); 8508816f70bSRichard Henderson return true; 8518816f70bSRichard Henderson } 8528816f70bSRichard Henderson 8533a7be554SRichard Henderson static bool trans_l_xori(DisasContext *dc, arg_rri *a) 8548816f70bSRichard Henderson { 855cdd0f459SRichard Henderson check_r0_write(dc, a->d); 8568bba7619SRichard Henderson tcg_gen_xori_tl(cpu_R(dc, a->d), cpu_R(dc, a->a), a->i); 8578816f70bSRichard Henderson return true; 8588816f70bSRichard Henderson } 8598816f70bSRichard Henderson 8603a7be554SRichard Henderson static bool trans_l_mfspr(DisasContext *dc, arg_l_mfspr *a) 8618816f70bSRichard Henderson { 862cdd0f459SRichard Henderson check_r0_write(dc, a->d); 8638816f70bSRichard Henderson 8642ba65417SRichard Henderson if (is_user(dc)) { 865bbe418f2SJia Liu gen_illegal_exception(dc); 8668816f70bSRichard Henderson } else { 867c28fa81fSRichard Henderson TCGv spr = tcg_temp_new(); 8688bba7619SRichard Henderson tcg_gen_ori_tl(spr, cpu_R(dc, a->a), a->k); 8698bba7619SRichard Henderson gen_helper_mfspr(cpu_R(dc, a->d), cpu_env, cpu_R(dc, a->d), spr); 870c28fa81fSRichard Henderson tcg_temp_free(spr); 8714dd044c6SJia Liu } 8728816f70bSRichard Henderson return true; 8738816f70bSRichard Henderson } 874bbe418f2SJia Liu 8753a7be554SRichard Henderson static bool trans_l_mtspr(DisasContext *dc, arg_l_mtspr *a) 8764dd044c6SJia Liu { 8772ba65417SRichard Henderson if (is_user(dc)) { 8784dd044c6SJia Liu gen_illegal_exception(dc); 8798816f70bSRichard Henderson } else { 880c28fa81fSRichard Henderson TCGv spr; 88101ec3ec9SRichard Henderson 88201ec3ec9SRichard Henderson /* For SR, we will need to exit the TB to recognize the new 88301ec3ec9SRichard Henderson * exception state. For NPC, in theory this counts as a branch 88401ec3ec9SRichard Henderson * (although the SPR only exists for use by an ICE). Save all 88501ec3ec9SRichard Henderson * of the cpu state first, allowing it to be overwritten. 88601ec3ec9SRichard Henderson */ 88701ec3ec9SRichard Henderson if (dc->delayed_branch) { 88801ec3ec9SRichard Henderson tcg_gen_mov_tl(cpu_pc, jmp_pc); 88901ec3ec9SRichard Henderson tcg_gen_discard_tl(jmp_pc); 89001ec3ec9SRichard Henderson } else { 89101ec3ec9SRichard Henderson tcg_gen_movi_tl(cpu_pc, dc->base.pc_next + 4); 89201ec3ec9SRichard Henderson } 89301ec3ec9SRichard Henderson dc->base.is_jmp = DISAS_EXIT; 89401ec3ec9SRichard Henderson 895c28fa81fSRichard Henderson spr = tcg_temp_new(); 8968bba7619SRichard Henderson tcg_gen_ori_tl(spr, cpu_R(dc, a->a), a->k); 8978bba7619SRichard Henderson gen_helper_mtspr(cpu_env, spr, cpu_R(dc, a->b)); 898c28fa81fSRichard Henderson tcg_temp_free(spr); 8994dd044c6SJia Liu } 9008816f70bSRichard Henderson return true; 901bbe418f2SJia Liu } 902bbe418f2SJia Liu 9033a7be554SRichard Henderson static bool trans_l_mac(DisasContext *dc, arg_ab *a) 904bbe418f2SJia Liu { 9058bba7619SRichard Henderson gen_mac(dc, cpu_R(dc, a->a), cpu_R(dc, a->b)); 90699d863d6SRichard Henderson return true; 907bbe418f2SJia Liu } 90899d863d6SRichard Henderson 9093a7be554SRichard Henderson static bool trans_l_msb(DisasContext *dc, arg_ab *a) 91099d863d6SRichard Henderson { 9118bba7619SRichard Henderson gen_msb(dc, cpu_R(dc, a->a), cpu_R(dc, a->b)); 91299d863d6SRichard Henderson return true; 91399d863d6SRichard Henderson } 91499d863d6SRichard Henderson 9153a7be554SRichard Henderson static bool trans_l_macu(DisasContext *dc, arg_ab *a) 91699d863d6SRichard Henderson { 9178bba7619SRichard Henderson gen_macu(dc, cpu_R(dc, a->a), cpu_R(dc, a->b)); 91899d863d6SRichard Henderson return true; 91999d863d6SRichard Henderson } 92099d863d6SRichard Henderson 9213a7be554SRichard Henderson static bool trans_l_msbu(DisasContext *dc, arg_ab *a) 92299d863d6SRichard Henderson { 9238bba7619SRichard Henderson gen_msbu(dc, cpu_R(dc, a->a), cpu_R(dc, a->b)); 92499d863d6SRichard Henderson return true; 925bbe418f2SJia Liu } 926bbe418f2SJia Liu 9273a7be554SRichard Henderson static bool trans_l_slli(DisasContext *dc, arg_dal *a) 928bbe418f2SJia Liu { 929cdd0f459SRichard Henderson check_r0_write(dc, a->d); 9308bba7619SRichard Henderson tcg_gen_shli_tl(cpu_R(dc, a->d), cpu_R(dc, a->a), 9318bba7619SRichard Henderson a->l & (TARGET_LONG_BITS - 1)); 932e20c2592SRichard Henderson return true; 933bbe418f2SJia Liu } 934e20c2592SRichard Henderson 9353a7be554SRichard Henderson static bool trans_l_srli(DisasContext *dc, arg_dal *a) 936e20c2592SRichard Henderson { 937cdd0f459SRichard Henderson check_r0_write(dc, a->d); 9388bba7619SRichard Henderson tcg_gen_shri_tl(cpu_R(dc, a->d), cpu_R(dc, a->a), 9398bba7619SRichard Henderson a->l & (TARGET_LONG_BITS - 1)); 940e20c2592SRichard Henderson return true; 941e20c2592SRichard Henderson } 942e20c2592SRichard Henderson 9433a7be554SRichard Henderson static bool trans_l_srai(DisasContext *dc, arg_dal *a) 944e20c2592SRichard Henderson { 945cdd0f459SRichard Henderson check_r0_write(dc, a->d); 9468bba7619SRichard Henderson tcg_gen_sari_tl(cpu_R(dc, a->d), cpu_R(dc, a->a), 9478bba7619SRichard Henderson a->l & (TARGET_LONG_BITS - 1)); 948e20c2592SRichard Henderson return true; 949e20c2592SRichard Henderson } 950e20c2592SRichard Henderson 9513a7be554SRichard Henderson static bool trans_l_rori(DisasContext *dc, arg_dal *a) 952e20c2592SRichard Henderson { 953cdd0f459SRichard Henderson check_r0_write(dc, a->d); 9548bba7619SRichard Henderson tcg_gen_rotri_tl(cpu_R(dc, a->d), cpu_R(dc, a->a), 9558bba7619SRichard Henderson a->l & (TARGET_LONG_BITS - 1)); 956e20c2592SRichard Henderson return true; 957bbe418f2SJia Liu } 958bbe418f2SJia Liu 9593a7be554SRichard Henderson static bool trans_l_movhi(DisasContext *dc, arg_l_movhi *a) 960bbe418f2SJia Liu { 961cdd0f459SRichard Henderson check_r0_write(dc, a->d); 9628bba7619SRichard Henderson tcg_gen_movi_tl(cpu_R(dc, a->d), a->k << 16); 963e720a571SRichard Henderson return true; 964bbe418f2SJia Liu } 965e720a571SRichard Henderson 9663a7be554SRichard Henderson static bool trans_l_macrc(DisasContext *dc, arg_l_macrc *a) 967e720a571SRichard Henderson { 968cdd0f459SRichard Henderson check_r0_write(dc, a->d); 9698bba7619SRichard Henderson tcg_gen_trunc_i64_tl(cpu_R(dc, a->d), cpu_mac); 970e720a571SRichard Henderson tcg_gen_movi_i64(cpu_mac, 0); 971e720a571SRichard Henderson return true; 972bbe418f2SJia Liu } 973bbe418f2SJia Liu 9743a7be554SRichard Henderson static bool trans_l_sfeq(DisasContext *dc, arg_ab *a) 975bbe418f2SJia Liu { 9768bba7619SRichard Henderson tcg_gen_setcond_tl(TCG_COND_EQ, cpu_sr_f, 9778bba7619SRichard Henderson cpu_R(dc, a->a), cpu_R(dc, a->b)); 978fbb3e29aSRichard Henderson return true; 979bbe418f2SJia Liu } 980fbb3e29aSRichard Henderson 9813a7be554SRichard Henderson static bool trans_l_sfne(DisasContext *dc, arg_ab *a) 982fbb3e29aSRichard Henderson { 9838bba7619SRichard Henderson tcg_gen_setcond_tl(TCG_COND_NE, cpu_sr_f, 9848bba7619SRichard Henderson cpu_R(dc, a->a), cpu_R(dc, a->b)); 985fbb3e29aSRichard Henderson return true; 986fbb3e29aSRichard Henderson } 987fbb3e29aSRichard Henderson 9883a7be554SRichard Henderson static bool trans_l_sfgtu(DisasContext *dc, arg_ab *a) 989fbb3e29aSRichard Henderson { 9908bba7619SRichard Henderson tcg_gen_setcond_tl(TCG_COND_GTU, cpu_sr_f, 9918bba7619SRichard Henderson cpu_R(dc, a->a), cpu_R(dc, a->b)); 992fbb3e29aSRichard Henderson return true; 993fbb3e29aSRichard Henderson } 994fbb3e29aSRichard Henderson 9953a7be554SRichard Henderson static bool trans_l_sfgeu(DisasContext *dc, arg_ab *a) 996fbb3e29aSRichard Henderson { 9978bba7619SRichard Henderson tcg_gen_setcond_tl(TCG_COND_GEU, cpu_sr_f, 9988bba7619SRichard Henderson cpu_R(dc, a->a), cpu_R(dc, a->b)); 999fbb3e29aSRichard Henderson return true; 1000fbb3e29aSRichard Henderson } 1001fbb3e29aSRichard Henderson 10023a7be554SRichard Henderson static bool trans_l_sfltu(DisasContext *dc, arg_ab *a) 1003fbb3e29aSRichard Henderson { 10048bba7619SRichard Henderson tcg_gen_setcond_tl(TCG_COND_LTU, cpu_sr_f, 10058bba7619SRichard Henderson cpu_R(dc, a->a), cpu_R(dc, a->b)); 1006fbb3e29aSRichard Henderson return true; 1007fbb3e29aSRichard Henderson } 1008fbb3e29aSRichard Henderson 10093a7be554SRichard Henderson static bool trans_l_sfleu(DisasContext *dc, arg_ab *a) 1010fbb3e29aSRichard Henderson { 10118bba7619SRichard Henderson tcg_gen_setcond_tl(TCG_COND_LEU, cpu_sr_f, 10128bba7619SRichard Henderson cpu_R(dc, a->a), cpu_R(dc, a->b)); 1013fbb3e29aSRichard Henderson return true; 1014fbb3e29aSRichard Henderson } 1015fbb3e29aSRichard Henderson 10163a7be554SRichard Henderson static bool trans_l_sfgts(DisasContext *dc, arg_ab *a) 1017fbb3e29aSRichard Henderson { 10188bba7619SRichard Henderson tcg_gen_setcond_tl(TCG_COND_GT, cpu_sr_f, 10198bba7619SRichard Henderson cpu_R(dc, a->a), cpu_R(dc, a->b)); 1020fbb3e29aSRichard Henderson return true; 1021fbb3e29aSRichard Henderson } 1022fbb3e29aSRichard Henderson 10233a7be554SRichard Henderson static bool trans_l_sfges(DisasContext *dc, arg_ab *a) 1024fbb3e29aSRichard Henderson { 10258bba7619SRichard Henderson tcg_gen_setcond_tl(TCG_COND_GE, cpu_sr_f, 10268bba7619SRichard Henderson cpu_R(dc, a->a), cpu_R(dc, a->b)); 1027fbb3e29aSRichard Henderson return true; 1028fbb3e29aSRichard Henderson } 1029fbb3e29aSRichard Henderson 10303a7be554SRichard Henderson static bool trans_l_sflts(DisasContext *dc, arg_ab *a) 1031fbb3e29aSRichard Henderson { 10328bba7619SRichard Henderson tcg_gen_setcond_tl(TCG_COND_LT, cpu_sr_f, 10338bba7619SRichard Henderson cpu_R(dc, a->a), cpu_R(dc, a->b)); 1034fbb3e29aSRichard Henderson return true; 1035fbb3e29aSRichard Henderson } 1036fbb3e29aSRichard Henderson 10373a7be554SRichard Henderson static bool trans_l_sfles(DisasContext *dc, arg_ab *a) 1038fbb3e29aSRichard Henderson { 10398bba7619SRichard Henderson tcg_gen_setcond_tl(TCG_COND_LE, 10408bba7619SRichard Henderson cpu_sr_f, cpu_R(dc, a->a), cpu_R(dc, a->b)); 1041fbb3e29aSRichard Henderson return true; 1042bbe418f2SJia Liu } 1043bbe418f2SJia Liu 10443a7be554SRichard Henderson static bool trans_l_sfeqi(DisasContext *dc, arg_ai *a) 1045bbe418f2SJia Liu { 10468bba7619SRichard Henderson tcg_gen_setcondi_tl(TCG_COND_EQ, cpu_sr_f, cpu_R(dc, a->a), a->i); 1047032de4fcSRichard Henderson return true; 1048bbe418f2SJia Liu } 1049032de4fcSRichard Henderson 10503a7be554SRichard Henderson static bool trans_l_sfnei(DisasContext *dc, arg_ai *a) 1051032de4fcSRichard Henderson { 10528bba7619SRichard Henderson tcg_gen_setcondi_tl(TCG_COND_NE, cpu_sr_f, cpu_R(dc, a->a), a->i); 1053032de4fcSRichard Henderson return true; 1054032de4fcSRichard Henderson } 1055032de4fcSRichard Henderson 10563a7be554SRichard Henderson static bool trans_l_sfgtui(DisasContext *dc, arg_ai *a) 1057032de4fcSRichard Henderson { 10588bba7619SRichard Henderson tcg_gen_setcondi_tl(TCG_COND_GTU, cpu_sr_f, cpu_R(dc, a->a), a->i); 1059032de4fcSRichard Henderson return true; 1060032de4fcSRichard Henderson } 1061032de4fcSRichard Henderson 10623a7be554SRichard Henderson static bool trans_l_sfgeui(DisasContext *dc, arg_ai *a) 1063032de4fcSRichard Henderson { 10648bba7619SRichard Henderson tcg_gen_setcondi_tl(TCG_COND_GEU, cpu_sr_f, cpu_R(dc, a->a), a->i); 1065032de4fcSRichard Henderson return true; 1066032de4fcSRichard Henderson } 1067032de4fcSRichard Henderson 10683a7be554SRichard Henderson static bool trans_l_sfltui(DisasContext *dc, arg_ai *a) 1069032de4fcSRichard Henderson { 10708bba7619SRichard Henderson tcg_gen_setcondi_tl(TCG_COND_LTU, cpu_sr_f, cpu_R(dc, a->a), a->i); 1071032de4fcSRichard Henderson return true; 1072032de4fcSRichard Henderson } 1073032de4fcSRichard Henderson 10743a7be554SRichard Henderson static bool trans_l_sfleui(DisasContext *dc, arg_ai *a) 1075032de4fcSRichard Henderson { 10768bba7619SRichard Henderson tcg_gen_setcondi_tl(TCG_COND_LEU, cpu_sr_f, cpu_R(dc, a->a), a->i); 1077032de4fcSRichard Henderson return true; 1078032de4fcSRichard Henderson } 1079032de4fcSRichard Henderson 10803a7be554SRichard Henderson static bool trans_l_sfgtsi(DisasContext *dc, arg_ai *a) 1081032de4fcSRichard Henderson { 10828bba7619SRichard Henderson tcg_gen_setcondi_tl(TCG_COND_GT, cpu_sr_f, cpu_R(dc, a->a), a->i); 1083032de4fcSRichard Henderson return true; 1084032de4fcSRichard Henderson } 1085032de4fcSRichard Henderson 10863a7be554SRichard Henderson static bool trans_l_sfgesi(DisasContext *dc, arg_ai *a) 1087032de4fcSRichard Henderson { 10888bba7619SRichard Henderson tcg_gen_setcondi_tl(TCG_COND_GE, cpu_sr_f, cpu_R(dc, a->a), a->i); 1089032de4fcSRichard Henderson return true; 1090032de4fcSRichard Henderson } 1091032de4fcSRichard Henderson 10923a7be554SRichard Henderson static bool trans_l_sfltsi(DisasContext *dc, arg_ai *a) 1093032de4fcSRichard Henderson { 10948bba7619SRichard Henderson tcg_gen_setcondi_tl(TCG_COND_LT, cpu_sr_f, cpu_R(dc, a->a), a->i); 1095032de4fcSRichard Henderson return true; 1096032de4fcSRichard Henderson } 1097032de4fcSRichard Henderson 10983a7be554SRichard Henderson static bool trans_l_sflesi(DisasContext *dc, arg_ai *a) 1099032de4fcSRichard Henderson { 11008bba7619SRichard Henderson tcg_gen_setcondi_tl(TCG_COND_LE, cpu_sr_f, cpu_R(dc, a->a), a->i); 1101032de4fcSRichard Henderson return true; 1102bbe418f2SJia Liu } 1103bbe418f2SJia Liu 11043a7be554SRichard Henderson static bool trans_l_sys(DisasContext *dc, arg_l_sys *a) 1105bbe418f2SJia Liu { 11061ffa4bceSEmilio G. Cota tcg_gen_movi_tl(cpu_pc, dc->base.pc_next); 1107bbe418f2SJia Liu gen_exception(dc, EXCP_SYSCALL); 11081ffa4bceSEmilio G. Cota dc->base.is_jmp = DISAS_NORETURN; 11097de9729fSRichard Henderson return true; 11107de9729fSRichard Henderson } 1111bbe418f2SJia Liu 11123a7be554SRichard Henderson static bool trans_l_trap(DisasContext *dc, arg_l_trap *a) 11137de9729fSRichard Henderson { 11141ffa4bceSEmilio G. Cota tcg_gen_movi_tl(cpu_pc, dc->base.pc_next); 1115bbe418f2SJia Liu gen_exception(dc, EXCP_TRAP); 11161ffa4bceSEmilio G. Cota dc->base.is_jmp = DISAS_NORETURN; 11177de9729fSRichard Henderson return true; 11187de9729fSRichard Henderson } 1119bbe418f2SJia Liu 11203a7be554SRichard Henderson static bool trans_l_msync(DisasContext *dc, arg_l_msync *a) 11217de9729fSRichard Henderson { 112224fc5c0fSRichard Henderson tcg_gen_mb(TCG_MO_ALL); 11237de9729fSRichard Henderson return true; 1124bbe418f2SJia Liu } 11257de9729fSRichard Henderson 11263a7be554SRichard Henderson static bool trans_l_psync(DisasContext *dc, arg_l_psync *a) 11277de9729fSRichard Henderson { 11287de9729fSRichard Henderson return true; 11297de9729fSRichard Henderson } 11307de9729fSRichard Henderson 11313a7be554SRichard Henderson static bool trans_l_csync(DisasContext *dc, arg_l_csync *a) 11327de9729fSRichard Henderson { 11337de9729fSRichard Henderson return true; 1134bbe418f2SJia Liu } 1135bbe418f2SJia Liu 11363a7be554SRichard Henderson static bool trans_l_rfe(DisasContext *dc, arg_l_rfe *a) 11378816f70bSRichard Henderson { 11382ba65417SRichard Henderson if (is_user(dc)) { 11398816f70bSRichard Henderson gen_illegal_exception(dc); 11408816f70bSRichard Henderson } else { 11418816f70bSRichard Henderson gen_helper_rfe(cpu_env); 114264e46c95SRichard Henderson dc->base.is_jmp = DISAS_EXIT; 11438816f70bSRichard Henderson } 11448816f70bSRichard Henderson return true; 11458816f70bSRichard Henderson } 11468816f70bSRichard Henderson 1147fe636d37SRichard Henderson static bool do_fp2(DisasContext *dc, arg_da *a, 11486fd204a2SRichard Henderson void (*fn)(TCGv, TCGv_env, TCGv)) 1149bbe418f2SJia Liu { 1150fe636d37SRichard Henderson if (!check_of32s(dc)) { 1151fe636d37SRichard Henderson return false; 1152fe636d37SRichard Henderson } 1153cdd0f459SRichard Henderson check_r0_write(dc, a->d); 11548bba7619SRichard Henderson fn(cpu_R(dc, a->d), cpu_env, cpu_R(dc, a->a)); 11554e2d3007SRichard Henderson gen_helper_update_fpcsr(cpu_env); 1156fe636d37SRichard Henderson return true; 1157bbe418f2SJia Liu } 11586fd204a2SRichard Henderson 1159fe636d37SRichard Henderson static bool do_fp3(DisasContext *dc, arg_dab *a, 11606fd204a2SRichard Henderson void (*fn)(TCGv, TCGv_env, TCGv, TCGv)) 11616fd204a2SRichard Henderson { 1162fe636d37SRichard Henderson if (!check_of32s(dc)) { 1163fe636d37SRichard Henderson return false; 1164fe636d37SRichard Henderson } 1165cdd0f459SRichard Henderson check_r0_write(dc, a->d); 11668bba7619SRichard Henderson fn(cpu_R(dc, a->d), cpu_env, cpu_R(dc, a->a), cpu_R(dc, a->b)); 11676fd204a2SRichard Henderson gen_helper_update_fpcsr(cpu_env); 1168fe636d37SRichard Henderson return true; 11696fd204a2SRichard Henderson } 11706fd204a2SRichard Henderson 1171fe636d37SRichard Henderson static bool do_fpcmp(DisasContext *dc, arg_ab *a, 11726fd204a2SRichard Henderson void (*fn)(TCGv, TCGv_env, TCGv, TCGv), 11736fd204a2SRichard Henderson bool inv, bool swap) 11746fd204a2SRichard Henderson { 1175fe636d37SRichard Henderson if (!check_of32s(dc)) { 1176fe636d37SRichard Henderson return false; 1177fe636d37SRichard Henderson } 11786fd204a2SRichard Henderson if (swap) { 11798bba7619SRichard Henderson fn(cpu_sr_f, cpu_env, cpu_R(dc, a->b), cpu_R(dc, a->a)); 11806fd204a2SRichard Henderson } else { 11818bba7619SRichard Henderson fn(cpu_sr_f, cpu_env, cpu_R(dc, a->a), cpu_R(dc, a->b)); 11826fd204a2SRichard Henderson } 11836fd204a2SRichard Henderson if (inv) { 11846fd204a2SRichard Henderson tcg_gen_xori_tl(cpu_sr_f, cpu_sr_f, 1); 11856fd204a2SRichard Henderson } 11866fd204a2SRichard Henderson gen_helper_update_fpcsr(cpu_env); 1187fe636d37SRichard Henderson return true; 11886fd204a2SRichard Henderson } 11896fd204a2SRichard Henderson 11903a7be554SRichard Henderson static bool trans_lf_add_s(DisasContext *dc, arg_dab *a) 11916fd204a2SRichard Henderson { 1192fe636d37SRichard Henderson return do_fp3(dc, a, gen_helper_float_add_s); 11936fd204a2SRichard Henderson } 11946fd204a2SRichard Henderson 11953a7be554SRichard Henderson static bool trans_lf_sub_s(DisasContext *dc, arg_dab *a) 11966fd204a2SRichard Henderson { 1197fe636d37SRichard Henderson return do_fp3(dc, a, gen_helper_float_sub_s); 11986fd204a2SRichard Henderson } 11996fd204a2SRichard Henderson 12003a7be554SRichard Henderson static bool trans_lf_mul_s(DisasContext *dc, arg_dab *a) 12016fd204a2SRichard Henderson { 1202fe636d37SRichard Henderson return do_fp3(dc, a, gen_helper_float_mul_s); 12036fd204a2SRichard Henderson } 12046fd204a2SRichard Henderson 12053a7be554SRichard Henderson static bool trans_lf_div_s(DisasContext *dc, arg_dab *a) 12066fd204a2SRichard Henderson { 1207fe636d37SRichard Henderson return do_fp3(dc, a, gen_helper_float_div_s); 12086fd204a2SRichard Henderson } 12096fd204a2SRichard Henderson 12103a7be554SRichard Henderson static bool trans_lf_rem_s(DisasContext *dc, arg_dab *a) 12116fd204a2SRichard Henderson { 1212fe636d37SRichard Henderson return do_fp3(dc, a, gen_helper_float_rem_s); 12136fd204a2SRichard Henderson return true; 12146fd204a2SRichard Henderson } 12156fd204a2SRichard Henderson 12163a7be554SRichard Henderson static bool trans_lf_itof_s(DisasContext *dc, arg_da *a) 12176fd204a2SRichard Henderson { 1218fe636d37SRichard Henderson return do_fp2(dc, a, gen_helper_itofs); 12196fd204a2SRichard Henderson } 12206fd204a2SRichard Henderson 12213a7be554SRichard Henderson static bool trans_lf_ftoi_s(DisasContext *dc, arg_da *a) 12226fd204a2SRichard Henderson { 1223fe636d37SRichard Henderson return do_fp2(dc, a, gen_helper_ftois); 12246fd204a2SRichard Henderson } 12256fd204a2SRichard Henderson 12263a7be554SRichard Henderson static bool trans_lf_madd_s(DisasContext *dc, arg_dab *a) 12276fd204a2SRichard Henderson { 1228fe636d37SRichard Henderson if (!check_of32s(dc)) { 1229fe636d37SRichard Henderson return false; 1230fe636d37SRichard Henderson } 1231cdd0f459SRichard Henderson check_r0_write(dc, a->d); 12328bba7619SRichard Henderson gen_helper_float_madd_s(cpu_R(dc, a->d), cpu_env, cpu_R(dc, a->d), 12338bba7619SRichard Henderson cpu_R(dc, a->a), cpu_R(dc, a->b)); 12346fd204a2SRichard Henderson gen_helper_update_fpcsr(cpu_env); 12356fd204a2SRichard Henderson return true; 12366fd204a2SRichard Henderson } 12376fd204a2SRichard Henderson 12383a7be554SRichard Henderson static bool trans_lf_sfeq_s(DisasContext *dc, arg_ab *a) 12396fd204a2SRichard Henderson { 1240fe636d37SRichard Henderson return do_fpcmp(dc, a, gen_helper_float_eq_s, false, false); 12416fd204a2SRichard Henderson } 12426fd204a2SRichard Henderson 12433a7be554SRichard Henderson static bool trans_lf_sfne_s(DisasContext *dc, arg_ab *a) 12446fd204a2SRichard Henderson { 1245fe636d37SRichard Henderson return do_fpcmp(dc, a, gen_helper_float_eq_s, true, false); 12466fd204a2SRichard Henderson } 12476fd204a2SRichard Henderson 12483a7be554SRichard Henderson static bool trans_lf_sfgt_s(DisasContext *dc, arg_ab *a) 12496fd204a2SRichard Henderson { 1250fe636d37SRichard Henderson return do_fpcmp(dc, a, gen_helper_float_lt_s, false, true); 12516fd204a2SRichard Henderson } 12526fd204a2SRichard Henderson 12533a7be554SRichard Henderson static bool trans_lf_sfge_s(DisasContext *dc, arg_ab *a) 12546fd204a2SRichard Henderson { 1255fe636d37SRichard Henderson return do_fpcmp(dc, a, gen_helper_float_le_s, false, true); 12566fd204a2SRichard Henderson } 12576fd204a2SRichard Henderson 12583a7be554SRichard Henderson static bool trans_lf_sflt_s(DisasContext *dc, arg_ab *a) 12596fd204a2SRichard Henderson { 1260fe636d37SRichard Henderson return do_fpcmp(dc, a, gen_helper_float_lt_s, false, false); 12616fd204a2SRichard Henderson } 12626fd204a2SRichard Henderson 12633a7be554SRichard Henderson static bool trans_lf_sfle_s(DisasContext *dc, arg_ab *a) 12646fd204a2SRichard Henderson { 1265fe636d37SRichard Henderson return do_fpcmp(dc, a, gen_helper_float_le_s, false, false); 1266bbe418f2SJia Liu } 1267bbe418f2SJia Liu 1268*62f2b038SRichard Henderson static bool check_pair(DisasContext *dc, int r, int p) 1269*62f2b038SRichard Henderson { 1270*62f2b038SRichard Henderson return r + 1 + p < 32; 1271*62f2b038SRichard Henderson } 1272*62f2b038SRichard Henderson 1273*62f2b038SRichard Henderson static void load_pair(DisasContext *dc, TCGv_i64 t, int r, int p) 1274*62f2b038SRichard Henderson { 1275*62f2b038SRichard Henderson tcg_gen_concat_i32_i64(t, cpu_R(dc, r + 1 + p), cpu_R(dc, r)); 1276*62f2b038SRichard Henderson } 1277*62f2b038SRichard Henderson 1278*62f2b038SRichard Henderson static void save_pair(DisasContext *dc, TCGv_i64 t, int r, int p) 1279*62f2b038SRichard Henderson { 1280*62f2b038SRichard Henderson tcg_gen_extr_i64_i32(cpu_R(dc, r + 1 + p), cpu_R(dc, r), t); 1281*62f2b038SRichard Henderson } 1282*62f2b038SRichard Henderson 1283*62f2b038SRichard Henderson static bool do_dp3(DisasContext *dc, arg_dab_pair *a, 1284*62f2b038SRichard Henderson void (*fn)(TCGv_i64, TCGv_env, TCGv_i64, TCGv_i64)) 1285*62f2b038SRichard Henderson { 1286*62f2b038SRichard Henderson TCGv_i64 t0, t1; 1287*62f2b038SRichard Henderson 1288*62f2b038SRichard Henderson if (!check_of64a32s(dc) || 1289*62f2b038SRichard Henderson !check_pair(dc, a->a, a->ap) || 1290*62f2b038SRichard Henderson !check_pair(dc, a->b, a->bp) || 1291*62f2b038SRichard Henderson !check_pair(dc, a->d, a->dp)) { 1292*62f2b038SRichard Henderson return false; 1293*62f2b038SRichard Henderson } 1294*62f2b038SRichard Henderson check_r0_write(dc, a->d); 1295*62f2b038SRichard Henderson 1296*62f2b038SRichard Henderson t0 = tcg_temp_new_i64(); 1297*62f2b038SRichard Henderson t1 = tcg_temp_new_i64(); 1298*62f2b038SRichard Henderson load_pair(dc, t0, a->a, a->ap); 1299*62f2b038SRichard Henderson load_pair(dc, t1, a->b, a->bp); 1300*62f2b038SRichard Henderson fn(t0, cpu_env, t0, t1); 1301*62f2b038SRichard Henderson save_pair(dc, t0, a->d, a->dp); 1302*62f2b038SRichard Henderson tcg_temp_free_i64(t0); 1303*62f2b038SRichard Henderson tcg_temp_free_i64(t1); 1304*62f2b038SRichard Henderson 1305*62f2b038SRichard Henderson gen_helper_update_fpcsr(cpu_env); 1306*62f2b038SRichard Henderson return true; 1307*62f2b038SRichard Henderson } 1308*62f2b038SRichard Henderson 1309*62f2b038SRichard Henderson static bool do_dp2(DisasContext *dc, arg_da_pair *a, 1310*62f2b038SRichard Henderson void (*fn)(TCGv_i64, TCGv_env, TCGv_i64)) 1311*62f2b038SRichard Henderson { 1312*62f2b038SRichard Henderson TCGv_i64 t0; 1313*62f2b038SRichard Henderson 1314*62f2b038SRichard Henderson if (!check_of64a32s(dc) || 1315*62f2b038SRichard Henderson !check_pair(dc, a->a, a->ap) || 1316*62f2b038SRichard Henderson !check_pair(dc, a->d, a->dp)) { 1317*62f2b038SRichard Henderson return false; 1318*62f2b038SRichard Henderson } 1319*62f2b038SRichard Henderson check_r0_write(dc, a->d); 1320*62f2b038SRichard Henderson 1321*62f2b038SRichard Henderson t0 = tcg_temp_new_i64(); 1322*62f2b038SRichard Henderson load_pair(dc, t0, a->a, a->ap); 1323*62f2b038SRichard Henderson fn(t0, cpu_env, t0); 1324*62f2b038SRichard Henderson save_pair(dc, t0, a->d, a->dp); 1325*62f2b038SRichard Henderson tcg_temp_free_i64(t0); 1326*62f2b038SRichard Henderson 1327*62f2b038SRichard Henderson gen_helper_update_fpcsr(cpu_env); 1328*62f2b038SRichard Henderson return true; 1329*62f2b038SRichard Henderson } 1330*62f2b038SRichard Henderson 1331*62f2b038SRichard Henderson static bool do_dpcmp(DisasContext *dc, arg_ab_pair *a, 1332*62f2b038SRichard Henderson void (*fn)(TCGv, TCGv_env, TCGv_i64, TCGv_i64), 1333*62f2b038SRichard Henderson bool inv, bool swap) 1334*62f2b038SRichard Henderson { 1335*62f2b038SRichard Henderson TCGv_i64 t0, t1; 1336*62f2b038SRichard Henderson 1337*62f2b038SRichard Henderson if (!check_of64a32s(dc) || 1338*62f2b038SRichard Henderson !check_pair(dc, a->a, a->ap) || 1339*62f2b038SRichard Henderson !check_pair(dc, a->b, a->bp)) { 1340*62f2b038SRichard Henderson return false; 1341*62f2b038SRichard Henderson } 1342*62f2b038SRichard Henderson 1343*62f2b038SRichard Henderson t0 = tcg_temp_new_i64(); 1344*62f2b038SRichard Henderson t1 = tcg_temp_new_i64(); 1345*62f2b038SRichard Henderson load_pair(dc, t0, a->a, a->ap); 1346*62f2b038SRichard Henderson load_pair(dc, t1, a->b, a->bp); 1347*62f2b038SRichard Henderson if (swap) { 1348*62f2b038SRichard Henderson fn(cpu_sr_f, cpu_env, t1, t0); 1349*62f2b038SRichard Henderson } else { 1350*62f2b038SRichard Henderson fn(cpu_sr_f, cpu_env, t0, t1); 1351*62f2b038SRichard Henderson } 1352*62f2b038SRichard Henderson tcg_temp_free_i64(t0); 1353*62f2b038SRichard Henderson tcg_temp_free_i64(t1); 1354*62f2b038SRichard Henderson 1355*62f2b038SRichard Henderson if (inv) { 1356*62f2b038SRichard Henderson tcg_gen_xori_tl(cpu_sr_f, cpu_sr_f, 1); 1357*62f2b038SRichard Henderson } 1358*62f2b038SRichard Henderson gen_helper_update_fpcsr(cpu_env); 1359*62f2b038SRichard Henderson return true; 1360*62f2b038SRichard Henderson } 1361*62f2b038SRichard Henderson 1362*62f2b038SRichard Henderson static bool trans_lf_add_d(DisasContext *dc, arg_dab_pair *a) 1363*62f2b038SRichard Henderson { 1364*62f2b038SRichard Henderson return do_dp3(dc, a, gen_helper_float_add_d); 1365*62f2b038SRichard Henderson } 1366*62f2b038SRichard Henderson 1367*62f2b038SRichard Henderson static bool trans_lf_sub_d(DisasContext *dc, arg_dab_pair *a) 1368*62f2b038SRichard Henderson { 1369*62f2b038SRichard Henderson return do_dp3(dc, a, gen_helper_float_sub_d); 1370*62f2b038SRichard Henderson } 1371*62f2b038SRichard Henderson 1372*62f2b038SRichard Henderson static bool trans_lf_mul_d(DisasContext *dc, arg_dab_pair *a) 1373*62f2b038SRichard Henderson { 1374*62f2b038SRichard Henderson return do_dp3(dc, a, gen_helper_float_mul_d); 1375*62f2b038SRichard Henderson } 1376*62f2b038SRichard Henderson 1377*62f2b038SRichard Henderson static bool trans_lf_div_d(DisasContext *dc, arg_dab_pair *a) 1378*62f2b038SRichard Henderson { 1379*62f2b038SRichard Henderson return do_dp3(dc, a, gen_helper_float_div_d); 1380*62f2b038SRichard Henderson } 1381*62f2b038SRichard Henderson 1382*62f2b038SRichard Henderson static bool trans_lf_rem_d(DisasContext *dc, arg_dab_pair *a) 1383*62f2b038SRichard Henderson { 1384*62f2b038SRichard Henderson return do_dp3(dc, a, gen_helper_float_rem_d); 1385*62f2b038SRichard Henderson } 1386*62f2b038SRichard Henderson 1387*62f2b038SRichard Henderson static bool trans_lf_itof_d(DisasContext *dc, arg_da_pair *a) 1388*62f2b038SRichard Henderson { 1389*62f2b038SRichard Henderson return do_dp2(dc, a, gen_helper_itofd); 1390*62f2b038SRichard Henderson } 1391*62f2b038SRichard Henderson 1392*62f2b038SRichard Henderson static bool trans_lf_ftoi_d(DisasContext *dc, arg_da_pair *a) 1393*62f2b038SRichard Henderson { 1394*62f2b038SRichard Henderson return do_dp2(dc, a, gen_helper_ftoid); 1395*62f2b038SRichard Henderson } 1396*62f2b038SRichard Henderson 1397*62f2b038SRichard Henderson static bool trans_lf_stod_d(DisasContext *dc, arg_lf_stod_d *a) 1398*62f2b038SRichard Henderson { 1399*62f2b038SRichard Henderson TCGv_i64 t0; 1400*62f2b038SRichard Henderson 1401*62f2b038SRichard Henderson if (!check_of64a32s(dc) || 1402*62f2b038SRichard Henderson !check_pair(dc, a->d, a->dp)) { 1403*62f2b038SRichard Henderson return false; 1404*62f2b038SRichard Henderson } 1405*62f2b038SRichard Henderson check_r0_write(dc, a->d); 1406*62f2b038SRichard Henderson 1407*62f2b038SRichard Henderson t0 = tcg_temp_new_i64(); 1408*62f2b038SRichard Henderson gen_helper_stod(t0, cpu_env, cpu_R(dc, a->a)); 1409*62f2b038SRichard Henderson save_pair(dc, t0, a->d, a->dp); 1410*62f2b038SRichard Henderson tcg_temp_free_i64(t0); 1411*62f2b038SRichard Henderson 1412*62f2b038SRichard Henderson gen_helper_update_fpcsr(cpu_env); 1413*62f2b038SRichard Henderson return true; 1414*62f2b038SRichard Henderson } 1415*62f2b038SRichard Henderson 1416*62f2b038SRichard Henderson static bool trans_lf_dtos_d(DisasContext *dc, arg_lf_dtos_d *a) 1417*62f2b038SRichard Henderson { 1418*62f2b038SRichard Henderson TCGv_i64 t0; 1419*62f2b038SRichard Henderson 1420*62f2b038SRichard Henderson if (!check_of64a32s(dc) || 1421*62f2b038SRichard Henderson !check_pair(dc, a->a, a->ap)) { 1422*62f2b038SRichard Henderson return false; 1423*62f2b038SRichard Henderson } 1424*62f2b038SRichard Henderson check_r0_write(dc, a->d); 1425*62f2b038SRichard Henderson 1426*62f2b038SRichard Henderson t0 = tcg_temp_new_i64(); 1427*62f2b038SRichard Henderson load_pair(dc, t0, a->a, a->ap); 1428*62f2b038SRichard Henderson gen_helper_dtos(cpu_R(dc, a->d), cpu_env, t0); 1429*62f2b038SRichard Henderson tcg_temp_free_i64(t0); 1430*62f2b038SRichard Henderson 1431*62f2b038SRichard Henderson gen_helper_update_fpcsr(cpu_env); 1432*62f2b038SRichard Henderson return true; 1433*62f2b038SRichard Henderson } 1434*62f2b038SRichard Henderson 1435*62f2b038SRichard Henderson static bool trans_lf_madd_d(DisasContext *dc, arg_dab_pair *a) 1436*62f2b038SRichard Henderson { 1437*62f2b038SRichard Henderson TCGv_i64 t0, t1, t2; 1438*62f2b038SRichard Henderson 1439*62f2b038SRichard Henderson if (!check_of64a32s(dc) || 1440*62f2b038SRichard Henderson !check_pair(dc, a->a, a->ap) || 1441*62f2b038SRichard Henderson !check_pair(dc, a->b, a->bp) || 1442*62f2b038SRichard Henderson !check_pair(dc, a->d, a->dp)) { 1443*62f2b038SRichard Henderson return false; 1444*62f2b038SRichard Henderson } 1445*62f2b038SRichard Henderson check_r0_write(dc, a->d); 1446*62f2b038SRichard Henderson 1447*62f2b038SRichard Henderson t0 = tcg_temp_new_i64(); 1448*62f2b038SRichard Henderson t1 = tcg_temp_new_i64(); 1449*62f2b038SRichard Henderson t2 = tcg_temp_new_i64(); 1450*62f2b038SRichard Henderson load_pair(dc, t0, a->d, a->dp); 1451*62f2b038SRichard Henderson load_pair(dc, t1, a->a, a->ap); 1452*62f2b038SRichard Henderson load_pair(dc, t2, a->b, a->bp); 1453*62f2b038SRichard Henderson gen_helper_float_madd_d(t0, cpu_env, t0, t1, t2); 1454*62f2b038SRichard Henderson save_pair(dc, t0, a->d, a->dp); 1455*62f2b038SRichard Henderson tcg_temp_free_i64(t0); 1456*62f2b038SRichard Henderson tcg_temp_free_i64(t1); 1457*62f2b038SRichard Henderson tcg_temp_free_i64(t2); 1458*62f2b038SRichard Henderson 1459*62f2b038SRichard Henderson gen_helper_update_fpcsr(cpu_env); 1460*62f2b038SRichard Henderson return true; 1461*62f2b038SRichard Henderson } 1462*62f2b038SRichard Henderson 1463*62f2b038SRichard Henderson static bool trans_lf_sfeq_d(DisasContext *dc, arg_ab_pair *a) 1464*62f2b038SRichard Henderson { 1465*62f2b038SRichard Henderson return do_dpcmp(dc, a, gen_helper_float_eq_d, false, false); 1466*62f2b038SRichard Henderson } 1467*62f2b038SRichard Henderson 1468*62f2b038SRichard Henderson static bool trans_lf_sfne_d(DisasContext *dc, arg_ab_pair *a) 1469*62f2b038SRichard Henderson { 1470*62f2b038SRichard Henderson return do_dpcmp(dc, a, gen_helper_float_eq_d, true, false); 1471*62f2b038SRichard Henderson } 1472*62f2b038SRichard Henderson 1473*62f2b038SRichard Henderson static bool trans_lf_sfgt_d(DisasContext *dc, arg_ab_pair *a) 1474*62f2b038SRichard Henderson { 1475*62f2b038SRichard Henderson return do_dpcmp(dc, a, gen_helper_float_lt_d, false, true); 1476*62f2b038SRichard Henderson } 1477*62f2b038SRichard Henderson 1478*62f2b038SRichard Henderson static bool trans_lf_sfge_d(DisasContext *dc, arg_ab_pair *a) 1479*62f2b038SRichard Henderson { 1480*62f2b038SRichard Henderson return do_dpcmp(dc, a, gen_helper_float_le_d, false, true); 1481*62f2b038SRichard Henderson } 1482*62f2b038SRichard Henderson 1483*62f2b038SRichard Henderson static bool trans_lf_sflt_d(DisasContext *dc, arg_ab_pair *a) 1484*62f2b038SRichard Henderson { 1485*62f2b038SRichard Henderson return do_dpcmp(dc, a, gen_helper_float_lt_d, false, false); 1486*62f2b038SRichard Henderson } 1487*62f2b038SRichard Henderson 1488*62f2b038SRichard Henderson static bool trans_lf_sfle_d(DisasContext *dc, arg_ab_pair *a) 1489*62f2b038SRichard Henderson { 1490*62f2b038SRichard Henderson return do_dpcmp(dc, a, gen_helper_float_le_d, false, false); 1491*62f2b038SRichard Henderson } 1492*62f2b038SRichard Henderson 1493a4fd3ec3SEmilio G. Cota static void openrisc_tr_init_disas_context(DisasContextBase *dcb, CPUState *cs) 1494e67db06eSJia Liu { 1495a4fd3ec3SEmilio G. Cota DisasContext *dc = container_of(dcb, DisasContext, base); 14969c489ea6SLluís Vilanova CPUOpenRISCState *env = cs->env_ptr; 1497a4fd3ec3SEmilio G. Cota int bound; 1498bbe418f2SJia Liu 1499a4fd3ec3SEmilio G. Cota dc->mem_idx = cpu_mmu_index(env, false); 15001ffa4bceSEmilio G. Cota dc->tb_flags = dc->base.tb->flags; 1501a01deb36SRichard Henderson dc->delayed_branch = (dc->tb_flags & TB_FLAGS_DFLAG) != 0; 1502fe636d37SRichard Henderson dc->cpucfgr = env->cpucfgr; 15038000ba56SRichard Henderson dc->jmp_pc_imm = -1; 15048000ba56SRichard Henderson 1505a4fd3ec3SEmilio G. Cota bound = -(dc->base.pc_first | TARGET_PAGE_MASK) / 4; 1506a4fd3ec3SEmilio G. Cota dc->base.max_insns = MIN(dc->base.max_insns, bound); 1507190ce7fbSRichard Henderson } 1508bbe418f2SJia Liu 1509a4fd3ec3SEmilio G. Cota static void openrisc_tr_tb_start(DisasContextBase *db, CPUState *cs) 1510a4fd3ec3SEmilio G. Cota { 1511a4fd3ec3SEmilio G. Cota DisasContext *dc = container_of(db, DisasContext, base); 1512bbe418f2SJia Liu 15136597c28dSRichard Henderson /* Allow the TCG optimizer to see that R0 == 0, 15146597c28dSRichard Henderson when it's true, which is the common case. */ 15156597c28dSRichard Henderson if (dc->tb_flags & TB_FLAGS_R0_0) { 1516d29f4368SRichard Henderson dc->R0 = tcg_const_tl(0); 15176597c28dSRichard Henderson } else { 1518d29f4368SRichard Henderson dc->R0 = cpu_regs[0]; 15196597c28dSRichard Henderson } 1520a4fd3ec3SEmilio G. Cota } 15216597c28dSRichard Henderson 1522a4fd3ec3SEmilio G. Cota static void openrisc_tr_insn_start(DisasContextBase *dcbase, CPUState *cs) 1523a4fd3ec3SEmilio G. Cota { 1524a4fd3ec3SEmilio G. Cota DisasContext *dc = container_of(dcbase, DisasContext, base); 1525a4fd3ec3SEmilio G. Cota 15261ffa4bceSEmilio G. Cota tcg_gen_insn_start(dc->base.pc_next, (dc->delayed_branch ? 1 : 0) 1527a4fd3ec3SEmilio G. Cota | (dc->base.num_insns > 1 ? 2 : 0)); 1528a4fd3ec3SEmilio G. Cota } 1529bbe418f2SJia Liu 1530a4fd3ec3SEmilio G. Cota static bool openrisc_tr_breakpoint_check(DisasContextBase *dcbase, CPUState *cs, 1531a4fd3ec3SEmilio G. Cota const CPUBreakpoint *bp) 1532a4fd3ec3SEmilio G. Cota { 1533a4fd3ec3SEmilio G. Cota DisasContext *dc = container_of(dcbase, DisasContext, base); 1534a4fd3ec3SEmilio G. Cota 15351ffa4bceSEmilio G. Cota tcg_gen_movi_tl(cpu_pc, dc->base.pc_next); 1536b933066aSRichard Henderson gen_exception(dc, EXCP_DEBUG); 15371ffa4bceSEmilio G. Cota dc->base.is_jmp = DISAS_NORETURN; 1538522a0d4eSRichard Henderson /* The address covered by the breakpoint must be included in 1539522a0d4eSRichard Henderson [tb->pc, tb->pc + tb->size) in order to for it to be 1540522a0d4eSRichard Henderson properly cleared -- thus we increment the PC here so that 1541522a0d4eSRichard Henderson the logic setting tb->size below does the right thing. */ 15421ffa4bceSEmilio G. Cota dc->base.pc_next += 4; 1543a4fd3ec3SEmilio G. Cota return true; 1544b933066aSRichard Henderson } 1545b933066aSRichard Henderson 1546a4fd3ec3SEmilio G. Cota static void openrisc_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs) 1547a4fd3ec3SEmilio G. Cota { 1548a4fd3ec3SEmilio G. Cota DisasContext *dc = container_of(dcbase, DisasContext, base); 1549a4fd3ec3SEmilio G. Cota OpenRISCCPU *cpu = OPENRISC_CPU(cs); 1550c7b6f54bSRichard Henderson uint32_t insn = cpu_ldl_code(&cpu->env, dc->base.pc_next); 1551a4fd3ec3SEmilio G. Cota 1552c7b6f54bSRichard Henderson if (!decode(dc, insn)) { 1553c7b6f54bSRichard Henderson gen_illegal_exception(dc); 1554c7b6f54bSRichard Henderson } 15551ffa4bceSEmilio G. Cota dc->base.pc_next += 4; 155624c32852SRichard Henderson 15578000ba56SRichard Henderson /* When exiting the delay slot normally, exit via jmp_pc. 15588000ba56SRichard Henderson * For DISAS_NORETURN, we have raised an exception and already exited. 15598000ba56SRichard Henderson * For DISAS_EXIT, we found l.rfe in a delay slot. There's nothing 15608000ba56SRichard Henderson * in the manual saying this is illegal, but it surely it should. 15618000ba56SRichard Henderson * At least or1ksim overrides pcnext and ignores the branch. 15628000ba56SRichard Henderson */ 15638000ba56SRichard Henderson if (dc->delayed_branch 15648000ba56SRichard Henderson && --dc->delayed_branch == 0 15658000ba56SRichard Henderson && dc->base.is_jmp == DISAS_NEXT) { 15668000ba56SRichard Henderson dc->base.is_jmp = DISAS_JUMP; 1567bbe418f2SJia Liu } 1568a4fd3ec3SEmilio G. Cota } 1569bbe418f2SJia Liu 1570a4fd3ec3SEmilio G. Cota static void openrisc_tr_tb_stop(DisasContextBase *dcbase, CPUState *cs) 1571a4fd3ec3SEmilio G. Cota { 1572a4fd3ec3SEmilio G. Cota DisasContext *dc = container_of(dcbase, DisasContext, base); 15738000ba56SRichard Henderson target_ulong jmp_dest; 157424c32852SRichard Henderson 1575e0a369cfSRichard Henderson /* If we have already exited the TB, nothing following has effect. */ 1576e0a369cfSRichard Henderson if (dc->base.is_jmp == DISAS_NORETURN) { 1577e0a369cfSRichard Henderson return; 1578e0a369cfSRichard Henderson } 1579e0a369cfSRichard Henderson 15808000ba56SRichard Henderson /* Adjust the delayed branch state for the next TB. */ 1581a01deb36SRichard Henderson if ((dc->tb_flags & TB_FLAGS_DFLAG ? 1 : 0) != (dc->delayed_branch != 0)) { 1582a01deb36SRichard Henderson tcg_gen_movi_i32(cpu_dflag, dc->delayed_branch != 0); 1583a01deb36SRichard Henderson } 1584a01deb36SRichard Henderson 15858000ba56SRichard Henderson /* For DISAS_TOO_MANY, jump to the next insn. */ 15868000ba56SRichard Henderson jmp_dest = dc->base.pc_next; 15878000ba56SRichard Henderson tcg_gen_movi_tl(cpu_ppc, jmp_dest - 4); 15888000ba56SRichard Henderson 15891ffa4bceSEmilio G. Cota switch (dc->base.is_jmp) { 15908000ba56SRichard Henderson case DISAS_JUMP: 15918000ba56SRichard Henderson jmp_dest = dc->jmp_pc_imm; 15928000ba56SRichard Henderson if (jmp_dest == -1) { 15938000ba56SRichard Henderson /* The jump destination is indirect/computed; use jmp_pc. */ 15948000ba56SRichard Henderson tcg_gen_mov_tl(cpu_pc, jmp_pc); 15958000ba56SRichard Henderson tcg_gen_discard_tl(jmp_pc); 15968000ba56SRichard Henderson if (unlikely(dc->base.singlestep_enabled)) { 15978000ba56SRichard Henderson gen_exception(dc, EXCP_DEBUG); 15988000ba56SRichard Henderson } else { 15998000ba56SRichard Henderson tcg_gen_lookup_and_goto_ptr(); 16008000ba56SRichard Henderson } 1601bbe418f2SJia Liu break; 16028000ba56SRichard Henderson } 16038000ba56SRichard Henderson /* The jump destination is direct; use jmp_pc_imm. 16048000ba56SRichard Henderson However, we will have stored into jmp_pc as well; 16058000ba56SRichard Henderson we know now that it wasn't needed. */ 16068000ba56SRichard Henderson tcg_gen_discard_tl(jmp_pc); 16078000ba56SRichard Henderson /* fallthru */ 16088000ba56SRichard Henderson 16098000ba56SRichard Henderson case DISAS_TOO_MANY: 16108000ba56SRichard Henderson if (unlikely(dc->base.singlestep_enabled)) { 16118000ba56SRichard Henderson tcg_gen_movi_tl(cpu_pc, jmp_dest); 16128000ba56SRichard Henderson gen_exception(dc, EXCP_DEBUG); 16138000ba56SRichard Henderson } else if ((dc->base.pc_first ^ jmp_dest) & TARGET_PAGE_MASK) { 16148000ba56SRichard Henderson tcg_gen_movi_tl(cpu_pc, jmp_dest); 16158000ba56SRichard Henderson tcg_gen_lookup_and_goto_ptr(); 16168000ba56SRichard Henderson } else { 16178000ba56SRichard Henderson tcg_gen_goto_tb(0); 16188000ba56SRichard Henderson tcg_gen_movi_tl(cpu_pc, jmp_dest); 16198000ba56SRichard Henderson tcg_gen_exit_tb(dc->base.tb, 0); 16208000ba56SRichard Henderson } 16218000ba56SRichard Henderson break; 16228000ba56SRichard Henderson 162364e46c95SRichard Henderson case DISAS_EXIT: 1624e0a369cfSRichard Henderson if (unlikely(dc->base.singlestep_enabled)) { 1625e0a369cfSRichard Henderson gen_exception(dc, EXCP_DEBUG); 1626e0a369cfSRichard Henderson } else { 162707ea28b4SRichard Henderson tcg_gen_exit_tb(NULL, 0); 1628e0a369cfSRichard Henderson } 1629bbe418f2SJia Liu break; 1630a4fd3ec3SEmilio G. Cota default: 1631a4fd3ec3SEmilio G. Cota g_assert_not_reached(); 1632a4fd3ec3SEmilio G. Cota } 1633bbe418f2SJia Liu } 1634bbe418f2SJia Liu 1635a4fd3ec3SEmilio G. Cota static void openrisc_tr_disas_log(const DisasContextBase *dcbase, CPUState *cs) 1636a4fd3ec3SEmilio G. Cota { 1637a4fd3ec3SEmilio G. Cota DisasContext *s = container_of(dcbase, DisasContext, base); 16380a7df5daSRichard Henderson 1639a4fd3ec3SEmilio G. Cota qemu_log("IN: %s\n", lookup_symbol(s->base.pc_first)); 1640a4fd3ec3SEmilio G. Cota log_target_disas(cs, s->base.pc_first, s->base.tb->size); 1641bbe418f2SJia Liu } 1642a4fd3ec3SEmilio G. Cota 1643a4fd3ec3SEmilio G. Cota static const TranslatorOps openrisc_tr_ops = { 1644a4fd3ec3SEmilio G. Cota .init_disas_context = openrisc_tr_init_disas_context, 1645a4fd3ec3SEmilio G. Cota .tb_start = openrisc_tr_tb_start, 1646a4fd3ec3SEmilio G. Cota .insn_start = openrisc_tr_insn_start, 1647a4fd3ec3SEmilio G. Cota .breakpoint_check = openrisc_tr_breakpoint_check, 1648a4fd3ec3SEmilio G. Cota .translate_insn = openrisc_tr_translate_insn, 1649a4fd3ec3SEmilio G. Cota .tb_stop = openrisc_tr_tb_stop, 1650a4fd3ec3SEmilio G. Cota .disas_log = openrisc_tr_disas_log, 1651a4fd3ec3SEmilio G. Cota }; 1652a4fd3ec3SEmilio G. Cota 16538b86d6d2SRichard Henderson void gen_intermediate_code(CPUState *cs, TranslationBlock *tb, int max_insns) 1654a4fd3ec3SEmilio G. Cota { 1655a4fd3ec3SEmilio G. Cota DisasContext ctx; 1656a4fd3ec3SEmilio G. Cota 16578b86d6d2SRichard Henderson translator_loop(&openrisc_tr_ops, &ctx.base, cs, tb, max_insns); 1658e67db06eSJia Liu } 1659e67db06eSJia Liu 166090c84c56SMarkus Armbruster void openrisc_cpu_dump_state(CPUState *cs, FILE *f, int flags) 1661e67db06eSJia Liu { 1662878096eeSAndreas Färber OpenRISCCPU *cpu = OPENRISC_CPU(cs); 1663878096eeSAndreas Färber CPUOpenRISCState *env = &cpu->env; 1664e67db06eSJia Liu int i; 1665878096eeSAndreas Färber 166690c84c56SMarkus Armbruster qemu_fprintf(f, "PC=%08x\n", env->pc); 1667e67db06eSJia Liu for (i = 0; i < 32; ++i) { 166890c84c56SMarkus Armbruster qemu_fprintf(f, "R%02d=%08x%c", i, cpu_get_gpr(env, i), 1669e67db06eSJia Liu (i % 4) == 3 ? '\n' : ' '); 1670e67db06eSJia Liu } 1671e67db06eSJia Liu } 1672e67db06eSJia Liu 1673e67db06eSJia Liu void restore_state_to_opc(CPUOpenRISCState *env, TranslationBlock *tb, 1674bad729e2SRichard Henderson target_ulong *data) 1675e67db06eSJia Liu { 1676bad729e2SRichard Henderson env->pc = data[0]; 1677a01deb36SRichard Henderson env->dflag = data[1] & 1; 1678a01deb36SRichard Henderson if (data[1] & 2) { 167924c32852SRichard Henderson env->ppc = env->pc - 4; 168024c32852SRichard Henderson } 1681e67db06eSJia Liu } 1682